Browse Source

[Form] Introduced renderer theme factories so that themes can be changed during runtime

Bernhard Schussek 14 năm trước cách đây
mục cha
commit
1211d77f49
19 tập tin đã thay đổi với 343 bổ sung57 xóa
  1. 3 3
      src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
  2. 2 4
      src/Symfony/Bundle/FrameworkBundle/Form/PhpEngineTheme.php
  3. 41 0
      src/Symfony/Bundle/FrameworkBundle/Form/PhpEngineThemeFactory.php
  4. 8 9
      src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
  5. 2 2
      src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
  6. 28 0
      src/Symfony/Bundle/FrameworkBundle/Tests/Form/PhpEngineThemeFactoryTest.php
  7. 3 3
      src/Symfony/Bundle/FrameworkBundle/Tests/Form/PhpEngineThemeFunctionalTest.php
  8. 9 8
      src/Symfony/Component/Form/DefaultFormFactory.php
  9. 17 0
      src/Symfony/Component/Form/Renderer/Theme/FormThemeFactoryInterface.php
  10. 44 0
      src/Symfony/Component/Form/Renderer/Theme/PhpThemeFactory.php
  11. 44 0
      src/Symfony/Component/Form/Renderer/Theme/TwigThemeFactory.php
  12. 27 8
      src/Symfony/Component/Form/Renderer/ThemeRenderer.php
  13. 12 6
      src/Symfony/Component/Form/Type/FieldType.php
  14. 5 5
      src/Symfony/Component/Form/Type/Loader/DefaultTypeLoader.php
  15. 8 3
      tests/Symfony/Tests/Component/Form/Renderer/Theme/AbstractThemeFunctionalTest.php
  16. 39 0
      tests/Symfony/Tests/Component/Form/Renderer/Theme/PhpThemeFactoryTest.php
  17. 3 3
      tests/Symfony/Tests/Component/Form/Renderer/Theme/PhpThemeFunctionalTest.php
  18. 42 0
      tests/Symfony/Tests/Component/Form/Renderer/Theme/TwigThemeFactoryTest.php
  19. 6 3
      tests/Symfony/Tests/Component/Form/Type/TestCase.php

+ 3 - 3
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

@@ -408,10 +408,10 @@ class FrameworkExtension extends Extension
             $container->setAlias('templating', 'templating.engine.delegating');
         }
 
-        $container->setAlias('form.theme', 'form.theme.default');
+        $container->setAlias('form.theme.factory', 'form.theme.factory.default');
         foreach ($config['engines'] as $engine) {
-            if ($container->hasDefinition('form.theme.' . $engine)) {
-                $container->setAlias('form.theme', 'form.theme.' . $engine);
+            if ($container->hasDefinition('form.theme.factory.' . $engine)) {
+                $container->setAlias('form.theme.factory', 'form.theme.factory.' . $engine);
             }
         }
     }

+ 2 - 4
src/Symfony/Bundle/FrameworkBundle/Form/PhpEngineTheme.php

@@ -11,10 +11,8 @@
 
 namespace Symfony\Bundle\FrameworkBundle\Form;
 
-use Symfony\Component\Form\Form;
-use Symfony\Component\Form\FieldInterface;
 use Symfony\Component\Form\Exception\FormException;
-use Symfony\Component\Form\Renderer\Theme\ThemeInterface;
+use Symfony\Component\Form\Renderer\Theme\FormThemeInterface;
 use Symfony\Component\Templating\PhpEngine;
 
 /**
@@ -24,7 +22,7 @@ use Symfony\Component\Templating\PhpEngine;
  *
  * @author Benjamin Eberlei <kontakt@beberlei.de>
  */
-class PhpEngineTheme implements ThemeInterface
+class PhpEngineTheme implements FormThemeInterface
 {
     /**
      * @var array

+ 41 - 0
src/Symfony/Bundle/FrameworkBundle/Form/PhpEngineThemeFactory.php

@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * 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.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Form;
+
+use Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface;
+use Symfony\Component\Templating\PhpEngine;
+
+/**
+ * Constructs PhpEngineTheme instances
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class PhpEngineThemeFactory implements FormThemeFactoryInterface
+{
+    /**
+     * @var PhpEngine
+     */
+    private $engine;
+
+    public function __construct(PhpEngine $engine)
+    {
+        $this->engine = $engine;
+    }
+
+    /**
+     * @see Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface::create()
+     */
+    public function create($template = null)
+    {
+        return new PhpEngineTheme($this->engine, $template);
+    }
+}

+ 8 - 9
src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml

@@ -11,9 +11,9 @@
         <parameter key="form.type.loader.tagged.class">Symfony\Bundle\FrameworkBundle\Form\ContainerAwareTypeLoader</parameter>
         <parameter key="form.guesser.validator.class">Symfony\Component\Form\Type\Guesser\ValidatorTypeGuesser</parameter>
         <parameter key="form.csrf_provider.class">Symfony\Component\Form\CsrfProvider\SessionCsrfProvider</parameter>
-        <parameter key="form.theme.twig.class">Symfony\Component\Form\Renderer\Theme\TwigTheme</parameter>
-        <parameter key="form.theme.php.class">Symfony\Component\Form\Renderer\Theme\PhpTheme</parameter>
-        <parameter key="form.theme.phpengine.class">Symfony\Bundle\FrameworkBundle\Form\PhpEngineTheme</parameter>
+        <parameter key="form.theme.factory.twig.class">Symfony\Component\Form\Renderer\Theme\TwigThemeFactory</parameter>
+        <parameter key="form.theme.factory.php.class">Symfony\Component\Form\Renderer\Theme\PhpThemeFactory</parameter>
+        <parameter key="form.theme.factory.phpengine.class">Symfony\Bundle\FrameworkBundle\Form\PhpEngineThemeFactory</parameter>
         <parameter key="form.theme.template">TwigBundle::div_layout.html.twig</parameter>
         <parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
         <parameter key="form.csrf_protection.enabled">true</parameter>
@@ -46,18 +46,16 @@
         </service>
         
         <!-- Themes -->
-        <service id="form.theme.twig" class="%form.theme.twig.class%">
+        <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.default" class="%form.theme.php.class%">
+        <service id="form.theme.factory.default" class="%form.theme.factory.php.class%">
             <argument>%kernel.charset%</argument>
         </service>
 
-        <service id="form.theme.php" class="%form.theme.phpengine.class%">
+        <service id="form.theme.factory.php" class="%form.theme.factory.phpengine.class%">
             <argument type="service" id="templating.engine.php" />
-            <argument>%form.theme.template%</argument>
         </service>
         
         <!-- TemporaryStorage - where should we put this? -->
@@ -95,8 +93,9 @@
         <!-- FieldTypes -->
         <service id="form.type.field" class="Symfony\Component\Form\Type\FieldType">
             <tag name="form.type" alias="field" />
-            <argument type="service" id="form.theme" />
             <argument type="service" id="validator" />
+            <argument type="service" id="form.theme.factory" />
+            <argument>%form.theme.template%</argument>
         </service>
         <service id="form.type.form" class="Symfony\Component\Form\Type\FormType">
             <tag name="form.type" alias="form" />

+ 2 - 2
src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

@@ -61,8 +61,8 @@ abstract class FrameworkExtensionTest extends TestCase
     {
         $container = $this->createContainerFromFile('full');
 
-        $this->assertTrue($container->hasAlias('form.theme'), '->registerTemplatingConfiguration() aliases a form.theme service.');
-        $this->assertEquals('form.theme.twig', (string)$container->getAlias('form.theme'));
+        $this->assertTrue($container->hasAlias('form.theme.factory'), '->registerTemplatingConfiguration() aliases a form.theme.factory service.');
+        $this->assertEquals('form.theme.factory.twig', (string)$container->getAlias('form.theme.factory'));
     }
 
     /**

+ 28 - 0
src/Symfony/Bundle/FrameworkBundle/Tests/Form/PhpEngineThemeFactoryTest.php

@@ -0,0 +1,28 @@
+<?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\Form;
+
+use Symfony\Bundle\FrameworkBundle\Form\PhpEngineThemeFactory;
+
+class PhpEngineThemeFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    public function testCreate()
+    {
+        $engine = $this->getMockBuilder('Symfony\Component\Templating\PhpEngine')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $factory = new PhpEngineThemeFactory($engine);
+
+        $this->assertInstanceOf('Symfony\Bundle\FrameworkBundle\Form\PhpEngineTheme', $factory->create());
+    }
+}

+ 3 - 3
src/Symfony/Bundle/FrameworkBundle/Tests/Form/PhpEngineThemeFunctionalTest.php

@@ -12,7 +12,7 @@
 namespace Symfony\Bundle\FrameworkBundle\Tests\Form;
 
 use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
-use Symfony\Bundle\FrameworkBundle\Form\PhpEngineTheme;
+use Symfony\Bundle\FrameworkBundle\Form\PhpEngineThemeFactory;
 use Symfony\Component\Form\Type\AbstractFieldType;
 use Symfony\Component\Form\FieldBuilder;
 use Symfony\Component\Form\CsrfProvider\DefaultCsrfProvider;
@@ -25,7 +25,7 @@ use Symfony\Tests\Component\Form\Renderer\Theme\AbstractThemeFunctionalTest;
  */
 class PhpEngineThemeFunctionalTest extends AbstractThemeFunctionalTest
 {
-    protected function createTheme()
+    protected function createThemeFactory()
     {
         $parser = new \Symfony\Component\Templating\TemplateNameParser();
         $loader = new \Symfony\Component\Templating\Loader\FilesystemLoader(__DIR__ . '/../../Resources/views/Form/%name%');
@@ -37,6 +37,6 @@ class PhpEngineThemeFunctionalTest extends AbstractThemeFunctionalTest
                 )
             )
         ));
-        return new PhpEngineTheme($engine);
+        return new PhpEngineThemeFactory($engine);
     }
 }

+ 9 - 8
src/Symfony/Component/Form/DefaultFormFactory.php

@@ -16,10 +16,11 @@ use Symfony\Component\Validator\ValidatorInterface;
 use Symfony\Component\Form\FormFactoryInterface;
 use Symfony\Component\Form\Type;
 use Symfony\Component\Form\Type\FormTypeInterface;
-use Symfony\Component\Form\Renderer\Theme\FormThemeInterface;
+use Symfony\Component\Form\Type\AbstractFieldType;
 use Symfony\Component\Form\Type\Loader\TypeLoaderInterface;
 use Symfony\Component\Form\Type\Loader\DefaultTypeLoader;
-use Symfony\Component\Form\Type\AbstractFieldType;
+use Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface;
+use Symfony\Component\Form\Renderer\Theme\PhpThemeFactory;
 use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
 use Symfony\Component\Form\CsrfProvider\DefaultCsrfProvider;
 use Doctrine\ORM\EntityManager;
@@ -47,21 +48,21 @@ class DefaultFormFactory extends FormFactory
     {
         $csrfProvider = new DefaultCsrfProvider($csrfSecret);
         $tempStorage = new TemporaryStorage($storageSecret);
-        $defaultTheme = new PhpTheme($charset);
-        return self::createInstance($defaultTheme, $validator, $csrfProvider, $tempStorage, $entityManager);
+        $defaultThemeFactory = new PhpThemeFactory($charset);
+        return self::createInstance($defaultThemeFactory, $validator, $csrfProvider, $tempStorage, $entityManager);
     }
 
     /**
      * Factory method to simplify creation of a default form factory.
-     * 
-     * @param FormThemeInterface $theme
+     *
+     * @param FormThemeFactoryInterface $themeFactory
      * @param ValidatorInterface $validator
      * @param CsrfProviderInterface $crsfProvider
      * @param TemporaryStorage $tempStorage
      * @param \Doctrine\ORM\EntityManager $entityManager
      * @return DefaultFormFactory
      */
-    public static function createInstance(FormThemeInterface $theme,
+    public static function createInstance(FormThemeFactoryInterface $themeFactory,
             ValidatorInterface $validator,
             CsrfProviderInterface $crsfProvider,
             TemporaryStorage $tempStorage,
@@ -69,7 +70,7 @@ class DefaultFormFactory extends FormFactory
     {
         $typeLoader = new DefaultTypeLoader();
         $factory = new self($typeLoader);
-        $typeLoader->initialize($factory, $theme, $crsfProvider, $validator, $tempStorage, $entityManager);
+        $typeLoader->initialize($factory, $themeFactory, null, $crsfProvider, $validator, $tempStorage, $entityManager);
 
         return $factory;
     }

+ 17 - 0
src/Symfony/Component/Form/Renderer/Theme/FormThemeFactoryInterface.php

@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * 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.
+ */
+
+namespace Symfony\Component\Form\Renderer\Theme;
+
+interface FormThemeFactoryInterface
+{
+    function create($template = null);
+}

+ 44 - 0
src/Symfony/Component/Form/Renderer/Theme/PhpThemeFactory.php

@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * 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.
+ */
+
+namespace Symfony\Component\Form\Renderer\Theme;
+
+use Symfony\Component\Form\Exception\FormException;
+
+/**
+ * Creates PhpTheme instances
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class PhpThemeFactory implements FormThemeFactoryInterface
+{
+    /**
+     * @var string
+     */
+    private $charset;
+
+    public function __construct($charset = 'UTF-8')
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * @see Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface::create()
+     */
+    public function create($template = null)
+    {
+        if ($template !== null) {
+            throw new FormException('PHP don\'t accept templates');
+        }
+
+        return new PhpTheme($this->charset);
+    }
+}

+ 44 - 0
src/Symfony/Component/Form/Renderer/Theme/TwigThemeFactory.php

@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * 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.
+ */
+
+namespace Symfony\Component\Form\Renderer\Theme;
+
+use Symfony\Component\Form\Exception\FormException;
+
+/**
+ * Creates TwigTheme instances
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class TwigThemeFactory implements FormThemeFactoryInterface
+{
+    /**
+     * @var Twig_Environment
+     */
+    private $environment;
+
+    public function __construct(\Twig_Environment $environment)
+    {
+        $this->environment = $environment;
+    }
+
+    /**
+     * @see Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface::create()
+     */
+    public function create($template = null)
+    {
+        if ($template === null) {
+            throw new FormException('Twig themes expect a template');
+        }
+
+        return new TwigTheme($this->environment, $template);
+    }
+}

+ 27 - 8
src/Symfony/Component/Form/Renderer/ThemeRenderer.php

@@ -13,13 +13,16 @@ namespace Symfony\Component\Form\Renderer;
 
 use Symfony\Component\Form\FormInterface;
 use Symfony\Component\Form\Renderer\Theme\FormThemeInterface;
+use Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface;
 use Symfony\Component\Form\Renderer\Plugin\FormRendererPluginInterface;
 
 class ThemeRenderer implements FormRendererInterface, \ArrayAccess
 {
     private $form;
 
-    private $template;
+    private $block;
+
+    private $themeFactory;
 
     private $theme;
 
@@ -36,16 +39,17 @@ class ThemeRenderer implements FormRendererInterface, \ArrayAccess
      * Row implicitly includes widget, however certain rendering mechanisms
      * have to skip widget rendering when a row is rendered.
      *
-     * @var bool
+     * @var Boolean
      */
     private $rendered = false;
 
     private $children = array();
 
-    public function __construct(FormThemeInterface $theme, $template)
+    public function __construct(FormThemeFactoryInterface $themeFactory, $template = null)
     {
-        $this->theme = $theme;
-        $this->template = $template;
+        $this->themeFactory = $themeFactory;
+
+        $this->setTemplate($template);
     }
 
     public function __clone()
@@ -86,6 +90,11 @@ class ThemeRenderer implements FormRendererInterface, \ArrayAccess
         $this->children = $renderers;
     }
 
+    public function setTemplate($template)
+    {
+        $this->setTheme($this->themeFactory->create($template));
+    }
+
     public function setTheme(FormThemeInterface $theme)
     {
         $this->theme = $theme;
@@ -96,6 +105,16 @@ class ThemeRenderer implements FormRendererInterface, \ArrayAccess
         return $this->theme;
     }
 
+    public function setBlock($block)
+    {
+        $this->block = $block;
+    }
+
+    public function getBlock()
+    {
+        return $this->block;
+    }
+
     public function addPlugin(FormRendererPluginInterface $plugin)
     {
         $this->initialized = false;
@@ -162,7 +181,7 @@ class ThemeRenderer implements FormRendererInterface, \ArrayAccess
      * Renders the label of the given form
      *
      * @param FormInterface $form  The form to render the label for
-     * @param array $params          Additional variables passed to the template
+     * @param array $params          Additional variables passed to the block
      */
     public function getLabel($label = null, array $vars = array())
     {
@@ -178,11 +197,11 @@ class ThemeRenderer implements FormRendererInterface, \ArrayAccess
         return $this->render('enctype', $this->vars);
     }
 
-    protected function render($block, array $vars = array())
+    protected function render($part, array $vars = array())
     {
         $this->initialize();
 
-        return $this->theme->render($this->template, $block, array_replace(
+        return $this->theme->render($this->block, $part, array_replace(
             $this->vars,
             $vars
         ));

+ 12 - 6
src/Symfony/Component/Form/Type/FieldType.php

@@ -14,7 +14,7 @@ namespace Symfony\Component\Form\Type;
 use Symfony\Component\Form\PropertyPath;
 use Symfony\Component\Form\FormBuilder;
 use Symfony\Component\Form\Renderer\ThemeRenderer;
-use Symfony\Component\Form\Renderer\Theme\FormThemeInterface;
+use Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface;
 use Symfony\Component\Form\Renderer\Plugin\FieldPlugin;
 use Symfony\Component\Form\EventListener\TrimListener;
 use Symfony\Component\Form\EventListener\ValidationListener;
@@ -26,14 +26,17 @@ use Symfony\Component\Validator\ValidatorInterface;
 
 class FieldType extends AbstractType
 {
-    private $theme;
-
     private $validator;
 
-    public function __construct(FormThemeInterface $theme, ValidatorInterface $validator)
+    private $themeFactory;
+
+    private $template;
+
+    public function __construct(ValidatorInterface $validator, FormThemeFactoryInterface $themeFactory, $template = null)
     {
-        $this->theme = $theme;
         $this->validator = $validator;
+        $this->themeFactory = $themeFactory;
+        $this->template = $template;
     }
 
     public function configure(FormBuilder $builder, array $options)
@@ -52,6 +55,9 @@ class FieldType extends AbstractType
             ? null
             : (array)$options['validation_groups'];
 
+        $renderer = new ThemeRenderer($this->themeFactory, $this->template);
+        $renderer->setBlock($options['template']);
+
         $builder->setRequired($options['required'])
             ->setReadOnly($options['read_only'])
             ->setErrorBubbling($options['error_bubbling'])
@@ -60,7 +66,7 @@ class FieldType extends AbstractType
             ->setAttribute('validation_groups', $options['validation_groups'])
             ->setAttribute('error_mapping', $options['error_mapping'])
             ->setData($options['data'])
-            ->setRenderer(new ThemeRenderer($this->theme, $options['template']))
+            ->setRenderer($renderer)
             ->addRendererPlugin(new FieldPlugin())
             ->addValidator(new DefaultValidator())
             ->addValidator(new DelegatingValidator($this->validator));

+ 5 - 5
src/Symfony/Component/Form/Type/Loader/DefaultTypeLoader.php

@@ -14,7 +14,7 @@ namespace Symfony\Component\Form\Type\Loader;
 use Symfony\Component\Form\FormFactoryInterface;
 use Symfony\Component\Form\Type;
 use Symfony\Component\Form\Type\FormTypeInterface;
-use Symfony\Component\Form\Renderer\Theme\FormThemeInterface;
+use Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface;
 use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
 use Symfony\Component\Validator\ValidatorInterface;
 use Symfony\Component\HttpFoundation\File\TemporaryStorage;
@@ -25,11 +25,11 @@ class DefaultTypeLoader implements TypeLoaderInterface
     private $types = array();
 
     public function initialize(FormFactoryInterface $factory,
-            FormThemeInterface $theme, CsrfProviderInterface $csrfProvider,
-            ValidatorInterface $validator, TemporaryStorage $storage,
-            EntityManager $em = null)
+            FormThemeFactoryInterface $themeFactory, $template,
+            CsrfProviderInterface $csrfProvider, ValidatorInterface $validator,
+            TemporaryStorage $storage, EntityManager $em = null)
     {
-        $this->addType(new Type\FieldType($theme, $validator));
+        $this->addType(new Type\FieldType($validator, $themeFactory, $template));
         $this->addType(new Type\FormType());
         $this->addType(new Type\BirthdayType());
         $this->addType(new Type\CheckboxType());

+ 8 - 3
tests/Symfony/Tests/Component/Form/Renderer/Theme/AbstractThemeFunctionalTest.php

@@ -25,11 +25,16 @@ abstract class AbstractThemeFunctionalTest extends \PHPUnit_Framework_TestCase
     /** @var FormFactory */
     private $factory;
 
-    abstract protected function createTheme();
+    abstract protected function createThemeFactory();
+
+    protected function getTemplate()
+    {
+    }
 
     public function setUp()
     {
-        $theme = $this->createTheme();
+        $themeFactory = $this->createThemeFactory();
+        $template = $this->getTemplate();
         $csrfProvider = new DefaultCsrfProvider('foo');
         $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
         $storage = new \Symfony\Component\HttpFoundation\File\TemporaryStorage('foo', 1, \sys_get_temp_dir());
@@ -37,7 +42,7 @@ abstract class AbstractThemeFunctionalTest extends \PHPUnit_Framework_TestCase
         // ok more than 2 lines, see DefaultFormFactory.php for proposed simplication
         $typeLoader = new DefaultTypeLoader();
         $this->factory = new FormFactory($typeLoader);
-        $typeLoader->initialize($this->factory, $theme, $csrfProvider, $validator , $storage);
+        $typeLoader->initialize($this->factory, $themeFactory, $template, $csrfProvider, $validator , $storage);
         // this is the relevant bit about your own forms:
         $typeLoader->addType(new MyTestFormConfig());
         $typeLoader->addType(new MyTestSubFormConfig());

+ 39 - 0
tests/Symfony/Tests/Component/Form/Renderer/Theme/PhpThemeFactoryTest.php

@@ -0,0 +1,39 @@
+<?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\Tests\Component\Form\Renderer\Theme;
+
+use Symfony\Component\Form\Renderer\Theme\PhpThemeFactory;
+
+class PhpThemeFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    private $factory;
+
+    protected function setUp()
+    {
+        $this->factory = new PhpThemeFactory();
+    }
+
+    public function testCreate()
+    {
+        $theme = $this->factory->create();
+
+        $this->assertInstanceOf('Symfony\Component\Form\Renderer\Theme\PhpTheme', $theme);
+    }
+
+    /**
+     * @expectedException Symfony\Component\Form\Exception\FormException
+     */
+    public function testCreateDoesNotAcceptParams()
+    {
+        $this->factory->create('foobar');
+    }
+}

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

@@ -11,15 +11,15 @@
 
 namespace Symfony\Tests\Component\Form\Renderer\Theme;
 
-use Symfony\Component\Form\Renderer\Theme\PhpTheme;
+use Symfony\Component\Form\Renderer\Theme\PhpThemeFactory;
 
 /**
  * Test theme template files shipped with framework bundle.
  */
 class PhpThemeFunctionalTest extends AbstractThemeFunctionalTest
 {
-    protected function createTheme()
+    protected function createThemeFactory()
     {
-        return new PhpTheme();
+        return new PhpThemeFactory();
     }
 }

+ 42 - 0
tests/Symfony/Tests/Component/Form/Renderer/Theme/TwigThemeFactoryTest.php

@@ -0,0 +1,42 @@
+<?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\Tests\Component\Form\Renderer\Theme;
+
+use Symfony\Component\Form\Renderer\Theme\TwigThemeFactory;
+
+class TwigThemeFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    private $factory;
+
+    protected function setUp()
+    {
+        $environment = $this->getMockBuilder('Twig_Environment')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->factory = new TwigThemeFactory($environment);
+    }
+
+    public function testCreate()
+    {
+        $theme = $this->factory->create('template');
+
+        $this->assertInstanceOf('Symfony\Component\Form\Renderer\Theme\TwigTheme', $theme);
+    }
+
+    /**
+     * @expectedException Symfony\Component\Form\Exception\FormException
+     */
+    public function testCreateRequiresParams()
+    {
+        $this->factory->create();
+    }
+}

+ 6 - 3
tests/Symfony/Tests/Component/Form/Type/TestCase.php

@@ -18,7 +18,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
 
 abstract class TestCase extends \PHPUnit_Framework_TestCase
 {
-    protected $theme;
+    protected $themeFactory;
 
     protected $csrfProvider;
 
@@ -36,7 +36,10 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->theme = $this->getMock('Symfony\Component\Form\Renderer\Theme\FormThemeInterface');
+        $this->themeFactory = $this->getMock('Symfony\Component\Form\Renderer\Theme\FormThemeFactoryInterface');
+        $this->themeFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->getMock('Symfony\Component\Form\Renderer\Theme\FormThemeInterface')));
         $this->csrfProvider = $this->getMock('Symfony\Component\Form\CsrfProvider\CsrfProviderInterface');
         $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
         $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
@@ -49,7 +52,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
             ->getMock();
         $loader = new DefaultTypeLoader();
         $this->factory = new FormFactory($loader);
-        $loader->initialize($this->factory, $this->theme, $this->csrfProvider,
+        $loader->initialize($this->factory, $this->themeFactory, null, $this->csrfProvider,
                 $this->validator, $this->storage, $this->em);
 
         $this->builder = new FormBuilder($this->dispatcher);