Skip to content
This repository
Browse code

Add the serializer service

  • Loading branch information...
commit b4e4844235563eb078212b8ecc4981cde30141ec 1 parent bd53382
Javier Lopez authored January 20, 2013
1  src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Source Rendered
@@ -4,6 +4,7 @@ CHANGELOG
4 4
 2.3.0
5 5
 -----
6 6
 
  7
+ * added possibility to load the serializer component in the service container
7 8
  * added route debug information when using the `router:match` command
8 9
  * added `TimedPhpEngine`
9 10
  * added `--clean` option the the `translation:update` command
62  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php
... ...
@@ -0,0 +1,62 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
  13
+
  14
+use Symfony\Component\DependencyInjection\ContainerBuilder;
  15
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  16
+use Symfony\Component\DependencyInjection\Reference;
  17
+
  18
+/**
  19
+ * Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
  20
+ * encoders and normalizers to the Serializer service.
  21
+ *
  22
+ * @author Javier Lopez <f12loalf@gmail.com>
  23
+ */
  24
+class SerializerPass implements CompilerPassInterface
  25
+{
  26
+    public function process(ContainerBuilder $container)
  27
+    {
  28
+        if (!$container->hasDefinition('serializer')) {
  29
+            return;
  30
+        }
  31
+
  32
+        // Looks for all the services tagged "serializer.normalizer" and adds them to the Serializer service
  33
+        $normalizers = $this->findAndSortTaggedServices('serializer.normalizer', $container);
  34
+        $container->getDefinition('serializer')->replaceArgument(0, $normalizers);
  35
+
  36
+        // Looks for all the services tagged "serializer.encoders" and adds them to the Serializer service
  37
+        $encoders = $this->findAndSortTaggedServices('serializer.encoder', $container);
  38
+        $container->getDefinition('serializer')->replaceArgument(1, $encoders);
  39
+    }
  40
+
  41
+    private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
  42
+    {
  43
+        $services = $container->findTaggedServiceIds($tagName);
  44
+        
  45
+        if (empty($services)) {
  46
+            throw new \RuntimeException(sprintf('You must tag at least one service as "%s" to use the Serializer service', $tagName));    
  47
+        }
  48
+        
  49
+        $sortedServices = array();
  50
+        foreach ($services as $serviceId => $tags) {
  51
+            foreach ($tags as $tag) {
  52
+                $priority = isset($tag['priority']) ? $tag['priority'] : 0;
  53
+                $sortedServices[$priority][] = new Reference($serviceId);
  54
+            }
  55
+        }
  56
+
  57
+        krsort($sortedServices);
  58
+
  59
+        // Flatten the array
  60
+        return call_user_func_array('array_merge', $sortedServices);
  61
+    }
  62
+}
13  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -67,6 +67,7 @@ public function getConfigTreeBuilder()
67 67
         $this->addTranslatorSection($rootNode);
68 68
         $this->addValidationSection($rootNode);
69 69
         $this->addAnnotationsSection($rootNode);
  70
+        $this->addSerializerSection($rootNode);
70 71
 
71 72
         return $treeBuilder;
72 73
     }
@@ -382,4 +383,16 @@ private function addAnnotationsSection(ArrayNodeDefinition $rootNode)
382 383
             ->end()
383 384
         ;
384 385
     }
  386
+
  387
+    private function addSerializerSection(ArrayNodeDefinition $rootNode)
  388
+    {
  389
+        $rootNode
  390
+            ->children()
  391
+                ->arrayNode('serializer')
  392
+                    ->info('serializer configuration')
  393
+                    ->canBeEnabled()
  394
+                ->end()
  395
+            ->end()
  396
+        ;
  397
+    }
385 398
 }
4  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -100,6 +100,10 @@ public function load(array $configs, ContainerBuilder $container)
100 100
 
101 101
         $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);
102 102
 
  103
+        if (isset($config['serializer']) && $config['serializer']['enabled']) {
  104
+            $loader->load('serializer.xml');
  105
+        }
  106
+
103 107
         $this->addClassesToCompile(array(
104 108
             'Symfony\\Component\\HttpFoundation\\ParameterBag',
105 109
             'Symfony\\Component\\HttpFoundation\\HeaderBag',
2  src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -26,6 +26,7 @@
26 26
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
27 27
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
28 28
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FragmentRendererPass;
  29
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
29 30
 use Symfony\Component\DependencyInjection\ContainerBuilder;
30 31
 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
31 32
 use Symfony\Component\HttpFoundation\Request;
@@ -66,6 +67,7 @@ public function build(ContainerBuilder $container)
66 67
         $container->addCompilerPass(new TranslationExtractorPass());
67 68
         $container->addCompilerPass(new TranslationDumperPass());
68 69
         $container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
  70
+        $container->addCompilerPass(new SerializerPass());
69 71
 
70 72
         if ($container->getParameter('kernel.debug')) {
71 73
             $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
26  src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
... ...
@@ -0,0 +1,26 @@
  1
+<?xml version="1.0" ?>
  2
+
  3
+<container xmlns="http://symfony.com/schema/dic/services"
  4
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5
+    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  6
+
  7
+    <parameters>
  8
+        <parameter key="serializer.class">Symfony\Component\Serializer\Serializer</parameter>
  9
+        <parameter key="serializer.encoder.xml.class">Symfony\Component\Serializer\Encoder\XmlEncoder</parameter>
  10
+        <parameter key="serializer.encoder.json.class">Symfony\Component\Serializer\Encoder\JsonEncoder</parameter>
  11
+    </parameters>
  12
+
  13
+    <services>
  14
+        <service id="serializer" class="%serializer.class%" >
  15
+            <argument type="collection" />
  16
+            <argument type="collection" />
  17
+        </service>
  18
+        <!-- Encoders -->
  19
+        <service id="serializer.encoder.xml" class="%serializer.encoder.xml.class%" public="false" >
  20
+            <tag name="serializer.encoder" />
  21
+        </service>
  22
+        <service id="serializer.encoder.json" class="%serializer.encoder.json.class%" public="false" >
  23
+            <tag name="serializer.encoder" />
  24
+        </service>
  25
+    </services>
  26
+</container>
105  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php
... ...
@@ -0,0 +1,105 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
  13
+
  14
+use Symfony\Component\DependencyInjection\ContainerBuilder;
  15
+use Symfony\Component\DependencyInjection\Reference;
  16
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
  17
+
  18
+/**
  19
+ * Tests for the SerializerPass class
  20
+ * 
  21
+ * @author Javier Lopez <f12loalf@gmail.com>
  22
+ */
  23
+class SerializerPassTest extends \PHPUnit_Framework_TestCase
  24
+{
  25
+
  26
+    public function testThrowExceptionWhenNoNormalizers()
  27
+    {
  28
+        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
  29
+        
  30
+        $container->expects($this->once())
  31
+            ->method('hasDefinition')
  32
+            ->with('serializer')
  33
+            ->will($this->returnValue(true));
  34
+                
  35
+        $container->expects($this->once())
  36
+            ->method('findTaggedServiceIds')
  37
+            ->with('serializer.normalizer')
  38
+            ->will($this->returnValue(array()));
  39
+        
  40
+        $this->setExpectedException('RuntimeException');
  41
+        
  42
+        $serializerPass = new SerializerPass();
  43
+        $serializerPass->process($container);
  44
+    }
  45
+    
  46
+    public function testThrowExceptionWhenNoEncoders()
  47
+    {
  48
+        $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
  49
+        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
  50
+        
  51
+        $container->expects($this->once())
  52
+            ->method('hasDefinition')
  53
+            ->with('serializer')
  54
+            ->will($this->returnValue(true));
  55
+        
  56
+        $container->expects($this->any())
  57
+            ->method('findTaggedServiceIds')
  58
+            ->will($this->onConsecutiveCalls(
  59
+                    array('n' => array('serializer.normalizer')),
  60
+                    array()
  61
+              ));
  62
+        
  63
+        $container->expects($this->once())
  64
+            ->method('getDefinition')
  65
+            ->will($this->returnValue($definition));
  66
+        
  67
+        $this->setExpectedException('RuntimeException');
  68
+        
  69
+        $serializerPass = new SerializerPass();
  70
+        $serializerPass->process($container);
  71
+    }
  72
+    
  73
+    public function testServicesAreOrderedAccordingToPriority()
  74
+    {
  75
+       $services = array(
  76
+            'n3' => array('tag' => array()),
  77
+            'n1' => array('tag' => array('priority' => 200)),
  78
+            'n2' => array('tag' => array('priority' => 100))
  79
+        );
  80
+       
  81
+       $expected = array(
  82
+           new Reference('n1'),
  83
+           new Reference('n2'),
  84
+           new Reference('n3')
  85
+       );
  86
+
  87
+        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
  88
+
  89
+        $container->expects($this->atLeastOnce())
  90
+            ->method('findTaggedServiceIds')
  91
+            ->will($this->returnValue($services));
  92
+
  93
+        $serializerPass = new SerializerPass();
  94
+        
  95
+        $method = new \ReflectionMethod(
  96
+          'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass', 
  97
+          'findAndSortTaggedServices'
  98
+        );
  99
+        $method->setAccessible(TRUE);
  100
+        
  101
+        $actual = $method->invoke($serializerPass, 'tag', $container);
  102
+        
  103
+        $this->assertEquals($expected, $actual);
  104
+    }
  105
+}
3  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
@@ -124,6 +124,9 @@ protected static function getBundleDefaultConfig()
124 124
                 'file_cache_dir' => '%kernel.cache_dir%/annotations',
125 125
                 'debug'          => '%kernel.debug%',
126 126
             ),
  127
+            'serializer'          => array(
  128
+                'enabled' => false           
  129
+            )
127 130
         );
128 131
     }
129 132
 }

0 notes on commit b4e4844

Please sign in to comment.
Something went wrong with that request. Please try again.