Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
CounterService.php
1<?php
2
4
5use Bitrix\Im\Model\EO_MessageUnread;
6use Bitrix\Im\Model\EO_MessageUnread_Collection;
12use Bitrix\Im\V2\Common\ContextCustomer;
23use CTimeZone;
24
26{
27 use ContextCustomer;
28
29 protected const DELAY_DELETION_COUNTERS_OF_FIRED_USER = 604800; // 1 week
30 protected const EXPIRY_INTERVAL = '-12 months';
31
32 protected const CACHE_TTL = 86400; // 1 month
33 protected const CACHE_NAME = 'counter_v5';
34 protected const CACHE_CHATS_COUNTERS_NAME = 'chats_counter_v6';
35 protected const CACHE_PATH = '/bx/im/v2/counter/';
36
37 protected const DEFAULT_COUNTERS = [
38 'TYPE' => [
39 'ALL' => 0,
40 'NOTIFY' => 0,
41 'CHAT' => 0,
42 'LINES' => 0,
43 'COPILOT' => 0,
44 ],
45 'CHAT' => [],
46 'CHAT_MUTED' => [],
47 'CHAT_UNREAD' => [],
48 'LINES' => [],
49 'COPILOT' => [],
50 ];
51
52 protected static array $staticCounterCache = [];
53 protected static array $staticChatsCounterCache = [];
54 protected static array $staticSpecificChatsCounterCache = [];
55
56 protected array $counters;
57 protected array $countersByChatIds = [];
58
59 public function __construct(?int $userId = null)
60 {
61 $this->counters = static::DEFAULT_COUNTERS;
62
63 if (isset($userId))
64 {
65 $context = new Context();
66 $context->setUser($userId);
67 $this->setContext($context);
68 }
69 }
70
71 public function getTotal(): int
72 {
73 $totalUnreadMessages = $this->getTotalCountUnreadMessages();
74 $unreadUnmutedChats = $this->getUnreadChats(false);
75
76 return $totalUnreadMessages + count($unreadUnmutedChats);
77 }
78
79 public function getByChatForEachUsers(int $chatId, ?array $userIds = null): array
80 {
81 $result = [];
82 $countForEachUsers = $this->getCountUnreadMessagesByChatIdForEachUsers($chatId, $userIds);
83
84 foreach ($countForEachUsers as $countForUser)
85 {
86 $result[(int)$countForUser['USER_ID']] = (int)$countForUser['COUNT'];
87 }
88
89 if ($userIds === null)
90 {
91 return $result;
92 }
93
94 foreach ($userIds as $userId)
95 {
96 if (!isset($result[$userId]))
97 {
98 $result[$userId] = 0;
99 }
100 }
101
102 return $result;
103 }
104
105 public function getByChat(int $chatId): int
106 {
107 return $this->getCountUnreadMessagesByChatId($chatId);
108 }
109
110 public function get(): array
111 {
112 $userId = $this->getContext()->getUserId();
113 if (isset(self::$staticCounterCache[$userId]))
114 {
115 return self::$staticCounterCache[$userId];
116 }
117
118 $cache = $this->getCacheForPreparedCounters();
119 $cachedCounters = $cache->getVars();
120 if ($cachedCounters !== false)
121 {
122 self::$staticCounterCache[$userId] = $cachedCounters;
123
124 return $cachedCounters;
125 }
126
127 $this->counters = static::DEFAULT_COUNTERS;
128 $this->countersByChatIds = [];
129
130 $this->countUnreadMessages();
131 $this->countUnreadChats();
132
133 $this->savePreparedCountersInCache($cache);
135
136 return $this->counters;
137 }
138
139 public function getForEachChat(?array $chatIds = null): array
140 {
141 $userId = $this->getContext()->getUserId();
142 if (isset(self::$staticChatsCounterCache[$userId]))
143 {
144 return self::$staticChatsCounterCache[$userId];
145 }
146
147 if ($chatIds !== null && $this->haveInSpecificChatsCache($chatIds))
148 {
149 return static::$staticSpecificChatsCounterCache[$userId] ?? [];
150 }
151
152 $cache = $this->getCacheForChatsCounters();
153 $cachedCounters = $cache->getVars();
154 if ($cachedCounters !== false)
155 {
156 self::$staticChatsCounterCache[$userId] = $cachedCounters;
157
158 return $cachedCounters;
159 }
160
161 $this->counters = static::DEFAULT_COUNTERS;
162 $this->countersByChatIds = [];
163
164 $this->countUnreadMessages($chatIds);
165
166 if ($chatIds === null)
167 {
168 $this->saveChatsCountersInCache($cache);
169 }
170 else
171 {
172 $this->saveSpecificChatsCountersInCache($chatIds);
173 }
174
176 }
177
178 public function getForNotifyChat(): int
179 {
180 $findResult = NotifyChat::find(['TO_USER_ID' => $this->getContext()->getUserId()]);
181
182 if (!$findResult->isSuccess())
183 {
184 return 0;
185 }
186
187 $chatId = (int)$findResult->getResult()['ID'];
188
189 return $this->getByChat($chatId);
190 }
191
192 public function getForNotifyChats(array $chatIds): array
193 {
194 if (empty($chatIds))
195 {
196 return [];
197 }
198
199 $counters = $this->getCountersForEachChat($chatIds, false);
200 $countersByChatId = [];
201
202 foreach ($counters as $counter)
203 {
204 $countersByChatId[$counter['CHAT_ID']] = $counter['COUNT'];
205 }
206
207 $result = [];
208
209 foreach ($chatIds as $chatId)
210 {
211 $result[$chatId] = $countersByChatId[$chatId] ?? 0;
212 }
213
214 return $result;
215 }
216
217 public function getIdFirstUnreadMessage(int $chatId): ?int
218 {
219 $result = MessageUnreadTable::query()
220 ->setSelect(['MIN'])
221 ->where('CHAT_ID', $chatId)
222 ->where('USER_ID', $this->getContext()->getUserId())
223 ->registerRuntimeField('MIN', new ExpressionField('MIN', 'MIN(%s)', ['MESSAGE_ID']))
224 ->fetch()
225 ;
226
227 return isset($result['MIN']) ? (int)$result['MIN'] : null;
228 }
229
230 public function getIdFirstUnreadMessageForEachChats(array $chatIds): array
231 {
232 if (empty($chatIds))
233 {
234 return [];
235 }
236
237 $result = MessageUnreadTable::query()
238 ->setSelect(['CHAT_ID', 'UNREAD_ID' => new ExpressionField('UNREAD_ID', 'MIN(%s)', ['MESSAGE_ID'])])
239 ->whereIn('CHAT_ID', $chatIds)
240 ->where('USER_ID', $this->getContext()->getUserId())
241 ->setGroup(['CHAT_ID'])
242 ->fetchAll() //todo index (CHAT_ID, USER_ID, MESSAGE_ID)
243 ;
244
245 $firstUnread = [];
246
247 foreach ($result as $row)
248 {
249 $firstUnread[(int)$row['CHAT_ID']] = (int)$row['UNREAD_ID'];
250 }
251
252 return $firstUnread;
253 }
254
255 public function updateIsMuted(int $chatId, string $isMuted): void
256 {
258 ['IS_MUTED' => $isMuted],
259 ['=CHAT_ID' => $chatId, '=USER_ID' => $this->getContext()->getUserId()]
260 );
261 static::clearCache($this->getContext()->getUserId());
262 }
263
264 public function deleteByChatId(int $chatId): void
265 {
266 MessageUnreadTable::deleteByFilter(['=CHAT_ID' => $chatId, '=USER_ID' => $this->getContext()->getUserId()]);
267 static::clearCache($this->getContext()->getUserId());
268 }
269
270 /*public function deleteByChatIdForAll(int $chatId): void
271 {
272 MessageUnreadTable::deleteByFilter(['=CHAT_ID' => $chatId]);
273 static::clearCache();
274 }*/
275
276 public function deleteAll(bool $withNotify = false): void
277 {
278 $filter = ['=USER_ID' => $this->getContext()->getUserId()];
279
280 if (!$withNotify)
281 {
282 $filter['!=CHAT_TYPE'] = \IM_MESSAGE_SYSTEM; // todo: add index
283 }
284
285 MessageUnreadTable::deleteByFilter($filter);
286 static::clearCache($this->getContext()->getUserId());
287 }
288
289 public function addForEachUser(Message $message, RelationCollection $relations): void
290 {
291 $insertFields = [];
292 $usersIds = [];
293
294 foreach ($relations as $relation)
295 {
296 if ($relation->getMessageType() !== \IM_MESSAGE_SYSTEM && $message->getAuthorId() === $relation->getUserId())
297 {
298 continue;
299 }
300
301 $insertFields[] = $this->prepareInsertFields($message, $relation);
302 $usersIds[] = $relation->getUserId();
303 }
304
305 MessageUnreadTable::multiplyInsertWithoutDuplicate($insertFields);
306 foreach ($usersIds as $userId)
307 {
308 static::clearCache($userId);
309 }
310 }
311
312 public function addCollection(MessageCollection $messages, Relation $relation): void
313 {
314 $insertFields = [];
315
316 foreach ($messages as $message)
317 {
318 if ($relation->getMessageType() !== \IM_MESSAGE_SYSTEM && $message->getAuthorId() === $relation->getUserId())
319 {
320 continue;
321 }
322
323 $insertFields[] = $this->prepareInsertFields($message, $relation);
324 }
325
326 MessageUnreadTable::multiplyInsertWithoutDuplicate($insertFields);
327 static::clearCache($relation->getUserId());
328 }
329
330 public function addStartingFrom(int $messageId, Relation $relation): void
331 {
332 $query = MessageTable::query()
333 ->setSelect([
334 'ID_CONST' => new ExpressionField('ID_CONST', '0'),
335 'USER_ID_CONST' => new ExpressionField('USER_ID_CONST', (string)$this->getContext()->getUserId()),
336 'CHAT_ID_CONST' => new ExpressionField('CHAT_ID', (string)$relation->getChatId()),
337 'MESSAGE_ID' => 'ID',
338 'IS_MUTED' => new ExpressionField('IS_MUTED', $relation->getNotifyBlock() ? "'Y'" : "'N'"),
339 'CHAT_TYPE' => new ExpressionField('CHAT_TYPE', "'{$relation->getMessageType()}'"),
340 'DATE_CREATE'
341 ])
342 ->where('CHAT_ID', $relation->getChatId())
343 ->where('MESSAGE_ID', '>=', $messageId)
344 ;
345 if ($relation->getMessageType() !== \IM_MESSAGE_SYSTEM)
346 {
347 $query->whereNot('AUTHOR_ID', $this->getContext()->getUserId());
348 }
349
350 MessageUnreadTable::insertSelect($query, ['ID', 'USER_ID', 'CHAT_ID', 'MESSAGE_ID', 'IS_MUTED', 'CHAT_TYPE', 'DATE_CREATE']);
351
352 static::clearCache($this->getContext()->getUserId());
353 }
354
355 public function deleteByMessageIdForAll(int $messageId, ?array $invalidateCacheUsers = null): void
356 {
357 if (empty($messageId))
358 {
359 return;
360 }
361
362 MessageUnreadTable::deleteByFilter(['=MESSAGE_ID' => $messageId]); //todo add index
363
364 if (!isset($invalidateCacheUsers))
365 {
366 static::clearCache();
367
368 return;
369 }
370
371 foreach ($invalidateCacheUsers as $user)
372 {
373 static::clearCache((int)$user);
374 }
375 }
376
377 public function deleteByMessageIdsForAll(array $messageIds, ?array $invalidateCacheUsers = null): void
378 {
379 MessageUnreadTable::deleteByFilter(['=MESSAGE_ID' => $messageIds]); //todo add index
380
381 if (!isset($invalidateCacheUsers))
382 {
383 static::clearCache();
384
385 return;
386 }
387
388 foreach ($invalidateCacheUsers as $user)
389 {
390 static::clearCache((int)$user);
391 }
392 }
393
394 public function deleteTo(Message $message): void
395 {
396 $userId = $this->getContext()->getUserId();
397 MessageUnreadTable::deleteByFilter(['<=MESSAGE_ID' => $message->getMessageId(), '=CHAT_ID' => $message->getChatId(), '=USER_ID' => $userId]);
398 static::clearCache($userId);
399 }
400
401 public static function onAfterUserUpdate(array $fields): void
402 {
403 if (!isset($fields['ACTIVE']))
404 {
405 return;
406 }
407
408 if ($fields['ACTIVE'] === 'N')
409 {
410 self::onFireUser((int)$fields['ID']);
411 }
412 else
413 {
414 self::onHireUser((int)$fields['ID']);
415 }
416 }
417
418 public static function deleteCountersOfFiredUserAgent(int $userId): string
419 {
420 $user = User::getInstance($userId);
421 if ($user->isExist() && $user->isActive())
422 {
423 return '';
424 }
425
426 $counterService = new self($userId);
427 $counterService->deleteAll(true);
428
429 return '';
430 }
431
432 public static function deleteExpiredCountersAgent(): string
433 {
434 $dateExpired = (new DateTime())->add(self::EXPIRY_INTERVAL);
435 MessageUnreadTable::deleteByFilter(['<=DATE_CREATE' => $dateExpired]);
436 static::clearCache();
437
438 return '\Bitrix\Im\V2\Message\CounterService::deleteExpiredCountersAgent();';
439 }
440
441 protected static function onFireUser(int $userId): void
442 {
443 \CAgent::AddAgent(
444 "\Bitrix\Im\V2\Message\CounterService::deleteCountersOfFiredUserAgent({$userId});",
445 'im',
446 'N',
447 self::DELAY_DELETION_COUNTERS_OF_FIRED_USER,
448 '',
449 'Y',
450 ConvertTimeStamp(time()+CTimeZone::GetOffset()+self::DELAY_DELETION_COUNTERS_OF_FIRED_USER, "FULL")
451 );
452 }
453
454 protected static function onHireUser(int $userId): void
455 {
456 \CAgent::RemoveAgent(
457 "\Bitrix\Im\V2\Message\CounterService::deleteCountersOfFiredUserAgent({$userId});",
458 'im'
459 );
460 }
461
462 public static function clearCache(?int $userId = null): void
463 {
464 $cache = \Bitrix\Main\Data\Cache::createInstance();
465 if (isset($userId))
466 {
467 unset(self::$staticCounterCache[$userId], self::$staticChatsCounterCache[$userId], self::$staticSpecificChatsCounterCache[$userId]);
468 $cache->clean(static::CACHE_NAME.'_'.$userId, self::CACHE_PATH);
469 $cache->clean(static::CACHE_NAME.'_'.$userId, CounterServiceLegacy::CACHE_PATH);
470 $cache->clean(self::CACHE_CHATS_COUNTERS_NAME.'_'.$userId, self::CACHE_PATH);
471 }
472 else
473 {
474 self::$staticCounterCache = [];
475 self::$staticChatsCounterCache = [];
476 self::$staticSpecificChatsCounterCache = [];
477 $cache->cleanDir(self::CACHE_PATH);
478 $cache->cleanDir(CounterServiceLegacy::CACHE_PATH);
479 }
480 }
481
482 protected function getCacheForPreparedCounters(): Cache
483 {
484 $userId = $this->getContext()->getUserId();
485 $cache = \Bitrix\Main\Data\Cache::createInstance();
486 $cache->initCache(static::CACHE_TTL, static::CACHE_NAME . '_' . $userId, static::CACHE_PATH);
487
488 return $cache;
489 }
490
491 protected function getCacheForChatsCounters(): Cache
492 {
493 $userId = $this->getContext()->getUserId();
494 $cache = \Bitrix\Main\Data\Cache::createInstance();
495 $cache->initCache(self::CACHE_TTL, self::CACHE_CHATS_COUNTERS_NAME . '_' . $userId, self::CACHE_PATH);
496
497 return $cache;
498 }
499
500 protected function savePreparedCountersInCache(Cache $cache): void
501 {
502 $cache->startDataCache();
503 $cache->endDataCache($this->counters);
504 self::$staticCounterCache[$this->getContext()->getUserId()] = $this->counters;
505 }
506
507 protected function saveChatsCountersInCache(Cache $cache): void
508 {
509 $cache->startDataCache();
510 $cache->endDataCache($this->countersByChatIds);
511 self::$staticChatsCounterCache[$this->getContext()->getUserId()] = $this->countersByChatIds;
512 }
513
514 protected function saveSpecificChatsCountersInCache(array $chatIds): void
515 {
516 $userId = $this->getContext()->getUserId();
517
518 foreach ($chatIds as $chatId)
519 {
520 self::$staticSpecificChatsCounterCache[$userId][$chatId] = $this->countersByChatIds[$chatId] ?? 0;
521 }
522 }
523
524 protected function countUnreadChats(): void
525 {
526 $unreadChats = $this->getUnreadChats(false);
527
528 foreach ($unreadChats as $unreadChat)
529 {
530 $this->setUnreadChat((int)$unreadChat['CHAT_ID'], $unreadChat['IS_MUTED'] === 'Y');
531 }
532 }
533
534 protected function countUnreadMessages(?array $chatIds = null): void
535 {
536 $counters = $this->getCountersForEachChat($chatIds);
537
538 foreach ($counters as $counter)
539 {
540 $chatId = (int)$counter['CHAT_ID'];
541 $count = (int)$counter['COUNT'];
542 if ($counter['IS_MUTED'] === 'Y')
543 {
544 $this->setFromMutedChat($chatId, $count);
545 }
546 else if ($counter['CHAT_TYPE'] === \IM_MESSAGE_SYSTEM)
547 {
548 $this->setFromNotify($count);
549 }
550 else if ($counter['CHAT_TYPE'] === \IM_MESSAGE_OPEN_LINE)
551 {
552 $this->setFromLine($chatId, $count);
553 }
554 else if ($counter['CHAT_TYPE'] === Chat::IM_TYPE_COPILOT)
555 {
556 $this->setFromCopilot($chatId, $count);
557 }
558 else
559 {
560 $this->setFromChat($chatId, $count);
561 }
562 $this->countersByChatIds[$chatId] = $count;
563 }
564 }
565
566 protected function setUnreadChat(int $id, bool $isMuted): void
567 {
568 if (!$isMuted && !isset($this->counters['CHAT'][$id]))
569 {
570 $this->counters['TYPE']['ALL']++;
571 $this->counters['TYPE']['CHAT']++;
572 }
573
574 $this->counters['CHAT_UNREAD'][] = $id;
575 }
576
577 protected function setFromMutedChat(int $id, int $count): void
578 {
579 $this->counters['CHAT_MUTED'][$id] = $count;
580 }
581
582 protected function setFromNotify(int $count): void
583 {
584 $this->counters['TYPE']['ALL'] += $count;
585 $this->counters['TYPE']['NOTIFY'] += $count;
586 }
587
588 protected function setFromLine(int $id, int $count): void
589 {
590 $this->counters['TYPE']['ALL'] += $count;
591 $this->counters['TYPE']['LINES'] += $count;
592 $this->counters['LINES'][$id] = $count;
593 }
594
595 protected function setFromCopilot(int $id, int $count): void
596 {
597 $this->counters['TYPE']['COPILOT'] += $count;
598 $this->counters['COPILOT'][$id] = $count;
599 }
600
601 protected function setFromChat(int $id, int $count): void
602 {
603 $this->counters['TYPE']['ALL'] += $count;
604 $this->counters['TYPE']['CHAT'] += $count;
605 $this->counters['CHAT'][$id] = $count;
606 }
607
608 protected function getUnreadChats(?bool $isMuted = null): array
609 {
610 $query = RecentTable::query()
611 ->setSelect(['CHAT_ID' => 'ITEM_CID', 'IS_MUTED' => 'RELATION.NOTIFY_BLOCK'])
612 ->where('USER_ID', $this->getContext()->getUserId())
613 ->where('UNREAD', true)
614 ;
615 if (isset($isMuted))
616 {
617 $query->where('IS_MUTED', $isMuted);
618 }
619
620 return $query->fetchAll();
621 }
622
623 protected function getCountersForEachChat(?array $chatIds = null, bool $forCurrentUser = true): array
624 {
625 $additionalCounters = $this->getAdditionalCounters($chatIds, $forCurrentUser);
627 ->setSelect(['CHAT_ID', 'IS_MUTED', 'CHAT_TYPE', 'COUNT'])
628 ->setGroup(['CHAT_ID', 'CHAT_TYPE', 'IS_MUTED'])
629 ->registerRuntimeField('COUNT', new ExpressionField('COUNT', 'COUNT(*)'))
630 ;
631 if (isset($chatIds) && !empty($chatIds))
632 {
633 $query->whereIn('CHAT_ID', $chatIds);
634 }
635 if ($forCurrentUser)
636 {
637 $query->where('USER_ID', $this->getContext()->getUserId());
638 }
639
640 return array_merge($additionalCounters, $query->fetchAll());
641 }
642
643 protected function getAdditionalCounters(?array $chatIds = null, bool $forCurrentUser = true): array
644 {
645 $result = [];
646 $nonAnsweredLines = [];
647
648 if ($forCurrentUser && empty($chatIds) && Loader::includeModule('imopenlines'))
649 {
650 $nonAnsweredLines = \Bitrix\ImOpenLines\Recent::getNonAnsweredLines($this->getContext()->getUserId());
651 }
652
653 foreach ($nonAnsweredLines as $lineId)
654 {
655 $result[] = [
656 'CHAT_ID' => $lineId,
657 'IS_MUTED' => 'N',
658 'CHAT_TYPE' => Chat::IM_TYPE_OPEN_LINE,
659 'COUNT' => 1,
660 ];
661 }
662
663 return $result;
664 }
665
666 protected function getTotalCountUnreadMessages(): int
667 {
668 return (int)MessageUnreadTable::query()
669 ->setSelect(['COUNT'])
670 ->where('USER_ID', $this->getContext()->getUserId())
671 ->where('IS_MUTED', false)
672 ->whereNot('CHAT_TYPE', Chat::IM_TYPE_COPILOT)
673 ->registerRuntimeField('COUNT', new ExpressionField('COUNT', 'COUNT(*)'))
674 ->fetch()['COUNT']
675 ;
676 }
677
678 protected function getCountUnreadMessagesByChatIdForEachUsers(int $chatId, ?array $userIds = null): array
679 {
681 ->setSelect(['USER_ID', 'COUNT'])
682 ->where('CHAT_ID', $chatId)
683 ->setGroup(['USER_ID'])
684 ->registerRuntimeField('COUNT', new ExpressionField('COUNT', 'COUNT(*)'))
685 ;
686 if (isset($userIds) && !empty($userIds))
687 {
688 $query->whereIn('USER_ID', $userIds);
689 }
690
691 return $query->fetchAll();
692 }
693
694 protected function getCountUnreadMessagesByChatId(int $chatId): int
695 {
697 ->setSelect(['COUNT'])
698 ->where('CHAT_ID', $chatId)
699 ->where('USER_ID', $this->getContext()->getUserId())
700 ->registerRuntimeField('COUNT', new ExpressionField('COUNT', 'COUNT(*)'))
701 ->fetch()['COUNT'] ?? 0
702 ;
703 }
704
705 protected function haveInSpecificChatsCache(array $chatIds): bool
706 {
707 $userId = $this->getContext()->getUserId();
708
709 foreach ($chatIds as $chatId)
710 {
711 if ($chatId > 0 && !isset(self::$staticSpecificChatsCounterCache[$userId][$chatId]))
712 {
713 return false;
714 }
715 }
716
717 return true;
718 }
719
720 private function prepareInsertFields(Message $message, Relation $relation): array
721 {
722 return [
723 'MESSAGE_ID' => $message->getMessageId(),
724 'CHAT_ID' => $relation->getChatId(),
725 'USER_ID' => $relation->getUserId(),
726 'CHAT_TYPE' => $relation->getMessageType(),
727 'IS_MUTED' => $relation->getNotifyBlock() ? 'Y' : 'N',
728 ];
729 }
730}
static updateBatch(array $fields, array $filter)
static getInstance($userId=null)
Definition user.php:44
const IM_TYPE_OPEN_LINE
Definition Chat.php:58
const IM_TYPE_COPILOT
Definition Chat.php:62
static onAfterUserUpdate(array $fields)
getIdFirstUnreadMessageForEachChats(array $chatIds)
updateIsMuted(int $chatId, string $isMuted)
setUnreadChat(int $id, bool $isMuted)
getByChatForEachUsers(int $chatId, ?array $userIds=null)
getCountUnreadMessagesByChatIdForEachUsers(int $chatId, ?array $userIds=null)
getAdditionalCounters(?array $chatIds=null, bool $forCurrentUser=true)
countUnreadMessages(?array $chatIds=null)
addCollection(MessageCollection $messages, Relation $relation)
static deleteCountersOfFiredUserAgent(int $userId)
getCountersForEachChat(?array $chatIds=null, bool $forCurrentUser=true)
static clearCache(?int $userId=null)
deleteByMessageIdsForAll(array $messageIds, ?array $invalidateCacheUsers=null)
addForEachUser(Message $message, RelationCollection $relations)
deleteByMessageIdForAll(int $messageId, ?array $invalidateCacheUsers=null)
addStartingFrom(int $messageId, Relation $relation)
endDataCache($vars=false)
Definition cache.php:407
startDataCache($TTL=false, $uniqueString=false, $initDir=false, $vars=array(), $baseDir='cache')
Definition cache.php:348