1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
MessageCollection.php
См. документацию.
1<?php
2
3namespace Bitrix\Im\V2;
4
5use Bitrix\Im\V2\Chat\Copilot\CopilotPopupItem;
6use Bitrix\Im\V2\Chat\ChannelChat;
7use Bitrix\Im\V2\Chat\Comment\CommentPopupItem;
8use Bitrix\Im\V2\Entity\File\FilePopupItem;
9use Bitrix\Im\V2\Entity\Url\UrlCollection;
10use Bitrix\Im\V2\Entity\User\UserPopupItem;
11use Bitrix\Im\V2\Integration\AI\RoleManager;
12use Bitrix\Im\V2\Link\Pin\PinService;
13use Bitrix\Im\V2\Message\AdditionalMessagePopupItem;
14use Bitrix\Im\V2\Message\Param;
15use Bitrix\Im\V2\Message\Reaction\ReactionMessages;
16use Bitrix\Im\V2\Message\Reaction\ReactionPopupItem;
17use Bitrix\Im\V2\Message\ReadService;
18use Bitrix\Im\V2\TariffLimit\DateFilterable;
19use Bitrix\Im\V2\TariffLimit\FilterResult;
20use Bitrix\Imbot\Bot\CopilotChatBot;
21use Bitrix\Main\Loader;
22use Bitrix\Main\ORM\Query\Query;
23use Bitrix\Main\ORM\Fields\ExpressionField;
24use Bitrix\Im\Model\MessageTable;
25use Bitrix\Im\Model\MessageParamTable;
26use Bitrix\Im\Model\MessageUuidTable;
27use Bitrix\Im\V2\Common\ContextCustomer;
28use Bitrix\Im\V2\Entity\File\FileCollection;
29use Bitrix\Im\V2\Link\Reminder\ReminderCollection;
30use Bitrix\Im\V2\Rest\PopupData;
31use Bitrix\Im\V2\Rest\PopupDataAggregatable;
32use Bitrix\Im\V2\Rest\RestConvertible;
33use Bitrix\Im\V2\Service\Context;
34use Bitrix\Im\V2\Message\Params;
35use Bitrix\Main\Type\DateTime;
36
43{
44 use ContextCustomer;
45
46 protected bool $isFileFilled = false;
47 protected bool $isParamsFilled = false;
48 protected bool $isUuidFilled = false;
49 protected bool $isUrlsFilled = false;
50 protected bool $isUnreadFilled = false;
51 protected bool $isViewedFilled = false;
52 protected bool $isReactionsFilled = false;
53
54 //region Collection
55
60 public static function getCollectionElementClass(): string
61 {
62 return Message::class;
63 }
64
68 public static function find(array $filter, array $order, ?int $limit = null, ?Context $context = null, array $select = []): self
69 {
70 //$context = $context ?? Locator::getContext();
71
72 $query = MessageTable::query();
73 $query->setSelect(['ID']);
74
75 if (isset($limit))
76 {
77 $query->setLimit($limit);
78 }
79
80 $messageOrder = ['DATE_CREATE' => $order['ID'] ?? 'DESC', 'ID' => $order['ID'] ?? 'DESC'];
81 $query->setOrder($messageOrder);
82 static::processFilters($query, $filter, $messageOrder);
83 $messageIds = $query->fetchCollection()->getIdList();
84
85 if (empty($messageIds))
86 {
87 return new static();
88 }
89
90 if (empty($select))
91 {
92 $select = ['*'];
93 }
94
95 return new static(MessageTable::query()->whereIn('ID', $messageIds)->setOrder($messageOrder)->setSelect($select)->fetchCollection());
96 }
97
101 public function getIds(): array
102 {
103 return $this->getPrimaryIds();
104 }
105
106
110 public function getFileIds(): array
111 {
112 $this->fillParams();
113
114 $ids = [];
115 foreach ($this as $message)
116 {
117 if ($message->getParams()->isSet(Params::FILE_ID))
118 {
119 $ids[$message->getId()] = $message->getParams()->get(Params::FILE_ID)->getValue();
120 }
121 }
122
123 return $ids;
124 }
125
126 public function getCommonChatId(): ?int
127 {
128 $id = null;
129
130 foreach ($this as $message)
131 {
132 if (isset($id) && $message->getChatId() !== $id)
133 {
134 return null;
135 }
136
137 if (!isset($id))
138 {
139 $id = $message->getChatId();
140 }
141 }
142
143 return $id;
144 }
145
146 public function getCommonChat(): Chat
147 {
148 return Chat::getInstance($this->getCommonChatId());
149 }
150
151 //endregion
152
153 //region Rest
154
155 public function toRestFormat(array $option = []): array
156 {
157 $this->fillAllForRest($option['MESSAGE_SHORT_INFO'] ?? false, $option['MESSAGE_ONLY_COMMON_FIELDS'] ?? false);
158
159 $messagesForRest = [];
160
161 foreach ($this as $message)
162 {
163 $messagesForRest[] = $message->toRestFormat($option);
164 }
165
166 return $messagesForRest;
167 }
168
169 public static function getRestEntityName(): string
170 {
171 return 'messages';
172 }
173
178 public function filterByDate(DateTime $date): FilterResult
179 {
180 $filtered = $this->filter(static fn (Message $message) => $message->getDateCreate()?->getTimestamp() > $date->getTimestamp());
181
182 return (new FilterResult())->setResult($filtered)->setFiltered($this->count() !== $filtered->count());
183 }
184
185 public function getRelatedChatId(): ?int
186 {
187 return $this->getCommonChatId();
188 }
189
190 //endregion
191
192 //region Fillers
193
197 public function fillFiles(): self
198 {
199 if (!$this->isFileFilled)
200 {
201 $fileIdsByMessages = $this->getFileIds();
202
203 $fileIds = [];
204 foreach ($fileIdsByMessages as $fileIdsByMessage)
205 {
206 foreach ($fileIdsByMessage as $fileId)
207 {
208 $fileIds[] = $fileId;
209 }
210 }
211
213
214 foreach ($this as $message)
215 {
216 $messagesFiles = new FileCollection();
217 foreach ($fileIdsByMessages[$message->getId()] ?? [] as $fileId)
218 {
219 $file = $files->getById($fileId);
220 if ($file !== null)
221 {
222 $messagesFiles[] = $file->setChatId($message->getChatId());
223 }
224 }
225 $message->fillFiles($messagesFiles);
226 }
227
228 $this->isFileFilled = true;
229 }
230
231 return $this;
232 }
233
237 public function fillParams(): self
238 {
239 if ($this->isParamsFilled)
240 {
241 return $this;
242 }
243
244 $messageIds = $this->getIds();
245 if (!empty($messageIds))
246 {
247 foreach ($this as $message)
248 {
249 $message->getParams(true)->load([]);
250 }
251
252 $result = MessageParamTable::query()
253 ->setSelect(['*'])
254 ->whereIn('MESSAGE_ID', $this->getIds())
255 ->whereNot('PARAM_NAME', 'LIKE')
256 ->exec()
257 ;
258
259 while ($row = $result->fetch())
260 {
261 $this[$row['MESSAGE_ID']]->getParams(true)->load([$row]);
262 }
263
264 $this->isParamsFilled = true;
265 }
266
267 return $this;
268 }
269
270 public function isParamsFilled(): bool
271 {
273 }
274
275 public function deleteParams(): self
276 {
277 if (!empty($this->getIds()))
278 {
279 $filter = [
280 '=MESSAGE_ID' => $this->getIds(),
281 ];
282
283 MessageParamTable::deleteBatch($filter);
284 }
285
286 foreach ($this as $message)
287 {
288 $message->getParams(true)->clear();
289 }
290
291 $this->isParamsFilled = true;
292
293 return $this;
294 }
295
300 public function resetParams($params): self
301 {
302 if (empty($this->getIds()))
303 {
304 return $this;
305 }
306
307 return $this
308 ->deleteParams()
309 ->multiAddParams($params)
310 ;
311 }
312
313 protected function multiAddParams($params): self
314 {
316
317 if (empty($rows))
318 {
319 return $this;
320 }
321
322 $result = Param::getDataClass()::addMulti($rows, true);
323 if (!$result->isSuccess())
324 {
325 return $this;
326 }
327
328 $this->isParamsFilled = false;
329 $this->fillParams();
330
331 return $this;
332 }
333
335 {
336 $fields = [];
337
338 foreach ($this as $message)
339 {
340 foreach ($params as $paramName => $paramValue)
341 {
342 $fields[] = [
343 'MESSAGE_ID' => $message->getId(),
344 'PARAM_NAME' => $paramName,
345 'PARAM_VALUE' => $paramValue,
346 ];
347 }
348 }
349
350 return $fields;
351 }
352
357 public function setParams($params): self
358 {
359 foreach ($this as $message)
360 {
361 $message->setParams($params);
362 }
363
364 return $this;
365 }
366
370 public function fillUuid(): self
371 {
372 $messageIds = $this->getIds();
373 if (!$this->isUuidFilled && !empty($messageIds))
374 {
375 $uuids = MessageUuidTable::query()
376 ->setSelect(['UUID', 'MESSAGE_ID'])
377 ->whereIn('MESSAGE_ID', $this->getIds())
378 ->fetchAll()
379 ;
380
381 $uuidsByMessageId = [];
382 foreach ($uuids as $uuid)
383 {
384 $uuidsByMessageId[$uuid['MESSAGE_ID']] = $uuid['UUID'];
385 }
386
387 foreach ($this as $message)
388 {
389 $message->setUuid($uuidsByMessageId[$message->getId()] ?? null);
390 }
391
392 $this->isUuidFilled = true;
393 }
394
395 return $this;
396 }
397
401 public function fillUrls(): self
402 {
403 if ($this->isUrlsFilled)
404 {
405 return $this;
406 }
407
408 $this->fillParams();
409 $urlIdByMessageIds = [];
410 foreach ($this as $message)
411 {
412 if (!$message->getParams()->isSet(Params::URL_ID))
413 {
414 continue;
415 }
416
417 $urlId = $message->getParams()->get(Params::URL_ID)->getValue()[0] ?? null;
418 if (isset($urlId))
419 {
420 $urlIdByMessageIds[$message->getId()] = $urlId;
421 }
422 }
423 $urlCollection = UrlCollection::initByPreviewUrlsIds($urlIdByMessageIds, false);
424 foreach ($this as $message)
425 {
426 if (isset($urlIdByMessageIds[$message->getId()]))
427 {
428 $urlId = $urlIdByMessageIds[$message->getId()];
429 $message->setUrl($urlCollection->getById($urlId));
430 }
431 }
432
433 $this->isUrlsFilled = true;
434
435 return $this;
436 }
437
441 public function fillUnread(): self
442 {
443 if ($this->isUnreadFilled)
444 {
445 return $this;
446 }
447
448 $readStatuses = (new ReadService())->getReadStatusesByMessageIds($this->getIds());
449
450 foreach ($this as $message)
451 {
452 $message->setUnread(!($readStatuses[$message->getMessageId()]));
453 }
454
455 $this->isUnreadFilled = true;
456
457 return $this;
458 }
459
460 public function fillViewed(): self
461 {
462 if ($this->isViewedFilled)
463 {
464 return $this;
465 }
466
467 $notOwnMessages = [];
468
469 foreach ($this as $message)
470 {
471 if ($message->getAuthorId() === $this->getContext()->getUserId())
472 {
473 $message->setViewed(true);
474
475 continue;
476 }
477
478 $notOwnMessages[] = $message->getMessageId();
479 }
480
481 $viewStatuses = (new ReadService())->getViewStatusesByMessageIds($notOwnMessages);
482
483 foreach ($notOwnMessages as $notOwnMessageId)
484 {
485 $this[$notOwnMessageId]->setViewed($viewStatuses[$notOwnMessageId]);
486 }
487
488 $this->isViewedFilled = true;
489
490 return $this;
491 }
492
493 public function fillReactions(): self
494 {
495 if ($this->isReactionsFilled)
496 {
497 return $this;
498 }
499
500 $messageIds = $this->getIds();
501
502 if (empty($messageIds))
503 {
504 return $this;
505 }
506
507 $reactions = new ReactionMessages($messageIds);
508
509 foreach ($this as $message)
510 {
511 $message->setReactions($reactions->getReactionMessage($message->getMessageId()));
512 }
513
514 $this->isReactionsFilled = true;
515
516 return $this;
517 }
518
522 public function fillAllForRest(bool $shortInfo = false, bool $onlyCommonInfo = false): self
523 {
524 if (!$shortInfo)
525 {
526 $this->fillUrls()->fillReactions();
527 }
528
529 if (!$onlyCommonInfo)
530 {
531 $this->fillUnread()->fillViewed();
532 }
533
534 return $this
535 ->fillParams()
536 ->fillUuid()
537 ;
538 }
539
540 //endregion
541
542 public function setViewedByOthers(): self
543 {
544 foreach ($this as $message)
545 {
546 if (!$message->isNotifyRead())
547 {
548 $message->markNotifyRead(true);
549 }
550 }
551
552 return $this;
553 }
554
555 //region Getters
556
560 public function getFiles(): FileCollection
561 {
562 $this->fillFiles();
563
564 $files = new FileCollection();
565
566 foreach ($this as $message)
567 {
568 $filesFromMessage = $message->getFiles();
569 foreach ($filesFromMessage as $fileFromMessage)
570 {
571 $files[] = $fileFromMessage;
572 }
573 }
574
575 return $files->getUnique();
576 }
577
578 public function getUserIds(): array
579 {
580 $users = [];
581
582 $this->fillParams();
583 foreach ($this as $message)
584 {
585 $usersFromMessage = $message->getUserIds();
586
587 if ($message->getParams()->isSet(Params::FORWARD_USER_ID))
588 {
589 $forwardUserId = $message->getParams()->get(Params::FORWARD_USER_ID)->getValue();
590 $usersFromMessage[] = $forwardUserId;
591 }
592
593 if ($message->getParams()->isSet(Params::CHAT_USER))
594 {
595 foreach ($message->getParams()->get(Params::CHAT_USER)->getValue() as $chatUser)
596 {
597 $usersFromMessage[] = $chatUser;
598 }
599 }
600
601 foreach ($usersFromMessage as $userFromMessage)
602 {
603 $users[] = $userFromMessage;
604 }
605 }
606
607 return $users;
608 }
609
614 {
615 return ReminderCollection::getByMessagesAndAuthorId($this, $this->getContext()->getUserId());
616 }
617
618 public function getReplayedMessageIds(): array
619 {
620 $this->fillParams();
621 $result = [];
622 foreach ($this as $message)
623 {
624 if ($message->getParams()->isSet(Params::REPLY_ID))
625 {
626 $result[] = $message->getParams()->get(Params::REPLY_ID)->getValue();
627 }
628 }
629
630 return $result;
631 }
632
634 {
635 $reactions = new ReactionMessages([]);
636 $this->fillReactions();
637
638 foreach ($this as $message)
639 {
640 $reactions->addReactionMessage($message->getReactions());
641 }
642
643 return $reactions;
644 }
645
646 public function getCopilotRoles(): array
647 {
648 $this->fillParams();
649 $copilotRoles = [];
650
651 foreach ($this as $message)
652 {
653 $params = $message->getParams();
654
655 if ($params->isSet(Params::COPILOT_ROLE))
656 {
657 if ($params->isSet(Params::FORWARD_ID))
658 {
659 $messageId = (int)$params->get(Params::FORWARD_ID)->getValue();
660 }
661
662 $copilotRoles[$messageId ?? $message->getId()] = $params->get(Params::COPILOT_ROLE)->getValue();
663
664 continue;
665 }
666
667 if (!$params->isSet(Params::COMPONENT_ID))
668 {
669 continue;
670 }
671
672 $messageComponentId = $params->get(Params::COMPONENT_ID)->getValue();
673
674 if (
675 Loader::includeModule('imbot')
676 && in_array($messageComponentId, CopilotChatBot::ALL_COPILOT_MESSAGE_COMPONENTS, true)
677 )
678 {
679 $copilotRoles[$message->getId()] = RoleManager::getDefaultRoleCode();
680 }
681 }
682
683 return $copilotRoles;
684 }
685
686 public function getPopupData(array $excludedList = []): PopupData
687 {
688 $additionalMessageIds = array_diff($this->getReplayedMessageIds(), $this->getIds());
689 $popup = [
690 new UserPopupItem($this->getUserIds()),
691 new FilePopupItem($this->getFiles()),
692 new AdditionalMessagePopupItem($additionalMessageIds),
693 CopilotPopupItem::getInstanceByMessages($this),
694 ];
695
696 if (!in_array(ReactionPopupItem::class, $excludedList, true))
697 {
698 $popup[] = new ReactionPopupItem($this->getReactions());
699 }
700
701 $chat = $this->getCommonChat();
702
703 if (
704 !in_array(CommentPopupItem::class, $excludedList, true)
705 && $chat instanceof ChannelChat
706 )
707 {
708 $popup[] = new CommentPopupItem($chat->getId(), $this->getIds());
709 }
710
711 return new PopupData($popup, $excludedList);
712 }
713
714 public function filterByChatId(int $chatId): self
715 {
716 $filteredCollection = new static();
717
718 foreach ($this as $message)
719 {
720 if ($message->getChatId() === $chatId)
721 {
722 $filteredCollection->add($message);
723 }
724 }
725
726 return $filteredCollection;
727 }
728
729 //endregion
730
731 public function unpin(bool $clearParams = true): Result
732 {
733 $pinService = new PinService();
734 $pinService->setContext($this->context);
735
736 return $pinService->unpinMessages($this, $clearParams);
737 }
738
739 protected static function processFilters(Query $query, array $filter, array $order): void
740 {
741 if (isset($filter['CHAT_ID']))
742 {
743 $query->where('CHAT_ID', $filter['CHAT_ID']);
744 }
745
746 if (isset($filter['SEARCH_MESSAGE']) && mb_strlen($filter['SEARCH_MESSAGE']) > 2)
747 {
749 if ($connection instanceof \Bitrix\Main\DB\PgsqlConnection)
750 {
751 $filter['SEARCH_MESSAGE'] = $connection->getSqlHelper()->forSql($filter['SEARCH_MESSAGE']);
752 $query->registerRuntimeField(
753 new ExpressionField(
754 'CASE_INSENSITIVE_MESSAGE',
755 "(CASE WHEN %s ILIKE '%%{$filter['SEARCH_MESSAGE']}%%' THEN 1 ELSE 0 END)",
756 ['MESSAGE']
757 )
758 );
759 $query->where('CASE_INSENSITIVE_MESSAGE', '=', '1');
760 }
761 else
762 {
763 $query->whereLike('MESSAGE', "%{$filter['SEARCH_MESSAGE']}%");
764 }
765 }
766
767 if (isset($filter['START_ID']) && (int)$filter['START_ID'] > 0)
768 {
769 $query->where('ID', '>=', $filter['START_ID']);
770 }
771
772 if (isset($filter['LAST_ID']))
773 {
774 $operator = $order['ID'] === 'DESC' ? '<' : '>';
775 $query->where('ID', $operator, $filter['LAST_ID']);
776 }
777
778 if (isset($filter['DATE_FROM']))
779 {
780 $query->where('DATE_CREATE', '>=', $filter['DATE_FROM']);
781 }
782
783 if (isset($filter['DATE_TO']))
784 {
785 $query->where('DATE_CREATE', '<=', $filter['DATE_TO']);
786 }
787
788 if (isset($filter['DATE']))
789 {
790 $query->where('DATE_CREATE', '>=', $filter['DATE']);
791
792 $to = clone $filter['DATE'];
793 $to->add('1 DAY');
794
795 $query->where('DATE_CREATE', '<=', $to);
796 }
797
798 if ($filter['WITHOUT_SYSTEM_MESSAGE'] ?? false)
799 {
800 $query->where('AUTHOR_ID', '!=', 0);
801 }
802 }
803}
$connection
Определения actionsdefinitions.php:38
if(! $messageFields||!isset($messageFields['message_id'])||!isset($messageFields['status'])||!CModule::IncludeModule("messageservice")) $messageId
Определения callback_ismscenter.php:26
static initByDiskFilesIds(array $diskFilesIds, ?int $chatId=null)
Определения FileCollection.php:57
static initByPreviewUrlsIds(array $previewUrlsIds, bool $withHtml=true)
Определения UrlCollection.php:39
static getRestEntityName()
Определения MessageCollection.php:169
toRestFormat(array $option=[])
Определения MessageCollection.php:155
static getCollectionElementClass()
Определения MessageCollection.php:60
static processFilters(Query $query, array $filter, array $order)
Определения MessageCollection.php:739
static find(array $filter, array $order, ?int $limit=null, ?Context $context=null, array $select=[])
Определения MessageCollection.php:68
getPopupData(array $excludedList=[])
Определения MessageCollection.php:686
fillAllForRest(bool $shortInfo=false, bool $onlyCommonInfo=false)
Определения MessageCollection.php:522
getParamsFieldsForMultiAdd(array $params)
Определения MessageCollection.php:334
unpin(bool $clearParams=true)
Определения MessageCollection.php:731
filterByDate(DateTime $date)
Определения MessageCollection.php:178
filterByChatId(int $chatId)
Определения MessageCollection.php:714
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
Определения result.php:20
getDataClass()
Определения entity.php:696
getTimestamp()
Определения date.php:218
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$select
Определения iblock_catalog_list.php:194
$filter
Определения iblock_catalog_list.php:54
$context
Определения csv_new_setup.php:223
Определения Uuid.php:3
Определения culture.php:9
Определения arrayresult.php:2
Определения chain.php:3
$files
Определения mysql_to_pgsql.php:30
$order
Определения payment.php:8
$message
Определения payment.php:8
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$option
Определения options.php:1711
$rows
Определения options.php:264
$fields
Определения yandex_run.php:501