- Модуль: iblock
- Путь к файлу: ~/bitrix/modules/iblock/lib/Controller/DefaultElement.php
- Класс: BitrixIblockControllerDefaultElement
- Вызов: DefaultElement::checkFields
static function checkFields($fields, Entity $entity)
{
$propertyEntityAllowedList = static::getPropertyEntityAllowedList();
$elementEntityAllowedList = static::getElementEntityAllowedList();
$allowedList = array_merge($elementEntityAllowedList, static::getAllowedList());
// replace REF.* for allowed fields REF.ALLOWED1, REF.ALLOWED2, etc.
$chainReplacement = [];
// analyze
foreach ($fields as $definition)
{
// check allowed list
if (in_array($definition, $allowedList, true))
{
continue;
}
// smart check for relations and property fields
$chain = Chain::getChainByDefinition($entity, $definition);
$currentDefinition = '';
$elements = $chain->getAllElements();
$lastElement = $chain->getLastElement();
foreach ($elements as $element)
{
$isLastElement = ($element === $lastElement);
// skip init entity
if ($element->getValue() instanceof ElementEntity && !$isLastElement)
{
continue;
}
// append definition
$currentDefinition = Chain::appendDefinition($currentDefinition, $element->getDefinitionFragment());
// handle wildcard
if ($currentDefinition === '*' && $isLastElement)
{
$chainReplacement[$definition] = [];
foreach ($elementEntityAllowedList as $allowedFieldName)
{
if ($entity->hasField($allowedFieldName))
{
$chainReplacement[$definition][] = $allowedFieldName;
}
}
continue;
}
// check access
if (!($element->getValue() instanceof Field))
{
throw new ArgumentException(
sprintf('Restricted field `%s`', $currentDefinition)
);
}
$currentField = $element->getValue();
$currentEntity = $currentField->getEntity();
// case 1. iblock
if ($currentEntity instanceof ElementEntity)
{
// case 1.1. iblock scalar
if (in_array($currentField->getName(), $elementEntityAllowedList, true))
{
continue;
}
// case 1.2. iblock property
if (!empty(class_uses($currentField)[PropertyRelation::class]))
{
if ($isLastElement)
{
// replace * with allowed fields
$propEntity = $currentField->getRefEntity();
$chainReplacement[$definition] = [];
foreach ($propertyEntityAllowedList as $allowedFieldName)
{
if ($propEntity->hasField($allowedFieldName))
{
$chainReplacement[$definition][] = Chain::appendDefinition($currentDefinition, $allowedFieldName);
}
}
}
continue;
}
}
// case 2. property entity
if ($currentEntity instanceof ValueStorageEntity)
{
// case 2.1. property scalar
if (in_array($currentField->getName(), $propertyEntityAllowedList, true))
{
continue;
}
// case 2.1. ref to another iblock
if ($currentField instanceof Reference)
{
$refEntity = $currentField->getRefEntity();
// check if remote iblock is readable
if ($refEntity instanceof ElementEntity && $refEntity->getIblock()->fillRestOn())
{
if ($isLastElement)
{
// replace * with allowed fields
$chainReplacement[$definition] = [];
foreach ($elementEntityAllowedList as $allowedFieldName)
{
if ($refEntity->hasField($allowedFieldName))
{
$chainReplacement[$definition][] = Chain::appendDefinition($currentDefinition, $allowedFieldName);
}
}
}
continue;
}
}
}
// restricted by default
throw new ArgumentException(
sprintf('Restricted field `%s`', $currentDefinition)
);
}
}
// time to replace *
foreach ($chainReplacement as $definition => $replacement)
{
// unset original
$key = array_search($definition, $fields);
unset($fields[$key]);
// add replacement
$fields = array_merge($fields, $replacement);
}
return $fields;
}