Skip to content

Commit

Permalink
Add the serializer service
Browse files Browse the repository at this point in the history
  • Loading branch information
humandb committed Mar 23, 2013
1 parent bd53382 commit b4e4844
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
2.3.0
-----

* added possibility to load the serializer component in the service container
* added route debug information when using the `router:match` command
* added `TimedPhpEngine`
* added `--clean` option the the `translation:update` command
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

/**
* Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
* encoders and normalizers to the Serializer service.
*
* @author Javier Lopez <f12loalf@gmail.com>
*/
class SerializerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('serializer')) {

This comment has been minimized.

Copy link
@schmittjoh

schmittjoh Nov 25, 2014

Contributor

You might want to check for the actual class of that service as someone might define his own serializer service, and not use the Symfony component.

As a workaround something like this is currently necessary:

services:
    serializer: @my_serializer
    my_serializer:
        public: false
        class: SomeClass
return;
}

// Looks for all the services tagged "serializer.normalizer" and adds them to the Serializer service
$normalizers = $this->findAndSortTaggedServices('serializer.normalizer', $container);
$container->getDefinition('serializer')->replaceArgument(0, $normalizers);

// Looks for all the services tagged "serializer.encoders" and adds them to the Serializer service
$encoders = $this->findAndSortTaggedServices('serializer.encoder', $container);
$container->getDefinition('serializer')->replaceArgument(1, $encoders);
}

private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
{
$services = $container->findTaggedServiceIds($tagName);

if (empty($services)) {
throw new \RuntimeException(sprintf('You must tag at least one service as "%s" to use the Serializer service', $tagName));
}

$sortedServices = array();
foreach ($services as $serviceId => $tags) {
foreach ($tags as $tag) {
$priority = isset($tag['priority']) ? $tag['priority'] : 0;
$sortedServices[$priority][] = new Reference($serviceId);

This comment has been minimized.

Copy link
@Taluu

Taluu Nov 25, 2014

Contributor

You should check if $sortedServices[$priority] is set (otherwise you may trigger a notice)

This comment has been minimized.

Copy link
@stof

stof Jan 3, 2015

Member

no it won't. This is a write context, not a read one. So there is no notice.

}
}

krsort($sortedServices);

// Flatten the array
return call_user_func_array('array_merge', $sortedServices);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public function getConfigTreeBuilder()
$this->addTranslatorSection($rootNode);
$this->addValidationSection($rootNode);
$this->addAnnotationsSection($rootNode);
$this->addSerializerSection($rootNode);

return $treeBuilder;
}
Expand Down Expand Up @@ -382,4 +383,16 @@ private function addAnnotationsSection(ArrayNodeDefinition $rootNode)
->end()
;
}

private function addSerializerSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('serializer')
->info('serializer configuration')
->canBeEnabled()
->end()
->end()
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ public function load(array $configs, ContainerBuilder $container)

$this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);

if (isset($config['serializer']) && $config['serializer']['enabled']) {
$loader->load('serializer.xml');
}

$this->addClassesToCompile(array(
'Symfony\\Component\\HttpFoundation\\ParameterBag',
'Symfony\\Component\\HttpFoundation\\HeaderBag',
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FragmentRendererPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -66,6 +67,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new TranslationExtractorPass());
$container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new SerializerPass());

if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
Expand Down
26 changes: 26 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<parameters>
<parameter key="serializer.class">Symfony\Component\Serializer\Serializer</parameter>
<parameter key="serializer.encoder.xml.class">Symfony\Component\Serializer\Encoder\XmlEncoder</parameter>
<parameter key="serializer.encoder.json.class">Symfony\Component\Serializer\Encoder\JsonEncoder</parameter>
</parameters>

<services>
<service id="serializer" class="%serializer.class%" >
<argument type="collection" />
<argument type="collection" />
</service>
<!-- Encoders -->
<service id="serializer.encoder.xml" class="%serializer.encoder.xml.class%" public="false" >
<tag name="serializer.encoder" />
</service>
<service id="serializer.encoder.json" class="%serializer.encoder.json.class%" public="false" >
<tag name="serializer.encoder" />
</service>
</services>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;

/**
* Tests for the SerializerPass class
*
* @author Javier Lopez <f12loalf@gmail.com>
*/
class SerializerPassTest extends \PHPUnit_Framework_TestCase
{

public function testThrowExceptionWhenNoNormalizers()
{
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');

$container->expects($this->once())
->method('hasDefinition')
->with('serializer')
->will($this->returnValue(true));

$container->expects($this->once())
->method('findTaggedServiceIds')
->with('serializer.normalizer')
->will($this->returnValue(array()));

$this->setExpectedException('RuntimeException');

$serializerPass = new SerializerPass();
$serializerPass->process($container);
}

public function testThrowExceptionWhenNoEncoders()
{
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');

$container->expects($this->once())
->method('hasDefinition')
->with('serializer')
->will($this->returnValue(true));

$container->expects($this->any())
->method('findTaggedServiceIds')
->will($this->onConsecutiveCalls(
array('n' => array('serializer.normalizer')),
array()
));

$container->expects($this->once())
->method('getDefinition')
->will($this->returnValue($definition));

$this->setExpectedException('RuntimeException');

$serializerPass = new SerializerPass();
$serializerPass->process($container);
}

public function testServicesAreOrderedAccordingToPriority()
{
$services = array(
'n3' => array('tag' => array()),
'n1' => array('tag' => array('priority' => 200)),
'n2' => array('tag' => array('priority' => 100))
);

$expected = array(
new Reference('n1'),
new Reference('n2'),
new Reference('n3')
);

$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');

$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
->will($this->returnValue($services));

$serializerPass = new SerializerPass();

$method = new \ReflectionMethod(
'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass',
'findAndSortTaggedServices'
);
$method->setAccessible(TRUE);

$actual = $method->invoke($serializerPass, 'tag', $container);

$this->assertEquals($expected, $actual);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ protected static function getBundleDefaultConfig()
'file_cache_dir' => '%kernel.cache_dir%/annotations',
'debug' => '%kernel.debug%',
),
'serializer' => array(
'enabled' => false
)
);
}
}

0 comments on commit b4e4844

Please sign in to comment.