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