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.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 403]

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4: */
   3  // +----------------------------------------------------------------------+
   4  // | PHP version 4.0                                                      |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1997, 1998, 1999, 2000, 2001 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: Adam Daniel <adaniel1@eesus.jnj.com>                        |
  17  // |          Bertrand Mansion <bmansion@mamasam.com>                     |
  18  // +----------------------------------------------------------------------+
  19  //
  20  // $Id$
  21  
  22  require_once('HTML/Common.php');
  23  /**
  24   * Static utility methods.
  25   */
  26  require_once('HTML/QuickForm/utils.php');
  27  
  28  /**
  29   * Base class for form elements
  30   * 
  31   * @author       Adam Daniel <adaniel1@eesus.jnj.com>
  32   * @author       Bertrand Mansion <bmansion@mamasam.com>
  33   * @version      1.3
  34   * @since        PHP4.04pl1
  35   * @access       public
  36   * @abstract
  37   */
  38  class HTML_QuickForm_element extends HTML_Common
  39  {
  40      // {{{ properties
  41  
  42      /**
  43       * Label of the field
  44       * @var       string
  45       * @since     1.3
  46       * @access    private
  47       */
  48      var $_label = '';
  49  
  50      /**
  51       * Form element type
  52       * @var       string
  53       * @since     1.0
  54       * @access    private
  55       */
  56      var $_type = '';
  57  
  58      /**
  59       * Flag to tell if element is frozen
  60       * @var       boolean
  61       * @since     1.0
  62       * @access    private
  63       */
  64      var $_flagFrozen = false;
  65  
  66      /**
  67       * Does the element support persistant data when frozen
  68       * @var       boolean
  69       * @since     1.3
  70       * @access    private
  71       */
  72      var $_persistantFreeze = false;
  73      
  74      // }}}
  75      // {{{ constructor
  76      
  77      /**
  78       * Class constructor
  79       * 
  80       * @param    string     Name of the element
  81       * @param    mixed      Label(s) for the element
  82       * @param    mixed      Associative array of tag attributes or HTML attributes name="value" pairs
  83       * @since     1.0
  84       * @access    public
  85       * @return    void
  86       */
  87      public function __construct($elementName=null, $elementLabel=null, $attributes=null) {
  88          parent::__construct($attributes);
  89          if (isset($elementName)) {
  90              $this->setName($elementName);
  91          }
  92          if (isset($elementLabel)) {
  93              $this->setLabel($elementLabel);
  94          }
  95      } //end constructor
  96  
  97      /**
  98       * Old syntax of class constructor. Deprecated in PHP7.
  99       *
 100       * @deprecated since Moodle 3.1
 101       */
 102      public function HTML_QuickForm_element($elementName=null, $elementLabel=null, $attributes=null) {
 103          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
 104          self::__construct($elementName, $elementLabel, $attributes);
 105      }
 106      
 107      // }}}
 108      // {{{ apiVersion()
 109  
 110      /**
 111       * Returns the current API version
 112       *
 113       * @since     1.0
 114       * @access    public
 115       * @return    float
 116       */
 117      function apiVersion()
 118      {
 119          return 2.0;
 120      } // end func apiVersion
 121  
 122      // }}}
 123      // {{{ getType()
 124  
 125      /**
 126       * Returns element type
 127       *
 128       * @since     1.0
 129       * @access    public
 130       * @return    string
 131       */
 132      function getType()
 133      {
 134          return $this->_type;
 135      } // end func getType
 136  
 137      // }}}
 138      // {{{ setName()
 139  
 140      /**
 141       * Sets the input field name
 142       * 
 143       * @param     string    $name   Input field name attribute
 144       * @since     1.0
 145       * @access    public
 146       * @return    void
 147       */
 148      function setName($name)
 149      {
 150          // interface method
 151      } //end func setName
 152      
 153      // }}}
 154      // {{{ getName()
 155  
 156      /**
 157       * Returns the element name
 158       * 
 159       * @since     1.0
 160       * @access    public
 161       * @return    string
 162       */
 163      function getName()
 164      {
 165          // interface method
 166      } //end func getName
 167      
 168      // }}}
 169      // {{{ setValue()
 170  
 171      /**
 172       * Sets the value of the form element
 173       *
 174       * @param     string    $value      Default value of the form element
 175       * @since     1.0
 176       * @access    public
 177       * @return    void
 178       */
 179      function setValue($value)
 180      {
 181          // interface
 182      } // end func setValue
 183  
 184      // }}}
 185      // {{{ getValue()
 186  
 187      /**
 188       * Returns the value of the form element
 189       *
 190       * @since     1.0
 191       * @access    public
 192       * @return    mixed
 193       */
 194      function getValue()
 195      {
 196          // interface
 197          return null;
 198      } // end func getValue
 199      
 200      // }}}
 201      // {{{ freeze()
 202  
 203      /**
 204       * Freeze the element so that only its value is returned
 205       * 
 206       * @access    public
 207       * @return    void
 208       */
 209      function freeze()
 210      {
 211          $this->_flagFrozen = true;
 212      } //end func freeze
 213  
 214      // }}}
 215      // {{{ unfreeze()
 216  
 217     /**
 218      * Unfreezes the element so that it becomes editable
 219      *
 220      * @access public
 221      * @return void
 222      * @since  3.2.4
 223      */
 224      function unfreeze()
 225      {
 226          $this->_flagFrozen = false;
 227      }
 228  
 229      // }}}
 230      // {{{ getFrozenHtml()
 231  
 232      /**
 233       * Returns the value of field without HTML tags
 234       * 
 235       * @since     1.0
 236       * @access    public
 237       * @return    string
 238       */
 239      function getFrozenHtml()
 240      {
 241          $value = $this->getValue();
 242          return ('' != $value? htmlspecialchars($value): '&nbsp;') .
 243                 $this->_getPersistantData();
 244      } //end func getFrozenHtml
 245      
 246      // }}}
 247      // {{{ _getPersistantData()
 248  
 249     /**
 250      * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on
 251      * 
 252      * @access private
 253      * @return string
 254      */
 255      function _getPersistantData()
 256      {
 257          if (!$this->_persistantFreeze) {
 258              return '';
 259          } else {
 260              $id = $this->getAttribute('id');
 261              if (isset($id)) {
 262                  // Id of persistant input is different then the actual input.
 263                  $id = array('id' => $id . '_persistant');
 264              } else {
 265                  $id = array();
 266              }
 267  
 268              return '<input' . $this->_getAttrString(array(
 269                         'type'  => 'hidden',
 270                         'name'  => $this->getName(),
 271                         'value' => $this->getValue()
 272                     ) + $id) . ' />';
 273          }
 274      }
 275  
 276      // }}}
 277      // {{{ isFrozen()
 278  
 279      /**
 280       * Returns whether or not the element is frozen
 281       *
 282       * @since     1.3
 283       * @access    public
 284       * @return    bool
 285       */
 286      function isFrozen()
 287      {
 288          return $this->_flagFrozen;
 289      } // end func isFrozen
 290  
 291      // }}}
 292      // {{{ setPersistantFreeze()
 293  
 294      /**
 295       * Sets wether an element value should be kept in an hidden field
 296       * when the element is frozen or not
 297       * 
 298       * @param     bool    $persistant   True if persistant value
 299       * @since     2.0
 300       * @access    public
 301       * @return    void
 302       */
 303      function setPersistantFreeze($persistant=false)
 304      {
 305          $this->_persistantFreeze = $persistant;
 306      } //end func setPersistantFreeze
 307  
 308      // }}}
 309      // {{{ setLabel()
 310  
 311      /**
 312       * Sets display text for the element
 313       * 
 314       * @param     string    $label  Display text for the element
 315       * @since     1.3
 316       * @access    public
 317       * @return    void
 318       */
 319      function setLabel($label)
 320      {
 321          $this->_label = $label;
 322      } //end func setLabel
 323  
 324      // }}}
 325      // {{{ getLabel()
 326  
 327      /**
 328       * Returns display text for the element
 329       * 
 330       * @since     1.3
 331       * @access    public
 332       * @return    string
 333       */
 334      function getLabel()
 335      {
 336          return $this->_label;
 337      } //end func getLabel
 338  
 339      // }}}
 340      // {{{ _findValue()
 341  
 342      /**
 343       * Tries to find the element value from the values array
 344       * 
 345       * @since     2.7
 346       * @access    private
 347       * @return    mixed
 348       */
 349      function _findValue(&$values)
 350      {
 351          if (empty($values)) {
 352              return null;
 353          }
 354          $elementName = $this->getName() ?? '';
 355          if (isset($values[$elementName])) {
 356              return $values[$elementName];
 357          } elseif (strpos($elementName, '[')) {
 358              $keys = str_replace(
 359                  array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
 360                  $elementName
 361              );
 362              $arrayKeys = explode("']['", $keys);
 363              return HTML_QuickForm_utils::recursiveValue($values, $arrayKeys);
 364          } else {
 365              return null;
 366          }
 367      } //end func _findValue
 368  
 369      // }}}
 370      // {{{ onQuickFormEvent()
 371  
 372      /**
 373       * Called by HTML_QuickForm whenever form event is made on this element
 374       *
 375       * @param     string    $event  Name of event
 376       * @param     mixed     $arg    event arguments
 377       * @param     object    $caller calling object
 378       * @since     1.0
 379       * @access    public
 380       * @return    void
 381       */
 382      function onQuickFormEvent($event, $arg, &$caller)
 383      {
 384          switch ($event) {
 385              case 'createElement':
 386                  static::__construct($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]);
 387                  if ($caller->getAttribute('data-random-ids') && !$this->getAttribute('id')) {
 388                      $this->_generateId();
 389                      $this->updateAttributes(array('id' => $this->getAttribute('id') . '_' . random_string()));
 390                  }
 391                  break;
 392              case 'addElement':
 393                  $this->onQuickFormEvent('createElement', $arg, $caller);
 394                  $this->onQuickFormEvent('updateValue', null, $caller);
 395                  break;
 396              case 'updateValue':
 397                  // constant values override both default and submitted ones
 398                  // default values are overriden by submitted
 399                  $value = $this->_findValue($caller->_constantValues);
 400                  if (null === $value) {
 401                      $value = $this->_findValue($caller->_submitValues);
 402                      if (null === $value) {
 403                          $value = $this->_findValue($caller->_defaultValues);
 404                      }
 405                  }
 406                  if (null !== $value) {
 407                      $this->setValue($value);
 408                  }
 409                  break;
 410              case 'setGroupValue':
 411                  $this->setValue($arg);
 412          }
 413          return true;
 414      } // end func onQuickFormEvent
 415  
 416      // }}}
 417      // {{{ accept()
 418  
 419     /**
 420      * Accepts a renderer
 421      *
 422      * @param object     An HTML_QuickForm_Renderer object
 423      * @param bool       Whether an element is required
 424      * @param string     An error message associated with an element
 425      * @access public
 426      * @return void 
 427      */
 428      function accept(&$renderer, $required=false, $error=null)
 429      {
 430          $renderer->renderElement($this, $required, $error);
 431      } // end func accept
 432  
 433      // }}}
 434      // {{{ _generateId()
 435  
 436     /**
 437      * Automatically generates and assigns an 'id' attribute for the element.
 438      * 
 439      * Currently used to ensure that labels work on radio buttons and
 440      * checkboxes. Per idea of Alexander Radivanovich.
 441      *
 442      * @access private
 443      * @return void 
 444      */
 445      function _generateId() {
 446          if ($this->getAttribute('id')) {
 447              return;
 448          }
 449  
 450          $id = $this->getName() ?? '';
 451          $id = 'id_' . str_replace(array('qf_', '[', ']'), array('', '_', ''), $id);
 452          $id = clean_param($id, PARAM_ALPHANUMEXT);
 453          $this->updateAttributes(array('id' => $id));
 454      }
 455  
 456      // }}}
 457      // {{{ exportValue()
 458  
 459     /**
 460      * Returns a 'safe' element's value
 461      *
 462      * @param  array   array of submitted values to search
 463      * @param  bool    whether to return the value as associative array
 464      * @access public
 465      * @return mixed
 466      */
 467      function exportValue(&$submitValues, $assoc = false)
 468      {
 469          $value = $this->_findValue($submitValues);
 470          if (null === $value) {
 471              $value = $this->getValue();
 472          }
 473          return $this->_prepareValue($value, $assoc);
 474      }
 475      
 476      // }}}
 477      // {{{ _prepareValue()
 478  
 479     /**
 480      * Used by exportValue() to prepare the value for returning
 481      *
 482      * @param  mixed   the value found in exportValue()
 483      * @param  bool    whether to return the value as associative array
 484      * @access private
 485      * @return mixed
 486      */
 487      function _prepareValue($value, $assoc)
 488      {
 489          if (null === $value) {
 490              return null;
 491          } elseif (!$assoc) {
 492              return $value;
 493          } else {
 494              $name = $this->getName();
 495              if (!strpos($name, '[')) {
 496                  return array($name => $value);
 497              } else {
 498                  $keys = str_replace(
 499                      array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
 500                      $name
 501                  );
 502                  $keysArray = explode("']['", $keys);
 503                  return HTML_QuickForm_utils::recursiveBuild($keysArray, $value);
 504              }
 505          }
 506      }
 507      
 508      // }}}
 509  } // end class HTML_QuickForm_element
 510  ?>