Переглянути джерело

removed a circular reference in the definition of the templating and Twig services

 * added a new TemplateNameConverter that parses a template name
 * removed the dependency between the Twig loader and the Templating engine
Fabien Potencier 14 роки тому
батько
коміт
911dbe9cc4

+ 5 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml

@@ -21,6 +21,7 @@
         <parameter key="templating.helper.form.class">Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper</parameter>
         <parameter key="templating.assets.version">null</parameter>
         <parameter key="templating.assets.base_urls" type="collection"></parameter>
+        <parameter key="templating.name_converter.class">Symfony\Bundle\FrameworkBundle\Templating\TemplateNameConverter</parameter>
         <parameter key="debug.file_link_format">null</parameter>
     </parameters>
 
@@ -99,6 +100,10 @@
             <argument type="service" id="templating" />
         </service>
 
+        <service id="templating.name_converter" class="%templating.name_converter.class%">
+            <argument type="service" id="service_container" />
+        </service>
+
         <service id="templating.loader" alias="templating.loader.filesystem" />
 
         <service id="templating" alias="templating.engine" />

+ 4 - 37
src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php

@@ -91,44 +91,11 @@ class Engine extends BaseEngine
         $this->helpers = $helpers;
     }
 
-    // parses template names following the following pattern:
-    // bundle:section:template(.format).renderer
+    /**
+     * {@inheritdoc}
+     */
     public function splitTemplateName($name, array $defaults = array())
     {
-        $parts = explode(':', $name);
-        if (3 !== count($parts)) {
-            throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
-        }
-
-        $options = array_replace(
-            array(
-                'format' => '',
-            ),
-            $defaults,
-            array(
-                'bundle'     => str_replace('\\', '/', $parts[0]),
-                'controller' => $parts[1],
-            )
-        );
-
-        $elements = explode('.', $parts[2]);
-        if (3 === count($elements)) {
-            $parts[2] = $elements[0];
-            if ('html' !== $elements[1]) {
-                $options['format'] = '.'.$elements[1];
-            }
-            $options['renderer'] = $elements[2];
-        } elseif (2 === count($elements)) {
-            $parts[2] = $elements[0];
-            $options['renderer'] = $elements[1];
-            $format = $this->container->get('request')->getRequestFormat();
-            if (null !== $format && 'html' !== $format) {
-                $options['format'] = '.'.$format;
-            }
-        } else {
-            throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
-        }
-
-        return array($parts[2], $options);
+        return $this->container->get('templating.name_converter')->fromShortNotation($name, $defaults);
     }
 }

+ 83 - 0
src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameConverter.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace Symfony\Bundle\FrameworkBundle\Templating;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * TemplateNameConverter converts template name from the short notation
+ * "bundle:section:template(.format).renderer" to a template name
+ * and an array of options.
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class TemplateNameConverter
+{
+    protected $container;
+
+    /**
+     * Constructor.
+     *
+     * @param ContainerInterface $container The DI container
+     */
+    public function __construct(ContainerInterface $container)
+    {
+        $this->container = $container;
+    }
+
+    /**
+     * Converts a short template notation to a template name and an array of options.
+     *
+     * @param string $name     A short template template
+     * @param array  $defaults An array of default options
+     *
+     * @return array An array composed of the template name and an array of options
+     */
+    public function fromShortNotation($name, array $defaults = array())
+    {
+        $parts = explode(':', $name);
+        if (3 !== count($parts)) {
+            throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
+        }
+
+        $options = array_replace(
+            array(
+                'format' => '',
+            ),
+            $defaults,
+            array(
+                'bundle'     => str_replace('\\', '/', $parts[0]),
+                'controller' => $parts[1],
+            )
+        );
+
+        $elements = explode('.', $parts[2]);
+        if (3 === count($elements)) {
+            $parts[2] = $elements[0];
+            if ('html' !== $elements[1]) {
+                $options['format'] = '.'.$elements[1];
+            }
+            $options['renderer'] = $elements[2];
+        } elseif (2 === count($elements)) {
+            $parts[2] = $elements[0];
+            $options['renderer'] = $elements[1];
+            $format = $this->container->get('request')->getRequestFormat();
+            if (null !== $format && 'html' !== $format) {
+                $options['format'] = '.'.$format;
+            }
+        } else {
+            throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
+        }
+
+        return array($parts[2], $options);
+    }
+}

+ 12 - 21
src/Symfony/Bundle/FrameworkBundle/Tests/Templating/EngineTest.php

@@ -12,30 +12,21 @@
 namespace Symfony\Bundle\FrameworkBundle\Tests\Templating;
 
 use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
-use Symfony\Bundle\FrameworkBundle\Templating\Engine;
-use Symfony\Component\Templating\Storage\StringStorage;
-use Symfony\Component\Templating\Storage\Storage;
-use Symfony\Component\Templating\Renderer\PhpRenderer;
+use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameConverter;
 
-// simulate the rendering of another controller
-function foo($engine)
-{
-    return $engine->render('FooBundle:Foo:tpl1.php', array('foo' => 'foo <br />'));
-}
-
-class EngineTest extends TestCase
+class TemplateNameConverterTest extends TestCase
 {
     /**
-     * @dataProvider getSplitTemplateNameTests
+     * @dataProvider getFromShortNotationTests
      */
-    public function testSplitTemplateName($name, $parameters)
+    public function testFromShortNotation($name, $parameters)
     {
-        $engine = new Engine($this->getContainerMock(), $this->getLoaderMock(), array());
+        $converter = new TemplateNameConverter($this->getContainerMock(), $this->getLoaderMock(), array());
 
-        $this->assertEquals($parameters, $engine->splitTemplateName($name));
+        $this->assertEquals($parameters, $converter->fromShortNotation($name));
     }
 
-    public function getSplitTemplateNameTests()
+    public function getFromShortNotationTests()
     {
         return array(
             array('BlogBundle:Post:index.php', array('index', array('bundle' => 'BlogBundle', 'controller' => 'Post', 'renderer' => 'php', 'format' => ''))),
@@ -45,17 +36,17 @@ class EngineTest extends TestCase
     }
 
     /**
-     * @dataProvider      getSplitTemplateNameInvalidTests
+     * @dataProvider      getFromShortNotationInvalidTests
      * @expectedException \InvalidArgumentException
      */
-    public function testSplitTemplateNameInvalid($name)
+    public function testFromShortNotationInvalid($name)
     {
-        $engine = new Engine($this->getContainerMock(), $this->getLoaderMock(), array());
+        $converter = new TemplateNameConverter($this->getContainerMock(), $this->getLoaderMock(), array());
 
-        $engine->splitTemplateName($name);
+        $converter->fromShortNotation($name);
     }
 
-    public function getSplitTemplateNameInvalidTests()
+    public function getFromShortNotationInvalidTests()
     {
         return array(
             array('BlogBundle:Post:index'),

+ 12 - 9
src/Symfony/Bundle/TwigBundle/Loader/Loader.php

@@ -2,9 +2,10 @@
 
 namespace Symfony\Bundle\TwigBundle\Loader;
 
-use Symfony\Component\Templating\Engine;
 use Symfony\Component\Templating\Storage\Storage;
 use Symfony\Component\Templating\Storage\FileStorage;
+use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameConverter;
+use Symfony\Component\Templating\Loader\LoaderInterface;
 
 /*
  * This file is part of the Symfony package.
@@ -21,11 +22,13 @@ use Symfony\Component\Templating\Storage\FileStorage;
  */
 class Loader implements \Twig_LoaderInterface
 {
-    protected $engine;
+    protected $converter;
+    protected $loader;
 
-    public function setEngine(Engine $engine)
+    public function __construct(TemplateNameConverter $converter, LoaderInterface $loader)
     {
-        $this->engine = $engine;
+        $this->converter = $converter;
+        $this->loader = $loader;
     }
 
     /**
@@ -41,13 +44,13 @@ class Loader implements \Twig_LoaderInterface
             return $name->getContent();
         }
 
-        list($name, $options) = $this->engine->splitTemplateName($name);
+        list($name, $options) = $this->converter->fromShortNotation($name);
 
         if ('twig' !== $options['renderer']) {
             throw new \LogicException(sprintf('A "%s" template cannot extend a "Twig" template.', $options['renderer']));
         }
 
-        $template = $this->engine->getLoader()->load($name, $options);
+        $template = $this->loader->load($name, $options);
 
         if (false === $template) {
             throw new \InvalidArgumentException(sprintf('The template "%s" does not exist (renderer: %s).', $name, $options['renderer']));
@@ -69,7 +72,7 @@ class Loader implements \Twig_LoaderInterface
             return (string) $name;
         }
 
-        list($name, $options) = $this->engine->splitTemplateName($name);
+        list($name, $options) = $this->converter->fromShortNotation($name);
 
         return $name.'_'.serialize($options);
     }
@@ -90,8 +93,8 @@ class Loader implements \Twig_LoaderInterface
             return false;
         }
 
-        list($name, $options) = $this->engine->splitTemplateName($name);
+        list($name, $options) = $this->converter->fromShortNotation($name);
 
-        return $this->engine->getLoader()->isFresh($name, $options, $time);
+        return $this->loader->isFresh($name, $options, $time);
     }
 }

+ 2 - 3
src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml

@@ -25,9 +25,8 @@
         </service>
 
         <service id="twig.loader" class="%twig.loader.class%">
-            <call method="setEngine">
-                <argument type="service" id="templating" />
-            </call>
+            <argument type="service" id="templating.name_converter" />
+            <argument type="service" id="templating.loader" />
         </service>
 
         <service id="twig.renderer" class="%twig.renderer.class%">

+ 8 - 0
src/Symfony/Component/Templating/Engine.php

@@ -363,6 +363,14 @@ class Engine implements \ArrayAccess
         $renderer->setEngine($this);
     }
 
+    /**
+     * Converts a short template notation to a template name and an array of options.
+     *
+     * @param string $name     A short template template
+     * @param array  $defaults An array of default options
+     *
+     * @return array An array composed of the template name and an array of options
+     */
     public function splitTemplateName($name)
     {
         if (false !== $pos = strpos($name, ':')) {