Update core 8.3.0

This commit is contained in:
Rob Davies 2017-04-13 15:53:35 +01:00
parent da7a7918f8
commit cd7a898e66
6144 changed files with 132297 additions and 87747 deletions

View file

@ -4,6 +4,8 @@ namespace Drupal\serialization\Encoder;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\JsonDecode;
use Symfony\Component\Serializer\Encoder\JsonEncode;
use Symfony\Component\Serializer\Encoder\JsonEncoder as BaseJsonEncoder;
/**
@ -16,7 +18,19 @@ class JsonEncoder extends BaseJsonEncoder implements EncoderInterface, DecoderIn
*
* @var array
*/
protected static $format = array('json', 'ajax');
protected static $format = ['json', 'ajax'];
/**
* {@inheritdoc}
*/
public function __construct(JsonEncode $encodingImpl = NULL, JsonDecode $decodingImpl = NULL) {
// Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be
// embedded into HTML.
// @see \Symfony\Component\HttpFoundation\JsonResponse
$json_encoding_options = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT;
$this->encodingImpl = $encodingImpl ?: new JsonEncode($json_encoding_options);
$this->decodingImpl = $decodingImpl ?: new JsonDecode(TRUE);
}
/**
* {@inheritdoc}

View file

@ -19,7 +19,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface {
*
* @var array
*/
static protected $format = array('xml');
static protected $format = ['xml'];
/**
* An instance of the Symfony XmlEncoder to perform the actual encoding.
@ -54,7 +54,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface {
/**
* {@inheritdoc}
*/
public function encode($data, $format, array $context = array()){
public function encode($data, $format, array $context = []){
return $this->getBaseEncoder()->encode($data, $format, $context);
}
@ -68,7 +68,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface {
/**
* {@inheritdoc}
*/
public function decode($data, $format, array $context = array()){
public function decode($data, $format, array $context = []){
return $this->getBaseEncoder()->decode($data, $format, $context);
}

View file

@ -14,7 +14,7 @@ class ChainEntityResolver implements ChainEntityResolverInterface {
*
* @var \Drupal\serialization\EntityResolver\EntityResolverInterface[]
*/
protected $resolvers = array();
protected $resolvers = [];
/**
* Constructs a ChainEntityResolver object.
@ -22,7 +22,7 @@ class ChainEntityResolver implements ChainEntityResolverInterface {
* @param \Drupal\serialization\EntityResolver\EntityResolverInterface[] $resolvers
* The array of concrete resolvers.
*/
public function __construct(array $resolvers = array()) {
public function __construct(array $resolvers = []) {
$this->resolvers = $resolvers;
}

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\serialization\EventSubscriber;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\DrupalKernelInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Config event subscriber to rebuild the container when BC config is saved.
*/
class BcConfigSubscriber implements EventSubscriberInterface {
/**
* The Drupal Kernel.
*
* @var \Drupal\Core\DrupalKernelInterface
*/
protected $kernel;
/**
* BcConfigSubscriber constructor.
*
* @param \Drupal\Core\DrupalKernelInterface $kernel
* The Drupal Kernel.
*/
public function __construct(DrupalKernelInterface $kernel) {
$this->kernel = $kernel;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[ConfigEvents::SAVE][] = 'onConfigSave';
return $events;
}
/**
* Invalidates the service container if serialization BC config gets updated.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
*/
public function onConfigSave(ConfigCrudEvent $event) {
$saved_config = $event->getConfig();
if ($saved_config->getName() === 'serialization.settings') {
if ($event->isChanged('bc_primitives_as_strings')) {
$this->kernel->invalidateContainer();
}
}
}
}

View file

@ -56,88 +56,25 @@ class DefaultExceptionSubscriber extends HttpExceptionSubscriberBase {
}
/**
* Handles a 400 error for HTTP.
* Handles all 4xx errors for all serialization failures.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on400(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_BAD_REQUEST);
}
public function on4xx(GetResponseForExceptionEvent $event) {
/** @var \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $exception */
$exception = $event->getException();
$request = $event->getRequest();
/**
* Handles a 403 error for HTTP.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on403(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_FORBIDDEN);
}
/**
* Handles a 404 error for HTTP.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on404(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_NOT_FOUND);
}
/**
* Handles a 405 error for HTTP.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on405(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_METHOD_NOT_ALLOWED);
}
/**
* Handles a 406 error for HTTP.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on406(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_NOT_ACCEPTABLE);
}
/**
* Handles a 422 error for HTTP.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on422(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_UNPROCESSABLE_ENTITY);
}
/**
* Handles a 429 error for HTTP.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The event to process.
*/
public function on429(GetResponseForExceptionEvent $event) {
$this->setEventResponse($event, Response::HTTP_TOO_MANY_REQUESTS);
}
/**
* Sets the Response for the exception event.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
* The current exception event.
* @param int $status
* The HTTP status code to set for the response.
*/
protected function setEventResponse(GetResponseForExceptionEvent $event, $status) {
$format = $event->getRequest()->getRequestFormat();
$format = $request->getRequestFormat();
$content = ['message' => $event->getException()->getMessage()];
$encoded_content = $this->serializer->serialize($content, $format);
$response = new Response($encoded_content, $status);
$headers = $exception->getHeaders();
// Add the MIME type from the request to send back in the header.
$headers['Content-Type'] = $request->getMimeType($format);
$response = new Response($encoded_content, $exception->getStatusCode(), $headers);
$event->setResponse($response);
}

View file

@ -5,20 +5,12 @@ namespace Drupal\serialization\EventSubscriber;
use Drupal\Core\Routing\RouteBuildEvent;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Alters user authentication routes to support additional serialization formats.
*/
class UserRouteAlterSubscriber implements EventSubscriberInterface {
/**
* The serializer.
*
* @var \Symfony\Component\Serializer\Serializer
*/
protected $serializer;
/**
* The available serialization formats.
*
@ -29,13 +21,10 @@ class UserRouteAlterSubscriber implements EventSubscriberInterface {
/**
* UserRouteAlterSubscriber constructor.
*
* @param \Symfony\Component\Serializer\SerializerInterface $serializer
* The serializer service.
* @param array $serializer_formats
* The available serializer formats.
*/
public function __construct(SerializerInterface $serializer, array $serializer_formats) {
$this->serializer = $serializer;
public function __construct(array $serializer_formats) {
$this->serializerFormats = $serializer_formats;
}

View file

@ -24,8 +24,9 @@ class ComplexDataNormalizer extends NormalizerBase {
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
$attributes = array();
public function normalize($object, $format = NULL, array $context = []) {
$attributes = [];
/** @var \Drupal\Core\TypedData\TypedDataInterface $field */
foreach ($object as $name => $field) {
$attributes[$name] = $this->serializer->normalize($field, $format, $context);
}

View file

@ -12,12 +12,12 @@ class ConfigEntityNormalizer extends EntityNormalizer {
*
* @var array
*/
protected $supportedInterfaceOrClass = array('Drupal\Core\Config\Entity\ConfigEntityInterface');
protected $supportedInterfaceOrClass = ['Drupal\Core\Config\Entity\ConfigEntityInterface'];
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
public function normalize($object, $format = NULL, array $context = []) {
return $object->toArray();
}

View file

@ -8,19 +8,17 @@ namespace Drupal\serialization\Normalizer;
class ContentEntityNormalizer extends EntityNormalizer {
/**
* The interface or class that this Normalizer supports.
*
* @var array
* {@inheritdoc}
*/
protected $supportedInterfaceOrClass = ['Drupal\Core\Entity\ContentEntityInterface'];
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
$context += array(
public function normalize($object, $format = NULL, array $context = []) {
$context += [
'account' => NULL,
);
];
$attributes = [];
foreach ($object as $name => $field) {

View file

@ -2,8 +2,9 @@
namespace Drupal\serialization\Normalizer;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Drupal\Core\Entity\FieldableEntityInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
/**
@ -11,19 +12,14 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
*/
class EntityNormalizer extends ComplexDataNormalizer implements DenormalizerInterface {
use FieldableEntityNormalizerTrait;
/**
* The interface or class that this Normalizer supports.
*
* @var array
*/
protected $supportedInterfaceOrClass = array('Drupal\Core\Entity\EntityInterface');
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
protected $supportedInterfaceOrClass = [EntityInterface::class];
/**
* Constructs an EntityNormalizer object.
@ -39,49 +35,26 @@ class EntityNormalizer extends ComplexDataNormalizer implements DenormalizerInte
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = NULL, array $context = []) {
// Get the entity type ID while letting context override the $class param.
$entity_type_id = !empty($context['entity_type']) ? $context['entity_type'] : $this->entityManager->getEntityTypeFromClass($class);
$entity_type_id = $this->determineEntityTypeId($class, $context);
$entity_type_definition = $this->getEntityTypeDefinition($entity_type_id);
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type_definition */
// Get the entity type definition.
$entity_type_definition = $this->entityManager->getDefinition($entity_type_id, FALSE);
// The bundle property will be required to denormalize a bundleable
// fieldable entity.
if ($entity_type_definition->hasKey('bundle') && $entity_type_definition->isSubclassOf(FieldableEntityInterface::class)) {
// Get an array containing the bundle only. This also remove the bundle
// key from the $data array.
$bundle_data = $this->extractBundleData($data, $entity_type_definition);
// Don't try to create an entity without an entity type id.
if (!$entity_type_definition) {
throw new UnexpectedValueException(sprintf('The specified entity type "%s" does not exist. A valid etnity type is required for denormalization', $entity_type_id));
// Create the entity from bundle data only, then apply field values after.
$entity = $this->entityManager->getStorage($entity_type_id)->create($bundle_data);
$this->denormalizeFieldData($data, $entity, $format, $context);
}
// The bundle property will be required to denormalize a bundleable entity.
if ($entity_type_definition->hasKey('bundle')) {
$bundle_key = $entity_type_definition->getKey('bundle');
// Get the base field definitions for this entity type.
$base_field_definitions = $this->entityManager->getBaseFieldDefinitions($entity_type_id);
// Get the ID key from the base field definition for the bundle key or
// default to 'value'.
$key_id = isset($base_field_definitions[$bundle_key]) ? $base_field_definitions[$bundle_key]->getFieldStorageDefinition()->getMainPropertyName() : 'value';
// Normalize the bundle if it is not explicitly set.
$data[$bundle_key] = isset($data[$bundle_key][0][$key_id]) ? $data[$bundle_key][0][$key_id] : (isset($data[$bundle_key]) ? $data[$bundle_key] : NULL);
// Get the bundle entity type from the entity type definition.
$bundle_type_id = $entity_type_definition->getBundleEntityType();
$bundle_types = $bundle_type_id ? $this->entityManager->getStorage($bundle_type_id)->getQuery()->execute() : [];
// Make sure a bundle has been provided.
if (!is_string($data[$bundle_key])) {
throw new UnexpectedValueException('A string must be provided as a bundle value.');
}
// Make sure the submitted bundle is a valid bundle for the entity type.
if ($bundle_types && !in_array($data[$bundle_key], $bundle_types)) {
throw new UnexpectedValueException(sprintf('"%s" is not a valid bundle type for denormalization.', $data[$bundle_key]));
}
else {
// Create the entity from all data.
$entity = $this->entityManager->getStorage($entity_type_id)->create($data);
}
// Create the entity from data.
$entity = $this->entityManager->getStorage($entity_type_id)->create($data);
// Pass the names of the fields whose values can be merged.
// @todo https://www.drupal.org/node/2456257 remove this.
$entity->_restSubmittedFields = array_keys($data);

View file

@ -0,0 +1,57 @@
<?php
namespace Drupal\serialization\Normalizer;
use Drupal\Core\Field\FieldItemInterface;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
/**
* Denormalizes field item object structure by updating the entity field values.
*/
class FieldItemNormalizer extends ComplexDataNormalizer implements DenormalizerInterface {
/**
* {@inheritdoc}
*/
protected $supportedInterfaceOrClass = FieldItemInterface::class;
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = NULL, array $context = []) {
if (!isset($context['target_instance'])) {
throw new InvalidArgumentException('$context[\'target_instance\'] must be set to denormalize with the FieldItemNormalizer');
}
if ($context['target_instance']->getParent() == NULL) {
throw new InvalidArgumentException('The field item passed in via $context[\'target_instance\'] must have a parent set.');
}
/** @var \Drupal\Core\Field\FieldItemInterface $field_item */
$field_item = $context['target_instance'];
$field_item->setValue($this->constructValue($data, $context));
return $field_item;
}
/**
* Build the field item value using the incoming data.
*
* Most normalizers that extend this class can simply use this method to
* construct the denormalized value without having to override denormalize()
* and reimplementing its validation logic or its call to set the field value.
*
* @param mixed $data
* The incoming data for this field item.
* @param array $context
* The context passed into the Normalizer.
*
* @return mixed
* The value to use in Entity::setValue().
*/
protected function constructValue($data, $context) {
return $data;
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace Drupal\serialization\Normalizer;
use Drupal\Core\Field\FieldItemListInterface;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
/**
* Denormalizes data to Drupal field values.
*
* This class simply calls denormalize() on the individual FieldItems. The
* FieldItem normalizers are responsible for setting the field values for each
* item.
*
* @see \Drupal\serialization\Normalizer\FieldItemNormalizer.
*/
class FieldNormalizer extends ListNormalizer implements DenormalizerInterface {
/**
* {@inheritdoc}
*/
protected $supportedInterfaceOrClass = FieldItemListInterface::class;
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = NULL, array $context = []) {
if (!isset($context['target_instance'])) {
throw new InvalidArgumentException('$context[\'target_instance\'] must be set to denormalize with the FieldNormalizer');
}
if ($context['target_instance']->getParent() == NULL) {
throw new InvalidArgumentException('The field passed in via $context[\'target_instance\'] must have a parent set.');
}
/** @var FieldItemListInterface $items */
$items = $context['target_instance'];
$item_class = $items->getItemDefinition()->getClass();
if (!is_array($data)) {
throw new UnexpectedValueException(sprintf('Field values for "%s" must use an array structure', $items->getName()));
}
foreach ($data as $item_data) {
// Create a new item and pass it as the target for the unserialization of
// $item_data. All items in field should have removed before this method
// was called.
// @see \Drupal\serialization\Normalizer\ContentEntityNormalizer::denormalize().
$context['target_instance'] = $items->appendItem();
$this->serializer->denormalize($item_data, $item_class, $format, $context);
}
return $items;
}
}

View file

@ -0,0 +1,140 @@
<?php
namespace Drupal\serialization\Normalizer;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
/**
* A trait for providing fieldable entity normalization/denormalization methods.
*
* @todo Move this into a FieldableEntityNormalizer in Drupal 9. This is a trait
* used in \Drupal\serialization\Normalizer\EntityNormalizer to maintain BC.
* @see https://www.drupal.org/node/2834734
*/
trait FieldableEntityNormalizerTrait {
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* Determines the entity type ID to denormalize as.
*
* @param string $class
* The entity type class to be denormalized to.
* @param array $context
* The serialization context data.
*
* @return string
* The entity type ID.
*/
protected function determineEntityTypeId($class, $context) {
// Get the entity type ID while letting context override the $class param.
return !empty($context['entity_type']) ? $context['entity_type'] : $this->entityManager->getEntityTypeFromClass($class);
}
/**
* Gets the entity type definition.
*
* @param string $entity_type_id
* The entity type ID to load the definition for.
*
* @return \Drupal\Core\Entity\EntityTypeInterface
* The loaded entity type definition.
*
* @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException
*/
protected function getEntityTypeDefinition($entity_type_id) {
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type_definition */
// Get the entity type definition.
$entity_type_definition = $this->entityManager->getDefinition($entity_type_id, FALSE);
// Don't try to create an entity without an entity type id.
if (!$entity_type_definition) {
throw new UnexpectedValueException(sprintf('The specified entity type "%s" does not exist. A valid entity type is required for denormalization', $entity_type_id));
}
return $entity_type_definition;
}
/**
* Denormalizes the bundle property so entity creation can use it.
*
* @param array $data
* The data being denormalized.
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type_definition
* The entity type definition.
*
* @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException
*
* @return string
* The valid bundle name.
*/
protected function extractBundleData(array &$data, EntityTypeInterface $entity_type_definition) {
$bundle_key = $entity_type_definition->getKey('bundle');
// Get the base field definitions for this entity type.
$base_field_definitions = $this->entityManager->getBaseFieldDefinitions($entity_type_definition->id());
// Get the ID key from the base field definition for the bundle key or
// default to 'value'.
$key_id = isset($base_field_definitions[$bundle_key]) ? $base_field_definitions[$bundle_key]->getFieldStorageDefinition()->getMainPropertyName() : 'value';
// Normalize the bundle if it is not explicitly set.
$bundle_value = isset($data[$bundle_key][0][$key_id]) ? $data[$bundle_key][0][$key_id] : (isset($data[$bundle_key]) ? $data[$bundle_key] : NULL);
// Unset the bundle from the data.
unset($data[$bundle_key]);
// Get the bundle entity type from the entity type definition.
$bundle_type_id = $entity_type_definition->getBundleEntityType();
$bundle_types = $bundle_type_id ? $this->entityManager->getStorage($bundle_type_id)->getQuery()->execute() : [];
// Make sure a bundle has been provided.
if (!is_string($bundle_value)) {
throw new UnexpectedValueException(sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_key));
}
// Make sure the submitted bundle is a valid bundle for the entity type.
if ($bundle_types && !in_array($bundle_value, $bundle_types)) {
throw new UnexpectedValueException(sprintf('"%s" is not a valid bundle type for denormalization.', $bundle_value));
}
return [$bundle_key => $bundle_value];
}
/**
* Denormalizes entity data by denormalizing each field individually.
*
* @param array $data
* The data to denormalize.
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The fieldable entity to set field values for.
* @param string $format
* The serialization format.
* @param array $context
* The context data.
*/
protected function denormalizeFieldData(array $data, FieldableEntityInterface $entity, $format, array $context) {
foreach ($data as $field_name => $field_data) {
$field_item_list = $entity->get($field_name);
// Remove any values that were set as a part of entity creation (e.g
// uuid). If the incoming field data is set to an empty array, this will
// also have the effect of emptying the field in REST module.
$field_item_list->setValue([]);
$field_item_list_class = get_class($field_item_list);
if ($field_data) {
// The field instance must be passed in the context so that the field
// denormalizer can update field values for the parent entity.
$context['target_instance'] = $field_item_list;
$this->serializer->denormalize($field_data, $field_item_list_class, $format, $context);
}
}
}
}

View file

@ -23,8 +23,8 @@ class ListNormalizer extends NormalizerBase {
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
$attributes = array();
public function normalize($object, $format = NULL, array $context = []) {
$attributes = [];
foreach ($object as $fieldItem) {
$attributes[] = $this->serializer->normalize($fieldItem, $format, $context);
}

View file

@ -12,12 +12,12 @@ class MarkupNormalizer extends NormalizerBase {
*
* @var array
*/
protected $supportedInterfaceOrClass = array('Drupal\Component\Render\MarkupInterface');
protected $supportedInterfaceOrClass = ['Drupal\Component\Render\MarkupInterface'];
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
public function normalize($object, $format = NULL, array $context = []) {
return (string) $object;
}

View file

@ -20,7 +20,7 @@ class NullNormalizer extends NormalizerBase {
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
public function normalize($object, $format = NULL, array $context = []) {
return NULL;
}

View file

@ -0,0 +1,32 @@
<?php
namespace Drupal\serialization\Normalizer;
use Drupal\Core\TypedData\PrimitiveInterface;
/**
* Converts primitive data objects to their casted values.
*/
class PrimitiveDataNormalizer extends NormalizerBase {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected $supportedInterfaceOrClass = PrimitiveInterface::class;
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = []) {
// Typed data casts NULL objects to their empty variants, so for example
// the empty string ('') for string type data, or 0 for integer typed data.
// In a better world with typed data implementing algebraic data types,
// getCastedValue would return NULL, but as typed data is not aware of real
// optional values on the primitive level, we implement our own optional
// value normalization here.
return $object->getValue() === NULL ? NULL : $object->getCastedValue();
}
}

View file

@ -17,7 +17,7 @@ class TypedDataNormalizer extends NormalizerBase {
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
public function normalize($object, $format = NULL, array $context = []) {
return $object->getValue();
}

View file

@ -19,7 +19,7 @@ class RegisterEntityResolversCompilerPass implements CompilerPassInterface {
*/
public function process(ContainerBuilder $container) {
$definition = $container->getDefinition('serializer.entity_resolver');
$resolvers = array();
$resolvers = [];
// Retrieve registered Normalizers and Encoders from the container.
foreach ($container->findTaggedServiceIds('entity_resolver') as $id => $attributes) {
@ -29,7 +29,7 @@ class RegisterEntityResolversCompilerPass implements CompilerPassInterface {
// Add the registered concrete EntityResolvers to the ChainEntityResolver.
foreach ($this->sort($resolvers) as $resolver) {
$definition->addMethodCall('addResolver', array($resolver));
$definition->addMethodCall('addResolver', [$resolver]);
}
}
@ -48,7 +48,7 @@ class RegisterEntityResolversCompilerPass implements CompilerPassInterface {
* to low priority.
*/
protected function sort($services) {
$sorted = array();
$sorted = [];
krsort($services);
// Flatten the array.

View file

@ -2,6 +2,7 @@
namespace Drupal\serialization;
use Drupal\Core\Config\BootstrapConfigStorageFactory;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
@ -22,6 +23,12 @@ class RegisterSerializationClassesCompilerPass implements CompilerPassInterface
// Retrieve registered Normalizers and Encoders from the container.
foreach ($container->findTaggedServiceIds('normalizer') as $id => $attributes) {
// If there is a BC key present, pass this to determine if the normalizer
// should be skipped.
if (isset($attributes[0]['bc']) && $this->normalizerBcSettingIsEnabled($attributes[0]['bc'], $attributes[0]['bc_config_name'])) {
continue;
}
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
$normalizers[$priority][] = new Reference($id);
}
@ -39,7 +46,7 @@ class RegisterSerializationClassesCompilerPass implements CompilerPassInterface
}
// Find all serialization formats known.
$formats = array();
$formats = [];
$format_providers = [];
foreach ($container->findTaggedServiceIds('encoder') as $service_id => $attributes) {
$format = $attributes[0]['format'];
@ -53,6 +60,18 @@ class RegisterSerializationClassesCompilerPass implements CompilerPassInterface
$container->setParameter('serializer.format_providers', $format_providers);
}
/**
* Returns whether a normalizer BC setting is disabled or not.
*
* @param string $key
*
* @return bool
*/
protected function normalizerBcSettingIsEnabled($key, $config_name) {
$settings = BootstrapConfigStorageFactory::get()->read($config_name);
return !empty($settings[$key]);
}
/**
* Sorts by priority.
*
@ -68,7 +87,7 @@ class RegisterSerializationClassesCompilerPass implements CompilerPassInterface
* to low priority.
*/
protected function sort($services) {
$sorted = array();
$sorted = [];
krsort($services);
// Flatten the array.

View file

@ -1,45 +0,0 @@
<?php
namespace Drupal\serialization\Tests;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\serialization\RegisterSerializationClassesCompilerPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Serializer\Serializer;
/**
* @coversDefaultClass \Drupal\serialization\RegisterSerializationClassesCompilerPass
* @group serialization
*/
class RegisterSerializationClassesCompilerPassTest extends \PHPUnit_Framework_TestCase {
/**
* @covers ::process
*/
public function testEncoders() {
$container = new ContainerBuilder();
$container->setDefinition('serializer', new Definition(Serializer::class, [[], []]));
$definition = new Definition('TestClass');
$definition->addTag('encoder', ['format' => 'xml']);
$definition->addTag('_provider', ['provider' => 'test_provider_a']);
$container->setDefinition('encoder_1', $definition);
$definition = new Definition('TestClass');
$definition->addTag('encoder', ['format' => 'json']);
$definition->addTag('_provider', ['provider' => 'test_provider_a']);
$container->setDefinition('encoder_2', $definition);
$definition = new Definition('TestClass');
$definition->addTag('encoder', ['format' => 'hal_json']);
$definition->addTag('_provider', ['provider' => 'test_provider_b']);
$container->setDefinition('encoder_3', $definition);
$compiler_pass = new RegisterSerializationClassesCompilerPass();
$compiler_pass->process($container);
$this->assertEquals(['xml', 'json', 'hal_json'], $container->getParameter('serializer.formats'));
$this->assertEquals(['xml' => 'test_provider_a', 'json' => 'test_provider_a', 'hal_json' => 'test_provider_b'], $container->getParameter('serializer.format_providers'));
}
}