• Модуль: im
  • Путь к файлу: ~/bitrix/modules/im/classes/general/im_chat.php
  • Класс: CIMChat
  • Вызов: CIMChat::GetLastMessage
function GetLastMessage($toChatId, $fromUserId = false, $loadExtraData = false, $bTimeZone = true, $limit = true)
{
	global $DB;

	$fromUserId = intval($fromUserId);
	if ($fromUserId <= 0)
		$fromUserId = $this->user_id;

	$toChatId = intval($toChatId);
	if ($toChatId <= 0)
	{
		$GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_EMPTY_CHAT_ID"), "ERROR_TO_CHAT_ID");
		return false;
	}

	$orm = IMModelChatTable::getById($toChatId);
	if (!($chatData = $orm->fetch()))
	{
		$GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_CHAT_NOT_EXISTS"), "ERROR_CHAT_NOT_EXISTS");
		return false;
	}

	if ($chatData['TYPE'] == IM_MESSAGE_OPEN && !CIMMessenger::CheckEnableOpenChat())
	{
		$GLOBALS["APPLICATION"]->ThrowException(GetMessage("IM_ERROR_CHAT_NOT_EXISTS"), "ERROR_CHAT_NOT_EXISTS");
		return false;
	}

	if ($limit)
	{
		if ($DB->type == "MYSQL")
			$sqlLimit = " AND M.DATE_CREATE > DATE_SUB(NOW(), INTERVAL 30 DAY)";
		elseif ($DB->type == "MSSQL")
			$sqlLimit = " AND M.DATE_CREATE > dateadd(day, -30, getdate())";
		elseif ($DB->type == "ORACLE")
			$sqlLimit = " AND M.DATE_CREATE > SYSDATE-30";
	}

	$readService = new IMV2MessageReadService($fromUserId);
	$lastMessageIdInChat = $readService->getLastMessageIdInChat($toChatId);
	$limitById = '';
	$limitFetchMessages = 30;
	$relations = CIMChat::GetRelationById($toChatId, false, $bTimeZone, false);
	if (isset($relations[$fromUserId]))
	{
		if ($relations[$fromUserId]['START_ID'] > 0)
		{
			$limitById = 'AND M.ID >= '.intval($relations[$fromUserId]['START_ID']);
		}

		//if ($relations[$fromUserId]['STATUS'] != IM_STATUS_READ && $relations[$fromUserId]['COUNTER'] > $limitFetchMessages)
		$messageCountFilter = BitrixMainORMQueryQuery::filter()
			->where('ID', '>=', (int)$relations[$fromUserId]['START_ID'])
			->where('ID', '>=', (int)$relations[$fromUserId]['LAST_ID'])
			->where('ID', '<=', $lastMessageIdInChat)
			->where('CHAT_ID', $toChatId)
		;
		$messageCount = BitrixImModelMessageTable::getCount($messageCountFilter);
		$limitFetchMessages = max($messageCount, 30);
	}

	if (!$bTimeZone)
		CTimeZone::Disable();

	$lineId = 0;
	$crmEntityType = null;
	$crmEntityId = null;
	if (
		$chatData['TYPE'] == IM_MESSAGE_OPEN_LINE
		&& BitrixMainLoader::includeModule('imopenlines')
	)
	{
		$explodeData = explode('|', $chatData['ENTITY_DATA_1']);
		$crmEntityType = ($explodeData[0] == 'Y') ? $explodeData[1] : null;
		$crmEntityId = ($explodeData[0] == 'Y') ? intval($explodeData[2]) : null;

		$lineId = BitrixImOpenLinesChat::parseLinesChatEntityId($chatData['ENTITY_ID'])['lineId'];
	}

	$strSql = "";
	if ($chatData['TYPE'] == IM_MESSAGE_OPEN)
	{
		$strSql = "
			SELECT
				M.ID,
				M.CHAT_ID,
				M.MESSAGE,
				".$DB->DatetimeToTimestampFunction('M.DATE_CREATE')." DATE_CREATE,
				M.AUTHOR_ID,
				C.TYPE CHAT_TYPE,
				C.ENTITY_TYPE CHAT_ENTITY_TYPE,
				R.USER_ID RID
			FROM b_im_message M
			INNER JOIN b_im_chat C ON C.ID = M.CHAT_ID AND C.TYPE = '".IM_MESSAGE_OPEN."'
			LEFT JOIN b_im_relation R ON R.CHAT_ID = M.CHAT_ID AND R.USER_ID = ".$fromUserId."
			WHERE
				M.CHAT_ID = ".$toChatId."
				".$limitById."
				#LIMIT#
			ORDER BY M.DATE_CREATE DESC
		";
	}
	else if (
		$chatData['TYPE'] == IM_MESSAGE_OPEN_LINE
		&& BitrixMainLoader::includeModule('imopenlines')
		&& BitrixImOpenLinesConfig::canJoin($lineId, $crmEntityType, $crmEntityId)
	)
	{
		$strSql = "
			SELECT
				M.ID,
				M.CHAT_ID,
				M.MESSAGE,
				".$DB->DatetimeToTimestampFunction('M.DATE_CREATE')." DATE_CREATE,
				M.AUTHOR_ID,
				C.TYPE CHAT_TYPE,
				C.ENTITY_TYPE CHAT_ENTITY_TYPE,
				R.USER_ID RID
			FROM b_im_message M
			INNER JOIN b_im_chat C ON C.ID = M.CHAT_ID AND C.TYPE = '".IM_MESSAGE_OPEN_LINE."'
			LEFT JOIN b_im_relation R ON R.CHAT_ID = M.CHAT_ID AND R.USER_ID = ".$fromUserId."
			WHERE
				M.CHAT_ID = ".$toChatId."
				".$limitById."
				#LIMIT#
			ORDER BY M.DATE_CREATE DESC
		";

		BitrixImDiskNoRelationPermission::add($toChatId, $fromUserId);
	}
	else if (isset($relations[$fromUserId]))
	{
		$strSql = "
			SELECT
				M.ID,
				M.CHAT_ID,
				M.MESSAGE,
				".$DB->DatetimeToTimestampFunction('M.DATE_CREATE')." DATE_CREATE,
				M.AUTHOR_ID,
				C.TYPE CHAT_TYPE,
				C.ENTITY_TYPE CHAT_ENTITY_TYPE,
				'".$fromUserId."' RID
			FROM b_im_message M
			INNER JOIN b_im_chat C ON C.ID = M.CHAT_ID
			WHERE
				M.CHAT_ID = ".$toChatId."
				".$limitById."
				#LIMIT#
			ORDER BY M.DATE_CREATE DESC
		";
	}

	if (!$bTimeZone)
		CTimeZone::Enable();

	$chatType = $chatData['TYPE'];
	$chatRelationUserId = 0;

	$arUsers = Array();
	$arMessages = Array();
	$arMessageId = Array();
	$arUsersMessage = Array();
	$arUnreadMessages = Array();
	$readedList = Array();

	if ($strSql)
	{
		$strSql = $DB->TopSql($strSql, $limitFetchMessages);
		//LEFT JOIN b_im_message_param MP on MP.MESSAGE_ID = M.ID and MP.PARAM_NAME = 'FOR_USER_ID'
		//and (MP.PARAM_VALUE is null or MP.PARAM_VALUE = '".$fromUserId."')

		if ($limit)
		{
			$dbRes = $DB->Query(str_replace("#LIMIT#", $sqlLimit, $strSql), false, "File: ".__FILE__."
Line: ".__LINE__); if (!$dbRes->SelectedRowsCount()) $dbRes = $DB->Query(str_replace("#LIMIT#", "", $strSql), false, "File: ".__FILE__."
Line: ".__LINE__); } else { $dbRes = $DB->Query(str_replace("#LIMIT#", "", $strSql), false, "File: ".__FILE__."
Line: ".__LINE__); } $lastReads = $readService ->getViewedService() ->getDateViewedByMessageIdForEachUser($lastMessageIdInChat, array_keys($relations)) ; while ($arRes = $dbRes->Fetch()) { if ($arRes['CHAT_ENTITY_TYPE'] != 'LIVECHAT' && BitrixImUser::getInstance($fromUserId)->isConnector()) { return false; } $arRes['CHAT_TYPE'] = trim($arRes['CHAT_TYPE']); $chatType = $arRes['CHAT_TYPE']; $chatRelationUserId = intval($arRes['RID']); $arMessages[$arRes['ID']] = Array( 'id' => $arRes['ID'], 'chatId' => $arRes['CHAT_ID'], 'senderId' => $arRes['AUTHOR_ID'], 'recipientId' => $arRes['CHAT_ID'], 'date' => BitrixMainTypeDateTime::createFromTimestamp($arRes['DATE_CREATE']), 'text' => BitrixImText::parse($arRes['MESSAGE']), 'textLegacy' => BitrixImText::parseLegacyFormat($arRes['MESSAGE']), ); $arMessageId[] = $arRes['ID']; if ($arRes['AUTHOR_ID'] > 0) { $arUsers[] = $arRes['AUTHOR_ID']; } if (isset($relations[$fromUserId]) && $relations[$fromUserId]['LAST_ID'] < $arRes['ID']) { $arUnreadMessages['chat'.$arRes['CHAT_ID']][] = $arRes['ID']; } $arUsersMessage[$arRes['CHAT_ID']][] = $arRes['ID']; foreach ($relations as $userId => $relation) { $readedList['chat'.$arRes['CHAT_ID']][$relation['USER_ID']] = Array( 'messageId' => $relation['LAST_ID'], 'date' => $lastReads[$userId] ?? null, ); } } foreach ($arUsersMessage as $chatId => $messageIds) { $arUsersMessage[$chatId] = array_values(array_unique($messageIds)); } } if ( $chatType == IM_MESSAGE_OPEN && $chatRelationUserId <= 0 || $chatType == IM_MESSAGE_OPEN_LINE && $chatRelationUserId <= 0 ) { if (IMUser::getInstance($fromUserId)->isExtranet()) { $arMessages = Array(); $arMessageId = Array(); $arUsersMessage = Array(); $loadExtraData = false; } else if (CModule::IncludeModule('pull')) { CPullWatch::Add($fromUserId, 'IM_PUBLIC_'.$toChatId, true); } } $params = CIMMessageParam::Get($arMessageId); $arFiles = Array(); foreach ($params as $messageId => $param) { $arMessages[$messageId]['params'] = $param; if ( mb_strlen($arMessages[$messageId]['text']) <= 0 && !isset($param['FILE_ID']) && !isset($param['KEYBOARD']) && !isset($param['ATTACH']) ) { $arMessages[$messageId]['text'] = GetMessage('IM_MESSAGE_DELETED'); $arMessages[$messageId]['params']['IS_DELETED'] = 'Y'; } if (isset($param['FILE_ID'])) { foreach ($param['FILE_ID'] as $fileId) { $arFiles[$fileId] = $fileId; } } } $arChatFiles = CIMDisk::GetFiles($toChatId, $arFiles); $arMessages = CIMMessageLink::prepareShow($arMessages, $params); $arResult = Array( 'chatId' => $toChatId, 'message' => $arMessages, 'usersMessage' => $arUsersMessage, 'unreadMessage' => $arUnreadMessages, 'users' => Array(), 'userInGroup' => Array(), 'readedList' => $readedList, 'files' => $arChatFiles ); if (is_array($loadExtraData) || is_bool($loadExtraData) && $loadExtraData == true) { $bDepartment = true; if (is_array($loadExtraData) && $loadExtraData['DEPARTMENT'] == 'N') $bDepartment = false; $arChat = self::GetChatData(array( 'ID' => $toChatId, 'USE_CACHE' => 'N' )); if ( isset($arChat['chat'][$toChatId]) && $arChat['chat'][$toChatId]['message_type'] == IM_MESSAGE_OPEN || isset($arChat['chat'][$toChatId]) && $arChat['chat'][$toChatId]['message_type'] == IM_MESSAGE_OPEN_LINE || isset($arChat['userInChat'][$toChatId]) && in_array($fromUserId, $arChat['userInChat'][$toChatId]) ) { $arResult['lines'] = $arChat['lines']; $arResult['userInChat'] = $arChat['userInChat']; $arResult['userChatBlockStatus'] = $arChat['userChatBlockStatus']; $ar = CIMContactList::GetUserData(array( 'ID' => array_values(array_merge($arUsers, $arChat['userInChat'][$toChatId])), 'DEPARTMENT' => ($bDepartment? 'Y': 'N'), 'USE_CACHE' => 'N' ) ); $arResult['users'] = $ar['users']; $arResult['userInGroup'] = $ar['userInGroup']; if ($arChat['chat'][$toChatId]['extranet'] === "") { $isExtranet = false; foreach ($ar['users'] as $userData) { if ($userData['extranet']) { $isExtranet = true; break; } } IMModelChatTable::update($toChatId, Array('EXTRANET' => $isExtranet? "Y":"N")); $arChat['chat'][$toChatId]['extranet'] = $isExtranet; } $arResult['chat'] = $arChat['chat']; } } if ($chatData['ENTITY_TYPE'] == 'LINES' && $chatData['ENTITY_ID'] && CModule::IncludeModule('imopenlines')) { [, $lineId] = explode('|', $chatData["ENTITY_ID"]); $configManager = new BitrixImOpenLinesConfig(); $arResult['openlines']['canVoteAsHead'][$lineId] = $configManager->canVoteAsHead($lineId); } else if ($chatData['ENTITY_TYPE'] == 'LIVECHAT' && $chatData['ENTITY_ID'] && CModule::IncludeModule('imopenlines')) { [$lineId, $userId] = explode('|', $chatData["ENTITY_ID"]); $userCode = 'livechat|' . $lineId . '|' . $chatData['ID'] . '|' . $userId; unset($lineId, $userId); foreach ($arResult['users'] as $userId => $userData) { $arResult['users'][$userId] = BitrixImOpenLinesConnector::getOperatorInfo($lineId, $userId, $userCode); } } return $arResult; }