Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
Params.php
1<?php
2
4
9use Bitrix\Im\Model\EO_MessageParam;
10use Bitrix\Im\Model\EO_MessageParam_Collection;
16
21class Params extends Registry
22{
23 public const EVENT_MESSAGE_PARAM_TYPE_INIT = 'OnMessageParamTypesInit';
24
25 public const
26 TS = 'TS',
27 FILE_ID = 'FILE_ID',
28 ATTACH = 'ATTACH',
29 MENU = 'MENU',
30 KEYBOARD = 'KEYBOARD',
31 KEYBOARD_UID = 'KEYBOARD_UID',
32 IS_DELETED = 'IS_DELETED',
33 IS_ERROR = 'IS_ERROR',
34 IS_DELIVERED = 'IS_DELIVERED',
35 IS_EDITED = 'IS_EDITED',
36 IS_PINNED = 'IS_PINNED',
37 CAN_ANSWER = 'CAN_ANSWER',
38 URL_ONLY = 'URL_ONLY',
39 LARGE_FONT = 'LARGE_FONT',
40 SENDING = 'SENDING',
41 SENDING_TS = 'SENDING_TS',
42 USER_ID = 'USER_ID',
43 AVATAR = 'AVATAR',
44 NAME = 'NAME',
45 NOTIFY = 'NOTIFY',
46 CODE = 'CODE',
47 TYPE = 'TYPE',
48 COMPONENT_ID = 'COMPONENT_ID',
49 COMPONENT_PARAMS = 'COMPONENT_PARAMS',
50 STYLE_CLASS = 'CLASS',
51 CALL_ID = 'CALL_ID',
52 CHAT_ID = 'CHAT_ID',
53 CHAT_MESSAGE = 'CHAT_MESSAGE',
54 CHAT_USER = 'CHAT_USER',
55 DATE_TS = 'DATE_TS',
56 LIKE = 'LIKE',
57 FAVORITE = 'FAVORITE',
58 KEYBOARD_ACTION = 'KEYBOARD_ACTION',
59 URL_ID = 'URL_ID',
60 LINK_ACTIVE = 'LINK_ACTIVE',
61 USERS = 'USERS',
62 CHAT_LAST_DATE = 'CHAT_LAST_DATE',
63 DATE_TEXT = 'DATE_TEXT',
64 IS_ROBOT_MESSAGE = 'IS_ROBOT_MESSAGE',
65 FORWARD_ID = 'FORWARD_ID',
66 FORWARD_CONTEXT_ID = 'FORWARD_CONTEXT_ID',
67 FORWARD_USER_ID = 'FORWARD_USER_ID',
68 REPLY_ID = 'REPLY_ID',
69 BETA = 'BETA'
70 ;
71
72 //todo: Move it into CRM module
73 public const
74 CRM_FORM_FILLED = 'CRM_FORM_FILLED',
75 CRM_FORM_ID = 'CRM_FORM_ID',
76 CRM_FORM_SEC = 'CRM_FORM_SEC'
77 ;
78
79 protected static bool $typeLoaded = false;
80
81 protected bool $isLoaded = false;
82
83 protected static array $typeMap = [
84 self::TS => [
85 'type' => Param::TYPE_STRING,
86 ],
87 self::FILE_ID => [
88 'type' => Param::TYPE_INT_ARRAY,
89 ],
90 self::IS_DELETED => [
91 'type' => Param::TYPE_BOOL,
92 'default' => false,
93 ],
94 self::IS_ERROR => [
95 'type' => Param::TYPE_BOOL,
96 'default' => false,
97 ],
98 self::IS_DELIVERED => [
99 'type' => Param::TYPE_BOOL,
100 'default' => true,
101 ],
102 self::IS_EDITED => [
103 'type' => Param::TYPE_BOOL,
104 'default' => false,
105 ],
106 self::IS_PINNED => [
107 'type' => Param::TYPE_BOOL,
108 'default' => false,
109 ],
110 self::CAN_ANSWER => [
111 'type' => Param::TYPE_BOOL,
112 'default' => false,
113 ],
114 self::URL_ONLY => [
115 'type' => Param::TYPE_BOOL,
116 'default' => false,
117 ],
118 self::LARGE_FONT => [
119 'type' => Param::TYPE_BOOL,
120 'default' => false,
121 ],
122 self::ATTACH => [
123 'className' => \Bitrix\Im\V2\Message\Param\AttachArray::class,
124 'classItem' => \Bitrix\Im\V2\Message\Param\Attach::class,
125 'type' => Param::TYPE_JSON,
126 ],
127 self::MENU => [
128 'className' => \Bitrix\Im\V2\Message\Param\Menu::class,
129 'type' => Param::TYPE_JSON,
130 ],
131 self::KEYBOARD => [
132 'className' => \Bitrix\Im\V2\Message\Param\Keyboard::class,
133 'type' => Param::TYPE_JSON,
134 ],
135 self::KEYBOARD_UID => [
136 'type' => Param::TYPE_INT,
137 'default' => 0,
138 ],
139 self::SENDING => [
140 'type' => Param::TYPE_BOOL,
141 'default' => false,
142 ],
143 self::SENDING_TS => [
144 'type' => Param::TYPE_INT,
145 'default' => 0,
146 ],
147 // Message User
148 self::USER_ID => [
149 'type' => Param::TYPE_INT,
150 ],
151 self::AVATAR => [
152 'className' => \Bitrix\Im\V2\Message\Param\UserAvatar::class,
153 'type' => Param::TYPE_INT,
154 ],
155 self::NAME => [
156 'className' => \Bitrix\Im\V2\Message\Param\UserName::class,
157 'type' => Param::TYPE_STRING,
158 ],
159 // Disable notification for message
160 self::NOTIFY => [
161 'type' => Param::TYPE_BOOL,
162 ],
163 self::CODE => [
164 'type' => Param::TYPE_STRING,
165 'default' => '',
166 ],
167 self::TYPE => [
168 'type' => Param::TYPE_STRING,
169 'default' => '',
170 ],
171 self::COMPONENT_ID => [
172 'type' => Param::TYPE_STRING,
173 'default' => '',
174 ],
175 self::COMPONENT_PARAMS => [
176 'className' => Message\Param\ComponentParams::class,
177 'type' => Param::TYPE_JSON,
178 ],
179 self::STYLE_CLASS => [
180 'type' => Param::TYPE_STRING,
181 'default' => '',
182 ],
183 self::CALL_ID => [
184 'type' => Param::TYPE_INT,
185 'default' => 0,
186 ],
187 self::CHAT_ID => [
188 'type' => Param::TYPE_INT,
189 'default' => 0,
190 ],
191 self::CHAT_MESSAGE => [
192 'type' => Param::TYPE_INT,
193 'default' => 0,
194 ],
195 self::CHAT_USER => [
196 'type' => Param::TYPE_INT_ARRAY,
197 ],
198 self::DATE_TS => [
199 'type' => Param::TYPE_INT_ARRAY,
200 ],
201 self::LIKE => [
202 'type' => Param::TYPE_INT_ARRAY,
203 ],
204 self::FAVORITE => [
205 'type' => Param::TYPE_INT_ARRAY,
206 ],
207 self::KEYBOARD_ACTION => [
208 'type' => Param::TYPE_INT_ARRAY,
209 ],
210 self::URL_ID => [
211 'type' => Param::TYPE_INT_ARRAY,
212 ],
213 self::LINK_ACTIVE => [
214 'type' => Param::TYPE_INT_ARRAY,
215 ],
216 self::USERS => [
217 'type' => Param::TYPE_INT_ARRAY,
218 ],
219 self::CHAT_LAST_DATE => [
220 'type' => Param::TYPE_DATE_TIME,
221 ],
222 self::DATE_TEXT => [
223 'className' => \Bitrix\Im\V2\Message\Param\TextDate::class,
224 'type' => Param::TYPE_STRING_ARRAY,
225 ],
226 self::IS_ROBOT_MESSAGE => [
227 'type' => Param::TYPE_BOOL,
228 ],
229 self::FORWARD_ID => [
230 'type' => Param::TYPE_INT,
231 'isHidden' => true,
232 ],
233 self::FORWARD_USER_ID => [
234 'type' => Param::TYPE_INT,
235 'isHidden' => true,
236 ],
237 self::FORWARD_CONTEXT_ID => [
238 'type' => Param::TYPE_STRING,
239 'isHidden' => true,
240 ],
241 self::REPLY_ID => [
242 'type' => Param::TYPE_INT,
243 ],
244 self::BETA => [
245 'type' => Param::TYPE_BOOL,
246 'default' => false,
247 ],
248
249 //todo: Move it into CRM module
250 self::CRM_FORM_FILLED => [
251 'type' => Param::TYPE_BOOL,
252 'default' => false,
253 ],
254 self::CRM_FORM_ID => [
255 'type' => Param::TYPE_STRING,
256 'default' => '',
257 ],
258 self::CRM_FORM_SEC => [
259 'type' => Param::TYPE_STRING,
260 'default' => '',
261 ],
262 ];
263
264
265 protected ?int $messageId = null;
266
268 protected array $droppedItems = [];
269
270 //region Types
271
277 public static function getType(string $paramName): array
278 {
280
281 if (isset(self::$typeMap[$paramName]))
282 {
283 $type = self::$typeMap[$paramName];
284 if (!isset($type['className']))
285 {
286 if ($type['type'] == Param::TYPE_INT_ARRAY || $type['type'] == Param::TYPE_STRING_ARRAY)
287 {
288 $type['className'] = ParamArray::class;
289 }
290 elseif ($type['type'] == Param::TYPE_DATE_TIME)
291 {
292 $type['className'] = Param\DateTime::class;
293 }
294 else
295 {
296 $type['className'] = Param::class;
297 }
298 }
299 }
300 else
301 {
302 $type = [
303 'className' => Param::class,
304 'type' => Param::TYPE_STRING,
305 ];
306 }
307
308 $type['isHidden'] ??= false;
309
310 return $type;
311 }
312
319 public static function addType(string $paramName, array $description): void
320 {
321 self::$typeMap[$paramName] = $description;
322 }
323
328 public static function initTypes(): void
329 {
330 if (!self::$typeLoaded)
331 {
332 $event = new Event('im', self::EVENT_MESSAGE_PARAM_TYPE_INIT);
333 $event->send();
334 $resultList = $event->getResults();
335
336 foreach ($resultList as $eventResult)
337 {
338 if ($eventResult->getType() === EventResult::SUCCESS)
339 {
340 $settings = $eventResult->getParameters();
341 if (is_array($settings))
342 {
343 foreach ($settings as $paramName => $description)
344 {
345 if (
346 is_array($description)
347 && (
348 !empty($description['type'])
349 || !empty($description['className'])
350 )
351 )
352 {
353 self::addType($paramName, $description);
354 }
355 }
356 }
357 }
358 }
359 }
360
361 self::$typeLoaded = true;
362 }
363
364 //endregion
365
366 //region Loaders
367
372 public function isLoaded(): bool
373 {
374 return $this->isLoaded;
375 }
376
381 public function load($source): Result
382 {
383 if (is_array($source))
384 {
385 $result = $this->initByArray($source);
386 }
387 elseif ($source instanceof ORM\Objectify\Collection)
388 {
389 $result = $this->initByEntitiesCollection($source);
390 }
391 elseif ($source instanceof ORM\Objectify\EntityObject)
392 {
393 $result = $this->initByDataEntity($source);
394 }
395 else
396 {
397 $result = (new Result)->addError(new Error(Error::NOT_FOUND));
398 }
399
400 if ($result->isSuccess())
401 {
402 foreach ($this as $param)
403 {
404 if ($param->getMessageId())
405 {
406 $this->setMessageId($param->getMessageId());
407 break;
408 }
409 }
410
411 $this->isLoaded = true;
412 }
413
414 return $result;
415 }
416
421 public function loadByMessage(Message $message): Result
422 {
423 if ($message->getMessageId())
424 {
425 return $this->loadByMessageId($message->getMessageId());
426 }
427
428 return new Result;
429 }
430
435 public function loadByMessageId(int $messageId): Result
436 {
437 if ($messageId > 0)
438 {
439 $this->setMessageId($messageId);
440
441 $collection = Param::getDataClass()::query()
442 ->setSelect(['ID', 'MESSAGE_ID', 'PARAM_NAME', 'PARAM_VALUE', 'PARAM_JSON'])
443 ->where('MESSAGE_ID', '=', $messageId)
444 ->fetchCollection()
445 ;
446
447 return $this->initByEntitiesCollection($collection);
448 }
449
450 return new Result;
451 }
452
457 protected function initByEntitiesCollection(ORM\Objectify\Collection $entitiesCollection): Result
458 {
460 foreach ($entitiesCollection as $entity)
461 {
462 $paramName = $entity->getParamName();
463 if (!parent::offsetExists($paramName))
464 {
465 $this[$paramName] = self::create($paramName);
466 }
467
468 $item = $this[$paramName];
469 if ($item instanceof ParamArray)
470 {
471 $type = self::getType($paramName);
472 if (isset($type['classItem']))
473 {
474 $classItem = $type['classItem'];
475 $item->add(new $classItem($entity));
476 }
477 else
478 {
479 $item->add(new Param($entity));
480 }
481 }
482 else
483 {
484 $item->load($entity);
485 }
486 }
487
488 $this->isLoaded = true;
489
490 return new Result();
491 }
492
497 protected function initByArray(array $items): Result
498 {
499 foreach ($items as $entityId => $entity)
500 {
501 if (is_array($entity) && isset($entity['PARAM_NAME']))
502 {
503 $paramName = $entity['PARAM_NAME'];
504 if (!parent::offsetExists($paramName))
505 {
506 $this[$paramName] = self::create($paramName);
507 }
508
509 $item = $this[$paramName];
510 if ($item instanceof ParamArray)
511 {
512 $type = self::getType($paramName);
513 if (isset($type['classItem']))
514 {
515 $classItem = $type['classItem'];
516 $item->add(new $classItem($entity));
517 }
518 else
519 {
520 $item->add(new Param($entity));
521 }
522 }
523 else
524 {
525 $item->load($entity);
526 }
527 }
528 else
529 {
530 if (!parent::offsetExists($entityId))
531 {
532 $this[$entityId] = self::create($entityId);
533 }
534
535 $this[$entityId]->setValue($entity);
536 }
537 }
538
539 return new Result();
540 }
541
546 protected function initByDataEntity(ORM\Objectify\EntityObject $entity): Result
547 {
548 $paramName = $entity->getParamName();
549 if (!parent::offsetExists($paramName))
550 {
551 $this[$paramName] = self::create($paramName);
552 }
553
554 $item = $this[$paramName];
555 if ($item instanceof ParamArray)
556 {
557 $type = self::getType($paramName);
558 if (isset($type['classItem']))
559 {
560 $classItem = $type['classItem'];
561 $item->add(new $classItem($entity));
562 }
563 else
564 {
565 $item->add(new Param($entity));
566 }
567 }
568 else
569 {
570 $item->load($entity);
571 }
572
573 return new Result();
574 }
575
576 //endregion
577
578 //region Save
579
584 public function save(): Result
585 {
586 $result = new Result;
587
589 $entityCollectionClass = Param::getDataClass()::getCollectionClass();
590 $dataEntityCollection = new $entityCollectionClass;
591
592 $dropIds = [];
593
594 $itemKeyToUnset = [];
595 foreach ($this as $item)
596 {
597 if ($item->isDeleted())
598 {
599 $itemKeyToUnset[] = $item->getName();
600 continue;
601 }
602 if (!$item->hasValue())
603 {
604 continue;
605 }
606
607 if ($item instanceof Param)
608 {
609 $prepareResult = $item->prepareFields();
610 if ($prepareResult->isSuccess())
611 {
612 if ($item->isChanged())
613 {
614 $dataEntityCollection->add($item->getDataEntity());
615 $item->markChanged(false);
616 }
617 }
618 else
619 {
620 $result->addErrors($prepareResult->getErrors());
621 }
622 }
623 elseif ($item instanceof ParamArray)
624 {
625 $subItemKeyToUnset = [];
626 foreach ($item as $key => $subItem)
627 {
628 if ($subItem->isDeleted())
629 {
630 if ($subItem->getPrimaryId())
631 {
632 $dropIds[] = $subItem->getPrimaryId();
633 $subItemKeyToUnset[] = $key;
634 }
635 }
636 else
637 {
638 $prepareResult = $subItem->prepareFields();
639 if ($prepareResult->isSuccess())
640 {
641 if ($subItem->isChanged())
642 {
643 $dataEntityCollection->add($subItem->getDataEntity());
644 $subItem->markChanged(false);
645 }
646 }
647 else
648 {
649 $result->addErrors($prepareResult->getErrors());
650 }
651 }
652 }
653 $item->unsetByKeys($subItemKeyToUnset);
654 }
655 }
656 $this->unsetByKeys($itemKeyToUnset);
657
658 foreach ($this->droppedItems as $item)
659 {
660 if ($item instanceof Param)
661 {
662 if ($item->getPrimaryId())
663 {
664 $dropIds[] = $item->getPrimaryId();
665 }
666 }
667 elseif ($item instanceof ParamArray)
668 {
669 foreach ($item as $subItem)
670 {
671 if ($subItem->getPrimaryId())
672 {
673 $dropIds[] = $subItem->getPrimaryId();
674 }
675 }
676 }
677 }
678
679 $saveResult = $dataEntityCollection->save(true);
680 if ($saveResult->isSuccess())
681 {
682 if (!empty($dropIds))
683 {
684 MessageParamTable::deleteBatch(['=ID' => $dropIds]);
685 }
686
687 $this->droppedItems = [];
688 }
689 else
690 {
691 $result->addErrors($saveResult->getErrors());
692 }
693
694 return $result;
695 }
696
703 public function delete(bool $deleteWithTs = false): Result
704 {
705 $result = new Result;
706
707 $keysToUnset = [];
708 foreach ($this as $key => $item)
709 {
710 $keysToUnset[$key] = $key;
711 }
712 $this->unsetByKeys($keysToUnset);
713
714 if ($this->getMessageId())
715 {
716 $filter = [
717 '=MESSAGE_ID' => $this->getMessageId(),
718 ];
719 if (!$deleteWithTs)
720 {
721 $filter['!=PARAM_NAME'] = self::TS;
722 }
723 MessageParamTable::deleteBatch($filter);
724 }
725
726 $this->droppedItems = [];
727 $this->isLoaded = false;
728
729 return $result;
730 }
731
732 //endregion
733
734 //region Params get/set
735
742 public static function create(string $paramName): MessageParameter
743 {
744 $type = self::getType($paramName);
745
746 if ($type['className'])
747 {
748 $paramClass = $type['className'];
749 }
750 else
751 {
752 $paramClass = Param::class;
753 }
754
755 return (new $paramClass)
756 ->setName($paramName)
757 ->setType($type['type'] ?? Param::TYPE_STRING)
758 ;
759 }
760
765 public function isSet(string $paramName): bool
766 {
767 return isset($this[$paramName])
768 && $this[$paramName]->hasValue()
769 && !$this[$paramName]->isDeleted()
770 ;
771 }
772
777 public function offsetExists($offset): bool
778 {
779 if (
780 !parent::offsetExists($offset)
781 && !$this->isLoaded()
782 && $this->getMessageId()
783 )
784 {
785 // lazyload
786 $this->loadByMessageId($this->getMessageId());
787 }
788
789 return parent::offsetExists($offset);
790 }
791
796 public function get(string $paramName): MessageParameter
797 {
798 if (!isset($this[$paramName]))// lazyload
799 {
800 $this[$paramName] = self::create($paramName);
801 }
802
803 return $this[$paramName];
804 }
805
811 public function set(string $paramName, $parameter): self
812 {
813 if ($parameter instanceof MessageParameter)
814 {
815 $this[$paramName] = $parameter;
816 }
817 else
818 {
819 $this[$paramName] = self::create($paramName);
820 $this[$paramName]->load($parameter);
821 }
822
823 if ($this->getMessageId())
824 {
825 $this[$paramName]->setMessageId($this->getMessageId());
826 }
827
828 return $this;
829 }
830
831 public function isValid(): Result
832 {
833 $result = new Result();
834
836 foreach ($this as $param)
837 {
838 $validParamResult = $param->isValid();
839 if (!$validParamResult->isSuccess())
840 {
841 $result->addErrors($validParamResult->getErrors());
842 }
843 }
844
845 return $result;
846 }
847
852 public function add(MessageParameter $parameter): self
853 {
854 $this[$parameter->getName()] = $parameter;
855
856 if ($this->getMessageId())
857 {
858 $parameter->setMessageId($this->getMessageId());
859 }
860
861 return $this;
862 }
863
872 public function offsetSet($offset, $entry): void
873 {
874 if (!($entry instanceof MessageParameter))
875 {
876 $entryClass = \get_class($entry);
877 throw new ArgumentTypeException("Entry is instance of {$entryClass}, but collection support MessageParameter");
878 }
879
880 if ($this->getMessageId())
881 {
882 $entry->setMessageId($this->getMessageId());
883 }
884
885 parent::offsetSet($offset, $entry);
886 }
887
892 public function remove(string $paramName = ''): self
893 {
894 if (empty($paramName))
895 {
896 $keysToUnset = [];
897 foreach ($this as $paramName => $param)
898 {
899 $keysToUnset[$paramName] = $paramName;
900 }
901 $this->unsetByKeys($keysToUnset);
902 $this->isLoaded = true;
903 }
904 else
905 {
906 unset($this[$paramName]);
907 }
908
909 return $this;
910 }
911
916 public function offsetUnset($offset): void
917 {
918 if (parent::offsetExists($offset))
919 {
920 $this[$offset]->markDrop();
921 $this->droppedItems[] = $this[$offset];
922 }
923
924 parent::offsetUnset($offset);
925 }
926
931 public function setMessageId(int $messageId): self
932 {
933 $this->messageId = $messageId;
934 foreach ($this as $param)
935 {
936 $param->setMessageId($this->messageId);
937 }
938
939 return $this;
940 }
941
942 public function getMessageId(): ?int
943 {
944 return $this->messageId;
945 }
946
947 //endregion
948
952 public function toRestFormat(): array
953 {
954 $result = [];
955 foreach ($this as $paramName => $param)
956 {
957 if ($param->hasValue() && !$param->isHidden())
958 {
959 $result[$paramName] = $param->toRestFormat();
960 }
961 }
962
963 return $result;
964 }
965
969 public function toPullFormat(?array $extraParams = null): array
970 {
971 $result = [];
972 foreach ($this as $paramName => $param)
973 {
974 if ($param->hasValue() && !$param->isHidden())
975 {
976 $result[$paramName] = $param->toPullFormat();
977 }
978 }
979
980 if (!isset($extraParams))
981 {
982 return $result;
983 }
984
985 foreach ($extraParams as $extraParam)
986 {
987 if (!isset($result[$extraParam]))
988 {
989 $result[$extraParam] = Params::create($extraParam)->toPullFormat();
990 }
991 }
992
993 return $result;
994 }
995
999 public function fill(array $values): self
1000 {
1001 foreach ($values as $paramName => $value)
1002 {
1003 $this->get($paramName)->setValue($value);
1004 }
1005
1006 return $this;
1007 }
1008
1009 public function __clone()
1010 {
1011 foreach ($this as $key => $param)
1012 {
1013 $this[$key] = clone $param;
1014 }
1015 }
1016}
const NOT_FOUND
Definition Error.php:9
offsetSet($offset, $entry)
Definition Params.php:872
loadByMessage(Message $message)
Definition Params.php:421
static create(string $paramName)
Definition Params.php:742
isSet(string $paramName)
Definition Params.php:765
initByDataEntity(ORM\Objectify\EntityObject $entity)
Definition Params.php:546
add(MessageParameter $parameter)
Definition Params.php:852
toPullFormat(?array $extraParams=null)
Definition Params.php:969
loadByMessageId(int $messageId)
Definition Params.php:435
setMessageId(int $messageId)
Definition Params.php:931
static getType(string $paramName)
Definition Params.php:277
static addType(string $paramName, array $description)
Definition Params.php:319
initByArray(array $items)
Definition Params.php:497
unsetByKeys(array $keys)
Definition Registry.php:10