static function getMessages($chatId, $userId = null, $options = Array())
{
$userId = BitrixImCommon::getUserId($userId);
if (!$userId)
{
return false;
}
$chatData = BitrixImModelChatTable::getList(Array(
'select' => Array(
'CHAT_ID' => 'ID',
'CHAT_TYPE' => 'TYPE',
'CHAT_ENTITY_TYPE' => 'ENTITY_TYPE',
'CHAT_ENTITY_ID' => 'ENTITY_ID',
'RELATION_USER_ID' => 'RELATION.USER_ID',
'RELATION_START_ID' => 'RELATION.START_ID',
//'RELATION_UNREAD_ID' => 'RELATION.UNREAD_ID',
'RELATION_LAST_ID' => 'RELATION.LAST_ID',
//'RELATION_STATUS' => 'RELATION.STATUS',
//'RELATION_COUNTER' => 'RELATION.COUNTER'
),
'filter' => Array('=ID' => $chatId),
'runtime' => Array(
new BitrixMainEntityReferenceField(
'RELATION',
'BitrixImModelRelationTable',
array(
"=ref.CHAT_ID" => "this.ID",
"=ref.USER_ID" => new BitrixMainDBSqlExpression('?', $userId)
),
array("join_type"=>"LEFT")
)
)
))->fetch();
if (!$chatData)
{
return false;
}
$readService = new ReadService($userId);
$chatData['RELATION_UNREAD_ID'] = $readService->getCounterService()->getIdFirstUnreadMessage($chatId) ?? 0;
$chatData['RELATION_COUNTER'] = $readService->getCounterService()->getByChat($chatId);
$chatData['RELATION_START_ID'] = (int)$chatData['RELATION_START_ID'];
if (isset($options['LIMIT']))
{
$options['LIMIT'] = intval($options['LIMIT']);
$limit = $options['LIMIT'] >= 100? 100: $options['LIMIT'];
}
else
{
$limit = 50;
}
$filter = Array(
'=CHAT_ID' => $chatId
);
$fileSort = 'ASC';
$startFromUnread = false;
if (
!isset($options['LAST_ID'])
&& !isset($options['FIRST_ID'])
//&& $chatData['RELATION_STATUS'] != BitrixImChat::STATUS_READ
&& $chatData['RELATION_COUNTER'] > 0
)
{
if ($chatData['RELATION_COUNTER'] > $limit)
{
$startFromUnread = true;
$options['FIRST_ID'] = $chatData['RELATION_LAST_ID'];
}
else
{
$limit += $chatData['RELATION_COUNTER'];
}
}
if (isset($options['FIRST_ID']))
{
$orderId = [];
$orderResult = [];
if ($chatData['RELATION_START_ID'] > 0 && intval($options['FIRST_ID']) < $chatData['RELATION_START_ID'])
{
$filter['>=ID'] = $chatData['RELATION_START_ID'];
}
else
{
if (intval($options['FIRST_ID']) > 0)
{
$filter['>ID'] = $options['FIRST_ID'];
}
}
}
else
{
$fileSort = 'DESC';
$orderId = Array('CHAT_ID' => 'ASC', 'ID' => 'DESC');
$orderResult = Array('ID' => 'DESC');
if ($chatData['RELATION_START_ID'] > 0)
{
$filter['>=ID'] = $chatData['RELATION_START_ID'];
}
if (isset($options['LAST_ID']) && intval($options['LAST_ID']) > 0)
{
$filter[' ['ID'],
'filter' => $filter,
'order' => $orderId,
'limit' => $limit
));
$ids = array_map(fn ($item) => $item['ID'], $orm->fetchAll());
if (empty($ids))
{
$result = [
'CHAT_ID' => (int)$chatId,
'MESSAGES' => [],
'USERS' => [],
'FILES' => [],
];
if ($options['JSON'])
{
$result = array_change_key_case($result, CASE_LOWER);
}
return $result;
}
$orm = BitrixImModelMessageTable::getList(array(
'select' => [
'ID', 'AUTHOR_ID', 'DATE_CREATE', 'NOTIFY_EVENT', 'MESSAGE',
'USER_LAST_ACTIVITY_DATE' => 'AUTHOR.LAST_ACTIVITY_DATE',
'USER_IDLE' => 'STATUS.IDLE',
'USER_MOBILE_LAST_DATE' => 'STATUS.MOBILE_LAST_DATE',
'USER_DESKTOP_LAST_DATE' => 'STATUS.DESKTOP_LAST_DATE',
'MESSAGE_UUID' => 'UUID.UUID',
],
'filter' => ['=ID' => $ids],
'order' => $orderResult,
));
$users = Array();
$userOptions = ['SKIP_ONLINE' => 'Y'];
if ($options['JSON'] == 'Y')
{
$userOptions['JSON'] = 'Y';
}
if ($chatData['CHAT_ENTITY_TYPE'] == 'LIVECHAT')
{
[$lineId] = explode('|', $chatData['CHAT_ENTITY_ID']);
$userOptions['LIVECHAT'] = $lineId;
$userOptions['USER_CODE'] = 'livechat|' . $lineId . '|' . $chatData['CHAT_ID'] . '|' . $userId;
}
$messages = Array();
while($message = $orm->fetch())
{
if ($message['NOTIFY_EVENT'] == 'private_system')
{
$message['AUTHOR_ID'] = 0;
}
if ($options['USER_TAG_SPREAD'] === 'Y')
{
$message['MESSAGE'] = preg_replace_callback("/[USER=([0-9]{1,})][/USER]/i", Array('BitrixImText', 'modifyShortUserTag'), $message['MESSAGE']);
}
$messages[$message['ID']] = Array(
'ID' => (int)$message['ID'],
'CHAT_ID' => (int)$chatId,
'AUTHOR_ID' => (int)$message['AUTHOR_ID'],
'DATE' => $message['DATE_CREATE'],
'TEXT' => (string)BitrixImText::parse($message['MESSAGE']),
'UNREAD' => $chatData['RELATION_USER_ID'] > 0 && $chatData['RELATION_LAST_ID'] < $message['ID'],
'UUID' => $message['MESSAGE_UUID'],
);
$messages[$message['ID']]['REPLACES'] = BitrixImText::getReplaceMap($messages[$message['ID']]['TEXT']);
if ($message['AUTHOR_ID'] && !isset($users[$message['AUTHOR_ID']]))
{
$user = User::getInstance($message['AUTHOR_ID'])->getArray($userOptions);
$user['last_activity_date'] = $message['USER_LAST_ACTIVITY_DATE']? date('c', $message['USER_LAST_ACTIVITY_DATE']->getTimestamp()): false;
$user['desktop_last_date'] = $message['USER_DESKTOP_LAST_DATE']? date('c', $message['USER_DESKTOP_LAST_DATE']->getTimestamp()): false;
$user['mobile_last_date'] = $message['USER_MOBILE_LAST_DATE']? date('c', $message['USER_MOBILE_LAST_DATE']->getTimestamp()): false;
$user['idle'] = $message['USER_IDLE']?: false;
$users[$message['AUTHOR_ID']] = $user;
}
if ($options['CONVERT_TEXT'])
{
$messages[$message['ID']]['TEXT_CONVERTED'] = BitrixImText::parseLegacyFormat($message['MESSAGE']);
}
}
$params = CIMMessageParam::Get(array_keys($messages));
$fileIds = Array();
foreach ($params as $messageId => $param)
{
$messages[$messageId]['PARAMS'] = empty($param)? []: $param;
if (
empty($messages[$messageId]['TEXT'])
&& !isset($param['FILE_ID'])
&& !isset($param['KEYBOARD'])
&& !isset($param['ATTACH'])
)
{
$messages[$messageId]['TEXT'] = Loc::getMessage('IM_CHAT_MESSAGE_DELETED');
$messages[$messageId]['PARAMS']['IS_DELETED'] = 'Y';
}
if (isset($param['FILE_ID']))
{
foreach ($param['FILE_ID'] as $fileId)
{
$fileIds[$fileId] = $fileId;
}
}
if (is_array($param['CHAT_USER']) > 0)
{
foreach ($param['CHAT_USER'] as $paramsUserId)
{
$users[$paramsUserId] = User::getInstance($paramsUserId)->getArray($userOptions);
}
}
}
$disappearing = DisappearService::getMessagesDisappearingTime(array_keys($messages));
foreach ($messages as $messageId => $message)
{
if (
isset($disappearing[$messageId])
&& $disappearing[$messageId]['DATE_REMOVE'] instanceof DateTime
)
{
$messages[$messageId]['DISAPPEARING_DATE'] = $disappearing[$messageId]['DATE_REMOVE']->format(DATE_ATOM);
}
else
{
$messages[$messageId]['DISAPPEARING_DATE'] = null;
}
}
$messages = CIMMessageLink::prepareShow($messages, $params);
$files = CIMDisk::GetFiles($chatId, $fileIds);
$result = Array(
'CHAT_ID' => (int)$chatId,
'MESSAGES' => $messages,
'USERS' => array_values($users),
'FILES' => array_values($files),
);
if (count($files) && $fileSort == 'DESC')
{
$result['FILES'] = array_reverse($result['FILES']);
}
if ($startFromUnread)
{
$result['MESSAGES'] = array_reverse($result['MESSAGES']);
$additionalMessages = self::getMessages($chatId, $userId, [
'LIMIT' => $limit,
'LAST_ID' => $chatData['RELATION_UNREAD_ID']
]);
$result['MESSAGES'] = array_merge($result['MESSAGES'], $additionalMessages['MESSAGES']);
}
if ($options['JSON'])
{
foreach ($result['MESSAGES'] as $key => $value)
{
if ($value['DATE'] instanceof BitrixMainTypeDateTime)
{
$result['MESSAGES'][$key]['DATE'] = date('c', $value['DATE']->getTimestamp());
}
if (isset($value['PARAMS']['CHAT_LAST_DATE']) && $value['PARAMS']['CHAT_LAST_DATE'] instanceof BitrixMainTypeDateTime)
{
$result['MESSAGES'][$key]['PARAMS']['CHAT_LAST_DATE'] = date('c', $value['PARAMS']['CHAT_LAST_DATE']->getTimestamp());
}
if (is_array($value['REPLACES']) && !empty($value['REPLACES']))
{
$result['MESSAGES'][$key]['REPLACES'] = Common::toJson($value['REPLACES']);
}
$result['MESSAGES'][$key] = array_change_key_case($result['MESSAGES'][$key], CASE_LOWER);
}
$result['MESSAGES'] = array_values($result['MESSAGES']);
foreach ($result['FILES'] as $key => $value)
{
if ($value['date'] instanceof BitrixMainTypeDateTime)
{
$result['FILES'][$key]['date'] = date('c', $value['date']->getTimestamp());
}
foreach (['urlPreview', 'urlShow', 'urlDownload'] as $field)
{
$url = $result['FILES'][$key][$field];
if (is_string($url) && $url && mb_strpos($url, 'http') !== 0)
{
$result['FILES'][$key][$field] = BitrixImCommon::getPublicDomain().$url;
}
}
}
$result = array_change_key_case($result, CASE_LOWER);
}
return $result;
}