44 parent::__construct();
46 if (isset(
$options[
'searchableChatTypes']) && is_array(
$options[
'searchableChatTypes']))
48 foreach (
$options[
'searchableChatTypes'] as $chatType)
50 if (in_array($chatType, static::getSearchableChatTypes(),
true))
52 $this->options[
'searchableChatTypes'][] = $chatType;
57 $this->options[
'fillDialog'] =
true;
60 $this->options[
'fillDialog'] =
$options[
'fillDialog'];
63 $this->options[
'fillDialogWithDefaultValues'] =
true;
64 if (isset(
$options[
'fillDialogWithDefaultValues']) && is_bool(
$options[
'fillDialogWithDefaultValues']))
66 $this->options[
'fillDialogWithDefaultValues'] =
$options[
'fillDialogWithDefaultValues'];
72 return $GLOBALS[
'USER']->isAuthorized();
78 'searchQuery' => $searchQuery->
getQuery(),
79 'limit' => static::MAX_CHATS_IN_SAMPLE
82 $isLimitExceeded = static::MAX_CHATS_IN_SAMPLE <= count($items);
83 $isTooSmallToken = mb_strlen($searchQuery->
getQuery()) < Filter\Helper::getMinTokenSize();
84 if ($isLimitExceeded || $isTooSmallToken)
130 return static::getChatsByIds(
$options);
135 $options[
'chatIds'] = array_merge($groupChatAndOpenLineIds, $openChatIds);
137 return static::getChatsByIds(
$options);
140 private static function getChatsByIds(array
$options = []): array
149 $query = ChatTable::query();
152 ->addSelect(
'RELATION.USER_ID',
'RELATION_USER_ID')
153 ->addSelect(
'RELATION.NOTIFY_BLOCK',
'RELATION_NOTIFY_BLOCK')
155 ->addSelect(
'RELATION.START_COUNTER',
'RELATION_START_COUNTER')
159 ->addSelect(
'ALIAS.ALIAS',
'ALIAS_NAME')
162 $query->registerRuntimeField(
166 RelationTable::class,
167 Join::on(
'this.ID',
'ref.CHAT_ID')
168 ->where(
'ref.USER_ID', $currentUserId),
171 $query->whereIn(
'ID',
$options[
'chatIds']);
172 $query->where(Query::filter()
174 ->where(Query::filter()
177 ->where(
'USER_COUNT',
'>', 0)
179 ->where(
'RELATION.USER_ID', $currentUserId)
184 $query->setOrder(
$options[
'order']);
188 $query->setOrder([
'LAST_MESSAGE_ID' =>
'DESC']);
193 $query->setLimit(
$options[
'limit']);
196 $chatsRaw = $query->exec()->fetchAll();
201 private static function getChatIds(array
$options, array $chatTypes): array
203 if (!isset(
$options[
'searchableChatTypes']) || !is_array(
$options[
'searchableChatTypes']))
210 $query = ChatTable::query();
211 $query->addSelect(
'ID');
213 $searchQuery =
$options[
'searchQuery'] ??
'';
214 if (self::isValidSearchQuery($searchQuery))
216 $query->registerRuntimeField(
220 ChatIndexTable::class,
221 Join::on(
'this.ID',
'ref.CHAT_ID'),
222 [
'join_type' => Join::TYPE_INNER]
227 $filteredChatTypes = [];
228 $relationJoinType = Join::TYPE_INNER;
230 count($chatTypes) === 1
235 $relationJoinType = Join::TYPE_LEFT;
238 $query->registerRuntimeField(
242 RelationTable::class,
243 Join::on(
'this.ID',
'ref.CHAT_ID')->where(
'ref.USER_ID', $currentUserId),
244 [
'join_type' => $relationJoinType]
248 if (self::isValidSearchQuery($searchQuery))
250 $filter = Query::filter()->logic(
'and');
251 static::addFilterBySearchQuery($filter, $searchQuery);
252 $query->where($filter);
255 $chatTypesFilter = Query::filter()->logic(
'or');
265 ->where(Query::filter()
267 ->where(
'ENTITY_TYPE',
'!=',
'SUPPORT24_QUESTION')
268 ->whereNull(
'ENTITY_TYPE')
270 ->where(
'RELATION.USER_ID',
'=', $currentUserId)
273 $chatTypesFilter->where($groupChatFilter);
287 ->where(
'RELATION.USER_ID',
'=', $currentUserId)
290 $chatTypesFilter->where($openLineFilter);
305 $chatTypesFilter->where($channelFilter);
308 if (empty($filteredChatTypes))
313 $query->where($chatTypesFilter);
317 $query->whereIn(
'ID',
$options[
'chatIds']);
322 $query->setOrder(
$options[
'order']);
326 $query->setOrder([
'LAST_MESSAGE_ID' =>
'DESC']);
331 $query->setLimit(
$options[
'limit']);
335 foreach ($query->exec() as $chat)
337 $chatIdList[] = $chat[
'ID'];
346 foreach ($chats as $chat)
348 $result[] = static::makeItem($chat,
$options);
357 'id' => (
int)$chat[
'ID'],
358 'entityId' => static::getEntityId(),
359 'entityType' =>
Helper\Chat::getSelectorEntityType($chat),
360 'title' => $chat[
'TITLE'],
361 'avatar' => \CIMChat::GetAvatarImage($chat[
'AVATAR'], 200,
false),
371 !isset(
$options[
'searchableChatTypes'])
372 || !is_array(
$options[
'searchableChatTypes'])
380 $isExtranetUserRequest
387 return in_array($chatType,
$options[
'searchableChatTypes'],
true);
392 return $this->
getOption(
'fillDialog',
true);
402 if (!$this->
getOption(
'fillDialogWithDefaultValues',
true))
405 $recentItems = $dialog->
getRecentItems()->getEntityItems(static::getEntityId());
406 $recentIds = array_map(
'intval', array_keys($recentItems));
407 $recentChats = $this->fillRecentChats($recentChats, $recentIds, []);
419 $recentItems = $dialog->
getRecentItems()->getEntityItems(static::getEntityId());
420 $recentIds = array_map(
'intval', array_keys($recentItems));
421 $recentChats = $this->fillRecentChats($recentChats, $recentIds, $preloadedChats);
424 if (count($recentChats) < self::MAX_CHATS_IN_RECENT_TAB)
427 $recentGlobalIds = [];
429 if (!empty($recentGlobalItems))
431 $recentGlobalIds = array_map(
'intval', array_keys($recentGlobalItems));
432 $recentChatsIdList = array_column($recentChats,
'ID');
433 $recentGlobalIds = array_values(array_diff($recentGlobalIds, $recentChatsIdList));
434 $recentGlobalIds = array_slice(
437 self::MAX_CHATS_IN_RECENT_TAB - count($recentChats)
441 $recentChats = $this->fillRecentChats($recentChats, $recentGlobalIds, $preloadedChats);
445 foreach ($preloadedChats as $preloadedChat)
447 $recentChats[] = $preloadedChat;
456 'order' => [
'ID' =>
'DESC'],
457 'limit' => self::MAX_CHATS_IN_RECENT_TAB
461 private function fillRecentChats(array $recentChats, array $recentIds, array $preloadedChats): array
463 if (count($recentIds) < 1)
468 $chatIds = array_values(array_diff($recentIds, array_column($preloadedChats,
'ID')));
469 if (!empty($chatIds))
472 foreach ($chats as $chat)
474 $preloadedChats[] = $chat;
478 foreach ($recentIds as $recentId)
480 $chat = $preloadedChats[$recentId] ??
null;
483 $recentChats[] = $chat;
492 $isFulltextIndexExist = Option::get(
'im',
'search_title_fulltext_index_created',
'N') ===
'Y';
494 if ($isFulltextIndexExist)
499 $connection = \Bitrix\Main\Application::getConnection();
500 if ($connection->getType() ==
'mysql')
502 $result = $connection->query(
"SHOW INDEX FROM b_im_chat_index where Index_type = 'FULLTEXT' and Column_name = 'SEARCH_TITLE'");
504 elseif ($connection->getType() ==
'pgsql')
506 $result = $connection->query(
"select indexname from pg_indexes where tablename = 'b_im_chat_index' and indexdef like '%to_tsvector%search_title%'");
513 if ($result->fetch())
515 Option::set(
'im',
'search_title_fulltext_index_created',
'Y');
526 $searchQuery = trim($searchQuery);
528 if (empty($searchQuery) || mb_strlen($searchQuery) < Filter\Helper::getMinTokenSize())
533 if (!static::isFulltextIndexExist())
535 $filter->whereLike(
'CHAT_INDEX.SEARCH_TITLE', $searchQuery .
'%');
540 $searchText = Filter\Helper::matchAgainstWildcard(Content::prepareStringToken($searchQuery));
541 $filter->whereMatch(
'CHAT_INDEX.SEARCH_TITLE', $searchText);
544 private static function isValidSearchQuery(
string $searchQuery): bool
546 $searchQuery = trim($searchQuery);
547 if ($searchQuery ===
'')
552 if (mb_strlen($searchQuery) < Filter\Helper::getMinTokenSize())
$GLOBALS['____1444769544']