Commit 6d29b0ee authored by Dries's avatar Dries
Browse files

Issue #1846000 by damiankloip, linclark, dawehner: Add serializer support for JSON and AJAX.

parent 79fa70ee
......@@ -233,6 +233,11 @@ public function build(ContainerBuilder $container) {
->addArgument(array())
->addArgument(array());
$container->register('serializer.normalizer.complex_data', 'Drupal\Core\Serialization\ComplexDataNormalizer')->addTag('normalizer');
$container->register('serializer.normalizer.list', 'Drupal\Core\Serialization\ListNormalizer')->addTag('normalizer');
$container->register('serializer.normalizer.typed_data', 'Drupal\Core\Serialization\TypedDataNormalizer')->addTag('normalizer');
$container->register('serializer.encoder.json', 'Drupal\Core\Serialization\JsonEncoder')->addTag('encoder');
$container->register('flood', 'Drupal\Core\Flood\DatabaseBackend')
->addArgument(new Reference('database'));
......
<?php
/**
* @file
* Contains \Drupal\Core\Serialization\ComplexDataNormalizer.
*/
namespace Drupal\Core\Serialization;
use Drupal\Core\Serialization\NormalizerBase;
use Symfony\Component\Serializer\Exception\RuntimeException;
/**
* Converts the Drupal entity object structures to a normalized array.
*
* This is the default Normalizer for entities. All formats that have Encoders
* registered with the Serializer in the DIC will be normalized with this
* class unless another Normalizer is registered which supersedes it. If a
* module wants to use format-specific or class-specific normalization, then
* that module can register a new Normalizer and give it a higher priority than
* this one.
*/
class ComplexDataNormalizer extends NormalizerBase {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected static $supportedInterfaceOrClass = 'Drupal\Core\TypedData\ComplexDataInterface';
/**
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize().
*/
public function normalize($object, $format = NULL) {
$attributes = array();
foreach ($object as $name => $field) {
$attributes[$name] = $this->serializer->normalize($field, $format);
}
return $attributes;
}
}
<?php
/**
* @file
* Contains Drupal\Core\Serialization\JsonEncoder.
*/
namespace Drupal\Core\Serialization;
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 {
/**
* The formats that this Encoder supports.
*
* @var array
*/
static protected $format = array('json', 'ajax');
/**
* Overrides Symfony\Component\Serializer\Encoder\JsonEncoder::supportEncoding().
*/
public function supportsEncoding($format) {
return in_array($format, static::$format);
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Serialization\ListNormalizer.
*/
namespace Drupal\Core\Serialization;
use Drupal\Core\Serialization\NormalizerBase;
use Symfony\Component\Serializer\Exception\RuntimeException;
/**
* Converts list objects to arrays.
*
* Ordinarily, this would be handled automatically by Serializer, but since
* there is a TypedDataNormalizer and the Field class extends TypedData, any
* Field will be handled by that Normalizer instead of being traversed. This
* class ensures that TypedData classes that also implement ListInterface are
* traversed instead of simply returning getValue().
*/
class ListNormalizer extends NormalizerBase {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected static $supportedInterfaceOrClass = 'Drupal\Core\TypedData\ListInterface';
/**
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize().
*/
public function normalize($object, $format = NULL) {
$attributes = array();
foreach ($object as $fieldItem) {
$attributes[] = $this->serializer->normalize($fieldItem, $format);
}
return $attributes;
}
}
<?php
/**
* @file
* Contains Drupal\Core\Serialization\NormalizerBase.
*/
namespace Drupal\Core\Serialization;
use Drupal\Core\Entity\EntityInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\SerializerAwareNormalizer;
/**
* Base class for Normalizers.
*/
abstract class NormalizerBase extends SerializerAwareNormalizer implements NormalizerInterface {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected static $supportedInterfaceOrClass;
/**
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::supportsNormalization().
*/
public function supportsNormalization($data, $format = NULL) {
return is_object($data) && ($data instanceof static::$supportedInterfaceOrClass);
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Serialization\TypedDataNormalizer.
*/
namespace Drupal\Core\Serialization;
use Drupal\Core\Serialization\NormalizerBase;
use Symfony\Component\Serializer\Exception\RuntimeException;
/**
* Converts typed data objects to arrays.
*/
class TypedDataNormalizer extends NormalizerBase {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected static $supportedInterfaceOrClass = 'Drupal\Core\TypedData\TypedDataInterface';
/**
* Implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface::normalize().
*/
public function normalize($object, $format = NULL) {
return $object->getValue();
}
}
<?php
/**
* @file
* Contains \Drupal\system\Tests\Serialization\EntitySerializationTest.
*/
namespace Drupal\system\Tests\Serialization;
use Drupal\simpletest\WebTestBase;
use Symfony\Component\Serializer\Serializer;
use Drupal\Core\Serialization\JsonEncoder;
use Drupal\Core\Serialization\ComplexDataNormalizer;
use Drupal\Core\Serialization\TypedDataNormalizer;
/**
* Tests entity normalization and serialization of supported core formats.
*/
class EntitySerializationTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('entity_test');
/**
* The test values.
*
* @var array
*/
protected $values;
/**
* The test entity.
*
* @var \Drupal\Core\Entity\EntityNG
*/
protected $entity;
public static function getInfo() {
return array(
'name' => 'Entity serialization tests',
'description' => 'Tests that entities can be serialized to supported core formats.',
'group' => 'Serialization',
);
}
protected function setUp() {
parent::setUp();
// Create a test entity to serialize.
$this->values = array(
'name' => $this->randomName(),
'user_id' => $GLOBALS['user']->uid,
'field_test_text' => array(
'value' => $this->randomName(),
'format' => 'full_html',
),
);
$this->entity = entity_create('entity_test', $this->values);
$this->entity->save();
}
/**
* Test the normalize function.
*/
public function testNormalize() {
// Set up the serializer.
$encoders = array(new JsonEncoder());
$normalizers = array(new ComplexDataNormalizer(), new TypedDataNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$expected = array(
'id' => array(
array('value' => 1),
),
'revision_id' => array(
array('value' => 1),
),
'uuid' => array(
array('value' => $this->entity->uuid()),
),
'langcode' => array(
array('value' => LANGUAGE_NOT_SPECIFIED),
),
'default_langcode' => array(NULL),
'name' => array(
array('value' => $this->values['name']),
),
'user_id' => array(
array('value' => $this->values['user_id']),
),
'field_test_text' => array(
array(
'value' => $this->values['field_test_text']['value'],
'format' => $this->values['field_test_text']['format'],
),
),
);
$normalized = $serializer->normalize($this->entity);
foreach (array_keys($expected) as $fieldName) {
$this->assertEqual($expected[$fieldName], $normalized[$fieldName], "ComplexDataNormalizer produces expected array for $fieldName.");
}
$this->assertEqual(array_keys($expected), array_keys($normalized), 'No unexpected data is added to the normalized array.');
}
/**
* Test registered Serializer's entity serialization for core's formats.
*/
public function testSerialize() {
$serializer = drupal_container()->get('serializer');
// Test that Serializer responds using the ComplexDataNormalizer and
// JsonEncoder. The output of ComplexDataNormalizer::normalize() is tested
// elsewhere, so we can just assume that it works properly here.
$normalized = $serializer->normalize($this->entity, 'json');
$expected = json_encode($normalized);
// Test 'json'.
$actual = $serializer->serialize($this->entity, 'json');
$this->assertIdentical($actual, $expected, 'Entity serializes to JSON when json is requested.');
// Test 'ajax'.
$actual = $serializer->serialize($this->entity, 'ajax');
$this->assertIdentical($actual, $expected, 'Entity serializes to JSON when ajax is requested.');
}
}
......@@ -2,7 +2,7 @@
/**
* @file
* Definition of Drupal\jsonld\Tests\SerializationTest.
* Definition of Drupal\system\Tests\Serialization\SerializationTest.
*/
namespace Drupal\system\Tests\Serialization;
......
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