Benjamin Eberlei 14 лет назад
Родитель
Сommit
85b61fe1e2

+ 6 - 0
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

@@ -380,6 +380,12 @@ class FrameworkExtension extends Extension
             $container->getDefinition('templating.engine.delegating')->setArgument(1, $engines);
             $container->setAlias('templating', 'templating.engine.delegating');
         }
+
+        foreach ($config['engines'] as $engine) {
+            if ($container->hasDefinition('form.theme.' . $engine)) {
+                $container->setAlias('form.theme', 'form.theme.' . $engine);
+            }
+        }
     }
 
     /**

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

@@ -9,7 +9,8 @@
         <parameter key="form.config.loader.class">Symfony\Bundle\FrameworkBundle\Form\ContainerAwareConfigLoader</parameter>
         <parameter key="form.guesser.validator.class">Symfony\Component\Form\Guesser\ValidatorFieldGuesser</parameter>
         <parameter key="form.csrf_provider.class">Symfony\Component\Form\CsrfProvider\SessionCsrfProvider</parameter>
-        <parameter key="form.theme.class">Symfony\Component\Form\Renderer\Theme\TwigTheme</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.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>
@@ -42,11 +43,16 @@
             <argument>%form.csrf_protection.secret%</argument>
         </service>
         
-        <!-- Theme -->
-        <service id="form.theme" class="%form.theme.class%">
+        <!-- Themes -->
+        <service id="form.theme.twig" class="%form.theme.twig.class%">
             <argument type="service" id="twig" />
             <argument>%form.theme.template%</argument>
         </service>
+
+        <service id="form.theme.php" class="%form.theme.php.class%">
+            <argument type="service" id="templating.engine.php" />
+            <argument>%form.theme.template%</argument>
+        </service>
         
         <!-- TemporaryStorage - where should we put this? -->
         <service id="file.temporary_storage" class="%file.temporary_storage.class%">

+ 0 - 9
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/checkbox_field.html.php

@@ -1,9 +0,0 @@
-<input type="checkbox"
-    id="<?php echo $field->getId() ?>"
-    name="<?php echo $field->getName() ?>"
-    <?php if ($field->hasValue()): ?>value="<?php echo $field->getValue() ?>"<?php endif ?>
-    <?php if ($field->isDisabled()): ?>disabled="disabled"<?php endif ?>
-    <?php if ($field->isRequired()): ?>required="required"<?php endif ?>
-    <?php if ($field->isChecked()): ?>checked="checked"<?php endif ?>
-    <?php echo $view['form']->attributes($attr) ?>
-/>

+ 8 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/checkbox_widget.html.php

@@ -0,0 +1,8 @@
+<input type="checkbox"
+    id="<?php echo $id; ?>"
+    name="<?php echo $name ?>"
+    <?php if ($value): ?>value="<?php echo $value ?>"<?php endif ?>
+    <?php if ($disabled): ?>disabled="disabled"<?php endif ?>
+    <?php if ($required): ?>required="required"<?php endif ?>
+    <?php if ($checked): ?>checked="checked"<?php endif ?>
+/>

src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_field.html.php → src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget.html.php


src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_field.html.php → src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php


+ 10 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/text_widget.html.php

@@ -0,0 +1,10 @@
+<input type="text"
+    id="<?php echo $id ?>"
+    name="<?php echo $name ?>"
+    value="<?php echo $value ?>"
+    <?php if ($class): ?>class="<?php echo $class; ?>"<?php endif; ?>
+    <?php if ($disabled): ?>disabled="disabled"<?php endif ?>
+    <?php if ($required): ?>required="required"<?php endif ?>
+    <?php if ($max_length && $max_length > 0): ?>maxlength="<?php echo $max_length; ?>"<?php endif; ?>
+    <?php if ($size && $size > 0): ?>size="<?php echo $size; ?>"<?php endif; ?>
+/>

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

@@ -56,6 +56,14 @@ abstract class FrameworkExtensionTest extends TestCase
         $this->assertEquals('router.cached', (string) $container->getAlias('router'), '->registerRouterConfiguration() changes router alias to cached if cache warming is set');
     }
 
+    public function testForm()
+    {
+        $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'));
+    }
+
     /**
      * @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
      */

+ 43 - 0
src/Symfony/Bundle/FrameworkBundle/Tests/Form/PhpThemeTest.php

@@ -0,0 +1,43 @@
+<?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\Tests\TestCase;
+
+/**
+ * Test theme template files shipped with framework bundle.
+ */
+class PhpThemeTest extends TestCase
+{
+    private $engine;
+    private $theme;
+
+    public function setUp()
+    {
+        $parser = new \Symfony\Component\Templating\TemplateNameParser();
+        $loader = new \Symfony\Component\Templating\Loader\FilesystemLoader(__DIR__ . '/../../Resources/views/Form/%name%');
+        $this->engine = new \Symfony\Component\Templating\PhpEngine($parser, $loader, array());
+        $this->theme = new \Symfony\Component\Form\Renderer\Theme\PhpTheme($this->engine);
+    }
+
+    public function testTextWidget()
+    {
+        $field = new \Symfony\Component\Form\Field('foo');
+        $plugin = new \Symfony\Component\Form\Renderer\Plugin\FieldPlugin($field);
+        $field->setRenderer(new \Symfony\Component\Form\Renderer\DefaultRenderer($this->theme, 'text'));
+        $field->setRendererVar('max_length', 128);
+        $field->addRendererPlugin($plugin);
+        $plugin->setUp($field->getRenderer());
+
+        echo $field->getRenderer()->getWidget();
+    }
+}

+ 117 - 0
src/Symfony/Component/Form/Renderer/Theme/PhpTheme.php

@@ -0,0 +1,117 @@
+<?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\Form;
+use Symfony\Component\Form\FieldInterface;
+use Symfony\Component\Form\Exception\FormException;
+use Symfony\Component\Templating\PhpEngine;
+
+/**
+ * Renders a Form using the PHP Templating Engine.
+ *
+ * Each field is rendered as slot of a template.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class PhpTheme implements ThemeInterface
+{
+    /**
+     * @var array
+     */
+    static protected $cache = array();
+
+    /**
+     * @var PhpEngine
+     */
+    private $engine;
+
+    /**
+     * @var string
+     */
+    private $template;
+
+    /**
+     * @param PhpEngine $engine
+     */
+    public function __construct(PhpEngine $engine, $template = null)
+    {
+        $this->engine = $engine;
+        $this->template = $template;
+    }
+
+    public function render($field, $section, array $parameters)
+    {
+        if ($template = $this->lookupTemplate($field."_".$section)) {
+            return $this->engine->render($template, $parameters);
+        } else if ($template = $this->lookupTemplate($section)) {
+            return $this->engine->render($template, $parameters);
+        } else {
+            throw new FormException(sprintf('The form theme is missing the "%s" template file.', $section));
+        }
+    }
+
+    protected function lookupTemplate($templateName)
+    {
+        if (isset(self::$cache[$templateName])) {
+            return self::$cache[$templateName];
+        }
+
+        $template = (($this->template) ? ($this->template.":") : "") . $templateName.'.html.php';
+        if (!$this->engine->exists($template)) {
+            $template = false;
+        }
+
+        self::$cache[$templateName] = $template;
+
+        return $template;
+    }
+
+    /**
+     * Convert an array of HTML attributes into its string representation.
+     * 
+     * @param  array $attributes
+     * @return string
+     */
+    private function attributes($attributes)
+    {
+        if ($attributes instanceof \Traversable) {
+            $attributes = iterator_to_array($attributes);
+        }
+
+        return implode('', array_map(array($this, 'attributesCallback'), array_keys($attributes), array_values($attributes)));
+    }
+
+    private function attribute($name, $value)
+    {
+        return sprintf('%s="%s"', $name, true === $value ? $name : $value);
+    }
+
+    /**
+     * Prepares an attribute key and value for HTML representation.
+     *
+     * It removes empty attributes, except for the value one.
+     *
+     * @param  string $name   The attribute name
+     * @param  string $value  The attribute value
+     *
+     * @return string The HTML representation of the HTML key attribute pair.
+     */
+    private function attributesCallback($name, $value)
+    {
+        if (false === $value || null === $value || ('' === $value && 'value' != $name)) {
+            return '';
+        }
+
+        return ' '.$this->attribute($name, $value);
+    }
+}