Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4: */
   3  // +----------------------------------------------------------------------+
   4  // | PHP version 4.0                                                      |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1997-2003 The PHP Group                                |
   7  // +----------------------------------------------------------------------+
   8  // | This source file is subject to version 2.0 of the PHP license,       |
   9  // | that is bundled with this package in the file LICENSE, and is        |
  10  // | available at through the world-wide-web at                           |
  11  // | http://www.php.net/license/2_02.txt.                                 |
  12  // | If you did not receive a copy of the PHP license and are unable to   |
  13  // | obtain it through the world-wide-web, please send a note to          |
  14  // | license@php.net so we can mail you a copy immediately.               |
  15  // +----------------------------------------------------------------------+
  16  // | Authors: Alexey Borzov <borz_off@cs.msu.su>                          |
  17  // |          Adam Daniel <adaniel1@eesus.jnj.com>                        |
  18  // |          Bertrand Mansion <bmansion@mamasam.com>                     |
  19  // +----------------------------------------------------------------------+
  20  //
  21  // $Id$
  22  
  23  require_once('HTML/QuickForm/Renderer.php');
  24  
  25  /**
  26   * A concrete renderer for HTML_QuickForm,
  27   * based on QuickForm 2.x built-in one
  28   * 
  29   * @access public
  30   */
  31  class HTML_QuickForm_Renderer_Default extends HTML_QuickForm_Renderer
  32  {
  33     /**
  34      * The HTML of the form  
  35      * @var      string
  36      * @access   private
  37      */
  38      var $_html;
  39  
  40     /**
  41      * Header Template string
  42      * @var      string
  43      * @access   private
  44      */
  45      var $_headerTemplate = 
  46          "\n\t<tr>\n\t\t<td style=\"white-space: nowrap; background-color: #CCCCCC;\" align=\"left\" valign=\"top\" colspan=\"2\"><b>{header}</b></td>\n\t</tr>";
  47  
  48     /**
  49      * Element template string
  50      * @var      string
  51      * @access   private
  52      */
  53      var $_elementTemplate = 
  54          "\n\t<tr>\n\t\t<td align=\"right\" valign=\"top\"><!-- BEGIN required --><span style=\"color: #ff0000\">*</span><!-- END required --><b>{label}</b></td>\n\t\t<td valign=\"top\" align=\"left\"><!-- BEGIN error --><span style=\"color: #ff0000\">{error}</span><br /><!-- END error -->\t{element}</td>\n\t</tr>";
  55  
  56     /**
  57      * Form template string
  58      * @var      string
  59      * @access   private
  60      */
  61      var $_formTemplate = 
  62          "\n<form{attributes}>\n<div>\n{hidden}<table border=\"0\">\n{content}\n</table>\n</div>\n</form>";
  63  
  64     /**
  65      * Required Note template string
  66      * @var      string
  67      * @access   private
  68      */
  69      var $_requiredNoteTemplate = 
  70          "\n\t<tr>\n\t\t<td></td>\n\t<td align=\"left\" valign=\"top\">{requiredNote}</td>\n\t</tr>";
  71  
  72     /**
  73      * Array containing the templates for customised elements
  74      * @var      array
  75      * @access   private
  76      */
  77      var $_templates = array();
  78  
  79     /**
  80      * Array containing the templates for group wraps.
  81      * 
  82      * These templates are wrapped around group elements and groups' own
  83      * templates wrap around them. This is set by setGroupTemplate().
  84      * 
  85      * @var      array
  86      * @access   private
  87      */
  88      var $_groupWraps = array();
  89  
  90     /**
  91      * Array containing the templates for elements within groups
  92      * @var      array
  93      * @access   private
  94      */
  95      var $_groupTemplates = array();
  96  
  97     /**
  98      * True if we are inside a group 
  99      * @var      bool
 100      * @access   private
 101      */
 102      var $_inGroup = false;
 103  
 104     /**
 105      * Array with HTML generated for group elements
 106      * @var      array
 107      * @access   private
 108      */
 109      var $_groupElements = array();
 110  
 111     /**
 112      * Template for an element inside a group
 113      * @var      string
 114      * @access   private
 115      */
 116      var $_groupElementTemplate = '';
 117  
 118     /**
 119      * HTML that wraps around the group elements
 120      * @var      string
 121      * @access   private
 122      */
 123      var $_groupWrap = '';
 124  
 125     /**
 126      * HTML for the current group
 127      * @var      string
 128      * @access   private
 129      */
 130      var $_groupTemplate = '';
 131      
 132     /**
 133      * Collected HTML of the hidden fields
 134      * @var      string
 135      * @access   private
 136      */
 137      var $_hiddenHtml = '';
 138  
 139     /**
 140      * Constructor
 141      *
 142      * @access public
 143      */
 144      public function __construct() {
 145          parent::__construct();
 146      } // end constructor
 147  
 148      /**
 149       * Old syntax of class constructor. Deprecated in PHP7.
 150       *
 151       * @deprecated since Moodle 3.1
 152       */
 153      public function HTML_QuickForm_Renderer_Default() {
 154          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
 155          self::__construct();
 156      } // end constructor
 157  
 158     /**
 159      * returns the HTML generated for the form
 160      *
 161      * @access public
 162      * @return string
 163      */
 164      function toHtml()
 165      {
 166          // _hiddenHtml is cleared in finishForm(), so this only matters when
 167          // finishForm() was not called (e.g. group::toHtml(), bug #3511)
 168          return $this->_hiddenHtml . $this->_html;
 169      } // end func toHtml
 170      
 171     /**
 172      * Called when visiting a form, before processing any form elements
 173      *
 174      * @param    object      An HTML_QuickForm object being visited
 175      * @access   public
 176      * @return   void
 177      */
 178      function startForm(&$form)
 179      {
 180          $this->_html = '';
 181          $this->_hiddenHtml = '';
 182      } // end func startForm
 183  
 184     /**
 185      * Called when visiting a form, after processing all form elements
 186      * Adds required note, form attributes, validation javascript and form content.
 187      * 
 188      * @param    object      An HTML_QuickForm object being visited
 189      * @access   public
 190      * @return   void
 191      */
 192      function finishForm(&$form)
 193      {
 194          // add a required note, if one is needed
 195          if (!empty($form->_required) && !$form->_freezeAll) {
 196              $this->_html .= str_replace('{requiredNote}', $form->getRequiredNote(), $this->_requiredNoteTemplate);
 197          }
 198          // add form attributes and content
 199          $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate);
 200          if (strpos($this->_formTemplate, '{hidden}')) {
 201              $html = str_replace('{hidden}', $this->_hiddenHtml, $html);
 202          } else {
 203              $this->_html .= $this->_hiddenHtml;
 204          }
 205          $this->_hiddenHtml = '';
 206          $this->_html = str_replace('{content}', $this->_html, $html);
 207          // add a validation script
 208          if ('' != ($script = $form->getValidationScript())) {
 209              $this->_html = $script . "\n" . $this->_html;
 210          }
 211      } // end func finishForm
 212        
 213     /**
 214      * Called when visiting a header element
 215      *
 216      * @param    object     An HTML_QuickForm_header element being visited
 217      * @access   public
 218      * @return   void
 219      */
 220      function renderHeader(&$header)
 221      {
 222          $name = $header->getName();
 223          if (!empty($name) && isset($this->_templates[$name])) {
 224              $this->_html .= str_replace('{header}', $header->toHtml(), $this->_templates[$name]);
 225          } else {
 226              $this->_html .= str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
 227          }
 228      } // end func renderHeader
 229  
 230     /**
 231      * Helper method for renderElement
 232      *
 233      * @param    string      Element name
 234      * @param    mixed       Element label (if using an array of labels, you should set the appropriate template)
 235      * @param    bool        Whether an element is required
 236      * @param    string      Error message associated with the element
 237      * @access   private
 238      * @see      renderElement()
 239      * @return   string      Html for element
 240      */
 241      function _prepareTemplate($name, $label, $required, $error)
 242      {
 243          if (is_array($label)) {
 244              $nameLabel = array_shift($label);
 245          } else {
 246              $nameLabel = $label;
 247          }
 248          if (isset($this->_templates[$name])) {
 249              $html = str_replace('{label}', $nameLabel, $this->_templates[$name]);
 250          } else {
 251              $html = str_replace('{label}', $nameLabel, $this->_elementTemplate);
 252          }
 253          if ($required) {
 254              $html = str_replace('<!-- BEGIN required -->', '', $html);
 255              $html = str_replace('<!-- END required -->', '', $html);
 256          } else {
 257              $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->(\s|\S)*<!-- END required -->([ \t\n\r]*)?/iU", '', $html);
 258          }
 259          if (isset($error)) {
 260              $html = str_replace('{error}', $error, $html);
 261              $html = str_replace('<!-- BEGIN error -->', '', $html);
 262              $html = str_replace('<!-- END error -->', '', $html);
 263          } else {
 264              $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN error -->(\s|\S)*<!-- END error -->([ \t\n\r]*)?/iU", '', $html);
 265          }
 266          if (is_array($label)) {
 267              foreach($label as $key => $text) {
 268                  $key  = is_int($key)? $key + 2: $key;
 269                  $html = str_replace("{label_{$key}}", $text, $html);
 270                  $html = str_replace("<!-- BEGIN label_{$key} -->", '', $html);
 271                  $html = str_replace("<!-- END label_{$key} -->", '', $html);
 272              }
 273          }
 274          if (strpos($html, '{label_')) {
 275              $html = preg_replace('/\s*<!-- BEGIN label_(\S+) -->.*<!-- END label_\1 -->\s*/i', '', $html);
 276          }
 277          return $html;
 278      } // end func _prepareTemplate
 279  
 280     /**
 281      * Renders an element Html
 282      * Called when visiting an element
 283      *
 284      * @param object     An HTML_QuickForm_element object being visited
 285      * @param bool       Whether an element is required
 286      * @param string     An error message associated with an element
 287      * @access public
 288      * @return void
 289      */
 290      function renderElement(&$element, $required, $error)
 291      {
 292          if (!$this->_inGroup) {
 293              $html = $this->_prepareTemplate($element->getName(), $element->getLabel(), $required, $error);
 294              $this->_html .= str_replace('{element}', $element->toHtml(), $html);
 295  
 296          } elseif (!empty($this->_groupElementTemplate)) {
 297              $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate);
 298              if ($required) {
 299                  $html = str_replace('<!-- BEGIN required -->', '', $html);
 300                  $html = str_replace('<!-- END required -->', '', $html);
 301              } else {
 302                  $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->(\s|\S)*<!-- END required -->([ \t\n\r]*)?/iU", '', $html);
 303              }
 304              $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html);
 305  
 306          } else {
 307              $this->_groupElements[] = $element->toHtml();
 308          }
 309      } // end func renderElement
 310     
 311     /**
 312      * Renders an hidden element
 313      * Called when visiting a hidden element
 314      * 
 315      * @param object     An HTML_QuickForm_hidden object being visited
 316      * @access public
 317      * @return void
 318      */
 319      function renderHidden(&$element)
 320      {
 321          $this->_hiddenHtml .= $element->toHtml() . "\n";
 322      } // end func renderHidden
 323  
 324     /**
 325      * Called when visiting a raw HTML/text pseudo-element
 326      * 
 327      * @param  object     An HTML_QuickForm_html element being visited
 328      * @access public
 329      * @return void
 330      */
 331      function renderHtml(&$data)
 332      {
 333          $this->_html .= $data->toHtml();
 334      } // end func renderHtml
 335  
 336     /**
 337      * Called when visiting a group, before processing any group elements
 338      *
 339      * @param object     An HTML_QuickForm_group object being visited
 340      * @param bool       Whether a group is required
 341      * @param string     An error message associated with a group
 342      * @access public
 343      * @return void
 344      */
 345      function startGroup(&$group, $required, $error)
 346      {
 347          $name = $group->getName();
 348          $this->_groupTemplate        = $this->_prepareTemplate($name, $group->getLabel(), $required, $error);
 349          $this->_groupElementTemplate = empty($this->_groupTemplates[$name])? '': $this->_groupTemplates[$name];
 350          $this->_groupWrap            = empty($this->_groupWraps[$name])? '': $this->_groupWraps[$name];
 351          $this->_groupElements        = array();
 352          $this->_inGroup              = true;
 353      } // end func startGroup
 354  
 355     /**
 356      * Called when visiting a group, after processing all group elements
 357      *
 358      * @param    object      An HTML_QuickForm_group object being visited
 359      * @access   public
 360      * @return   void
 361      */
 362      function finishGroup(&$group)
 363      {
 364          $separator = $group->_separator;
 365          if (is_array($separator)) {
 366              $count = count($separator);
 367              $html  = '';
 368              for ($i = 0; $i < count($this->_groupElements); $i++) {
 369                  $html .= (0 == $i? '': $separator[($i - 1) % $count]) . $this->_groupElements[$i];
 370              }
 371          } else {
 372              if (is_null($separator)) {
 373                  $separator = '&nbsp;';
 374              }
 375              $html = implode((string)$separator, $this->_groupElements);
 376          }
 377          if (!empty($this->_groupWrap)) {
 378              $html = str_replace('{content}', $html, $this->_groupWrap);
 379          }
 380          $this->_html   .= str_replace('{element}', $html, $this->_groupTemplate);
 381          $this->_inGroup = false;
 382      } // end func finishGroup
 383  
 384      /**
 385       * Sets element template 
 386       *
 387       * @param       string      The HTML surrounding an element 
 388       * @param       string      (optional) Name of the element to apply template for
 389       * @access      public
 390       * @return      void
 391       */
 392      function setElementTemplate($html, $element = null)
 393      {
 394          if (is_null($element)) {
 395              $this->_elementTemplate = $html;
 396          } else {
 397              $this->_templates[$element] = $html;
 398          }
 399      } // end func setElementTemplate
 400  
 401  
 402      /**
 403       * Sets template for a group wrapper 
 404       * 
 405       * This template is contained within a group-as-element template 
 406       * set via setTemplate() and contains group's element templates, set
 407       * via setGroupElementTemplate()
 408       *
 409       * @param       string      The HTML surrounding group elements
 410       * @param       string      Name of the group to apply template for
 411       * @access      public
 412       * @return      void
 413       */
 414      function setGroupTemplate($html, $group)
 415      {
 416          $this->_groupWraps[$group] = $html;
 417      } // end func setGroupTemplate
 418  
 419      /**
 420       * Sets element template for elements within a group
 421       *
 422       * @param       string      The HTML surrounding an element 
 423       * @param       string      Name of the group to apply template for
 424       * @access      public
 425       * @return      void
 426       */
 427      function setGroupElementTemplate($html, $group)
 428      {
 429          $this->_groupTemplates[$group] = $html;
 430      } // end func setGroupElementTemplate
 431  
 432      /**
 433       * Sets header template
 434       *
 435       * @param       string      The HTML surrounding the header 
 436       * @access      public
 437       * @return      void
 438       */
 439      function setHeaderTemplate($html)
 440      {
 441          $this->_headerTemplate = $html;
 442      } // end func setHeaderTemplate
 443  
 444      /**
 445       * Sets form template 
 446       *
 447       * @param     string    The HTML surrounding the form tags 
 448       * @access    public
 449       * @return    void
 450       */
 451      function setFormTemplate($html)
 452      {
 453          $this->_formTemplate = $html;
 454      } // end func setFormTemplate
 455  
 456      /**
 457       * Sets the note indicating required fields template
 458       *
 459       * @param       string      The HTML surrounding the required note 
 460       * @access      public
 461       * @return      void
 462       */
 463      function setRequiredNoteTemplate($html)
 464      {
 465          $this->_requiredNoteTemplate = $html;
 466      } // end func setRequiredNoteTemplate
 467  
 468      /**
 469       * Clears all the HTML out of the templates that surround notes, elements, etc.
 470       * Useful when you want to use addData() to create a completely custom form look
 471       *
 472       * @access  public
 473       * @return  void
 474       */
 475      function clearAllTemplates()
 476      {
 477          $this->setElementTemplate('{element}');
 478          $this->setFormTemplate("\n\t<form{attributes}>{content}\n\t</form>\n");
 479          $this->setRequiredNoteTemplate('');
 480          $this->_templates = array();
 481      } // end func clearAllTemplates
 482  } // end class HTML_QuickForm_Renderer_Default
 483  ?>