Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
Notification.php
1<?php
2
4
8use Bitrix\Main\Db\SqlQueryException;
16
17class Notification extends Base
18{
19 public const SITE = 'site';
20 public const MAIL = 'mail';
21 public const XMPP = 'xmpp';
22 public const PUSH = 'push';
23
24 protected const ENTITY = 'no';
25 protected const MODULE = 1;
26 protected const NAME = 2;
27 protected const TYPE = 3;
28
29 protected static $defaultSettings = [];
30
31 private $module;
32 private $name;
33
34 private static $types = [
35 'SITE' => 1,
36 'MAIL' => 2,
37 'XMPP' => 3,
38 'PUSH' => 4,
39 ];
40
45 public function __construct(string $module, string $name)
46 {
47 $this->module = $module;
48 $this->name = $name;
49 }
50
54 public function setModule(string $module): void
55 {
56 $this->module = $module;
57 }
58
62 public function setName(string $name): void
63 {
64 $this->name = $name;
65 }
66
72 public function isAllowed(int $userId, string $type): bool
73 {
75 {
76 return false;
77 }
78
79 $encodedSetting = self::encodeName($this->module, $this->name, $type);
80
82
84
85 if (!array_key_exists($encodedSetting, $defaultSettings))
86 {
87 $encodedSetting = self::encodeName('im', 'default', $type);
88 }
89
90 $value = $defaultSettings[$encodedSetting] === 'Y' ? 'Y' : 'N';
91
92 $result =
93 OptionUserTable::query()
94 ->addSelect('USER_ID')
95 ->registerRuntimeField(
96 'USER',
97 new Reference(
98 'USER',
99 UserTable::class,
100 Join::on('this.USER_ID', 'ref.ID'),
101 ['join_type' => Join::TYPE_INNER]
102 )
103 )
104 ->registerRuntimeField(
105 'OPTION_STATE',
106 new Reference(
107 'OPTION_STATE',
108 OptionStateTable::class,
109 Join::on('this.NOTIFY_GROUP_ID', 'ref.GROUP_ID')
110 ->where('ref.NAME', $encodedSetting),
111 ['join_type' => Join::TYPE_LEFT]
112 )
113 )
114 ->whereExpr("COALESCE(%s, '$value') = 'Y'", ['OPTION_STATE.VALUE'])
115 ->where('USER_ID', $userId)
116 ->where('USER.ACTIVE', 'Y')
117 ->where('USER.IS_REAL_USER', 'Y')
118 ->fetch()
119 ;
120
121 $result = $result !== false;
122
123 if ($type !== self::PUSH)
124 {
125 return $result;
126 }
127 //checked push
128
129 if ($result)
130 {
131 $query =
132 PushTable::query()
133 ->addSelect('ID')
134 ->where('USER_ID', $userId)
135 ->setLimit(1)
136 ;
137 $pushId = $query->fetch();
138
139 return $pushId !== false;
140 }
141
142 return false;
143 }
144
152 public function filterAllowedUsers(array $userList, string $type): array
153 {
154 if (empty($userList))
155 {
156 return [];
157 }
158
160 if (empty($userList))
161 {
162 return [];
163 }
164
165 $encodedSetting = self::encodeName($this->module, $this->name, $type);
166
168
170
171 if (!array_key_exists($encodedSetting, $defaultSettings))
172 {
173 $encodedSetting = self::encodeName('im', 'default', $type);
174 }
175
176 $value = $defaultSettings[$encodedSetting] === 'Y' ? 'Y' : 'N';
177
178 $filteredUsers = [];
179 if (count($userList) < 1000)
180 {
181 $filteredUsers = $this->filterChunk($userList, $encodedSetting, $value);
182 }
183 else
184 {
185 $chunkList = array_chunk($userList, static::CHUNK_LENGTH);
186 foreach ($chunkList as $chunk)
187 {
188 $filteredUsers = array_merge($filteredUsers, $this->filterChunk($chunk, $encodedSetting, $value));
189 }
190 }
191
192 if ($type !== self::PUSH)
193 {
194 return $filteredUsers;
195 }
196
197 //checked push
198 if (empty($filteredUsers))
199 {
200 return $filteredUsers;
201 }
202
203 $rowFilteredPushUsers =
204 PushTable::query()
205 ->addSelect('USER_ID')
206 ->whereIn('USER_ID', $filteredUsers)
207 ;
208
209 $filteredUsers = [];
210 foreach ($rowFilteredPushUsers->exec() as $user)
211 {
212 $filteredUsers[] = (int)$user['USER_ID'];
213 }
214
215 return array_unique($filteredUsers);
216 }
217
218 private function filterChunk(array $userListChunk, $encodedSettingName, $value): array
219 {
220 $query =
221 OptionUserTable::query()
222 ->addSelect('USER_ID')
223 ->registerRuntimeField(
224 'USER',
225 new Reference(
226 'USER',
227 UserTable::class,
228 Join::on('this.USER_ID', 'ref.ID'),
229 ['join_type' => Join::TYPE_INNER]
230 )
231 )
232 ->registerRuntimeField(
233 'OPTION_STATE',
234 new Reference(
235 'OPTION_STATE',
236 OptionStateTable::class,
237 Join::on('this.NOTIFY_GROUP_ID', 'ref.GROUP_ID')
238 ->where('ref.NAME', $encodedSettingName),
239 ['join_type' => Join::TYPE_LEFT]
240 )
241 )
242 ->whereExpr("COALESCE(%s, '$value') = 'Y'", ['OPTION_STATE.VALUE'])
243 ->whereIn('USER_ID', $userListChunk)
244 ->where('USER.ACTIVE', 'Y')
245 ->where('USER.IS_REAL_USER', 'Y');
246
247 $filteredUsers = [];
248 foreach ($query->exec() as $user)
249 {
250 $filteredUsers[] = (int)$user['USER_ID'];
251 }
252
253 return $filteredUsers;
254 }
255
260 public function checkDisableFeature(string $feature): bool
261 {
263 if (isset($defaultSettings[$this->module]['NOTIFY'][$this->name]['DISABLED'][mb_strtoupper($feature)]))
264 {
265 return (bool)$defaultSettings[$this->module]['NOTIFY'][$this->name]['DISABLED'][mb_strtoupper($feature)];
266 }
267
268 return false;
269 }
270
271 public function getDefaultFeature(string $feature): bool
272 {
273 return (bool)self::getDefaultSettings()[$this->module]['NOTIFY'][$this->name][mb_strtoupper($feature)];
274 }
275
276 public function getLifetime(): int
277 {
278 return (int)self::getDefaultSettings()[$this->module]['NOTIFY'][$this->name]['LIFETIME'];
279 }
280
281 public function getValue(int $userId, string $type): bool
282 {
283 $encodedName = self::encodeName($this->module, $this->name, $type);
284
285 if (!$encodedName)
286 {
287 return false;
288 }
289
290 $defaultSettings = self::encodeSettings(self::getDefaultSettings());
291
292 $cachedPreset = Configuration::getUserPresetFromCache($userId);
293 if (
294 !empty($cachedPreset)
295 && isset($cachedPreset[Configuration::NOTIFY_GROUP])
296 && is_array($cachedPreset[Configuration::NOTIFY_GROUP])
297 )
298 {
299 $notifySettings = $cachedPreset[Configuration::NOTIFY_GROUP]['settings'];
300
301 if (!$notifySettings)
302 {
303 return $defaultSettings[$encodedName];
304 }
305
306 $notifySettings = self::encodeSettings($notifySettings);
307
308 if (is_null($notifySettings[$encodedName]))
309 {
310 return $defaultSettings[$encodedName] === 'Y';
311 }
312
313 return $notifySettings[$encodedName] === 'Y';
314 }
315
316 $query =
317 OptionStateTable::query()
318 ->addSelect('VALUE')
319 ->registerRuntimeField(
320 'OPTION_USER',
321 new Reference(
322 'OPTION_USER',
323 OptionUserTable::class,
324 Join::on('this.GROUP_ID', 'ref.NOTIFY_GROUP_ID'),
325 ['join_type' => Join::TYPE_INNER]
326 )
327 )
328 ->where('OPTION_USER.USER_ID', $userId)
329 ->where('NAME', $encodedName)
330 ;
331
332 $value = $query->fetch()['VALUE'];
333
334 if (!$value)
335 {
336 return $defaultSettings[$encodedName] === 'Y';
337 }
338
339 return $value === 'Y';
340 }
341
347 public static function getDefaultSettings(): array
348 {
349 if (!empty(self::$defaultSettings))
350 {
352 }
353
354 foreach (EventManager::getInstance()->findEventHandlers("im", "OnGetNotifySchema") as $events)
355 {
356 $event = ExecuteModuleEventEx($events);
357
358 if (!is_array($event))
359 {
360 continue;
361 }
362
363 foreach ($event as $moduleId => $notifyType)
364 {
365 self::$defaultSettings[$moduleId]['NAME'] =
366 isset($notifyType['NOTIFY'], $notifyType['NAME'])
367 ? $notifyType['NAME']
368 : '';
369
370 $notify = $notifyType['NOTIFY'] ?? $notifyType;
371
372 foreach ($notify as $notifyEvent => $config)
373 {
374 $config['DISABLED'] = $config['DISABLED'] ?? [];
375
376 if (!isset($config['PUSH']) || $config['PUSH'] === 'NONE')
377 {
378 $config['DISABLED'][] = self::PUSH;
379 }
380
381 $disabled['SITE'] = in_array(self::SITE, $config['DISABLED'], true);
382 $disabled['MAIL'] = in_array(self::MAIL, $config['DISABLED'], true);
383 $disabled['XMPP'] = in_array(self::XMPP, $config['DISABLED'], true);
384 $disabled['PUSH'] = in_array(self::PUSH, $config['DISABLED'], true);
385
386 $config['DISABLED'] = $disabled;
387
388 // backward compatibility
389 $config['SITE'] = !isset($config['SITE']) || $config['SITE'] == 'Y';
390 $config['MAIL'] = !isset($config['MAIL']) || $config['MAIL'] == 'Y';
391 $config['XMPP'] = !isset($config['XMPP']) || $config['XMPP'] == 'Y';
392 $config['PUSH'] = isset($config['PUSH']) && $config['PUSH'] == 'Y';
393
394 $config['LIFETIME'] = isset($config['LIFETIME']) ? (int)$config['LIFETIME'] : 0;
395
396 self::$defaultSettings[$moduleId]['NOTIFY'][$notifyEvent] = $config;
397 }
398 }
399 }
400
402 }
403
404 public static function getSimpleNotifySettings(array $generalSettings): array
405 {
406 $defaultGeneralSettings = General::getDefaultSettings();
407
408 $send['SITE'] = $generalSettings['notifySchemeSendSite'] ?? $defaultGeneralSettings['notifySchemeSendSite'];
409 $send['MAIL'] = $generalSettings['notifySchemeSendEmail'] ?? $defaultGeneralSettings['notifySchemeSendEmail'];
410 $send['XMPP'] = $generalSettings['notifySchemeSendXmpp'] ?? $defaultGeneralSettings['notifySchemeSendXmpp'];
411 $send['PUSH'] = $generalSettings['notifySchemeSendPush'] ?? $defaultGeneralSettings['notifySchemeSendPush'];
412
413 $notifySettings = Notification::getDefaultSettings();
414
415 foreach ($notifySettings as $moduleId => $moduleSchema)
416 {
417 foreach ($moduleSchema['NOTIFY'] as $eventName => $eventSchema)
418 {
419 foreach (['SITE', 'MAIL', 'XMPP', 'PUSH'] as $type)
420 {
421 if ($eventSchema['DISABLED'][$type])
422 {
423 continue;
424 }
425
426 $notifySettings[$moduleId]['NOTIFY'][$eventName][$type] =
427 !$send[$type]
428 ? false
429 : $eventSchema[$type]
430 ;
431 }
432 }
433 }
434
435 return $notifySettings;
436 }
437
445 public static function getUserSettings(int $userId): array
446 {
448
449 $query =
450 OptionStateTable::query()
451 ->setSelect(['NAME','VALUE'])
452 ->registerRuntimeField(
453 'OPTION_USER_TABLE',
454 new Reference(
455 'OPTION_USER_TABLE',
456 OptionUserTable::class,
457 Join::on('this.GROUP_ID', 'ref.NOTIFY_GROUP_ID'),
458 ['join_type' => Join::TYPE_INNER]
459 )
460 )
461 ->where('OPTION_USER_TABLE.USER_ID', $userId)
462 ->whereLike('NAME', static::ENTITY.'%')
463 ;
464
465 $rowSettings = [];
466 foreach ($query->exec() as $rowSetting)
467 {
468 $rowSettings[] = $rowSetting;
469 }
470
471 if (empty($rowSettings))
472 {
473 return $defaultSettings;
474 }
475
476 $decodedSettings = static::decodeSettings($rowSettings);
477
478 return array_replace_recursive($defaultSettings, $decodedSettings);
479 }
480
488 public static function getGroupSettings(int $groupId): array
489 {
491
492 $query =
493 OptionStateTable::query()
494 ->setSelect(['NAME','VALUE'])
495 ->where('GROUP_ID', $groupId)
496 ->whereLike('NAME', static::ENTITY . '%')
497 ;
498
499 $settings = [];
500 foreach ($query->exec() as $rowSetting)
501 {
502 $settings[] = $rowSetting;
503 }
504
505 if (empty($settings))
506 {
507 return $defaultSettings;
508 }
509
510 $settings = static::decodeSettings($settings);
511
512 return array_replace_recursive($defaultSettings, $settings);
513 }
514
521 public static function updateGroupSettings(int $groupId, array $settings): void
522 {
523 if (!$settings)
524 {
525 return;
526 }
527 $encodedSettings = self::encodeSettings($settings);
528 $defaultSettings = self::encodeSettings(self::getDefaultSettings());
529
530 $query =
531 OptionStateTable::query()
532 ->setSelect(['NAME', 'VALUE'])
533 ->where('GROUP_ID', $groupId)
534 ->whereLike('NAME', self::ENTITY . '%')
535 ;
536 $addedSettings = [];
537 $enabledSettings = [];
538 $disabledSettings = [];
539 foreach ($query->exec() as $row)
540 {
541 if (array_key_exists($row['NAME'], $encodedSettings))
542 {
543 if ($row['VALUE'] === $encodedSettings[$row['NAME']])
544 {
545 unset($encodedSettings[$row['NAME']]);
546 continue;
547 }
548 if ($encodedSettings[$row['NAME']] === 'Y')
549 {
550 $enabledSettings[] = [
551 'GROUP_ID' => $groupId,
552 'NAME' => $row['NAME']
553 ];
554 unset($encodedSettings[$row['NAME']]);
555 continue;
556 }
557 if ($encodedSettings[$row['NAME']] === 'N')
558 {
559 $disabledSettings[] = [
560 'GROUP_ID' => $groupId,
561 'NAME' => $row['NAME']
562 ];
563 unset($encodedSettings[$row['NAME']]);
564 }
565 }
566 }
567
568 foreach ($encodedSettings as $name => $value)
569 {
570 if (!array_key_exists($name, $defaultSettings))
571 {
572 continue;
573 }
574
575 $addedSettings[] = [
576 'GROUP_ID' => $groupId,
577 'NAME' => $name,
578 'VALUE' => $value
579 ];
580 }
581 if (!empty($addedSettings))
582 {
583 OptionStateTable::addMulti($addedSettings, true);
584 }
585 if (!empty($enabledSettings))
586 {
587 OptionStateTable::updateMulti($enabledSettings, ['VALUE' => 'Y'], true);
588 }
589 if (!empty($disabledSettings))
590 {
591 OptionStateTable::updateMulti($disabledSettings, ['VALUE' => 'N'], true);
592 }
593
594 }
595
602 public static function setSettings(int $groupId, array $settings = [], bool $forInitialize = false): void
603 {
604 if (empty($settings) && !$forInitialize)
605 {
606 return;
607 }
608
609 $selectedSettings = [];
610 $query =
611 OptionStateTable::query()
612 ->setSelect(['NAME', 'VALUE'])
613 ->where('GROUP_ID', $groupId)
614 ->whereLike('NAME', self::ENTITY . '%')
615 ;
616 foreach ($query->exec() as $row)
617 {
618 $selectedSettings[$row['NAME']] = $row['VALUE'];
619 }
620 $defaultSettings = self::encodeSettings(self::getDefaultSettings());
621 $encodedSettings = self::encodeSettings($settings);
622 $encodedSettings = array_merge($defaultSettings, $encodedSettings);
623
624 $rows = [];
625 foreach ($encodedSettings as $name => $value)
626 {
627 if (!array_key_exists($name, $defaultSettings) || isset($selectedSettings[$name]))
628 {
629 continue;
630 }
631
632 $rows[] = [
633 'GROUP_ID' => $groupId,
634 'NAME' => $name,
635 'VALUE' => $value
636 ];
637 }
638
639 OptionStateTable::addMulti($rows, true);
640 }
641
642 public static function getEventNames(): array
643 {
644 $names = [];
646 foreach ($defaultSettings as $moduleId => $notifyTypes)
647 {
648 $names[$moduleId]['NAME'] = $notifyTypes['NAME'];
649 if ($notifyTypes['NAME'] == '')
650 {
651 $moduleObject = \CModule::CreateModuleObject($moduleId);
652 $names[$moduleId]['NAME'] = $moduleObject->MODULE_NAME;
653 }
654 foreach ($notifyTypes['NOTIFY'] as $eventId => $event)
655 {
656 $names[$moduleId]['NOTIFY'][$eventId] = $event['NAME'];
657 }
658 }
659
660 return $names;
661 }
662
670 public static function decodeSettings(array $rowSettings): array
671 {
672 $decodedSettings = [];
673
674 foreach ($rowSettings as $rowSetting)
675 {
676 if (!$rowSetting['NAME'])
677 {
678 continue;
679 }
680
681 $setting = self::decodeName($rowSetting['NAME']);
682
683 if ($setting === null)
684 {
685 continue;
686 }
687 $module = $setting[self::MODULE];
688 $name = $setting[self::NAME];
689
690 if(!in_array((int)$setting[self::TYPE], [1,2,3,4]))
691 {
692 continue;
693 }
694
695 $type = self::getType((int)$setting[self::TYPE]);
696
697 $decodedSettings[$module]['NOTIFY'][$name][$type] = $rowSetting['VALUE'] === 'Y';
698 }
699
700 return $decodedSettings;
701 }
702
711 public static function encodeSettings(array $settings): array
712 {
713 $encodedSettings = [];
714
715 foreach ($settings as $moduleName => $notifies)
716 {
717 if (!is_array($notifies))
718 {
719 continue;
720 }
721
722 foreach ($notifies as $notify)
723 {
724 if (!is_array($notify))
725 {
726 continue;
727 }
728
729 foreach ($notify as $notifyName => $types)
730 {
731 foreach ($types as $type => $value)
732 {
733 $setting = self::encodeName($moduleName, $notifyName, $type);
734
735 if (!$setting || mb_strlen($setting) > 64)
736 {
737 continue;
738 }
739
740 $encodedSettings[$setting] = $value ? 'Y' : 'N';
741 }
742
743 }
744 }
745 }
746
747 return $encodedSettings;
748 }
749
757 private static function decodeName(string $setting): ?array
758 {
759 $row = explode(static::SEPARATOR, $setting);
760
761 if (!array_key_exists(self::MODULE, $row)
762 || !array_key_exists(self::NAME, $row)
763 || !array_key_exists(self::TYPE, $row)
764 )
765 {
766 return null;
767 }
768
769 return $row;
770 }
771
781 private static function encodeName(string $module, string $name, string $type): ?string
782 {
783 if ($type === '')
784 {
785 return null;
786 }
787
788 $postfix = self::getPostfix($type);
789
790 if ($postfix === null)
791 {
792 return null;
793 }
794
795 return implode(
796 static::SEPARATOR,
797 [
798 static::ENTITY,
799 $module,
800 $name,
801 $postfix,
802 ]
803 );
804 }
805
811 private static function getPostfix(string $type): ?int
812 {
813 return self::$types[mb_strtoupper($type)] ?? null;
814 }
815
821 private static function getType(int $postfix): ?string
822 {
823 $arr = array_flip(self::$types);
824
825 return $arr[$postfix];
826 }
827
828}
static filterAllowedUsersBySimpleNotificationSettings(array $userList, string $notifyType)
Definition General.php:232
static allowedUserBySimpleNotificationSettings(int $userId, string $notifyType)
Definition General.php:220
static updateGroupSettings(int $groupId, array $settings)
isAllowed(int $userId, string $type)
static setSettings(int $groupId, array $settings=[], bool $forInitialize=false)
filterAllowedUsers(array $userList, string $type)
__construct(string $module, string $name)
static encodeSettings(array $settings)
static getSimpleNotifySettings(array $generalSettings)
getValue(int $userId, string $type)
static decodeSettings(array $rowSettings)