/** * @dataProvider getOptionsFixture */ public function testCreateWithOptions(array $options) { $options = array_merge([EmbeddedEntityListAttribute::OPTION_ENTITY_TYPES => [ParagraphType::CLASS]], $options); $embed_attribute = new EmbeddedEntityListAttribute(self::ATTR_NAME, $this->getTypeMock(), $options); $this->assertEquals($embed_attribute->getName(), self::ATTR_NAME); $this->assertEquals($embed_attribute->getName(), self::ATTR_NAME); $this->assertFalse($embed_attribute->hasOption('snafu_flag')); foreach ($options as $optName => $optValue) { $this->assertTrue($embed_attribute->hasOption($optName)); $this->assertEquals($embed_attribute->getOption($optName), $optValue); } }
protected function buildFieldFilterSpec(EmbeddedEntityListAttribute $embed_attribute) { $filter_parts = []; $parent_attribute = $embed_attribute->getParent(); while ($parent_attribute) { $filter_parts[] = $parent_attribute->getName(); $parent_attribute = $parent_attribute->getParent(); } $filter_parts[] = $embed_attribute->getName(); $filter_parts[] = 'referenced_identifier'; return implode('.', $filter_parts); }
/** * @return array */ protected function getEmbeddedCommands(EmbeddedEntityListAttribute $attribute, array $values, EntityInterface $parent_entity = null) { $errors = []; $affected_identifiers = []; $attribute_name = $attribute->getName(); $embedded_entity_list = $parent_entity ? $parent_entity->getValue($attribute_name) : new EntityList(); $builder_list = new CommandBuilderList(); foreach ($values as $position => $embedded_values) { if (!isset($embedded_values['@type'])) { $value_path = sprintf('%s.%d.@type', $attribute_name, $position); $errors[$value_path]['@incidents'][] = ['path' => $attribute->getPath(), 'incidents' => ['invalid_type' => ['reason' => 'missing']]]; continue; } $embed_type_prefix = $embedded_values['@type']; unset($embedded_values['@type']); $embed_type = $attribute->getEmbeddedTypeByPrefix($embed_type_prefix); if (!$embed_type) { $value_path = sprintf('%s.%d.@type', $attribute_name, $position); $errors[$value_path]['@incidents'][] = ['path' => $attribute->getPath(), 'incidents' => ['invalid_type' => ['reason' => 'unknown']]]; continue; } /* * Filter entities from the entity by incoming payload identifiers. If the * identifier is not matched then prepare an 'add' command, otherwise a 'modify'. */ $affected_entity = $embedded_entity_list->filter(function ($embedded_entity) use($embedded_values) { return $embedded_entity instanceof EntityInterface && isset($embedded_values['identifier']) && $embedded_entity->getIdentifier() === $embedded_values['identifier']; })->getFirst(); if (!$affected_entity) { $builder_list->push((new self($embed_type, AddEmbeddedEntityCommand::CLASS))->withParentAttributeName($attribute_name)->withPosition($position)->withValues($embedded_values)); } else { $affected_identifiers[] = $affected_entity->getIdentifier(); $modified_values = $this->filterUnmodifiedValues($affected_entity, $embedded_values); // prepare a modify command if values or position has changed if (!empty($modified_values) || $embedded_entity_list->getKey($affected_entity) != $position) { $builder_list->push((new self($embed_type, ModifyEmbeddedEntityCommand::CLASS))->fromEntity($affected_entity)->withParentAttributeName($attribute_name)->withPosition($position)->withValues($modified_values)); } } } /* * Iterate the attribute entity list and prepare remove commands for * any embedded entities with no incoming payload, or compensate for commands * which already exist. */ foreach ($embedded_entity_list as $embedded_entity) { // if an entity is not found in the payload then we do compensation checks to make // sure we don't inadvertently add an existing entity if (!in_array($embedded_entity->getIdentifier(), $affected_identifiers)) { // look for any add command which has no difference in values for the current entity $command_key = null; foreach ($builder_list as $key => $command_builder) { if ($command_builder->getCommandClass() === AddEmbeddedEntityCommand::CLASS && empty($this->filterUnmodifiedValues($embedded_entity, $command_builder->getValues()))) { $command_key = $key; break; } } if (!is_null($command_key)) { // remove the unnecessary add command if the entity already exists in the entity $builder_list->splice($command_key); } else { // the entity was not found in the payload so we can prepare removal $builder_list->push((new self($embedded_entity->getType(), RemoveEmbeddedEntityCommand::CLASS))->fromEntity($embedded_entity)->withParentAttributeName($attribute_name)); } } } $build_result = $builder_list->build(); if (!empty($errors)) { if ($build_result instanceof Error) { $errors = array_merge($errors, $build_result->get()); } return Error::unit($errors); } return $build_result; }