• Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/lib/security/controller/querybuilder/controllerbased.php
  • Класс: Bitrix\Crm\Security\Controller\QueryBuilder\ControllerBased
  • Вызов: ControllerBased::getRestrictionsByAttributes
protected function getRestrictionsByAttributes(Collection $attributesCollection, Options $options): array
{
	$restrictionData = [];
	$userDepartmentIDs = $this->getUserDepartmentIDs($attributesCollection->getUserId());

	$permissionEntityTypes = $attributesCollection->getAllowedEntityTypes();

	foreach ($permissionEntityTypes as $permissionEntityType)
	{
		$entityAttributes = $attributesCollection->getByEntityType($permissionEntityType);
		if (empty($entityAttributes))
		{
			continue;
		}

		$permissionSets = [];
		foreach ($entityAttributes as $attributes)
		{
			if (empty($attributes))
			{
				continue;
			}

			$permissionSet = [
				'USER_ID' => 0,
				'DEPARTMENT_IDS' => [],
				'PROGRESS_STEPS' => [],
				'OPENED' => false,
			];
			for ($i = 0, $length = count($attributes); $i < $length; $i++)
			{
				$attributeValue = $attributes[$i];

				$parsedAttributeValue = '';

				if (
					$this->controller->hasProgressSteps()
					&& $this->controller->tryParseProgressStep($attributeValue, $parsedAttributeValue)
					&& $parsedAttributeValue != ''
				)
				{
					$permissionSet['PROGRESS_STEPS'][] = $parsedAttributeValue;
				}
				elseif ($attributeValue === 'O')
				{
					$permissionSet['OPENED'] = true;
				}
				elseif ($this->tryParseUser($attributeValue, $parsedAttributeValue) && $parsedAttributeValue > 0)
				{
					$permissionSet['USER_ID'] = (int)$parsedAttributeValue;
				}
				elseif ($this->tryParseDepartment($attributeValue, $parsedAttributeValue) && $parsedAttributeValue > 0)
				{
					$permissionSet['DEPARTMENT_IDS'][] = (int)$parsedAttributeValue;
				}
			}

			$permissionSets[] = $permissionSet;
			if ($permissionSet['OPENED']) // if opened are allowed, also my and my department are allowed
			{
				$permissionSets[] = [
					'USER_ID' => $attributesCollection->getUserId(),
					'DEPARTMENT_IDS' => [],
					'PROGRESS_STEPS' => $permissionSet['PROGRESS_STEPS'],
					'OPENED' => false,
				];

				if (!empty($userDepartmentIDs))
				{
					$permissionSets[] = [
						'USER_ID' => 0,
						'DEPARTMENT_IDS' => $userDepartmentIDs,
						'PROGRESS_STEPS' => $permissionSet['PROGRESS_STEPS'],
						'OPENED' => false,
					];
				}
			}
		}

		$permissionFurl = [];
		foreach ($permissionSets as $permissionSet)
		{
			$userID = $permissionSet['USER_ID'];
			$departmentIDs = $permissionSet['DEPARTMENT_IDS'];
			$isOpened = $permissionSet['OPENED'];
			if (!empty($departmentIDs))
			{
				sort($departmentIDs, SORT_NUMERIC);
			}
			$hash = md5(
				'U:' . $userID
				. 'D:' . (!empty($departmentIDs) ? implode(',', $departmentIDs) : '-')
				. 'O:' . ($isOpened ? 'Y' : 'N'));

			if (!isset($permissionFurl[$hash]))
			{
				$permissionFurl[$hash] = $permissionSet;
			}
			elseif (!empty($permissionSet['PROGRESS_STEPS']))
			{
				$permissionFurl[$hash]['PROGRESS_STEPS'] = array_merge(
					$permissionFurl[$hash]['PROGRESS_STEPS'],
					array_diff(
						$permissionSet['PROGRESS_STEPS'],
						$permissionFurl[$hash]['PROGRESS_STEPS']
					)
				);
			}
		}
		$permissionSets = array_values($permissionFurl);

		$restrictionData[$permissionEntityType] = [];
		foreach ($permissionSets as $permissionSet)
		{
			$hash = '-';
			$progressSteps = $permissionSet['PROGRESS_STEPS'];
			if (!empty($progressSteps))
			{
				sort($progressSteps, SORT_STRING);
				$hash = md5(implode(',', $permissionSet['PROGRESS_STEPS']));
			}

			if (!isset($restrictionData[$permissionEntityType][$hash]))
			{
				$restriction = ['PROGRESS_STEPS' => $progressSteps];
			}
			else
			{
				$restriction = $restrictionData[$permissionEntityType][$hash];
			}

			if ($permissionSet['OPENED'])
			{
				$restriction['OPENED'] = true;
			}

			$userID = $permissionSet['USER_ID'];
			if ($userID > 0)
			{
				if (!isset($restriction['USER_IDS']))
				{
					$restriction['USER_IDS'] = [];
				}
				if (!in_array($userID, $restriction['USER_IDS'], true))
				{
					$restriction['USER_IDS'][] = $userID;
				}
			}

			if (!empty($permissionSet['DEPARTMENT_IDS']))
			{
				if (!isset($restriction['USER_IDS']))
				{
					$restriction['USER_IDS'] = [];
				}
				$restriction['USER_IDS'] = array_unique(
					array_merge(
						$restriction['USER_IDS'],
						$this->getDepartmentsUsers($permissionSet['DEPARTMENT_IDS'])
					)
				);
			}
			$restrictionData[$permissionEntityType][$hash] = $restriction;
		}
	}

	$canSkipCategoryRestrictions = false;
	if ($options->canSkipCheckOtherEntityTypes())
	{
		$canSkipCategoryRestrictions = $attributesCollection->areAllEntityTypesAllowed();
		if ($canSkipCategoryRestrictions)
		{
			foreach ($restrictionData as $restrictions)
			{
				if (empty($restrictions))
				{
					continue;
				}
				foreach ($restrictions as $restriction)
				{
					if (
						!(
							count($restriction) === 1
							&& isset($restriction['PROGRESS_STEPS'])
							&& empty($this->getProgressSteps($permissionEntityType, $restriction))
						)
					)
					{
						$canSkipCategoryRestrictions = false;
						break;
					}
				}
			}
		}
	}

	$restrictionMap = [];
	foreach ($restrictionData as $permissionEntityType => $restrictions)
	{
		if (empty($restrictions))
		{
			if (!isset($restrictionMap['-']))
			{
				$restrictionMap['-'] = [];
			}
			$this->addTypeAndCategoryToRestrictionMap(
				$restrictionMap['-'],
				$permissionEntityType,
				$canSkipCategoryRestrictions
			);

			continue;
		}

		foreach ($restrictions as $restriction)
		{
			$isProcessed = false;

			$progressSteps = $this->getProgressSteps($permissionEntityType, $restriction);

			$userIDs = isset($restriction['USER_IDS']) ? $restriction['USER_IDS'] : [];
			if (!empty($userIDs))
			{
				sort($userIDs, SORT_NUMERIC);

				$hash = md5(
					(!empty($progressSteps) ? $permissionEntityType . ':' . implode(',', $progressSteps) : '-')
					. 'U:' . (!empty($userIDs) ? implode(',', $userIDs) : '-')
				);

				if (!isset($restrictionMap[$hash]))
				{
					$restrictionMap[$hash] = [
						'PROGRESS_STEPS' => $progressSteps,
						'USER_IDS' => $userIDs,
					];
				}
				$this->addTypeAndCategoryToRestrictionMap(
					$restrictionMap[$hash],
					$permissionEntityType
				);

				$isProcessed = true;
			}

			$isOpened = isset($restriction['OPENED']) && $restriction['OPENED'];
			if ($isOpened)
			{
				$hash = md5(
					(!empty($progressSteps) ? $permissionEntityType . ':' . implode(',', $progressSteps) : '-')
					. 'O:' . ($isOpened ? 'Y' : 'N')
				);

				if (!isset($restrictionMap[$hash]))
				{
					$restrictionMap[$hash] = [
						'PROGRESS_STEPS' => $progressSteps,
						'OPENED' => true,
					];
				}
				$this->addTypeAndCategoryToRestrictionMap(
					$restrictionMap[$hash],
					$permissionEntityType
				);

				$isProcessed = true;
			}

			if (!$isProcessed)
			{
				$hash = md5(
					!empty($progressSteps) ? $permissionEntityType . ':' . implode(',', $progressSteps) : '-'
				);

				if (!isset($restrictionMap[$hash]))
				{
					$restrictionMap[$hash] = [
						'PROGRESS_STEPS' => $progressSteps,
					];
				}
				$this->addTypeAndCategoryToRestrictionMap(
					$restrictionMap[$hash],
					$permissionEntityType,
					$canSkipCategoryRestrictions
				);
			}
		}
	}

	return $restrictionMap;
}