Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
notify.php
1<?php
2namespace Bitrix\Im;
3
7
8class Notify
9{
10 public const
11 EVENT_DEFAULT = 'default',
12 EVENT_SYSTEM = 'system',
13 EVENT_GROUP = 'group',
14 EVENT_PRIVATE = 'private',
15 EVENT_PRIVATE_SYSTEM = 'private_system'
16 ;
17
18 private const CONFIRM_TYPE = 1;
19 private const SIMPLE_TYPE = 3;
20 private const ALL_TYPES = 4;
21
22 private $convertText;
23 private $pageLimit;
24 private $lastType;
25 private $lastId;
26 private $chatId;
27 private $users = [];
28 private $firstPage;
29 private $searchText;
30 private $searchType;
31 private $searchDate;
32 private $totalCount;
33
34 public function __construct($options = [])
35 {
36 $this->convertText = $options['CONVERT_TEXT'] ?? null;
37 $this->searchText = $options['SEARCH_TEXT'] ?? null;
38 $this->searchType = $options['SEARCH_TYPE'] ?? null;
39 $this->searchDate = $options['SEARCH_DATE'] ?? null;
40 $this->pageLimit = $options['LIMIT'] ?? null;
41 $this->lastType = $options['LAST_TYPE'] ?? null;
42 $this->lastId = $options['LAST_ID'] ?? null;
43 $this->firstPage = !$this->lastId && !$this->lastType;
44
45 $chatData = $this->getChatData();
46 if ($chatData !== null)
47 {
48 $this->chatId = (int)$chatData['CHAT_ID'];
49 $this->totalCount = (int)$chatData['IM_MODEL_RELATION_CHAT_MESSAGE_COUNT'];
50 }
51 }
52
53 private function getChatData(): ?array
54 {
55 $userId = \Bitrix\Im\Common::getUserId();
56 if (!$userId)
57 {
58 return null;
59 }
60
61 $chatData = \Bitrix\Im\Model\RelationTable::getList([
62 'select' => ['CHAT_ID', 'CHAT.MESSAGE_COUNT'],
63 'filter' => [
64 '=USER_ID' => $userId,
65 '=MESSAGE_TYPE' => 'S'
66 ]
67 ])->fetch();
68 if (!$chatData)
69 {
70 return null;
71 }
72
73 return $chatData;
74 }
75
76 public static function getRealCounter($chatId): int
77 {
78 return self::getCounters($chatId, true)[$chatId];
79 }
80
81 public static function getRealCounters($chatId)
82 {
83 return self::getCounters($chatId, true);
84 }
85
86 public static function getCounter($chatId): int
87 {
88 return self::getCounters($chatId)[$chatId];
89 }
90
91 public static function getCounters($chatId, $isReal = false)
92 {
93 $result = Array();
94 $chatList = Array();
95 if (is_array($chatId))
96 {
97 foreach($chatId as $id)
98 {
99 $id = intval($id);
100 if ($id)
101 {
102 $result[$id] = 0;
103 $chatList[$id] = $id;
104 }
105 }
106 $chatList = array_values($chatList);
107 $isMulti = count($chatList) > 1;
108 }
109 else
110 {
111 $id = intval($chatId);
112 if ($id)
113 {
114 $result[$id] = 0;
115 $chatList[] = $id;
116 }
117 $isMulti = false;
118 }
119
120 if (!$chatList)
121 {
122 return false;
123 }
124
125 /*if ($isReal)
126 {
127 $query = "
128 SELECT CHAT_ID, COUNT(1) COUNTER
129 FROM b_im_message
130 WHERE CHAT_ID ".($isMulti? ' IN ('.implode(',', $chatList).')': ' = '.$chatList[0])."
131 AND NOTIFY_READ = 'N'
132 GROUP BY CHAT_ID
133 ";
134 }
135 else
136 {
137 $query = "
138 SELECT CHAT_ID, COUNTER
139 FROM b_im_relation
140 WHERE CHAT_ID ".($isMulti? ' IN ('.implode(',', $chatList).')': ' = '.$chatList[0])."
141 ";
142 }*/
143
144 /*$orm = \Bitrix\Main\Application::getInstance()->getConnection()->query($query);
145 while($row = $orm->fetch())
146 {
147 $result[$row['CHAT_ID']] = (int)$row['COUNTER'];
148 }*/
149
150 if ($isMulti)
151 {
152 $result = (new CounterService(Common::getUserId()))->getForNotifyChats($chatList);
153 }
154 else
155 {
156 $counter = (new CounterService(Common::getUserId()))->getByChat($chatList[0]);
157 $result[$chatList[0]] = $counter;
158 }
159
160 return $result;
161 }
162
163 public function get()
164 {
165 if (!$this->chatId || !$this->totalCount)
166 {
167 return [
168 'notifications' => [],
169 'users' => [],
170 ];
171 }
172 // fetching confirm notifications
173 $confirmCollection = $this->fetchConfirms();
174
175 // fetching simple notifications
176 $offset = count($confirmCollection);
177 $simpleCollection = $this->fetchSimple($offset);
178 $notifications = array_merge($confirmCollection, $simpleCollection);
179
180 /*$unreadCount = \Bitrix\Im\Model\MessageTable::getList(
181 [
182 'select' => ['CNT'],
183 'filter' => [
184 '=CHAT_ID' => $this->chatId,
185 '=NOTIFY_READ' => 'N'
186 ],
187 'runtime' => [
188 new \Bitrix\Main\ORM\Fields\ExpressionField('CNT', 'COUNT(*)')
189 ]
190 ]
191 )->fetch();*/
192
193 $unreadCount = (new CounterService(\Bitrix\Im\Common::getUserId()))->getByChat($this->chatId);
194
195 $result = [
196 'TOTAL_COUNT' => $this->totalCount,
197 'TOTAL_UNREAD_COUNT' => (int)$unreadCount,
198 'CHAT_ID' => $this->chatId,
199 'NOTIFICATIONS' => $notifications,
200 'USERS' => $this->users,
201 ];
202
203 foreach ($result['NOTIFICATIONS'] as $key => $value)
204 {
205 if ($value['DATE'] instanceof DateTime)
206 {
207 $result['NOTIFICATIONS'][$key]['DATE'] = date('c', $value['DATE']->getTimestamp());
208 }
209
210 $result['NOTIFICATIONS'][$key] = array_change_key_case($result['NOTIFICATIONS'][$key], CASE_LOWER);
211 }
212 $result['NOTIFICATIONS'] = array_values($result['NOTIFICATIONS']);
213 $result['USERS'] = array_values($result['USERS']);
214 $result = array_change_key_case($result, CASE_LOWER);
215
216 return $result;
217 }
218
219 private function requestData(int $requestType, int $limit): array
220 {
221 $collection = [];
222 $ormParams = $this->prepareGettingIdParams($requestType, $limit);
223 $ids = \Bitrix\Im\Model\MessageTable::getList($ormParams)->fetchAll();
224 if (count($ids) === 0)
225 {
226 return $collection;
227 }
228
229 $ids = array_map(static function($item) {
230 return (int)$item['ID'];
231 }, $ids);
232
233 $ormParams = $this->prepareFilteringByIdParams($ids);
234 $ormResult = \Bitrix\Im\Model\MessageTable::getList($ormParams);
235
236 foreach ($ormResult as $notifyItem)
237 {
238 if ($notifyItem['NOTIFY_EVENT'] === self::EVENT_PRIVATE_SYSTEM)
239 {
240 $notifyItem['AUTHOR_ID'] = 0;
241 }
242
243 $collection[$notifyItem['ID']] = [
244 'ID' => (int)$notifyItem['ID'],
245 'CHAT_ID' => $this->chatId,
246 'AUTHOR_ID' => (int)$notifyItem['AUTHOR_ID'],
247 'DATE' => $notifyItem['DATE_CREATE'],
248 'NOTIFY_TYPE' => (int)$notifyItem['NOTIFY_TYPE'],
249 'NOTIFY_MODULE' => $notifyItem['NOTIFY_MODULE'],
250 'NOTIFY_EVENT' => $notifyItem['NOTIFY_EVENT'],
251 'NOTIFY_TAG' => $notifyItem['NOTIFY_TAG'],
252 'NOTIFY_SUB_TAG' => $notifyItem['NOTIFY_SUB_TAG'],
253 'NOTIFY_TITLE' => $notifyItem['NOTIFY_TITLE'],
254 //'NOTIFY_READ' => $notifyItem['NOTIFY_READ'],
255 'SETTING_NAME' => $notifyItem['NOTIFY_MODULE'].'|'.$notifyItem['NOTIFY_EVENT'],
256 ];
257 $collection[$notifyItem['ID']]['TEXT'] = \Bitrix\Im\Text::parse(
258 \Bitrix\Im\Text::convertHtmlToBbCode($notifyItem['MESSAGE']),
259 ['LINK_TARGET_SELF' => 'Y']
260 );
261 if ($notifyItem['AUTHOR_ID'] && !isset($this->users[$notifyItem['AUTHOR_ID']]))
262 {
263 $user = User::getInstance($notifyItem['AUTHOR_ID'])->getArray([
264 'JSON' => 'Y',
265 'SKIP_ONLINE' => 'Y'
266 ]);
267 $user['last_activity_date'] =
268 $notifyItem['USER_LAST_ACTIVITY_DATE']
269 ? date('c', $notifyItem['USER_LAST_ACTIVITY_DATE']->getTimestamp())
270 : false
271 ;
272 $user['desktop_last_date'] = false;
273 $user['mobile_last_date'] = false;
274 $user['idle'] = false;
275
276 $this->users[$notifyItem['AUTHOR_ID']] = $user;
277 }
278
279 //keyboard creation
280 if ($notifyItem['NOTIFY_BUTTONS'])
281 {
282 $buttons = unserialize($notifyItem['NOTIFY_BUTTONS'], ['allowed_classes' => false]);
283
284 $keyboard = new \Bitrix\Im\Bot\Keyboard(111);
285 $command = 'notifyConfirm';
286 foreach ($buttons as $button)
287 {
288 $keyboard->addButton(
289 [
290 'TEXT' => $button['TITLE'],
291 'COMMAND' => $command,
292 'COMMAND_PARAMS' => $notifyItem['ID'].'|'.$button['VALUE'],
293 'TEXT_COLOR' => '#fff',
294 'BG_COLOR' => $button['TYPE'] === 'accept' ? '#8BC84B' : '#ef4b57',
295 'DISPLAY' => 'LINE'
296 ]
297 );
298 }
299 $collection[$notifyItem['ID']]['NOTIFY_BUTTONS'] = $keyboard->getJson();
300 }
301 }
302
303 if (count($collection) > 0)
304 {
305 $params = \CIMMessageParam::Get(array_keys($collection));
306 foreach ($params as $notificationId => $param)
307 {
308 $collection[$notificationId]['PARAMS'] = empty($param) ? null : $param;
309 }
310
311 $collection = $this->fillReadStatuses($collection);
312 }
313
314 return $collection;
315 }
316
317 private function fetchConfirms(): array
318 {
319 $confirmCollection = [];
320
321 $nextPageIsConfirm = $this->lastType === self::CONFIRM_TYPE;
322 if ($this->firstPage || $nextPageIsConfirm)
323 {
324 $confirmCollection = $this->requestData(self::CONFIRM_TYPE, $this->pageLimit);
325 }
326
327 return $confirmCollection;
328 }
329
330 private function fetchSimple(int $offset): array
331 {
332 $simpleCollection = [];
333 $nextPageIsSimple = $this->lastType === self::SIMPLE_TYPE;
334 $needMoreOnFirstPage = $this->firstPage && $offset < $this->pageLimit;
335 $notEnoughFromPreviousStep = $this->lastType === self::CONFIRM_TYPE && $offset < $this->pageLimit;
336
337 if ($needMoreOnFirstPage || $notEnoughFromPreviousStep || $nextPageIsSimple)
338 {
339 $simpleCollection = $this->requestData(self::SIMPLE_TYPE, $this->pageLimit - $offset);
340 }
341
342 return $simpleCollection;
343 }
344
345 public function search(): array
346 {
347 if (!$this->chatId)
348 {
349 return [];
350 }
351
352 if (!$this->searchText && !$this->searchType && !$this->searchDate)
353 {
354 return [];
355 }
356
357 if ($this->lastId > 0)
358 {
359 $this->lastType = self::ALL_TYPES;
360 $this->firstPage = false;
361 }
362
363 // fetching searched notifications
364 $collection = $this->requestData(self::ALL_TYPES, $this->pageLimit);
365
366 $result = [
367 'CHAT_ID' => $this->chatId,
368 'NOTIFICATIONS' => $collection,
369 'USERS' => $this->users,
370 ];
371
372 if (!$this->lastId)
373 {
374 $result['TOTAL_RESULTS'] = $this->requestSearchTotalCount();
375 }
376
377 foreach ($result['NOTIFICATIONS'] as $key => $value)
378 {
379 if ($value['DATE'] instanceof DateTime)
380 {
381 $result['NOTIFICATIONS'][$key]['DATE'] = date('c', $value['DATE']->getTimestamp());
382 }
383
384 $result['NOTIFICATIONS'][$key] = array_change_key_case($result['NOTIFICATIONS'][$key], CASE_LOWER);
385 }
386 $result['NOTIFICATIONS'] = array_values($result['NOTIFICATIONS']);
387 $result['USERS'] = array_values($result['USERS']);
388 $result = array_change_key_case($result, CASE_LOWER);
389
390 return $result;
391 }
392
398 public static function cleanNotifyAgent(): string
399 {
400 $dayCount = 60;
401 $limit = 2000;
402 $step = 1000;
403
404 $batches = [];
405 $result = \Bitrix\Im\Model\MessageTable::getList([
406 'select' => ['ID'],
407 'filter' => [
408 '=NOTIFY_TYPE' => [IM_NOTIFY_CONFIRM, IM_NOTIFY_FROM, IM_NOTIFY_SYSTEM],
409 '<DATE_CREATE' => ConvertTimeStamp((time() - 86400 * $dayCount), 'FULL')
410 ],
411 'limit' => $limit
412 ]);
413
414 $batch = [];
415 $i = 0;
416
417 while ($row = $result->fetch())
418 {
419 if ($i++ === $step)
420 {
421 $i = 0;
422 $batches[] = $batch;
423 $batch = [];
424 }
425
426 $batch[] = (int)$row['ID'];
427 }
428 if (!empty($batch))
429 {
430 $batches[] = $batch;
431 }
432
433 $counterService = new CounterService();
434 foreach ($batches as $batch)
435 {
436 \Bitrix\Im\Model\MessageTable::deleteBatch([
437 '=ID' => $batch
438 ]);
439 \Bitrix\Im\Model\MessageParamTable::deleteBatch([
440 '=MESSAGE_ID' => $batch
441 ]);
442 $counterService->deleteByMessageIdsForAll($batch);
443 }
444
445 return __METHOD__. '();';
446 }
447
448 private function requestSearchTotalCount(): int
449 {
450 $filter = [
451 '=CHAT_ID' => $this->chatId,
452 ];
453
454 if ($this->searchText)
455 {
456 $filter['*%MESSAGE'] = $this->searchText;
457 }
458 if ($this->searchType)
459 {
460 $options = explode('|', $this->searchType);
461 $filter['=NOTIFY_MODULE'] = $options[0];
462 if (isset($options[1]))
463 {
464 $filter['=NOTIFY_EVENT'] = $options[1];
465 }
466 }
467 if ($this->searchDate)
468 {
469 $dateStart = new DateTime(
470 $this->searchDate,
471 \DateTimeInterface::RFC3339,
472 new \DateTimeZone('UTC')
473 );
474 $dateEnd = (
475 new DateTime(
476 $this->searchDate,
477 \DateTimeInterface::RFC3339,
478 new \DateTimeZone('UTC')
479 )
480 )->add('1 DAY');
481
482 $filter['><DATE_CREATE'] = [$dateStart, $dateEnd];
483 }
484
485 return \Bitrix\Im\Model\MessageTable::getCount($filter);
486 }
487
497 private function prepareGettingIdParams(int $requestType, int $limit): array
498 {
499 $ormParams = [
500 'select' => ['ID'],
501 'filter' => ['=CHAT_ID' => $this->chatId],
502 'order' => ['DATE_CREATE' => 'DESC', 'ID' => 'DESC'],
503 'limit' => $limit
504 ];
505
506 if ($requestType === self::CONFIRM_TYPE)
507 {
508 $ormParams['filter']['=NOTIFY_TYPE'] = IM_NOTIFY_CONFIRM;
509 }
510 elseif ($requestType === self::SIMPLE_TYPE)
511 {
512 $ormParams['filter']['!=NOTIFY_TYPE'] = IM_NOTIFY_CONFIRM;
513 }
514 elseif ($requestType === self::ALL_TYPES)
515 {
516 if ($this->searchText)
517 {
518 $ormParams['filter']['*%MESSAGE'] = $this->searchText;
519 }
520 if ($this->searchType)
521 {
522 $options = explode('|', $this->searchType);
523 $ormParams['filter']['=NOTIFY_MODULE'] = $options[0];
524 if (isset($options[1]))
525 {
526 $ormParams['filter']['=NOTIFY_EVENT'] = $options[1];
527 }
528 }
529 if ($this->searchDate)
530 {
531 $dateStart = new DateTime(
532 $this->searchDate,
533 \DateTimeInterface::RFC3339,
534 new \DateTimeZone('UTC')
535 );
536 $dateEnd = (
537 new DateTime(
538 $this->searchDate,
539 \DateTimeInterface::RFC3339,
540 new \DateTimeZone('UTC')
541 )
542 )->add('1 DAY');
543 $ormParams['filter']['><DATE_CREATE'] = [$dateStart, $dateEnd];
544 }
545 }
546
547 if (!$this->firstPage)
548 {
549 if (
550 $requestType === self::CONFIRM_TYPE
551 || ($requestType === self::SIMPLE_TYPE && $this->lastType === self::SIMPLE_TYPE)
552 || ($requestType === self::ALL_TYPES && $this->lastType === self::ALL_TYPES)
553 )
554 {
555 $ormParams['filter']['<ID'] = $this->lastId;
556 }
557 }
558
559 return $ormParams;
560 }
561
569 private function prepareFilteringByIdParams(array $ids): array
570 {
571 return [
572 'select' => [
573 'ID',
574 'AUTHOR_ID',
575 'MESSAGE',
576 'DATE_CREATE',
577 'NOTIFY_TYPE',
578 'NOTIFY_EVENT',
579 'NOTIFY_MODULE',
580 'NOTIFY_TAG',
581 'NOTIFY_SUB_TAG',
582 'NOTIFY_TITLE',
583 //'NOTIFY_READ',
584 'NOTIFY_BUTTONS',
585 'USER_LAST_ACTIVITY_DATE' => 'AUTHOR.LAST_ACTIVITY_DATE',
586 //'USER_IDLE' => 'STATUS.IDLE',
587 //'USER_MOBILE_LAST_DATE' => 'STATUS.MOBILE_LAST_DATE',
588 //'USER_DESKTOP_LAST_DATE' => 'STATUS.DESKTOP_LAST_DATE',
589 ],
590 'filter' => ['=ID' => $ids],
591 'order' => ['DATE_CREATE' => 'DESC', 'ID' => 'DESC'],
592 ];
593 }
594
595 public function getLastId(): ?int
596 {
597 if (!$this->chatId)
598 {
599 return null;
600 }
601
602 $ormParams = [
603 'select' => ['ID'],
604 'filter' => ['=CHAT_ID' => $this->chatId],
605 'order' => ['DATE_CREATE' => 'DESC', 'ID' => 'DESC'],
606 'limit' => 1,
607 ];
608
609 $getListResult = \Bitrix\Im\Model\MessageTable::getList($ormParams)->fetch();
610 if (!$getListResult)
611 {
612 return null;
613 }
614
615 if (count($getListResult) === 1)
616 {
617 return (int)$getListResult['ID'];
618 }
619
620 return null;
621 }
622
623 private function fillReadStatuses(array $notifications): array
624 {
625 $messageIds = array_keys($notifications);
626
627 $readStatuses = (new ReadService(\Bitrix\Im\Common::getUserId()))->getReadStatusesByMessageIds($messageIds);
628
629 foreach ($notifications as $id => $notification)
630 {
631 $notifications[$id]['NOTIFY_READ'] = $readStatuses[$id] ? 'Y' : 'N';
632 }
633
634 return $notifications;
635 }
636}
static getUserId($userId=null)
Definition common.php:74
static getRealCounters($chatId)
Definition notify.php:81
const EVENT_PRIVATE_SYSTEM
Definition notify.php:15
const EVENT_DEFAULT
Definition notify.php:11
const EVENT_PRIVATE
Definition notify.php:14
static cleanNotifyAgent()
Definition notify.php:398
const EVENT_GROUP
Definition notify.php:13
static getCounters($chatId, $isReal=false)
Definition notify.php:91
__construct($options=[])
Definition notify.php:34
static getCounter($chatId)
Definition notify.php:86
static getRealCounter($chatId)
Definition notify.php:76
const EVENT_SYSTEM
Definition notify.php:12
static convertHtmlToBbCode($html)
Definition text.php:389
static getInstance($userId=null)
Definition user.php:44