2namespace Bitrix\Im\Integration\UI\EntitySelector;
5use Bitrix\Im\Model\ChatIndexTable;
6use Bitrix\Im\Model\ChatTable;
7use Bitrix\Im\Model\RelationTable;
9use Bitrix\Main\Config\Option;
10use Bitrix\Main\ORM\Fields\Relations\Reference;
11use Bitrix\Main\ORM\Query\Filter;
12use Bitrix\Main\ORM\Query\Join;
13use Bitrix\Main\ORM\Query\Query;
14use Bitrix\Main\Search\Content;
15use Bitrix\UI\EntitySelector\BaseProvider;
16use Bitrix\UI\EntitySelector\Dialog;
17use Bitrix\UI\EntitySelector\Item;
18use Bitrix\UI\EntitySelector\SearchQuery;
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);
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),
172 $query->where(Query::filter()
174 ->where(Query::filter()
177 ->where(
'USER_COUNT',
'>', 0)
179 ->where(
'RELATION.USER_ID', $currentUserId)
188 $query->setOrder([
'LAST_MESSAGE_ID' =>
'DESC']);
196 $chatsRaw =
$query->exec()->fetchAll();
203 if (!isset(
$options[
'searchableChatTypes']) || !is_array(
$options[
'searchableChatTypes']))
210 $query = ChatTable::query();
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);
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);
326 $query->setOrder([
'LAST_MESSAGE_ID' =>
'DESC']);
335 foreach (
$query->exec() as $chat)
337 $chatIdList[] = $chat[
'ID'];
346 foreach ($chats as $chat)
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)
502 $result =
$connection->query(
"SHOW INDEX FROM b_im_chat_index where Index_type = 'FULLTEXT' and Column_name = 'SEARCH_TITLE'");
506 $result =
$connection->query(
"select indexname from pg_indexes where tablename = 'b_im_chat_index' and indexdef like '%to_tsvector%search_title%'");
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())
static fillCounterData(array $chats)
static formatChatData($chat)
static addFilterBySearchQuery(Filter\ConditionTree $filter, string $searchQuery)
static getSearchableChatTypes()
const MAX_CHATS_IN_SAMPLE
__construct(array $options=[])
static isFulltextIndexExist()
static getChats(array $options=[])
fillDialog(Dialog $dialog)
const MAX_CHATS_IN_RECENT_TAB
getPreloadedChatsCollection()
getChatCollection(array $options=[])
getChatItems(array $options=[])
static makeItems(array $chats, array $options=[])
makeChatItems(array $chats, array $options=[])
getSelectedItems(array $ids)
doSearch(SearchQuery $searchQuery, Dialog $dialog)
static shouldSearchChatType(string $chatType, array $options=[])
static makeItem(array $chat, array $options=[])
static getInstance($userId=null)
static getConnection($name="")
getOption(string $option, $defaultValue=null)
addRecentItems(array $items)
setCacheable(bool $flag=true)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$GLOBALS['____1690880296']
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"