diff --git a/src/EntityReferenceRevisionsServiceProvider.php b/src/EntityReferenceRevisionsServiceProvider.php index 65db785..585c044 100644 --- a/src/EntityReferenceRevisionsServiceProvider.php +++ b/src/EntityReferenceRevisionsServiceProvider.php @@ -4,6 +4,7 @@ namespace Drupal\entity_reference_revisions; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceProviderBase; +use Drupal\entity_reference_revisions\Normalizer\EntityReferenceRevisionItemNormalizer; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; @@ -20,14 +21,19 @@ class EntityReferenceRevisionsServiceProvider extends ServiceProviderBase { if (isset($modules['hal'])) { // Hal module is enabled, add our new normalizer for entity reference // revision items. - $service_definition = new Definition('Drupal\entity_reference_revisions\Normalizer\EntityReferenceRevisionItemNormalizer', array( - new Reference('hal.link_manager'), - new Reference('serializer.entity_resolver'), - )); + + // To avoid problems the arguments to + // \Drupal\hal\Normalizer\EntityReferenceItemNormalizer change, re-use + // the same constructor arguments and set the additional dependency + // with a setter method. + $parent_definition = $container->getDefinition('serializer.normalizer.entity_reference_item.hal'); + $service_definition = new Definition(EntityReferenceRevisionItemNormalizer::class, $parent_definition->getArguments()); + $service_definition->addMethodCall('setEntityTypeManager', [new Reference('entity_type.manager')]); + // The priority must be higher than that of // serializer.normalizer.entity_reference_item.hal in // hal.services.yml. - $service_definition->addTag('normalizer', array('priority' => 20)); + $service_definition->addTag('normalizer', array('priority' => $parent_definition->getTags()['normalizer'][0]['priority'] + 1)); $container->setDefinition('serializer.normalizer.entity_reference_revision_item', $service_definition); } } diff --git a/src/Normalizer/EntityReferenceRevisionItemNormalizer.php b/src/Normalizer/EntityReferenceRevisionItemNormalizer.php index 5833615..7259ac8 100644 --- a/src/Normalizer/EntityReferenceRevisionItemNormalizer.php +++ b/src/Normalizer/EntityReferenceRevisionItemNormalizer.php @@ -2,6 +2,7 @@ namespace Drupal\entity_reference_revisions\Normalizer; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\entity_reference_revisions\EntityNeedsSaveInterface; use Drupal\entity_reference_revisions\Plugin\Field\FieldType\EntityReferenceRevisionsItem; use Drupal\hal\Normalizer\EntityReferenceItemNormalizer; @@ -18,19 +19,40 @@ class EntityReferenceRevisionItemNormalizer extends EntityReferenceItemNormalize */ protected $supportedInterfaceOrClass = EntityReferenceRevisionsItem::class; + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Set the entity type manager. + * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + */ + public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) { + $this->entityTypeManager = $entity_type_manager; + } + /** * {@inheritdoc} */ protected function constructValue($data, $context) { $field_item = $context['target_instance']; + /** @var \Drupal\entity_reference_revisions\Plugin\Field\FieldType\EntityReferenceRevisionsItem $field_item */ $field_definition = $field_item->getFieldDefinition(); $target_type_id = $field_definition->getSetting('target_type'); - $target_type = \Drupal::entityTypeManager()->getDefinition($target_type_id); + $target_type = $this->entityTypeManager->getDefinition($target_type_id); - // If the target type has a revision parent id field and that is field is - // part of data, this is a composite normalization, denormalize it. - if ($target_type->get('entity_revision_parent_id_field') && - isset($data[$target_type->get('entity_revision_parent_id_field')])) { + // If the target type has a revision parent type field and that field is + // part of data, this is a composite normalization. + $parent_type_field = $target_type->get('entity_revision_parent_type_field'); + if ($parent_type_field && isset($data[$parent_type_field])) { + + // Denormalize the embedded entity, if it implements the + // EntityNeedsSaveInterface interface, ensure that it will be saved. if ($target_entity = $this->serializer->denormalize($data, $target_type->getClass(), 'hal_json')) { if ($target_entity instanceof EntityNeedsSaveInterface) { $target_entity->needsSave(); @@ -51,6 +73,7 @@ class EntityReferenceRevisionItemNormalizer extends EntityReferenceItemNormalize */ public function normalize($field_item, $format = NULL, array $context = array()) { $data = parent::normalize($field_item, $format, $context); + /** @var \Drupal\entity_reference_revisions\Plugin\Field\FieldType\EntityReferenceRevisionsItem $field_item */ $target_entity = $field_item->get('entity')->getValue(); $entity = $field_item->getEntity(); @@ -67,6 +90,14 @@ class EntityReferenceRevisionItemNormalizer extends EntityReferenceItemNormalize $embedded['lang'] = $data['_links'][$field_uri][0]['lang']; } + // Remove empty links. + if (empty($data['_links'][$field_uri][0]['href'])) { + unset($data['_links'][$field_uri]); + } + if (empty($embedded['_links']['self']['href'])) { + unset($embedded['_links']['self']); + } + $data['_embedded'][$field_uri][0] = $embedded; } else { diff --git a/tests/src/Kernel/EntityReferenceRevisionsNormalizerTest.php b/tests/src/Kernel/EntityReferenceRevisionsNormalizerTest.php index e35ae92..68d7ab5 100644 --- a/tests/src/Kernel/EntityReferenceRevisionsNormalizerTest.php +++ b/tests/src/Kernel/EntityReferenceRevisionsNormalizerTest.php @@ -9,8 +9,8 @@ use Drupal\field\Entity\FieldStorageConfig; use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; -use Drupal\simpletest\ContentTypeCreationTrait; -use Drupal\simpletest\NodeCreationTrait; +use Drupal\Tests\node\Traits\ContentTypeCreationTrait; +use Drupal\Tests\node\Traits\NodeCreationTrait; /** * Tests the entity_reference_revisions normalizer. @@ -169,6 +169,12 @@ class EntityReferenceRevisionsNormalizerTest extends EntityKernelTestBase { $this->assertEquals($nested_revision_id, $normalized['_embedded']['http://localhost/rest/relation/node/article/composite_reference'][0]['_embedded']['http://localhost/rest/relation/entity_test_composite/entity_test_composite/composite_nested_reference'][0]['id'][0]['value']); + // Assert there is no link to the embedded composite as it has no href but + // the one to the node is still there. + $this->assertFalse(isset($normalized['_links']['http://localhost/rest/relation/node/article/composite_reference'])); + $this->assertFalse(isset($normalized['_embedded']['http://localhost/rest/relation/node/article/composite_reference'][0]['_links']['self'])); + $this->assertTrue(isset($normalized['_links']['http://localhost/rest/relation/node/article/node_reference'][0]['href'])); + // Check the denormalization of the embedded composite field. $nested_composite->delete(); $composite->delete();