Browse Source

[Form] Added fallback templates to TwigThemeFactory

Bernhard Schussek 14 years ago
parent
commit
2faa47d03b

+ 1 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml

@@ -48,6 +48,7 @@
         <!-- Themes -->
         <service id="form.theme.factory.twig" class="%form.theme.factory.twig.class%">
             <argument type="service" id="twig" />
+            <argument>%form.theme.template%</argument>
         </service>
 
         <service id="form.theme.factory.default" class="%form.theme.factory.php.class%">

+ 22 - 3
src/Symfony/Component/Form/Renderer/Theme/TwigTheme.php

@@ -23,8 +23,25 @@ class TwigTheme implements FormThemeInterface
 
     public function __construct(\Twig_Environment $environment, $templates)
     {
+        if (empty($templates)) {
+            $templates = array();
+        } else if (!is_array($templates)) {
+            // Don't use type casting, because then objects (Twig_Template)
+            // are converted to arrays
+            $templates = array($templates);
+        }
+
         $this->environment = $environment;
-        $this->templates = (array)$templates;
+        $this->templates = array();
+
+        foreach ($templates as $template) {
+            // Remove duplicate template names
+            if (!is_string($template)) {
+                $this->templates[] = $template;
+            } else if (!isset($this->templates[$template])) {
+                $this->templates[$template] = $template;
+            }
+        }
     }
 
     private function initialize()
@@ -32,8 +49,10 @@ class TwigTheme implements FormThemeInterface
         if (!$this->templatesByBlock) {
             $this->templatesByBlock = array();
 
-            foreach ($this->templates as $template) {
-                $template = $this->environment->loadTemplate($template);
+            foreach ($this->templates as $key => $template) {
+                if (!$template instanceof \Twig_Template) {
+                    $this->templates[$key] = $template = $this->environment->loadTemplate($template);
+                }
 
                 foreach ($this->getBlockNames($template) as $blockName) {
                     $this->templatesByBlock[$blockName] = $template;

+ 23 - 2
src/Symfony/Component/Form/Renderer/Theme/TwigThemeFactory.php

@@ -12,6 +12,7 @@
 namespace Symfony\Component\Form\Renderer\Theme;
 
 use Symfony\Component\Form\Exception\FormException;
+use Symfony\Component\Form\Exception\UnexpectedTypeException;
 
 /**
  * Creates TwigTheme instances
@@ -25,9 +26,23 @@ class TwigThemeFactory implements FormThemeFactoryInterface
      */
     private $environment;
 
-    public function __construct(\Twig_Environment $environment)
+    /**
+     * @var array
+     */
+    private $fallbackTemplates;
+
+    public function __construct(\Twig_Environment $environment, $fallbackTemplates = null)
     {
+        if (empty($fallbackTemplates)) {
+            $fallbackTemplates = array();
+        } else if (!is_array($fallbackTemplates)) {
+            // Don't use type casting, because then objects (Twig_Template)
+            // are converted to arrays
+            $fallbackTemplates = array($fallbackTemplates);
+        }
+
         $this->environment = $environment;
+        $this->fallbackTemplates = $fallbackTemplates;
     }
 
     /**
@@ -39,6 +54,12 @@ class TwigThemeFactory implements FormThemeFactoryInterface
             throw new FormException('Twig themes expect a template');
         }
 
-        return new TwigTheme($this->environment, $template);
+        if (!is_string($template) && !$template instanceof \Twig_Template) {
+            throw new UnexpectedTypeException($template, 'string or Twig_Template');
+        }
+
+        $templates = array_merge($this->fallbackTemplates, array($template));
+
+        return new TwigTheme($this->environment, $templates);
     }
 }

+ 33 - 3
tests/Symfony/Tests/Component/Form/Renderer/Theme/TwigThemeFactoryTest.php

@@ -11,25 +11,47 @@
 
 namespace Symfony\Tests\Component\Form\Renderer\Theme;
 
+use Symfony\Component\Form\Renderer\Theme\TwigTheme;
 use Symfony\Component\Form\Renderer\Theme\TwigThemeFactory;
 
 class TwigThemeFactoryTest extends \PHPUnit_Framework_TestCase
 {
+    private $environment;
+
     private $factory;
 
     protected function setUp()
     {
-        $environment = $this->getMockBuilder('Twig_Environment')
+        $this->environment = $this->getMockBuilder('Twig_Environment')
             ->disableOriginalConstructor()
             ->getMock();
-        $this->factory = new TwigThemeFactory($environment);
+        $this->factory = new TwigThemeFactory($this->environment);
     }
 
     public function testCreate()
     {
         $theme = $this->factory->create('template');
 
-        $this->assertInstanceOf('Symfony\Component\Form\Renderer\Theme\TwigTheme', $theme);
+        $this->assertEquals(new TwigTheme($this->environment, 'template'), $theme);
+    }
+
+    public function testCreateWithTwigTemplate()
+    {
+        $template = $this->getMockBuilder('Twig_Template')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $theme = $this->factory->create($template);
+
+        $this->assertEquals(new TwigTheme($this->environment, $template), $theme);
+    }
+
+    public function testCreateWithFallbacks()
+    {
+        $this->factory = new TwigThemeFactory($this->environment, 'fallback');
+
+        $theme = $this->factory->create('template');
+
+        $this->assertEquals(new TwigTheme($this->environment, array('fallback', 'template')), $theme);
     }
 
     /**
@@ -39,4 +61,12 @@ class TwigThemeFactoryTest extends \PHPUnit_Framework_TestCase
     {
         $this->factory->create();
     }
+
+    /**
+     * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
+     */
+    public function testCreateRequiresStringOrTwigTemplate()
+    {
+        $this->factory->create(new \stdClass());
+    }
 }