Your IP : 18.118.33.239


Current Path : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/landing/lib/
Upload File :
Current File : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/landing/lib/rights.php

<?php
namespace Bitrix\Landing;

use \Bitrix\Landing\Internals\RightsTable;
use \Bitrix\Main\Localization\Loc;
use \Bitrix\Main\UserAccessTable;

Loc::loadMessages(__FILE__);

class Rights
{
	/**
	 * Site entity type.
	 */
	const ENTITY_TYPE_SITE = 'S';

	/**
	 * Access types for different levels.
	 */
	const ACCESS_TYPES = [
		'denied' => 'denied',
		'read' => 'read',
		'edit' => 'edit',
		'sett' => 'sett',
		'public' => 'public',
		'delete' => 'delete'
	];

	/**
	 * Additional rights for some functionality.
	 */
	const ADDITIONAL_RIGHTS = [
		'menu24' => 'menu24',//show in main menu of Bitrix24
		'admin' => 'admin',//admin rights
		'create' => 'create',//can create new sites
		'unexportable' => 'unexportable',
		'knowledge_menu24' => 'knowledge_menu24',// show Knowledge in main menu of Bitrix24
		'knowledge_admin' => 'knowledge_admin',//admin rights
		'knowledge_create' => 'knowledge_create',//can create new Knowledge base
		'knowledge_unexportable' => 'knowledge_unexportable',
		'knowledge_extension' => 'knowledge_extension',
		'group_create' => 'group_create',//can create new social network group base
		'group_admin' => 'group_admin',//admin rights
		'group_menu24' => 'group_menu24',// show group in main menu of Bitrix24
		'group_unexportable' => 'group_unexportable',
	];

	const SET_PREFIX = [
		'knowledge',
		'group',
	];

	const REVERSE_RIGHTS = [
		'unexportable',
		'knowledge_unexportable',
		'group_unexportable',
	];

	/**
	 * Allowed site ids with full access.
	 * @var int[]
	 */
	protected static $allowedSites = [];

	/**
	 * If true, rights is not checking.
	 * @var bool
	 */
	protected static $available = true;

	/**
	 * If true, rights is not checking (global mode).
	 * @var bool
	 */
	protected static $globalAvailable = true;

	/**
	 * Context user id.
	 * @var int
	 */
	protected static $userId = null;

	/**
	 * Set rights checking to 'no'.
	 * @return void
	 */
	public static function setOff()
	{
		self::$available = false;
	}

	/**
	 * Set rights checking to 'yes'.
	 * @return void
	 */
	public static function setOn()
	{
		self::$available = true;
	}

	/**
	 * Set rights checking to 'no' (global mode).
	 * @return void
	 */
	public static function setGlobalOff()
	{
		self::$globalAvailable = false;
	}

	/**
	 * Set rights checking to 'yes' (global mode).
	 * @return void
	 */
	public static function setGlobalOn()
	{
		self::$globalAvailable = true;
	}

	/**
	 * Check current status for checking rights.
	 * @return bool
	 */
	public static function isOn()
	{
		if (
			defined('LANDING_DISABLE_RIGHTS') &&
			LANDING_DISABLE_RIGHTS === true
		)
		{
			return false;
		}
		if (!self::$globalAvailable)
		{
			return false;
		}
		return self::$available;
	}

	/**
	 * Current user is admin or not.
	 * @return bool
	 */
	public static function isAdmin()
	{
		if (self::hasAdditionalRight(self::ADDITIONAL_RIGHTS['admin'], null, false, true))
		{
			return true;
		}
		return Manager::isAdmin();
	}

	/**
	 * Returns allowed sites with full access.
	 * @return int[]
	 */
	public static function getAllowedSites(): array
	{
		return self::$allowedSites;
	}

	/**
	 * Sets context user id.
	 * @param int $uid
	 * @return void
	 */
	public static function setContextUserId(int $uid): void
	{
		self::$userId = $uid;
	}

	/**
	 * Clears context user id.
	 * @return void
	 */
	public static function clearContextUserId(): void
	{
		self::$userId = null;
	}

	/**
	 * Returns context user id (current by default).
	 * @return int
	 */
	public static function getContextUserId(): int
	{
		if (!self::$userId)
		{
			self::$userId = Manager::getUserId();
		}
		return self::$userId;
	}

	/**
	 * Available or not permission feature by current plan.
	 * @return bool
	 */
	protected static function isFeatureOn()
	{
		return Manager::checkFeature(
			Manager::FEATURE_PERMISSIONS_AVAILABLE
		);
	}

	/**
	 * Gets tasks for access.
	 * @return array
	 */
	public static function getAccessTasks()
	{
		static $tasks = [];

		if (empty($tasks))
		{
			$res = \CTask::getList(
				['LETTER' => 'ASC'],
				['MODULE_ID' => 'landing']
			);
			while ($row = $res->fetch())
			{
				$row['NAME'] = mb_substr($row['NAME'], 14);
				$tasks[$row['ID']] = $row;
			}
		}

		return $tasks;
	}

	/**
	 * Gets tasks for access.
	 * @return array
	 */
	public static function getAccessTasksReferences()
	{
		static $tasks = [];

		if (empty($tasks))
		{
			foreach (self::getAccessTasks() as $accessTask)
			{
				$tasks[$accessTask['NAME']] = $accessTask['ID'];
			}
		}

		return $tasks;
	}

	/**
	 * Remove all rows for entity.
	 * @param int|array $entityId Entity id (id or array of id).
	 * @param string $entityType Entity type.
	 * @return void
	 */
	protected static function removeData($entityId, $entityType)
	{
		if (self::isFeatureOn())
		{
			$res = RightsTable::getList([
				'select' => [
					'ID'
				],
				'filter' => [
					'ENTITY_ID' => $entityId,
					'=ENTITY_TYPE' => $entityType
				]
			]);
			while ($row = $res->fetch())
			{
				RightsTable::delete($row['ID']);
			}
		}
	}

	/**
	 * Remove all rows for site.
	 * @param int|array $siteId Site id (id or array of id).
	 * @return void
	 */
	public static function removeDataForSite($siteId)
	{
		self::removeData(
			$siteId,
			self::ENTITY_TYPE_SITE
		);
	}

	/**
	 * Get all rows for entity.
	 * @param int|array $entityId Entity id (id or array of id).
	 * @param string $entityType Entity type.
	 * @param array $preDefined Predefined array of rights.
	 * @return array
	 */
	protected static function getData($entityId, $entityType, array $preDefined = [])
	{
		static $access = null;
		$items = [];
		$codes = [];

		if ($access === null)
		{
			$access = new \CAccess;
		}

		// filter (with predefined_
		$filter = [
			'ENTITY_ID' => $entityId,
			'=ENTITY_TYPE' => $entityType
		];
		if ($preDefined)
		{
			$filter['=ACCESS_CODE'] = array_keys($preDefined);
		}

		// main query
		$res = RightsTable::getList([
			'select' => [
				'TASK_ID',
				'ACCESS_CODE'
			],
			'filter' => $filter
		]);
		while ($row = $res->fetch())
		{
			$codes[] = $row['ACCESS_CODE'];
			if (!isset($items[$row['ACCESS_CODE']]))
			{
				$row['TASK_ID'] = [$row['TASK_ID']];
				$items[$row['ACCESS_CODE']] = $row;
			}
			else
			{
				$items[$row['ACCESS_CODE']]['TASK_ID'][] = $row['TASK_ID'];
			}
			if (isset($preDefined[$row['ACCESS_CODE']]))
			{
				unset($preDefined[$row['ACCESS_CODE']]);
			}
		}

		$items = array_values($items);

		// fill with predefined
		foreach ($preDefined as $accessCode => $rightCode)
		{
			$items[] = [
				'TASK_ID' => $rightCode,
				'ACCESS_CODE' => $accessCode
			];
			$codes[] = $accessCode;
		}

		// get titles
		if ($items)
		{
			$codesNames  = $access->getNames($codes);
			foreach ($items as &$item)
			{
				if (isset($codesNames[$item['ACCESS_CODE']]))
				{
					$item['ACCESS_PROVIDER'] = (
								isset($codesNames[$item['ACCESS_CODE']]['provider']) &&
								$codesNames[$item['ACCESS_CODE']]['provider']
							)
						? $codesNames[$item['ACCESS_CODE']]['provider']
						: '';
					$item['ACCESS_NAME'] = isset($codesNames[$item['ACCESS_CODE']]['name'])
						? $codesNames[$item['ACCESS_CODE']]['name']
						: $item['ACCESS_CODE'];
				}
			}
			unset($item);
		}

		return $items;
	}

	/**
	 * Get all rows for site.
	 * @param int|array $siteId Site id (id or array of id).
	 * @param array $preDefined Predefined array of rights.
	 * @return array
	 */
	public static function getDataForSite($siteId, array $preDefined = [])
	{
		return self::getData(
			$siteId,
			self::ENTITY_TYPE_SITE,
			$preDefined
		);
	}

	/**
	 * Get all available operations for entity (for current user).
	 * @param int|array $entityId Entity id (id or array of id).
	 * @param string $entityType Entity type.
	 * @return array
	 */
	protected static function getOperations($entityId, $entityType)
	{
		// full access for allowed sites
		if (
			$entityType == self::ENTITY_TYPE_SITE &&
			in_array($entityId, self::$allowedSites)
		)
		{
			$types = self::ACCESS_TYPES;
			unset($types[self::ACCESS_TYPES['delete']]);
			return array_values($types);
		}

		// check scoped method
		if (
			$entityType == self::ENTITY_TYPE_SITE
			&& !is_array($entityId) && $entityId > 0
		)
		{
			$scopeOperationsSite = Site\Type::getOperationsForSite($entityId);
			if ($scopeOperationsSite !== null)
			{
				return array_values($scopeOperationsSite);
			}
		}

		$operations = [];
		$operationsDefault = [];
		$wasChecked = false;
		$uid = self::getContextUserId();
		$extendedMode = self::isExtendedMode();

		// full access for admin
		if (
			$uid &&
			self::isOn() &&
			!self::isAdmin() &&
			self::isFeatureOn() &&
			self::exist()
		)
		{
			$wasChecked = true;
			$entityIdFilter = $entityId;
			if (is_array($entityIdFilter))
			{
				$entityIdFilter[] = 0;
			}
			else
			{
				$entityIdFilter = [
					$entityIdFilter, 0
				];
			}
			$filter = [
				'ENTITY_ID' => $entityIdFilter,
				'=ENTITY_TYPE' => $entityType,
				'USER_ACCESS.USER_ID' => $uid,
				'!TASK_OPERATION.OPERATION.NAME' => false
			];
			if ($extendedMode)
			{
				$filter['ROLE_ID'] = 0;
			}
			else
			{
				$filter['ROLE_ID'] = Role::getExpectedRoleIds();
			}
			$res = RightsTable::getList(
				[
					'select' => [
						'ENTITY_ID',
						'OPERATION_NAME' => 'TASK_OPERATION.OPERATION.NAME'
					],
					'filter' => $filter
				]
			);
			while ($row = $res->fetch())
			{
				if ($row['ENTITY_ID'] == 0)
				{
					$operationsDefault[] = mb_substr($row['OPERATION_NAME'], 8);
					continue;
				}
				if (!isset($operations[$row['ENTITY_ID']]))
				{
					$operations[$row['ENTITY_ID']] = array();
				}
				$operations[$row['ENTITY_ID']][] = mb_substr($row['OPERATION_NAME'], 8);
				$operations[$row['ENTITY_ID']] = array_unique($operations[$row['ENTITY_ID']]);
			}
		}

		// set full rights, if rights are empty
		foreach ((array) $entityId as $id)
		{
			if (!isset($operations[$id]))
			{
				if ($wasChecked && !$extendedMode)
				{
					$operations[$id] = !empty($operationsDefault)
						? $operationsDefault
						: [self::ACCESS_TYPES['denied']];
				}
				else
				{
					$operations[$id] = array_values(self::ACCESS_TYPES);
				}
			}
		}

		return is_array($entityId)
				? $operations
				: $operations[$entityId];
	}

	/**
	 * Returns  all available operations for site (for current user).
	 * @param int|array $siteId Site id (id or array of id).
	 * @return array
	 */
	public static function getOperationsForSite($siteId): array
	{
		if (
			is_array($siteId) ||
			$siteId == 0 ||
			Site::ping($siteId, true)
		)
		{
			return self::getOperations(
				$siteId,
				self::ENTITY_TYPE_SITE
			);
		}
		else
		{
			return [];
		}
	}

	/**
	 * Can current user do something.
	 * @param int $siteId Site id.
	 * @param string $accessType Access type code.
	 * @param bool $deleted And from recycle bin.
	 * @return boolean
	 */
	public static function hasAccessForSite($siteId, $accessType, $deleted = false)
	{
		static $operations = [];
		$siteId = intval($siteId);

		if (!is_string($accessType))
		{
			return false;
		}

		if (!isset($operations[$siteId]))
		{
			if ($siteId === 0 || !self::isOn() || Site::ping($siteId, $deleted))
			{
				$operations[$siteId] = self::getOperations(
					$siteId,
					self::ENTITY_TYPE_SITE
				);
			}
			else
			{
				$operations[$siteId] = [];
			}
		}

		return in_array($accessType, $operations[$siteId]);
	}

	/**
	 * Can current user do something.
	 * @param int $landingId Landing id.
	 * @param string $accessType Access type code.
	 * @return boolean
	 */
	public static function hasAccessForLanding($landingId, $accessType)
	{
		static $operations = [];
		$landingId = intval($landingId);

		if (!is_string($accessType))
		{
			return false;
		}

		if (!isset($operations[$landingId]))
		{
			$site = Landing::getList([
 				'select' => [
					'SITE_ID'
				],
				'filter' => [
					'ID' => $landingId,
					'=SITE.DELETED' => ['Y', 'N'],
					'=DELETED' => ['Y', 'N']
				]
			])->fetch();

			if ($site)
			{
				$operations[$landingId] = self::getOperations(
					$site['SITE_ID'],
					self::ENTITY_TYPE_SITE
				);
			}
			else
			{
				$operations[$landingId] = [];
			}
		}

		return in_array($accessType, $operations[$landingId]);
	}

	/**
	 * Set operations for entity.
	 * @param int $entityId Entity id.
	 * @param string $entityType Entity type.
	 * @param array $rights Rights array (set empty for clear rights).
	 * @return boolean
	 */
	protected static function setOperations($entityId, $entityType, array $rights = [])
	{
		if (!self::isFeatureOn())
		{
			return false;
		}

		$tasks = self::getAccessTasksReferences();
		$entityId = intval($entityId);

		self::removeData(
			$entityId,
			$entityType
		);

		// add new rights
		foreach ($rights as $accessCode => $rightCodes)
		{
			$rightCodes = (array) $rightCodes;
			if (in_array(self::ACCESS_TYPES['denied'], $rightCodes))
			{
				$rightCodes = [self::ACCESS_TYPES['denied']];
			}
			else if (!in_array(self::ACCESS_TYPES['read'], $rightCodes))
			{
				$rightCodes[] = self::ACCESS_TYPES['read'];
			}

			foreach ($rightCodes as $rightCode)
			{
				if (isset($tasks[$rightCode]))
				{
					RightsTable::add([
						'ENTITY_ID' => $entityId,
						'ENTITY_TYPE' => $entityType,
						'TASK_ID' => $tasks[$rightCode],
						'ACCESS_CODE' => $accessCode
					]);
				}
			}
		}

		return true;
	}

	/**
	 * Set operations for site.
	 * @param int $siteId Site id.
	 * @param array $rights Rights array (set empty for clear rights).
	 * @return bool
	 */
	public static function setOperationsForSite($siteId, array $rights = [])
	{
		$siteId = intval($siteId);

		if ($siteId == 0 || Site::ping($siteId))
		{
			return self::setOperations(
				$siteId,
				self::ENTITY_TYPE_SITE,
				$rights
			);
		}
		else
		{
			return false;
		}
	}

	/**
	 * If any records of rights exists.
	 * @return bool
	 */
	protected static function exist()
	{
		static $exist = null;

		if ($exist === null)
		{
			$type = Site\Type::getCurrentScopeId();
			$res = RightsTable::getList([
				'select' => [
					'ID'
				],
				'filter' => $type
						? ['=ROLE.TYPE' => $type]
						: [],
				'limit' => 1
			]);
			$exist = (bool) $res->fetch();
		}

		return $exist;
	}

	/**
	 * Gets access filter for current user.
	 * @param array $additionalFilterOr Additional filter for OR section.
	 * @return array
	 */
	public static function getAccessFilter(array $additionalFilterOr = [])
	{
		$filter = [];

		if (
			self::isOn() &&
			!self::isAdmin() &&
			self::isFeatureOn() &&
			self::exist()
		)
		{
			$tasks = self::getAccessTasksReferences();
			$extendedRights = self::isExtendedMode();
			$uid = self::getContextUserId();

			if ($extendedRights)
			{
				$filter[] = [
					'LOGIC' => 'OR',
					[
						'!RIGHTS.TASK_ID' => $tasks[Rights::ACCESS_TYPES['denied']],
						'RIGHTS.USER_ACCESS.USER_ID' => $uid
					],
					[
						'=RIGHTS.TASK_ID' => null
					],
					$additionalFilterOr
				];
			}
			else
			{
				if ($additionalFilterOr)
				{
					$filter[] = [
						'LOGIC' => 'OR',
						[
							'!RIGHTS.TASK_ID' => $tasks[Rights::ACCESS_TYPES['denied']],
							'RIGHTS.USER_ACCESS.USER_ID' => $uid
						],
						$additionalFilterOr
					];
				}
				else
				{
					$filter['RIGHTS.USER_ACCESS.USER_ID'] = $uid;
					$filter['!RIGHTS.TASK_ID'] = $tasks[Rights::ACCESS_TYPES['denied']];
				}
			}
		}

		return $filter;
	}

	/**
	 * Extended mode available.
	 * @return bool
	 */
	public static function isExtendedMode()
	{
		if (Manager::isB24())
		{
			return Manager::getOption('rights_extended_mode', 'N') == 'Y';
		}
		else
		{
			return true;
		}
	}

	/**
	 * Switch extended mode.
	 * @return void
	 */
	public static function switchMode()
	{
		if (self::isFeatureOn())
		{
			$current = Manager::getOption('rights_extended_mode', 'N');
			$current = ($current == 'Y') ? 'N' : 'Y';
			Manager::setOption('rights_extended_mode', $current);
		}
	}

	/**
	 * Refresh additional rights for all roles.
	 * @param array $additionalRights Array for set additional.
	 * @return void
	 */
	public static function refreshAdditionalRights(array $additionalRights = [])
	{
		if (!self::isFeatureOn())
		{
			return;
		}

		$rights = [];
		foreach (self::ADDITIONAL_RIGHTS as $right)
		{
			$rights[$right] = [];
		}

		// get additional from all roles
		$res = Role::getList([
			'select' => [
				'ID', 'ACCESS_CODES', 'ADDITIONAL_RIGHTS'
			]
		]);
		while ($row = $res->fetch())
		{
			$row['ACCESS_CODES'] = (array) $row['ACCESS_CODES'];
			$row['ADDITIONAL_RIGHTS'] = (array) $row['ADDITIONAL_RIGHTS'];
			foreach ($row['ADDITIONAL_RIGHTS'] as $right)
			{
				if (isset($rights[$right]))
				{
					$rights[$right][$row['ID']] = $row['ACCESS_CODES'];
				}
			}
		}

		// refresh options
		foreach ($rights as $code => $right)
		{
			// gets current from option
			$option = Manager::getOption('access_codes_' . $code, '');
			$option = unserialize($option, ['allowed_classes' => false]);
			if (isset($option[0]))
			{
				$right[0] = $option[0];
			}

			// rewrite some rights, if need
			if (
				isset($additionalRights[$code]) &&
				is_array($additionalRights[$code])
			)
			{
				foreach ($additionalRights[$code] as $i => $accCodes)
				{
					$right[$i] = (array) $accCodes;
				}
			}

			// set new rights in option
			Manager::setOption('access_codes_' . $code, $right ? serialize($right) : '');

			// clear menu cache
			if (Manager::isB24())
			{
				Manager::getCacheManager()->clearByTag(
					'bitrix24_left_menu'
				);
				Manager::getCacheManager()->cleanDir(
					'menu'
				);
				\CBitrixComponent::clearComponentCache(
					'bitrix:menu'
				);
			}
		}
	}

	/**
	 * Set additional right.
	 * @param string $code Code from ADDITIONAL_RIGHTS.
	 * @param array $accessCodes Additional rights array.
	 * @return void
	 */
	public static function setAdditionalRightExtended($code, array $accessCodes = [])
	{
		if (!is_string($code))
		{
			return;
		}
		self::refreshAdditionalRights([
		  	$code => [
				0 => $accessCodes
			]
		]);
	}

	/**
	 * Gets additional right.
	 * @param string $code Code from ADDITIONAL_RIGHTS.
	 * @return array
	 */
	public static function getAdditionalRightExtended($code)
	{
		static $access = null;
		$return = [];

		if (!is_string($code))
		{
			return $return;
		}
		if ($access === null)
		{
			$access = new \CAccess;
		}

		$option = Manager::getOption('access_codes_' . $code, '');
		$option = unserialize($option, ['allowed_classes' => false]);
		$accessCodes = isset($option[0]) ? (array)$option[0] : [];
		$codesNames  = $access->getNames($accessCodes);

		foreach ($accessCodes as $code)
		{
			if (isset($codesNames[$code]))
			{
				$provider = (
					isset($codesNames[$code]['provider']) &&
					$codesNames[$code]['provider']
				)
					? $codesNames[$code]['provider']
					: '';
				$name = isset($codesNames[$code]['name'])
					? $codesNames[$code]['name']
					: $code;
				$return[$code] = [
					'CODE' => $code,
					'PROVIDER' => $provider,
					'NAME' => $name
				];
			}
		}

		return $return;
	}

	/**
	 * Gets additional rights with labels.
	 * @return array
	 */
	public static function getAdditionalRightsLabels()
	{
		$rights = [];

		$type = Site\Type::getCurrentScopeId();

		foreach (self::ADDITIONAL_RIGHTS as $right)
		{
			if (mb_strpos($right, '_') > 0)
			{
				[$prefix, ] = explode('_', $right);
				$prefix = mb_strtoupper($prefix);
				if ($prefix != $type)
				{
					continue;
				}
			}
			else if ($type !== null)
			{
				continue;
			}
			$rights[$right] = Loc::getMessage('LANDING_RIGHTS_R_'.mb_strtoupper($right));
		}

		return $rights;
	}

	/**
	 * Has user some extra access?
	 * @return bool
	 */
	protected static function hasExtraRights(): bool
	{
		// has context user access to crm forms
		if (\Bitrix\Main\Loader::includeModule('crm'))
		{
			$access = new \CCrmPerms(self::getContextUserId());
			if (!$access->havePerm('WEBFORM', BX_CRM_PERM_NONE, 'WRITE'))
			{
				// grant access to crm forms sites
				$res = Site::getList([
					'select' => [
						'ID'
					],
					'filter' => [
						'CODE' => '/' . Site\Type::PSEUDO_SCOPE_CODE_FORMS . '%',
						'=SPECIAL' => 'Y',
						'CHECK_PERMISSIONS' => 'N'
					]
				]);
				while ($row = $res->fetch())
				{
					self::$allowedSites[] = $row['ID'];
				}

				return true;
			}
		}
		return false;
	}

	/**
	 * Has current user additional right or not.
	 * @param string $code Code from ADDITIONAL_RIGHTS.
	 * @param string $type Scope type.
	 * @param bool $checkExtraRights Check extra rights.
	 * @return bool
	 */
	public static function hasAdditionalRight($code, $type = null, bool $checkExtraRights = false, bool $strict = false)
	{
		static $options = [];

		if ($checkExtraRights && self::hasExtraRights())
		{
			return true;
		}

		if (!is_string($code))
		{
			return false;
		}
		if ($type === null)
		{
			$type = Site\Type::getCurrentScopeId();
		}

		if ($type !== null)
		{
			$type = mb_strtolower($type);
			//@todo: hotfix for group right
			if ($type == Site\Type::SCOPE_CODE_GROUP)
			{
				return true;
			}
			$code = $type . '_' . $code;
		}

		if (array_key_exists($code, self::ADDITIONAL_RIGHTS))
		{
			if (!self::isFeatureOn())
			{
				return true;
			}

			if (!self::getContextUserId())
			{
				return false;
			}

			if (Manager::isAdmin())
			{
				if (in_array($code, self::REVERSE_RIGHTS))
				{
					return false;
				}
				return true;
			}

			$accessCodes = [];
			if (!isset($options[$code]))
			{
				$options[$code] = Manager::getOption('access_codes_' . $code, '');
				$options[$code] = unserialize($options[$code], ['allowed_classes' => false]);
			}
			$option = $options[$code];

			if (!is_array($option) && !$strict)
			{
				return true;
			}

			if (empty($option))
			{
				return false;
			}

			if (self::isExtendedMode())
			{
				if (isset($option[0]) && is_array($option[0]))
				{
					$accessCodes = $option[0];
				}
			}
			else
			{
				if (isset($option[0]))
				{
					unset($option[0]);
				}
				foreach ($option as $roleAccess)
				{
					$accessCodes = array_merge($accessCodes, (array)$roleAccess);
				}
				$accessCodes = array_unique($accessCodes);
			}

			if ($accessCodes)
			{
				static $accessCodesStatic = [];

				sort($accessCodes);
				$accessCodesStr = implode('|', $accessCodes);

				if (array_key_exists($accessCodesStr, $accessCodesStatic))
				{
					return $accessCodesStatic[$accessCodesStr];
				}

				$res = UserAccessTable::getList([
					'select' => [
						'USER_ID'
					],
					'filter' => [
						'=ACCESS_CODE' => $accessCodes,
						'USER_ID' => self::getContextUserId()
					]
				]);
				$accessCodesStatic[$accessCodesStr] = (boolean)$res->fetch();
				return $accessCodesStatic[$accessCodesStr];
			}

			return false;
		}

		return false;
	}
}