Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[Form] Added entry point "Forms" for more convenient usage outside of…

… Symfony
  • Loading branch information...
commit bf274bbcdb0c73e3a522e084f7abe99896a0ddd7 1 parent 73f3ce3
Bernhard Schussek authored July 30, 2012
1  CHANGELOG.md
Source Rendered
@@ -177,3 +177,4 @@ CHANGELOG
177 177
  * made FormView properties public and deprecated their accessor methods
178 178
  * made the normalized data of a form accessible in the template through the variable "form.vars.data"
179 179
  * made the original data of a choice accessible in the template through the property "choice.data"
  180
+ * added convenience class Forms and FormFactoryBuilderInterface
2  Extension/Csrf/CsrfExtension.php
@@ -27,7 +27,7 @@ class CsrfExtension extends AbstractExtension
27 27
      *
28 28
      * @param CsrfProviderInterface $csrfProvider The CSRF provider
29 29
      */
30  
-    public function __construct(CsrfProviderInterface $csrfProvider)
  30
+    public function __construct(CsrfProviderInterface $csrfProvider = null)
31 31
     {
32 32
         $this->csrfProvider = $csrfProvider;
33 33
     }
208  Extension/Templating/FormHelper.php
... ...
@@ -0,0 +1,208 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form\Extension\Templating;
  13
+
  14
+use Symfony\Component\Templating\Helper\Helper;
  15
+use Symfony\Component\Form\FormRendererInterface;
  16
+use Symfony\Component\Form\FormView;
  17
+use Symfony\Component\Templating\EngineInterface;
  18
+use Symfony\Component\Form\Exception\FormException;
  19
+use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
  20
+use Symfony\Component\Form\Extension\Core\View\ChoiceView;
  21
+use Symfony\Component\Form\Util\FormUtil;
  22
+
  23
+/**
  24
+ * FormHelper provides helpers to help display forms.
  25
+ *
  26
+ * @author Fabien Potencier <fabien@symfony.com>
  27
+ * @author Bernhard Schussek <bschussek@gmail.com>
  28
+ */
  29
+class FormHelper extends Helper
  30
+{
  31
+    /**
  32
+     * @var FormRendererInterface
  33
+     */
  34
+    private $renderer;
  35
+
  36
+    /**
  37
+     * @param FormRendererInterface $renderer
  38
+     */
  39
+    public function __construct(FormRendererInterface $renderer)
  40
+    {
  41
+        $this->renderer = $renderer;
  42
+    }
  43
+
  44
+    /**
  45
+     * {@inheritdoc}
  46
+     */
  47
+    public function getName()
  48
+    {
  49
+        return 'form';
  50
+    }
  51
+
  52
+    /**
  53
+     * Sets a theme for a given view.
  54
+     *
  55
+     * The theme format is "<Bundle>:<Controller>".
  56
+     *
  57
+     * @param FormView     $view   A FormView instance
  58
+     * @param string|array $themes A theme or an array of theme
  59
+     */
  60
+    public function setTheme(FormView $view, $themes)
  61
+    {
  62
+        $this->renderer->setTheme($view, $themes);
  63
+    }
  64
+
  65
+    /**
  66
+     * Renders the HTML enctype in the form tag, if necessary.
  67
+     *
  68
+     * Example usage templates:
  69
+     *
  70
+     *     <form action="..." method="post" <?php echo $view['form']->enctype() ?>>
  71
+     *
  72
+     * @param FormView $view The view for which to render the encoding type
  73
+     *
  74
+     * @return string The HTML markup
  75
+     */
  76
+    public function enctype(FormView $view)
  77
+    {
  78
+        return $this->renderer->searchAndRenderBlock($view, 'enctype');
  79
+    }
  80
+
  81
+    /**
  82
+     * Renders the HTML for a given view.
  83
+     *
  84
+     * Example usage:
  85
+     *
  86
+     *     <?php echo view['form']->widget() ?>
  87
+     *
  88
+     * You can pass options during the call:
  89
+     *
  90
+     *     <?php echo view['form']->widget(array('attr' => array('class' => 'foo'))) ?>
  91
+     *
  92
+     *     <?php echo view['form']->widget(array('separator' => '+++++)) ?>
  93
+     *
  94
+     * @param FormView $view      The view for which to render the widget
  95
+     * @param array    $variables Additional variables passed to the template
  96
+     *
  97
+     * @return string The HTML markup
  98
+     */
  99
+    public function widget(FormView $view, array $variables = array())
  100
+    {
  101
+        return $this->renderer->searchAndRenderBlock($view, 'widget', $variables);
  102
+    }
  103
+
  104
+    /**
  105
+     * Renders the entire form field "row".
  106
+     *
  107
+     * @param FormView $view      The view for which to render the row
  108
+     * @param array    $variables Additional variables passed to the template
  109
+     *
  110
+     * @return string The HTML markup
  111
+     */
  112
+    public function row(FormView $view, array $variables = array())
  113
+    {
  114
+        return $this->renderer->searchAndRenderBlock($view, 'row', $variables);
  115
+    }
  116
+
  117
+    /**
  118
+     * Renders the label of the given view.
  119
+     *
  120
+     * @param FormView $view      The view for which to render the label
  121
+     * @param string   $label     The label
  122
+     * @param array    $variables Additional variables passed to the template
  123
+     *
  124
+     * @return string The HTML markup
  125
+     */
  126
+    public function label(FormView $view, $label = null, array $variables = array())
  127
+    {
  128
+        if (null !== $label) {
  129
+            $variables += array('label' => $label);
  130
+        }
  131
+
  132
+        return $this->renderer->searchAndRenderBlock($view, 'label', $variables);
  133
+    }
  134
+
  135
+    /**
  136
+     * Renders the errors of the given view.
  137
+     *
  138
+     * @param FormView $view The view to render the errors for
  139
+     *
  140
+     * @return string The HTML markup
  141
+     */
  142
+    public function errors(FormView $view)
  143
+    {
  144
+        return $this->renderer->searchAndRenderBlock($view, 'errors');
  145
+    }
  146
+
  147
+    /**
  148
+     * Renders views which have not already been rendered.
  149
+     *
  150
+     * @param FormView $view      The parent view
  151
+     * @param array    $variables An array of variables
  152
+     *
  153
+     * @return string The HTML markup
  154
+     */
  155
+    public function rest(FormView $view, array $variables = array())
  156
+    {
  157
+        return $this->renderer->searchAndRenderBlock($view, 'rest', $variables);
  158
+    }
  159
+
  160
+    /**
  161
+     * Renders a block of the template.
  162
+     *
  163
+     * @param FormView $view      The view for determining the used themes.
  164
+     * @param string   $blockName The name of the block to render.
  165
+     * @param array    $variables The variable to pass to the template.
  166
+     *
  167
+     * @return string The HTML markup
  168
+     */
  169
+    public function block(FormView $view, $blockName, array $variables = array())
  170
+    {
  171
+        return $this->renderer->renderBlock($view, $blockName, $variables);
  172
+    }
  173
+
  174
+    /**
  175
+     * Returns a CSRF token.
  176
+     *
  177
+     * Use this helper for CSRF protection without the overhead of creating a
  178
+     * form.
  179
+     *
  180
+     * <code>
  181
+     * echo $view['form']->csrfToken('rm_user_'.$user->getId());
  182
+     * </code>
  183
+     *
  184
+     * Check the token in your action using the same intention.
  185
+     *
  186
+     * <code>
  187
+     * $csrfProvider = $this->get('form.csrf_provider');
  188
+     * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) {
  189
+     *     throw new \RuntimeException('CSRF attack detected.');
  190
+     * }
  191
+     * </code>
  192
+     *
  193
+     * @param string $intention The intention of the protected action
  194
+     *
  195
+     * @return string A CSRF token
  196
+     *
  197
+     * @throws \BadMethodCallException When no CSRF provider was injected in the constructor.
  198
+     */
  199
+    public function csrfToken($intention)
  200
+    {
  201
+        return $this->renderer->renderCsrfToken($intention);
  202
+    }
  203
+
  204
+    public function humanize($text)
  205
+    {
  206
+        return $this->renderer->humanize($text);
  207
+    }
  208
+}
11  Extension/Validator/ValidatorExtension.php
@@ -17,6 +17,11 @@
17 17
 use Symfony\Component\Validator\ValidatorInterface;
18 18
 use Symfony\Component\Validator\Constraints\Valid;
19 19
 
  20
+/**
  21
+ * Extension supporting the Symfony2 Validator component in forms.
  22
+ *
  23
+ * @author Bernhard Schussek <bschussek@gmail.com>
  24
+ */
20 25
 class ValidatorExtension extends AbstractExtension
21 26
 {
22 27
     private $validator;
@@ -25,6 +30,12 @@ public function __construct(ValidatorInterface $validator)
25 30
     {
26 31
         $this->validator = $validator;
27 32
 
  33
+        // Register the form constraints in the validator programmatically.
  34
+        // This functionality is required when using the Form component without
  35
+        // the DIC, where the XML file is loaded automatically. Thus the following
  36
+        // code must be kept synchronized with validation.xml
  37
+
  38
+        /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */
28 39
         $metadata = $this->validator->getMetadataFactory()->getClassMetadata('Symfony\Component\Form\Form');
29 40
         $metadata->addConstraint(new Form());
30 41
         $metadata->addPropertyConstraint('children', new Valid());
8  FormFactory.php
@@ -37,7 +37,7 @@ public function __construct(FormRegistryInterface $registry, ResolvedFormTypeFac
37 37
     /**
38 38
      * {@inheritdoc}
39 39
      */
40  
-    public function create($type, $data = null, array $options = array(), FormBuilderInterface $parent = null)
  40
+    public function create($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null)
41 41
     {
42 42
         return $this->createBuilder($type, $data, $options, $parent)->getForm();
43 43
     }
@@ -45,7 +45,7 @@ public function create($type, $data = null, array $options = array(), FormBuilde
45 45
     /**
46 46
      * {@inheritdoc}
47 47
      */
48  
-    public function createNamed($name, $type, $data = null, array $options = array(), FormBuilderInterface $parent = null)
  48
+    public function createNamed($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null)
49 49
     {
50 50
         return $this->createNamedBuilder($name, $type, $data, $options, $parent)->getForm();
51 51
     }
@@ -61,7 +61,7 @@ public function createForProperty($class, $property, $data = null, array $option
61 61
     /**
62 62
      * {@inheritdoc}
63 63
      */
64  
-    public function createBuilder($type, $data = null, array $options = array(), FormBuilderInterface $parent = null)
  64
+    public function createBuilder($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null)
65 65
     {
66 66
         $name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface
67 67
             ? $type->getName()
@@ -73,7 +73,7 @@ public function createBuilder($type, $data = null, array $options = array(), For
73 73
     /**
74 74
      * {@inheritdoc}
75 75
      */
76  
-    public function createNamedBuilder($name, $type, $data = null, array $options = array(), FormBuilderInterface $parent = null)
  76
+    public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null)
77 77
     {
78 78
         if (null !== $data && !array_key_exists('data', $options)) {
79 79
             $options['data'] = $data;
164  FormFactoryBuilder.php
... ...
@@ -0,0 +1,164 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form;
  13
+
  14
+/**
  15
+ * @author Bernhard Schussek <bschussek@gmail.com>
  16
+ */
  17
+
  18
+/**
  19
+ * The default implementation of FormFactoryBuilderInterface.
  20
+ *
  21
+ * @author Bernhard Schussek <bschussek@gmail.com>
  22
+ */
  23
+class FormFactoryBuilder implements FormFactoryBuilderInterface
  24
+{
  25
+    /**
  26
+     * @var ResolvedFormTypeFactoryInterface
  27
+     */
  28
+    private $resolvedTypeFactory;
  29
+
  30
+    /**
  31
+     * @var array
  32
+     */
  33
+    private $extensions = array();
  34
+
  35
+    /**
  36
+     * @var array
  37
+     */
  38
+    private $types = array();
  39
+
  40
+    /**
  41
+     * @var array
  42
+     */
  43
+    private $typeExtensions = array();
  44
+
  45
+    /**
  46
+     * @var array
  47
+     */
  48
+    private $typeGuessers = array();
  49
+
  50
+    /**
  51
+     * {@inheritdoc}
  52
+     */
  53
+    public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory)
  54
+    {
  55
+        $this->resolvedTypeFactory = $resolvedTypeFactory;
  56
+
  57
+        return $this;
  58
+    }
  59
+
  60
+    /**
  61
+     * {@inheritdoc}
  62
+     */
  63
+    public function addExtension(FormExtensionInterface $extension)
  64
+    {
  65
+        $this->extensions[] = $extension;
  66
+
  67
+        return $this;
  68
+    }
  69
+
  70
+    /**
  71
+     * {@inheritdoc}
  72
+     */
  73
+    public function addExtensions(array $extensions)
  74
+    {
  75
+        $this->extensions = array_merge($this->extensions, $extensions);
  76
+
  77
+        return $this;
  78
+    }
  79
+
  80
+    /**
  81
+     * {@inheritdoc}
  82
+     */
  83
+    public function addType(FormTypeInterface $type)
  84
+    {
  85
+        $this->types[$type->getName()] = $type;
  86
+
  87
+        return $this;
  88
+    }
  89
+
  90
+    /**
  91
+     * {@inheritdoc}
  92
+     */
  93
+    public function addTypes(array $types)
  94
+    {
  95
+        foreach ($types as $type) {
  96
+            $this->types[$type->getName()] = $type;
  97
+        }
  98
+
  99
+        return $this;
  100
+    }
  101
+
  102
+    /**
  103
+     * {@inheritdoc}
  104
+     */
  105
+    public function addTypeExtension(FormTypeExtensionInterface $typeExtension)
  106
+    {
  107
+        $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension;
  108
+
  109
+        return $this;
  110
+    }
  111
+
  112
+    /**
  113
+     * {@inheritdoc}
  114
+     */
  115
+    public function addTypeExtensions(array $typeExtensions)
  116
+    {
  117
+        foreach ($typeExtensions as $typeExtension) {
  118
+            $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension;
  119
+        }
  120
+
  121
+        return $this;
  122
+    }
  123
+
  124
+    /**
  125
+     * {@inheritdoc}
  126
+     */
  127
+    public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser)
  128
+    {
  129
+        $this->typeGuessers[] = $typeGuesser;
  130
+
  131
+        return $this;
  132
+    }
  133
+
  134
+    /**
  135
+     * {@inheritdoc}
  136
+     */
  137
+    public function addTypeGuessers(array $typeGuessers)
  138
+    {
  139
+        $this->typeGuessers = array_merge($this->typeGuessers, $typeGuessers);
  140
+
  141
+        return $this;
  142
+    }
  143
+
  144
+    /**
  145
+     * {@inheritdoc}
  146
+     */
  147
+    public function getFormFactory()
  148
+    {
  149
+        $extensions = $this->extensions;
  150
+
  151
+        if (count($this->types) > 0 || count($this->typeExtensions) > 0 || count($this->typeGuessers) > 0) {
  152
+            $typeGuesser = count($this->typeGuessers) > 1
  153
+                ? new FormTypeGuesserChain($this->typeGuessers)
  154
+                : $this->typeGuessers[0];
  155
+
  156
+            $extensions[] = new PreloadedExtension($this->types, $this->typeExtensions, $typeGuesser);
  157
+        }
  158
+
  159
+        $resolvedTypeFactory = $this->resolvedTypeFactory ?: new ResolvedFormTypeFactory();
  160
+        $registry = new FormRegistry($extensions, $resolvedTypeFactory);
  161
+
  162
+        return new FormFactory($registry, $resolvedTypeFactory);
  163
+    }
  164
+}
108  FormFactoryBuilderInterface.php
... ...
@@ -0,0 +1,108 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form;
  13
+
  14
+/**
  15
+ * A builder for FormFactoryInterface objects.
  16
+ *
  17
+ * @author Bernhard Schussek <bschussek@gmail.com>
  18
+ */
  19
+interface FormFactoryBuilderInterface
  20
+{
  21
+    /**
  22
+     * Sets the factory for creating ResolvedFormTypeInterface instances.
  23
+     *
  24
+     * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory
  25
+     *
  26
+     * @return FormFactoryBuilderInterface The builder.
  27
+     */
  28
+    public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory);
  29
+
  30
+    /**
  31
+     * Adds an extension to be loaded by the factory.
  32
+     *
  33
+     * @param FormExtensionInterface $extension The extension.
  34
+     *
  35
+     * @return FormFactoryBuilderInterface The builder.
  36
+     */
  37
+    public function addExtension(FormExtensionInterface $extension);
  38
+
  39
+    /**
  40
+     * Adds a list of extensions to be loaded by the factory.
  41
+     *
  42
+     * @param array $extensions The extensions.
  43
+     *
  44
+     * @return FormFactoryBuilderInterface The builder.
  45
+     */
  46
+    public function addExtensions(array $extensions);
  47
+
  48
+    /**
  49
+     * Adds a form type to the factory.
  50
+     *
  51
+     * @param FormTypeInterface $type The form type.
  52
+     *
  53
+     * @return FormFactoryBuilderInterface The builder.
  54
+     */
  55
+    public function addType(FormTypeInterface $type);
  56
+
  57
+    /**
  58
+     * Adds a list of form types to the factory.
  59
+     *
  60
+     * @param array $types The form types.
  61
+     *
  62
+     * @return FormFactoryBuilderInterface The builder.
  63
+     */
  64
+    public function addTypes(array $types);
  65
+
  66
+    /**
  67
+     * Adds a form type extension to the factory.
  68
+     *
  69
+     * @param FormTypeExtensionInterface $typeExtension The form type extension.
  70
+     *
  71
+     * @return FormFactoryBuilderInterface The builder.
  72
+     */
  73
+    public function addTypeExtension(FormTypeExtensionInterface $typeExtension);
  74
+
  75
+    /**
  76
+     * Adds a list of form type extensions to the factory.
  77
+     *
  78
+     * @param array $typeExtensions The form type extensions.
  79
+     *
  80
+     * @return FormFactoryBuilderInterface The builder.
  81
+     */
  82
+    public function addTypeExtensions(array $typeExtensions);
  83
+
  84
+    /**
  85
+     * Adds a type guesser to the factory.
  86
+     *
  87
+     * @param FormTypeGuesserInterface $typeGuesser The type guesser.
  88
+     *
  89
+     * @return FormFactoryBuilderInterface The builder.
  90
+     */
  91
+    public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser);
  92
+
  93
+    /**
  94
+     * Adds a list of type guessers to the factory.
  95
+     *
  96
+     * @param array $typeGuessers The type guessers.
  97
+     *
  98
+     * @return FormFactoryBuilderInterface The builder.
  99
+     */
  100
+    public function addTypeGuessers(array $typeGuessers);
  101
+
  102
+    /**
  103
+     * Builds and returns the factory.
  104
+     *
  105
+     * @return FormFactoryInterface The form factory.
  106
+     */
  107
+    public function getFormFactory();
  108
+}
8  FormFactoryInterface.php
@@ -30,7 +30,7 @@
30 30
      *
31 31
      * @throws Exception\FormException if any given option is not applicable to the given type
32 32
      */
33  
-    public function create($type, $data = null, array $options = array(), FormBuilderInterface $parent = null);
  33
+    public function create($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null);
34 34
 
35 35
     /**
36 36
      * Returns a form.
@@ -47,7 +47,7 @@ public function create($type, $data = null, array $options = array(), FormBuilde
47 47
      *
48 48
      * @throws Exception\FormException if any given option is not applicable to the given type
49 49
      */
50  
-    public function createNamed($name, $type, $data = null, array $options = array(), FormBuilderInterface $parent = null);
  50
+    public function createNamed($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null);
51 51
 
52 52
     /**
53 53
      * Returns a form for a property of a class.
@@ -78,7 +78,7 @@ public function createForProperty($class, $property, $data = null, array $option
78 78
      *
79 79
      * @throws Exception\FormException if any given option is not applicable to the given type
80 80
      */
81  
-    public function createBuilder($type, $data = null, array $options = array(), FormBuilderInterface $parent = null);
  81
+    public function createBuilder($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null);
82 82
 
83 83
     /**
84 84
      * Returns a form builder.
@@ -93,7 +93,7 @@ public function createBuilder($type, $data = null, array $options = array(), For
93 93
      *
94 94
      * @throws Exception\FormException if any given option is not applicable to the given type
95 95
      */
96  
-    public function createNamedBuilder($name, $type, $data = null, array $options = array(), FormBuilderInterface $parent = null);
  96
+    public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null);
97 97
 
98 98
     /**
99 99
      * Returns a form builder for a property of a class.
138  Forms.php
... ...
@@ -0,0 +1,138 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form;
  13
+
  14
+use Symfony\Component\Form\Extension\Core\CoreExtension;
  15
+use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
  16
+
  17
+/**
  18
+ * Entry point of the Form component.
  19
+ *
  20
+ * Use this class to conveniently create new form factories:
  21
+ *
  22
+ * <code>
  23
+ * use Symfony\Component\Form\Forms;
  24
+ *
  25
+ * $formFactory = Forms::createFormFactory();
  26
+ *
  27
+ * $form = $formFactory->createBuilder()
  28
+ *     ->add('firstName', 'text')
  29
+ *     ->add('lastName', 'text')
  30
+ *     ->add('age', 'integer')
  31
+ *     ->add('gender', 'choice', array(
  32
+ *         'choices' => array('m' => 'Male', 'f' => 'Female'),
  33
+ *     ))
  34
+ *     ->getForm();
  35
+ * </code>
  36
+ *
  37
+ * You can also add custom extensions to the form factory:
  38
+ *
  39
+ * <code>
  40
+ * $formFactory = Forms::createFormFactoryBuilder()
  41
+ *     ->addExtension(new AcmeExtension())
  42
+ *     ->getFormFactory();
  43
+ * </code>
  44
+ *
  45
+ * If you create custom form types or type extensions, it is
  46
+ * generally recommended to create your own extensions that lazily
  47
+ * load these types and type extensions. In projects where performance
  48
+ * does not matter that much, you can also pass them directly to the
  49
+ * form factory:
  50
+ *
  51
+ * <code>
  52
+ * $formFactory = Forms::createFormFactoryBuilder()
  53
+ *     ->addType(new PersonType())
  54
+ *     ->addType(new PhoneNumberType())
  55
+ *     ->addTypeExtension(new FormTypeHelpTextExtension())
  56
+ *     ->getFormFactory();
  57
+ * </code>
  58
+ *
  59
+ * Support for CSRF protection is provided by the CsrfExtension.
  60
+ * This extension needs a CSRF provider with a strong secret
  61
+ * (e.g. a 20 character long random string). The default
  62
+ * implementation for this is DefaultCsrfProvider:
  63
+ *
  64
+ * <code>
  65
+ * use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
  66
+ * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;
  67
+ *
  68
+ * $secret = 'V8a5Z97e...';
  69
+ * $formFactory = Forms::createFormFactoryBuilder()
  70
+ *     ->addExtension(new CsrfExtension(new DefaultCsrfProvider($secret)))
  71
+ *     ->getFormFactory();
  72
+ * </code>
  73
+ *
  74
+ * Support for the HttpFoundation is provided by the
  75
+ * HttpFoundationExtension. You are also advised to load the CSRF
  76
+ * extension with the driver for HttpFoundation's Session class:
  77
+ *
  78
+ * <code>
  79
+ * use Symfony\Component\HttpFoundation\Session\Session;
  80
+ * use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
  81
+ * use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
  82
+ * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider;
  83
+ *
  84
+ * $session = new Session();
  85
+ * $secret = 'V8a5Z97e...';
  86
+ * $formFactory = Forms::createFormFactoryBuilder()
  87
+ *     ->addExtension(new HttpFoundationExtension())
  88
+ *     ->addExtension(new CsrfExtension(new SessionCsrfProvider($session, $secret)))
  89
+ *     ->getFormFactory();
  90
+ * </code>
  91
+ *
  92
+ * Support for the Validator component is provided by ValidatorExtension.
  93
+ * This extension needs a validator object to function properly:
  94
+ *
  95
+ * <code>
  96
+ * use Symfony\Component\Validator\ValidatorFactory;
  97
+ * use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
  98
+ *
  99
+ * $validator = ValidatorFactory::buildDefault()->getValidator();
  100
+ * $formFactory = Forms::createFormFactoryBuilder()
  101
+ *     ->addExtension(new ValidatorExtension($validator))
  102
+ *     ->getFormFactory();
  103
+ * </code>
  104
+ *
  105
+ * @author Bernhard Schussek <bschussek@gmail.com>
  106
+ */
  107
+final class Forms
  108
+{
  109
+    /**
  110
+     * Creates a form factory with the default configuration.
  111
+     *
  112
+     * @return FormFactoryInterface The form factory.
  113
+     */
  114
+    public static function createFormFactory()
  115
+    {
  116
+        return self::createFormFactoryBuilder()->getFormFactory();
  117
+    }
  118
+
  119
+    /**
  120
+     * Creates a form factory builder with the default configuration.
  121
+     *
  122
+     * @return FormFactoryBuilderInterface The form factory builder.
  123
+     */
  124
+    public static function createFormFactoryBuilder()
  125
+    {
  126
+        $builder = new FormFactoryBuilder();
  127
+        $builder->addExtension(new CoreExtension());
  128
+
  129
+        return $builder;
  130
+    }
  131
+
  132
+    /**
  133
+     * This class cannot be instantiated.
  134
+     */
  135
+    private function __construct()
  136
+    {
  137
+    }
  138
+}
100  PreloadedExtension.php
... ...
@@ -0,0 +1,100 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form;
  13
+
  14
+/**
  15
+ * @author Bernhard Schussek <bschussek@gmail.com>
  16
+ */
  17
+use Symfony\Component\Form\Exception\FormException;
  18
+
  19
+/**
  20
+ * A form extension with preloaded types, type exceptions and type guessers.
  21
+ *
  22
+ * @author Bernhard Schussek <bschussek@gmail.com>
  23
+ */
  24
+class PreloadedExtension implements FormExtensionInterface
  25
+{
  26
+    /**
  27
+     * @var array
  28
+     */
  29
+    private $types = array();
  30
+
  31
+    /**
  32
+     * @var array
  33
+     */
  34
+    private $typeExtensions = array();
  35
+
  36
+    /**
  37
+     * @var FormTypeGuesserInterface
  38
+     */
  39
+    private $typeGuesser;
  40
+
  41
+    /**
  42
+     * Creates a new preloaded extension.
  43
+     *
  44
+     * @param array                    $types          The types that the extension should support.
  45
+     * @param array                    $typeExtensions The type extensions that the extension should support.
  46
+     * @param FormTypeGuesserInterface $typeGuesser    The guesser that the extension should support.
  47
+     */
  48
+    public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser)
  49
+    {
  50
+        $this->types = $types;
  51
+        $this->typeExtensions = $typeExtensions;
  52
+        $this->typeGuesser = $typeGuesser;
  53
+    }
  54
+
  55
+    /**
  56
+     * {@inheritdoc}
  57
+     */
  58
+    public function getType($name)
  59
+    {
  60
+        if (!isset($this->types[$name])) {
  61
+            throw new FormException(sprintf('The type "%s" can not be loaded by this extension', $name));
  62
+        }
  63
+
  64
+        return $this->types[$name];
  65
+    }
  66
+
  67
+    /**
  68
+     * {@inheritdoc}
  69
+     */
  70
+    public function hasType($name)
  71
+    {
  72
+        return isset($this->types[$name]);
  73
+    }
  74
+
  75
+    /**
  76
+     * {@inheritdoc}
  77
+     */
  78
+    public function getTypeExtensions($name)
  79
+    {
  80
+        return isset($this->typeExtensions[$name])
  81
+            ? $this->typeExtensions[$name]
  82
+            : array();
  83
+    }
  84
+
  85
+    /**
  86
+     * {@inheritdoc}
  87
+     */
  88
+    public function hasTypeExtensions($name)
  89
+    {
  90
+        return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0;
  91
+    }
  92
+
  93
+    /**
  94
+     * {@inheritdoc}
  95
+     */
  96
+    public function getTypeGuesser()
  97
+    {
  98
+        return $this->typeGuesser;
  99
+    }
  100
+}
1  Tests/AbstractLayoutTest.php
@@ -39,7 +39,6 @@ protected function setUp()
39 39
     protected function getExtensions()
40 40
     {
41 41
         return array(
42  
-            new CoreExtension(),
43 42
             new CsrfExtension($this->csrfProvider),
44 43
         );
45 44
     }
43  Tests/Extension/Templating/Fixtures/StubTemplateNameParser.php
... ...
@@ -0,0 +1,43 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form\Tests\Extension\Templating\Fixtures;
  13
+
  14
+use Symfony\Component\Templating\TemplateNameParserInterface;
  15
+use Symfony\Component\Templating\TemplateReference;
  16
+
  17
+class StubTemplateNameParser implements TemplateNameParserInterface
  18
+{
  19
+    private $root;
  20
+
  21
+    private $rootTheme;
  22
+
  23
+    public function __construct($root, $rootTheme)
  24
+    {
  25
+        $this->root = $root;
  26
+        $this->rootTheme = $rootTheme;
  27
+    }
  28
+
  29
+    public function parse($name)
  30
+    {
  31
+        list($bundle, $controller, $template) = explode(':', $name, 3);
  32
+
  33
+        if ($template[0] == '_') {
  34
+            $path = $this->rootTheme.'/Custom/'.$template;
  35
+        } elseif ($bundle === 'TestBundle') {
  36
+            $path = $this->rootTheme.'/'.$controller.'/'.$template;
  37
+        } else {
  38
+            $path = $this->root.'/'.$controller.'/'.$template;
  39
+        }
  40
+
  41
+        return new TemplateReference($path, 'php');
  42
+    }
  43
+}
35  Tests/Extension/Templating/Fixtures/StubTranslator.php
... ...
@@ -0,0 +1,35 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form\Tests\Extension\Templating\Fixtures;
  13
+
  14
+use Symfony\Component\Translation\TranslatorInterface;
  15
+
  16
+class StubTranslator implements TranslatorInterface
  17
+{
  18
+    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
  19
+    {
  20
+        return '[trans]'.$id.'[/trans]';
  21
+    }
  22
+
  23
+    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
  24
+    {
  25
+        return '[trans]'.$id.'[/trans]';
  26
+    }
  27
+
  28
+    public function setLocale($locale)
  29
+    {
  30
+    }
  31
+
  32
+    public function getLocale()
  33
+    {
  34
+    }
  35
+}
116  Tests/Extension/Templating/FormHelperDivLayoutTest.php
... ...
@@ -0,0 +1,116 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form\Tests\Extension\Templating;
  13
+
  14
+use Symfony\Component\Form\FormView;
  15
+use Symfony\Component\Form\FormRenderer;
  16
+use Symfony\Component\Form\Extension\Templating\FormHelper;
  17
+use Symfony\Component\Form\Extension\Templating\TemplatingRendererEngine;
  18
+use Symfony\Component\Form\Tests\AbstractDivLayoutTest;
  19
+use Symfony\Component\Form\Tests\Extension\Templating\Fixtures\StubTemplateNameParser;
  20
+use Symfony\Component\Form\Tests\Extension\Templating\Fixtures\StubTranslator;
  21
+use Symfony\Component\Templating\PhpEngine;
  22
+use Symfony\Component\Templating\Loader\FilesystemLoader;
  23
+
  24
+// should probably be moved to the Translation component
  25
+use Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper;
  26
+
  27
+class FormHelperDivLayoutTest extends AbstractDivLayoutTest
  28
+{
  29
+    protected $helper;
  30
+
  31
+    protected function setUp()
  32
+    {
  33
+        if (!class_exists('Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper')) {
  34
+            $this->markTestSkipped('The "FrameworkBundle" is not available');
  35
+        }
  36
+
  37
+        if (!class_exists('Symfony\Component\Templating\PhpEngine')) {
  38
+            $this->markTestSkipped('The "Templating" component is not available');
  39
+        }
  40
+
  41
+        parent::setUp();
  42
+
  43
+        // should be moved to the Form component once absolute file paths are supported
  44
+        // by the default name parser in the Templating component
  45
+        $reflClass = new \ReflectionClass('Symfony\Bundle\FrameworkBundle\FrameworkBundle');
  46
+        $root = realpath(dirname($reflClass->getFileName()) . '/Resources/views');
  47
+        $rootTheme = realpath(__DIR__.'/Resources');
  48
+        $templateNameParser = new StubTemplateNameParser($root, $rootTheme);
  49
+        $loader = new FilesystemLoader(array());
  50
+        $engine = new PhpEngine($templateNameParser, $loader);
  51
+        $engine->addGlobal('global', '');
  52
+        $rendererEngine = new TemplatingRendererEngine($engine, array('FrameworkBundle:Form'));
  53
+        $renderer = new FormRenderer($rendererEngine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'));
  54
+
  55
+        $this->helper = new FormHelper($renderer);
  56
+
  57
+        $engine->setHelpers(array(
  58
+            $this->helper,
  59
+            new TranslatorHelper(new StubTranslator()),
  60
+        ));
  61
+    }
  62
+
  63
+    protected function tearDown()
  64
+    {
  65
+        $this->helper = null;
  66
+    }
  67
+
  68
+    protected function renderEnctype(FormView $view)
  69
+    {
  70
+        return (string) $this->helper->enctype($view);
  71
+    }
  72
+
  73
+    protected function renderLabel(FormView $view, $label = null, array $vars = array())
  74
+    {
  75
+        return (string) $this->helper->label($view, $label, $vars);
  76
+    }
  77
+
  78
+    protected function renderErrors(FormView $view)
  79
+    {
  80
+        return (string) $this->helper->errors($view);
  81
+    }
  82
+
  83
+    protected function renderWidget(FormView $view, array $vars = array())
  84
+    {
  85
+        return (string) $this->helper->widget($view, $vars);
  86
+    }
  87
+
  88
+    protected function renderRow(FormView $view, array $vars = array())
  89
+    {
  90
+        return (string) $this->helper->row($view, $vars);
  91
+    }
  92
+
  93
+    protected function renderRest(FormView $view, array $vars = array())
  94
+    {
  95
+        return (string) $this->helper->rest($view, $vars);
  96
+    }
  97
+
  98
+    protected function setTheme(FormView $view, array $themes)
  99
+    {
  100
+        $this->helper->setTheme($view, $themes);
  101
+    }
  102
+
  103
+    public static function themeBlockInheritanceProvider()
  104
+    {
  105
+        return array(
  106
+            array(array('TestBundle:Parent'))
  107
+        );
  108
+    }
  109
+
  110
+    public static function themeInheritanceProvider()
  111
+    {
  112
+        return array(
  113
+            array(array('TestBundle:Parent'), array('TestBundle:Child'))
  114
+        );
  115
+    }
  116
+}
105  Tests/Extension/Templating/FormHelperTableLayoutTest.php
... ...
@@ -0,0 +1,105 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Component\Form\Tests\Extension\Templating;
  13
+
  14
+use Symfony\Component\Form\FormView;
  15
+use Symfony\Component\Form\FormRenderer;
  16
+use Symfony\Component\Form\Extension\Templating\FormHelper;
  17
+use Symfony\Component\Form\Extension\Templating\TemplatingRendererEngine;
  18
+use Symfony\Component\Form\Tests\AbstractTableLayoutTest;
  19
+use Symfony\Component\Form\Tests\Extension\Templating\Fixtures\StubTemplateNameParser;
  20
+use Symfony\Component\Form\Tests\Extension\Templating\Fixtures\StubTranslator;
  21
+use Symfony\Component\Templating\PhpEngine;
  22
+use Symfony\Component\Templating\Loader\FilesystemLoader;
  23
+
  24
+// should probably be moved to the Translation component
  25
+use Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper;
  26
+
  27
+class FormHelperTableLayoutTest extends AbstractTableLayoutTest
  28
+{
  29
+    protected $helper;
  30
+
  31
+    protected function setUp()
  32
+    {
  33
+        if (!class_exists('Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper')) {
  34
+            $this->markTestSkipped('The "FrameworkBundle" is not available');
  35
+        }
  36
+
  37
+        if (!class_exists('Symfony\Component\Templating\PhpEngine')) {
  38
+            $this->markTestSkipped('The "Templating" component is not available');
  39
+        }
  40
+
  41
+        parent::setUp();
  42
+
  43
+        // should be moved to the Form component once absolute file paths are supported
  44
+        // by the default name parser in the Templating component
  45
+        $reflClass = new \ReflectionClass('Symfony\Bundle\FrameworkBundle\FrameworkBundle');
  46
+        $root = realpath(dirname($reflClass->getFileName()) . '/Resources/views');
  47
+        $rootTheme = realpath(__DIR__.'/Resources');
  48
+        $templateNameParser = new StubTemplateNameParser($root, $rootTheme);
  49
+        $loader = new FilesystemLoader(array());
  50
+        $engine = new PhpEngine($templateNameParser, $loader);
  51
+        $engine->addGlobal('global', '');
  52
+        $rendererEngine = new TemplatingRendererEngine($engine, array(
  53
+            'FrameworkBundle:Form',
  54
+            'FrameworkBundle:FormTable'
  55
+        ));
  56
+        $renderer = new FormRenderer($rendererEngine, $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'));
  57
+
  58
+        $this->helper = new FormHelper($renderer);
  59
+
  60
+        $engine->setHelpers(array(
  61
+            $this->helper,
  62
+            new TranslatorHelper(new StubTranslator()),
  63
+        ));
  64
+    }
  65
+
  66
+    protected function tearDown()
  67
+    {
  68
+        $this->helper = null;
  69
+    }
  70
+
  71
+    protected function renderEnctype(FormView $view)
  72
+    {
  73
+        return (string) $this->helper->enctype($view);
  74
+    }
  75
+
  76
+    protected function renderLabel(FormView $view, $label = null, array $vars = array())
  77
+    {
  78
+        return (string) $this->helper->label($view, $label, $vars);
  79
+    }
  80
+
  81
+    protected function renderErrors(FormView $view)
  82
+    {
  83
+        return (string) $this->helper->errors($view);
  84
+    }
  85
+
  86
+    protected function renderWidget(FormView $view, array $vars = array())
  87
+    {