• Модуль: im
  • Путь к файлу: ~/bitrix/modules/im/lib/chat.php
  • Класс: BitrixImChat
  • Вызов: Chat::getMessages
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;
}