public function getFieldAccessor(string $fieldName, EntityDefinition $definition, string $root, Context $context): string
    {
        $fieldName = str_replace('extensions.', '', $fieldName);

        $original = $fieldName;
        $prefix = $root . '.';

        if (strpos($fieldName, $prefix) === 0) {
            $fieldName = substr($fieldName, \strlen($prefix));
        }

        $fields = $definition->getFields();
        if ($fields->has($fieldName)) {
            $field = $fields->get($fieldName);

            return $this->buildInheritedAccessor($field, $root, $definition, $context, $fieldName);
        }

        $parts = explode('.', $fieldName);
        $associationKey = array_shift($parts);

        if ($associationKey === 'extensions') {
            $associationKey = array_shift($parts);
        }

        if (!$fields->has($associationKey)) {
            throw new UnmappedFieldException($original, $definition);
        }

        /** @var Field $field */
        $field = $fields->get($associationKey);

        //case for json object fields, other fields has now same option to act with more point notations but hasn't to be an association field. E.g. price.gross
        if (!$field instanceof AssociationField && ($field instanceof StorageAware || $field instanceof TranslatedField)) {
            return $this->buildInheritedAccessor($field, $root, $definition, $context, $fieldName);
        }

        /** @var AssociationField $field */
        $field = $field;

        $referenceDefinition = $field->getReferenceDefinition();
        if ($field instanceof ManyToManyAssociationField) {
            $referenceDefinition = $field->getToManyReferenceDefinition();
        }

        return $this->getFieldAccessor(
            $original,
            $referenceDefinition,
            $root . '.' . $field->getPropertyName(),
            $context
        );
    }
public function getFieldAccessor(string $fieldName, EntityDefinition $definition, string $root, Context $context): string
    {
        $fieldName = str_replace('extensions.', '', $fieldName);

        $original = $fieldName;
        $prefix = $root . '.';

        if (strpos($fieldName, $prefix) === 0) {
            $fieldName = substr($fieldName, \strlen($prefix));
        }

        $fields = $definition->getFields();
        if ($fields->has($fieldName)) {
            $field = $fields->get($fieldName);

            return $this->buildInheritedAccessor($field, $root, $definition, $context, $fieldName);
        }

        $parts = explode('.', $fieldName);
        $associationKey = array_shift($parts);

        if ($associationKey === 'extensions') {
            $associationKey = array_shift($parts);
        }

        if (!$fields->has($associationKey)) {
            throw new UnmappedFieldException($original, $definition);
        }

        /** @var Field $field */
        $field = $fields->get($associationKey);

        //case for json object fields, other fields has now same option to act with more point notations but hasn't to be an association field. E.g. price.gross
        if (!$field instanceof AssociationField && ($field instanceof StorageAware || $field instanceof TranslatedField)) {
            return $this->buildInheritedAccessor($field, $root, $definition, $context, $fieldName);
        }

        /** @var AssociationField $field */
        $field = $field;

        $referenceDefinition = $field->getReferenceDefinition();
        if ($field instanceof ManyToManyAssociationField) {
            $referenceDefinition = $field->getToManyReferenceDefinition();
        }

        return $this->getFieldAccessor(
            $original,
            $referenceDefinition,
            $root . '.' . $field->getPropertyName(),
            $context
        );
    }
public function getFieldAccessor ( string $ fieldName , EntityDefinition $ definition , string $ root , Context $ context ) : string { $ fieldName = str_replace ( 'extensions.' , '' , $ fieldName ) ; $ original = $ fieldName ; $ prefix = $ root . '.' ; if ( strpos ( $ fieldName , $ prefix ) === 0 ) { $ fieldName = substr ( $ fieldName , \ strlen ( $ prefix ) ) ; } $ fields = $ definition -> getFields ( ) ; if ( $ fields -> has ( $ fieldName ) ) { $ field = $ fields -> get ( $ fieldName ) ; return $ this -> buildInheritedAccessor ( $ field , $ root , $ definition , $ context , $ fieldName ) ; } $ parts = explode ( '.' , $ fieldName ) ; $ associationKey = array_shift ( $ parts ) ; if ( $ associationKey === 'extensions' ) { $ associationKey = array_shift ( $ parts ) ; } if ( ! $ fields -> has ( $ associationKey ) ) { throw new UnmappedFieldException ( $ original , $ definition ) ; } /** @var Field $field */ $ field = $ fields -> get ( $ associationKey ) ; //case for json object fields, other fields has now same option to act with more point notations but hasn't to be an association field. E.g. price.gross if ( ! $ field instanceof AssociationField && ( $ field instanceof StorageAware || $ field instanceof TranslatedField ) ) { return $ this -> buildInheritedAccessor ( $ field , $ root , $ definition , $ context , $ fieldName ) ; } /** @var AssociationField $field */ $ field = $ field ; $ referenceDefinition = $ field -> getReferenceDefinition ( ) ; if ( $ field instanceof ManyToManyAssociationField ) { $ referenceDefinition = $ field -> getToManyReferenceDefinition ( ) ; } return $ this -> getFieldAccessor ( $ original , $ referenceDefinition , $ root . '.' . $ field -> getPropertyName ( ) , $ context ) ; }
Builds the sql field accessor for the provided field.

@example

fieldName => product.taxId
root      => product
returns   => `product`.`tax_id`

This function is also used for complex field accessors like JsonArray Field, JsonObject fields.
It considers the translation and parent-child inheritance.

fieldName => product.name
root      => product
return    => COALESCE(`product.translation`.`name`,`product.parent.translation`.`name`)

@throws UnmappedFieldException
Builds the sql field accessor for the provided field .