From 4db928776abe4fd4f8c3e1501e74b0b0628439bc Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 8 May 2017 11:18:45 +0100
Subject: [PATCH] Issue #2868362 by Berdir, Ginovski, dawehner, Wim Leers,
 alexpott: HAL RelationLinkManager caches and returns entity type definition
 object instead of id

---
 .../src/LinkManager/RelationLinkManager.php   | 26 ++++++++++---
 .../RelationLinkManagerInterface.php          |  4 +-
 .../tests/src/Kernel/HalLinkManagerTest.php   | 39 ++++++++++++++++++-
 3 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/core/modules/hal/src/LinkManager/RelationLinkManager.php b/core/modules/hal/src/LinkManager/RelationLinkManager.php
index dc6486f203a1..282dfde0dfee 100644
--- a/core/modules/hal/src/LinkManager/RelationLinkManager.php
+++ b/core/modules/hal/src/LinkManager/RelationLinkManager.php
@@ -100,17 +100,26 @@ public function getRelationInternalIds($relation_uri, $context = []) {
    *   Context from the normalizer/serializer operation.
    *
    * @return array
-   *   An array of typed data ids (entity_type, bundle, and field name) keyed
-   *   by corresponding relation URI.
+   *   An array of typed data ids (entity_type_id, bundle, and field name) keyed
+   *   by corresponding relation URI. For backwards compatibility, the
+   *   entity_type key returns the full entity type object, this will be removed
+   *   before Drupal 9.0.
    */
   protected function getRelations($context = []) {
     $cid = 'hal:links:relations';
     $cache = $this->cache->get($cid);
     if (!$cache) {
-      $this->writeCache($context);
-      $cache = $this->cache->get($cid);
+      $data = $this->writeCache($context);
+    }
+    else {
+      $data = $cache->data;
+    }
+
+    // @todo Remove this in Drupal 9.0.
+    foreach ($data as $relation_uri => $ids) {
+      $data[$relation_uri]['entity_type'] = $this->entityManager->getDefinition($ids['entity_type_id']);
     }
-    return $cache->data;
+    return $data;
   }
 
   /**
@@ -118,6 +127,10 @@ protected function getRelations($context = []) {
    *
    * @param array $context
    *   Context from the normalizer/serializer operation.
+   *
+   * @return array
+   *   An array of typed data ids (entity_type_id, bundle, and field name) keyed
+   *   by corresponding relation URI.
    */
   protected function writeCache($context = []) {
     $data = [];
@@ -128,7 +141,7 @@ protected function writeCache($context = []) {
           foreach ($this->entityManager->getFieldDefinitions($entity_type->id(), $bundle) as $field_definition) {
             $relation_uri = $this->getRelationUri($entity_type->id(), $bundle, $field_definition->getName(), $context);
             $data[$relation_uri] = [
-              'entity_type' => $entity_type,
+              'entity_type_id' => $entity_type->id(),
               'bundle' => $bundle,
               'field_name' => $field_definition->getName(),
             ];
@@ -139,6 +152,7 @@ protected function writeCache($context = []) {
     // These URIs only change when field info changes, so cache it permanently
     // and only clear it when the fields cache is cleared.
     $this->cache->set('hal:links:relations', $data, Cache::PERMANENT, ['entity_field_info']);
+    return $data;
   }
 
 }
diff --git a/core/modules/hal/src/LinkManager/RelationLinkManagerInterface.php b/core/modules/hal/src/LinkManager/RelationLinkManagerInterface.php
index 18d78637b023..8ba8c949e816 100644
--- a/core/modules/hal/src/LinkManager/RelationLinkManagerInterface.php
+++ b/core/modules/hal/src/LinkManager/RelationLinkManagerInterface.php
@@ -32,7 +32,9 @@ public function getRelationUri($entity_type, $bundle, $field_name, $context = []
    *   Relation URI (or IANA link relation type) to transform into internal IDs.
    *
    * @return array
-   *   Array with keys 'entity_type', 'bundle' and 'field_name'.
+   *   Array with keys 'entity_type_id', 'bundle' and 'field_name'. For
+   *   backwards compatibility, the entity_type key returns the full entity type
+   *   object, this will be removed before Drupal 9.0.
    */
   public function getRelationInternalIds($relation_uri);
 
diff --git a/core/modules/hal/tests/src/Kernel/HalLinkManagerTest.php b/core/modules/hal/tests/src/Kernel/HalLinkManagerTest.php
index b675059abd6b..57413ad8160c 100644
--- a/core/modules/hal/tests/src/Kernel/HalLinkManagerTest.php
+++ b/core/modules/hal/tests/src/Kernel/HalLinkManagerTest.php
@@ -3,7 +3,10 @@
 namespace Drupal\Tests\hal\Kernel;
 
 use Drupal\Core\Url;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\KernelTests\KernelTestBase;
+use Drupal\node\Entity\NodeType;
 
 /**
  * @coversDefaultClass \Drupal\hal\LinkManager\LinkManager
@@ -14,13 +17,30 @@ class HalLinkManagerTest extends KernelTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['hal', 'hal_test', 'serialization', 'system'];
+  public static $modules = [ 'hal', 'hal_test', 'serialization', 'system', 'node', 'user', 'field'];
 
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
+
+    $this->installEntitySchema('node');
+
+    NodeType::create([
+      'type' => 'page',
+    ])->save();
+    FieldStorageConfig::create([
+      'entity_type' => 'node',
+      'type' => 'entity_reference',
+      'field_name' => 'field_ref',
+    ])->save();
+    FieldConfig::create([
+      'entity_type' => 'node',
+      'bundle' => 'page',
+      'field_name' => 'field_ref',
+    ])->save();
+
     \Drupal::service('router.builder')->rebuild();
   }
 
@@ -58,6 +78,23 @@ public function testGetRelationUri() {
     $this->assertSame($link, 'rest_test_relation');
   }
 
+  /**
+   * @covers ::getRelationInternalIds
+   */
+  public function testGetRelationInternalIds() {
+    /* @var \Drupal\rest\LinkManager\RelationLinkManagerInterface $relation_manager */
+    $relation_manager = \Drupal::service('hal.link_manager.relation');
+    $link = $relation_manager->getRelationUri('node', 'page', 'field_ref');
+    $internal_ids = $relation_manager->getRelationInternalIds($link);
+
+    $this->assertEquals([
+      'entity_type_id' => 'node',
+      'entity_type' => \Drupal::entityTypeManager()->getDefinition('node'),
+      'bundle' => 'page',
+      'field_name' => 'field_ref'
+    ], $internal_ids);
+  }
+
   /**
    * @covers ::setLinkDomain
    */
-- 
GitLab