1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
botprovider.php
См. документацию.
1<?php
3
23
25{
26 public function __construct(array $options = [])
27 {
28 parent::__construct();
29
30 if (isset($options['searchableBotTypes']) && is_array($options['searchableBotTypes']))
31 {
32 $this->options['searchableBotTypes'] = $options['searchableBotTypes'];
33 }
34
35 $this->options['fillDialog'] = true;
36 if (isset($options['fillDialog']) && is_bool($options['fillDialog']))
37 {
38 $this->options['fillDialog'] = $options['fillDialog'];
39 }
40
41 $this->options['fillDialogWithDefaultValues'] = true;
42 if (isset($options['fillDialogWithDefaultValues']) && is_bool($options['fillDialogWithDefaultValues']))
43 {
44 $this->options['fillDialogWithDefaultValues'] = $options['fillDialogWithDefaultValues'];
45 }
46 }
47
48 public function isAvailable(): bool
49 {
50 return $GLOBALS['USER']->isAuthorized() && !User::getInstance()->isExtranet();
51 }
52
53 public function doSearch(SearchQuery $searchQuery, Dialog $dialog): void
54 {
55 $limit = 100;
56
57 $items = $this->getBotItems([
58 'searchQuery' => $searchQuery->getQuery(),
59 'limit' => $limit
60 ]);
61
62 $items = $this->filterHiddenBots($items);
63
64 $limitExceeded = $limit <= count($items);
65 if ($limitExceeded)
66 {
67 $searchQuery->setCacheable(false);
68 }
69
70 $dialog->addItems($items);
71 }
72
73 private function filterHiddenBots(array $items): array
74 {
75 foreach ($items as $key => $item)
76 {
78 if ($user instanceof UserBot && $user->isBot())
79 {
80 $botData = $user->getBotData()->toRestFormat();
81
82 if ($botData['isHidden'])
83 {
84 unset($items[$key]);
85 }
86 }
87 }
88
89 return $items;
90 }
91
92 public function shouldFillDialog(): bool
93 {
94 return $this->getOption('fillDialog', true);
95 }
96
97 public function getItems(array $ids): array
98 {
99 if (!$this->shouldFillDialog())
100 {
101 return [];
102 }
103
104 return $this->getBotItems([
105 'userId' => $ids,
106 ]);
107 }
108
109 public function getSelectedItems(array $ids): array
110 {
111 return $this->getItems($ids);
112 }
113
114 public function getBotItems(array $options = []): array
115 {
116 return $this->makeBotItems($this->getBotCollection($options), $options);
117 }
118
119 public function makeBotItems(EO_User_Collection $bots, array $options = []): array
120 {
121 return self::makeItems($bots, array_merge($this->getOptions(), $options));
122 }
123
125 {
126 $options = array_merge($this->getOptions(), $options);
127
128 return self::getBots($options);
129 }
130
131 public static function getBots(array $options = []): EO_User_Collection
132 {
133 $query = UserTable::query();
134
135 $query->setSelect([
136 'ID',
137 'NAME',
138 'LAST_NAME',
139 'SECOND_NAME',
140 'PERSONAL_PHOTO',
141 'WORK_POSITION',
142 'BOT_TYPE' => 'im_bot.TYPE',
143 'BOT_COUNT_MESSAGE' => 'im_bot.COUNT_MESSAGE',
144 ]);
145
146 $query->registerRuntimeField(
147 new Reference(
148 'im_bot',
149 BotTable::class,
150 Join::on('this.ID', 'ref.BOT_ID'),
151 ['join_type' => Join::TYPE_INNER]
152 )
153 );
154
155 if (!empty($options['searchQuery']) && is_string($options['searchQuery']))
156 {
157 $query->registerRuntimeField(
158 new Reference(
159 'USER_INDEX',
160 \Bitrix\Main\UserIndexTable::class,
161 Join::on('this.ID', 'ref.USER_ID'),
162 ['join_type' => 'INNER']
163 )
164 );
165
166 $query->whereMatch(
167 'USER_INDEX.SEARCH_USER_CONTENT',
168 Filter\Helper::matchAgainstWildcard(
169 Content::prepareStringToken($options['searchQuery']), '*', 1
170 )
171 );
172 }
173
174 if (isset($options['searchableBotTypes']) && is_array($options['searchableBotTypes']))
175 {
176 $query->whereIn('BOT_TYPE', $options['searchableBotTypes']);
177 }
178
179 $userIds = [];
180 $userFilter = isset($options['userId']) ? 'userId' : (isset($options['!userId']) ? '!userId' : null);
181 if (isset($options[$userFilter]))
182 {
183 if (is_array($options[$userFilter]) && !empty($options[$userFilter]))
184 {
185 foreach ($options[$userFilter] as $id)
186 {
187 $id = (int)$id;
188 if ($id > 0)
189 {
190 $userIds[] = $id;
191 }
192 }
193
194 $userIds = array_unique($userIds);
195
196 if (!empty($userIds))
197 {
198 if ($userFilter === 'userId')
199 {
200 $query->whereIn('ID', $userIds);
201 }
202 else
203 {
204 $query->whereNotIn('ID', $userIds);
205 }
206 }
207 }
208 else if (!is_array($options[$userFilter]) && (int)$options[$userFilter] > 0)
209 {
210 if ($userFilter === 'userId')
211 {
212 $query->where('ID', (int)$options[$userFilter]);
213 }
214 else
215 {
216 $query->whereNot('ID', (int)$options[$userFilter]);
217 }
218 }
219 }
220
221 if (isset($options['limit']) && is_int($options['limit']))
222 {
223 $query->setLimit($options['limit']);
224 }
225 else
226 {
227 $query->setLimit(100);
228 }
229
230 if (!empty($options['order']) && is_array($options['order']))
231 {
232 $query->setOrder($options['order']);
233 }
234 else
235 {
236 $query->setOrder([
237 'BOT_COUNT_MESSAGE' => 'DESC'
238 ]);
239 }
240
241 $result = $query->exec();
242
243 return $result->fetchCollection();
244 }
245
246 public static function makeItems(EO_User_Collection $bots, array $options = []): array
247 {
248 $result = [];
249 $isBitrix24 = ModuleManager::isModuleInstalled('bitrix24');
250
251 $currentUserId = \Bitrix\Im\V2\Entity\User\User::getCurrent()->getId() ?? 0;
252 $chatIds = \Bitrix\Im\Dialog::getChatIds($bots->getIdList(), $currentUserId);
253
254 foreach ($bots as $bot)
255 {
256 $botData = Bot::getCache($bot->getId());
257 if (
258 $isBitrix24
259 && $botData['TYPE'] === Bot::TYPE_NETWORK
260 && $botData['CLASS'] === 'Bitrix\ImBot\Bot\Support24'
261 )
262 {
263 continue;
264 }
265
266 $result[] = self::makeItem($bot, $options, ($chatIds[$bot->getId()] ?? 0));
267 }
268
269 return $result;
270 }
271
272 public static function makeItem(EO_User $bot, array $options = [], int $chatId = 0): Item
273 {
274 $defaultIcon =
275 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2228%22%20'
276 . 'height%3D%2228%22%20viewBox%3D%220%200%2028%2028%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20'
277 . 'fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Ccircle%20cx%3D%2214%22%20cy%3D%2214%22%20r%3D%2214%22%20'
278 . 'fill%3D%22%232FC6F6%22%2F%3E%0A%20%20%20%20%3Cpath%20'
279 . 'fill%3D%22%23FFFFFF%22%20d%3D%22M19.053132%2C10.0133936%20L19.9184066%2C7.09247624%20C19'
280 . '.9937984%2C6.83851954%2019.930205%2C6.56296095%2019.7515811%2C6.36960075%20C19.5729573%2C6'
281 . '.17624054%2019.3064404%2C6.09445472%2019.0524247%2C6.15505122%20C18.798409%2C6.21564772%2018'
282 . '.5954856%2C6.40942049%2018.5200937%2C6.66337719%20L17.7789513%2C9.17078557%20C15.4748028%2C7'
283 . '.94807693%2012.7275787%2C7.95098931%2010.4259431%2C9.17858062%20L9.68114981%2C6.66337719%20C9'
284 . '.56460406%2C6.27079414%209.15710205%2C6.04859979%208.77096861%2C6.16709222%20C8.38483517%2C6'
285 . '.28558465%208.16629117%2C6.69989319%208.28283693%2C7.09247624%20L9.15176243%2C10.0249005%20C7'
286 . '.2004503%2C11.6106349%206.0672511%2C14.0147948%206.0740137%2C16.5545557%20C6.0740137%2C21.1380463%209'
287 . '.67019697%2C20.0133316%2014.1097491%2C20.0133316%20C18.5493013%2C20.0133316%2022.1454845%2C21'
288 . '.1380463%2022.1454845%2C16.5545557%20C22.1533008%2C14.0079881%2021.0139427%2C11.5979375%2019'
289 . '.053132%2C10.0133936%20Z%20M14.1024472%2C15.9316939%20C10.9334248%2C15.9316939%208.36315777%2C16'
290 . '.2657676%208.36315777%2C14.9001487%20C8.36315777%2C13.5345299%2010.9334248%2C12.4257765%2014'
291 . '.1024472%2C12.4257765%20C17.2714696%2C12.4257765%2019.8453876%2C13.5334163%2019.8453876%2C14'
292 . '.9001487%20C19.8453876%2C16.2668812%2017.2751206%2C15.9316939%2014.1024472%2C15.9316939%20Z%20M11'
293 . '.477416%2C13.4487843%20C11.0249669%2C13.5328062%2010.7150974%2C13.9604811%2010.7703097%2C14'
294 . '.4247164%20C10.825522%2C14.8889517%2011.2267231%2C15.229209%2011.6858298%2C15.201166%20C12'
295 . '.1449365%2C15.1731231%2012.5031841%2C14.7864774%2012.5033322%2C14.3188606%20C12.4520761%2C13'
296 . '.7928552%2011.9955831%2C13.4057049%2011.477416%2C13.4487843%20Z%20M16.0191544%2C14.4269902%20C16'
297 . '.0754002%2C14.8911461%2016.4771659%2C15.230674%2016.9362856%2C15.2020479%20C17.3954053%2C15'
298 . '.1734219%2017.7533545%2C14.7865259%2017.7533947%2C14.3188606%20C17.7021533%2C13.7912874%2017'
299 . '.2433569%2C13.4035634%2016.7238275%2C13.4487843%20C16.2716033%2C13.5343137%2015.9629087%2C13'
300 . '.9628342%2016.0191544%2C14.4269902%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A'
301 ;
302
303 $imBot = Bot::getCache($bot->getId());
304
305 $customData = [
306 'imChat' => [
307 'TEXT_FIELD_ENABLED' => (new TextFieldEnabled($chatId))->get(),
308 'BACKGROUND_ID' => (new Background($chatId))->get(),
309 ],
310 'imUser' => User::getInstance($bot->getId())->getArray(),
311 'imBot' => [
312 'APP_ID' => $imBot['APP_ID'] ?? null,
313 'BOT_ID' => $imBot['BOT_ID'] ?? null,
314 'CODE' => $imBot['CODE'] ?? null,
315 'HIDDEN' => $imBot['HIDDEN'] ?? null,
316 'LANG' => $imBot['LANG'] ?? null,
317 'MODULE_ID' => $imBot['MODULE_ID'] ?? null,
318 'OPENLINE' => $imBot['OPENLINE'] ?? null,
319 'TYPE' => $imBot['TYPE'] ?? null,
320 'VERIFIED' => $imBot['VERIFIED'] ?? null,
321 ],
322 ];
323
324 if ($bot->getId() !== null)
325 {
326 $botData = BotData::getInstance($bot->getId())?->toRestFormat();
327 }
328
329 $customData['imUser']['BOT_DATA'] = (!empty($botData)) ? $botData : null;
330
331 $avatar = Helper\User::makeAvatar($bot);
332 if (!$avatar)
333 {
334 if ($customData['imUser']['COLOR'] !== '')
335 {
336 $avatar = str_replace(
337 '2FC6F6',
338 explode('#', $customData['imUser']['COLOR'])[1],
339 $defaultIcon
340 );
341 }
342 else
343 {
344 $avatar = $defaultIcon;
345 }
346 }
347
348 return new Item([
349 'id' => $bot->getId(),
350 'entityId' => 'im-bot',
351 'entityType' => Bot::getListForJs()[$bot->getId()]['type'],
352 'title' => Helper\User::formatName($bot, $options),
353 'avatar' => $avatar,
354 'customData' => $customData,
355 ]);
356 }
357
358 public function fillDialog(Dialog $dialog): void
359 {
360 if (!$this->shouldFillDialog())
361 {
362 return;
363 }
364
365 if (!$this->getOption('fillDialogWithDefaultValues', true))
366 {
367 $recentBots = new EO_User_Collection();
368 $recentItems = $dialog->getRecentItems()->getEntityItems('im-bot');
369 $recentIds = array_map('intval', array_keys($recentItems));
370 $this->fillRecentBots($recentBots, $recentIds, new EO_User_Collection());
371
372 $dialog->addRecentItems($this->makeBotItems($recentBots));
373
374 return;
375 }
376
377 $maxBotsInRecentTab = 50;
378
379 // Preload first 50 users ('doSearch' method has to have the same filter).
380 $preloadedBots = $this->getBotCollection([
381 'order' => ['ID' => 'DESC'],
382 'limit' => $maxBotsInRecentTab
383 ]);
384
385 if (count($preloadedBots) < $maxBotsInRecentTab)
386 {
387 // Turn off the user search
388 $entity = $dialog->getEntity('im-bot');
389 if ($entity)
390 {
391 $entity->setDynamicSearch(false);
392 }
393 }
394
395 $recentBots = new EO_User_Collection();
396
397 // Recent Items
398 $recentItems = $dialog->getRecentItems()->getEntityItems('im-bot');
399 $recentIds = array_map('intval', array_keys($recentItems));
400 $this->fillRecentBots($recentBots, $recentIds, $preloadedBots);
401
402 // Global Recent Items
403 if (count($recentBots) < $maxBotsInRecentTab)
404 {
405 $recentGlobalItems = $dialog->getGlobalRecentItems()->getEntityItems('im-bot');
406 $recentGlobalIds = [];
407
408 if (!empty($recentGlobalItems))
409 {
410 $recentGlobalIds = array_map('intval', array_keys($recentGlobalItems));
411 $recentGlobalIds = array_values(array_diff($recentGlobalIds, $recentBots->getIdList()));
412 $recentGlobalIds = array_slice($recentGlobalIds, 0, $maxBotsInRecentTab - $recentBots->count());
413 }
414
415 $this->fillRecentBots($recentBots, $recentGlobalIds, $preloadedBots);
416 }
417
418 // The rest of preloaded users
419 foreach ($preloadedBots as $preloadedBot)
420 {
421 $recentBots->add($preloadedBot);
422 }
423
424 $dialog->addRecentItems($this->makeBotItems($recentBots));
425 }
426
427 private function fillRecentBots(
428 EO_User_Collection $recentBots,
429 array $recentIds,
430 EO_User_Collection $preloadedBots
431 ): void
432 {
433 if (count($recentIds) < 1)
434 {
435 return;
436 }
437
438 $ids = array_values(array_diff($recentIds, $preloadedBots->getIdList()));
439
440 if (!empty($ids))
441 {
442 $bots = $this->getBotCollection([
443 'userId' => $ids,
444 ]);
445
446 foreach ($bots as $bot)
447 {
448 $preloadedBots->add($bot);
449 }
450 }
451
452 foreach ($recentIds as $recentId)
453 {
454 $bot = $preloadedBots->getByPrimary($recentId);
455 if ($bot)
456 {
457 $recentBots->add($bot);
458 }
459 }
460 }
461}
static getChatIds(array $dialogIds, int $currentUserId)
Определения dialog.php:135
static getBots(array $options=[])
Определения botprovider.php:131
makeBotItems(EO_User_Collection $bots, array $options=[])
Определения botprovider.php:119
static makeItems(EO_User_Collection $bots, array $options=[])
Определения botprovider.php:246
getBotCollection(array $options=[])
Определения botprovider.php:124
static makeItem(EO_User $bot, array $options=[], int $chatId=0)
Определения botprovider.php:272
doSearch(SearchQuery $searchQuery, Dialog $dialog)
Определения botprovider.php:53
Определения bot.php:38
static getInstance($userId=null)
Определения user.php:45
static getInstance(?int $id)
Определения BotData.php:34
static getCurrent()
Определения User.php:89
static getInstance(?int $id)
Определения User.php:72
Определения orm.php:16144
static isModuleInstalled($moduleName)
Определения modulemanager.php:125
Определения user.php:48
getOption(string $option, $defaultValue=null)
Определения baseprovider.php:48
getEntity(string $entityId)
Определения dialog.php:298
getGlobalRecentItems()
Определения dialog.php:251
addItems(array $items)
Определения dialog.php:135
addRecentItems(array $items)
Определения dialog.php:162
setCacheable(bool $flag=true)
Определения searchquery.php:72
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$entity
Определения contextmenu.php:9
$user
Определения mysql_to_pgsql.php:33
$GLOBALS['____1690880296']
Определения license.php:1
if(empty($signedUserToken)) $key
Определения quickway.php:257
</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."%"
Определения waybill.php:936
$items
Определения template.php:224