diff --git a/src/Normalizer/EntityReferenceFieldNormalizer.php b/src/Normalizer/EntityReferenceFieldNormalizer.php index 247e82c..c7aea2c 100644 --- a/src/Normalizer/EntityReferenceFieldNormalizer.php +++ b/src/Normalizer/EntityReferenceFieldNormalizer.php @@ -85,17 +85,31 @@ class EntityReferenceFieldNormalizer extends FieldNormalizer implements Denormal $cardinality = $definition ->getFieldStorageDefinition() ->getCardinality(); - $entity_list = array_filter($field->getIterator()->getArrayCopy(), function ($item) { + /** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem[] $entity_reference_item_list */ + $entity_reference_item_list = array_filter($field->getIterator()->getArrayCopy(), function ($item) { return (bool) $item->get('entity')->getValue(); }); - $entity_list = array_map(function ($item) { + $entity_list_metadata = array(); + $entity_list = array(); + foreach ($entity_reference_item_list as $item) { + // Prepare a list of additional properties stored by the field. + $metadata = array(); + /** @var \Drupal\Core\TypedData\TypedDataInterface[] $properties */ + $properties = $item->getProperties(); + foreach ($properties as $property_key => $property) { + if ($property_key != $main_property) { + $metadata[$property_key] = $property->getValue(); + } + } + $entity_list_metadata[] = $metadata; + // Get the referenced entity. $entity = $item->get('entity')->getValue(); // And get the translation in the requested language. - return $this->entityRepository->getTranslationFromContext($entity); - }, $entity_list); + $entity_list[] = $this->entityRepository->getTranslationFromContext($entity); + } $entity_collection = new EntityCollection($entity_list); - $relationship = new Relationship($this->resourceTypeRepository, $field->getName(), $cardinality, $entity_collection, $field->getEntity(), $main_property); + $relationship = new Relationship($this->resourceTypeRepository, $field->getName(), $cardinality, $entity_collection, $field->getEntity(), $main_property, $entity_list_metadata); return $this->serializer->normalize($relationship, $format, $context); } diff --git a/src/Normalizer/Relationship.php b/src/Normalizer/Relationship.php index 2483b6d..9abc7cd 100644 --- a/src/Normalizer/Relationship.php +++ b/src/Normalizer/Relationship.php @@ -68,19 +68,23 @@ class Relationship implements AccessibleInterface { * The host entity. * @param string $target_key * The property name of the relationship id. + * @param array $entity_list_metadata + * An array of additional properties stored by the field and that will be + * added to the meta in the relationship. */ - public function __construct(ResourceTypeRepository $resource_type_repository, $field_name, $cardinality = FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, EntityCollection $entities, EntityInterface $host_entity, $target_key = 'target_id') { + public function __construct(ResourceTypeRepository $resource_type_repository, $field_name, $cardinality = FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, EntityCollection $entities, EntityInterface $host_entity, $target_key = 'target_id', array $entity_list_metadata = array()) { $this->resourceTypeRepository = $resource_type_repository; $this->propertyName = $field_name; $this->cardinality = $cardinality; $this->hostEntity = $host_entity; $this->items = []; - foreach ($entities as $entity) { + foreach ($entities as $key => $entity) { $this->items[] = new RelationshipItem( $resource_type_repository, $entity, $this, - $target_key + $target_key, + $entity_list_metadata[$key] ); } } diff --git a/src/Normalizer/RelationshipItem.php b/src/Normalizer/RelationshipItem.php index b10201e..90d6dab 100644 --- a/src/Normalizer/RelationshipItem.php +++ b/src/Normalizer/RelationshipItem.php @@ -39,6 +39,13 @@ class RelationshipItem { protected $parent; /** + * The list of metadata associated with this field item value. + * + * @var array + */ + protected $metadata; + + /** * Relationship item constructor. * * @param \Drupal\jsonapi\ResourceType\ResourceTypeRepository $resource_type_repository @@ -49,8 +56,10 @@ class RelationshipItem { * The parent of this item. * @param string $target_key * The key name of the target relationship. + * @param array $metadata + * The list of metadata associated with this field item value. */ - public function __construct(ResourceTypeRepository $resource_type_repository, EntityInterface $target_entity, Relationship $parent, $target_key = 'target_id') { + public function __construct(ResourceTypeRepository $resource_type_repository, EntityInterface $target_entity, Relationship $parent, $target_key = 'target_id', array $metadata = array()) { $this->targetResourceType = $resource_type_repository->get( $target_entity->getEntityTypeId(), $target_entity->bundle() @@ -58,6 +67,7 @@ class RelationshipItem { $this->targetKey = $target_key; $this->targetEntity = $target_entity; $this->parent = $parent; + $this->metadata = $metadata; } /** @@ -86,7 +96,10 @@ class RelationshipItem { * @return string */ public function getValue() { - return [$this->targetKey => $this->getTargetEntity()->uuid()]; + return [ + $this->targetKey => $this->getTargetEntity()->uuid(), + 'meta' => $this->metadata, + ]; } /** diff --git a/src/Normalizer/Value/RelationshipItemNormalizerValue.php b/src/Normalizer/Value/RelationshipItemNormalizerValue.php index 8955eaf..29d599c 100644 --- a/src/Normalizer/Value/RelationshipItemNormalizerValue.php +++ b/src/Normalizer/Value/RelationshipItemNormalizerValue.php @@ -39,10 +39,16 @@ class RelationshipItemNormalizerValue extends FieldItemNormalizerValue implement if (!$value = parent::rasterizeValue()) { return $value; } - return [ + $rasterizedValue = [ 'type' => $this->resource->getTypeName(), - 'id' => $value, + 'id' => $value['target_id'], ]; + + if (!empty($value['meta'])) { + $rasterizedValue['meta'] = $value['meta']; + } + + return $rasterizedValue; } /** diff --git a/tests/src/Kernel/JsonapiKernelTestBase.php b/tests/src/Kernel/JsonapiKernelTestBase.php index 5c17404..c22a16a 100644 --- a/tests/src/Kernel/JsonapiKernelTestBase.php +++ b/tests/src/Kernel/JsonapiKernelTestBase.php @@ -67,38 +67,4 @@ abstract class JsonapiKernelTestBase extends KernelTestBase { } } - /** - * Create an image field. - * - * @param string $entity_type_id - * The type of entity the field will be attached to. - * @param string $bundle - * The bundle name of the entity the field will be attached to. - * @param string $field_name - * The name of the field; if it exists, a new instance of the existing. - * field will be created. - * @param int $cardinality - * The cardinality of the field. - */ - protected function createImageField($entity_type_id, $bundle, $field_name, $cardinality = 1) { - if (!FieldStorageConfig::loadByName($entity_type_id, $field_name)) { - FieldStorageConfig::create([ - 'field_name' => $field_name, - 'type' => 'entity_reference', - 'entity_type' => $entity_type_id, - 'cardinality' => $cardinality, - 'settings' => [ - 'target_type' => 'file', - ], - ])->save(); - } - if (!FieldConfig::loadByName($entity_type_id, $bundle, $field_name)) { - FieldConfig::create([ - 'field_name' => $field_name, - 'entity_type' => $entity_type_id, - 'bundle' => $bundle, - ])->save(); - } - } - } diff --git a/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php b/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php index 810d276..da39d31 100644 --- a/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php +++ b/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php @@ -15,6 +15,7 @@ use Drupal\node\Entity\NodeType; use Drupal\jsonapi\ResourceResponse; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\image\Kernel\ImageFieldCreationTrait; use Drupal\Tests\jsonapi\Kernel\JsonapiKernelTestBase; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; @@ -32,6 +33,8 @@ use Symfony\Component\Routing\Route; */ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { + use ImageFieldCreationTrait; + /** * {@inheritdoc} */ @@ -71,11 +74,12 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { $this->installEntitySchema('node'); $this->installEntitySchema('user'); $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('file'); // Add the additional table schemas. $this->installSchema('system', ['sequences']); - $this->installEntitySchema('file'); $this->installSchema('node', ['node_access']); $this->installSchema('user', ['users_data']); + $this->installSchema('file', ['file_usage']); $type = NodeType::create([ 'type' => 'article', ]); @@ -91,7 +95,7 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED ); - $this->createImageField('node', 'article', 'field_image'); + $this->createImageField('field_image', 'article'); $this->user = User::create([ 'name' => 'user1', @@ -235,7 +239,7 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { 'title' => 'test title', 'width' => 10, 'height' => 11, - ], $normalized['data']['attributes']['field_image']['data']['meta']); + ], $normalized['data']['relationships']['field_image']['data']['meta']); $this->assertSame('node--article', $normalized['data']['type']); $this->assertEquals([ 'data' => [ @@ -251,7 +255,6 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { "The current user is not allowed to GET the selected resource. The 'access user profiles' permission is required and the user must be active.", $normalized['meta']['errors'][0]['detail'] ); - print_r($normalized); $this->assertEquals(403, $normalized['meta']['errors'][0]['status']); $this->assertEquals($this->term1->uuid(), $normalized['included'][0]['id']); $this->assertEquals('taxonomy_term--tags', $normalized['included'][0]['type']);