src/Projection/EntityType.php
public function createMirroredEntity(EntityInterface $source_entity, EntityInterface $reference_entity = null)
    {
        // compile non-list attribute values from the reference entity if available
        if ($reference_entity) {
            foreach ($this->getAttributes() as $attribute) {
                $attribute_name = $attribute->getName();
                $attribute_value = $reference_entity->getValue($attribute_name);
                $mirrored_values[$attribute_name] = $attribute_value instanceof BaseObjectInterface
                    ? $attribute_value->toArray()
                    : $attribute_value;
            }
        }

        // override default mirrored values
        $mirrored_values['@type'] = $source_entity->getType()->getPrefix();
        $mirrored_values['identifier'] = $source_entity->getIdentifier();
        if ($source_entity instanceof EntityReferenceInterface) {
            $mirrored_values['referenced_identifier'] = $source_entity->getReferencedIdentifier();
        }

        // collate the required mirrored attributes map
        $mirrored_attributes_map = $this->collateAttributes(
            function (AttributeInterface $attribute) {
                return (bool)$attribute->getOption('mirrored', false) === true;
            }
        );

        // extract our reference path which may be aliased
        $path_parts = explode('.', $this->getPrefix());
        $type_prefix = end($path_parts);

        // iterate the source attributes and extract the required mirrored values
        foreach ($mirrored_attributes_map->getKeys() as $mirrored_attribute_path) {
            // @todo possible risk of path name collision in greedy regex
            $mirrored_attribute_path = preg_replace('#([\w-]+\.)+'.$type_prefix.'\.#', '', $mirrored_attribute_path);
            $mirrored_attr_name = explode('.', $mirrored_attribute_path)[0];
            $mirrored_attribute = $this->getAttribute($mirrored_attr_name);
            $source_attribute_name = $mirrored_attribute->getOption('attribute_alias', $mirrored_attr_name);
            $source_attribute_value = $source_entity->getValue($source_attribute_name);
            if ($mirrored_attribute instanceof EmbeddedEntityListAttribute) {
                foreach ($source_attribute_value as $position => $source_embedded_entity) {
                    // skip entity mirroring if values already exist since we may traverse over paths repeatedly
                    // if (!isset($mirrored_values[$mirrored_attr_name][$position])) {
                    // 2016-09-28 shrink0r: when would this happen. commenting out if check,
                    // as this seems to work fine without.
                    $source_embed_prefix = $source_embedded_entity->getType()->getPrefix();
                    $mirrored_embed_type = $mirrored_attribute instanceof EntityReferenceListAttribute
                        ? $mirrored_attribute->getEmbeddedTypeByReferencedPrefix($source_embed_prefix)
                        : $mirrored_attribute->getEmbeddedTypeByPrefix($source_embed_prefix);
                    if ($mirrored_embed_type) {
                        $reference_embedded_entity = $reference_entity
                        ? $reference_entity->getValue($mirrored_attr_name)
                            ->getEntityByIdentifier($source_embedded_entity->getIdentifier())
                            : null;
                        $mirrored_embedded_entity = $mirrored_embed_type->createEntity(
                            $mirrored_embed_type->createMirroredEntity(
                                $source_embedded_entity,
                                $reference_embedded_entity
                            )->toArray(),
                            $reference_entity
                        );
                        $mirrored_values[$mirrored_attr_name][$position] = $mirrored_embedded_entity->toArray();
                    }
                }
            } else {
                $mirrored_values[$mirrored_attr_name] = $source_attribute_value instanceof BaseObjectInterface
                    ? $source_attribute_value->toArray()
                    : $source_attribute_value;
            }
        }

        return $this->createEntity($mirrored_values, $source_entity->getParent());
    }
public function createMirroredEntity(EntityInterface $source_entity, EntityInterface $reference_entity = null)
    {
        // compile non-list attribute values from the reference entity if available
        if ($reference_entity) {
            foreach ($this->getAttributes() as $attribute) {
                $attribute_name = $attribute->getName();
                $attribute_value = $reference_entity->getValue($attribute_name);
                $mirrored_values[$attribute_name] = $attribute_value instanceof BaseObjectInterface
                    ? $attribute_value->toArray()
                    : $attribute_value;
            }
        }

        // override default mirrored values
        $mirrored_values['@type'] = $source_entity->getType()->getPrefix();
        $mirrored_values['identifier'] = $source_entity->getIdentifier();
        if ($source_entity instanceof EntityReferenceInterface) {
            $mirrored_values['referenced_identifier'] = $source_entity->getReferencedIdentifier();
        }

        // collate the required mirrored attributes map
        $mirrored_attributes_map = $this->collateAttributes(
            function (AttributeInterface $attribute) {
                return (bool)$attribute->getOption('mirrored', false) === true;
            }
        );

        // extract our reference path which may be aliased
        $path_parts = explode('.', $this->getPrefix());
        $type_prefix = end($path_parts);

        // iterate the source attributes and extract the required mirrored values
        foreach ($mirrored_attributes_map->getKeys() as $mirrored_attribute_path) {
            // @todo possible risk of path name collision in greedy regex
            $mirrored_attribute_path = preg_replace('#([\w-]+\.)+'.$type_prefix.'\.#', '', $mirrored_attribute_path);
            $mirrored_attr_name = explode('.', $mirrored_attribute_path)[0];
            $mirrored_attribute = $this->getAttribute($mirrored_attr_name);
            $source_attribute_name = $mirrored_attribute->getOption('attribute_alias', $mirrored_attr_name);
            $source_attribute_value = $source_entity->getValue($source_attribute_name);
            if ($mirrored_attribute instanceof EmbeddedEntityListAttribute) {
                foreach ($source_attribute_value as $position => $source_embedded_entity) {
                    // skip entity mirroring if values already exist since we may traverse over paths repeatedly
                    // if (!isset($mirrored_values[$mirrored_attr_name][$position])) {
                    // 2016-09-28 shrink0r: when would this happen. commenting out if check,
                    // as this seems to work fine without.
                    $source_embed_prefix = $source_embedded_entity->getType()->getPrefix();
                    $mirrored_embed_type = $mirrored_attribute instanceof EntityReferenceListAttribute
                        ? $mirrored_attribute->getEmbeddedTypeByReferencedPrefix($source_embed_prefix)
                        : $mirrored_attribute->getEmbeddedTypeByPrefix($source_embed_prefix);
                    if ($mirrored_embed_type) {
                        $reference_embedded_entity = $reference_entity
                        ? $reference_entity->getValue($mirrored_attr_name)
                            ->getEntityByIdentifier($source_embedded_entity->getIdentifier())
                            : null;
                        $mirrored_embedded_entity = $mirrored_embed_type->createEntity(
                            $mirrored_embed_type->createMirroredEntity(
                                $source_embedded_entity,
                                $reference_embedded_entity
                            )->toArray(),
                            $reference_entity
                        );
                        $mirrored_values[$mirrored_attr_name][$position] = $mirrored_embedded_entity->toArray();
                    }
                }
            } else {
                $mirrored_values[$mirrored_attr_name] = $source_attribute_value instanceof BaseObjectInterface
                    ? $source_attribute_value->toArray()
                    : $source_attribute_value;
            }
        }

        return $this->createEntity($mirrored_values, $source_entity->getParent());
    }
public function createMirroredEntity ( EntityInterface $ source_entity , EntityInterface $ reference_entity = null ) { // compile non-list attribute values from the reference entity if available if ( $ reference_entity ) { foreach ( $ this -> getAttributes ( ) as $ attribute ) { $ attribute_name = $ attribute -> getName ( ) ; $ attribute_value = $ reference_entity -> getValue ( $ attribute_name ) ; $ mirrored_values [ $ attribute_name ] = $ attribute_value instanceof BaseObjectInterface ? $ attribute_value -> toArray ( ) : $ attribute_value ; } } // override default mirrored values $ mirrored_values [ '@type' ] = $ source_entity -> getType ( ) -> getPrefix ( ) ; $ mirrored_values [ 'identifier' ] = $ source_entity -> getIdentifier ( ) ; if ( $ source_entity instanceof EntityReferenceInterface ) { $ mirrored_values [ 'referenced_identifier' ] = $ source_entity -> getReferencedIdentifier ( ) ; } // collate the required mirrored attributes map $ mirrored_attributes_map = $ this -> collateAttributes ( function ( AttributeInterface $ attribute ) { return ( bool ) $ attribute -> getOption ( 'mirrored' , false ) === true ; } ) ; // extract our reference path which may be aliased $ path_parts = explode ( '.' , $ this -> getPrefix ( ) ) ; $ type_prefix = end ( $ path_parts ) ; // iterate the source attributes and extract the required mirrored values foreach ( $ mirrored_attributes_map -> getKeys ( ) as $ mirrored_attribute_path ) { // @todo possible risk of path name collision in greedy regex $ mirrored_attribute_path = preg_replace ( '#([\w-]+\.)+' . $ type_prefix . '\.#' , '' , $ mirrored_attribute_path ) ; $ mirrored_attr_name = explode ( '.' , $ mirrored_attribute_path ) [ 0 ] ; $ mirrored_attribute = $ this -> getAttribute ( $ mirrored_attr_name ) ; $ source_attribute_name = $ mirrored_attribute -> getOption ( 'attribute_alias' , $ mirrored_attr_name ) ; $ source_attribute_value = $ source_entity -> getValue ( $ source_attribute_name ) ; if ( $ mirrored_attribute instanceof EmbeddedEntityListAttribute ) { foreach ( $ source_attribute_value as $ position => $ source_embedded_entity ) { // skip entity mirroring if values already exist since we may traverse over paths repeatedly // if (!isset($mirrored_values[$mirrored_attr_name][$position])) { // 2016-09-28 shrink0r: when would this happen. commenting out if check, // as this seems to work fine without. $ source_embed_prefix = $ source_embedded_entity -> getType ( ) -> getPrefix ( ) ; $ mirrored_embed_type = $ mirrored_attribute instanceof EntityReferenceListAttribute ? $ mirrored_attribute -> getEmbeddedTypeByReferencedPrefix ( $ source_embed_prefix ) : $ mirrored_attribute -> getEmbeddedTypeByPrefix ( $ source_embed_prefix ) ; if ( $ mirrored_embed_type ) { $ reference_embedded_entity = $ reference_entity ? $ reference_entity -> getValue ( $ mirrored_attr_name ) -> getEntityByIdentifier ( $ source_embedded_entity -> getIdentifier ( ) ) : null ; $ mirrored_embedded_entity = $ mirrored_embed_type -> createEntity ( $ mirrored_embed_type -> createMirroredEntity ( $ source_embedded_entity , $ reference_embedded_entity ) -> toArray ( ) , $ reference_entity ) ; $ mirrored_values [ $ mirrored_attr_name ] [ $ position ] = $ mirrored_embedded_entity -> toArray ( ) ; } } } else { $ mirrored_values [ $ mirrored_attr_name ] = $ source_attribute_value instanceof BaseObjectInterface ? $ source_attribute_value -> toArray ( ) : $ source_attribute_value ; } } return $ this -> createEntity ( $ mirrored_values , $ source_entity -> getParent ( ) ) ; }
Create a new entity from the recursively mirrorred values of a given source entity, while
optionally merging attribute values from a given reference entity.

@param EntityInterface $source_entity
@param EntityInterface $reference_entity

@return EntityInterface
Create a new entity from the recursively mirrorred values of a given source entity while optionally merging attribute values from a given reference entity .