Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 323 lines (272 sloc) 9.738 kb
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
1 <?php
2
1c9d761 @blue-eyes normalized license messages in PHP files
blue-eyes authored
3 /*
4 * This file is part of the Symfony package.
5 *
506e5b7 @fabpot replaced symfony-project.org by symfony.com
fabpot authored
6 * (c) Fabien Potencier <fabien@symfony.com>
1c9d761 @blue-eyes normalized license messages in PHP files
blue-eyes authored
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
12 namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
13
14 use Symfony\Component\Templating\Helper\Helper;
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
15 use Symfony\Component\Templating\EngineInterface;
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
16 use Symfony\Component\Form\FormView;
94aae9c @fabpot [Form] reverted the templating part to be similar to what we have today
fabpot authored
17 use Symfony\Component\Form\Exception\FormException;
925e14d @fabpot moved some FormView methods to FormUtil where they really belongs
fabpot authored
18 use Symfony\Component\Form\Util\FormUtil;
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
19
20 /**
94aae9c @fabpot [Form] reverted the templating part to be similar to what we have today
fabpot authored
21 *
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
22 *
506e5b7 @fabpot replaced symfony-project.org by symfony.com
fabpot authored
23 * @author Fabien Potencier <fabien@symfony.com>
24 * @author Bernhard Schussek <bernhard.schussek@symfony.com>
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
25 */
26 class FormHelper extends Helper
27 {
28 protected $engine;
29
b0a6506 @webmozart [Form] Fixed variable scope when entering nested form helpers
webmozart authored
30 protected $varStack;
31
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
32 protected $context;
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
33
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
34 protected $resources;
35
36 protected $themes;
37
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
38 protected $templates;
39
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
40 /**
41 * Constructor;
42 *
43 * @param EngineInterface $engine The templating engine
44 * @param array $resources An array of theme name
45 */
6444155 @vicb [Form] Add the FormHelper configuration
vicb authored
46 public function __construct(EngineInterface $engine, array $resources)
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
47 {
48 $this->engine = $engine;
6444155 @vicb [Form] Add the FormHelper configuration
vicb authored
49 $this->resources = $resources;
60711af @vicb [Form] Add the ability to override label & widget options when rendering...
vicb authored
50 $this->varStack = array();
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
51 $this->context = array();
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
52 $this->templates = array();
53 $this->themes = array();
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
54 }
55
925e14d @fabpot moved some FormView methods to FormUtil where they really belongs
fabpot authored
56 public function isChoiceGroup($label)
57 {
58 return FormUtil::isChoiceGroup($label);
59 }
60
61 public function isChoiceSelected(FormView $view, $choice)
62 {
63 return FormUtil::isChoiceSelected($choice, $view->get('value'));
64 }
65
469016f @vicb [FrameworkBundle][Form] Fix label rendering
vicb authored
66 /**
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
67 * Sets a theme for a given view.
68 *
69 * The theme format is "<Bundle>:<Controller>".
70 *
71 * @param FormView $view A FormView instance
72 * @param string|array $resources A theme or an array of theme
73 */
74 public function setTheme(FormView $view, $themes)
75 {
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
76 $this->themes[$view->get('id')] = (array) $themes;
77 $this->templates = array();
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
78 }
79
80 /**
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
81 * Renders the HTML enctype in the form tag, if necessary.
82 *
5daa2b4 @vicb [FrameworkBundle] Fix the FormHelper phpDoc
vicb authored
83 * Example usage templates:
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
84 *
85 * <form action="..." method="post" <?php echo $view['form']->enctype() ?>>
86 *
87 * @param FormView $view The view for which to render the encoding type
88 *
89 * @return string The html markup
90 */
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
91 public function enctype(FormView $view)
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
92 {
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
93 return $this->renderSection($view, 'enctype');
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
94 }
95
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
96 /**
97 * Renders the HTML for a given view.
98 *
5daa2b4 @vicb [FrameworkBundle] Fix the FormHelper phpDoc
vicb authored
99 * Example usage:
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
100 *
5daa2b4 @vicb [FrameworkBundle] Fix the FormHelper phpDoc
vicb authored
101 * <?php echo view['form']->widget() ?>
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
102 *
103 * You can pass options during the call:
104 *
5daa2b4 @vicb [FrameworkBundle] Fix the FormHelper phpDoc
vicb authored
105 * <?php echo view['form']->widget(array('attr' => array('class' => 'foo'))) ?>
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
106 *
5daa2b4 @vicb [FrameworkBundle] Fix the FormHelper phpDoc
vicb authored
107 * <?php echo view['form']->widget(array('separator' => '+++++)) ?>
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
108 *
109 * @param FormView $view The view for which to render the widget
110 * @param array $variables Additional variables passed to the template
111 *
112 * @return string The html markup
113 */
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
114 public function widget(FormView $view, array $variables = array())
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
115 {
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
116 return trim($this->renderSection($view, 'widget', $variables));
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
117 }
118
119 /**
94aae9c @fabpot [Form] reverted the templating part to be similar to what we have today
fabpot authored
120 * Renders the entire form field "row".
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
121 *
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
122 * @param FormView $view The view for which to render the row
123 * @param array $variables Additional variables passed to the template
c4c66ff @pborreli [Phpdoc] Cleaning/fixing
pborreli authored
124 *
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
125 * @return string The html markup
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
126 */
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
127 public function row(FormView $view, array $variables = array())
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
128 {
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
129 return $this->renderSection($view, 'row', $variables);
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
130 }
131
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
132 /**
133 * Renders the label of the given view.
134 *
135 * @param FormView $view The view for which to render the label
136 * @param string $label The label
137 * @param array $variables Additional variables passed to the template
138 *
139 * @return string The html markup
140 */
657e00a @stloyd [Form] Added missing feature for adding attributes to an field label
stloyd authored
141 public function label(FormView $view, $label = null, array $variables = array())
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
142 {
657e00a @stloyd [Form] Added missing feature for adding attributes to an field label
stloyd authored
143 if ($label !== null) {
144 $variables += array('label' => $label);
145 }
146
147 return $this->renderSection($view, 'label', $variables);
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
148 }
149
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
150 /**
151 * Renders the errors of the given view.
152 *
153 * @param FormView $view The view to render the errors for
154 *
155 * @return string The html markup
156 */
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
157 public function errors(FormView $view)
c43d690 @weaverryan [Form] Adding a row() PHP helper equivalent to the Twig form_row() for o...
weaverryan authored
158 {
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
159 return $this->renderSection($view, 'errors');
c43d690 @weaverryan [Form] Adding a row() PHP helper equivalent to the Twig form_row() for o...
weaverryan authored
160 }
161
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
162 /**
163 * Renders views which have not already been rendered.
164 *
165 * @param FormView $view The parent view
166 * @param array $variables An array of variables
167 *
168 * @return string The html markup
169 */
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
170 public function rest(FormView $view, array $variables = array())
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
171 {
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
172 return $this->renderSection($view, 'rest', $variables);
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
173 }
174
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
175 /**
176 * Renders a template.
177 *
178 * 1. This function first looks for a block named "_<view id>_<section>",
179 * 2. if such a block is not found the function will look for a block named
180 * "<type name>_<section>",
181 * 3. the type name is recursively replaced by the parent type name until a
182 * corresponding block is found
183 *
184 * @param FormView $view The form view
185 * @param string $section The section to render (i.e. 'row', 'widget', 'label', ...)
186 * @param array $variables Additional variables
187 *
188 * @return string The html markup
189 *
190 * @throws FormException if no template block exists to render the given section of the view
191 */
13a9cf7 @webmozart [Form] Renamed TemplateContext to FormView
webmozart authored
192 protected function renderSection(FormView $view, $section, array $variables = array())
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
193 {
de24195 @vicb [Form] Never render a view again
vicb authored
194 $mainTemplate = in_array($section, array('row', 'widget'));
195 if ($mainTemplate && $view->isRendered()) {
196
197 return '';
198 }
199
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
200 $template = null;
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
201
202 $custom = '_'.$view->get('proto_id', $view->get('id'));
203 $rendering = $custom.$section;
a259d44 @webmozart [Form] Added tests for blocks/templates in the format _<ID>_(widget|row|...
webmozart authored
204
a7356b4 @vicb [Form] Optimize rendering
vicb authored
205 if (isset($this->varStack[$rendering])) {
206 $typeIndex = $this->varStack[$rendering]['typeIndex'] - 1;
207 $types = $this->varStack[$rendering]['types'];
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
208 $variables = array_replace_recursive($this->varStack[$rendering]['variables'], $variables);
a7356b4 @vicb [Form] Optimize rendering
vicb authored
209 } else {
210 $types = $view->get('types');
211 $types[] = $custom;
212 $typeIndex = count($types) - 1;
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
213 $variables = array_replace_recursive($view->all(), $variables);
214 $this->varStack[$rendering]['types'] = $types;
a7356b4 @vicb [Form] Optimize rendering
vicb authored
215 }
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
216
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
217 $this->varStack[$rendering]['variables'] = $variables;
218
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
219 do {
c22a6bb @vicb [Form] Fix the exception message when no block is found while rendering
vicb authored
220 $types[$typeIndex] .= '_'.$section;
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
221 $template = $this->lookupTemplate($view, $types[$typeIndex]);
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
222
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
223 if ($template) {
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
224
a7356b4 @vicb [Form] Optimize rendering
vicb authored
225 $this->varStack[$rendering]['typeIndex'] = $typeIndex;
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
226
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
227 $this->context[] = array(
228 'variables' => $variables,
229 'view' => $view,
230 );
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
231
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
232 $html = $this->engine->render($template, $variables);
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
233
234 array_pop($this->context);
a7356b4 @vicb [Form] Optimize rendering
vicb authored
235 unset($this->varStack[$rendering]);
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
236
8c59b3c @vicb [Order] Make Form::types and FormView::types use the same order (Parent ...
vicb authored
237 if ($mainTemplate) {
238 $view->setRendered();
239 }
de24195 @vicb [Form] Never render a view again
vicb authored
240
8c59b3c @vicb [Order] Make Form::types and FormView::types use the same order (Parent ...
vicb authored
241 return $html;
242 }
a7356b4 @vicb [Form] Optimize rendering
vicb authored
243 } while (--$typeIndex >= 0);
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
244
c22a6bb @vicb [Form] Fix the exception message when no block is found while rendering
vicb authored
245 throw new FormException(sprintf(
246 'Unable to render the form as none of the following blocks exist: "%s".',
247 implode('", "', array_reverse($types))
248 ));
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
249 }
250
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
251 /**
252 * Render a block from a form element.
253 *
254 * @param string $name
255 * @param array $variables Additional variables (those would override the current context)
256 *
257 * @throws FormException if the block is not found
258 * @throws FormException if the method is called out of a form element (no context)
259 */
260 public function renderBlock($name, $variables = array())
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
261 {
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
262 if (0 == count($this->context)) {
263 throw new FormException(sprintf('This method should only be called while rendering a form element.', $name));
264 }
b0a6506 @webmozart [Form] Fixed variable scope when entering nested form helpers
webmozart authored
265
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
266 $context = end($this->context);
267
268 $template = $this->lookupTemplate($context['view'], $name);
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
269
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
270 if (false === $template) {
271 throw new FormException(sprintf('No block "%s" found while rendering the form.', $name));
272 }
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
273
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
274 $variables = array_replace_recursive($context['variables'], $variables);
bf13576 @webmozart [FrameworkBundle] Added test coverage for FormHelper and fixed various r...
webmozart authored
275
65c41c4 @vicb [Form][FrameworkBundle] Make FormHelper::renderSection() recursively cal...
vicb authored
276 return $this->engine->render($template, $variables);
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
277 }
278
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
279 public function getName()
280 {
281 return 'form';
282 }
283
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
284 /**
285 * Returns the name of the template to use to render the block
286 *
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
287 * @param FormView $view The form view
288 * @param string $block The name of the block
e0f307c @vicb [FrameworkBundle][Form] Add some phpDoc for the FormHelper class
vicb authored
289 *
290 * @return string|Boolean The template logical name or false when no template is found
291 */
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
292 protected function lookupTemplate(FormView $view, $block)
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
293 {
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
294 $file = $block.'.html.php';
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
295 $id = $view->get('id');
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
296
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
297 if (!isset($this->templates[$id][$block])) {
298 $template = false;
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
299
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
300 $themes = $view->hasParent() ? array() : $this->resources;
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
301
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
302 if (isset($this->themes[$id])) {
303 $themes = array_merge($themes, $this->themes[$id]);
304 }
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
305
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
306 for ($i = count($themes) - 1; $i >= 0; --$i) {
307 if ($this->engine->exists($templateName = $themes[$i].':'.$file)) {
308 $template = $templateName;
309 break;
310 }
311 }
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
312
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
313 if (false === $template && $view->hasParent()) {
314 $template = $this->lookupTemplate($view->getParent(), $block);
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
315 }
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
316
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
317 $this->templates[$id][$block] = $template;
673e3a6 @vicb [Form][FrameworkBundle] PHP theming
vicb authored
318 }
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
319
412d723 @vicb [FrameworkBundle][Form] Adding a cache to FormHelper::lookupTemplate()
vicb authored
320 return $this->templates[$id][$block];
94aae9c @fabpot [Form] reverted the templating part to be similar to what we have today
fabpot authored
321 }
92b136b @webmozart [Form][FrameworkBundle][TwigBundle] Refactored the PHP and Twig templati...
webmozart authored
322 }
Something went wrong with that request. Please try again.