Commit cdd39859 authored by webchick's avatar webchick

Issue #1892320 by damiankloip, linclark: Add deserialize for JSON/AJAX.

parent 4b9ecbbb
......@@ -7,25 +7,34 @@
namespace Drupal\serialization\Encoder;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder as BaseJsonEncoder;
/**
* Adds 'ajax to the supported content types of the JSON encoder'
*/
class JsonEncoder extends BaseJsonEncoder implements EncoderInterface {
class JsonEncoder extends BaseJsonEncoder implements EncoderInterface, DecoderInterface {
/**
* The formats that this Encoder supports.
*
* @var array
*/
static protected $format = array('json', 'ajax');
protected static $format = array('json', 'ajax');
/**
* Overrides Symfony\Component\Serializer\Encoder\JsonEncoder::supportEncoding().
* {@inheritdoc}
*/
public function supportsEncoding($format) {
return in_array($format, static::$format);
}
/**
* {@inheritdoc}
*/
public function supportsDecoding($format) {
return in_array($format, static::$format);
}
}
<?php
/**
* @file
* Contains \Drupal\serialization\Normalizer\EntityNormalizer.
*/
namespace Drupal\serialization\Normalizer;
use Drupal\Core\Entity\EntityManagerInterface;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
/**
* Normalizes/denormalizes Drupal entity objects into an array structure.
*/
class EntityNormalizer extends NormalizerBase implements DenormalizerInterface {
/**
* 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;
/**
* Constructs an EntityNormalizer object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
*/
public function __construct(EntityManagerInterface $entity_manager) {
$this->entityManager = $entity_manager;
}
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
$attributes = array();
foreach ($object as $name => $field) {
$attributes[$name] = $this->serializer->normalize($field, $format);
}
return $attributes;
}
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = NULL, array $context = array()) {
if (empty($context['entity_type'])) {
throw new UnexpectedValueException('Entity type parameter must be included in context.');
}
$entity_info = $this->entityManager->getDefinition($context['entity_type']);
// The bundle property behaves differently from other entity properties.
// i.e. the nested structure with a 'value' key does not work.
if ($entity_info->hasKey('bundle')) {
$bundle_key = $entity_info->getKey('bundle');
$type = $data[$bundle_key][0]['value'];
$data[$bundle_key] = $type;
}
return $this->entityManager->getStorageController($context['entity_type'])->create($data);
}
}
......@@ -18,15 +18,65 @@ abstract class NormalizerBase extends SerializerAwareNormalizer implements Norma
/**
* The interface or class that this Normalizer supports.
*
* @var string
* @var string|array
*/
protected $supportedInterfaceOrClass;
/**
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::supportsNormalization().
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = NULL) {
return is_object($data) && (isset($this->supportedInterfaceOrClass) && ($data instanceof $this->supportedInterfaceOrClass));
// If we aren't dealing with an object or the format is not supported return
// now.
if (!is_object($data) || !$this->checkFormat($format)) {
return FALSE;
}
$supported = (array) $this->supportedInterfaceOrClass;
return (bool) array_filter($supported, function($name) use ($data) {
return $data instanceof $name;
});
}
/**
* Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization()
*
* This class doesn't implement DenormalizerInterface, but most of its child
* classes do, so this method is implemented at this level to reduce code
* duplication.
*/
public function supportsDenormalization($data, $type, $format = NULL) {
// If the format is not supported return now.
if (!$this->checkFormat($format)) {
return FALSE;
}
$supported = (array) $this->supportedInterfaceOrClass;
$subclass_check = function($name) use ($type) {
return (class_exists($name) || interface_exists($name)) && is_subclass_of($type, $name, TRUE);
};
return in_array($type, $supported) || array_filter($supported, $subclass_check);
}
/**
* Checks if the provided format is supported by this normalizer.
*
* @param string $format
* The format to check.
*
* @return bool
* TRUE if the format is supported, FALSE otherwise. If no format is
* specified this will return TRUE.
*/
protected function checkFormat($format = NULL) {
if (!isset($format) || !isset($this->format)) {
return TRUE;
}
return in_array($format, (array) $this->format);
}
}
......@@ -8,11 +8,8 @@
namespace Drupal\serialization\Tests;
use Drupal\Core\Language\Language;
use Drupal\serialization\Encoder\JsonEncoder;
use Drupal\serialization\Normalizer\ComplexDataNormalizer;
use Drupal\serialization\Normalizer\TypedDataNormalizer;
use Drupal\simpletest\DrupalUnitTestBase;
use Symfony\Component\Serializer\Serializer;
use Drupal\Component\Utility\String;
/**
* Tests entity normalization and serialization of supported core formats.
......@@ -40,6 +37,13 @@ class EntitySerializationTest extends NormalizerTestBase {
*/
protected $serializer;
/**
* The class name of the test class.
*
* @var string
*/
protected $entityClass = 'Drupal\entity_test\Entity\EntityTest';
public static function getInfo() {
return array(
'name' => 'Entity serialization tests',
......@@ -159,4 +163,19 @@ public function testSerialize() {
$actual = $this->serializer->serialize($normalized, 'xml');
$this->assertIdentical($actual, $expected);
}
/**
* Tests denormalization of an entity.
*/
public function testDenormalize() {
$normalized = $this->serializer->normalize($this->entity);
foreach (array('json', 'xml') as $type) {
$denormalized = $this->serializer->denormalize($normalized, $this->entityClass, $type, array('entity_type' => 'entity_test_mulrev'));
$this->assertTrue($denormalized instanceof $this->entityClass, String::format('Denormalized entity is an instance of @class', array('@class' => $this->entityClass)));
$this->assertIdentical($denormalized->entityType(), $this->entity->entityType(), 'Expected entity type found.');
$this->assertIdentical($denormalized->bundle(), $this->entity->bundle(), 'Expected entity bundle found.');
$this->assertIdentical($denormalized->uuid(), $this->entity->uuid(), 'Expected entity UUID found.');
}
}
}
......@@ -2,6 +2,11 @@ services:
serializer:
class: Symfony\Component\Serializer\Serializer
arguments: [{ }, { }]
serializer.normalizer.entity:
class: Drupal\serialization\Normalizer\EntityNormalizer
tags:
- { name: normalizer }
arguments: ['@entity.manager']
serializer.normalizer.complex_data:
class: Drupal\serialization\Normalizer\ComplexDataNormalizer
tags:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment