2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5 * A static renderer for HTML_QuickForm compatible
6 * with HTML_Template_IT and HTML_Template_Sigma.
10 * LICENSE: This source file is subject to version 3.01 of the PHP license
11 * that is available through the world-wide-web at the following URI:
12 * http://www.php.net/license/3_01.txt If you did not receive a copy of
13 * the PHP License and are unable to obtain it through the web, please
14 * send a note to license@php.net so we can mail you a copy immediately.
17 * @package HTML_QuickForm
18 * @author Bertrand Mansion <bmansion@mamasam.com>
19 * @copyright 2001-2011 The PHP Group
20 * @license http://www.php.net/license/3_01.txt PHP License 3.01
22 * @link http://pear.php.net/package/HTML_QuickForm
26 * An abstract base class for QuickForm renderers
28 require_once 'HTML/QuickForm/Renderer.php';
31 * A static renderer for HTML_QuickForm compatible
32 * with HTML_Template_IT and HTML_Template_Sigma.
34 * As opposed to the dynamic renderer, this renderer needs
35 * every elements and labels in the form to be specified by
36 * placeholders at the position you want them to be displayed.
39 * @package HTML_QuickForm
40 * @author Bertrand Mansion <bmansion@mamasam.com>
41 * @version Release: 3.2.16
44 class HTML_QuickForm_Renderer_ITStatic extends HTML_QuickForm_Renderer
50 * An HTML_Template_IT or some other API compatible Template instance
59 var $_formName = 'form';
62 * The errors that were not shown near concrete fields go here
65 var $_errors = array();
68 * Show the block with required note?
71 var $_showRequired = false;
74 * Which group are we currently parsing ?
80 * Index of the element in its group
83 var $_elementIndex = 0;
86 * If elements have been added with the same name
89 var $_duplicateElements = array();
92 * How to handle the required tag for required fields
95 var $_required = '{label}<font size="1" color="red">*</font>';
98 * How to handle error messages in form validation
101 var $_error = '<font color="red">{error}</font><br />{html}';
104 * Collected HTML for hidden elements, if needed
113 * @param HTML_Template_IT|HTML_Template_Sigma Template object to use
115 function HTML_QuickForm_Renderer_ITStatic(&$tpl)
117 $this->HTML_QuickForm_Renderer();
122 * Called when visiting a form, before processing any form elements
124 * @param HTML_QuickForm form object being visited
128 function startForm(&$form)
130 $this->_formName = $form->getAttribute('id');
132 if (count($form->_duplicateIndex) > 0) {
133 // Take care of duplicate elements
134 foreach ($form->_duplicateIndex as $elementName => $indexes) {
135 $this->_duplicateElements[$elementName] = 0;
138 } // end func startForm
141 * Called when visiting a form, after processing all form elements
143 * @param HTML_QuickForm form object being visited
147 function finishForm(&$form)
149 // display errors above form
150 if (!empty($this->_errors) && $this->_tpl->blockExists($this->_formName.'_error_loop')) {
151 foreach ($this->_errors as $error) {
152 $this->_tpl->setVariable($this->_formName.'_error', $error);
153 $this->_tpl->parse($this->_formName.'_error_loop');
156 // show required note
157 if ($this->_showRequired) {
158 $this->_tpl->setVariable($this->_formName.'_required_note', $form->getRequiredNote());
160 // add hidden elements, if collected
161 if (!empty($this->_hidden)) {
162 $this->_tpl->setVariable($this->_formName . '_hidden', $this->_hidden);
164 // assign form attributes
165 $this->_tpl->setVariable($this->_formName.'_attributes', $form->getAttributes(true));
166 // assign javascript validation rules
167 $this->_tpl->setVariable($this->_formName.'_javascript', $form->getValidationScript());
168 } // end func finishForm
171 * Called when visiting a header element
173 * @param HTML_QuickForm_header header element being visited
177 function renderHeader(&$header)
179 $name = $header->getName();
180 $varName = $this->_formName.'_header';
183 if (!empty($name) && $this->_tpl->placeHolderExists($this->_formName.'_header_'.$name)) {
184 $varName = $this->_formName.'_header_'.$name;
186 $this->_tpl->setVariable($varName, $header->toHtml());
187 } // end func renderHeader
190 * Called when visiting an element
192 * @param HTML_QuickForm_element form element being visited
193 * @param bool Whether an element is required
194 * @param string An error message associated with an element
198 function renderElement(&$element, $required, $error)
200 $name = $element->getName();
202 // are we inside a group?
203 if (!empty($this->_inGroup)) {
204 $varName = $this->_formName.'_'.str_replace(array('[', ']'), '_', $name);
205 if (substr($varName, -2) == '__') {
206 // element name is of type : group[]
207 $varName = $this->_inGroup.'_'.$this->_elementIndex.'_';
208 $this->_elementIndex++;
210 if ($varName != $this->_inGroup) {
211 $varName .= '_' == substr($varName, -1)? '': '_';
212 // element name is of type : group[name]
213 $label = $element->getLabel();
214 $html = $element->toHtml();
216 if ($required && !$element->isFrozen()) {
217 $this->_renderRequired($label, $html);
218 $this->_showRequired = true;
220 if (!empty($label)) {
221 if (is_array($label)) {
222 foreach ($label as $key => $value) {
223 $this->_tpl->setVariable($varName.'label_'.$key, $value);
226 $this->_tpl->setVariable($varName.'label', $label);
229 $this->_tpl->setVariable($varName.'html', $html);
234 $name = str_replace(array('[', ']'), array('_', ''), $name);
236 if (isset($this->_duplicateElements[$name])) {
237 // Element is a duplicate
238 $varName = $this->_formName.'_'.$name.'_'.$this->_duplicateElements[$name];
239 $this->_duplicateElements[$name]++;
241 $varName = $this->_formName.'_'.$name;
244 $label = $element->getLabel();
245 $html = $element->toHtml();
248 $this->_showRequired = true;
249 $this->_renderRequired($label, $html);
251 if (!empty($error)) {
252 $this->_renderError($label, $html, $error);
254 if (is_array($label)) {
255 foreach ($label as $key => $value) {
256 $this->_tpl->setVariable($varName.'_label_'.$key, $value);
259 $this->_tpl->setVariable($varName.'_label', $label);
261 $this->_tpl->setVariable($varName.'_html', $html);
263 } // end func renderElement
266 * Called when visiting a hidden element
268 * @param HTML_QuickForm_element hidden element being visited
272 function renderHidden(&$element)
274 if ($this->_tpl->placeholderExists($this->_formName . '_hidden')) {
275 $this->_hidden .= $element->toHtml();
277 $name = $element->getName();
278 $name = str_replace(array('[', ']'), array('_', ''), $name);
279 $this->_tpl->setVariable($this->_formName.'_'.$name.'_html', $element->toHtml());
281 } // end func renderHidden
284 * Called when visiting a group, before processing any group elements
286 * @param HTML_QuickForm_group group being visited
287 * @param bool Whether a group is required
288 * @param string An error message associated with a group
292 function startGroup(&$group, $required, $error)
294 $name = $group->getName();
295 $varName = $this->_formName.'_'.$name;
297 $this->_elementIndex = 0;
299 $html = $this->_tpl->placeholderExists($varName.'_html') ? $group->toHtml() : '';
300 $label = $group->getLabel();
303 $this->_renderRequired($label, $html);
305 if (!empty($error)) {
306 $this->_renderError($label, $html, $error);
309 $this->_tpl->setVariable($varName.'_html', $html);
311 // Uses error blocks to set the special groups layout error
312 // <!-- BEGIN form_group_error -->{form_group_error}<!-- END form_group_error -->
313 if (!empty($error)) {
314 if ($this->_tpl->placeholderExists($varName.'_error')) {
315 if ($this->_tpl->blockExists($this->_formName . '_error_block')) {
316 $this->_tpl->setVariable($this->_formName . '_error', $error);
317 $error = $this->_getTplBlock($this->_formName . '_error_block');
318 } elseif (strpos($this->_error, '{html}') !== false || strpos($this->_error, '{label}') !== false) {
319 $error = str_replace('{error}', $error, $this->_error);
322 $this->_tpl->setVariable($varName . '_error', $error);
323 array_pop($this->_errors);
326 if (is_array($label)) {
327 foreach ($label as $key => $value) {
328 $this->_tpl->setVariable($varName.'_label_'.$key, $value);
331 $this->_tpl->setVariable($varName.'_label', $label);
333 $this->_inGroup = $varName;
334 } // end func startGroup
337 * Called when visiting a group, after processing all group elements
339 * @param HTML_QuickForm_group group being visited
343 function finishGroup(&$group)
345 $this->_inGroup = '';
346 } // end func finishGroup
349 * Sets the way required elements are rendered
351 * You can use {label} or {html} placeholders to let the renderer know where
352 * where the element label or the element html are positionned according to the
353 * required tag. They will be replaced accordingly with the right value.
355 * <font color="red">*</font>{label}
356 * will put a red star in front of the label if the element is required.
358 * @param string The required element template
362 function setRequiredTemplate($template)
364 $this->_required = $template;
365 } // end func setRequiredTemplate
368 * Sets the way elements with validation errors are rendered
370 * You can use {label} or {html} placeholders to let the renderer know where
371 * where the element label or the element html are positionned according to the
372 * error message. They will be replaced accordingly with the right value.
373 * The error message will replace the {error} place holder.
375 * <font color="red">{error}</font><br />{html}
376 * will put the error message in red on top of the element html.
378 * If you want all error messages to be output in the main error block, do not specify
379 * {html} nor {label}.
381 * Groups can have special layouts. With this kind of groups, the renderer will need
382 * to know where to place the error message. In this case, use error blocks like:
383 * <!-- BEGIN form_group_error -->{form_group_error}<!-- END form_group_error -->
384 * where you want the error message to appear in the form.
386 * @param string The element error template
390 function setErrorTemplate($template)
392 $this->_error = $template;
393 } // end func setErrorTemplate
396 * Called when an element is required
398 * This method will add the required tag to the element label and/or the element html
399 * such as defined with the method setRequiredTemplate
401 * @param string The element label
402 * @param string The element html rendering
403 * @see setRequiredTemplate()
407 function _renderRequired(&$label, &$html)
409 if ($this->_tpl->blockExists($tplBlock = $this->_formName . '_required_block')) {
410 if (!empty($label) && $this->_tpl->placeholderExists($this->_formName . '_label', $tplBlock)) {
411 $this->_tpl->setVariable($this->_formName . '_label', is_array($label)? $label[0]: $label);
412 if (is_array($label)) {
413 $label[0] = $this->_getTplBlock($tplBlock);
415 $label = $this->_getTplBlock($tplBlock);
418 if (!empty($html) && $this->_tpl->placeholderExists($this->_formName . '_html', $tplBlock)) {
419 $this->_tpl->setVariable($this->_formName . '_html', $html);
420 $html = $this->_getTplBlock($tplBlock);
423 if (!empty($label) && strpos($this->_required, '{label}') !== false) {
424 if (is_array($label)) {
425 $label[0] = str_replace('{label}', $label[0], $this->_required);
427 $label = str_replace('{label}', $label, $this->_required);
430 if (!empty($html) && strpos($this->_required, '{html}') !== false) {
431 $html = str_replace('{html}', $html, $this->_required);
434 } // end func _renderRequired
437 * Called when an element has a validation error
439 * This method will add the error message to the element label or the element html
440 * such as defined with the method setErrorTemplate. If the error placeholder is not found
441 * in the template, the error will be displayed in the form error block.
443 * @param string The element label
444 * @param string The element html rendering
445 * @param string The element error
446 * @see setErrorTemplate()
450 function _renderError(&$label, &$html, $error)
452 if ($this->_tpl->blockExists($tplBlock = $this->_formName . '_error_block')) {
453 $this->_tpl->setVariable($this->_formName . '_error', $error);
454 if (!empty($label) && $this->_tpl->placeholderExists($this->_formName . '_label', $tplBlock)) {
455 $this->_tpl->setVariable($this->_formName . '_label', is_array($label)? $label[0]: $label);
456 if (is_array($label)) {
457 $label[0] = $this->_getTplBlock($tplBlock);
459 $label = $this->_getTplBlock($tplBlock);
461 } elseif (!empty($html) && $this->_tpl->placeholderExists($this->_formName . '_html', $tplBlock)) {
462 $this->_tpl->setVariable($this->_formName . '_html', $html);
463 $html = $this->_getTplBlock($tplBlock);
465 // clean up after ourselves
466 $this->_tpl->setVariable($this->_formName . '_error', null);
467 } elseif (!empty($label) && strpos($this->_error, '{label}') !== false) {
468 if (is_array($label)) {
469 $label[0] = str_replace(array('{label}', '{error}'), array($label[0], $error), $this->_error);
471 $label = str_replace(array('{label}', '{error}'), array($label, $error), $this->_error);
473 } elseif (!empty($html) && strpos($this->_error, '{html}') !== false) {
474 $html = str_replace(array('{html}', '{error}'), array($html, $error), $this->_error);
476 $this->_errors[] = $error;
478 }// end func _renderError
482 * Returns the block's contents
484 * The method is needed because ITX and Sigma implement clearing
485 * the block contents on get() a bit differently
487 * @param string Block name
488 * @return string Block contents
490 function _getTplBlock($block)
492 $this->_tpl->parse($block);
493 if (is_a($this->_tpl, 'html_template_sigma')) {
494 $ret = $this->_tpl->get($block, true);
496 $oldClear = $this->_tpl->clearCache;
497 $this->_tpl->clearCache = true;
498 $ret = $this->_tpl->get($block);
499 $this->_tpl->clearCache = $oldClear;
503 } // end class HTML_QuickForm_Renderer_ITStatic