/** * {@inheritdoc} */ public function process(ContextInterface $context) { /** @var ConfigContext $context */ /** @var array $definition */ $definition = $context->getResult(); if (empty($definition) || !array_key_exists(ConfigUtil::FIELDS, $definition)) { // virtual fields is added only if a definition of fields exists return; } $entityClass = $context->getClassName(); $virtualFields = $this->virtualFieldProvider->getVirtualFields($entityClass); if (!empty($virtualFields)) { foreach ($virtualFields as $field) { $query = $this->virtualFieldProvider->getVirtualFieldQuery($entityClass, $field); $propertyPath = $this->getPropertyPath($query); if (!empty($propertyPath)) { $definition[ConfigUtil::FIELDS][$field][ConfigUtil::PROPERTY_PATH] = $propertyPath; if (!empty($query['select']['label']) && $context->hasExtra(DescriptionsConfigExtra::NAME)) { $definition[ConfigUtil::FIELDS][$field][ConfigUtil::LABEL] = new Label($query['select']['label']); } } } $context->setResult($definition); } }
/** * Checks if the given column is the virtual one and if so, generates and saves table aliases for it * * @param string $columnName */ protected function addTableAliasesForVirtualColumn($columnName) { if (isset($this->virtualColumnExpressions[$columnName])) { // already added return; } $className = $this->getEntityClassName($columnName); $fieldName = $this->getFieldName($columnName); if (!$className || !$this->virtualFieldProvider->isVirtualField($className, $fieldName)) { // non virtual column return; } $mainEntityJoinId = $this->getParentJoinIdentifier($this->joinIdHelper->buildColumnJoinIdentifier($columnName)); $mainEntityJoinAlias = $this->tableAliases[$mainEntityJoinId]; $query = $this->virtualFieldProvider->getVirtualFieldQuery($className, $fieldName); $this->prepareAliases($query, $mainEntityJoinAlias); if (isset($query['join'])) { $joins = $this->buildVirtualJoins($query, $mainEntityJoinId); $this->replaceTableAliasesInVirtualColumnJoinConditions($joins, $this->aliases); foreach ($joins as &$item) { $this->registerVirtualColumnTableAlias($joins, $item, $mainEntityJoinId); } } $columnExpr = $this->replaceTableAliasesInVirtualColumnSelect($query['select']['expr'], $this->aliases); $this->virtualColumnExpressions[$columnName] = $columnExpr; $key = sprintf('%s::%s', $className, $fieldName); if (!isset($this->virtualColumnOptions[$key])) { $options = $query['select']; unset($options['expr']); $this->virtualColumnOptions[$key] = $options; } }
/** * @param QueryBuilder $qb * @param string $entityClass * @param string $fieldName * @return string */ protected function getVirtualFieldExpression(QueryBuilder $qb, $entityClass, $fieldName) { $rootAlias = $this->getRootTableAlias($qb); $conditions = ['entity' => $rootAlias]; $fieldConfig = $this->virtualFieldProvider->getVirtualFieldQuery($entityClass, $fieldName); $fieldConfigJoins = $fieldConfig['join']; $joins = $qb->getDQLPart('join'); if (empty($joins)) { foreach ($fieldConfigJoins as $type => $typedFieldConfigJoins) { foreach ($typedFieldConfigJoins as $typedFieldConfigJoin) { $join = new Join($type, $this->replaceAliases($conditions, $typedFieldConfigJoin['join']), $typedFieldConfigJoin['alias'], $typedFieldConfigJoin['conditionType'], $typedFieldConfigJoin['condition']); $qb->add('join', [$rootAlias => $join], true); $joins[$rootAlias][] = $join; } } } /** @var Join $join */ foreach ($joins[$rootAlias] as $join) { $joinType = strtolower($join->getJoinType()); if (array_key_exists($joinType, $fieldConfigJoins)) { foreach ($fieldConfigJoins[$joinType] as $fieldJoin) { if (strtoupper($fieldJoin['conditionType']) == strtoupper($join->getConditionType())) { $fixedJoin = $this->replaceAliases($conditions, $fieldJoin['join']); if ($fixedJoin == $join->getJoin()) { $conditions[$fieldJoin['alias']] = $join->getAlias(); $fixedCondition = $this->replaceAliases($conditions, $fieldJoin['condition']); if ($fixedCondition != (string) $join->getCondition()) { unset($conditions[$fieldJoin['alias']]); } } } } } } return $this->replaceAliases($conditions, $fieldConfig['select']['expr']); }
/** * Adds entity virtual fields to $result * * @param array $result * @param ClassMetadata $metadata * @param bool $applyExclusions * @param bool $translate */ protected function addVirtualFields(array &$result, ClassMetadata $metadata, $applyExclusions, $translate) { $className = $metadata->getName(); $virtualFields = $this->virtualFieldProvider->getVirtualFields($className); foreach ($virtualFields as $fieldName) { if ($applyExclusions && $this->exclusionProvider->isIgnoredField($metadata, $fieldName)) { continue; } $query = $this->virtualFieldProvider->getVirtualFieldQuery($className, $fieldName); $fieldLabel = isset($query['select']['label']) ? $query['select']['label'] : $this->getFieldLabel($className, $fieldName); $this->addField($result, $fieldName, $query['select']['return_type'], $fieldLabel, false, $translate); if (isset($query['select']['filter_by_id']) && $query['select']['filter_by_id']) { $result[$fieldName]['related_entity_name'] = $metadata->getAssociationTargetClass($fieldName); } } }
/** * Checks if the given column is a virtual field and if so, generates and saves table aliases for it * * @param string $columnName */ protected function addTableAliasesForVirtualField($columnName) { if (isset($this->virtualColumnExpressions[$columnName])) { // already processed return; } $className = $this->getEntityClassName($columnName); $fieldName = $this->getFieldName($columnName); if (!$className || !$this->virtualFieldProvider->isVirtualField($className, $fieldName)) { // not a virtual field return; } $mainEntityJoinId = $this->getParentJoinIdentifier($this->joinIdHelper->buildColumnJoinIdentifier($columnName)); $query = $this->registerVirtualColumnQueryAliases($this->virtualFieldProvider->getVirtualFieldQuery($className, $fieldName), $mainEntityJoinId); $this->virtualColumnExpressions[$columnName] = $query['select']['expr']; $key = sprintf('%s::%s', $className, $fieldName); if (!isset($this->virtualColumnOptions[$key])) { $options = $query['select']; unset($options['expr']); $this->virtualColumnOptions[$key] = $options; } }
/** * Checks if the given column is the virtual one and if so, generates and saves table aliases for it * * @param string $columnName */ protected function addTableAliasesForVirtualColumn($columnName) { if (isset($this->virtualColumnExpressions[$columnName])) { // already added return; } $className = $this->getEntityClassName($columnName); $fieldName = $this->getFieldName($columnName); if (!$this->virtualFieldProvider->isVirtualField($className, $fieldName)) { // non virtual column return; } $mainEntityJoinId = $this->getParentJoinIdentifier($this->joinIdHelper->buildColumnJoinIdentifier($columnName)); $mainEntityJoinAlias = $this->tableAliases[$mainEntityJoinId]; $query = $this->virtualFieldProvider->getVirtualFieldQuery($className, $fieldName); $joins = []; /** @var array $aliasMap * key = local alias (defined in virtual column query definition) * value = alias */ $aliases = [isset($query['root_alias']) ? $query['root_alias'] : 'entity' => $mainEntityJoinAlias]; if (isset($query['join'])) { $this->processVirtualColumnJoins($joins, $aliases, $query, 'inner', $mainEntityJoinId); $this->processVirtualColumnJoins($joins, $aliases, $query, 'left', $mainEntityJoinId); $this->replaceTableAliasesInVirtualColumnJoinConditions($joins, $aliases); foreach ($joins as &$item) { $this->registerVirtualColumnTableAlias($joins, $item, $mainEntityJoinId); } } $columnExpr = $this->replaceTableAliasesInVirtualColumnSelect($query['select']['expr'], $aliases); $this->virtualColumnExpressions[$columnName] = $columnExpr; $key = sprintf('%s::%s', $className, $fieldName); if (!isset($this->virtualColumnOptions[$key])) { $options = $query['select']; unset($options['expr']); $this->virtualColumnOptions[$key] = $options; } }