protected function updateAffectedRelatives(ProjectionMap $affected_relatives, ProjectionInterface $source_projection) { $referenced_identifier = $source_projection->getIdentifier(); $updated_relatives = []; foreach ($affected_relatives as $affected_relative) { // collate the paths and matching entity list attributes from the affected projection $updated_state = $affected_relative->toArray(); $affected_relative_type = $affected_relative->getType(); $affected_relative_prefix = $affected_relative_type->getPrefix(); $affected_entities = $affected_relative->collateChildren(function (EntityInterface $embedded_entity) use($referenced_identifier) { return $embedded_entity instanceof EntityReferenceInterface && $embedded_entity->getReferencedIdentifier() === $referenced_identifier; }); // reconstruct related projection state adding the updated mirrored values foreach ($affected_entities as $affected_entity_value_path => $affected_entity) { $affected_entity_type = $affected_entity->getType(); $affected_entity_prefix = $affected_entity_type->getPrefix(); $mirrored_values = $affected_entity_type->createMirroredEntity($source_projection, $affected_entity)->toArray(); // @todo if the current affected entity type has no mirrored attributes we can cache the // mirrored values and improve performance by skipping additional unecessary recursion $mirrored_values['@type'] = $affected_entity_prefix; $mirrored_values['identifier'] = $affected_entity->getIdentifier(); $mirrored_values['referenced_identifier'] = $affected_entity->getReferencedIdentifier(); // insert the mirrored values in the correct position in our updated state preg_match_all('#(?<parent>[\\w-]+)\\.[\\w-]+\\[(?<position>\\d+)\\]\\.?#', $affected_entity_value_path, $value_path_parts, PREG_SET_ORDER); $nested_value =& $updated_state; foreach ($value_path_parts as $value_path_part) { $nested_value =& $nested_value[$value_path_part['parent']][$value_path_part['position']]; } $nested_value = $mirrored_values; } // create the new projection from the updated state $updated_relative = $affected_relative_type->createEntity($updated_state); $updated_relatives[] = $updated_relative; } return new ProjectionMap($updated_relatives); }
protected function calculateMaterializedPath(ProjectionInterface $parent = null) { $path_parts = []; if ($parent) { $parent_path = $parent->getMaterializedPath(); if (!empty($parent_path)) { $path_parts = explode('/', $parent_path); } $path_parts[] = $parent->getIdentifier(); } return implode('/', $path_parts); }