403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/im/lib/Configuration/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/im/lib/Configuration/Notification.php
<?php

namespace Bitrix\Im\Configuration;

use Bitrix\Im\Model\OptionStateTable;
use Bitrix\Im\Model\OptionUserTable;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\Db\SqlQueryException;
use Bitrix\Main\EventManager;
use Bitrix\Main\ObjectPropertyException;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Query\Join;
use Bitrix\Main\SystemException;
use Bitrix\Main\UserTable;
use Bitrix\Pull\Model\PushTable;

class Notification extends Base
{
	public const SITE = 'site';
	public const MAIL = 'mail';
	public const XMPP = 'xmpp';
	public const PUSH = 'push';

	protected const ENTITY = 'no';
	protected const MODULE = 1;
	protected const NAME = 2;
	protected const TYPE = 3;

	protected static $defaultSettings = [];

	private $module;
	private $name;

	private static $types = [
		'SITE' => 1,
		'MAIL' => 2,
		'XMPP' => 3,
		'PUSH' => 4,
	];

	/**
	 * @param string $module
	 * @param string $name
	 */
	public function __construct(string $module, string $name)
	{
		$this->module = $module;
		$this->name = $name;
	}

	/**
	 * @param string $module
	 */
	public function setModule(string $module): void
	{
		$this->module = $module;
	}

	/**
	 * @param string $name
	 */
	public function setName(string $name): void
	{
		$this->name = $name;
	}

	/**
	 * Determines whether a notification can be sent to the user
	 *
	 * @throws SqlQueryException
	 */
	public function isAllowed(int $userId, string $type): bool
	{
		if (!General::allowedUserBySimpleNotificationSettings($userId, $type))
		{
			return false;
		}

		$encodedSetting = self::encodeName($this->module, $this->name, $type);

		$defaultSettings = self::getDefaultSettings();

		$defaultSettings = self::encodeSettings($defaultSettings);

		if (!array_key_exists($encodedSetting, $defaultSettings))
		{
			$encodedSetting = self::encodeName('im', 'default', $type);
		}

		$value = $defaultSettings[$encodedSetting] === 'Y' ? 'Y' : 'N';

		$result =
			OptionUserTable::query()
				->addSelect('USER_ID')
				->registerRuntimeField(
					'USER',
					new Reference(
						'USER',
						UserTable::class,
						Join::on('this.USER_ID', 'ref.ID'),
						['join_type' => Join::TYPE_INNER]
					)
				)
				->registerRuntimeField(
					'OPTION_STATE',
					new Reference(
						'OPTION_STATE',
						OptionStateTable::class,
						Join::on('this.NOTIFY_GROUP_ID', 'ref.GROUP_ID')
							->where('ref.NAME', $encodedSetting),
						['join_type' => Join::TYPE_LEFT]
					)
				)
				->whereExpr("COALESCE(%s, '$value') = 'Y'", ['OPTION_STATE.VALUE'])
				->where('USER_ID', $userId)
				->where('USER.ACTIVE', 'Y')
				->where('USER.IS_REAL_USER', 'Y')
				->fetch()
		;

		$result = $result !== false;

		if ($type !== self::PUSH)
		{
			return $result;
		}
		//checked push

		if ($result)
		{
			$query =
				PushTable::query()
				->addSelect('ID')
				->where('USER_ID', $userId)
				->setLimit(1)
			;
			$pushId = $query->fetch();

			return $pushId !== false;
		}

		return false;
	}

	/**
	 * Filters the list of users to whom can send a notification
	 *
	 * @throws SqlQueryException
	 * @throws ArgumentException
	 * @throws SystemException
	 */
	public function filterAllowedUsers(array $userList, string $type): array
	{
		if (empty($userList))
		{
			return [];
		}

		$userList = General::filterAllowedUsersBySimpleNotificationSettings($userList, $type);
		if (empty($userList))
		{
			return [];
		}

		$encodedSetting = self::encodeName($this->module, $this->name, $type);

		$defaultSettings = self::getDefaultSettings();

		$defaultSettings = self::encodeSettings($defaultSettings);

		if (!array_key_exists($encodedSetting, $defaultSettings))
		{
			$encodedSetting = self::encodeName('im', 'default', $type);
		}

		$value = $defaultSettings[$encodedSetting] === 'Y' ? 'Y' : 'N';

		$filteredUsers = [];
		if (count($userList) < 1000)
		{
			$filteredUsers = $this->filterChunk($userList, $encodedSetting, $value);
		}
		else
		{
			$chunkList = array_chunk($userList, static::CHUNK_LENGTH);
			foreach ($chunkList as $chunk)
			{
				$filteredUsers = array_merge($filteredUsers, $this->filterChunk($chunk, $encodedSetting, $value));
			}
		}

		if ($type !== self::PUSH)
		{
			return $filteredUsers;
		}

		//checked push
		if (empty($filteredUsers))
		{
			return $filteredUsers;
		}

		$rowFilteredPushUsers =
			PushTable::query()
			->addSelect('USER_ID')
			->whereIn('USER_ID', $filteredUsers)
		;

		$filteredUsers = [];
		foreach ($rowFilteredPushUsers->exec() as $user)
		{
			$filteredUsers[] = (int)$user['USER_ID'];
		}

		return array_unique($filteredUsers);
	}

	private function filterChunk(array $userListChunk, $encodedSettingName, $value): array
	{
		$query =
			OptionUserTable::query()
				->addSelect('USER_ID')
				->registerRuntimeField(
					'USER',
					new Reference(
						'USER',
						UserTable::class,
						Join::on('this.USER_ID', 'ref.ID'),
						['join_type' => Join::TYPE_INNER]
					)
				)
				->registerRuntimeField(
					'OPTION_STATE',
					new Reference(
						'OPTION_STATE',
						OptionStateTable::class,
						Join::on('this.NOTIFY_GROUP_ID', 'ref.GROUP_ID')
							->where('ref.NAME', $encodedSettingName),
						['join_type' => Join::TYPE_LEFT]
					)
				)
				->whereExpr("COALESCE(%s, '$value') = 'Y'", ['OPTION_STATE.VALUE'])
				->whereIn('USER_ID', $userListChunk)
				->where('USER.ACTIVE', 'Y')
				->where('USER.IS_REAL_USER', 'Y');

		$filteredUsers = [];
		foreach ($query->exec() as $user)
		{
			$filteredUsers[] = (int)$user['USER_ID'];
		}

		return $filteredUsers;
	}

	/**
	 * @param string $feature
	 * @return bool
	 */
	public function checkDisableFeature(string $feature): bool
	{
		$defaultSettings = self::getDefaultSettings();
		if (isset($defaultSettings[$this->module]['NOTIFY'][$this->name]['DISABLED'][mb_strtoupper($feature)]))
		{
			return (bool)$defaultSettings[$this->module]['NOTIFY'][$this->name]['DISABLED'][mb_strtoupper($feature)];
		}

		return false;
	}

	public function getDefaultFeature(string $feature): bool
	{
		return (bool)self::getDefaultSettings()[$this->module]['NOTIFY'][$this->name][mb_strtoupper($feature)];
	}

	public function getLifetime(): int
	{
		return (int)self::getDefaultSettings()[$this->module]['NOTIFY'][$this->name]['LIFETIME'];
	}

	public function getValue(int $userId, string $type): bool
	{
		$encodedName = self::encodeName($this->module, $this->name, $type);

		if (!$encodedName)
		{
			return false;
		}

		$defaultSettings = self::encodeSettings(self::getDefaultSettings());

		$cachedPreset = Configuration::getUserPresetFromCache($userId);
		if (
			!empty($cachedPreset)
			&& isset($cachedPreset[Configuration::NOTIFY_GROUP])
			&& is_array($cachedPreset[Configuration::NOTIFY_GROUP])
		)
		{
			$notifySettings = $cachedPreset[Configuration::NOTIFY_GROUP]['settings'];

			if (!$notifySettings)
			{
				return $defaultSettings[$encodedName];
			}

			$notifySettings = self::encodeSettings($notifySettings);

			if (is_null($notifySettings[$encodedName]))
			{
				return $defaultSettings[$encodedName] === 'Y';
			}

			return $notifySettings[$encodedName] === 'Y';
		}

		$query =
			OptionStateTable::query()
				->addSelect('VALUE')
				->registerRuntimeField(
					'OPTION_USER',
					new Reference(
						'OPTION_USER',
						OptionUserTable::class,
						Join::on('this.GROUP_ID', 'ref.NOTIFY_GROUP_ID'),
						['join_type' => Join::TYPE_INNER]
					)
				)
				->where('OPTION_USER.USER_ID', $userId)
				->where('NAME', $encodedName)
		;

		$value = $query->fetch()['VALUE'];

		if (!$value)
		{
			return $defaultSettings[$encodedName] === 'Y';
		}

		return $value === 'Y';
	}

	/**
	 * The method get the full notification scheme (from all modules)
	 *
	 * @return array
	 */
	public static function getDefaultSettings(): array
	{
		if (!empty(self::$defaultSettings))
		{
			return self::$defaultSettings;
		}

		foreach (EventManager::getInstance()->findEventHandlers("im", "OnGetNotifySchema") as $events)
		{
			$event = ExecuteModuleEventEx($events);

			if (!is_array($event))
			{
				continue;
			}

			foreach ($event as $moduleId => $notifyType)
			{
				self::$defaultSettings[$moduleId]['NAME'] =
					isset($notifyType['NOTIFY'], $notifyType['NAME'])
						? $notifyType['NAME']
						: '';

				$notify = $notifyType['NOTIFY'] ?? $notifyType;

				foreach ($notify as $notifyEvent => $config)
				{
					$config['DISABLED'] = $config['DISABLED'] ?? [];

					if (!isset($config['PUSH']) || $config['PUSH'] === 'NONE')
					{
						$config['DISABLED'][] = self::PUSH;
					}

					$disabled['SITE'] = in_array(self::SITE, $config['DISABLED'], true);
					$disabled['MAIL'] = in_array(self::MAIL, $config['DISABLED'], true);
					$disabled['XMPP'] = in_array(self::XMPP, $config['DISABLED'], true);
					$disabled['PUSH'] = in_array(self::PUSH, $config['DISABLED'], true);

					$config['DISABLED'] = $disabled;

					// backward compatibility
					$config['SITE'] = !isset($config['SITE']) || $config['SITE'] == 'Y';
					$config['MAIL'] = !isset($config['MAIL']) || $config['MAIL'] == 'Y';
					$config['XMPP'] = !isset($config['XMPP']) || $config['XMPP'] == 'Y';
					$config['PUSH'] = isset($config['PUSH']) && $config['PUSH'] == 'Y';

					$config['LIFETIME'] = isset($config['LIFETIME']) ? (int)$config['LIFETIME'] : 0;

					self::$defaultSettings[$moduleId]['NOTIFY'][$notifyEvent] = $config;
				}
			}
		}

		return self::$defaultSettings;
	}

	public static function getSimpleNotifySettings(array $generalSettings): array
	{
		$defaultGeneralSettings = General::getDefaultSettings();

		$send['SITE'] = $generalSettings['notifySchemeSendSite'] ?? $defaultGeneralSettings['notifySchemeSendSite'];
		$send['MAIL'] = $generalSettings['notifySchemeSendEmail'] ?? $defaultGeneralSettings['notifySchemeSendEmail'];
		$send['XMPP'] = $generalSettings['notifySchemeSendXmpp'] ?? $defaultGeneralSettings['notifySchemeSendXmpp'];
		$send['PUSH'] = $generalSettings['notifySchemeSendPush'] ?? $defaultGeneralSettings['notifySchemeSendPush'];

		$notifySettings = Notification::getDefaultSettings();

		foreach ($notifySettings as $moduleId => $moduleSchema)
		{
			foreach ($moduleSchema['NOTIFY'] as $eventName => $eventSchema)
			{
				foreach (['SITE', 'MAIL', 'XMPP', 'PUSH'] as $type)
				{
					if ($eventSchema['DISABLED'][$type])
					{
						continue;
					}

					$notifySettings[$moduleId]['NOTIFY'][$eventName][$type] =
						!$send[$type]
							? false
							: $eventSchema[$type]
					;
				}
			}
		}

		return $notifySettings;
	}

	/**
	 * Gets the user's notification settings
	 *
	 * @throws ArgumentException
	 * @throws ObjectPropertyException
	 * @throws SystemException
	 */
	public static function getUserSettings(int $userId): array
	{
		$defaultSettings = self::getDefaultSettings();

		$query =
			OptionStateTable::query()
				->setSelect(['NAME','VALUE'])
				->registerRuntimeField(
					'OPTION_USER_TABLE',
					new Reference(
						'OPTION_USER_TABLE',
						OptionUserTable::class,
						Join::on('this.GROUP_ID', 'ref.NOTIFY_GROUP_ID'),
						['join_type' => Join::TYPE_INNER]
					)
				)
				->where('OPTION_USER_TABLE.USER_ID', $userId)
				->whereLike('NAME', static::ENTITY.'%')
		;

		$rowSettings = [];
		foreach ($query->exec() as $rowSetting)
		{
			$rowSettings[] = $rowSetting;
		}

		if (empty($rowSettings))
		{
			return $defaultSettings;
		}

		$decodedSettings = static::decodeSettings($rowSettings);

		return array_replace_recursive($defaultSettings, $decodedSettings);
	}

	/**
	 * Gets the group's notification settings
	 *
	 * @throws ObjectPropertyException
	 * @throws SystemException
	 * @throws ArgumentException
	 */
	public static function getGroupSettings(int $groupId): array
	{
		$defaultSettings = self::getDefaultSettings();

		$query =
			OptionStateTable::query()
				->setSelect(['NAME','VALUE'])
				->where('GROUP_ID', $groupId)
				->whereLike('NAME', static::ENTITY . '%')
		;

		$settings = [];
		foreach ($query->exec() as $rowSetting)
		{
			$settings[] = $rowSetting;
		}

		if (empty($settings))
		{
			return $defaultSettings;
		}

		$settings = static::decodeSettings($settings);

		return self::filterGroupSettingsByDefault($settings);
	}

	public static function filterGroupSettingsByDefault(array $settings): array
	{
		$result = [];
		$defaultSettings = self::getDefaultSettings();

		foreach ($defaultSettings as $moduleId => $defaultModuleSettings)
		{
			$moduleSettings = $settings[$moduleId]['NOTIFY'] ?? [];

			foreach ($defaultModuleSettings['NOTIFY'] ?? [] as $notifyKey => $notifyValue)
			{
				$defaultModuleSettings['NOTIFY'][$notifyKey] =
					array_replace_recursive($notifyValue, $moduleSettings[$notifyKey] ?? [])
				;
			}

			$result[$moduleId] = $defaultModuleSettings;
		}

		return $result;
	}

	/**
	 * Updates the group's notification settings
	 *
	 * @throws SystemException
	 * @throws ArgumentException
	 */
	public static function updateGroupSettings(int $groupId, array $settings): void
	{
		if (!$settings)
		{
			return;
		}
		$encodedSettings = self::encodeSettings($settings);
		$defaultSettings = self::encodeSettings(self::getDefaultSettings());

		$query =
			OptionStateTable::query()
				->setSelect(['NAME', 'VALUE'])
				->where('GROUP_ID', $groupId)
				->whereLike('NAME', self::ENTITY . '%')
		;
		$addedSettings = [];
		$enabledSettings = [];
		$disabledSettings = [];
		foreach ($query->exec() as $row)
		{
			if (array_key_exists($row['NAME'], $encodedSettings))
			{
				if ($row['VALUE'] === $encodedSettings[$row['NAME']])
				{
					unset($encodedSettings[$row['NAME']]);
					continue;
				}
				if ($encodedSettings[$row['NAME']] === 'Y')
				{
					$enabledSettings[] = [
						'GROUP_ID' => $groupId,
						'NAME' => $row['NAME']
					];
					unset($encodedSettings[$row['NAME']]);
					continue;
				}
				if ($encodedSettings[$row['NAME']] === 'N')
				{
					$disabledSettings[] = [
						'GROUP_ID' => $groupId,
						'NAME' => $row['NAME']
					];
					unset($encodedSettings[$row['NAME']]);
				}
			}
		}

		foreach ($encodedSettings as $name => $value)
		{
			if (!array_key_exists($name, $defaultSettings))
			{
				continue;
			}

			$addedSettings[] = [
				'GROUP_ID' => $groupId,
				'NAME' => $name,
				'VALUE' => $value
			];
		}
		if (!empty($addedSettings))
		{
			OptionStateTable::addMulti($addedSettings, true);
		}
		if (!empty($enabledSettings))
		{
			OptionStateTable::updateMulti($enabledSettings, ['VALUE' => 'Y'], true);
		}
		if (!empty($disabledSettings))
		{
			OptionStateTable::updateMulti($disabledSettings, ['VALUE' => 'N'], true);
		}

	}

	/**
	 * Sets the group's notification settings
	 *
	 * @throws SystemException
	 * @throws ArgumentException
	 */
	public static function setSettings(int $groupId, array $settings = [], bool $forInitialize = false): void
	{
		if (empty($settings) && !$forInitialize)
		{
			return;
		}

		$selectedSettings = [];
		$query =
			OptionStateTable::query()
				->setSelect(['NAME', 'VALUE'])
				->where('GROUP_ID', $groupId)
				->whereLike('NAME', self::ENTITY . '%')
		;
		foreach ($query->exec() as $row)
		{
			$selectedSettings[$row['NAME']] = $row['VALUE'];
		}
		$defaultSettings = self::encodeSettings(self::getDefaultSettings());
		$encodedSettings = self::encodeSettings($settings);
		$encodedSettings = array_merge($defaultSettings, $encodedSettings);

		$rows = [];
		foreach ($encodedSettings as $name => $value)
		{
			if (!array_key_exists($name, $defaultSettings) || isset($selectedSettings[$name]))
			{
				continue;
			}

			$rows[] = [
				'GROUP_ID' => $groupId,
				'NAME' => $name,
				'VALUE' => $value
			];
		}

		OptionStateTable::multiplyInsertWithoutDuplicate($rows);
	}

	public static function getEventNames(): array
	{
		$names = [];
		$defaultSettings = self::getDefaultSettings();
		foreach ($defaultSettings as $moduleId => $notifyTypes)
		{
			$names[$moduleId]['NAME'] = $notifyTypes['NAME'];
			if ($notifyTypes['NAME'] == '')
			{
				$moduleObject = \CModule::CreateModuleObject($moduleId);
				$names[$moduleId]['NAME'] = $moduleObject->MODULE_NAME;
			}
			foreach ($notifyTypes['NOTIFY'] as $eventId => $event)
			{
				$names[$moduleId]['NOTIFY'][$eventId] = $event['NAME'];
			}
		}

		return $names;
	}

	/**
	 * Converts a flat array of templates into an array of notification schemes
	 *
	 * @param array $rowSettings
	 *
	 * @return array
	 */
	public static function decodeSettings(array $rowSettings): array
	{
		$decodedSettings = [];

		foreach ($rowSettings as $rowSetting)
		{
			if (!$rowSetting['NAME'])
			{
				continue;
			}

			$setting = self::decodeName($rowSetting['NAME']);

			if ($setting === null)
			{
				continue;
			}
			$module = $setting[self::MODULE];
			$name = $setting[self::NAME];

			if(!in_array((int)$setting[self::TYPE], [1,2,3,4]))
			{
				continue;
			}

			$type = self::getType((int)$setting[self::TYPE]);

			$decodedSettings[$module]['NOTIFY'][$name][$type] = $rowSetting['VALUE'] === 'Y';
		}

		return $decodedSettings;
	}

	/**
	 * Converts notification settings into a flat array,
	 * in which the key is a template, and the value is the value of the setting
	 *
	 * @param array $settings
	 *
	 * @return array
	 */
	public static function encodeSettings(array $settings): array
	{
		$encodedSettings = [];

		foreach ($settings as $moduleName => $notifies)
		{
			if (!is_array($notifies))
			{
				continue;
			}

			foreach ($notifies as $notify)
			{
				if (!is_array($notify))
				{
					continue;
				}

				foreach ($notify as $notifyName => $types)
				{
					foreach ($types as $type => $value)
					{
						$setting = self::encodeName($moduleName, $notifyName, $type);

						if (!$setting || mb_strlen($setting) > 64)
						{
							continue;
						}

						$encodedSettings[$setting] = $value ? 'Y' : 'N';
					}

				}
			}
		}

		return $encodedSettings;
	}

	/**
	 * Gets an array with the decoded template
	 *
	 * @param string $setting
	 *
	 * @return array|null
	 */
	private static function decodeName(string $setting): ?array
	{
		$row = explode(static::SEPARATOR, $setting);

		if (!array_key_exists(self::MODULE, $row)
			|| !array_key_exists(self::NAME, $row)
			|| !array_key_exists(self::TYPE, $row)
		)
		{
			return null;
		}

		return $row;
	}

	/**
	 * Gets a template string with encoded data: no|module_name|event_name|type
	 *
	 * @param string $module
	 * @param string $name
	 * @param string $type
	 *
	 * @return string|null
	 */
	private static function encodeName(string $module, string $name, string $type): ?string
	{
		if ($type === '')
		{
			return null;
		}

		$postfix = self::getPostfix($type);

		if ($postfix === null)
		{
			return null;
		}

		return implode(
			static::SEPARATOR,
			[
				static::ENTITY,
				$module,
				$name,
				$postfix,
			]
		);
	}

	/**
	 * @param string $type
	 *
	 * @return int|null
	 */
	private static function getPostfix(string $type): ?int
	{
		return self::$types[mb_strtoupper($type)] ?? null;
	}

	/**
	 * @param int $postfix
	 *
	 * @return string|null
	 */
	private static function getType(int $postfix): ?string
	{
		$arr = array_flip(self::$types);

		return $arr[$postfix];
	}

}

Youez - 2016 - github.com/yon3zu
LinuXploit