• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/lib/orm/query/query.php
  • Класс: Bitrix\Main\ORM\Query\Query
  • Вызов: Query::addToSelectChain
protected function addToSelectChain($definition, $alias = null)
{
	if ($definition instanceof ExpressionField)
	{
		if (empty($alias))
		{
			$alias = $definition->getName();
		}

		$this->registerRuntimeField($alias, $definition);
		$chain = $this->getRegisteredChain($alias);

		// add
		$this->registerChain('select', $chain);

		// recursively collect all "build_from" fields
		if ($chain->getLastElement()->getValue() instanceof ExpressionField)
		{
			$this->collectExprChains($chain, array('hidden', 'select_expr'));
		}
	}
	elseif (is_array($definition))
	{
		// it is runtime field
		// now they are @deprecated in here
		throw new Main\ArgumentException(
			'Expression as an array in `select` section is no more supported due to security reason.'
			.' Please use `runtime` parameter, or Query->registerRuntimeField method, or pass ExpressionField object instead of array.'
		);
	}
	else
	{
		// localize definition (get last field segment e.g. NAME from REF1.REF2.NAME)
		$localDefinitionPos = strrpos($definition, '.');

		if ($localDefinitionPos !== false)
		{
			$localDefinition = substr($definition, $localDefinitionPos + 1);
			$localEntityDef = substr($definition, 0, $localDefinitionPos);
			$localChain = Chain::getChainByDefinition($this->entity, $localEntityDef.'.*');
			$lastElemValue = $localChain->getLastElement()->getValue();

			if ($lastElemValue instanceof Reference)
			{
				$localEntity = $lastElemValue->getRefEntity();
			}
			elseif (is_array($lastElemValue))
			{
				list($localEntity, ) = $lastElemValue;
			}
			else
			{
				$localEntity = $lastElemValue;
			}
		}
		else
		{
			$localDefinition = $definition;
			$localEntityDef = "";
			$dataClass = $this->entity->getDataClass();
			$localEntity = $dataClass::getEntity();
		}

		// if there is a shell pattern in final segment, run recursively
		if ((strlen($localDefinition) > 1 && strpos($localDefinition, '*') !== false)
			|| strpos($localDefinition, '?') !== false
		)
		{
			// get fields by pattern
			foreach ($localEntity->getFields() as $field)
			{
				if (
					($field instanceof ScalarField || $field instanceof ExpressionField)
					&& fnmatch($localDefinition, $field->getName())
				)
				{
					// skip private fields
					if ($field instanceof ScalarField && $field->isPrivate())
					{
						continue;
					}

					// skip uf utm single
					if (
						substr($field->getName(), 0, 3) == 'UF_' && substr($field->getName(), -7) == '_SINGLE'
						&& $localEntity->hasField(substr($field->getName(), 0, -7))
					)
					{
						continue;
					}


					// build alias
					$customAlias = null;

					if ($alias !== null)
					{
						// put alias as a prefix
						$customAlias = $alias.$field->getName();
					}

					// build definition
					$fieldDefinition = $field->getName();

					if (!empty($localEntityDef))
					{
						$fieldDefinition = $localEntityDef.'.'.$fieldDefinition;
					}

					$this->addToSelectChain($fieldDefinition, $customAlias);
				}
			}

			return $this;
		}

		// there is normal scalar field, or Reference, or Entity (all fields of)
		$chain = $this->getRegisteredChain($definition, true);

		if ($alias !== null)
		{
			// custom alias
			$chain = clone $chain;
			$chain->setCustomAlias($alias);
		}

		$last_elem = $chain->getLastElement();

		// fill if element is not scalar
		/** @var null|Entity $expand_entity */
		$expand_entity = null;

		if ($last_elem->getValue() instanceof Reference)
		{
			$expand_entity = $last_elem->getValue()->getRefEntity();
		}
		elseif (is_array($last_elem->getValue()))
		{
			list($expand_entity, ) = $last_elem->getValue();
		}
		elseif ($last_elem->getValue() instanceof Entity)
		{
			$expand_entity = $last_elem->getValue();
		}
		elseif ($last_elem->getValue() instanceof OneToMany)
		{
			$expand_entity = $last_elem->getValue()->getRefEntity();
		}
		elseif ($last_elem->getValue() instanceof ManyToMany)
		{
			$expand_entity = $last_elem->getValue()->getRefEntity();
		}

		if (!$expand_entity && $alias !== null)
		{
			// we have a single field, let's check its custom alias
			if (
				$this->entity->hasField($alias)
				&& (
					// if it's not the same field
					$this->entity->getFullName() !== $last_elem->getValue()->getEntity()->getFullName()
					||
					$last_elem->getValue()->getName() !== $alias
				)
			)
			{
				// deny aliases eq. existing fields
				throw new Main\ArgumentException(sprintf(
					'Alias "%s" matches already existing field "%s" of initial entity "%s". '.
					'Please choose another name for alias.',
					$alias, $alias, $this->entity->getFullName()
				));
			}
		}

		if ($expand_entity)
		{
			// add all fields of entity
			foreach ($expand_entity->getFields() as $exp_field)
			{
				// except for references and expressions
				if ($exp_field instanceof ScalarField)
				{
					// skip private fields
					if ($exp_field->isPrivate())
					{
						continue;
					}

					$exp_chain = clone $chain;
					$exp_chain->addElement(new ChainElement(
						$exp_field
					));

					// custom alias
					if ($alias !== null)
					{
						$fieldAlias = $alias . $exp_field->getName();

						// deny aliases eq. existing fields
						if ($this->entity->hasField($fieldAlias))
						{
							throw new Main\ArgumentException(sprintf(
								'Alias "%s" + field "%s" match already existing field "%s" of initial entity "%s". '.
								'Please choose another name for alias.',
								$alias, $exp_field->getName(), $fieldAlias, $this->entity->getFullName()
							));
						}

						$exp_chain->setCustomAlias($fieldAlias);
					}

					// add
					$this->registerChain('select', $exp_chain);
				}
			}
		}
		else
		{
			// scalar field that defined in entity
			$this->registerChain('select', $chain);

			// it would be nice here to register field as a runtime when it has custom alias
			// it will make possible to use aliased fields as a native init entity fields
			// e.g. in expressions or in data_doubling=off filter

			// collect buildFrom fields (recursively)
			if ($chain->getLastElement()->getValue() instanceof ExpressionField)
			{
				$this->collectExprChains($chain, array('hidden', 'select_expr'));
			}
		}
	}

	return $this;
}