Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
ReadService.php
1<?php
2
4
11use Bitrix\Im\V2\Common\ContextCustomer;
22
24{
25 use ContextCustomer
26 {
27 setContext as private defaultSetContext;
28 }
29
32
33 private static array $lastMessageIdCache = [];
34
35 public function __construct(?int $userId = null)
36 {
37 $this->counterService = new CounterService();
38 $this->viewedService = new ViewedService();
39
40 if (isset($userId))
41 {
42 $context = new Context();
43 $context->setUser($userId);
44 $this->setContext($context);
45 $this->counterService->setContext($context);
46 $this->viewedService->setContext($context);
47 }
48 }
49
50 public function readTo(Message $message): Result
51 {
52 $this->setLastIdForRead($message->getMessageId(), $message->getChatId());
53 $this->counterService->deleteTo($message);
54 $counter = $this->counterService->getByChat($message->getChatId());
55 $viewResult = $this->viewedService->addTo($message);
56 $this->updateDateRecent($message->getChatId());
57 if (!$message->getChat() instanceof Chat\OpenLineChat)
58 {
59 Sync\Logger::getInstance()->add(
60 new Sync\Event(Sync\Event::ADD_EVENT, Sync\Event::CHAT_ENTITY, $message->getChatId()),
61 $this->getContext()->getUserId()
62 );
63 }
64
65 $viewedMessages = [];
66 if ($viewResult->isSuccess())
67 {
68 $viewedMessages = $viewResult->getResult()['VIEWED_MESSAGES'] ?? [];
69 }
70
71 return (new Result())->setResult(['COUNTER' => $counter, 'VIEWED_MESSAGES' => $viewedMessages]);
72 }
73
74 public function read(MessageCollection $messages, Chat $chat): Result
75 {
76 $maxId = max($messages->getIds());
77 $this->setLastIdForRead($maxId, $chat->getChatId());
78 $this->counterService->deleteTo($messages[$maxId]);
79 $counter = $this->counterService->getByChat($chat->getChatId());
80 $messagesToView = $messages
81 ->withContextUser($this->getContext()->getUserId())
82 ->fillViewed()
83 ->filter(fn (Message $message) => !$message->isViewed())
84 ;
85 $this->viewedService->add($messagesToView);
86 $this->updateDateRecent($chat->getChatId());
87 if (!$chat instanceof Chat\OpenLineChat)
88 {
89 Sync\Logger::getInstance()->add(
90 new Sync\Event(Sync\Event::ADD_EVENT, Sync\Event::CHAT_ENTITY, $chat->getChatId()),
91 $this->getContext()->getUserId()
92 );
93 }
94
95 return (new Result())->setResult(['COUNTER' => $counter, 'VIEWED_MESSAGES' => $messagesToView]);
96 }
97
98 public function readNotifications(MessageCollection $messages, array $userByChatId): Result
99 {
100 $chatIds = [];
101
102 foreach ($messages as $message)
103 {
104 $chatIds[$message->getChatId()] = 0;
105 }
106
107 $chatIds = array_keys($chatIds);
108
109 $this->counterService->deleteByMessageIdsForAll($messages->getIds(), $userByChatId);
110 $counters = $this->counterService->getForNotifyChats($chatIds);
111 $time = microtime(true);
112 //$this->viewedController->add($messages);
113
114 /*foreach ($chatIds as $chatId)
115 {
116 $this->sendPush($chatId, [(int)$userByChatId[$chatId]], $counters[$chatId], $time);
117 Sync\Logger::getInstance()->add(
118 new Sync\Event(Sync\Event::ADD_EVENT, Sync\Event::CHAT_ENTITY, $chatId),
119 (int)$userByChatId[$chatId]
120 );
121 }*/
122
123 return (new Result())->setResult(['COUNTERS' => $counters]);
124 }
125
126 public function readAllInChat(int $chatId): Result
127 {
128 $lastId = $this->getLastMessageIdInChat($chatId);
129 $this->setLastIdForRead($lastId, $chatId);
130 $this->counterService->deleteByChatId($chatId);
131 $counter = 0;
132 //$this->viewedController->addAllFromChat($chatId);
133 $this->updateDateRecent($chatId);
134 if (!Chat::getInstance($chatId) instanceof Chat\OpenLineChat)
135 {
136 Sync\Logger::getInstance()->add(
137 new Sync\Event(Sync\Event::ADD_EVENT, Sync\Event::CHAT_ENTITY, $chatId),
138 $this->getContext()->getUserId()
139 );
140 }
141
142 return (new Result())->setResult(['COUNTER' => $counter, 'VIEWED_MESSAGES' => new MessageCollection()]);
143 }
144
145 public function readAll(): void
146 {
147 $this->setLastIdForReadAll();
148 $this->counterService->deleteAll();
149 Sync\Logger::getInstance()->add(
150 new Sync\Event(Sync\Event::READ_ALL_EVENT, Sync\Event::CHAT_ENTITY, 0),
151 $this->getContext()->getUserId()
152 );
153 }
154
155 public function unreadTo(Message $message): Result
156 {
157 //$this->setLastIdForUnread($message->getMessageId(), $message->getChatId());
158 $relation = $message->getChat()->withContext($this->context)->getSelfRelation();
159 if ($relation === null)
160 {
161 return new Result();
162 }
163 $this->counterService->addStartingFrom($message->getMessageId(), $relation);
164 $this->viewedService->deleteStartingFrom($message);
165 if (!$message->getChat() instanceof Chat\OpenLineChat)
166 {
167 Sync\Logger::getInstance()->add(
168 new Sync\Event(Sync\Event::ADD_EVENT, Sync\Event::CHAT_ENTITY, $message->getChatId()),
169 $this->getContext()->getUserId()
170 );
171 }
172
173 return new Result();
174 }
175
176 public function unreadNotifications(MessageCollection $messages, Relation $relation): Result
177 {
178 $this->counterService->addCollection($messages, $relation);
179 $counter = $this->counterService->getByChat($relation->getChatId());
180
181 return (new Result())->setResult(['COUNTER' => $counter]);
182 }
183
191 public function markNotificationUnread(Message $message, RelationCollection $relations): self
192 {
193 $this->counterService->addForEachUser($message, $relations);
194 return $this;
195 }
196
204 public function markMessageUnread(Message $message, RelationCollection $relations): self
205 {
206 $this->counterService->addForEachUser($message, $relations);
207 $this->counterService->deleteTo($message);
208 return $this;
209 }
210
217 public function markRecentUnread(Message $message): self
218 {
219 Recent::unread($message->getChat()->withContext($this->context)->getDialogId(), false, $this->getContext()->getUserId());
220 return $this;
221 }
222
230 public function getCountersForUsers(Message $message, RelationCollection $relations): array
231 {
232 return $this->counterService->getByChatForEachUsers($message->getChatId(), $relations->getUserIds());
233 }
234
242 public function onAfterMessageSend(Message $message, RelationCollection $relations, bool $withoutCounters = false): Result
243 {
244 if (!$withoutCounters)
245 {
246 $this->markMessageUnread($message, $relations);
247 }
248
249 $counters = $this
250 ->markRecentUnread($message)
251 ->getCountersForUsers($message, $relations)
252 ;
253
254 return (new Result())->setResult(['COUNTERS' => $counters]);
255 }
256
257 public function onAfterNotificationSend(Message $message, Relation $relation): Result
258 {
259 $relationCollection = new RelationCollection();
260 $relationCollection->add($relation);
261 $this->counterService->addForEachUser($message, $relationCollection);
262 $counter = $this->counterService->getByChat($relation->getChatId());
263
264 return (new Result())->setResult(['COUNTER' => $counter]);
265 }
266
267 public function deleteByMessageId(int $messageId, ?array $invalidateCacheUsers = null): void
268 {
269 $this->counterService->deleteByMessageIdForAll($messageId, $invalidateCacheUsers);
270 $this->viewedService->deleteByMessageIdForAll($messageId);
271 }
272
273 public function deleteByChatId(int $chatId): void
274 {
275 $this->counterService->deleteByChatId($chatId);
276 $this->viewedService->deleteByChatId($chatId);
277 }
278
279 /*public function deleteByMessageIds(array $messageIds): void
280 {
281 $this->counterService->deleteByMessageIdsForAll($messageIds);
282 $this->viewedController->deleteByMessageIdsForAll($messageIds);
283 }*/
284
285 public function getReadStatusesByMessageIds(array $messageIds): array
286 {
287 if (empty($messageIds))
288 {
289 return [];
290 }
291
293 ->setSelect(['MESSAGE_ID'])
294 ->whereIn('MESSAGE_ID', $messageIds)
295 ->where('USER_ID', $this->getContext()->getUserId())
296 ->exec()
297 ; //todo add index
298
299 $unreadMessages = [];
300
301 while ($row = $query->fetch())
302 {
303 $unreadMessages[(int)$row['MESSAGE_ID']] = false;
304 }
305
306 $readStatuses = [];
307
308 foreach ($messageIds as $messageId)
309 {
310 $readStatuses[$messageId] = $unreadMessages[$messageId] ?? true;
311 }
312
313 return $readStatuses;
314 }
315
316 public function getViewStatusesByMessageIds(array $messageIds): array
317 {
318 if (empty($messageIds))
319 {
320 return [];
321 }
322
323 $query = MessageViewedTable::query()
324 ->setSelect(['MESSAGE_ID'])
325 ->whereIn('MESSAGE_ID', $messageIds)
326 ->where('USER_ID', $this->getContext()->getUserId())
327 ->exec()
328 ; //todo add index
329
330 $viewedMessages = [];
331
332 while ($row = $query->fetch())
333 {
334 $viewedMessages[(int)$row['MESSAGE_ID']] = true;
335 }
336
337 $viewStatuses = [];
338
339 foreach ($messageIds as $messageId)
340 {
341 $viewStatuses[$messageId] = $viewedMessages[$messageId] ?? false;
342 }
343
344 return $viewStatuses;
345 }
346
347 public function getLastIdByChatId(int $chatId): int
348 {
349 $relation = RelationTable::query()
350 ->setSelect(['LAST_ID'])
351 ->where('USER_ID', $this->getContext()->getUserId())
352 ->where('CHAT_ID', $chatId)->setLimit(1)
353 ->fetch();
354
355 if ($relation)
356 {
357 return $relation['LAST_ID'] ?? 0;
358 }
359
360 return 0;
361 }
362
363 public function getLastMessageIdInChat(int $chatId): int
364 {
365 if (isset(static::$lastMessageIdCache[$chatId]))
366 {
367 return static::$lastMessageIdCache[$chatId];
368 }
369
370 $result = ChatTable::query()->setSelect(['LAST_MESSAGE_ID'])->where('ID', $chatId)->fetch();
371 $lastMessageId = 0;
372
373 if (!$result)
374 {
375 $lastMessageId = 0;
376 }
377 else
378 {
379 $lastMessageId = (int)($result['LAST_MESSAGE_ID'] ?? 0);
380 }
381
382 static::$lastMessageIdCache[$chatId] = $lastMessageId;
383
384 return $lastMessageId;
385 }
386
387 public function getChatMessageStatus(int $chatId): string
388 {
389 $lastMessageId = $this->getLastMessageIdInChat($chatId);
390
391 if ($lastMessageId === 0)
392 {
393 return \IM_MESSAGE_STATUS_RECEIVED;
394 }
395
396 return $this->viewedService->getMessageStatus($lastMessageId);
397 }
398
400 {
402 }
403
405 {
407 }
408
409
410 public function setLastIdForRead(int $lastId, int $chatId): void
411 {
412 $sql = "
413 UPDATE b_im_relation
414 SET LAST_ID=(CASE WHEN LAST_ID > {$lastId} THEN LAST_ID ELSE {$lastId} END)
415 WHERE CHAT_ID={$chatId} AND USER_ID={$this->getContext()->getUserId()}
416 ";
417
418 Application::getConnection()->queryExecute($sql);
419 }
420
421 public function setContext(?Context $context): self
422 {
423 $this->defaultSetContext($context);
424 $this->getCounterService()->setContext($context);
425 $this->getViewedService()->setContext($context);
426
427 return $this;
428 }
429
430 private function setLastIdForReadAll(): void
431 {
432 $connection = Application::getConnection();
433 $helper = $connection->getSqlHelper();
434
435 $connection->queryExecute($helper->prepareCorrelatedUpdate(
436 'b_im_relation',
437 'R',
438 [
439 'LAST_ID' => 'C.LAST_MESSAGE_ID',
440 ],
441 ' b_im_chat C ',
442 " C.ID = R.CHAT_ID AND R.MESSAGE_TYPE NOT IN ('" . IM_MESSAGE_OPEN_LINE . "', '" . IM_MESSAGE_SYSTEM . "')
443 AND R.USER_ID = {$this->getContext()->getUserId()}"
444 ));
445 }
446
447 private function updateDateRecent(int $chatId): void
448 {
449 $userId = $this->getContext()->getUserId();
450 \Bitrix\Main\Application::getConnection()->query(
451 "UPDATE b_im_recent SET DATE_UPDATE = NOW() WHERE USER_ID = {$userId} AND ITEM_CID = {$chatId}"
452 );
453 }
454}
static unread($dialogId, $unread, $userId=null, ?int $markedId=null)
Definition recent.php:1308
getReadStatusesByMessageIds(array $messageIds)
read(MessageCollection $messages, Chat $chat)
getViewStatusesByMessageIds(array $messageIds)
readNotifications(MessageCollection $messages, array $userByChatId)
unreadNotifications(MessageCollection $messages, Relation $relation)
onAfterNotificationSend(Message $message, Relation $relation)
setLastIdForRead(int $lastId, int $chatId)
onAfterMessageSend(Message $message, RelationCollection $relations, bool $withoutCounters=false)
getCountersForUsers(Message $message, RelationCollection $relations)
markMessageUnread(Message $message, RelationCollection $relations)
deleteByMessageId(int $messageId, ?array $invalidateCacheUsers=null)
markNotificationUnread(Message $message, RelationCollection $relations)
setResult($result)
Definition Result.php:17
static getConnection($name="")