Issue #2219795 by damiankloip, Berdir: Config entity references broken and other bugs.
							parent
							
								
									02f761ba1d
								
							
						
					
					
						commit
						9dc59dda73
					
				| 
						 | 
				
			
			@ -16,10 +16,10 @@ services:
 | 
			
		|||
    class: Drupal\hal\Normalizer\FileEntityNormalizer
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: normalizer, priority: 20 }
 | 
			
		||||
    arguments: ['@entity.manager', '@http_default_client', '@rest.link_manager']
 | 
			
		||||
    arguments: ['@entity.manager', '@http_default_client', '@rest.link_manager', '@module_handler']
 | 
			
		||||
  serializer.normalizer.entity.hal:
 | 
			
		||||
    class: Drupal\hal\Normalizer\EntityNormalizer
 | 
			
		||||
    arguments: ['@rest.link_manager']
 | 
			
		||||
    class: Drupal\hal\Normalizer\ContentEntityNormalizer
 | 
			
		||||
    arguments: ['@rest.link_manager', '@entity.manager', '@module_handler']
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: normalizer, priority: 10 }
 | 
			
		||||
  serializer.encoder.hal:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,12 +2,14 @@
 | 
			
		|||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Contains \Drupal\hal\Normalizer\EntityNormalizer.
 | 
			
		||||
 * Contains \Drupal\hal\Normalizer\ContentEntityNormalizer.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Drupal\hal\Normalizer;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Utility\NestedArray;
 | 
			
		||||
use Drupal\Core\Entity\EntityManagerInterface;
 | 
			
		||||
use Drupal\Core\Extension\ModuleHandlerInterface;
 | 
			
		||||
use Drupal\Core\Language\Language;
 | 
			
		||||
use Drupal\rest\LinkManager\LinkManagerInterface;
 | 
			
		||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,14 +17,14 @@ use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 | 
			
		|||
/**
 | 
			
		||||
 * Converts the Drupal entity object structure to a HAL array structure.
 | 
			
		||||
 */
 | 
			
		||||
class EntityNormalizer extends NormalizerBase {
 | 
			
		||||
class ContentEntityNormalizer extends NormalizerBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The interface or class that this Normalizer supports.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $supportedInterfaceOrClass = 'Drupal\Core\Entity\EntityInterface';
 | 
			
		||||
  protected $supportedInterfaceOrClass = 'Drupal\Core\Entity\ContentEntityInterface';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The hypermedia link manager.
 | 
			
		||||
| 
						 | 
				
			
			@ -32,20 +34,37 @@ class EntityNormalizer extends NormalizerBase {
 | 
			
		|||
  protected $linkManager;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs an EntityNormalizer object.
 | 
			
		||||
   * The entity manager.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Core\Entity\EntityManagerInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $entityManager;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The module handler.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $moduleHandler;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs an ContentEntityNormalizer object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager
 | 
			
		||||
   *   The hypermedia link manager.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(LinkManagerInterface $link_manager) {
 | 
			
		||||
  public function __construct(LinkManagerInterface $link_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler) {
 | 
			
		||||
    $this->linkManager = $link_manager;
 | 
			
		||||
    $this->entityManager = $entity_manager;
 | 
			
		||||
    $this->moduleHandler = $module_handler;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize()
 | 
			
		||||
   */
 | 
			
		||||
  public function normalize($entity, $format = NULL, array $context = array()) {
 | 
			
		||||
    // Create the array of normalized properties, starting with the URI.
 | 
			
		||||
    // Create the array of normalized fields, starting with the URI.
 | 
			
		||||
    /** @var $entity \Drupal\Core\Entity\ContentEntityInterface */
 | 
			
		||||
    $normalized = array(
 | 
			
		||||
      '_links' => array(
 | 
			
		||||
| 
						 | 
				
			
			@ -58,24 +77,24 @@ class EntityNormalizer extends NormalizerBase {
 | 
			
		|||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // If the properties to use were specified, only output those properties.
 | 
			
		||||
    // Otherwise, output all properties except internal ID.
 | 
			
		||||
    // If the fields to use were specified, only output those field values.
 | 
			
		||||
    // Otherwise, output all field values except internal ID.
 | 
			
		||||
    if (isset($context['included_fields'])) {
 | 
			
		||||
      $properties = array();
 | 
			
		||||
      foreach ($context['included_fields'] as $property_name) {
 | 
			
		||||
        $properties[] = $entity->get($property_name);
 | 
			
		||||
      $fields = array();
 | 
			
		||||
      foreach ($context['included_fields'] as $field_name) {
 | 
			
		||||
        $fields[] = $entity->get($field_name);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $properties = $entity->getProperties();
 | 
			
		||||
      $fields = $entity->getProperties();
 | 
			
		||||
    }
 | 
			
		||||
    foreach ($properties as $property) {
 | 
			
		||||
      // In some cases, Entity API will return NULL array items. Ensure this is
 | 
			
		||||
      // a real property and that it is not the internal id.
 | 
			
		||||
      if (!is_object($property) || $property->getName() == 'id') {
 | 
			
		||||
    // Ignore the entity ID and revision ID.
 | 
			
		||||
    $exclude = array($entity->getEntityType()->getKey('id'), $entity->getEntityType()->getKey('revision'));
 | 
			
		||||
    foreach ($fields as $field) {
 | 
			
		||||
      if (in_array($field->getFieldDefinition()->getName(), $exclude)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      $normalized_property = $this->serializer->normalize($property, $format, $context);
 | 
			
		||||
      $normalized_property = $this->serializer->normalize($field, $format, $context);
 | 
			
		||||
      $normalized = NestedArray::mergeDeep($normalized, $normalized_property);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,14 +132,24 @@ class EntityNormalizer extends NormalizerBase {
 | 
			
		|||
      // Remove the langcode so it does not get iterated over below.
 | 
			
		||||
      unset($data['langcode']);
 | 
			
		||||
    }
 | 
			
		||||
    elseif (\Drupal::moduleHandler()->moduleExists('language')) {
 | 
			
		||||
    elseif ($this->moduleHandler->moduleExists('language')) {
 | 
			
		||||
      $langcode = language_get_default_langcode($typed_data_ids['entity_type'], $typed_data_ids['bundle']);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $langcode = Language::LANGCODE_NOT_SPECIFIED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $entity = entity_create($typed_data_ids['entity_type'], array('langcode' => $langcode, 'type' => $typed_data_ids['bundle']));
 | 
			
		||||
    $entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']);
 | 
			
		||||
    $values = array('langcode' => $langcode);
 | 
			
		||||
 | 
			
		||||
    if ($entity_type->hasKey('bundle')) {
 | 
			
		||||
      $bundle_key = $entity_type->getKey('bundle');
 | 
			
		||||
      $values[$bundle_key] = $typed_data_ids['bundle'];
 | 
			
		||||
      // Unset the bundle key from data, if it's there.
 | 
			
		||||
      unset($data[$bundle_key]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $entity = $this->entityManager->getStorageController($typed_data_ids['entity_type'])->create($values);
 | 
			
		||||
 | 
			
		||||
    // Special handling for PATCH: destroy all possible default values that
 | 
			
		||||
    // might have been set on entity creation. We want an "empty" entity that
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
 | 
			
		||||
namespace Drupal\hal\Normalizer;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\ContentEntityInterface;
 | 
			
		||||
use Drupal\rest\LinkManager\LinkManagerInterface;
 | 
			
		||||
use Drupal\serialization\EntityResolver\EntityResolverInterface;
 | 
			
		||||
use Drupal\serialization\EntityResolver\UuidReferenceInterface;
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +58,12 @@ class EntityReferenceItemNormalizer extends FieldItemNormalizer implements UuidR
 | 
			
		|||
    /** @var $field_item \Drupal\Core\Field\FieldItemInterface */
 | 
			
		||||
    $target_entity = $field_item->get('entity')->getValue();
 | 
			
		||||
 | 
			
		||||
    // If this is not a content entity, let the parent implementation handle it,
 | 
			
		||||
    // only content entities are supported as embedded resources.
 | 
			
		||||
    if (!($target_entity instanceof ContentEntityInterface)) {
 | 
			
		||||
      return parent::normalize($field_item, $format, $context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If the parent entity passed in a langcode, unset it before normalizing
 | 
			
		||||
    // the target entity. Otherwise, untranslatable fields of the target entity
 | 
			
		||||
    // will include the langcode.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,28 +99,19 @@ class FieldItemNormalizer extends NormalizerBase {
 | 
			
		|||
   *   The translated field item instance.
 | 
			
		||||
   */
 | 
			
		||||
  protected function createTranslatedInstance(FieldItemInterface $field_item, $langcode) {
 | 
			
		||||
    $parent = $field_item->getParent();
 | 
			
		||||
    $ancestors = array();
 | 
			
		||||
    $field_items = $field_item->getParent();
 | 
			
		||||
 | 
			
		||||
    // Remove the untranslated instance from the field's list of items.
 | 
			
		||||
    $parent->offsetUnset($field_item->getName());
 | 
			
		||||
    $field_items->offsetUnset($field_item->getName());
 | 
			
		||||
 | 
			
		||||
    // Get the property path.
 | 
			
		||||
    while (!method_exists($parent, 'getTranslation')) {
 | 
			
		||||
      array_unshift($ancestors, $parent);
 | 
			
		||||
      $parent = $parent->getParent();
 | 
			
		||||
    }
 | 
			
		||||
    // Get the entity in the requested language and the field's item list from
 | 
			
		||||
    // that.
 | 
			
		||||
    $entity_translation = $field_item->getEntity()->getTranslation($langcode);
 | 
			
		||||
    $field_items_translation = $entity_translation->get($field_item->getFieldDefinition()->getName());
 | 
			
		||||
 | 
			
		||||
    // Recreate the property path with translations.
 | 
			
		||||
    $translation = $parent->getTranslation($langcode);
 | 
			
		||||
    foreach ($ancestors as $ancestor) {
 | 
			
		||||
      $ancestor_name =  $ancestor->getName();
 | 
			
		||||
      $translation = $translation->get($ancestor_name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create a new instance at the end of the property path and return it.
 | 
			
		||||
    $count = $translation->isEmpty() ? 0 : $translation->count();
 | 
			
		||||
    return $translation->get($count);
 | 
			
		||||
    // Create a new instance and return it.
 | 
			
		||||
    $count = $field_items_translation->isEmpty() ? 0 : $field_items_translation->count();
 | 
			
		||||
    return $field_items_translation->get($count);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,14 +8,14 @@
 | 
			
		|||
namespace Drupal\hal\Normalizer;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\EntityManagerInterface;
 | 
			
		||||
use Drupal\file\Plugin\Core\Entity\File;
 | 
			
		||||
use Drupal\Core\Extension\ModuleHandlerInterface;
 | 
			
		||||
use Drupal\rest\LinkManager\LinkManagerInterface;
 | 
			
		||||
use Guzzle\Http\ClientInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts the Drupal entity object structure to a HAL array structure.
 | 
			
		||||
 */
 | 
			
		||||
class FileEntityNormalizer extends EntityNormalizer {
 | 
			
		||||
class FileEntityNormalizer extends ContentEntityNormalizer {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The interface or class that this Normalizer supports.
 | 
			
		||||
| 
						 | 
				
			
			@ -24,13 +24,6 @@ class FileEntityNormalizer extends EntityNormalizer {
 | 
			
		|||
   */
 | 
			
		||||
  protected $supportedInterfaceOrClass = 'Drupal\file\FileInterface';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The entity manager.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Core\Entity\EntityManagerInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $entityManager;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The HTTP client.
 | 
			
		||||
   *
 | 
			
		||||
| 
						 | 
				
			
			@ -47,11 +40,12 @@ class FileEntityNormalizer extends EntityNormalizer {
 | 
			
		|||
   *   The HTTP Client.
 | 
			
		||||
   * @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager
 | 
			
		||||
   *   The hypermedia link manager.
 | 
			
		||||
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
 | 
			
		||||
   *   The module handler.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(EntityManagerInterface $entity_manager, ClientInterface $http_client, LinkManagerInterface $link_manager) {
 | 
			
		||||
    parent::__construct($link_manager);
 | 
			
		||||
  public function __construct(EntityManagerInterface $entity_manager, ClientInterface $http_client, LinkManagerInterface $link_manager, ModuleHandlerInterface $module_handler) {
 | 
			
		||||
    parent::__construct($link_manager, $entity_manager, $module_handler);
 | 
			
		||||
 | 
			
		||||
    $this->entityManager = $entity_manager;
 | 
			
		||||
    $this->httpClient = $http_client;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,121 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Contains \Drupal\hal\Tests\NormalizeTest.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Drupal\hal\Tests;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test the HAL normalizer on various entities
 | 
			
		||||
 */
 | 
			
		||||
class EntityTest extends NormalizerTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Modules to enable.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $modules = array('node', 'taxonomy');
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public static function getInfo() {
 | 
			
		||||
    return array(
 | 
			
		||||
      'name' => 'Entity normalizer Test',
 | 
			
		||||
      'description' => 'Test that nodes and terms are correctly normalized and denormalized.',
 | 
			
		||||
      'group' => 'HAL',
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  function setUp() {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    \Drupal::service('router.builder')->rebuild();
 | 
			
		||||
    $this->installSchema('system', array('sequences'));
 | 
			
		||||
    $this->installSchema('node', array('node', 'node_field_data', 'node_revision', 'node_field_revision'));
 | 
			
		||||
    $this->installSchema('user', array('users_roles'));
 | 
			
		||||
    $this->installSchema('taxonomy', array('taxonomy_term_data', 'taxonomy_term_hierarchy'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the normalization of nodes.
 | 
			
		||||
   */
 | 
			
		||||
  public function testNode() {
 | 
			
		||||
    $node_type = entity_create('node_type', array('type' => 'example_type'));
 | 
			
		||||
    $node_type->save();
 | 
			
		||||
 | 
			
		||||
    $user = entity_create('user', array('name' => $this->randomName()));
 | 
			
		||||
    $user->save();
 | 
			
		||||
 | 
			
		||||
    $node = entity_create('node', array(
 | 
			
		||||
      'title' => $this->randomName(),
 | 
			
		||||
      'uid' => $user->id(),
 | 
			
		||||
      'type' => $node_type->id(),
 | 
			
		||||
      'status' => NODE_PUBLISHED,
 | 
			
		||||
      'promote' => 1,
 | 
			
		||||
      'sticky' => 0,
 | 
			
		||||
      'body' => array(
 | 
			
		||||
        'value' => $this->randomName(),
 | 
			
		||||
        'format' => $this->randomName(),
 | 
			
		||||
      )
 | 
			
		||||
    ));
 | 
			
		||||
    $node->save();
 | 
			
		||||
 | 
			
		||||
    $original_values = $node->getPropertyValues();
 | 
			
		||||
    unset($original_values['nid']);
 | 
			
		||||
    unset($original_values['vid']);
 | 
			
		||||
 | 
			
		||||
    $normalized = $this->serializer->normalize($node, $this->format);
 | 
			
		||||
 | 
			
		||||
    $denormalized_node = $this->serializer->denormalize($normalized, 'Drupal\node\Entity\Node', $this->format);
 | 
			
		||||
 | 
			
		||||
    // Verify that the ID and revision ID were skipped by the normalizer.
 | 
			
		||||
    $this->assertEqual(NULL, $denormalized_node->id());
 | 
			
		||||
    $this->assertEqual(NULL, $denormalized_node->getRevisionId());
 | 
			
		||||
 | 
			
		||||
    // Loop over the remaining fields and verify that they are identical.
 | 
			
		||||
    foreach ($original_values as $field_name => $field_values) {
 | 
			
		||||
      $this->assertEqual($field_values, $denormalized_node->get($field_name)->getValue());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the normalization of terms.
 | 
			
		||||
   */
 | 
			
		||||
  public function testTerm() {
 | 
			
		||||
    $vocabulary = entity_create('taxonomy_vocabulary', array('vid' => 'example_vocabulary'));
 | 
			
		||||
    $vocabulary->save();
 | 
			
		||||
 | 
			
		||||
    $term = entity_create('taxonomy_term', array(
 | 
			
		||||
      'name' => $this->randomName(),
 | 
			
		||||
      'vid' => $vocabulary->id(),
 | 
			
		||||
      'description' => array(
 | 
			
		||||
        'value' => $this->randomName(),
 | 
			
		||||
        'format' => $this->randomName(),
 | 
			
		||||
      )
 | 
			
		||||
    ));
 | 
			
		||||
    $term->save();
 | 
			
		||||
 | 
			
		||||
    $original_values = $term->getPropertyValues();
 | 
			
		||||
    unset($original_values['tid']);
 | 
			
		||||
 | 
			
		||||
    $normalized = $this->serializer->normalize($term, $this->format);
 | 
			
		||||
 | 
			
		||||
    $denormalized_term = $this->serializer->denormalize($normalized, 'Drupal\taxonomy\Entity\Term', $this->format);
 | 
			
		||||
 | 
			
		||||
    // Verify that the ID and revision ID were skipped by the normalizer.
 | 
			
		||||
    $this->assertEqual(NULL, $denormalized_term->id());
 | 
			
		||||
 | 
			
		||||
    // Loop over the remaining fields and verify that they are identical.
 | 
			
		||||
    foreach ($original_values as $field_name => $field_values) {
 | 
			
		||||
      $this->assertEqual($field_values, $denormalized_term->get($field_name)->getValue());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,13 +10,15 @@ namespace Drupal\hal\Tests;
 | 
			
		|||
use Drupal\Core\Cache\MemoryBackend;
 | 
			
		||||
use Drupal\Core\Language\Language;
 | 
			
		||||
use Drupal\hal\Encoder\JsonEncoder;
 | 
			
		||||
use Drupal\hal\Normalizer\EntityNormalizer;
 | 
			
		||||
use Drupal\hal\Normalizer\ContentEntityNormalizer;
 | 
			
		||||
use Drupal\hal\Normalizer\EntityReferenceItemNormalizer;
 | 
			
		||||
use Drupal\hal\Normalizer\FieldItemNormalizer;
 | 
			
		||||
use Drupal\hal\Normalizer\FieldNormalizer;
 | 
			
		||||
use Drupal\rest\LinkManager\LinkManager;
 | 
			
		||||
use Drupal\rest\LinkManager\RelationLinkManager;
 | 
			
		||||
use Drupal\rest\LinkManager\TypeLinkManager;
 | 
			
		||||
use Drupal\serialization\EntityResolver\ChainEntityResolver;
 | 
			
		||||
use Drupal\serialization\EntityResolver\TargetIdResolver;
 | 
			
		||||
use Drupal\serialization\EntityResolver\UuidResolver;
 | 
			
		||||
use Drupal\simpletest\DrupalUnitTestBase;
 | 
			
		||||
use Symfony\Component\Serializer\Serializer;
 | 
			
		||||
| 
						 | 
				
			
			@ -120,12 +122,14 @@ abstract class NormalizerTestBase extends DrupalUnitTestBase {
 | 
			
		|||
      'bundle' => 'entity_test',
 | 
			
		||||
    ))->save();
 | 
			
		||||
 | 
			
		||||
    $link_manager = new LinkManager(new TypeLinkManager(new MemoryBackend('cache')), new RelationLinkManager(new MemoryBackend('cache')));
 | 
			
		||||
    $link_manager = new LinkManager(new TypeLinkManager(new MemoryBackend('cache')), new RelationLinkManager(new MemoryBackend('cache'), \Drupal::entityManager()));
 | 
			
		||||
 | 
			
		||||
    $chain_resolver = new ChainEntityResolver(array(new UuidResolver(), new TargetIdResolver()));
 | 
			
		||||
 | 
			
		||||
    // Set up the mock serializer.
 | 
			
		||||
    $normalizers = array(
 | 
			
		||||
      new EntityNormalizer($link_manager),
 | 
			
		||||
      new EntityReferenceItemNormalizer($link_manager, new UuidResolver()),
 | 
			
		||||
      new ContentEntityNormalizer($link_manager, \Drupal::entityManager(), \Drupal::moduleHandler()),
 | 
			
		||||
      new EntityReferenceItemNormalizer($link_manager, $chain_resolver),
 | 
			
		||||
      new FieldItemNormalizer(),
 | 
			
		||||
      new FieldNormalizer(),
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ namespace Drupal\rest\LinkManager;
 | 
			
		|||
 | 
			
		||||
use Drupal\Core\Cache\Cache;
 | 
			
		||||
use Drupal\Core\Cache\CacheBackendInterface;
 | 
			
		||||
use Drupal\Core\Entity\EntityManagerInterface;
 | 
			
		||||
 | 
			
		||||
class RelationLinkManager implements RelationLinkManagerInterface{
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +18,24 @@ class RelationLinkManager implements RelationLinkManagerInterface{
 | 
			
		|||
   */
 | 
			
		||||
  protected $cache;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Entity manager.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Core\Entity\EntityManagerInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $entityManager;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructor.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
 | 
			
		||||
   *   The cache of relation URIs and their associated Typed Data IDs.
 | 
			
		||||
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
 | 
			
		||||
   *   The entity manager.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(CacheBackendInterface $cache) {
 | 
			
		||||
  public function __construct(CacheBackendInterface $cache, EntityManagerInterface $entity_manager) {
 | 
			
		||||
    $this->cache = $cache;
 | 
			
		||||
    $this->entityManager = $entity_manager;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -75,20 +86,22 @@ class RelationLinkManager implements RelationLinkManagerInterface{
 | 
			
		|||
  protected function writeCache() {
 | 
			
		||||
    $data = array();
 | 
			
		||||
 | 
			
		||||
    foreach (field_info_field_map() as $entity_type => $entity_type_map) {
 | 
			
		||||
      foreach ($entity_type_map as $field_name => $field_info) {
 | 
			
		||||
        foreach ($field_info['bundles'] as $bundle) {
 | 
			
		||||
          $relation_uri = $this->getRelationUri($entity_type, $bundle, $field_name);
 | 
			
		||||
          $data[$relation_uri] = array(
 | 
			
		||||
            'entity_type' => $entity_type,
 | 
			
		||||
            'bundle' => $bundle,
 | 
			
		||||
            'field_name' => $field_name,
 | 
			
		||||
          );
 | 
			
		||||
    foreach ($this->entityManager->getDefinitions() as $entity_type) {
 | 
			
		||||
      if ($entity_type->isFieldable()) {
 | 
			
		||||
        foreach ($this->entityManager->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) {
 | 
			
		||||
          foreach ($this->entityManager->getFieldDefinitions($entity_type->id(), $bundle) as $field_definition) {
 | 
			
		||||
            $relation_uri = $this->getRelationUri($entity_type->id(), $bundle, $field_definition->getName());
 | 
			
		||||
            $data[$relation_uri] = array(
 | 
			
		||||
              'entity_type' => $entity_type,
 | 
			
		||||
              'bundle' => $bundle,
 | 
			
		||||
              'field_name' => $field_definition->getName(),
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // These URIs only change when field info changes, so cache it permanently
 | 
			
		||||
    // and only clear it when field_info is cleared.
 | 
			
		||||
    $this->cache->set('rest:links:relations', $data, Cache::PERMANENT, array('field_info' => TRUE));
 | 
			
		||||
    // and only clear it when the fields cache is cleared.
 | 
			
		||||
    $this->cache->set('rest:links:relations', $data, Cache::PERMANENT, array('entity_field_info' => TRUE));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,4 +21,4 @@ services:
 | 
			
		|||
    arguments: ['@cache.cache']
 | 
			
		||||
  rest.link_manager.relation:
 | 
			
		||||
    class: Drupal\rest\LinkManager\RelationLinkManager
 | 
			
		||||
    arguments: ['@cache.cache']
 | 
			
		||||
    arguments: ['@cache.cache', '@entity.manager']
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Contains \Drupal\serialization\EntityResolver\TargetIdResolver.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Drupal\serialization\EntityResolver;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Resolves entities from data that contains an entity target ID.
 | 
			
		||||
 */
 | 
			
		||||
class TargetIdResolver implements EntityResolverInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function resolve(NormalizerInterface $normalizer, $data, $entity_type) {
 | 
			
		||||
    if (isset($data['target_id'])) {
 | 
			
		||||
      return $data['target_id'];
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -39,3 +39,7 @@ services:
 | 
			
		|||
    class: Drupal\serialization\EntityResolver\UuidResolver
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: entity_resolver}
 | 
			
		||||
  serialization.entity_resolver.target_id:
 | 
			
		||||
    class: Drupal\serialization\EntityResolver\TargetIdResolver
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: entity_resolver}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue