- Модуль: main
- Путь к файлу: ~/bitrix/modules/main/lib/orm/query/query.php
- Класс: Bitrix\Main\ORM\Query\Query
- Вызов: Query::setFilterChains
public function setFilterChains(&$filter, $section = 'filter')
{
foreach ($filter as $filter_def => &$filter_match)
{
if ($filter_def === 'LOGIC')
{
continue;
}
if (!is_numeric($filter_def))
{
$sqlWhere = new \CSQLWhere();
$csw_result = $sqlWhere->makeOperation($filter_def);
list($definition, ) = array_values($csw_result);
// do not register it in global chain registry - get it in a smuggled way
// - we will do the registration later after UF rewriting and data doubling checking
$chain = $this->getRegisteredChain($definition);
if (!$chain)
{
// try to find it in filter chains if it is 2nd call of method (when dividing filter for where/having)
// and chain is still not registered in global (e.g. when forcesDataDoublingOff)
$chain = $this->filter_chains[$definition] ?? Chain::getChainByDefinition($this->entity, $definition);
}
// dirty hack for UF multiple fields: replace text UF_SMTH by UF_SMTH_SINGLE
$dstField = $chain->getLastElement()->getValue();
$dstEntity = $dstField->getEntity();
if ($dstField instanceof ExpressionField && count($dstField->getBuildFromChains()) == 1)
{
// hold entity, but get real closing field
$dstBuildFromChains = $dstField->getBuildFromChains();
/** @var Chain $firstChain */
$firstChain = $dstBuildFromChains[0];
$dstField = $firstChain->getLastElement()->getValue();
}
// check for base linking
if (($dstField instanceof TextField || $dstField instanceof ArrayField)
&& $dstEntity->hasField($dstField->getName().'_SINGLE'))
{
$utmLinkField = $dstEntity->getField($dstField->getName().'_SINGLE');
if ($utmLinkField instanceof ExpressionField)
{
$buildFromChains = $utmLinkField->getBuildFromChains();
// check for back-reference
if (count($buildFromChains) == 1 && $buildFromChains[0]->hasBackReference())
{
$endField = $buildFromChains[0]->getLastElement()->getValue();
// and final check for entity name
if(strpos($endField->getEntity()->getName(), 'Utm'))
{
$expressionChain = clone $chain;
$expressionChain->removeLastElement();
$expressionChain->addElement(new ChainElement(clone $utmLinkField));
$expressionChain->forceDataDoublingOff();
$chain = $expressionChain;
// rewrite filter definition
unset($filter[$filter_def]);
$filter[$filter_def.'_SINGLE'] = $filter_match;
$definition .= '_SINGLE';
}
}
}
}
// continue
$registerChain = true;
// if data doubling disabled and it is back-reference - do not register, it will be overwritten
if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
{
$registerChain = false;
}
if ($registerChain)
{
$this->registerChain($section, $chain, $definition);
// fill hidden select
if ($chain->getLastElement()->getValue() instanceof ExpressionField)
{
$this->collectExprChains($chain);
}
}
else
{
// hide from global registry to avoid "join table"
// but we still need it in filter chains
$this->filter_chains[$chain->getAlias()] = $chain;
$this->filter_chains[$definition] = $chain;
// and we will need primary chain in filter later when overwriting data-doubling
$this->getRegisteredChain($this->entity->getPrimary(), true);
}
}
elseif (is_array($filter_match))
{
$this->setFilterChains($filter_match, $section);
}
}
}