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