• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/lib/orm/query/query.php
  • Класс: Bitrix\Main\ORM\Query\Query
  • Вызов: Query::getFilterCswFields
protected function getFilterCswFields(&$filter)
{
	$fields = array();

	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, $operation) = array_values($csw_result);

			$chain = $this->filter_chains[$definition];
			$last = $chain->getLastElement();

			// need to create an alternative of CSQLWhere in D7.Entity
			$field_type = $last->getValue()->getDataType();
			$callback = null;

			// rewrite type & value for CSQLWhere
			if (in_array($operation, array('SE', 'SN'), true)
				&& in_array($filter_match, array(null, true, false), true)
			)
			{
				$field_type = 'callback';

				if ($filter_match === null)
				{
					$callback = array($this, 'nullEqualityCallback');
				}
				else
				{
					// just boolean expression, without operator
					// e.g. WHERE EXISTS(...)
					$callback = array($this, 'booleanStrongEqualityCallback');
				}
			}
			elseif ($field_type == 'integer')
			{
				$field_type = 'int';
			}
			elseif ($field_type == 'boolean')
			{
				$field_type = 'string';

				/** @var BooleanField $field */
				$field = $last->getValue();
				$values = $field->getValues();

				if (is_numeric($values[0]) && is_numeric($values[1]))
				{
					$field_type = 'int';
				}

				if (is_scalar($filter_match))
				{
					$filter_match = $field->normalizeValue($filter_match);
				}
			}
			elseif ($field_type == 'float')
			{
				$field_type = 'double';
			}
			elseif ($field_type == 'enum' || $field_type == 'text')
			{
				$field_type = 'string';
			}

			$sqlDefinition = $chain->getSqlDefinition();

			// data-doubling-off mode
			/** @see disableDataDoubling */
			if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
			{
				$primaryName = $this->entity->getPrimary();
				$uniquePostfix = '_TMP'.rand();

				// build subquery
				$subQuery = new Query($this->entity);
				$subQuery->addSelect($primaryName);
				$subQuery->addFilter($filter_def, $filter_match);
				$subQuery->setTableAliasPostfix(strtolower($uniquePostfix));
				$subQuerySql = $subQuery->getQuery();

				// proxying subquery as value to callback
				$filter_match = $subQuerySql;
				$callback = array($this, 'dataDoublingCallback');

				$field_type = 'callback';

				// change sql definition
				$idChain = $this->getRegisteredChain($primaryName);
				$sqlDefinition = $idChain->getSqlDefinition();
			}

			// set entity connection to the sql expressions
			if ($filter_match instanceof Main\DB\SqlExpression)
			{
				$filter_match->setConnection($this->entity->getConnection());
			}

			//$is_having = $last->getValue() instanceof ExpressionField && $last->getValue()->isAggregated();

			// if back-reference found (Entity:REF)
			// if NO_DOUBLING mode enabled, then change getSQLDefinition to subquery exists(...)
			// and those chains should not be in joins if it is possible

			/*if (!$this->data_doubling && $chain->hasBackReference())
			{
				$field_type = 'callback';
				$init_query = $this;

				$callback = function ($field, $operation, $value) use ($init_query, $chain)
				{
					$init_entity = $init_query->getEntity();
					$init_table_alias = CBaseEntity::camel2snake($init_entity->getName()).$init_query->getTableAliasPostfix();

					$filter = array();

					// add primary linking with main query
					foreach ($init_entity->getPrimaryArray() as $primary)
					{
						$filter['='.$primary] = new CSQLWhereExpression('?#', $init_table_alias.'.'.$primary);
					}

					// add value filter
					$filter[CSQLWhere::getOperationByCode($operation).$chain->getDefinition()] = $value;

					// build subquery
					$query_class = __CLASS__;
					$sub_query = new $query_class($init_entity);
					$sub_query->setFilter($filter);
					$sub_query->setTableAliasPostfix('_sub');

					return 'EXISTS(' . $sub_query->getQuery() . ')';
				};
			}*/

			$fields[$definition] = array(
				'TABLE_ALIAS' => 'table',
				'FIELD_NAME' => $sqlDefinition,
				'FIELD_TYPE' => $field_type,
				'MULTIPLE' => '',
				'JOIN' => '',
				'CALLBACK' => $callback
			);
		}
		elseif (is_array($filter_match))
		{
			$fields = array_merge($fields, $this->getFilterCswFields($filter_match));
		}
	}

	return $fields;
}