Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
MessageCollection.php
1<?php
2
3namespace Bitrix\Im\V2;
4
19use Bitrix\Im\V2\Common\ContextCustomer;
28
35{
36 use ContextCustomer;
37
38 protected bool $isFileFilled = false;
39 protected bool $isParamsFilled = false;
40 protected bool $isUuidFilled = false;
41 protected bool $isUrlsFilled = false;
42 protected bool $isUnreadFilled = false;
43 protected bool $isViewedFilled = false;
44 protected bool $isViewedByOthersFilled = false;
45 protected bool $isReactionsFilled = false;
46
47 //region Collection
48
53 public static function getCollectionElementClass(): string
54 {
55 return Message::class;
56 }
57
61 public static function find(array $filter, array $order, ?int $limit = null, ?Context $context = null, array $select = []): self
62 {
63 //$context = $context ?? Locator::getContext();
64
65 $query = MessageTable::query();
66 $query->setSelect(['ID']);
67
68 if (isset($limit))
69 {
70 $query->setLimit($limit);
71 }
72
73 $messageOrder = ['DATE_CREATE' => $order['ID'] ?? 'DESC', 'ID' => $order['ID'] ?? 'DESC'];
74 $query->setOrder($messageOrder);
75 static::processFilters($query, $filter, $messageOrder);
76 $messageIds = $query->fetchCollection()->getIdList();
77
78 if (empty($messageIds))
79 {
80 return new static();
81 }
82
83 if (empty($select))
84 {
85 $select = ['*'];
86 }
87
88 return new static(MessageTable::query()->whereIn('ID', $messageIds)->setOrder($messageOrder)->setSelect($select)->fetchCollection());
89 }
90
94 public function getIds(): array
95 {
96 return $this->getPrimaryIds();
97 }
98
99
103 public function getFileIds(): array
104 {
105 $this->fillParams();
106
107 $ids = [];
108 foreach ($this as $message)
109 {
110 if ($message->getParams()->isSet(Params::FILE_ID))
111 {
112 $ids[$message->getId()] = $message->getParams()->get(Params::FILE_ID)->getValue();
113 }
114 }
115
116 return $ids;
117 }
118
119 public function getCommonChatId(): ?int
120 {
121 $id = null;
122
123 foreach ($this as $message)
124 {
125 if (isset($id) && $message->getChatId() !== $id)
126 {
127 return null;
128 }
129
130 if (!isset($id))
131 {
132 $id = $message->getChatId();
133 }
134 }
135
136 return $id;
137 }
138
139 //endregion
140
141 //region Rest
142
143 public function toRestFormat(array $option = []): array
144 {
145 $this->fillAllForRest();
146
147 $messagesForRest = [];
148
149 foreach ($this as $message)
150 {
151 $messagesForRest[] = $message->toRestFormat($option);
152 }
153
154 return $messagesForRest;
155 }
156
157 public static function getRestEntityName(): string
158 {
159 return 'messages';
160 }
161
162 //endregion
163
164 //region Fillers
165
169 public function fillFiles(): self
170 {
171 if (!$this->isFileFilled)
172 {
173 $fileIdsByMessages = $this->getFileIds();
174
175 $fileIds = [];
176 foreach ($fileIdsByMessages as $fileIdsByMessage)
177 {
178 foreach ($fileIdsByMessage as $fileId)
179 {
180 $fileIds[] = $fileId;
181 }
182 }
183
184 $files = FileCollection::initByDiskFilesIds($fileIds);
185
186 foreach ($this as $message)
187 {
188 $messagesFiles = new FileCollection();
189 foreach ($fileIdsByMessages[$message->getId()] ?? [] as $fileId)
190 {
191 $file = $files->getById($fileId);
192 if ($file !== null)
193 {
194 $messagesFiles[] = $file->setChatId($message->getChatId());
195 }
196 }
197 $message->fillFiles($messagesFiles);
198 }
199
200 $this->isFileFilled = true;
201 }
202
203 return $this;
204 }
205
209 public function fillParams(): self
210 {
211 $messageIds = $this->getIds();
212 if (!$this->isParamsFilled && !empty($messageIds))
213 {
214 $paramsCollection = MessageParamTable::query()
215 ->setSelect(['*'])
216 ->whereIn('MESSAGE_ID', $this->getIds())
217 ->fetchCollection()
218 ;
219
220 foreach ($paramsCollection as $paramRow)
221 {
222 $this[$paramRow->getMessageId()]->getParams(true)->load($paramRow);
223 }
224
225 $this->isParamsFilled = true;
226 }
227
228 return $this;
229 }
230
234 public function fillUuid(): self
235 {
236 $messageIds = $this->getIds();
237 if (!$this->isUuidFilled && !empty($messageIds))
238 {
239 $uuids = MessageUuidTable::query()
240 ->setSelect(['UUID', 'MESSAGE_ID'])
241 ->whereIn('MESSAGE_ID', $this->getIds())
242 ->fetchAll()
243 ;
244
245 $uuidsByMessageId = [];
246 foreach ($uuids as $uuid)
247 {
248 $uuidsByMessageId[$uuid['MESSAGE_ID']] = $uuid['UUID'];
249 }
250
251 foreach ($this as $message)
252 {
253 $message->setUuid($uuidsByMessageId[$message->getId()] ?? null);
254 }
255
256 $this->isUuidFilled = true;
257 }
258
259 return $this;
260 }
261
265 public function fillUrls(): self
266 {
267 if ($this->isUrlsFilled)
268 {
269 return $this;
270 }
271
272 $this->fillParams();
273 $urlIdByMessageIds = [];
274 foreach ($this as $message)
275 {
276 $urlId = $message->getParams()->get(Params::URL_ID)->getValue()[0] ?? null;
277 if (isset($urlId))
278 {
279 $urlIdByMessageIds[$message->getId()] = $urlId;
280 }
281 }
282 $urlCollection = UrlCollection::initByPreviewUrlsIds($urlIdByMessageIds, false);
283 foreach ($this as $message)
284 {
285 if (isset($urlIdByMessageIds[$message->getId()]))
286 {
287 $urlId = $urlIdByMessageIds[$message->getId()];
288 $message->setUrl($urlCollection->getById($urlId));
289 }
290 }
291
292 $this->isUrlsFilled = true;
293
294 return $this;
295 }
296
300 public function fillUnread(): self
301 {
302 if ($this->isUnreadFilled)
303 {
304 return $this;
305 }
306
307 $readStatuses = (new ReadService())->getReadStatusesByMessageIds($this->getIds());
308
309 foreach ($this as $message)
310 {
311 $message->setUnread(!($readStatuses[$message->getMessageId()]));
312 }
313
314 $this->isUnreadFilled = true;
315
316 return $this;
317 }
318
319 public function fillViewed(): self
320 {
321 if ($this->isViewedFilled)
322 {
323 return $this;
324 }
325
326 $notOwnMessages = [];
327
328 foreach ($this as $message)
329 {
330 if ($message->getAuthorId() === $this->getContext()->getUserId())
331 {
332 $message->setViewed(true);
333
334 continue;
335 }
336
337 $notOwnMessages[] = $message->getMessageId();
338 }
339
340 $viewStatuses = (new ReadService())->getViewStatusesByMessageIds($notOwnMessages);
341
342 foreach ($notOwnMessages as $notOwnMessageId)
343 {
344 $this[$notOwnMessageId]->setViewed($viewStatuses[$notOwnMessageId]);
345 }
346
347 $this->isViewedFilled = true;
348
349 return $this;
350 }
351
352 public function fillViewedByOthers(): self
353 {
354 if ($this->isViewedByOthersFilled)
355 {
356 return $this;
357 }
358
359 $statuses = (new ViewedService())->getMessageStatuses($this->getIds());
360
361 foreach ($this as $message)
362 {
363 $status = $statuses[$message->getId()] ?? \IM_MESSAGE_STATUS_RECEIVED;
364 $message->setViewedByOthers($status === \IM_MESSAGE_STATUS_DELIVERED);
365 }
366
367 $this->isViewedByOthersFilled = true;
368
369 return $this;
370 }
371
372 public function fillReactions(): self
373 {
374 if ($this->isReactionsFilled)
375 {
376 return $this;
377 }
378
379 $messageIds = $this->getIds();
380
381 if (empty($messageIds))
382 {
383 return $this;
384 }
385
386 $reactions = new ReactionMessages($messageIds);
387
388 foreach ($this as $message)
389 {
390 $message->setReactions($reactions->getReactionMessage($message->getMessageId()));
391 }
392
393 $this->isReactionsFilled = true;
394
395 return $this;
396 }
397
401 public function fillAllForRest(): self
402 {
403 return $this
404 ->fillParams()
405 ->fillUrls()
406 ->fillUuid()
407 ->fillUnread()
408 ->fillViewed()
409 ->fillViewedByOthers()
410 ->fillReactions()
411 ;
412 }
413
414 //endregion
415
416 //region Getters
417
421 public function getFiles(): FileCollection
422 {
423 $this->fillFiles();
424
425 $files = new FileCollection();
426
427 foreach ($this as $message)
428 {
429 $filesFromMessage = $message->getFiles();
430 foreach ($filesFromMessage as $fileFromMessage)
431 {
432 $files[] = $fileFromMessage;
433 }
434 }
435
436 return $files->getUnique();
437 }
438
439 public function getUserIds(): array
440 {
441 $users = [];
442
443 $this->fillParams();
444 foreach ($this as $message)
445 {
446 $usersFromMessage = $message->getUserIds();
447
448 if ($message->getParams()->isSet(Params::FORWARD_USER_ID))
449 {
450 $forwardUserId = $message->getParams()->get(Params::FORWARD_USER_ID)->getValue();
451 $usersFromMessage[] = $forwardUserId;
452 }
453
454 if ($message->getParams()->isSet(Params::CHAT_USER))
455 {
456 foreach ($message->getParams()->get(Params::CHAT_USER)->getValue() as $chatUser)
457 {
458 $usersFromMessage[] = $chatUser;
459 }
460 }
461
462 foreach ($usersFromMessage as $userFromMessage)
463 {
464 $users[] = $userFromMessage;
465 }
466 }
467
468 return $users;
469 }
470
475 {
476 return ReminderCollection::getByMessagesAndAuthorId($this, $this->getContext()->getUserId());
477 }
478
479 public function getReplayedMessageIds(): array
480 {
481 $this->fillParams();
482 $result = [];
483 foreach ($this as $message)
484 {
485 if ($message->getParams()->isSet(Params::REPLY_ID))
486 {
487 $result[] = $message->getParams()->get(Params::REPLY_ID)->getValue();
488 }
489 }
490
491 return $result;
492 }
493
495 {
496 $reactions = new ReactionMessages([]);
497
498 foreach ($this as $message)
499 {
500 $reactions->addReactionMessage($message->getReactions());
501 }
502
503 return $reactions;
504 }
505
506 public function getPopupData(array $excludedList = []): PopupData
507 {
508 $this->fillAllForRest();
509
510 return (new PopupData([
511 new UserPopupItem($this->getUserIds()),
512 new FilePopupItem($this->getFiles()),
513 new ReminderPopupItem($this->getReminders()),
515 new ReactionPopupItem($this->getReactions())
516 ], $excludedList));
517 }
518
519 public function filterByChatId(int $chatId): self
520 {
521 $filteredCollection = new static();
522
523 foreach ($this as $message)
524 {
525 if ($message->getChatId() === $chatId)
526 {
527 $filteredCollection->add($message);
528 }
529 }
530
531 return $filteredCollection;
532 }
533
534 //endregion
535
536 protected static function processFilters(Query $query, array $filter, array $order): void
537 {
538 if (isset($filter['CHAT_ID']))
539 {
540 $query->where('CHAT_ID', $filter['CHAT_ID']);
541 }
542
543 if (isset($filter['SEARCH_MESSAGE']) && mb_strlen($filter['SEARCH_MESSAGE']) > 2)
544 {
545 $connection = \Bitrix\Main\Application::getConnection();
546 if ($connection instanceof \Bitrix\Main\DB\PgsqlConnection)
547 {
548 $filter['SEARCH_MESSAGE'] = $connection->getSqlHelper()->forSql($filter['SEARCH_MESSAGE']);
549 $query->registerRuntimeField(
550 new ExpressionField(
551 'CASE_INSENSITIVE_MESSAGE',
552 "(CASE WHEN %s ILIKE '%%{$filter['SEARCH_MESSAGE']}%%' THEN 1 ELSE 0 END)",
553 ['MESSAGE']
554 )
555 );
556 $query->where('CASE_INSENSITIVE_MESSAGE', '=', '1');
557 }
558 else
559 {
560 $query->whereLike('MESSAGE', "%{$filter['SEARCH_MESSAGE']}%");
561 }
562 }
563
564 if (isset($filter['START_ID']) && (int)$filter['START_ID'] > 0)
565 {
566 $query->where('ID', '>=', $filter['START_ID']);
567 }
568
569 if (isset($filter['LAST_ID']))
570 {
571 $operator = $order['ID'] === 'DESC' ? '<' : '>';
572 $query->where('ID', $operator, $filter['LAST_ID']);
573 }
574
575 if (isset($filter['DATE_FROM']))
576 {
577 $query->where('DATE_CREATE', '>=', $filter['DATE_FROM']);
578 }
579
580 if (isset($filter['DATE_TO']))
581 {
582 $query->where('DATE_CREATE', '<=', $filter['DATE_TO']);
583 }
584
585 if (isset($filter['DATE']))
586 {
587 $query->where('DATE_CREATE', '>=', $filter['DATE']);
588
589 $to = clone $filter['DATE'];
590 $to->add('1 DAY');
591
592 $query->where('DATE_CREATE', '<=', $to);
593 }
594 }
595}
static initByDiskFilesIds(array $diskFilesIds, ?int $chatId=null)
static initByPreviewUrlsIds(array $previewUrlsIds, bool $withHtml=true)
static processFilters(Query $query, array $filter, array $order)
static find(array $filter, array $order, ?int $limit=null, ?Context $context=null, array $select=[])
getPopupData(array $excludedList=[])
registerRuntimeField($name, $fieldInfo=null)
Definition query.php:831