Bläddra i källkod

[FrameworkBundle] Added test coverage for FormHelper and fixed various rendering bugs

Bernhard Schussek 14 år sedan
förälder
incheckning
c2dcebf6ea
27 ändrade filer med 324 tillägg och 95 borttagningar
  1. 1 2
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/checkbox_widget.html.php
  2. 1 2
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget.html.php
  3. 9 7
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php
  4. 5 3
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/datetime_widget.html.php
  5. 1 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_enctype.html.php
  6. 1 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rest.html.php
  7. 2 4
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_widget.html.php
  8. 11 9
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/file_widget.html.php
  9. 1 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_widget.html.php
  10. 1 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_row.html.php
  11. 1 2
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_widget.html.php
  12. 8 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/integer_widget.html.php
  13. 1 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/money_widget.html.php
  14. 3 5
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php
  15. 2 4
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php
  16. 1 1
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php
  17. 1 2
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/radio_widget.html.php
  18. 2 0
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/repeated_row.html.php
  19. 2 4
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/text_widget.html.php
  20. 1 2
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/textarea_widget.html.php
  21. 13 11
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/time_widget.html.php
  22. 1 2
      src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/url_widget.html.php
  23. 61 24
      src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php
  24. 33 0
      src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTemplateNameParser.php
  25. 35 0
      src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTranslator.php
  26. 78 0
      src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTest.php
  27. 48 5
      tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php

+ 1 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/checkbox_widget.html.php

@@ -1,9 +1,8 @@
 <input type="checkbox"
-    id="<?php echo $id; ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     <?php if ($value): ?>value="<?php echo $value ?>"<?php endif ?>
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
     <?php if ($required): ?>required="required"<?php endif ?>
     <?php if ($checked): ?>checked="checked"<?php endif ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
 />

+ 1 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget.html.php

@@ -5,12 +5,11 @@
     <?php endforeach ?>
 <?php else: ?>
     <select
-        id="<?php echo $id ?>"
+        <?php echo $view['form']->attributes() ?>
         name="<?php echo $name ?>"
         <?php if ($read_only): ?> disabled="disabled"<?php endif ?>
         <?php if ($multiple): ?> multiple="multiple"<?php endif ?>
         <?php if ($class): ?> class="<?php echo $class ?>"<?php endif ?>
-        <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
     >
         <?php if (!$required): ?><option value=""><?php echo $empty_value; ?></option><?php endif; ?>
         <?php if (count($preferred_choices) > 0): ?>

+ 9 - 7
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php

@@ -1,17 +1,19 @@
 <?php if ($widget == 'text'): ?>
     <input type="text"
-        id="<?php echo $id ?>"
+        <?php echo $view['form']->attributes() ?>
         name="<?php echo $name ?>"
         value="<?php echo $value ?>"
         <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
         <?php if ($required): ?>required="required"<?php endif ?>
         <?php if ($class): ?>class="<?php echo $class ?>"<?php endif ?>
-        <?php if (isset($attr)): echo $form['view']->attributes($attr); endif; ?>
+        <?php if ($max_length): ?>maxlength="<?php echo $max_length ?>"<?php endif ?>
     />
 <?php else: ?>
-    <?php echo str_replace(array('{{ year }}', '{{ month }}', '{{ day }}'), array(
-        $form['view']->widget($context['year']),
-        $form['view']->widget($context['month']),
-        $form['view']->widget($context['day']),
-    ), $date_pattern) ?>
+    <div<?php echo $view['form']->attributes() ?>>
+        <?php echo str_replace(array('{{ year }}', '{{ month }}', '{{ day }}'), array(
+            $view['form']->widget($context['year']),
+            $view['form']->widget($context['month']),
+            $view['form']->widget($context['day']),
+        ), $date_pattern) ?>
+    </div>
 <?php endif ?>

+ 5 - 3
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/datetime_widget.html.php

@@ -1,3 +1,5 @@
-<?php echo $form['form']->widget($context['date']) ?>
-<?php /* keep space */ ?>
-<?php echo $form['form']->widget($context['time']) ?>
+<div<?php echo $view['form']->attributes() ?>>
+    <?php echo $view['form']->widget($context['date'])
+        . ' '
+        . $view['form']->widget($context['time']) ?>
+</div>

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_enctype.html.php

@@ -1 +1 @@
-<?php if ($context->get('multipart')): ?>enctype="multipart/form-data"<?php endif ?>
+<?php if ($context->getVar('multipart')): ?>enctype="multipart/form-data"<?php endif ?>

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rest.html.php

@@ -1,5 +1,5 @@
 <?php foreach ($context->getChildren() as $context): ?>
     <?php if (!$context->isRendered()): ?>
-        <?php echo $view['form']->widget($context) ?>
+        <?php echo $view['form']->row($context) ?>
     <?php endif; ?>
 <?php endforeach; ?>

+ 2 - 4
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_widget.html.php

@@ -1,10 +1,8 @@
-<input id="<?php echo $id ?>" type="<?php echo $type ?>"
+<input
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($class): ?>class="<?php echo $class; ?>"<?php endif; ?>
     <?php if ($read_only): ?>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; ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
 />

+ 11 - 9
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/file_widget.html.php

@@ -1,10 +1,12 @@
-<input type="file"
-    id="<?php echo $context['file']->get('id') ?>"
-    name="<?php echo $context['file']->get('name') ?>"
-    <?php if ($context['file']->get('disabled')): ?>disabled="disabled"<?php endif ?>
-    <?php if ($context['file']->get('required')): ?>required="required"<?php endif ?>
-    <?php if ($context['file']->get('class')): ?>class="<?php echo $context['file']->get('class') ?>"<?php endif ?>
-/>
+<div<?php echo $view['form']->attributes() ?>>
+    <input type="file"
+        id="<?php echo $context['file']->getVar('id') ?>"
+        name="<?php echo $context['file']->getVar('name') ?>"
+        <?php if ($context['file']->getVar('disabled')): ?>disabled="disabled"<?php endif ?>
+        <?php if ($context['file']->getVar('required')): ?>required="required"<?php endif ?>
+        <?php if ($context['file']->getVar('class')): ?>class="<?php echo $context['file']->getVar('class') ?>"<?php endif ?>
+    />
 
-<?php echo $view['form']->widget($context['token']) ?>
-<?php echo $view['form']->widget($context['name']) ?>
+    <?php echo $view['form']->widget($context['token']) ?>
+    <?php echo $view['form']->widget($context['name']) ?>
+</div>

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_widget.html.php

@@ -1,4 +1,4 @@
-<div>
+<div<?php echo $view['form']->attributes() ?>>
     <?php echo $view['form']->errors($context); ?>
     <?php foreach ($context->getChildren() as $context): ?>
         <?php echo $view['form']->row($context); ?>

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_row.html.php

@@ -1 +1 @@
-<?php /** Dont render hidden rows, they are rendered in $form->getRest() */ ?>
+<?php echo $view['form']->widget($context) ?>

+ 1 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_widget.html.php

@@ -1,7 +1,6 @@
 <input type="hidden"
-    id="<?php echo $id ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
 />

+ 8 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/integer_widget.html.php

@@ -1 +1,8 @@
-<?php echo $renderer->getTheme()->render('number', 'widget', $renderer->getVars()); ?>
+<input type="number"
+    <?php echo $view['form']->attributes() ?>
+    name="<?php echo $name ?>"
+    value="<?php echo $value ?>"
+    <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
+    <?php if ($required): ?>required="required"<?php endif ?>
+    <?php if ($class): ?>class="<?php echo $class ?>"<?php endif ?>
+/>

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/money_widget.html.php

@@ -1,4 +1,4 @@
 <?php echo str_replace('{{ widget }}',
-    $renderer->getTheme()->render('number', 'widget', $renderer->getVars()),
+    $view['form']->render('FrameworkBundle:Form:number_widget.html.php'),
     $money_pattern
 ) ?>

+ 3 - 5
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php

@@ -1,11 +1,9 @@
-<input type="number"
-    id="<?php echo $id ?>"
+<input type="text"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
     <?php if ($required): ?>required="required"<?php endif ?>
     <?php if ($class): ?>class="<?php echo $class ?>"<?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; ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
+    <?php if ($max_length): ?>maxlength="<?php echo $max_length ?>"<?php endif ?>
 />

+ 2 - 4
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php

@@ -1,11 +1,9 @@
 <input type="password"
-    id="<?php echo $id ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
     <?php if ($required): ?>required="required"<?php endif ?>
     <?php if ($class): ?>class="<?php echo $class ?>"<?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; ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
+    <?php if ($max_length): ?>maxlength="<?php echo $max_length ?>"<?php endif ?>
 />

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php

@@ -1 +1 @@
-<?php echo $view['form']->widget('number', 'widget', $context) ?> %
+<?php echo $view['form']->render('FrameworkBundle:Form:number_widget.html.php') ?> %

+ 1 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/radio_widget.html.php

@@ -1,10 +1,9 @@
 <input type="radio"
-    id="<?php echo $id ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
     <?php if ($required): ?>required="required"<?php endif ?>
     <?php if ($checked): ?>checked="checked"<?php endif ?>
     <?php if ($class): ?>class="<?php echo $class ?>"<?php endif ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
 />

+ 2 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/repeated_row.html.php

@@ -1,3 +1,5 @@
+<?php echo $view['form']->errors($context) ?>
+
 <?php foreach ($context->getChildren() as $context): ?>
     <?php echo $view['form']->row($context); ?>
 <?php endforeach; ?>

+ 2 - 4
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/text_widget.html.php

@@ -1,11 +1,9 @@
 <input type="text"
-    id="<?php echo $id ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($class): ?>class="<?php echo $class; ?>"<?php endif; ?>
     <?php if ($read_only): ?>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; ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
+    <?php if ($max_length): ?>maxlength="<?php echo $max_length ?>"<?php endif ?>
 />

+ 1 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/textarea_widget.html.php

@@ -1,10 +1,9 @@
 <textarea
-    id="<?php echo $id ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
     <?php if ($required): ?>required="required"<?php endif ?>
     <?php if ($class): ?>class="<?php echo $class ?>"<?php endif ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
 ><?php
     echo $view->escape($value)
 ?></textarea>

+ 13 - 11
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/time_widget.html.php

@@ -1,12 +1,14 @@
-<?php
-    // There should be no spaces between the colons and the widgets, that's why
-    // this block is written in a single PHP tag
-    echo $view['form']->widget($context['hour'], array('size' => 1));
-    echo ':';
-    echo $view['form']->widget($context['minute'], array('size' => 1));
-
-    if ($with_seconds) {
+<div<?php echo $view['form']->attributes() ?>>
+    <?php
+        // There should be no spaces between the colons and the widgets, that's why
+        // this block is written in a single PHP tag
+        echo $view['form']->widget($context['hour'], array('size' => 1));
         echo ':';
-        echo $view['form']->widget($context['second'], array('size' => 1));
-    }
-?>
+        echo $view['form']->widget($context['minute'], array('size' => 1));
+
+        if ($with_seconds) {
+            echo ':';
+            echo $view['form']->widget($context['second'], array('size' => 1));
+        }
+    ?>
+</div>

+ 1 - 2
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/url_widget.html.php

@@ -1,9 +1,8 @@
 <input type="url"
-    id="<?php echo $id ?>"
+    <?php echo $view['form']->attributes() ?>
     name="<?php echo $name ?>"
     value="<?php echo $value ?>"
     <?php if ($read_only): ?>disabled="disabled"<?php endif ?>
     <?php if ($required): ?>required="required"<?php endif ?>
     <?php if ($class): ?>class="<?php echo $class ?>"<?php endif ?>
-    <?php if (isset($attr)): echo $view['form']->attributes($attr); endif; ?>
 />

+ 61 - 24
src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php

@@ -12,7 +12,7 @@
 namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
 
 use Symfony\Component\Templating\Helper\Helper;
-use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
+use Symfony\Component\Templating\EngineInterface;
 use Symfony\Component\Form\TemplateContext;
 use Symfony\Component\Form\Exception\FormException;
 
@@ -28,16 +28,32 @@ class FormHelper extends Helper
 
     protected $engine;
 
+    protected $varStack = array();
+
     public function __construct(EngineInterface $engine)
     {
         $this->engine = $engine;
     }
 
-    public function attributes(array $attribs)
+    public function attributes()
     {
         $html = '';
-        foreach ($attribs as $k => $v) {
-            $html .= $this->engine->escape($k).'="'.$this->engine->escape($v).'" ';
+        $attr = array();
+
+        if (count($this->varStack) > 0) {
+            $vars = end($this->varStack);
+
+            if (isset($vars['attr'])) {
+                $attr = $vars['attr'];
+            }
+
+            if (isset($vars['id'])) {
+                $attr['id'] = $vars['id'];
+            }
+        }
+
+        foreach ($attr as $k => $v) {
+            $html .= ' '.$this->engine->escape($k).'="'.$this->engine->escape($v).'"';
         }
 
         return $html;
@@ -45,12 +61,12 @@ class FormHelper extends Helper
 
     public function enctype(TemplateContext $context)
     {
-        return $this->renderTemplate($context, 'enctype');
+        return $this->renderSection($context, 'enctype');
     }
 
-    public function widget(TemplateContext $context, array $parameters = array(), $template = null)
+    public function widget(TemplateContext $context, array $variables = array())
     {
-        return trim($this->renderTemplate($context, 'widget', $parameters, $template));
+        return trim($this->renderSection($context, 'widget', $variables));
     }
 
     /**
@@ -59,42 +75,63 @@ class FormHelper extends Helper
      * @param  FieldInterface $field
      * @return string
      */
-    public function row(TemplateContext $context, $template = null)
+    public function row(TemplateContext $context, array $variables = array())
     {
-        return $this->renderTemplate($context, 'row', array(), $template);
+        return $this->renderSection($context, 'row', $variables);
     }
 
-    public function label(TemplateContext $context, $label = null, array $parameters = array(), $template = null)
+    public function label(TemplateContext $context, $label = null)
     {
-        return $this->renderTemplate($context, 'label', null === $label ? array() : array('label' => $label));
+        return $this->renderSection($context, 'label', null === $label ? array() : array('label' => $label));
     }
 
-    public function errors(TemplateContext $context, array $parameters = array(), $template = null)
+    public function errors(TemplateContext $context)
     {
-        return $this->renderTemplate($context, 'errors', array(), $template);
+        return $this->renderSection($context, 'errors');
     }
 
-    public function rest(TemplateContext $context, array $parameters = array(), $template = null)
+    public function rest(TemplateContext $context, array $variables = array())
     {
-        return $this->renderTemplate($context, 'rest', array(), $template);
+        return $this->renderSection($context, 'rest', $variables);
     }
 
-    protected function renderTemplate(TemplateContext $context, $section, array $variables = array(), array $resources = null)
+    protected function renderSection(TemplateContext $context, $section, array $variables = array())
     {
-        $blocks = $context->get('types');
+        $template = null;
+        $blocks = $context->getVar('types');
+
         foreach ($blocks as &$block) {
             $block = $block.'_'.$section;
+            $template = $this->lookupTemplate($block);
 
-            if ($template = $this->lookupTemplate($block)) {
-                if ('widget' === $section) {
-                    $context->set('is_rendered', true);
-                }
-
-                return $this->engine->render($template, array_merge($context->all(), $variables));
+            if ($template) {
+                break;
             }
         }
 
-        throw new FormException(sprintf('Unable to render form as none of the following blocks exist: "%s".', implode('", "', $blocks)));
+        if (!$template) {
+            throw new FormException(sprintf('Unable to render form as none of the following blocks exist: "%s".', implode('", "', $blocks)));
+        }
+
+        if ('widget' === $section || 'row' === $section) {
+            $context->setRendered(true);
+        }
+
+        return $this->render($template, array_merge($context->getVars(), $variables));
+    }
+
+    public function render($template, array $variables = array())
+    {
+        array_push($this->varStack, array_merge(
+            count($this->varStack) > 0 ? end($this->varStack) : array(),
+            $variables
+        ));
+
+        $html = $this->engine->render($template, end($this->varStack));
+
+        array_pop($this->varStack);
+
+        return $html;
     }
 
     protected function lookupTemplate($templateName)

+ 33 - 0
src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTemplateNameParser.php

@@ -0,0 +1,33 @@
+<?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\Templating\Helper\Fixtures;
+
+use Symfony\Component\Templating\TemplateNameParserInterface;
+use Symfony\Component\Templating\TemplateReference;
+
+class StubTemplateNameParser implements TemplateNameParserInterface
+{
+    private $root;
+
+    public function __construct($root)
+    {
+        $this->root = $root;
+    }
+
+    public function parse($name)
+    {
+        $parts = explode(':', $name);
+        $name = $parts[count($parts)-1];
+
+        return new TemplateReference($this->root.'/'.$name, 'php');
+    }
+}

+ 35 - 0
src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTranslator.php

@@ -0,0 +1,35 @@
+<?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\Templating\Helper\Fixtures;
+
+use Symfony\Component\Translation\TranslatorInterface;
+
+class StubTranslator implements TranslatorInterface
+{
+    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+    {
+        return '[trans]'.$id.'[/trans]';
+    }
+
+    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+    {
+        return '[trans]'.$id.'[/trans]';
+    }
+
+    public function setLocale($locale)
+    {
+    }
+
+    public function getLocale()
+    {
+    }
+}

+ 78 - 0
src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTest.php

@@ -0,0 +1,78 @@
+<?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\Templating\Helper;
+
+require_once __DIR__.'/Fixtures/StubTemplateNameParser.php';
+require_once __DIR__.'/Fixtures/StubTranslator.php';
+
+use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper;
+use Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper;
+use Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper\Fixtures\StubTemplateNameParser;
+use Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper\Fixtures\StubTranslator;
+use Symfony\Component\Form\FormInterface;
+use Symfony\Component\Templating\PhpEngine;
+use Symfony\Component\Templating\TemplateNameParser;
+use Symfony\Component\Templating\Loader\FilesystemLoader;
+use Symfony\Tests\Component\Form\AbstractDivLayoutTest;
+
+class FormHelperTest extends AbstractDivLayoutTest
+{
+    protected $helper;
+
+    protected function setUp()
+    {
+        parent::setUp();
+
+        $root = realpath(__DIR__.'/../../../Resources/views/Form');
+        $templateNameParser = new StubTemplateNameParser($root);
+        $loader = new FilesystemLoader(array());
+        $engine = new PhpEngine($templateNameParser, $loader);
+
+        $this->helper = new FormHelper($engine);
+
+        $engine->setHelpers(array(
+            $this->helper,
+            new TranslatorHelper(new StubTranslator()),
+        ));
+    }
+
+    protected function renderEnctype(FormInterface $form)
+    {
+        return (string)$this->helper->enctype($form->getContext());
+    }
+
+    protected function renderLabel(FormInterface $form, $label = null)
+    {
+        return (string)$this->helper->label($form->getContext(), $label);
+    }
+
+    protected function renderErrors(FormInterface $form)
+    {
+        return (string)$this->helper->errors($form->getContext());
+    }
+
+    protected function renderWidget(FormInterface $form, array $vars = array())
+    {
+        return (string)$this->helper->widget($form->getContext(), $vars);
+    }
+
+    protected function renderRow(FormInterface $form, array $vars = array())
+    {
+        return (string)$this->helper->row($form->getContext(), $vars);
+    }
+
+    protected function renderRest(FormInterface $form, array $vars = array())
+    {
+        return (string)$this->helper->rest($form->getContext(), $vars);
+    }
+
+}

+ 48 - 5
tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php

@@ -77,14 +77,12 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
     protected function assertWidgetMatchesXpath(FormInterface $form, array $vars, $xpath)
     {
         $html = $this->renderWidget($form, array_merge(array(
-            'name' => 'my_name',
             'id' => 'my_id',
             'attr' => array('class' => 'my_class'),
         ), $vars));
 
         $xpath = trim($xpath).'
     [@id="my_id"]
-    [@name="my_name"]
     [@class="my_class"]';
 
         $this->assertMatchesXpath($html, $xpath);
@@ -173,6 +171,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="checkbox"]
+    [@name="name"]
     [@checked="checked"]
     [@value="1"]
 '
@@ -189,6 +188,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="checkbox"]
+    [@name="name"]
     [@checked="checked"]
     [@value="foobar"]
 '
@@ -204,6 +204,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="checkbox"]
+    [@name="name"]
     [not(@checked)]
 '
         );
@@ -218,6 +219,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [
         ./option[@value="a"][@selected="selected"][.="A"]
         /following-sibling::option[@value="b"][not(@selected)][.="B"]
@@ -237,6 +239,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array('separator' => '-- sep --'),
 '/select
+    [@name="name"]
     [
         ./option[@value="b"][not(@selected)][.="B"]
         /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"]
@@ -257,6 +260,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [
         ./option[@value=""][.=""]
         /following-sibling::option[@value="a"][@selected="selected"][.="A"]
@@ -279,6 +283,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [./optgroup[@label="Group1"]
         [
             ./option[@value="a"][@selected="selected"][.="A"]
@@ -303,6 +308,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [./option[@value="AT"][@selected="selected"][.="Austria"]]
     [count(./option)>200]
 '
@@ -414,7 +420,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/div
-    [./select
+    [
+        ./select
             [@id="name_month"]
             [./option[@value="2"][@selected="selected"]]
         /following-sibling::select
@@ -440,6 +447,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="text"]
+    [@name="name"]
     [@value="Feb 3, 2011"]
 '
         );
@@ -470,6 +478,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="hidden"]
+    [@name="name"]
     [@value="foobar"]
 '
         );
@@ -484,6 +493,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="number"]
+    [@name="name"]
     [@value="123"]
 '
         );
@@ -497,6 +507,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [./option[@value="de"][@selected="selected"][.="German"]]
     [count(./option)>200]
 '
@@ -511,6 +522,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [./option[@value="de_AT"][@selected="selected"][.="German (Austria)"]]
     [count(./option)>200]
 '
@@ -527,6 +539,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="text"]
+    [@name="name"]
     [@value="1234.56"]
     [contains(.., "€")]
 '
@@ -542,6 +555,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="text"]
+    [@name="name"]
     [@value="1234.56"]
 '
         );
@@ -556,7 +570,25 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="password"]
+    [@name="name"]
+    [@value=""]
+'
+        );
+    }
+
+    public function testPasswordWithMaxLength()
+    {
+        $form = $this->factory->create('password', 'name', array(
+            'data' => 'Pa$sW0rD',
+            'max_length' => 123,
+        ));
+
+        $this->assertWidgetMatchesXpath($form, array(),
+'/input
+    [@type="password"]
+    [@name="name"]
     [@value=""]
+    [@maxlength="123"]
 '
         );
     }
@@ -570,6 +602,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="text"]
+    [@name="name"]
     [@value="10"]
     [contains(.., "%")]
 '
@@ -585,6 +618,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="radio"]
+    [@name="name"]
     [@checked="checked"]
     [@value=""]
 '
@@ -601,6 +635,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="radio"]
+    [@name="name"]
     [@checked="checked"]
     [@value="foobar"]
 '
@@ -616,6 +651,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="radio"]
+    [@name="name"]
     [not(@checked)]
 '
         );
@@ -629,6 +665,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/textarea
+    [@name="name"]
     [.="foobar"]
 '
         );
@@ -643,6 +680,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="text"]
+    [@name="name"]
     [@value="foobar"]
     [not(@maxlength)]
 '
@@ -659,6 +697,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="text"]
+    [@name="name"]
     [@value="foobar"]
     [@maxlength="123"]
 '
@@ -675,7 +714,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/div
-    [./select
+    [
+        ./select
             [@id="name_hour"]
             [./option[@value="4"][@selected="selected"]]
         /following-sibling::select
@@ -697,7 +737,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/div
-    [./select
+    [
+        ./select
             [@id="name_hour"]
             [./option[@value="4"][@selected="selected"]]
         /following-sibling::select
@@ -720,6 +761,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 
         $this->assertWidgetMatchesXpath($form, array(),
 '/select
+    [@name="name"]
     [./optgroup
         [@label="Europe"]
         [./option[@value="Europe/Vienna"][@selected="selected"][.="Vienna"]]
@@ -739,6 +781,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
         $this->assertWidgetMatchesXpath($form, array(),
 '/input
     [@type="url"]
+    [@name="name"]
     [@value="http://www.google.com"]
 '
         );