Issue #1924220 by linclark: Support serialization in hal+json.
parent
11632e296b
commit
b59ad36f0b
|
@ -237,6 +237,9 @@ Filter module
|
|||
Forum module
|
||||
- Lee Rowlands 'larowlan' http://drupal.org/user/395439
|
||||
|
||||
Hypertext Application Language (HAL) module
|
||||
- Lin Clark 'linclark' http://drupal.org/user/396253
|
||||
|
||||
Help module
|
||||
- ?
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
name: 'HAL (Hypertext Application Language)'
|
||||
description: 'Serializes entities using HAL'
|
||||
package: Core
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- rest
|
||||
- serialization
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Drupal-required module file for HAL module.
|
||||
*/
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\JsonEncoder.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder as SymfonyJsonEncoder;
|
||||
|
||||
/**
|
||||
* Encodes HAL data in JSON.
|
||||
*
|
||||
* Simply respond to application/hal+json requests using the JSON encoder.
|
||||
*/
|
||||
class JsonEncoder extends SymfonyJsonEncoder {
|
||||
|
||||
/**
|
||||
* The formats that this Encoder supports.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* Overrides \Symfony\Component\Serializer\Encoder\JsonEncoder::supportsEncoding()
|
||||
*/
|
||||
public function supportsEncoding($format) {
|
||||
return $format == $this->format;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\HalBundle.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
/**
|
||||
* HAL dependency injection container.
|
||||
*/
|
||||
class HalBundle extends Bundle {
|
||||
|
||||
/**
|
||||
* Overrides \Symfony\Component\HttpKernel\Bundle\Bundle::build().
|
||||
*/
|
||||
public function build(ContainerBuilder $container) {
|
||||
$priority = 10;
|
||||
|
||||
$container->register('serializer.normalizer.entity_reference_item.hal', 'Drupal\hal\Normalizer\EntityReferenceItemNormalizer')
|
||||
->addMethodCall('setLinkManager', array(new Reference('rest.link_manager')))
|
||||
->addTag('normalizer', array('priority' => $priority));
|
||||
$container->register('serializer.normalizer.field_item.hal', 'Drupal\hal\Normalizer\FieldItemNormalizer')
|
||||
->addMethodCall('setLinkManager', array(new Reference('rest.link_manager')))
|
||||
->addTag('normalizer', array('priority' => $priority));
|
||||
$container->register('serializer.normalizer.field.hal', 'Drupal\hal\Normalizer\FieldNormalizer')
|
||||
->addMethodCall('setLinkManager', array(new Reference('rest.link_manager')))
|
||||
->addTag('normalizer', array('priority' => $priority));
|
||||
$container->register('serializer.normalizer.entity.hal', 'Drupal\hal\Normalizer\EntityNormalizer')
|
||||
->addMethodCall('setLinkManager', array(new Reference('rest.link_manager')))
|
||||
->addTag('normalizer', array('priority' => $priority));
|
||||
|
||||
$container->register('serializer.encoder.hal', 'Drupal\hal\Encoder\JsonEncoder')
|
||||
->addTag('encoder', array(
|
||||
'priority' => $priority,
|
||||
'format' => array(
|
||||
'hal_json' => 'HAL (JSON)',
|
||||
),
|
||||
));
|
||||
|
||||
$container->register('hal.subscriber', 'Drupal\hal\HalSubscriber')
|
||||
->addTag('event_subscriber');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\HalSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal;
|
||||
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Subscribes to the kernel request event to add HAL media types.
|
||||
*/
|
||||
class HalSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Registers HAL formats with the Request class.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* The event to process.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event) {
|
||||
$request = $event->getRequest();
|
||||
$request->setFormat('hal_json', 'application/hal+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the methods in this class that should be listeners.
|
||||
*
|
||||
* @return array
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
static function getSubscribedEvents() {
|
||||
$events[KernelEvents::REQUEST][] = array('onKernelRequest', 40);
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Normalizer\EntityNormalizer.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Normalizer;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Entity\EntityNG;
|
||||
|
||||
/**
|
||||
* Converts the Drupal entity object structure to a HAL array structure.
|
||||
*/
|
||||
class EntityNormalizer extends NormalizerBase {
|
||||
|
||||
/**
|
||||
* The interface or class that this Normalizer supports.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $supportedInterfaceOrClass = 'Drupal\Core\Entity\EntityInterface';
|
||||
|
||||
/**
|
||||
* 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.
|
||||
$normalized = array(
|
||||
'_links' => array(
|
||||
'self' => array(
|
||||
'href' => $this->getEntityUri($entity),
|
||||
),
|
||||
'type' => array(
|
||||
'href' => $this->linkManager->getTypeUri($entity->entityType(), $entity->bundle()),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// If the properties to use were specified, only output those properties.
|
||||
// Otherwise, output all properties except internal ID.
|
||||
if (isset($context['included_fields'])) {
|
||||
foreach ($context['included_fields'] as $property_name) {
|
||||
$properties[] = $entity->get($property_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$properties = $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') {
|
||||
continue;
|
||||
}
|
||||
$normalized_property = $this->serializer->normalize($property, $format, $context);
|
||||
$normalized = NestedArray::mergeDeep($normalized, $normalized_property);
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the entity URI.
|
||||
*
|
||||
* @param $entity
|
||||
* The entity.
|
||||
*
|
||||
* @return string
|
||||
* The entity URI.
|
||||
*/
|
||||
protected function getEntityUri($entity) {
|
||||
$uri_info = $entity->uri();
|
||||
return url($uri_info['path'], array('absolute' => TRUE));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Normalizer\EntityReferenceItemNormalizer.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Normalizer;
|
||||
|
||||
/**
|
||||
* Converts the Drupal entity reference item object to HAL array structure.
|
||||
*/
|
||||
class EntityReferenceItemNormalizer extends FieldItemNormalizer {
|
||||
|
||||
/**
|
||||
* The interface or class that this Normalizer supports.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $supportedInterfaceOrClass = 'Drupal\Core\Entity\Field\Type\EntityReferenceItem';
|
||||
|
||||
/**
|
||||
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize()
|
||||
*/
|
||||
public function normalize($field_item, $format = NULL, array $context = array()) {
|
||||
$target_entity = $field_item->get('entity')->getValue();
|
||||
|
||||
// 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.
|
||||
$langcode = isset($context['langcode']) ? $context['langcode'] : NULL;
|
||||
unset($context['langcode']);
|
||||
$context['included_fields'] = array('uuid');
|
||||
|
||||
// Normalize the target entity.
|
||||
$embedded = $this->serializer->normalize($target_entity, $format, $context);
|
||||
$link = $embedded['_links']['self'];
|
||||
// If the field is translatable, add the langcode to the link relation
|
||||
// object. This does not indicate the language of the target entity.
|
||||
if ($langcode) {
|
||||
$embedded['lang'] = $link['lang'] = $langcode;
|
||||
}
|
||||
|
||||
// The returned structure will be recursively merged into the normalized
|
||||
// entity so that the items are properly added to the _links and _embedded
|
||||
// objects.
|
||||
$field_name = $field_item->getParent()->getName();
|
||||
$entity = $field_item->getRoot();
|
||||
$field_uri = $this->linkManager->getRelationUri($entity->entityType(), $entity->bundle(), $field_name);
|
||||
return array(
|
||||
'_links' => array(
|
||||
$field_uri => array($link),
|
||||
),
|
||||
'_embedded' => array(
|
||||
$field_uri => array($embedded),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Normalizer\FieldItemNormalizer.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Normalizer;
|
||||
|
||||
/**
|
||||
* Converts the Drupal field item object structure to HAL array structure.
|
||||
*/
|
||||
class FieldItemNormalizer extends NormalizerBase {
|
||||
|
||||
/**
|
||||
* The interface or class that this Normalizer supports.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $supportedInterfaceOrClass = 'Drupal\Core\Entity\Field\FieldItemInterface';
|
||||
|
||||
/**
|
||||
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize()
|
||||
*/
|
||||
public function normalize($field_item, $format = NULL, array $context = array()) {
|
||||
$values = $field_item->getPropertyValues();
|
||||
if (isset($context['langcode'])) {
|
||||
$values['lang'] = $context['langcode'];
|
||||
}
|
||||
|
||||
// The values are wrapped in an array, and then wrapped in another array
|
||||
// keyed by field name so that field items can be merged by the
|
||||
// FieldNormalizer. This is necessary for the EntityReferenceItemNormalizer
|
||||
// to be able to place values in the '_links' array.
|
||||
$field = $field_item->getParent();
|
||||
return array(
|
||||
$field->getName() => array($values),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Normalizer\FieldNormalizer.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Normalizer;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
|
||||
/**
|
||||
* Converts the Drupal field structure to HAL array structure.
|
||||
*/
|
||||
class FieldNormalizer extends NormalizerBase {
|
||||
|
||||
/**
|
||||
* The interface or class that this Normalizer supports.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $supportedInterfaceOrClass = 'Drupal\Core\Entity\Field\FieldInterface';
|
||||
|
||||
/**
|
||||
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize()
|
||||
*/
|
||||
public function normalize($field, $format = NULL, array $context = array()) {
|
||||
$normalized_field_items = array();
|
||||
$entity = $field->getParent();
|
||||
$field_name = $field->getName();
|
||||
$field_definition = $entity->getPropertyDefinition($field_name);
|
||||
|
||||
// If this field is not translatable, it can simply be normalized without
|
||||
// separating it into different translations.
|
||||
if (empty($field_definition['translatable'])) {
|
||||
$normalized_field_items = $this->normalizeFieldItems($field, $format, $context);
|
||||
}
|
||||
// Otherwise, the languages have to be extracted from the entity and passed
|
||||
// in to the field item normalizer in the context. The langcode is appended
|
||||
// to the field item values.
|
||||
else {
|
||||
foreach ($entity->getTranslationLanguages() as $lang) {
|
||||
$context['langcode'] = $lang->langcode == 'und' ? LANGUAGE_DEFAULT : $lang->langcode;
|
||||
$translation = $entity->getTranslation($lang->langcode);
|
||||
$translated_field = $translation->get($field_name);
|
||||
$normalized_field_items = array_merge($normalized_field_items, $this->normalizeFieldItems($translated_field, $format, $context));
|
||||
}
|
||||
}
|
||||
|
||||
// Merge deep so that links set in entity reference normalizers are merged
|
||||
// into the links property.
|
||||
$normalized = NestedArray::mergeDeepArray($normalized_field_items);
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to normalize field items.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\Field\FieldInterface $field
|
||||
* The field object.
|
||||
* @param string $format
|
||||
* The format.
|
||||
* @param array $context
|
||||
* The context array.
|
||||
*
|
||||
* @return array
|
||||
* The array of normalized field items.
|
||||
*/
|
||||
protected function normalizeFieldItems($field, $format, $context) {
|
||||
$normalized_field_items = array();
|
||||
if (!$field->isEmpty()) {
|
||||
foreach ($field as $field_item) {
|
||||
$normalized_field_items[] = $this->serializer->normalize($field_item, $format, $context);
|
||||
}
|
||||
}
|
||||
return $normalized_field_items;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Normalizer\NormalizerBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Normalizer;
|
||||
|
||||
use Drupal\serialization\Normalizer\NormalizerBase as SerializationNormalizerBase;
|
||||
|
||||
/**
|
||||
* Base class for Normalizers.
|
||||
*/
|
||||
abstract class NormalizerBase extends SerializationNormalizerBase {
|
||||
|
||||
/**
|
||||
* The formats that the Normalizer can handle.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $formats = array('hal_json');
|
||||
|
||||
/**
|
||||
* The hypermedia link manager.
|
||||
*
|
||||
* @var \Drupal\rest\LinkManager\LinkManager
|
||||
*/
|
||||
protected $linkManager;
|
||||
|
||||
/**
|
||||
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::supportsNormalization().
|
||||
*/
|
||||
public function supportsNormalization($data, $format = NULL) {
|
||||
return in_array($format, $this->formats) && parent::supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the link manager.
|
||||
*
|
||||
* The link manager determines the hypermedia type and relation links which
|
||||
* correspond to different bundles and fields.
|
||||
*
|
||||
* @param \Drupal\rest\LinkManager\LinkManager $link_manager
|
||||
*/
|
||||
public function setLinkManager($link_manager) {
|
||||
$this->linkManager = $link_manager;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Tests\NormalizeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Tests;
|
||||
|
||||
/**
|
||||
* Test the HAL normalizer.
|
||||
*/
|
||||
class NormalizeTest extends NormalizerTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Normalize Test',
|
||||
'description' => 'Test that entities can be normalized in HAL.',
|
||||
'group' => 'HAL',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the normalize function.
|
||||
*/
|
||||
public function testNormalize() {
|
||||
$target_entity_de = entity_create('entity_test', (array('langcode' => 'de', 'field_test_entity_reference' => NULL)));
|
||||
$target_entity_de->save();
|
||||
$target_entity_en = entity_create('entity_test', (array('langcode' => 'en', 'field_test_entity_reference' => NULL)));
|
||||
$target_entity_en->save();
|
||||
|
||||
// Create a German entity.
|
||||
$values = array(
|
||||
'langcode' => 'de',
|
||||
'name' => $this->randomName(),
|
||||
'user_id' => 1,
|
||||
'field_test_text' => array(
|
||||
'value' => $this->randomName(),
|
||||
'format' => 'full_html',
|
||||
),
|
||||
'field_test_entity_reference' => array(
|
||||
'target_id' => $target_entity_de->id(),
|
||||
),
|
||||
);
|
||||
// Array of translated values.
|
||||
$translation_values = array(
|
||||
'name' => $this->randomName(),
|
||||
'field_test_entity_reference' => array(
|
||||
'target_id' => $target_entity_en->id(),
|
||||
)
|
||||
);
|
||||
|
||||
$entity = entity_create('entity_test', $values);
|
||||
$entity->save();
|
||||
// Add an English value for name and entity reference properties.
|
||||
$entity->getTranslation('en')->set('name', array(0 => array('value' => $translation_values['name'])));
|
||||
$entity->getTranslation('en')->set('field_test_entity_reference', array(0 => $translation_values['field_test_entity_reference']));
|
||||
$entity->save();
|
||||
|
||||
$type_uri = url('rest/type/entity_test/entity_test', array('absolute' => TRUE));
|
||||
$relation_uri = url('rest/relation/entity_test/entity_test/field_test_entity_reference', array('absolute' => TRUE));
|
||||
|
||||
$expected_array = array(
|
||||
'_links' => array(
|
||||
'curies' => array(
|
||||
array(
|
||||
'href' => '/relations',
|
||||
'name' => 'site',
|
||||
'templated' => true,
|
||||
),
|
||||
),
|
||||
'self' => array(
|
||||
'href' => $this->getEntityUri($entity),
|
||||
),
|
||||
'type' => array(
|
||||
'href' => $type_uri,
|
||||
),
|
||||
$relation_uri => array(
|
||||
array(
|
||||
'href' => $this->getEntityUri($target_entity_de),
|
||||
'lang' => 'de',
|
||||
),
|
||||
array(
|
||||
'href' => $this->getEntityUri($target_entity_en),
|
||||
'lang' => 'en',
|
||||
),
|
||||
),
|
||||
),
|
||||
'_embedded' => array(
|
||||
$relation_uri => array(
|
||||
array(
|
||||
'_links' => array(
|
||||
'self' => array(
|
||||
'href' => $this->getEntityUri($target_entity_de),
|
||||
),
|
||||
'type' => array(
|
||||
'href' => $type_uri,
|
||||
),
|
||||
),
|
||||
'uuid' => array(
|
||||
array(
|
||||
'value' => $target_entity_de->uuid(),
|
||||
),
|
||||
),
|
||||
'lang' => 'de',
|
||||
),
|
||||
array(
|
||||
'_links' => array(
|
||||
'self' => array(
|
||||
'href' => $this->getEntityUri($target_entity_en),
|
||||
),
|
||||
'type' => array(
|
||||
'href' => $type_uri,
|
||||
),
|
||||
),
|
||||
'uuid' => array(
|
||||
array(
|
||||
'value' => $target_entity_en->uuid(),
|
||||
),
|
||||
),
|
||||
'lang' => 'en',
|
||||
),
|
||||
),
|
||||
),
|
||||
'uuid' => array(
|
||||
array(
|
||||
'value' => $entity->uuid(),
|
||||
),
|
||||
),
|
||||
'langcode' => array(
|
||||
array(
|
||||
'value' => 'de',
|
||||
),
|
||||
),
|
||||
'name' => array(
|
||||
array(
|
||||
'value' => $values['name'],
|
||||
'lang' => 'de',
|
||||
),
|
||||
array(
|
||||
'value' => $translation_values['name'],
|
||||
'lang' => 'en',
|
||||
),
|
||||
),
|
||||
'field_test_text' => array(
|
||||
array(
|
||||
'value' => $values['field_test_text']['value'],
|
||||
'format' => $values['field_test_text']['format'],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$normalized = $this->container->get('serializer')->normalize($entity, $this->format);
|
||||
$this->assertEqual($normalized['_links']['self'], $expected_array['_links']['self'], 'self link placed correctly.');
|
||||
// @todo Test curies.
|
||||
// @todo Test type.
|
||||
$this->assertFalse(isset($normalized['id']), 'Internal id is not exposed.');
|
||||
$this->assertEqual($normalized['uuid'], $expected_array['uuid'], 'Non-translatable fields is normalized.');
|
||||
$this->assertEqual($normalized['name'], $expected_array['name'], 'Translatable field with multiple language values is normalized.');
|
||||
$this->assertEqual($normalized['field_test_text'], $expected_array['field_test_text'], 'Field with properties is normalized.');
|
||||
$this->assertEqual($normalized['_embedded'][$relation_uri], $expected_array['_embedded'][$relation_uri], 'Entity reference field is normalized.');
|
||||
$this->assertEqual($normalized['_links'][$relation_uri], $expected_array['_links'][$relation_uri], 'Links are added for entity reference field.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the entity URI.
|
||||
*
|
||||
* @param $entity
|
||||
* The entity.
|
||||
*
|
||||
* @return string
|
||||
* The entity URI.
|
||||
*/
|
||||
protected function getEntityUri($entity) {
|
||||
$entity_uri_info = $entity->uri();
|
||||
return url($entity_uri_info['path'], array('absolute' => TRUE));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\Tests\NormalizerTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal\Tests;
|
||||
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\simpletest\DrupalUnitTestBase;
|
||||
|
||||
/**
|
||||
* Test the HAL normalizer.
|
||||
*/
|
||||
abstract class NormalizerTestBase extends DrupalUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_test', 'entity_reference', 'field', 'field_sql_storage', 'hal', 'language', 'rest', 'serialization', 'system', 'text', 'user');
|
||||
|
||||
/**
|
||||
* The format being tested.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\simpletest\DrupalUnitTestBase::setup().
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', array('variable', 'url_alias'));
|
||||
$this->installSchema('field', array('field_config', 'field_config_instance'));
|
||||
$this->installSchema('user', array('users'));
|
||||
$this->installSchema('language', array('language'));
|
||||
$this->installSchema('entity_test', array('entity_test'));
|
||||
|
||||
// Add English as a language.
|
||||
$english = new Language(array(
|
||||
'langcode' => 'en',
|
||||
'name' => 'English',
|
||||
));
|
||||
language_save($english);
|
||||
// Add German as a language.
|
||||
$german = new Language(array(
|
||||
'langcode' => 'de',
|
||||
'name' => 'Deutsch',
|
||||
));
|
||||
language_save($german);
|
||||
|
||||
// Create the test text field.
|
||||
$field = array(
|
||||
'field_name' => 'field_test_text',
|
||||
'type' => 'text',
|
||||
'cardinality' => 1,
|
||||
'translatable' => FALSE,
|
||||
);
|
||||
field_create_field($field);
|
||||
$instance = array(
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_test_text',
|
||||
'bundle' => 'entity_test',
|
||||
);
|
||||
field_create_instance($instance);
|
||||
|
||||
// Create the test entity reference field.
|
||||
$field = array(
|
||||
'translatable' => TRUE,
|
||||
'settings' => array(
|
||||
'target_type' => 'entity_test',
|
||||
),
|
||||
'field_name' => 'field_test_entity_reference',
|
||||
'type' => 'entity_reference',
|
||||
);
|
||||
field_create_field($field);
|
||||
$instance = array(
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_test_entity_reference',
|
||||
'bundle' => 'entity_test',
|
||||
);
|
||||
field_create_instance($instance);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\rest\LinkManager\LinkManager.
|
||||
*/
|
||||
|
||||
namespace Drupal\rest\LinkManager;
|
||||
|
||||
class LinkManager implements LinkManagerInterface {
|
||||
|
||||
/**
|
||||
* The type link manager.
|
||||
*
|
||||
* @var \Drupal\rest\LinkManager\TypeLinkManagerInterface
|
||||
*/
|
||||
protected $typeLinkManager;
|
||||
|
||||
/**
|
||||
* The relation link manager.
|
||||
*
|
||||
* @var \Drupal\rest\LinkManager\RelationLinkManagerInterface
|
||||
*/
|
||||
protected $relationLinkManager;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Drupal\rest\LinkManager\TypeLinkManagerInterface $type_link_manager
|
||||
* Manager for handling bundle URIs.
|
||||
* @param \Drupal\rest\LinkManager\RelationLinkManagerInterface $relation_link_manager
|
||||
* Manager for handling bundle URIs.
|
||||
*/
|
||||
public function __construct(TypeLinkManagerInterface $type_link_manager, RelationLinkManagerInterface $relation_link_manager) {
|
||||
$this->typeLinkManager = $type_link_manager;
|
||||
$this->relationLinkManager = $relation_link_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\rest\LinkManager\TypeLinkManagerInterface::getTypeUri().
|
||||
*/
|
||||
public function getTypeUri($entity_type, $bundle) {
|
||||
return $this->typeLinkManager->getTypeUri($entity_type, $bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\rest\LinkManager\RelationLinkManagerInterface::getRelationUri().
|
||||
*/
|
||||
public function getRelationUri($entity_type, $bundle, $field_name) {
|
||||
return $this->relationLinkManager->getRelationUri($entity_type, $bundle, $field_name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\rest\LinkManager\LinkManagerInterface
|
||||
*/
|
||||
|
||||
namespace Drupal\rest\LinkManager;
|
||||
|
||||
/**
|
||||
* Interface implemented by link managers.
|
||||
*
|
||||
* There are no explicit methods on the manager interface. Instead link managers
|
||||
* broker the interactions of the different components, and therefore must
|
||||
* implement each component interface, which is enforced by this interface
|
||||
* extending all of the component ones.
|
||||
*
|
||||
* While a link manager may directly implement these interface methods with
|
||||
* custom logic, it is expected to be more common for plugin managers to proxy
|
||||
* the method invocations to the respective components.
|
||||
*/
|
||||
interface LinkManagerInterface extends TypeLinkManagerInterface, RelationLinkManagerInterface {
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\rest\LinkManager\RelationLinkManager.
|
||||
*/
|
||||
|
||||
namespace Drupal\rest\LinkManager;
|
||||
|
||||
class RelationLinkManager implements RelationLinkManagerInterface{
|
||||
|
||||
/**
|
||||
* Get a relation link for the field.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The bundle's entity type.
|
||||
* @param string $bundle
|
||||
* The name of the bundle.
|
||||
* @param string $field_name
|
||||
* The name of the field.
|
||||
*
|
||||
* @return array
|
||||
* The URI that identifies this field.
|
||||
*/
|
||||
public function getRelationUri($entity_type, $bundle, $field_name) {
|
||||
// @todo Make the base path configurable.
|
||||
return url("rest/relation/$entity_type/$bundle/$field_name", array('absolute' => TRUE));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\rest\LinkManager\RelationLinkManagerInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\rest\LinkManager;
|
||||
|
||||
interface RelationLinkManagerInterface {
|
||||
|
||||
/**
|
||||
* Gets the URI that corresponds to a field.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The bundle's entity type.
|
||||
* @param string $bundle
|
||||
* The bundle name.
|
||||
* @param string $field_name
|
||||
* The field name.
|
||||
*
|
||||
* @return string
|
||||
* The corresponding URI for the field.
|
||||
*/
|
||||
public function getRelationUri($entity_type, $bundle, $field_name);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\rest\LinkManager\TypeLinkManager.
|
||||
*/
|
||||
|
||||
namespace Drupal\rest\LinkManager;
|
||||
|
||||
class TypeLinkManager implements TypeLinkManagerInterface {
|
||||
|
||||
/**
|
||||
* Get a type link for a bundle.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The bundle's entity type.
|
||||
* @param string $bundle
|
||||
* The name of the bundle.
|
||||
*
|
||||
* @return array
|
||||
* The URI that identifies this bundle.
|
||||
*/
|
||||
public function getTypeUri($entity_type, $bundle) {
|
||||
// @todo Make the base path configurable.
|
||||
return url("rest/type/$entity_type/$bundle", array('absolute' => TRUE));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\rest\LinkManager\TypeLinkManagerInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\rest\LinkManager;
|
||||
|
||||
interface TypeLinkManagerInterface {
|
||||
|
||||
/**
|
||||
* Gets the URI that corresponds to a bundle.
|
||||
*
|
||||
* When using hypermedia formats, this URI can be used to indicate which
|
||||
* bundle the data represents. Documentation about required and optional
|
||||
* fields can also be provided at this URI.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The bundle's entity type.
|
||||
* @param $bundle
|
||||
* The bundle name.
|
||||
*
|
||||
* @return string
|
||||
* The corresponding URI for the bundle.
|
||||
*/
|
||||
public function getTypeUri($entity_type, $bundle);
|
||||
}
|
|
@ -32,5 +32,11 @@ class RestBundle extends Bundle {
|
|||
|
||||
$container->register('access_check.rest.csrf', 'Drupal\rest\Access\CSRFAccessCheck')
|
||||
->addTag('access_check');
|
||||
|
||||
$container->register('rest.link_manager', 'Drupal\rest\LinkManager\LinkManager')
|
||||
->addArgument(new Reference('rest.link_manager.type'))
|
||||
->addArgument(new Reference('rest.link_manager.relation'));
|
||||
$container->register('rest.link_manager.type', 'Drupal\rest\LinkManager\TypeLinkManager');
|
||||
$container->register('rest.link_manager.relation', 'Drupal\rest\LinkManager\RelationLinkManager');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue