- Модуль: main
- Путь к файлу: ~/bitrix/modules/main/classes/general/entity_query_chain.php
- Класс: CEntityQueryChain
- Вызов: CEntityQueryChain::getChainByDefinition
static function getChainByDefinition(CBaseEntity $init_entity, $definition)
{
$chain = new CEntityQueryChain;
$chain->addElement(new CEntityQueryChainElement($init_entity));
$def_elements = explode('.', $definition);
$def_elements_size = count($def_elements);
$prev_entity = $init_entity;
$i = 0;
foreach ($def_elements as &$def_element)
{
$is_first_elem = ($i == 0);
$is_last_elem = (++$i == $def_elements_size);
// all elements should be a Reference field or Entity
// normal (scalar) field can only be the last element
if ($prev_entity->hasField($def_element))
{
// field has been found at current entity
$field = $prev_entity->getField($def_element);
if ($field instanceof CReferenceEntityField)
{
$prev_entity = $field->getRefEntity();
}
elseif ($field instanceof CExpressionEntityField)
{
// expr can be in the middle too
}
elseif (!$is_last_elem)
{
throw new Exception(sprintf(
'Normal fields can be only the last in chain, `%s` %s is not the last.',
$field->getName(), get_class($field)
));
}
if ($is_last_elem && $field instanceof CExpressionEntityField)
{
// we should have own copy of build_from_chains to set join aliases there
$field = clone $field;
}
$chain->addElement(new CEntityQueryChainElement($field));
}
elseif ($prev_entity->hasUField($def_element))
{
// extend chain with utm/uts entity
$ufield = $prev_entity->getUField($def_element);
$u_entity = null;
if ($ufield->isMultiple())
{
// add utm entity user.utm:source_object (1:N)
$utm_entity = CBaseEntity::getInstance('Utm'.$prev_entity->getName());
$u_entity = $utm_entity;
$chain->addElement(new CEntityQueryChainElement(
array($utm_entity, $utm_entity->getField('SOURCE_OBJECT')),
array('ufield' => $ufield)
));
if ($ufield->getTypeId() == 'iblock_section'
&& substr($ufield->getName(), -3) == '_BY'
&& $prev_entity->hasUField(substr($ufield->getName(), 0, -3))
)
{
// connect next entity
$utm_fname = $ufield->getName();
$prev_entity = CBaseEntity::getInstance('IblockSection');
}
else
{
$utm_fname = $ufield->getValueFieldName();
}
$chain->addElement(new CEntityQueryChainElement(
$utm_entity->getField($utm_fname),
array('ufield' => $ufield)
));
}
else
{
// uts table - single value
// add uts entity user.uts (1:1)
$uts_entity = CBaseEntity::getInstance('Uts'.$prev_entity->getName());
$u_entity = $uts_entity;
$chain->addElement(new CEntityQueryChainElement(
$prev_entity->getField('UTS_OBJECT')
));
// add `value` field
$chain->addElement(new CEntityQueryChainElement(
$uts_entity->getField($def_element)
));
}
}
elseif (CBaseEntity::isExists($def_element)
&& CBaseEntity::getInstance($def_element)->getReferencesCountTo($prev_entity->getName()) == 1
)
{
// def_element is another entity with only 1 reference to current entity
// need to identify Reference field
$ref_entity = CBaseEntity::getInstance($def_element);
$field = end($ref_entity->getReferencesTo($prev_entity->getName()));
$prev_entity = $ref_entity;
$chain->addElement(new CEntityQueryChainElement(
array($ref_entity, $field)
));
}
elseif ( ($pos_wh = strpos($def_element, ':')) > 0
&& CBaseEntity::isExists(($ref_entity_name = substr($def_element, 0, $pos_wh)))
&& CBaseEntity::getInstance($ref_entity_name)->hasField($ref_field_name = substr($def_element, $pos_wh+1))
&& CBaseEntity::getInstance($ref_entity_name)->getField($ref_field_name)->getRefEntity()->getName() == $prev_entity->getName()
)
{
// chain element is another entity with >1 references to current entity
// def like NewsArticle:AUTHOR, NewsArticle:LAST_COMMENTER
// NewsArticle - entity, AUTHOR and LAST_COMMENTER - Reference fields
$chain->addElement(new CEntityQueryChainElement(array(
CBaseEntity::getInstance($ref_entity_name),
CBaseEntity::getInstance($ref_entity_name)->getField($ref_field_name)
)));
$prev_entity = CBaseEntity::getInstance($ref_entity_name);
}
elseif ($def_element == '*' && $is_last_elem)
{
continue;
}
else
{
// unknown chain
throw new Exception(sprintf(
'Unknown field definition `%s` (%s) for %s Entity.',
$def_element, $definition, $prev_entity->getName()
), 100);
}
}
return $chain;
}