5use Bitrix\Im\Model\MessageParamTable;
6use Bitrix\Im\Model\MessageUnreadTable;
7use Bitrix\Im\Model\RecentTable;
8use Bitrix\Im\V2\Chat\Background\Background;
9use Bitrix\Im\V2\Application\Features;
10use Bitrix\Im\V2\Chat\Copilot\CopilotPopupItem;
11use Bitrix\Im\V2\Chat\EntityLink;
12use Bitrix\Im\V2\Chat\Param\Params;
13use Bitrix\Im\V2\Chat\MessagesAutoDelete\MessagesAutoDeleteConfigs;
14use Bitrix\Im\V2\Chat\TextField\TextFieldEnabled;
15use Bitrix\Im\V2\Integration\Socialnetwork\Collab\Collab;
16use Bitrix\Im\V2\Message\Counter\CounterType;
17use Bitrix\Im\V2\MessageCollection;
18use Bitrix\Im\V2\Entity\User\NullUser;
19use Bitrix\Im\V2\Permission;
20use Bitrix\Im\V2\Integration\AI\RoleManager;
21use Bitrix\Im\V2\Integration\Socialnetwork\Group;
22use Bitrix\Im\V2\Message;
23use Bitrix\Im\V2\Message\CounterService;
24use Bitrix\Im\V2\Entity\File\FileCollection;
25use Bitrix\Im\V2\Entity\File\FileItem;
26use Bitrix\Im\V2\Message\Param;
27use Bitrix\Im\V2\Message\MessagePopupItem;
28use Bitrix\Im\V2\Message\ReadService;
29use Bitrix\Im\V2\Message\Send\PushService;
30use Bitrix\Im\V2\Recent\Config\RecentConfigManager;
31use Bitrix\Im\V2\RelationCollection;
32use Bitrix\Im\V2\Rest\RestAdapter;
33use Bitrix\Im\V2\Settings\UserConfiguration;
35use Bitrix\Imbot\Bot\CopilotChatBot;
36use Bitrix\Main\Application, Bitrix\Main\Localization\Loc;
37use Bitrix\Main\Config\Option;
38use Bitrix\Main\DB\SqlExpression;
39use Bitrix\Main\Engine\Response\Converter;
40use Bitrix\Main\Loader;
41use Bitrix\Main\ORM\Fields\ExpressionField;
42use Bitrix\Main\Type\DateTime;
45Loc::loadMessages(__FILE__);
49 private static array $unreadElementCache = [];
50 private const PINNED_CHATS_LIMIT = 45;
52 static private bool $limitError =
false;
56 $onlyOpenlinesOption =
$options[
'ONLY_OPENLINES'] ??
null;
57 $onlyCopilotOption =
$options[
'ONLY_COPILOT'] ??
null;
58 $skipOpenlinesOption =
$options[
'SKIP_OPENLINES'] ??
null;
59 $skipChat =
$options[
'SKIP_CHAT'] ??
null;
60 $skipDialog =
$options[
'SKIP_DIALOG'] ??
null;
61 $byChatIds = isset(
$options[
'CHAT_IDS']);
63 if (isset(
$options[
'FORCE_OPENLINES']) &&
$options[
'FORCE_OPENLINES'] ===
'Y')
65 $forceOpenlines =
'Y';
69 $forceOpenlines =
'N';
80 && ($onlyOpenlinesOption ===
'Y' || $skipOpenlinesOption !==
'Y')
85 && $forceOpenlines !==
'Y'
86 && class_exists(
'\Bitrix\ImOpenLines\Recent')
92 $generalChatId = \CIMChat::GetGeneralChatId();
94 $ormParams = self::getOrmParams([
96 'SHOW_OPENLINES' => $showOpenlines,
97 'WITHOUT_COMMON_USERS' =>
true,
98 'CHAT_IDS' =>
$options[
'CHAT_IDS'] ??
null,
101 $lastSyncDateOption =
$options[
'LAST_SYNC_DATE'] ??
null;
102 if ($lastSyncDateOption)
104 $maxLimit = (new \Bitrix\Main\Type\DateTime())->add(
'-7 days');
105 if ($maxLimit >
$options[
'LAST_SYNC_DATE'])
107 $options[
'LAST_SYNC_DATE'] = $maxLimit;
109 $ormParams[
'filter'][
'>=DATE_UPDATE'] =
$options[
'LAST_SYNC_DATE'];
111 else if (
$options[
'ONLY_OPENLINES'] !==
'Y' && !$byChatIds)
113 $ormParams[
'filter'][
'>=DATE_UPDATE'] = (new \Bitrix\Main\Type\DateTime())->add(
'-30 days');
117 if ($onlyCopilotOption ===
'Y')
119 $ormParams[
'filter'][] = [
120 '=ITEM_TYPE' => \Bitrix\Im\V2\Chat::IM_TYPE_COPILOT
123 elseif ($onlyOpenlinesOption ===
'Y')
125 $ormParams[
'filter'][] = [
131 if (
$options[
'SKIP_OPENLINES'] ===
'Y')
135 if ($skipChat ===
'Y')
140 if ($skipDialog ===
'Y')
144 if (!empty($skipTypes))
146 $ormParams[
'filter'][] = [
147 '!@ITEM_TYPE' => $skipTypes
152 if (!isset(
$options[
'LAST_SYNC_DATE']))
156 $ormParams[
'offset'] =
$options[
'OFFSET'];
160 $ormParams[
'limit'] =
$options[
'LIMIT'];
164 $ormParams[
'order'] =
$options[
'ORDER'];
169 $orm = \Bitrix\Im\Model\RecentTable::getList($ormParams);
170 $rows = $orm->fetchAll();
172 foreach (
$rows as $row)
175 $id = $isUser? (int)$row[
'ITEM_ID']:
'chat'.$row[
'ITEM_ID'];
179 if (isset(
$result[$id]) && !$row[
'ITEM_MID'])
189 $item = self::formatRow($row, [
190 'GENERAL_CHAT_ID' => $generalChatId,
191 'GET_ORIGINAL_TEXT' =>
$options[
'GET_ORIGINAL_TEXT'] ??
null,
205 && class_exists(
'\Bitrix\ImOpenLines\Recent')
209 $chatsInQueue = \Bitrix\ImOpenLines\Recent::getRecent(
$userId,
$options);
215 [
'PINNED' => SORT_DESC,
'MESSAGE' => SORT_DESC,
'ID' => SORT_DESC],
217 'ID' =>
function($row) {
220 'MESSAGE' =>
function($row) {
221 return $row[
'DATE'] instanceof \Bitrix\Main\Type\DateTime ? $row[
'DATE']->getTimeStamp() : 0;
228 foreach (
$result as $index => $item)
230 $result[$index] = self::jsonRow($item);
245 $generalChatId = \CIMChat::GetGeneralChatId();
247 $viewCommonUsers = Option::get(
'im',
'view_common_users',
'Y') ===
'N'
252 $onlyOpenlinesOption =
$options[
'ONLY_OPENLINES'] ??
null;
253 $onlyCopilotOption =
$options[
'ONLY_COPILOT'] ??
null;
254 $onlyChannelOption =
$options[
'ONLY_CHANNEL'] ??
null;
255 $canManageMessagesOption =
$options[
'CAN_MANAGE_MESSAGES'] ??
null;
256 $skipChatOption =
$options[
'SKIP_CHAT'] ??
null;
257 $skipDialogOption =
$options[
'SKIP_DIALOG'] ??
null;
258 $skipCollabOption = Collab::isAvailable() ? (
$options[
'SKIP_COLLAB'] ??
null) :
'Y';
259 $lastMessageDateOption =
$options[
'LAST_MESSAGE_DATE'] ??
null;
260 $withoutCommonUsers = !$viewCommonUsers || $onlyOpenlinesOption ===
'Y';
261 $unreadOnly = isset(
$options[
'UNREAD_ONLY']) &&
$options[
'UNREAD_ONLY'] ===
'Y';
262 $shortInfo = isset(
$options[
'SHORT_INFO']) &&
$options[
'SHORT_INFO'] ===
'Y';
263 $parseText =
$options[
'PARSE_TEXT'] ??
null;
268 $onlyOpenlinesOption ===
'Y'
269 ||
$options[
'SKIP_OPENLINES'] !==
'Y'
273 $ormParams = self::getOrmParams([
275 'SHOW_OPENLINES' => $showOpenlines,
276 'WITHOUT_COMMON_USERS' => $withoutCommonUsers,
277 'UNREAD_ONLY' => $unreadOnly,
278 'SHORT_INFO' => $shortInfo,
281 if ($onlyCopilotOption ===
'Y')
283 $ormParams[
'filter'][] = [
284 '=ITEM_TYPE' => \Bitrix\Im\V2\Chat::IM_TYPE_COPILOT
287 elseif ($onlyOpenlinesOption ===
'Y')
289 $ormParams[
'filter'][] = [
293 elseif ($onlyChannelOption ===
'Y')
295 $ormParams[
'filter'][] = [
296 '=ITEM_TYPE' => [\Bitrix\Im\V2\Chat::IM_TYPE_OPEN_CHANNEL, \Bitrix\Im\V2\Chat::IM_TYPE_CHANNEL],
302 if (
$options[
'SKIP_OPENLINES'] ===
'Y')
306 if ($skipChatOption ===
'Y')
311 if ($skipDialogOption ===
'Y')
315 if ($skipCollabOption ===
'Y')
317 $skipTypes[] = \Bitrix\Im\V2\Chat::IM_TYPE_COLLAB;
319 if (!RecentConfigManager::EXTERNAL_CHAT_USE_DEFAULT_RECENT_SECTION)
321 $skipTypes[] = \Bitrix\Im\V2\Chat::IM_TYPE_EXTERNAL;
323 if (!empty($skipTypes))
325 $ormParams[
'filter'][] = [
326 '!@ITEM_TYPE' => $skipTypes
333 $ormParams[
'filter'][
'<=DATE_LAST_ACTIVITY'] = $lastMessageDateOption;
337 $ormParams[
'offset'] =
$options[
'OFFSET'];
342 $ormParams[
'limit'] = (int)
$options[
'LIMIT'];
346 $ormParams[
'limit'] = 50;
350 if ($sortOption ===
'byCost')
352 $ormParams[
'order'] = [
355 'DATE_LAST_ACTIVITY' =>
'DESC',
360 $ormParams[
'order'] = [
362 'DATE_LAST_ACTIVITY' =>
'DESC',
366 if ($canManageMessagesOption ===
'Y')
371 $orm = \Bitrix\Im\Model\RecentTable::getList($ormParams);
375 $messageIdsWithCopilotRole = [];
378 $messagesAutoDeleteConfigs = [];
380 $rows = $orm->fetchAll();
382 foreach (
$rows as $row)
386 $id = $isUser? (int)$row[
'ITEM_ID']:
'chat'.$row[
'ITEM_ID'];
390 if (isset(
$result[$id]) && !$row[
'ITEM_MID'])
400 $item = self::formatRow($row, [
401 'GENERAL_CHAT_ID' => $generalChatId,
402 'WITHOUT_COMMON_USERS' => $withoutCommonUsers,
403 'GET_ORIGINAL_TEXT' =>
$options[
'GET_ORIGINAL_TEXT'] ??
null,
404 'SHORT_INFO' => $shortInfo,
405 'PARSE_TEXT' => $parseText,
412 if ($row[
'ITEM_TYPE'] === \
Bitrix\
Im\
V2\Chat::IM_TYPE_COPILOT)
414 $copilotChatRole = (
new RoleManager())->getMainRole((
int)$item[
'CHAT_ID']);
415 if (isset($copilotChatRole))
417 $copilotData[
'chats'][$item[
'ID']] = $copilotChatRole;
423 $chatsIds[] = (int)$item[
'CHAT_ID'];
428 && (isset($item[
'USER'][
'BOT']) && $item[
'USER'][
'BOT'] ===
true)
429 && Loader::includeModule(
'imbot')
430 && (
int)$item[
'MESSAGE'][
'AUTHOR_ID'] === CopilotChatBot::getBotId()
433 $messageIdsWithCopilotRole[] = (int)$item[
'MESSAGE'][
'ID'];
438 $result[$id] = self::jsonRow($item);
446 if (!$shortInfo && !empty($messageIdsWithCopilotRole))
448 $copilotMessageRoles = self::fillCopilotMessageRoles($messageIdsWithCopilotRole);
452 if (in_array((
int)$item[
'MESSAGE'][
'ID'], $messageIdsWithCopilotRole,
true))
454 $copilotData[
'messages'][(int)$item[
'MESSAGE'][
'ID']] =
455 $copilotMessageRoles[(
int)$item[
'MESSAGE'][
'ID']] ?? RoleManager::getDefaultRoleCode()
461 $copilotData = self::prepareCopilotData($copilotData,
$userId, $shortInfo);
463 if ($showOpenlines && !$onlyCopilotOption && Loader::includeModule(
'imopenlines'))
465 if (!isset(
$options[
'SKIP_UNDISTRIBUTED_OPENLINES']) ||
$options[
'SKIP_UNDISTRIBUTED_OPENLINES'] !==
'Y')
467 $recentOpenLines = \Bitrix\ImOpenLines\Recent::getRecent(
$userId, [
'ONLY_IN_QUEUE' =>
true]);
469 if (is_array($recentOpenLines))
487 foreach (
$result as $index => $item)
489 $result[$index] = self::jsonRow($item);
495 'hasMorePages' => $ormParams[
'limit'] ==
$counter,
496 'hasMore' => $ormParams[
'limit'] ==
$counter,
497 'copilot' => !empty($copilotData) ? $copilotData :
null,
498 'messagesAutoDeleteConfigs' => $messagesAutoDeleteConfigs,
501 if (!isset(
$options[
'LAST_MESSAGE_DATE']))
506 return $objectToReturn;
509 $converter =
new Converter(Converter::TO_SNAKE | Converter::TO_UPPER | Converter::KEYS);
513 'HAS_MORE_PAGES' => $ormParams[
'limit'] ==
$counter,
514 'HAS_MORE' => $ormParams[
'limit'] ==
$counter,
515 'COPILOT' => !empty($copilotData) ? $converter->process($copilotData) :
null,
516 'MESSAGES_AUTO_DELETE_CONFIGS' => $converter->process($messagesAutoDeleteConfigs) ?? [],
520 private static function fillCopilotMessageRoles(
array $messageIdsWithCopilotRole):
array
522 $copilotMessageRoles = [];
525 ->setSelect([
'MESSAGE_ID',
'PARAM_VALUE'])
526 ->whereIn(
'MESSAGE_ID', $messageIdsWithCopilotRole)
531 foreach ($collection as $item)
533 $copilotMessageRoles[(int)$item->getMessageId()] = $item->getParamValue();
536 return $copilotMessageRoles;
539 private static function prepareCopilotData(
array $copilotData,
int $userId,
bool $shortInfo):
array
541 $roleManager = (
new RoleManager())->setContextUser(
$userId);
542 $recentCopilotRoles = !$shortInfo ? $roleManager->getRecentKeyRoles() : [];
543 $copilotRoles = array_values(array_merge(
544 $copilotData[
'chats'] ?? [],
545 $copilotData[
'messages'] ?? [],
549 $chats = CopilotPopupItem::convertArrayDataForChats($copilotData[
'chats'] ?? []);
550 $messages = CopilotPopupItem::convertArrayDataForMessages($copilotData[
'messages'] ?? []);
553 ? $roleManager->getRolesShort($copilotRoles)
554 : $roleManager->getRoles($copilotRoles)
557 'chats' => !empty($chats) ? $chats :
null,
559 'roles' => !empty($roles) ? $roles :
null,
560 'recommendedRoles' => !empty($recentCopilotRoles) ? $recentCopilotRoles :
null,
572 $generalChatId = \CIMChat::GetGeneralChatId();
574 $ormParams = self::getOrmParams([
577 'WITHOUT_COMMON_USERS' =>
true,
580 $ormParams[
'filter'][
'=ITEM_TYPE'] = $itemType;
581 $ormParams[
'filter'][
'=ITEM_ID'] = $itemId;
583 $orm = \Bitrix\Im\Model\RecentTable::getList([
584 'select' => $ormParams[
'select'],
585 'filter' => $ormParams[
'filter'],
586 'runtime' => $ormParams[
'runtime'],
590 $rows = $orm->fetchAll();
592 foreach (
$rows as $row)
597 if (
$result && !$row[
'ITEM_MID'])
607 $item = self::formatRow($row, [
608 'GENERAL_CHAT_ID' => $generalChatId,
627 private static function getOrmParams(
$params)
632 $isIntranet = $isIntranetInstalled && \Bitrix\Intranet\Util::isIntranetUser(
$userId);
633 $withoutCommonUsers =
$params[
'WITHOUT_COMMON_USERS'] ===
true || !$isIntranet;
634 $unreadOnly = isset(
$params[
'UNREAD_ONLY']) &&
$params[
'UNREAD_ONLY'] ===
true;
635 $shortInfo = isset(
$params[
'SHORT_INFO']) &&
$params[
'SHORT_INFO'] ===
true;
636 $chatIds =
$params[
'CHAT_IDS'] ??
null;
647 'DATE_LAST_ACTIVITY',
649 'RELATION_ID' =>
'RELATION.ID',
650 'RELATION_NOTIFY_BLOCK' =>
'RELATION.NOTIFY_BLOCK',
651 'RELATION_IS_MANAGER' =>
'RELATION.MANAGER',
652 'CHAT_ID' =>
'CHAT.ID',
653 'CHAT_TITLE' =>
'CHAT.TITLE',
654 'CHAT_TYPE' =>
'CHAT.TYPE',
655 'CHAT_AVATAR' =>
'CHAT.AVATAR',
656 'CHAT_AUTHOR_ID' =>
'CHAT.AUTHOR_ID',
657 'CHAT_COLOR' =>
'CHAT.COLOR',
658 'CHAT_ENTITY_TYPE' =>
'CHAT.ENTITY_TYPE',
659 'CHAT_CAN_POST' =>
'CHAT.CAN_POST',
660 'CHAT_EXTRANET' =>
'CHAT.EXTRANET',
661 'USER_LAST_ACTIVITY_DATE' =>
'USER.LAST_ACTIVITY_DATE',
664 $additionalInfoFields = [
667 'MESSAGE_ID' =>
'MESSAGE.ID',
668 'MESSAGE_AUTHOR_ID' =>
'MESSAGE.AUTHOR_ID',
669 'MESSAGE_TEXT' =>
'MESSAGE.MESSAGE',
670 'MESSAGE_USER_LAST_ACTIVITY_DATE' =>
'MESSAGE.AUTHOR.LAST_ACTIVITY_DATE',
671 'USER_EMAIL' =>
'USER.EMAIL',
672 'MESSAGE_UUID_VALUE' =>
'MESSAGE_UUID.UUID',
673 'CHAT_MANAGE_USERS_ADD' =>
'CHAT.MANAGE_USERS_ADD',
674 'CHAT_MANAGE_USERS_DELETE' =>
'CHAT.MANAGE_USERS_DELETE',
675 'CHAT_MANAGE_UI' =>
'CHAT.MANAGE_UI',
676 'CHAT_MANAGE_SETTINGS' =>
'CHAT.MANAGE_SETTINGS',
677 'CHAT_LAST_MESSAGE_STATUS_BOOL' =>
'MESSAGE.NOTIFY_READ',
678 'RELATION_LAST_ID' =>
'RELATION.LAST_ID',
679 'CHAT_PARENT_ID' =>
'CHAT.PARENT_ID',
680 'CHAT_PARENT_MID' =>
'CHAT.PARENT_MID',
681 'CHAT_ENTITY_ID' =>
'CHAT.ENTITY_ID',
682 'CHAT_ENTITY_DATA_1' =>
'CHAT.ENTITY_DATA_1',
683 'CHAT_ENTITY_DATA_2' =>
'CHAT.ENTITY_DATA_2',
684 'CHAT_ENTITY_DATA_3' =>
'CHAT.ENTITY_DATA_3',
685 'CHAT_DATE_CREATE' =>
'CHAT.DATE_CREATE',
686 'CHAT_USER_COUNT' =>
'CHAT.USER_COUNT',
690 new \Bitrix\Main\Entity\ReferenceField(
692 '\Bitrix\Main\UserTable',
694 array(
"join_type"=>
"LEFT")
700 $shortRuntime[] = new \Bitrix\Main\Entity\ReferenceField(
702 '\Bitrix\Im\Model\MessageParamTable',
704 "=ref.MESSAGE_ID" =>
"this.ITEM_MID",
707 [
"join_type" =>
"LEFT"]
709 $shortInfoFields[
'MESSAGE_CODE'] =
'CODE.PARAM_VALUE';
712 $unreadTable = MessageUnreadTable::getTableName();
714 $additionalRuntime = [
716 'HAS_UNREAD_MESSAGE',
717 "EXISTS(SELECT 1 FROM {$unreadTable} WHERE CHAT_ID = %s AND USER_ID = %s)",
718 [
'ITEM_CID',
'USER_ID']
722 $select = $shortInfo ? $shortInfoFields : array_merge($shortInfoFields, $additionalInfoFields);
723 $runtime = $shortInfo ? $shortRuntime : array_merge($shortRuntime, $additionalRuntime);
725 if (!$withoutCommonUsers)
727 $select[
'INVITATION_ORIGINATOR_ID'] =
'INVITATION.ORIGINATOR_ID';
731 $select[
'LINES_ID'] =
'LINES.ID';
732 $select[
'LINES_STATUS'] =
'LINES.STATUS';
733 $select[
'LINES_DATE_CREATE'] =
'LINES.DATE_CREATE';
736 if (!$withoutCommonUsers)
738 $runtime[] = new \Bitrix\Main\Entity\ReferenceField(
740 '\Bitrix\Intranet\Internals\InvitationTable',
741 array(
"=this.ITEM_TYPE" =>
new \Bitrix\Main\DB\SqlExpression(
"?s",
IM_MESSAGE_PRIVATE),
"=ref.USER_ID" =>
"this.ITEM_ID"),
742 array(
"join_type"=>
"LEFT")
745 if ($showOpenlines && !$shortInfo)
747 $runtime[] = new \Bitrix\Main\Entity\ReferenceField(
749 '\Bitrix\ImOpenlines\Model\SessionTable',
750 [
">this.ITEM_OLID" =>
new \Bitrix\Main\DB\SqlExpression(
"?i", 0),
"=ref.ID" =>
"this.ITEM_OLID"],
751 [
"join_type" =>
"LEFT"]
755 if ($withoutCommonUsers)
764 if ($isIntranetInstalled && !$isIntranet)
766 $subQuery = Group::getExtranetAccessibleUsersQuery(
$userId);
767 if ($subQuery !==
null)
771 [
'!=ITEM_TYPE' =>
'P'],
772 [
'@USER.ID' =>
new SqlExpression($subQuery->getQuery())],
781 [
'==HAS_UNREAD_MESSAGE' =>
true],
788 $filter[
'@ITEM_CID'] = $chatIds;
794 'runtime' => $runtime,
798 private static function formatRow($row,
$options = []): ?
array
800 $generalChatId = (int)
$options[
'GENERAL_CHAT_ID'];
801 $withoutCommonUsers = isset(
$options[
'WITHOUT_COMMON_USERS']) &&
$options[
'WITHOUT_COMMON_USERS'] ===
true;
805 $id = $isUser? (int)$row[
'ITEM_ID']:
'chat'.$row[
'ITEM_ID'];
806 $row[
'MESSAGE_ID'] ??=
null;
808 if (!$isUser && ((!$row[
'MESSAGE_ID'] && !$shortInfo) || !$row[
'RELATION_ID'] || !$row[
'CHAT_ID']))
813 $item = self::formatItem($row,
$options, $shortInfo, $isUser, $id);
819 && ($row[
'USER_ID'] == 0 || $row[
'MESSAGE_CODE'] ===
'USER_JOIN')
825 $row[
'INVITATION_ORIGINATOR_ID'] ??=
null;
826 if (!$row[
'USER_LAST_ACTIVITY_DATE'] && $row[
'INVITATION_ORIGINATOR_ID'])
829 'ORIGINATOR_ID' => (int)$row[
'INVITATION_ORIGINATOR_ID'],
830 'CAN_RESEND' => !empty($row[
'USER_EMAIL'])
834 'ID' => (int)$row[
'ITEM_ID'],
837 $item[
'CHAT'][
'TEXT_FIELD_ENABLED'] = self::getTextFieldEnabled((
int)$row[
'ITEM_CID']);
838 $item[
'CHAT'][
'BACKGROUND_ID'] = self::getBackgroundId((
int)$row[
'ITEM_CID']);
842 $item[
'CHAT'] = self::formatChat($row, $shortInfo, $generalChatId);
847 'URL' => $item[
'CHAT'][
'AVATAR'],
848 'COLOR' => $item[
'CHAT'][
'COLOR'],
850 $item[
'TITLE'] = $row[
'CHAT_TITLE'];
853 if ($row[
"CHAT_ENTITY_TYPE"] ==
'LINES')
856 'ID' => (int)$row[
'LINES_ID'],
857 'STATUS' => (
int)$row[
'LINES_STATUS'],
858 'DATE_CREATE' => $row[
'LINES_DATE_CREATE'] ?? $row[
'DATE_UPDATE'],
862 'ID' => (int)($row[
'MESSAGE_AUTHOR_ID'] ?? 0),
866 if ($item[
'USER'][
'ID'] > 0)
868 $user = self::formatUser($row, $item, $shortInfo);
875 $item[
'USER'] =
$user;
879 && $item[
'TYPE'] ==
'user'
884 'URL' =>
$user[
'AVATAR'],
885 'COLOR' =>
$user[
'COLOR']
887 $item[
'TITLE'] =
$user[
'NAME'];
891 $item[
'OPTIONS'] = [];
892 if ($row[
'USER_ID'] == 0 || $row[
'MESSAGE_CODE'] ===
'USER_JOIN')
894 $item[
'OPTIONS'][
'DEFAULT_USER_RECORD'] =
true;
902 $row[
'DATE_MESSAGE'] ??=
null;
907 'ID' => (int)($row[
'ITEM_MID'] ?? 0),
908 'DATE' => $row[
'DATE_MESSAGE'] ?: $row[
'DATE_LAST_ACTIVITY'],
912 if (!$row[
'ITEM_MID'] || !$row[
'MESSAGE_ID'])
915 'ID' => (int)($row[
'ITEM_MID'] ?? 0),
920 'DATE' => $row[
'DATE_MESSAGE']?: $row[
'DATE_UPDATE'],
921 'STATUS' => $row[
'CHAT_LAST_MESSAGE_STATUS'],
926 if ($row[
'MESSAGE_ATTACH'] || $row[
"MESSAGE_ATTACH_JSON"])
928 if (preg_match(
'/^(\d+)$/', $row[
'MESSAGE_ATTACH']))
932 else if ($row[
'MESSAGE_ATTACH'] === \CIMMessageParamAttach::FIRST_MESSAGE)
936 $value = \Bitrix\Main\Web\Json::decode($row[
"MESSAGE_ATTACH_JSON"]);
937 $attachRestored = \CIMMessageParamAttach::PrepareAttach($value);
938 $attach = $attachRestored[
'DESCRIPTION'];
940 catch (\Bitrix\Main\SystemException $e)
945 else if (!empty($row[
'MESSAGE_ATTACH']))
947 $attach = $row[
'MESSAGE_ATTACH'];
955 $text = $row[
'MESSAGE_TEXT'] ??
'';
957 $getOriginalTextOption =
$options[
'GET_ORIGINAL_TEXT'] ??
null;
958 $parseText =
$options[
'PARSE_TEXT'] ??
null;
959 if ($parseText ===
'Y')
963 elseif ($getOriginalTextOption ===
'Y')
970 str_replace(
"\n",
" ",
$text),
971 $row[
'MESSAGE_FILE'] > 0,
977 'ID' => (int)$row[
'ITEM_MID'],
979 'FILE' => $row[
'MESSAGE_FILE'],
980 'AUTHOR_ID' => (
int)$row[
'MESSAGE_AUTHOR_ID'],
982 'DATE' => $row[
'DATE_MESSAGE']?: $row[
'DATE_UPDATE'],
983 'STATUS' => $row[
'CHAT_LAST_MESSAGE_STATUS'],
984 'UUID' => $row[
'MESSAGE_UUID_VALUE'],
988 private static function formatItem(
1002 'CHAT_ID' => (int)$row[
'CHAT_ID'],
1003 'TYPE' => $isUser ?
'user' :
'chat',
1005 'COUNTER' => (int)$row[
'COUNTER'],
1006 'PINNED' => $row[
'PINNED'] ===
'Y',
1007 'UNREAD' => $row[
'UNREAD'] ===
'Y',
1008 'DATE_LAST_ACTIVITY' => $row[
'DATE_LAST_ACTIVITY'],
1014 'CHAT_ID' => (int)$row[
'CHAT_ID'],
1015 'TYPE' => $isUser ?
'user' :
'chat',
1019 'COUNTER' => (int)$row[
'COUNTER'],
1020 'LAST_ID' => (int)($row[
'RELATION_LAST_ID'] ?? 0),
1021 'PINNED' => $row[
'PINNED'] ===
'Y',
1022 'UNREAD' => $row[
'UNREAD'] ===
'Y',
1023 'HAS_REMINDER' => isset($row[
'HAS_REMINDER']) && $row[
'HAS_REMINDER'] ===
'Y',
1024 'DATE_UPDATE' => $row[
'DATE_UPDATE'],
1025 'DATE_LAST_ACTIVITY' => $row[
'DATE_LAST_ACTIVITY'],
1029 private static function formatChat(
array $row,
bool $shortInfo,
int $generalChatId):
array
1031 $avatar = \CIMChat::GetAvatarImage($row[
'CHAT_AVATAR'], 200,
false);
1032 $color = $row[
'CHAT_COLOR'] <>
''
1034 :
Color::getColorByNumber(
1037 $chatType = \Bitrix\Im\Chat::getType($row);
1039 if ($generalChatId == $row[
'ITEM_ID'])
1041 $row[
"CHAT_ENTITY_TYPE"] =
'GENERAL';
1045 if ($row[
'RELATION_NOTIFY_BLOCK'] ==
'Y')
1047 $muteList = [$row[
'RELATION_USER_ID'] =>
true];
1053 'ID' => (int)$row[
'ITEM_CID'],
1054 'NAME' => $row[
'CHAT_TITLE'],
1055 'EXTRANET' => $row[
'CHAT_EXTRANET'] ==
'Y',
1056 'CONTAINS_COLLABER' => self::containsCollaber((
int)$row[
'ITEM_CID']),
1057 'AVATAR' => $avatar,
1059 'TYPE' => $chatType,
1060 'ENTITY_TYPE' => (string)$row[
'CHAT_ENTITY_TYPE'],
1061 'MUTE_LIST' => $muteList,
1062 'ROLE' => self::getRole($row),
1063 'TEXT_FIELD_ENABLED' => self::getTextFieldEnabled((
int)$row[
'ITEM_CID']),
1064 'BACKGROUND_ID' => self::getBackgroundId((
int)$row[
'ITEM_CID']),
1066 'MANAGE_MESSAGES' => mb_strtolower($row[
'CHAT_CAN_POST'] ??
''),
1071 $publicOption =
null;
1074 $publicOption = \Bitrix\Im\V2\Chat::getInstance((
int)$row[
'ITEM_CID'])->getPublicOption();
1078 if ($row[
'CHAT_OWNER'] ??
null == $row[
'RELATION_USER_ID'] || $row[
'RELATION_IS_MANAGER'] ==
'Y')
1080 $managerList = [(int)$row[
'RELATION_USER_ID']];
1083 $chatOptions = \CIMChat::GetChatOptions();
1084 $restrictions = $chatOptions[
'DEFAULT'];
1085 if ($row[
'CHAT_ENTITY_TYPE'] && array_key_exists($row[
'CHAT_ENTITY_TYPE'], $chatOptions))
1087 $restrictions = $chatOptions[$row[
'CHAT_ENTITY_TYPE']];
1091 'ID' => (int)$row[
'ITEM_CID'],
1092 'PARENT_CHAT_ID' => (
int)$row[
'CHAT_PARENT_ID'],
1093 'PARENT_MESSAGE_ID' => (int)$row[
'CHAT_PARENT_MID'],
1094 'NAME' => $row[
'CHAT_TITLE'],
1095 'OWNER' => (
int)$row[
'CHAT_AUTHOR_ID'],
1096 'EXTRANET' => $row[
'CHAT_EXTRANET'] ==
'Y',
1097 'CONTAINS_COLLABER' => self::containsCollaber((
int)$row[
'ITEM_CID']),
1098 'AVATAR' => $avatar,
1100 'TYPE' => $chatType,
1101 'ENTITY_TYPE' => (string)$row[
'CHAT_ENTITY_TYPE'],
1102 'ENTITY_ID' => (
string)$row[
'CHAT_ENTITY_ID'],
1103 'ENTITY_DATA_1' => (string)$row[
'CHAT_ENTITY_DATA_1'],
1104 'ENTITY_DATA_2' => (
string)$row[
'CHAT_ENTITY_DATA_2'],
1105 'ENTITY_DATA_3' => (string)$row[
'CHAT_ENTITY_DATA_3'],
1106 'MUTE_LIST' => $muteList,
1107 'MANAGER_LIST' => $managerList,
1108 'DATE_CREATE' => $row[
'CHAT_DATE_CREATE'],
1109 'MESSAGE_TYPE' => $row[
"CHAT_TYPE"],
1110 'USER_COUNTER' => (
int)$row[
'CHAT_USER_COUNT'],
1111 'RESTRICTIONS' => $restrictions,
1112 'ROLE' => self::getRole($row),
1113 'TEXT_FIELD_ENABLED' => self::getTextFieldEnabled((
int)$row[
'ITEM_CID']),
1114 'BACKGROUND_ID' => self::getBackgroundId((
int)$row[
'ITEM_CID']),
1115 'ENTITY_LINK' => EntityLink::getInstance(\CIMChat::initChatByArray($row))->toArray(),
1117 'MANAGE_USERS_ADD' => mb_strtolower($row[
'CHAT_MANAGE_USERS_ADD'] ??
''),
1118 'MANAGE_USERS_DELETE' => mb_strtolower($row[
'CHAT_MANAGE_USERS_DELETE'] ??
''),
1119 'MANAGE_UI' => mb_strtolower($row[
'CHAT_MANAGE_UI'] ??
''),
1120 'MANAGE_SETTINGS' => mb_strtolower($row[
'CHAT_MANAGE_SETTINGS'] ??
''),
1121 'MANAGE_MESSAGES' => mb_strtolower($row[
'CHAT_CAN_POST'] ??
''),
1122 'CAN_POST' => mb_strtolower($row[
'CHAT_CAN_POST'] ??
''),
1124 'PUBLIC' => $publicOption ??
'',
1128 private static function containsCollaber(
int $chatId): bool
1135 $paramsService = Params::getInstance($chatId);
1137 return (
bool)$paramsService->get(Params::CONTAINS_COLLABER)?->getValue();
1140 private static function getTextFieldEnabled(
int $chatId): bool
1142 return (
new TextFieldEnabled($chatId))->get();
1145 private static function getBackgroundId(
int $chatId): ?string
1147 return (
new Background($chatId))->get();
1150 private static function getChatMessagesAutoDeleteConfigs(
int $chatId):
array
1154 return (
new Converter(Converter::TO_SNAKE | Converter::TO_UPPER | Converter::KEYS))->process(
$config);
1157 private static function formatUser(
array $row,
array $item,
bool $shortInfo): ?
array
1159 $userObject = \Bitrix\Im\V2\Entity\User\User::getInstance($item[
'USER'][
'ID']);
1160 if ($userObject instanceof NullUser)
1165 $user = $userObject->getArray([
'WITHOUT_ONLINE' =>
true,
'USER_SHORT_FORMAT' => $shortInfo]);
1169 if (!$userObject->isActive())
1177 if ($item[
'TYPE'] ==
'user')
1180 !empty(
$user[
'BOT_DATA'])
1181 && Loader::includeModule(
'imbot')
1182 &&
$user[
'BOT_DATA'][
'code'] === CopilotChatBot::BOT_CODE
1189 (!
$user[
'ACTIVE'] && $item[
'COUNTER'] <= 0)
1191 && !
$user[
'CONNECTOR']
1192 && !
$user[
'NETWORK']
1199 if ($item[
'TYPE'] ==
'user')
1201 $lastActivityDate = $row[
'USER_LAST_ACTIVITY_DATE'] ??
null;
1205 $lastActivityDate = $row[
'MESSAGE_USER_LAST_ACTIVITY_DATE'] ??
null;
1208 $user[
'LAST_ACTIVITY_DATE'] = $lastActivityDate ?:
false;
1209 $user[
'DESKTOP_LAST_DATE'] =
false;
1210 $user[
'MOBILE_LAST_DATE'] =
false;
1211 $user[
'IDLE'] =
false;
1216 private static function jsonRow($item)
1218 if (!is_array($item))
1223 foreach ($item as
$key => $value)
1225 if ($value instanceof \Bitrix\Main\Type\DateTime)
1227 $item[
$key] = date(
'c',
$value->getTimestamp());
1229 else if (is_array($value))
1231 foreach ($value as $subKey => $subValue)
1233 if ($subValue instanceof \Bitrix\Main\Type\DateTime)
1235 $value[$subKey] = date(
'c', $subValue->getTimestamp());
1238 is_string($subValue)
1240 && in_array($subKey, [
'URL',
'AVATAR'])
1241 && mb_strpos($subValue,
'http') !== 0
1244 $value[$subKey] = \Bitrix\Im\Common::getPublicDomain().$subValue;
1246 else if (is_array($subValue))
1248 $value[$subKey] = array_change_key_case($subValue, CASE_LOWER);
1251 $item[
$key] = array_change_key_case($value, CASE_LOWER);
1255 return array_change_key_case($item, CASE_LOWER);
1266 $pinnedCount = \Bitrix\Im\Model\RecentTable::getCount([
'=USER_ID' =>
$userId,
'=PINNED' =>
'Y']);
1268 self::$limitError =
false;
1269 if ($pin && (
int)$pinnedCount >= self::PINNED_CHATS_LIMIT)
1271 self::$limitError =
true;
1276 $pin = $pin ===
true?
'Y':
'N';
1280 if (mb_substr($dialogId, 0, 4) ==
'chat')
1283 $id = mb_substr($dialogId, 4);
1292 $element = \Bitrix\Im\Model\RecentTable::getList(
1294 'select' => [
'USER_ID',
'ITEM_TYPE',
'ITEM_ID',
'PINNED',
'PIN_SORT'],
1297 '=ITEM_TYPE' => $itemTypes,
1323 $relationData = \Bitrix\Im\Model\RelationTable::getList(
1325 'select' => [
'ID',
'LAST_MESSAGE_ID' =>
'CHAT.LAST_MESSAGE_ID'],
1327 '=CHAT_ID' => $chatId,
1333 $messageId = $relationData[
'LAST_MESSAGE_ID'];
1334 $relationId = $relationData[
'ID'];
1336 $addResult = \Bitrix\Im\Model\RecentTable::add(
1339 'ITEM_TYPE' => $itemTypes,
1342 'ITEM_RID' => $relationId,
1343 'ITEM_CID' => $chatId,
1347 if (!$addResult->isSuccess())
1354 $element[
'USER_ID'] =
$userId;
1355 $element[
'ITEM_TYPE'] = $itemTypes;
1356 $element[
'ITEM_ID'] = $id;
1359 if ($element[
'PINNED'] == $pin)
1369 self::increasePinSortCost(
$userId);
1373 $pinSort = $element[
'PIN_SORT'] ? (int)$element[
'PIN_SORT'] :
null;
1374 self::decreasePinSortCost(
$userId, $pinSort);
1378 \Bitrix\Im\Model\RecentTable::update(
1380 'USER_ID' => $element[
'USER_ID'],
1381 'ITEM_TYPE' => $element[
'ITEM_TYPE'],
1382 'ITEM_ID' => $element[
'ITEM_ID'],
1387 'PIN_SORT' => ($pin ===
'Y') ? 1 :
null,
1400 self::clearCache($element[
'USER_ID']);
1408 'module_id' =>
'im',
1409 'command' =>
'chatPin',
1412 'dialogId' => $dialogId,
1413 'active' => $pin ==
'Y'
1423 private static function increasePinSortCost(
int $userId): void
1427 RecentTable::updateByFilter(
1433 [
'PIN_SORT' => $caseField]
1437 private static function decreasePinSortCost(
int $userId, ?
int $pinSort)
1439 if (!isset($pinSort))
1444 $caseField =
new SqlExpression(
'?# - 1',
'PIN_SORT');
1446 RecentTable::updateByFilter(
1450 '>PIN_SORT' => $pinSort,
1452 [
'PIN_SORT' => $caseField]
1461 $query = RecentTable::query()
1462 ->setSelect([
'PIN_SORT'])
1465 ->where(
'ITEM_CID', (
int)$chat->getChatId())
1466 ->where(
'PINNED',
'Y')
1476 $currentCost = (int)
$query[
'PIN_SORT'];
1478 $query = RecentTable::query()
1479 ->setSelect([
'PIN_SORT'])
1480 ->setOrder([
'PIN_SORT'])
1481 ->setOffset($newPosition - 1)
1483 ->where(
'PINNED',
'Y')
1494 $newCost = (int)
$query[
'PIN_SORT'];
1496 if ($currentCost === $newCost)
1503 if ($currentCost < $newCost)
1506 "CASE WHEN ?# = ?i THEN ?i WHEN ?# > ?i AND ?# <= ?i THEN ?# - 1 END",
1520 '>=PIN_SORT' => $currentCost,
1521 '<=PIN_SORT' => $newCost,
1527 "CASE WHEN ?# = ?i THEN ?i WHEN ?# >= ?i AND ?# < ?i THEN ?# + 1 END",
1541 '>=PIN_SORT' => $newCost,
1542 '<=PIN_SORT' => $currentCost,
1546 RecentTable::updateByFilter(
1548 [
'PIN_SORT' => $caseField]
1556 return self::PINNED_CHATS_LIMIT ?? 25;
1566 RecentTable::updateByFilter(
1571 [
'PIN_SORT' => $caseField]
1585 if (empty($userIds))
1591 $dateCreate = $lastActivity ?? $dateMessage;
1594 foreach ($relations as $relation)
1596 $userId = $relation->getUserId();
1601 'ITEM_TYPE' => $chat->getType(),
1602 'ITEM_ID' => $chat->getId(),
1603 'ITEM_MID' => $chat->getLastMessageId(),
1604 'ITEM_CID' => $chat->getId(),
1605 'ITEM_RID' => $relation->getId(),
1606 'DATE_MESSAGE' => $dateMessage,
1607 'DATE_UPDATE' => $dateCreate,
1608 'DATE_LAST_ACTIVITY' => $dateCreate,
1613 static::merge(
$fields, [
'DATE_LAST_ACTIVITY' => $dateCreate,
'DATE_UPDATE' => $dateCreate]);
1620 static::sendPullRecentUpdate($chat, $userIds, $dateCreate);
1627 $pull = $restAdapter->toRestFormat([
1628 'WITHOUT_OWN_REACTIONS' =>
true,
1629 'MESSAGE_ONLY_COMMON_FIELDS' =>
true,
1631 $pull[
'chat'] = $chat->toPullFormat();
1632 $pull[
'lastActivityDate'] = $lastCommentDate;
1633 $pull[
'counterType'] = $chat->getCounterType()->value;
1634 $pull[
'recentConfig'] = $chat->getRecentConfig()->toPullFormat();
1637 'module_id' =>
'im',
1638 'command' =>
'recentUpdate',
1642 $events = PushService::getEventGroups(
$event, $userIds, $chat->getId());
1644 foreach ($events as
$event)
1652 RecentTable::multiplyMerge(
$fields, $update, [
'USER_ID',
'ITEM_TYPE',
'ITEM_ID']);
1657 $relations = $chat->getRelations()->filterActive();
1658 $users = $relations->getUserIds();
1659 $usersAlreadyInRecentRows = RecentTable::query()
1660 ->setSelect([
'USER_ID'])
1661 ->where(
'ITEM_CID', $chat->getId())
1662 ->whereIn(
'USER_ID', $users)
1665 foreach ($usersAlreadyInRecentRows as $row)
1667 $userId = (int)$row[
'USER_ID'];
1674 public static function unread($dialogId, $unread,
$userId =
null, ?
int $markedId =
null, ?
string $itemTypes =
null)
1682 $unread = $unread ===
true?
'Y':
'N';
1684 $element = self::getUnreadElement(
$userId, $itemTypes, $dialogId);
1690 if ($element[
'UNREAD'] === $unread && !isset($markedId))
1695 self::$unreadElementCache[
$userId][$dialogId] =
null;
1698 'UNREAD' => $unread,
1699 'DATE_UPDATE' => new \Bitrix\Main\Type\DateTime(),
1702 if ($unread ===
'N')
1706 if (isset($markedId))
1708 $updatedFields[
'MARKED_ID'] = $markedId;
1711 \Bitrix\Im\Model\RecentTable::update(
1713 'USER_ID' => $element[
'USER_ID'],
1714 'ITEM_TYPE' => $element[
'ITEM_TYPE'],
1715 'ITEM_ID' => $element[
'ITEM_ID'],
1720 self::clearCache($element[
'USER_ID']);
1723 $chatId = (int)$element[
'ITEM_CID'];
1735 $counter = $readService->getCounterService()->getByChatWithOverflow($chatId);
1740 'module_id' =>
'im',
1741 'command' =>
'chatUnread',
1744 'chatId' => $chatId,
1745 'dialogId' => $dialogId,
1746 'active' => $unread ===
'Y',
1747 'muted' => $element[
'MUTED'] ===
'Y',
1749 'markedId' => $markedId ?? $element[
'MARKED_ID'],
1751 'counterType' => $chat->getCounterType()->value,
1752 'recentConfig' => $chat->getRecentConfig()->toPullFormat(),
1762 private static function getUnreadElement(
int $userId, ?
string $itemTypes, $dialogId):
array|
false
1764 if (self::$unreadElementCache[
$userId][$dialogId] !==
null)
1766 return self::$unreadElementCache[
$userId][$dialogId];
1770 if (mb_substr($dialogId, 0, 4) ===
'chat')
1772 if ($itemTypes ===
null)
1777 $id = mb_substr($dialogId, 4);
1784 self::$unreadElementCache[
$userId][$dialogId] = \Bitrix\Im\Model\RecentTable::getList([
1790 'MUTED' =>
'RELATION.NOTIFY_BLOCK',
1793 'ENTITY_TYPE' =>
'CHAT.ENTITY_TYPE',
1797 '=ITEM_TYPE' => $itemTypes,
1802 return self::$unreadElementCache[
$userId][$dialogId];
1807 \Bitrix\Im\Model\RecentTable::updateByFilter(
1821 $id = mb_strpos($dialogId,
'chat') === 0 ? mb_substr($dialogId, 4) : $dialogId;
1822 $element = \Bitrix\Im\Model\RecentTable::getList([
1823 'select' => [
'USER_ID',
'ITEM_TYPE',
'ITEM_ID',
'UNREAD',
'MUTED' =>
'RELATION.NOTIFY_BLOCK',
'ITEM_CID'],
1826 '=ITEM_TYPE' => $itemType,
1835 return ($element[
'UNREAD'] ??
'N') ===
'Y';
1840 $id = mb_strpos($dialogId,
'chat') === 0 ? mb_substr($dialogId, 4) : $dialogId;
1841 $queryResult = \Bitrix\Im\Model\RecentTable::getList([
1842 'select' => [
'USER_ID',
'UNREAD',],
1844 '=ITEM_TYPE' => $itemType,
1851 foreach ($queryResult as $row)
1853 $result[(int)$row[
'USER_ID']] = ($row[
'UNREAD'] ??
'N') ===
'Y';
1861 $id = mb_strpos($dialogId,
'chat') === 0 ? mb_substr($dialogId, 4) : $dialogId;
1862 $element = \Bitrix\Im\Model\RecentTable::getList([
1863 'select' => [
'MARKED_ID'],
1866 '=ITEM_TYPE' => $itemType,
1875 return (
int)($element[
'MARKED_ID'] ?? 0);
1880 if (empty($chatIds))
1885 $markedIdByChatIds = [];
1887 $result = RecentTable::query()
1888 ->setSelect([
'ITEM_CID',
'MARKED_ID'])
1890 ->whereIn(
'ITEM_CID', $chatIds)
1896 $markedIdByChatIds[(int)$row[
'ITEM_CID']] = (
int)$row[
'MARKED_ID'];
1899 return $markedIdByChatIds;
1904 return \CIMContactList::DialogHide($dialogId,
$userId);
1925 $relation = \Bitrix\Im\Model\RelationTable::getList([
1928 'TYPE' =>
'CHAT.TYPE',
1929 'LAST_MESSAGE_ID' =>
'CHAT.LAST_MESSAGE_ID',
1930 'LAST_MESSAGE_DATE' =>
'MESSAGE.DATE_CREATE'
1933 '=CHAT_ID' => $chatId,
1939 '\Bitrix\Im\Model\MessageTable',
1940 [
"=ref.ID" =>
"this.CHAT.LAST_MESSAGE_ID"],
1941 [
"join_type" =>
"LEFT"]
1948 $relationId = $relation[
'ID'];
1949 $entityType = $relation[
'TYPE'];
1951 $messageDate = $relation[
'LAST_MESSAGE_DATE'];
1954 isset(
$options[
'CHAT_DATA'][
'TYPE'])
1955 && isset(
$options[
'CHAT_DATA'][
'LAST_MESSAGE_ID'])
1959 $entityType =
$options[
'CHAT_DATA'][
'TYPE'];
1961 $messageDate =
$options[
'CHAT_DATA'][
'LAST_MESSAGE_DATE'];
1965 $chat = \Bitrix\Im\Model\ChatTable::getList([
1969 'LAST_MESSAGE_DATE' =>
'MESSAGE.DATE_CREATE'
1977 '\Bitrix\Im\Model\MessageTable',
1978 [
"=ref.ID" =>
"this.LAST_MESSAGE_ID"],
1979 [
"join_type" =>
"LEFT"]
1989 $entityType = $chat[
'TYPE'];
1991 $messageDate = $chat[
'LAST_MESSAGE_DATE'];
1999 $sessionId = (int)
$options[
'SESSION_ID'];
2001 else if (\
Bitrix\
Main\Loader::includeModule(
'imopenlines'))
2003 $session = \Bitrix\ImOpenLines\Model\SessionTable::getList([
2005 'filter' => [
'=CHAT_ID' => $chatId],
2006 'order' => [
'ID' =>
'DESC'],
2011 $sessionId = $session[
'ID'];
2016 \CIMContactList::SetRecent($temp = [
2017 'ENTITY_TYPE' => $entityType,
2020 'MESSAGE_DATE' => $messageDate,
2021 'CHAT_ID' => $chatId,
2022 'RELATION_ID' => $relationId,
2023 'SESSION_ID' => $sessionId,
2027 if (!\
Bitrix\
Main\Loader::includeModule(
"pull"))
2036 !isset(
$data[
'message'])
2038 && class_exists(
'\Bitrix\ImOpenLines\Recent')
2041 $data = \Bitrix\ImOpenLines\Recent::getElement(
2051 'module_id' =>
'im',
2052 'command' =>
'chatShow',
2069 [$messageIds, $chatIds] = self::getKeysForFetchAdditionalEntities(
$rows);
2071 $params = $shortInfo ? [] : self::getMessageParams($messageIds);
2081 foreach (
$rows as $row)
2083 if (isset($row[
'ITEM_MID']) && $row[
'ITEM_MID'] > 0)
2085 $messageIds[] = (int)$row[
'ITEM_MID'];
2088 if (isset($row[
'ITEM_CID']) && $row[
'ITEM_CID'] > 0)
2090 $chatIds[] = (int)$row[
'ITEM_CID'];
2094 return [$messageIds, $chatIds];
2102 if (empty($messageIds))
2107 $rows = MessageParamTable::query()
2109 ->whereIn(
'MESSAGE_ID', $messageIds)
2113 foreach (
$rows as $item)
2116 $paramName = $item[
'PARAM_NAME'];
2118 if ($paramName ===
'CODE')
2122 elseif ($paramName ===
'ATTACH')
2125 'VALUE' => $item[
'PARAM_VALUE'],
2126 'JSON' => $item[
'PARAM_JSON'],
2129 elseif ($paramName ===
'URL_ID')
2136 elseif ($paramName ===
'FILE_ID')
2138 $fileIds[
$messageId] = (int)$item[
'PARAM_VALUE'];
2143 return self::fillFiles(
$result, $fileIds);
2148 if (empty($fileIds))
2162 $file =
$files->getById($fileId);
2170 'ID' => $file->getId(),
2171 'TYPE' => $file->getContentType(),
2172 'NAME' => $file->getDiskFile()->getName(),
2184 $chatId = (int)($row[
'ITEM_CID'] ?? 0);
2186 $boolStatus = $row[
'CHAT_LAST_MESSAGE_STATUS_BOOL'] ??
'N';
2207 if (!isset($row[
'RELATION_USER_ID']))
2209 return \Bitrix\Im\V2\Chat::ROLE_GUEST;
2211 if ((
int)$row[
'CHAT_AUTHOR_ID'] === (
int)$row[
'RELATION_USER_ID'])
2213 return \Bitrix\Im\V2\Chat::ROLE_OWNER;
2215 if ($row[
'RELATION_IS_MANAGER'] ===
'Y')
2217 return \Bitrix\Im\V2\Chat::ROLE_MANAGER;
2220 return \Bitrix\Im\V2\Chat::ROLE_MEMBER;
2225 return self::$limitError;
if(! $messageFields||!isset($messageFields['message_id'])||!isset($messageFields['status'])||!CModule::IncludeModule("messageservice")) $messageId
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
const ENTITY_TYPE_VIDEOCONF
static getCacheUserPostfix($id)
static getUserId($userId=null)
static getChatId($dialogId, $userId=null)
static getBirthdayForToday()
static readAll(int $userId)
static show($dialogId, $options=[], $userId=null)
static prepareRows(array $rows, int $userId, bool $shortInfo=false)
static isUnread(int $userId, string $itemType, string $dialogId)
static clearCache($userId=null)
static getUnread(string $itemType, string $dialogId)
static updateByFilter(array $filter, array $fields)
static getMarkedIdByChatIds(int $userId, array $chatIds)
static raiseChat(\Bitrix\Im\V2\Chat $chat, RelationCollection $relations, ?DateTime $lastActivity=null)
static sortPin(\Bitrix\Im\V2\Chat $chat, int $newPosition, int $userId)
static unread($dialogId, $unread, $userId=null, ?int $markedId=null, ?string $itemTypes=null)
static updatePinSortCost(int $userId)
static fillRows(array $rows, array $params, array $counters, int $userId)
static getMarkedId(int $userId, string $itemType, string $dialogId)
static getRole(array $row)
static getList($userId=null, $options=[])
static hide($dialogId, $userId=null)
static fillFiles(array $params, array $fileIds)
static getUsersOutOfRecent(\Bitrix\Im\V2\Chat $chat)
static getMessageParams(array $messageIds)
static merge(array $fields, array $update)
static getKeysForFetchAdditionalEntities(array $rows)
static getElement($itemType, $itemId, $userId=null, $options=[])
static sendPullRecentUpdate(\Bitrix\Im\V2\Chat $chat, array $userIds, ?DateTime $lastCommentDate)
static pin($dialogId, $pin, $userId=null)
static isLegacyChatActivated($userId=false)
static parse($text, $params=Array())
static populateUserBbCode(string $text)
static removeBbCodes($text, $withFile=false, $attachValue=false)
static initByDiskFilesIds(array $diskFilesIds, ?int $chatId=null)
static getRoleGetListFilter(array $ormParams, ActionGroup $action, string $relationTableAlias, string $chatTableAlias)
static clearCache($moduleId)
static includeModule($moduleName)
static sortByColumn(array &$array, $columns, $callbacks='', $defaultValueIfNotSetValue=null, $preserveKeys=false)
static add($recipient, array $parameters, $channelType=\CPullChannel::TYPE_PRIVATE)
static GetSetting($type, $value, $userId=false)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
const IM_MESSAGE_STATUS_DELIVERED
const IM_MESSAGE_STATUS_RECEIVED
const IM_MESSAGE_OPEN_LINE
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']