Issue #1814864 by linclark, effulgentsia: Added Provide way to register serialization classes.

8.0.x
webchick 2012-11-06 01:18:39 -08:00
parent 876bcaeb5d
commit 99bef1de6c
8 changed files with 283 additions and 0 deletions

View File

@ -10,6 +10,7 @@ namespace Drupal\Core;
use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
use Drupal\Core\DependencyInjection\Compiler\RegisterMatchersPass;
use Drupal\Core\DependencyInjection\Compiler\RegisterNestedMatchersPass;
use Drupal\Core\DependencyInjection\Compiler\RegisterSerializationClassesPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@ -126,10 +127,17 @@ class CoreBundle extends Bundle
->setFactoryClass('Drupal\Core\ExceptionController')
->setFactoryMethod('getExceptionListener');
// Add Serializer with arguments to be replaced in the compiler pass.
$container->register('serializer', 'Symfony\Component\Serializer\Serializer')
->addArgument(array())
->addArgument(array());
$container->addCompilerPass(new RegisterMatchersPass());
$container->addCompilerPass(new RegisterNestedMatchersPass());
// Add a compiler pass for registering event subscribers.
$container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
// Add a compiler pass for adding Normalizers and Encoders to Serializer.
$container->addCompilerPass(new RegisterSerializationClassesPass());
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* @file
* Contains Drupal\serialization\RegisterSerializationClassesPass.
*/
namespace Drupal\Core\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
/**
* Adds services tagged 'normalizer' and 'encoder' to the Serializer.
*/
class RegisterSerializationClassesPass implements CompilerPassInterface {
/**
* Adds services to the Serializer.
*
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
* The container to process.
*/
public function process(ContainerBuilder $container) {
$definition = $container->getDefinition('serializer');
// Retrieve registered Normalizers and Encoders from the container.
foreach ($container->findTaggedServiceIds('normalizer') as $id => $attributes) {
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
$normalizers[$priority][] = new Reference($id);
}
foreach ($container->findTaggedServiceIds('encoder') as $id => $attributes) {
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
$encoders[$priority][] = new Reference($id);
}
// Add the registered Normalizers and Encoders to the Serializer.
if (!empty($normalizers)) {
$definition->replaceArgument(0, $this->sort($normalizers));
}
if (!empty($encoders)) {
$definition->replaceArgument(1, $this->sort($encoders));
}
}
/**
* Sorts by priority.
*
* Order services from highest priority number to lowest (reverse sorting).
*
* @param array $services
* A nested array keyed on priority number. For each priority number, the
* value is an array of Symfony\Component\DependencyInjection\Reference
* objects, each a reference to a normalizer or encoder service.
*
* @return array
* A flattened array of Reference objects from $services, ordered from high
* to low priority.
*/
protected function sort($services) {
$sorted = array();
krsort($services);
// Flatten the array.
foreach ($services as $a) {
$sorted = array_merge($sorted, $a);
}
return $sorted;
}
}

View File

@ -0,0 +1,61 @@
<?php
/**
* @file
* Definition of Drupal\jsonld\Tests\SerializationTest.
*/
namespace Drupal\system\Tests\Serialization;
use Drupal\simpletest\WebTestBase;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
class SerializationTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('serialization_test');
/**
* The serializer service to test.
*
* @var Symfony\Component\Serializer\SerializerInterface
*/
protected $serializer;
public static function getInfo() {
return array(
'name' => 'Serialization tests',
'description' => 'Funtional tests for serialization system.',
'group' => 'Serialization',
);
}
protected function setUp() {
parent::setUp();
$this->serializer = drupal_container()->get('serializer');
}
/**
* Confirms that modules can register normalizers and encoders.
*/
public function testSerializerComponentRegistration() {
$object = new \stdClass();
$format = 'serialization_test';
$expected = 'Normalized by SerializationTestNormalizer, Encoded by SerializationTestEncoder';
// Ensure the serialization invokes the expected normalizer and encoder.
$this->assertIdentical($this->serializer->serialize($object, $format), $expected);
// Ensure the serialization fails for an unsupported format.
try {
$this->serializer->serialize($object, 'unsupported_format');
$this->fail('The serializer was expected to throw an exception for an unsupported format, but did not.');
}
catch (UnexpectedValueException $e) {
}
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* @file
* Definition of Drupal\serialization_test\SerializationTestBundle.
*/
namespace Drupal\serialization_test;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\Serializer\Serializer;
/**
* SerializationTest dependency injection container.
*/
class SerializationTestBundle extends Bundle {
/**
* Overrides Symfony\Component\HttpKernel\Bundle\Bundle::build().
*/
public function build(ContainerBuilder $container) {
$container->register('serializer.normalizer.serialization_test', 'Drupal\serialization_test\SerializationTestNormalizer')->addTag('normalizer');
$container->register('serializer.encoder.serialization_test', 'Drupal\serialization_test\SerializationTestEncoder')->addTag('encoder');
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* @file
* Definition of Drupal\serialization_test\SerializationTestEncoder.
*/
namespace Drupal\serialization_test;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
class SerializationTestEncoder implements EncoderInterface {
/**
* The format that this Encoder supports.
*
* @var string
*/
static protected $format = 'serialization_test';
/**
* Encodes data into the requested format.
*
* @param mixed $data
* Data to encode.
* @param string $format
* Format name.
*
* @return string
* A string representation of $data in the requested format.
*/
public function encode($data, $format) {
// @see Drupal\serialization_test\SerializationTestNormalizer::normalize().
return 'Normalized by ' . $data['normalized_by'] . ', Encoded by SerializationTestEncoder';
}
/**
* Checks whether this encoder can encode to the requested format.
*
* @param string $format
* The short name of the format.
*
* @return bool
* Returns TRUE if this encoder can encode to the requested format.
*/
public function supportsEncoding($format) {
return static::$format === $format;
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* @file
* Definition of Drupal\serialization_test\SerializationTestNormalizer.
*/
namespace Drupal\serialization_test;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class SerializationTestNormalizer implements NormalizerInterface {
/**
* The format that this Normalizer supports.
*
* @var string
*/
static protected $format = 'serialization_test';
/**
* Normalizes an object into a set of arrays/scalars.
*
* @param object $object
* Object to normalize.
* @param string $format
* Format the normalization result will be encoded as.
*
* @return array
* An array containing a normalized representation of $object, appropriate
* for encoding to the requested format.
*/
public function normalize($object, $format = NULL) {
$normalized = (array) $object;
// Add identifying value that can be used to verify that the expected
// normalizer was invoked.
$normalized['normalized_by'] = 'SerializationTestNormalizer';
return $normalized;
}
/**
* Checks whether format is supported by this normalizer.
*
* @param mixed $data
* Data to normalize.
* @param string $format
* Format the normalization result will be encoded as.
*
* @return bool
* Returns TRUE if the normalizer can handle the request.
*/
public function supportsNormalization($data, $format = NULL) {
return static::$format === $format;
}
}

View File

@ -0,0 +1,5 @@
name = Serialization test module
description = "Support module for serialization tests."
package = Testing
core = 8.x
hidden = TRUE

View File

@ -0,0 +1,7 @@
<?php
/**
* @file
* Helper module for serialization tests. This file is empty, because all
* implementation is in autoloaded classes.
*/