1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
userprovider.php
См. документацию.
1<?php
2
3namespace Bitrix\Socialnetwork\Integration\UI\EntitySelector;
4
5use Bitrix\Extranet\Enum\User\ExtranetRole;
6use Bitrix\Extranet\Model\ExtranetUserTable;
7use Bitrix\Extranet\Service\ServiceContainer;
8use Bitrix\HumanResources\Service\Container;
9use Bitrix\HumanResources\Util\StructureHelper;
10use Bitrix\Intranet\Integration\Mail\EmailUser;
11use Bitrix\Intranet\Internals\InvitationTable;
12use Bitrix\Intranet\Invitation;
13use Bitrix\Intranet\UserAbsence;
14use Bitrix\Main\Application;
15use Bitrix\Main\Config\Option;
16use Bitrix\Main\Engine\Router;
17use Bitrix\Main\Engine\UrlManager;
18use Bitrix\Main\Entity\Query;
19use Bitrix\Main\EO_User;
20use Bitrix\Main\EO_User_Collection;
21use Bitrix\Main\Loader;
22use Bitrix\Main\ModuleManager;
23use Bitrix\Main\ORM\Fields\ExpressionField;
24use Bitrix\Main\ORM\Query\Filter;
25use Bitrix\Main\ORM\Fields\Relations\Reference;
26use Bitrix\Main\ORM\Query\Join;
27use Bitrix\Main\Search\Content;
28use Bitrix\Main\UserTable;
29use Bitrix\Socialnetwork\Collab\CollabFeature;
30use Bitrix\Socialnetwork\Integration\HumanResources\EmployeeHelper;
31use Bitrix\Socialnetwork\UserToGroupTable;
32use Bitrix\Socialnetwork\WorkgroupSiteTable;
33use Bitrix\UI\EntitySelector\BaseProvider;
34use Bitrix\UI\EntitySelector\Dialog;
35use Bitrix\UI\EntitySelector\Item;
36use Bitrix\UI\EntitySelector\SearchQuery;
37
39{
40 protected const EXTRANET_ROLES = [
45 ];
46 protected const MAX_USERS_IN_RECENT_TAB = 50;
47 protected const SEARCH_LIMIT = 100;
48
49 protected const ENTITY_ID = 'user';
50
51 public function __construct(array $options = [])
52 {
53 parent::__construct();
55 }
56
57 protected function prepareOptions(array $options = []): void
58 {
59 if (isset($options['nameTemplate']) && is_string($options['nameTemplate']))
60 {
61 preg_match_all(
62 '/#NAME#|#LAST_NAME#|#SECOND_NAME#|#NAME_SHORT#|#SECOND_NAME_SHORT#|\s|,/',
63 urldecode($options['nameTemplate']),
65 );
66
67 $this->options['nameTemplate'] = implode('', $matches[0]);
68 }
69 else
70 {
71 $this->options['nameTemplate'] = \CSite::getNameFormat(false);
72 }
73
74 $this->options['analyticsSource'] = 'userProvider';
75 if (isset($options['analyticsSource']))
76 {
77 $this->options['analyticsSource'] = $options['analyticsSource'];
78 }
79
80 if (isset($options['onlyWithEmail']) && is_bool($options['onlyWithEmail']))
81 {
82 $this->options['onlyWithEmail'] = $options['onlyWithEmail'];
83 }
84
85 if (isset($options['extranetUsersOnly']) && is_bool($options['extranetUsersOnly']))
86 {
87 $this->options['extranetUsersOnly'] = $options['extranetUsersOnly'];
88 }
89
90 if (isset($options['intranetUsersOnly']) && is_bool($options['intranetUsersOnly']))
91 {
92 $this->options['intranetUsersOnly'] = $options['intranetUsersOnly'];
93 }
94
95 if (isset($options['footerInviteIntranetOnly']) && is_bool($options['footerInviteIntranetOnly']))
96 {
97 $this->options['footerInviteIntranetOnly'] = $options['footerInviteIntranetOnly'];
98 }
99
100 $this->options['showInvitationFooter'] = true;
101 if (isset($options['showInvitationFooter']) && is_bool($options['showInvitationFooter']))
102 {
103 $this->options['showInvitationFooter'] = $options['showInvitationFooter'];
104 }
105
106 $this->options['emailUsers'] = false;
107 if (isset($options['emailUsers']) && is_bool($options['emailUsers']))
108 {
109 $this->options['emailUsers'] = $options['emailUsers'];
110 }
111
112 $this->options['myEmailUsers'] = true;
113 if (isset($options['myEmailUsers']) && is_bool($options['myEmailUsers']))
114 {
115 $this->options['myEmailUsers'] = $options['myEmailUsers'];
116 }
117
118 if (isset($options['emailUsersOnly']) && is_bool($options['emailUsersOnly']))
119 {
120 $this->options['emailUsersOnly'] = $options['emailUsersOnly'];
121 }
122
123 $this->options['networkUsers'] = false;
124 if (isset($options['networkUsers']) && is_bool($options['networkUsers']))
125 {
126 $this->options['networkUsers'] = $options['networkUsers'];
127 }
128
129 if (isset($options['networkUsersOnly']) && is_bool($options['networkUsersOnly']))
130 {
131 $this->options['networkUsersOnly'] = $options['networkUsersOnly'];
132 }
133
134 $intranetInstalled = ModuleManager::isModuleInstalled('intranet');
135 $this->options['showLogin'] = $intranetInstalled;
136 $this->options['showEmail'] = $intranetInstalled;
137
138 $this->options['inviteEmployeeLink'] = true;
139 if (isset($options['inviteEmployeeLink']) && is_bool($options['inviteEmployeeLink']))
140 {
141 $this->options['inviteEmployeeLink'] = $options['inviteEmployeeLink'];
142 }
143
144 $this->options['inviteExtranetLink'] = false;
145 if (isset($options['inviteExtranetLink']) && is_bool($options['inviteExtranetLink']))
146 {
147 $this->options['inviteExtranetLink'] = $options['inviteExtranetLink'];
148 }
149
150 $this->options['inviteGuestLink'] = false;
151 if (isset($options['inviteGuestLink']) && is_bool($options['inviteGuestLink']))
152 {
153 $this->options['inviteGuestLink'] = $options['inviteGuestLink'];
154 }
155
156 $this->options['lockGuestLinkFeatureId'] = '';
157 if (isset($options['lockGuestLinkFeatureId']) && is_string($options['lockGuestLinkFeatureId']))
158 {
159 $this->options['lockGuestLinkFeatureId'] = $options['lockGuestLinkFeatureId'];
160 }
161
162 $this->options['lockGuestLink'] = false;
163 if (isset($options['lockGuestLink']) && is_bool($options['lockGuestLink']))
164 {
165 $this->options['lockGuestLink'] = $options['lockGuestLink'];
166 }
167
168 $this->options['collabers'] = true;
169 if (isset($options['collabers']) && is_bool($options['collabers']))
170 {
171 $this->options['collabers'] = $options['collabers'];
172 }
173
174 // User Whitelist
175 if (isset($options['userId']))
176 {
177 $ids = static::prepareUserIds($options['userId']);
178 if (!empty($ids))
179 {
180 $this->options['userId'] = $ids;
181 }
182 }
183
184 // User Blacklist
185 if (isset($options['!userId']))
186 {
187 $ids = static::prepareUserIds($options['!userId']);
188 if (!empty($ids))
189 {
190 $this->options['!userId'] = $ids;
191 }
192 }
193
194 if (isset($options['selectFields']) && is_array($options['selectFields']))
195 {
196 $selectFields = [];
197 $allowedFields = static::getAllowedFields();
198 foreach ($options['selectFields'] as $field)
199 {
200 if (is_string($field) && array_key_exists($field, $allowedFields))
201 {
202 $selectFields[] = $field;
203 }
204 }
205
206 $this->options['selectFields'] = array_unique($selectFields);
207 }
208
209 $this->options['fillDialog'] = true;
210 if (isset($options['fillDialog']) && is_bool($options['fillDialog']))
211 {
212 $this->options['fillDialog'] = $options['fillDialog'];
213 }
214
215 $this->options['maxUsersInRecentTab'] = static::MAX_USERS_IN_RECENT_TAB;
216 if (isset($options['maxUsersInRecentTab']) && is_int($options['maxUsersInRecentTab']))
217 {
218 $this->options['maxUsersInRecentTab'] = max(
219 1,
220 min($options['maxUsersInRecentTab'], static::MAX_USERS_IN_RECENT_TAB),
221 );
222 }
223
224 $this->options['searchLimit'] = static::SEARCH_LIMIT;
225 if (isset($options['searchLimit']) && is_int($options['searchLimit']))
226 {
227 $this->options['searchLimit'] = max(1, min($options['searchLimit'], static::SEARCH_LIMIT));
228 }
229 }
230
231 public function isAvailable(): bool
232 {
233 if (!$GLOBALS['USER']->isAuthorized())
234 {
235 return false;
236 }
237
238 $intranetInstalled = ModuleManager::isModuleInstalled('intranet');
239 if ($intranetInstalled)
240 {
242 }
243
244 return \Bitrix\Socialnetwork\ComponentHelper::getModuleUsed();
245 }
246
247 public function shouldFillDialog(): bool
248 {
249 return $this->getOption('fillDialog', true);
250 }
251
252 public function getItems(array $ids): array
253 {
254 if (!$this->shouldFillDialog())
255 {
256 return [];
257 }
258
259 return $this->getUserItems([
260 'userId' => $ids,
261 ]);
262 }
263
264 public function getSelectedItems(array $ids): array
265 {
266 return $this->getUserItems([
267 'userId' => $ids,
268 'ignoreUserWhitelist' => true,
269 'activeUsers' => null, // to see fired employees
270 ]);
271 }
272
273 public function fillDialog(Dialog $dialog): void
274 {
275 if (!$this->shouldFillDialog())
276 {
277 return;
278 }
279
280 // Preload first 50 users ('doSearch' method has to have the same filter).
281 $preloadedUsers = $this->getPreloadedUsersCollection();
282
283 if ($preloadedUsers->count() < $this->options['maxUsersInRecentTab'])
284 {
285 // Turn off the user search
286 $entity = $dialog->getEntity(static::ENTITY_ID);
287 if ($entity)
288 {
289 $entity->setDynamicSearch(false);
290 }
291 }
292
293 $recentUsers = new EO_User_Collection();
294
295 // Recent Items
296 $recentItems = $dialog->getRecentItems()->getEntityItems(static::ENTITY_ID);
297 $recentIds = array_map('intval', array_keys($recentItems));
298 $this->fillRecentUsers($recentUsers, $recentIds, $preloadedUsers);
299
300 // Global Recent Items
301 if ($recentUsers->count() < $this->options['maxUsersInRecentTab'])
302 {
303 $recentGlobalItems = $dialog->getGlobalRecentItems()->getEntityItems(static::ENTITY_ID);
304 $recentGlobalIds = [];
305
306 if (!empty($recentGlobalItems))
307 {
308 $recentGlobalIds = array_map('intval', array_keys($recentGlobalItems));
309 $recentGlobalIds = array_values(array_diff($recentGlobalIds, $recentUsers->getIdList()));
310 $recentGlobalIds = array_slice($recentGlobalIds, 0, $this->options['maxUsersInRecentTab'] - $recentUsers->count());
311 }
312
313 $this->fillRecentUsers($recentUsers, $recentGlobalIds, $preloadedUsers);
314 }
315
316 // The rest of preloaded users
317 foreach ($preloadedUsers as $preloadedUser)
318 {
319 $recentUsers->add($preloadedUser);
320 }
321
322 $dialog->addRecentItems($this->makeUserItems($recentUsers));
323
324 // Footer
325 if ($this->options['showInvitationFooter'] && Loader::includeModule('intranet'))
326 {
327 $inviteEmployeeLink = null;
328 $employeeInvitationAvailable = Invitation::canCurrentUserInvite();
329 $intranetUsersOnly = $this->options['intranetUsersOnly'] ?? false;
330 $footerInviteIntranetOnly = $this->options['footerInviteIntranetOnly'] ?? CollabFeature::isOn();
331 $extranetInvitationAvailable = (
332 ModuleManager::isModuleInstalled('extranet')
333 && Option::get('extranet', 'extranet_site')
334 && !$intranetUsersOnly
335 && !$footerInviteIntranetOnly
336 );
337
338 if (
339 $this->options['inviteEmployeeLink']
340 && (
341 $employeeInvitationAvailable
342 || $extranetInvitationAvailable
343 )
344 && self::isIntranetUser()
345 )
346 {
347
348 $inviteEmployeeLink = UrlManager::getInstance()->create('getSliderContent', [
349 'c' => 'bitrix:intranet.invitation',
350 'mode' => Router::COMPONENT_MODE_AJAX,
351 'analyticsLabel[source]' => $this->options['analyticsSource'],
352 'analyticsLabel[tool]' => 'Invitation',
353 'analyticsLabel[category]' => 'invitation',
354 'analyticsLabel[event]' => 'drawer_open',
355 'analyticsLabel[c_section]' => $this->options['analyticsSource'],
356 ]);
357 }
358
359 $inviteGuestLink = null;
360 if ($this->options['inviteGuestLink'] && ModuleManager::isModuleInstalled('mail') && self::isIntranetUser())
361 {
362 $inviteGuestLink = UrlManager::getInstance()->create('getSliderContent', [
363 'c' => 'bitrix:intranet.invitation.guest',
364 'mode' => Router::COMPONENT_MODE_AJAX,
365 ]);
366 }
367
368 if ($inviteEmployeeLink || $inviteGuestLink)
369 {
370 $footerOptions = [];
371 if ($dialog->getFooter() === 'BX.SocialNetwork.EntitySelector.Footer')
372 {
373 // Footer could be set from ProjectProvider
374 $footerOptions = $dialog->getFooterOptions() ?? [];
375 }
376
377 $footerOptions['inviteEmployeeLink'] = $inviteEmployeeLink;
378 $footerOptions['inviteGuestLink'] = $inviteGuestLink;
379 if ($inviteEmployeeLink)
380 {
381 $footerOptions['inviteEmployeeScope'] = ($employeeInvitationAvailable ? 'I' : '').($extranetInvitationAvailable ? 'E' : '');
382 }
383
384 if ($inviteGuestLink && $this->options['lockGuestLink'])
385 {
386 $footerOptions['lockGuestLink'] = true;
387 $footerOptions['lockGuestLinkFeatureId'] = $this->options['lockGuestLinkFeatureId'] ?? '';
388 }
389
390 $dialog->setFooter('BX.SocialNetwork.EntitySelector.Footer', $footerOptions);
391 }
392 }
393 }
394
396 {
397 return $this->getUserCollection([
398 'order' => ['ID' => 'asc'],
399 'limit' => $this->options['maxUsersInRecentTab'],
400 ]);
401 }
402
403 private function fillRecentUsers(
404 EO_User_Collection $recentUsers,
405 array $recentIds,
406 EO_User_Collection $preloadedUsers,
407 ): void
408 {
409 if (count($recentIds) < 1)
410 {
411 return;
412 }
413
414 $ids = array_values(array_diff($recentIds, $preloadedUsers->getIdList()));
415 if (!empty($ids))
416 {
417 $users = $this->getUserCollection(['userId' => $ids]);
418 foreach ($users as $user)
419 {
420 $preloadedUsers->add($user);
421 }
422 }
423
424 foreach ($recentIds as $recentId)
425 {
426 $user = $preloadedUsers->getByPrimary($recentId);
427 if ($user)
428 {
429 $recentUsers->add($user);
430 }
431 }
432 }
433
434 public function doSearch(SearchQuery $searchQuery, Dialog $dialog): void
435 {
436 $atom = '=_0-9a-z+~\'!\$&*^`|\\#%/?{}-';
437 $isEmailLike = (bool)preg_match('#^['.$atom.']+(\\.['.$atom.']+)*@#i', $searchQuery->getQuery());
438
439 if ($isEmailLike)
440 {
441 $items = $this->getUserItems([
442 'searchByEmail' => $searchQuery->getQuery(),
443 'myEmailUsers' => false,
444 'limit' => $this->options['searchLimit'],
445 ]);
446 }
447 else
448 {
449 $items = $this->getUserItems([
450 'searchQuery' => $searchQuery->getQuery(),
451 'limit' => $this->options['searchLimit'],
452 ]);
453 }
454
455 $limitExceeded = ($this->options['searchLimit'] <= count($items));
456 if ($limitExceeded)
457 {
458 $searchQuery->setCacheable(false);
459 }
460
461 $dialog->addItems($items);
462 }
463
464 public function handleBeforeItemSave(Item $item): void
465 {
466 if ($item->getEntityType() === 'email')
467 {
468 $user = UserTable::getById($item->getId())->fetchObject();
469 if ($user && $user->getExternalAuthId() === 'email' && Loader::includeModule('intranet'))
470 {
471 EmailUser::invite($user->getId());
472 }
473 }
474 }
475
477 {
478 $dialogOptions = $this->getOptions();
479 $options = array_merge($dialogOptions, $options);
480
481 $ignoreUserWhitelist = isset($options['ignoreUserWhitelist']) && $options['ignoreUserWhitelist'] === true;
482 if (!empty($dialogOptions['userId']) && !$ignoreUserWhitelist)
483 {
484 $options['userId'] = $dialogOptions['userId'];
485 }
486
487 static $usersCache = [];
488
489 $cacheKey = md5(serialize($options));
490
491 if (!isset($usersCache[$cacheKey]))
492 {
493 $usersCache[$cacheKey] = static::getUsers($options);
494 }
495
496 return $usersCache[$cacheKey];
497 }
498
499 public function getUserItems(array $options = []): array
500 {
501 return $this->makeUserItems($this->getUserCollection($options), $options);
502 }
503
504 public function makeUserItems(EO_User_Collection $users, array $options = []): array
505 {
506 return self::makeItems($users, array_merge($this->getOptions(), $options));
507 }
508
509 public static function isIntranetUser(int $userId = null): bool
510 {
511 return self::hasUserRole($userId, 'intranet');
512 }
513
514 public static function isExtranetUser(int $userId = null): bool
515 {
516 return self::hasUserRole($userId, 'extranet');
517 }
518
519 public static function getCurrentUserId(): int
520 {
521 return is_object($GLOBALS['USER']) ? (int)$GLOBALS['USER']->getId() : 0;
522 }
523
524 private static function hasUserRole(?int $userId, string $role): bool
525 {
526 static $roles = [
527 'intranet' => [],
528 'extranet' => [],
529 ];
530
531 if (!isset($roles[$role]) || !ModuleManager::isModuleInstalled('intranet'))
532 {
533 return false;
534 }
535
536 if (is_null($userId))
537 {
539 if ($userId <= 0)
540 {
541 return false;
542 }
543 }
544
545 if (
546 $userId === self::getCurrentUserId()
547 && \CSocNetUser::isCurrentUserModuleAdmin()
548 )
549 {
550 return true;
551 }
552
553 if (isset($roles[$role][$userId]))
554 {
555 return $roles[$role][$userId];
556 }
557
558 $cacheId = 'UserRole:'.$role;
559 $cachePath = '/external_user_info/'.substr(md5($userId),-2).'/'.$userId.'/';
560 $cache = Application::getInstance()->getCache();
561 $ttl = 2592000; // 1 month
562
563 if ($cache->initCache($ttl, $cacheId, $cachePath))
564 {
565 $roles[$role][$userId] = (bool)$cache->getVars();
566 }
567 else
568 {
569 $cache->startDataCache();
570
571 $taggedCache = Application::getInstance()->getTaggedCache();
572 $taggedCache->startTagCache($cachePath);
573 $taggedCache->registerTag('USER_NAME_'.$userId);
574 $taggedCache->endTagCache();
575
576 $filter = [
577 '=ID' => $userId,
578 '=IS_REAL_USER' => true,
579 ];
580
581 if ($role === 'intranet')
582 {
583 $filter['!UF_DEPARTMENT'] = false;
584 }
585 else if ($role === 'extranet')
586 {
587 $filter['UF_DEPARTMENT'] = false;
588 }
589
590 $roles[$role][$userId] =
591 UserTable::getList(['select' => ['ID'], 'filter' => $filter])
592 ->fetchCollection()->count() === 1
593 ;
594
595 $cache->endDataCache($roles[$role][$userId]);
596 }
597
598 return $roles[$role][$userId];
599 }
600
601 public static function isIntegrator(int $userId = null): bool
602 {
603 static $integrators;
604
605 if ($integrators === null)
606 {
607 $integrators = [];
608 if (Loader::includeModule('bitrix24'))
609 {
610 $integrators = array_fill_keys(\Bitrix\Bitrix24\Integrator::getIntegratorsId(), true);
611 }
612 }
613
614 if (is_null($userId))
615 {
617 if ($userId <= 0)
618 {
619 return false;
620 }
621 }
622
623 return isset($integrators[$userId]);
624 }
625
626 public static function getAllowedFields(): array
627 {
628 static $fields = null;
629
630 if ($fields !== null)
631 {
632 return $fields;
633 }
634
635 $fields = [
636 'lastName' => 'LAST_NAME',
637 'name' => 'NAME',
638 'secondName' => 'SECOND_NAME',
639 'login' => 'LOGIN',
640 'email' => 'EMAIL',
641 'title' => 'TITLE',
642 'position', 'WORK_POSITION',
643 'lastLogin' => 'LAST_LOGIN',
644 'dateRegister' => 'DATE_REGISTER',
645 'lastActivityDate' => 'LAST_ACTIVITY_DATE',
646 'online' => 'IS_ONLINE',
647 'profession' => 'PERSONAL_PROFESSION',
648 'www' => 'PERSONAL_WWW',
649 'birthday' => 'PERSONAL_BIRTHDAY',
650 'icq' => 'PERSONAL_ICQ',
651 'phone' => 'PERSONAL_PHONE',
652 'fax' => 'PERSONAL_FAX',
653 'mobile' => 'PERSONAL_MOBILE',
654 'pager' => 'PERSONAL_PAGER',
655 'street' => 'PERSONAL_STREET',
656 'city' => 'PERSONAL_CITY',
657 'state' => 'PERSONAL_STATE',
658 'zip' => 'PERSONAL_ZIP',
659 'mailbox' => 'PERSONAL_MAILBOX',
660 'country' => 'PERSONAL_COUNTRY',
661 'timeZoneOffset' => 'TIME_ZONE_OFFSET',
662 'company' => 'WORK_COMPANY',
663 'workPhone' => 'WORK_PHONE',
664 'workDepartment' => 'WORK_DEPARTMENT',
665 'workPosition' => 'WORK_POSITION',
666 'workCity' => 'WORK_CITY',
667 'workCountry' => 'WORK_COUNTRY',
668 'workStreet' => 'WORK_STREET',
669 'workState' => 'WORK_STATE',
670 'workZip' => 'WORK_ZIP',
671 'workMailbox' => 'WORK_MAILBOX',
672 ];
673
674 foreach ($fields as $id => $dbName)
675 {
676 if (mb_strpos($dbName, 'PERSONAL_') === 0)
677 {
678 $fields['personal' . ucfirst($id)] = $dbName;
679 }
680
681 $fields[$dbName] = $dbName;
682 }
683
684 $intranetInstalled = ModuleManager::isModuleInstalled('intranet');
685 if ($intranetInstalled)
686 {
687 $userFields = $GLOBALS['USER_FIELD_MANAGER']->GetUserFields('USER');
688 $allowedUserFields = [
689 'ufPhoneInner' => 'UF_PHONE_INNER',
690 'ufDistrict' => 'UF_DISTRICT',
691 'ufSkype' => 'UF_SKYPE',
692 'ufSkypeLink' => 'UF_SKYPE_LINK',
693 'ufZoom' => 'UF_ZOOM',
694 'ufTwitter' => 'UF_TWITTER',
695 'ufFacebook' => 'UF_FACEBOOK',
696 'ufLinkedin' => 'UF_LINKEDIN',
697 'ufXing' => 'UF_XING',
698 'ufWebSites' => 'UF_WEB_SITES',
699 'ufSkills' => 'UF_SKILLS',
700 'ufInterests' => 'UF_INTERESTS',
701 'ufEmploymentDate' => 'UF_EMPLOYMENT_DATE',
702 ];
703
704 foreach ($allowedUserFields as $id => $dbName)
705 {
706 if (array_key_exists($dbName, $userFields))
707 {
708 $fields[$id] = $dbName;
709 $fields[$dbName] = $dbName;
710 }
711 }
712 }
713
714 return $fields;
715 }
716
717 public static function getUsers(array $options = []): EO_User_Collection
718 {
719 $query = static::getQuery($options);
720 //echo '<pre>'.$query->getQuery().'</pre>';
721
722 $result = $query->exec();
723
724 return $result->fetchCollection();
725 }
726
727 protected static function getQuery(array $options = []): Query
728 {
729 $selectFields = [
730 'ID', 'ACTIVE', 'LAST_NAME', 'NAME', 'SECOND_NAME', 'LOGIN', 'EMAIL', 'TITLE',
731 'PERSONAL_GENDER', 'PERSONAL_PHOTO', 'WORK_POSITION',
732 'CONFIRM_CODE', 'EXTERNAL_AUTH_ID',
733 ];
734
735 if (isset($options['selectFields']) && is_array($options['selectFields']))
736 {
737 $allowedFields = static::getAllowedFields();
738 foreach ($options['selectFields'] as $field)
739 {
740 if (is_string($field) && array_key_exists($field, $allowedFields))
741 {
742 $selectFields[] = $allowedFields[$field];
743 }
744 }
745 }
746
747 $query = UserTable::query();
748 $query->setSelect(array_unique($selectFields));
749
750 $intranetInstalled = ModuleManager::isModuleInstalled('intranet');
751 if ($intranetInstalled)
752 {
753 $query->addSelect('UF_DEPARTMENT');
754 }
755
756 $activeUsers = array_key_exists('activeUsers', $options) ? $options['activeUsers'] : true;
757 if (is_bool($activeUsers))
758 {
759 $query->where('ACTIVE', $activeUsers ? 'Y' : 'N');
760 }
761
762 if (isset($options['onlyWithEmail']) && is_bool(isset($options['onlyWithEmail'])))
763 {
764 $query->addFilter(($options['onlyWithEmail'] ? '!' : '').'EMAIL', false);
765 }
766
767 if (isset($options['invitedUsers']) && is_bool(isset($options['invitedUsers'])))
768 {
769 $query->addFilter(($options['invitedUsers'] ? '!' : '').'CONFIRM_CODE', false);
770 }
771
772 if (!empty($options['searchQuery']) && is_string($options['searchQuery']))
773 {
774 $query->registerRuntimeField(
775 new Reference(
776 'USER_INDEX',
777 \Bitrix\Main\UserIndexTable::class,
778 Join::on('this.ID', 'ref.USER_ID'),
779 ['join_type' => 'INNER'],
780 ),
781 );
782
783 $query->whereMatch(
784 'USER_INDEX.SEARCH_USER_CONTENT',
785 Filter\Helper::matchAgainstWildcard(
786 Content::prepareStringToken($options['searchQuery']), '*', 1,
787 ),
788 );
789 }
790 else if (!empty($options['searchByEmail']) && is_string($options['searchByEmail']))
791 {
792 $query->whereLike('EMAIL', $options['searchByEmail'].'%');
793 }
794
795 $currentUserId = (
796 !empty($options['currentUserId']) && is_int($options['currentUserId'])
797 ? $options['currentUserId']
798 : $GLOBALS['USER']->getId()
799 );
800
801 $isIntranetUser = $intranetInstalled && self::isIntranetUser($currentUserId);
802 if ($intranetInstalled)
803 {
804 $emptyValue = serialize([]);
805 $emptyValue2 = serialize([0]);
806
807 $query->registerRuntimeField(new ExpressionField(
808 'IS_INTRANET_USER',
809 'CASE WHEN
810 (%s IS NOT NULL AND %s != \'' . $emptyValue . '\' AND %s != \'' . $emptyValue2 . '\') AND
811 (%s IS NULL OR %s NOT IN (\'' . implode('\', \'', UserTable::getExternalUserTypes()) . '\'))
812 THEN \'Y\'
813 ELSE \'N\'
814 END',
815 ['UF_DEPARTMENT', 'UF_DEPARTMENT', 'UF_DEPARTMENT', 'EXTERNAL_AUTH_ID', 'EXTERNAL_AUTH_ID']),
816 );
817
818 $query->registerRuntimeField(new ExpressionField(
819 'IS_EXTRANET_USER',
820 'CASE WHEN
821 (%s IS NULL OR %s = \'' . $emptyValue . '\' OR %s = \'' . $emptyValue2 . '\') AND
822 (%s IS NULL OR %s NOT IN (\'' . implode('\', \'', UserTable::getExternalUserTypes()) . '\'))
823 THEN \'Y\'
824 ELSE \'N\'
825 END',
826 ['UF_DEPARTMENT', 'UF_DEPARTMENT', 'UF_DEPARTMENT', 'EXTERNAL_AUTH_ID', 'EXTERNAL_AUTH_ID']),
827 );
828
829 $query->registerRuntimeField(
830 new Reference(
831 'INVITATION',
832 InvitationTable::class,
833 Join::on('this.ID', 'ref.USER_ID')->where('ref.ORIGINATOR_ID', $currentUserId),
834 ['join_type' => 'LEFT'],
835 ),
836 );
837
838 $extranetUsersQuery = (empty($options['searchByEmail']) ? self::getExtranetUsersQuery($currentUserId) : null);
839
840 $intranetUsersOnly = isset($options['intranetUsersOnly']) && $options['intranetUsersOnly'] === true;
841 $extranetUsersOnly = isset($options['extranetUsersOnly']) && $options['extranetUsersOnly'] === true;
842 $emailUsersOnly = isset($options['emailUsersOnly']) && $options['emailUsersOnly'] === true;
843 $networkUsersOnly = isset($options['networkUsersOnly']) && $options['networkUsersOnly'] === true;
844
845 $emailUsers =
846 isset($options['emailUsers']) && is_bool($options['emailUsers']) ? $options['emailUsers'] : true
847 ;
848
849 $myEmailUsers =
850 isset($options['myEmailUsers']) && is_bool($options['myEmailUsers']) && $options['myEmailUsers']
851 ;
852
853 $networkUsers =
854 !(isset($options['networkUsers']) && is_bool($options['networkUsers'])) || $options['networkUsers']
855 ;
856
857 if ($isIntranetUser)
858 {
859 if (isset($options['departmentId']) && is_int($options['departmentId']))
860 {
861 $query->addFilter('UF_DEPARTMENT', $options['departmentId']);
862 }
863
864 if ($emailUsersOnly)
865 {
866 $query->where('EXTERNAL_AUTH_ID', 'email');
867 if ($myEmailUsers)
868 {
869 $query->whereNotNull('INVITATION.ID');
870 }
871 }
872 else if ($networkUsersOnly)
873 {
874 $query->where('EXTERNAL_AUTH_ID', 'replica');
875 }
876 else if ($intranetUsersOnly)
877 {
878 $query->where('IS_INTRANET_USER', 'Y');
879 }
880 else if ($extranetUsersOnly)
881 {
882 $query->where('IS_EXTRANET_USER', 'Y');
883 if ($extranetUsersQuery)
884 {
885 $query->whereIn('ID', $extranetUsersQuery);
886 }
887 }
888 else
889 {
890 $filter = Query::filter()->logic('or');
891
892 if (
893 empty($options['searchByEmail'])
894 && !\CSocNetUser::isCurrentUserModuleAdmin()
895 )
896 {
897 $filter->where('IS_INTRANET_USER', 'Y');
898 }
899 else
900 {
901 $filter->addCondition(Query::filter()
902 ->logic('or')
903 ->whereNotIn('EXTERNAL_AUTH_ID', UserTable::getExternalUserTypes())
904 ->whereNull('EXTERNAL_AUTH_ID'),
905 );
906 }
907
908 if ($emailUsers === true)
909 {
910 if ($myEmailUsers)
911 {
912 $filter->addCondition(Query::filter()
913 ->where('EXTERNAL_AUTH_ID', 'email')
914 ->whereNotNull('INVITATION.ID'),
915 );
916 }
917 else
918 {
919 $filter->where('EXTERNAL_AUTH_ID', 'email');
920 }
921 }
922
923 if ($networkUsers === true)
924 {
925 $filter->where('EXTERNAL_AUTH_ID', 'replica');
926 }
927
928 if ($extranetUsersQuery)
929 {
930 $filter->whereIn('ID', $extranetUsersQuery);
931 $filter->addCondition(Query::filter()
932 ->where(Query::filter()
933 ->logic('or')
934 ->whereNull('EXTERNAL_AUTH_ID')
935 ->whereNot('EXTERNAL_AUTH_ID', 'email'),
936 )
937 ->whereNotNull('INVITATION.ID'),
938 );
939 }
940
941 $query->where($filter);
942 }
943 }
944 else
945 {
946 if ($intranetUsersOnly)
947 {
948 $query->where('IS_INTRANET_USER', 'Y');
949 }
950 else if ($extranetUsersOnly)
951 {
952 $query->where('IS_EXTRANET_USER', 'Y');
953 }
954 else
955 {
956 $query->addFilter('!=EXTERNAL_AUTH_ID', UserTable::getExternalUserTypes());
957 }
958
959 if ($extranetUsersQuery)
960 {
961 $query->whereIn('ID', $extranetUsersQuery);
962 }
963 else
964 {
965 $query->where(new ExpressionField('EMPTY_LIST', '1'), '!=', 1);
966 }
967 }
968 }
969 else
970 {
971 $query->addFilter('!=EXTERNAL_AUTH_ID', UserTable::getExternalUserTypes());
972 }
973
974 if (!($options['collabers'] ?? true) && Loader::includeModule('extranet'))
975 {
976 $query->registerRuntimeField(
977 new Reference(
978 'EXTRANET_USER',
979 ExtranetUserTable::class,
980 Join::on('this.ID', 'ref.USER_ID'),
981 ['join_type' => Join::TYPE_LEFT]
982 ),
983 );
984 $query->addFilter('!=EXTRANET_USER.ROLE', ExtranetRole::Collaber->value);
985 }
986
987 $userIds = self::prepareUserIds($options['userId'] ?? []);
988 $notUserIds = self::prepareUserIds($options['!userId'] ?? []);
989
990 // User Whitelist
991 if (!empty($userIds))
992 {
993 $query->whereIn('ID', $userIds);
994 }
995
996 // User Blacklist
997 if (!empty($notUserIds))
998 {
999 $query->whereNotIn('ID', $notUserIds);
1000 }
1001
1002 if (
1003 empty($options['order'])
1004 &&
1005 ($usersCount = count($userIds)) > 1
1006 )
1007 {
1008 $helper = Application::getConnection()->getSqlHelper();
1009 $expression = $helper->getOrderByIntField('%s', $userIds, false);
1010 $field = new ExpressionField(
1011 'ID_SEQUENCE',
1012 $expression,
1013 array_fill(0, $usersCount, 'ID'),
1014 );
1015 $query
1016 ->registerRuntimeField($field)
1017 ->setOrder($field->getName());
1018 }
1019 elseif (!empty($options['order']) && is_array($options['order']))
1020 {
1021 $query->setOrder($options['order']);
1022 }
1023 else
1024 {
1025 $query->setOrder(['LAST_NAME' => 'asc']);
1026 }
1027
1028 if (isset($options['limit']) && is_int($options['limit']))
1029 {
1030 $query->setLimit($options['limit']);
1031 }
1032 elseif (empty($userIds)) // no limit if we filter users by ids
1033 {
1034 $query->setLimit(100);
1035 }
1036
1037 return $query;
1038 }
1039
1040 private static function prepareUserIds($items): array
1041 {
1042 $ids = [];
1043 if (is_array($items) && !empty($items))
1044 {
1045 foreach ($items as $id)
1046 {
1047 if ((int)$id > 0)
1048 {
1049 $ids[] = (int)$id;
1050 }
1051 }
1052
1053 $ids = array_unique($ids);
1054 }
1055 else if (!is_array($items) && (int)$items > 0)
1056 {
1057 $ids = [(int)$items];
1058 }
1059
1060 return $ids;
1061 }
1062
1063 protected static function getExtranetUsersQuery(int $currentUserId): ?Query
1064 {
1065 $extranetSiteId = Option::get('extranet', 'extranet_site');
1066 $extranetSiteId = ($extranetSiteId && ModuleManager::isModuleInstalled('extranet') ? $extranetSiteId : false);
1067
1068 if (
1069 !$extranetSiteId
1070 || \CSocNetUser::isCurrentUserModuleAdmin()
1071 )
1072 {
1073 return null;
1074 }
1075
1076 $query = UserToGroupTable::query();
1077 $query->addSelect(new ExpressionField('DISTINCT_USER_ID', 'DISTINCT %s', 'USER.ID'));
1078 // $query->where('ROLE', '<=', UserToGroupTable::ROLE_USER);
1079 $query->whereIn('ROLE', self::EXTRANET_ROLES);
1080 $query->registerRuntimeField(
1081 new Reference(
1082 'GS',
1083 WorkgroupSiteTable::class,
1084 Join::on('ref.GROUP_ID', 'this.GROUP_ID')->where('ref.SITE_ID', $extranetSiteId),
1085 ['join_type' => 'INNER'],
1086 ),
1087 );
1088
1089 $query->registerRuntimeField(
1090 new Reference(
1091 'UG_MY',
1092 UserToGroupTable::class,
1093 Join::on('ref.GROUP_ID', 'this.GROUP_ID')
1094 ->where('ref.USER_ID', $currentUserId)
1095 ->whereIn('ref.ROLE', self::EXTRANET_ROLES),
1096 ['join_type' => 'INNER'],
1097 ),
1098 );
1099
1100 return $query;
1101 }
1102
1103 public static function getUser(int $userId, array $options = []): ?EO_User
1104 {
1105 $options['userId'] = $userId;
1106 $users = static::getUsers($options);
1107
1108 return $users->count() ? $users->getAll()[0] : null;
1109 }
1110
1114 public static function makeItems(EO_User_Collection $users, array $options = []): array
1115 {
1116 $result = [];
1117 $options['departmentMap'] = EmployeeHelper::employeesToDepartment($users);
1118
1119 foreach ($users as $user)
1120 {
1121 $result[] = static::makeItem($user, $options);
1122 }
1123
1124 return $result;
1125 }
1126
1127 public static function makeItem(EO_User $user, array $options = []): Item
1128 {
1129 $customData = [];
1130 foreach (['name', 'lastName', 'secondName', 'email', 'login'] as $field)
1131 {
1132 if (!empty($user->{'get'.$field}()))
1133 {
1134 $customData[$field] = $user->{'get'.$field}();
1135 }
1136 }
1137
1138 if (!empty($user->getPersonalGender()))
1139 {
1140 $customData['gender'] = $user->getPersonalGender();
1141 }
1142
1143 if (!empty($user->getWorkPosition()))
1144 {
1145 $customData['position'] = $user->getWorkPosition();
1146 }
1147
1148 $userType = self::getUserType($user);
1149
1150 if ($user->getConfirmCode() && in_array($userType, ['employee', 'integrator']))
1151 {
1152 $customData['invited'] = true;
1153 }
1154
1155 if (isset($options['selectFields']) && is_array($options['selectFields']))
1156 {
1157 $userData = $user->collectValues();
1158 $allowedFields = static::getAllowedFields();
1159 foreach ($options['selectFields'] as $field)
1160 {
1161 if (!is_string($field))
1162 {
1163 continue;
1164 }
1165
1166 $dbName = $allowedFields[$field] ?? null;
1167 $value = $userData[$dbName] ?? null;
1168 if (!empty($value))
1169 {
1170 if ($field === 'country' || $field === 'workCountry')
1171 {
1172 $value = \Bitrix\Main\UserUtils::getCountryValue(['VALUE' => $value]);
1173 }
1174
1176 }
1177 }
1178 }
1179
1180 if (isset($options['showLogin']) && $options['showLogin'] === false)
1181 {
1182 unset($customData['login']);
1183 }
1184
1185 if (isset($options['showEmail']) && $options['showEmail'] === false)
1186 {
1187 unset($customData['email']);
1188 }
1189
1190 if (!empty($options['departmentMap']) && isset($options['departmentMap'][$user->getId()]))
1191 {
1192 $customData['nodeId'] = $options['departmentMap'][$user->getId()];
1193 }
1194
1195 $item = new Item([
1196 'id' => $user->getId(),
1197 'entityId' => static::ENTITY_ID,
1198 'entityType' => $userType,
1199 'title' => self::formatUserName($user, $options),
1200 'avatar' => self::makeUserAvatar($user),
1201 'customData' => $customData,
1202 'tabs' => static::getTabsNames(),
1203 ]);
1204
1205 if (($userType === 'employee' || $userType === 'integrator') && Loader::includeModule('intranet'))
1206 {
1207 $isOnVacation = UserAbsence::isAbsentOnVacation($user->getId());
1208 if ($isOnVacation)
1209 {
1210 $item->getCustomData()->set('isOnVacation', true);
1211 }
1212 }
1213
1214 return $item;
1215 }
1216
1217 protected static function getTabsNames(): array
1218 {
1219 return [static::ENTITY_ID];
1220 }
1221
1222 public static function getUserType(EO_User $user): string
1223 {
1224 $type = null;
1225 if (!$user->getActive())
1226 {
1227 $type = 'inactive';
1228 }
1229 else if ($user->getExternalAuthId() === 'email')
1230 {
1231 $type = 'email';
1232 }
1233 else if ($user->getExternalAuthId() === 'replica')
1234 {
1235 $type = 'network';
1236 }
1237 else if (!in_array($user->getExternalAuthId(), UserTable::getExternalUserTypes()))
1238 {
1239 if (ModuleManager::isModuleInstalled('intranet') || ModuleManager::isModuleInstalled('extranet'))
1240 {
1241 if (self::isIntegrator($user->getId()))
1242 {
1243 $type = 'integrator';
1244 }
1245 else if (
1246 Loader::includeModule('extranet')
1247 && ServiceContainer::getInstance()->getCollaberService()->isCollaberById($user->getId())
1248 )
1249 {
1250 $type = 'collaber';
1251 }
1252 else if (ModuleManager::isModuleInstalled('intranet'))
1253 {
1254 $ufDepartment = $user->getUfDepartment();
1255 if (
1256 empty($ufDepartment)
1257 || (is_array($ufDepartment) && count($ufDepartment) === 1 && (int)$ufDepartment[0] === 0)
1258 )
1259 {
1260 $type = 'extranet';
1261 }
1262 else
1263 {
1264 $type = 'employee';
1265 }
1266 }
1267 }
1268 else
1269 {
1270 $type = 'user';
1271 }
1272 }
1273 else
1274 {
1275 $type = 'unknown';
1276 }
1277
1278 return $type;
1279 }
1280
1281 public static function formatUserName(EO_User $user, array $options = []): string
1282 {
1283 return \CUser::formatName(
1284 !empty($options['nameTemplate']) ? $options['nameTemplate'] : \CSite::getNameFormat(false),
1285 [
1286 'NAME' => $user->getName(),
1287 'LAST_NAME' => $user->getLastName(),
1288 'SECOND_NAME' => $user->getSecondName(),
1289 'LOGIN' => $user->getLogin(),
1290 'EMAIL' => $user->getEmail(),
1291 'TITLE' => $user->getTitle(),
1292 ],
1293 true,
1294 false,
1295 );
1296 }
1297
1298 public static function makeUserAvatar(EO_User $user): ?string
1299 {
1300 if (empty($user->getPersonalPhoto()))
1301 {
1302 return null;
1303 }
1304
1305 $avatar = \CFile::resizeImageGet(
1306 $user->getPersonalPhoto(),
1307 ['width' => 100, 'height' => 100],
1309 false,
1310 );
1311
1312 return !empty($avatar['src']) ? $avatar['src'] : null;
1313 }
1314
1315 public static function getUserUrl(?int $userId = null): string
1316 {
1317
1318 return
1319 self::isExtranetUser($userId)
1320 ? self::getExtranetUserUrl($userId)
1321 : self::getIntranetUserUrl($userId)
1322 ;
1323 }
1324
1325 public static function getExtranetUserUrl(?int $userId = null): string
1326 {
1327 $extranetSiteId = Option::get('extranet', 'extranet_site');
1328 $userPage = Option::get('socialnetwork', 'user_page', false, $extranetSiteId);
1329 if (!$userPage)
1330 {
1331 $userPage = '/extranet/contacts/personal/';
1332 }
1333
1334 return $userPage.'user/' . ($userId !== null ? $userId : '#id#') . '/';
1335 }
1336
1337 public static function getIntranetUserUrl(?int $userId = null): string
1338 {
1339 $userPage = Option::get('socialnetwork', 'user_page', false, SITE_ID);
1340 if (!$userPage)
1341 {
1342 $siteDir = (defined('SITE_DIR') && !empty(SITE_DIR)) ? SITE_DIR : '/';
1343 $userPage = $siteDir . 'company/personal/';
1344 }
1345
1346 return $userPage.'user/' . ($userId !== null ? $userId : '#id#') . '/';
1347 }
1348}
$type
Определения options.php:106
$allowedFields
Определения push.php:9
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
Определения dialog.php:11
static $options
Определения option.php:18
Определения orm.php:16144
$customData
Определения error.php:24
$value
Определения date.php:11
static getCountryValue(array $params=[])
Определения userutils.php:357
static employeesToDepartment(EO_User_Collection $usersCollection)
Определения employeehelper.php:26
static formatUserName(EO_User $user, array $options=[])
Определения userprovider.php:1281
static getUser(int $userId, array $options=[])
Определения userprovider.php:1103
static getExtranetUsersQuery(int $currentUserId)
Определения userprovider.php:1063
static makeItem(EO_User $user, array $options=[])
Определения userprovider.php:1127
makeUserItems(EO_User_Collection $users, array $options=[])
Определения userprovider.php:504
doSearch(SearchQuery $searchQuery, Dialog $dialog)
Определения userprovider.php:434
static makeItems(EO_User_Collection $users, array $options=[])
Определения userprovider.php:1114
getOption(string $option, $defaultValue=null)
Определения baseprovider.php:48
getEntityType()
Определения item.php:190
setCacheable(bool $flag=true)
Определения searchquery.php:72
$options
Определения commerceml2.php:49
</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
$filter
Определения iblock_catalog_list.php:54
$selectFields
Определения iblock_catalog_list.php:160
const BX_RESIZE_IMAGE_EXACT
Определения constants.php:12
const SITE_DIR(!defined('LANG'))
Определения include.php:72
Определения chain.php:3
$user
Определения mysql_to_pgsql.php:33
$GLOBALS['____1690880296']
Определения license.php:1
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
</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
$matches
Определения index.php:22
const SITE_ID
Определения sonet_set_content_view.php:12
$fields
Определения yandex_run.php:501