Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 311 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/QuickForm/element.php");
  23  
  24  /**
  25   * HTML class for a form element group
  26   *
  27   * @author       Adam Daniel <adaniel1@eesus.jnj.com>
  28   * @author       Bertrand Mansion <bmansion@mamasam.com>
  29   * @version      1.0
  30   * @since        PHP4.04pl1
  31   * @access       public
  32   */
  33  class HTML_QuickForm_group extends HTML_QuickForm_element
  34  {
  35      // {{{ properties
  36  
  37      /**
  38       * Name of the element
  39       * @var       string
  40       * @since     1.0
  41       * @access    private
  42       */
  43      var $_name = '';
  44  
  45      /**
  46       * Array of grouped elements
  47       * @var       array
  48       * @since     1.0
  49       * @access    private
  50       */
  51      var $_elements = array();
  52  
  53      /**
  54       * String to separate elements
  55       * @var       mixed
  56       * @since     2.5
  57       * @access    private
  58       */
  59      var $_separator = null;
  60  
  61      /**
  62       * Required elements in this group
  63       * @var       array
  64       * @since     2.5
  65       * @access    private
  66       */
  67      var $_required = array();
  68  
  69     /**
  70      * Whether to change elements' names to $groupName[$elementName] or leave them as is
  71      * @var      bool
  72      * @since    3.0
  73      * @access   private
  74      */
  75      var $_appendName = true;
  76  
  77      // }}}
  78      // {{{ constructor
  79  
  80      /**
  81       * Class constructor
  82       *
  83       * @param     string    $elementName    (optional)Group name
  84       * @param     array     $elementLabel   (optional)Group label
  85       * @param     array     $elements       (optional)Group elements
  86       * @param     mixed     $separator      (optional)Use a string for one separator,
  87       *                                      use an array to alternate the separators.
  88       * @param     bool      $appendName     (optional)whether to change elements' names to
  89       *                                      the form $groupName[$elementName] or leave
  90       *                                      them as is.
  91       * @since     1.0
  92       * @access    public
  93       * @return    void
  94       */
  95      public function __construct($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true) {
  96          parent::__construct($elementName, $elementLabel);
  97          $this->_type = 'group';
  98          if (isset($elements) && is_array($elements)) {
  99              $this->setElements($elements);
 100          }
 101          if (isset($separator)) {
 102              $this->_separator = $separator;
 103          }
 104          if (isset($appendName)) {
 105              $this->_appendName = $appendName;
 106          }
 107      } //end constructor
 108  
 109      /**
 110       * Old syntax of class constructor. Deprecated in PHP7.
 111       *
 112       * @deprecated since Moodle 3.1
 113       */
 114      public function HTML_QuickForm_group($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true) {
 115          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
 116          self::__construct($elementName, $elementLabel, $elements, $separator, $appendName);
 117      }
 118  
 119      // }}}
 120      // {{{ setName()
 121  
 122      /**
 123       * Sets the group name
 124       *
 125       * @param     string    $name   Group name
 126       * @since     1.0
 127       * @access    public
 128       * @return    void
 129       */
 130      function setName($name)
 131      {
 132          $this->_name = $name;
 133      } //end func setName
 134  
 135      // }}}
 136      // {{{ getName()
 137  
 138      /**
 139       * Returns the group name
 140       *
 141       * @since     1.0
 142       * @access    public
 143       * @return    string
 144       */
 145      function getName()
 146      {
 147          return $this->_name;
 148      } //end func getName
 149  
 150      // }}}
 151      // {{{ setValue()
 152  
 153      /**
 154       * Sets values for group's elements
 155       *
 156       * @param     mixed    Values for group's elements
 157       * @since     1.0
 158       * @access    public
 159       * @return    void
 160       */
 161      function setValue($value)
 162      {
 163          $this->_createElementsIfNotExist();
 164          foreach (array_keys($this->_elements) as $key) {
 165              if (!$this->_appendName) {
 166                  $v = $this->_elements[$key]->_findValue($value);
 167                  if (null !== $v) {
 168                      $this->_elements[$key]->onQuickFormEvent('setGroupValue', $v, $this);
 169                  }
 170  
 171              } else {
 172                  $elementName = $this->_elements[$key]->getName();
 173                  $index       = strlen($elementName) ? $elementName : $key;
 174                  if (is_array($value)) {
 175                      if (isset($value[$index])) {
 176                          $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value[$index], $this);
 177                      }
 178                  } elseif (isset($value)) {
 179                      $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value, $this);
 180                  }
 181              }
 182          }
 183      } //end func setValue
 184  
 185      // }}}
 186      // {{{ getValue()
 187  
 188      /**
 189       * Returns the value of the group
 190       *
 191       * @since     1.0
 192       * @access    public
 193       * @return    mixed
 194       */
 195      function getValue()
 196      {
 197          $value = null;
 198          foreach (array_keys($this->_elements) as $key) {
 199              $element =& $this->_elements[$key];
 200              switch ($element->getType()) {
 201                  case 'radio':
 202                      $v = $element->getChecked()? $element->getValue(): null;
 203                      break;
 204                  case 'checkbox':
 205                      $v = $element->getChecked()? true: null;
 206                      break;
 207                  default:
 208                      $v = $element->getValue();
 209              }
 210              if (null !== $v) {
 211                  $elementName = $element->getName();
 212                  if (is_null($elementName)) {
 213                      $value = $v;
 214                  } else {
 215                      if (!is_array($value)) {
 216                          $value = is_null($value)? array(): array($value);
 217                      }
 218                      if ('' === $elementName) {
 219                          $value[] = $v;
 220                      } else {
 221                          $value[$elementName] = $v;
 222                      }
 223                  }
 224              }
 225          }
 226          return $value;
 227      } // end func getValue
 228  
 229      // }}}
 230      // {{{ setElements()
 231  
 232      /**
 233       * Sets the grouped elements
 234       *
 235       * @param     array     $elements   Array of elements
 236       * @since     1.1
 237       * @access    public
 238       * @return    void
 239       */
 240      function setElements($elements)
 241      {
 242          $this->_elements = array_values($elements);
 243          if ($this->_flagFrozen) {
 244              $this->freeze();
 245          }
 246      } // end func setElements
 247  
 248      // }}}
 249      // {{{ getElements()
 250  
 251      /**
 252       * Gets the grouped elements
 253       *
 254       * @since     2.4
 255       * @access    public
 256       * @return    array
 257       */
 258      function &getElements()
 259      {
 260          $this->_createElementsIfNotExist();
 261          return $this->_elements;
 262      } // end func getElements
 263  
 264      // }}}
 265      // {{{ getGroupType()
 266  
 267      /**
 268       * Gets the group type based on its elements
 269       * Will return 'mixed' if elements contained in the group
 270       * are of different types.
 271       *
 272       * @access    public
 273       * @return    string    group elements type
 274       */
 275      function getGroupType()
 276      {
 277          $this->_createElementsIfNotExist();
 278          $prevType = '';
 279          foreach (array_keys($this->_elements) as $key) {
 280              $type = $this->_elements[$key]->getType();
 281              if ($type != $prevType && $prevType != '') {
 282                  return 'mixed';
 283              }
 284              $prevType = $type;
 285          }
 286          return $type;
 287      } // end func getGroupType
 288  
 289      // }}}
 290      // {{{ toHtml()
 291  
 292      /**
 293       * Returns Html for the group
 294       *
 295       * @since       1.0
 296       * @access      public
 297       * @return      string
 298       */
 299      function toHtml()
 300      {
 301          include_once('HTML/QuickForm/Renderer/Default.php');
 302          $renderer = new HTML_QuickForm_Renderer_Default();
 303          $renderer->setElementTemplate('{element}');
 304          $this->accept($renderer);
 305          return $renderer->toHtml();
 306      } //end func toHtml
 307  
 308      // }}}
 309      // {{{ getElementName()
 310  
 311      /**
 312       * Returns the element name inside the group such as found in the html form
 313       *
 314       * @param     mixed     $index  Element name or element index in the group
 315       * @since     3.0
 316       * @access    public
 317       * @return    mixed     string with element name, false if not found
 318       */
 319      function getElementName($index)
 320      {
 321          $this->_createElementsIfNotExist();
 322          $elementName = false;
 323          if (is_int($index) && isset($this->_elements[$index])) {
 324              $elementName = $this->_elements[$index]->getName();
 325              if (isset($elementName) && $elementName == '') {
 326                  $elementName = $index;
 327              }
 328              if ($this->_appendName) {
 329                  if (is_null($elementName)) {
 330                      $elementName = $this->getName();
 331                  } else {
 332                      $elementName = $this->getName().'['.$elementName.']';
 333                  }
 334              }
 335  
 336          } elseif (is_string($index)) {
 337              foreach (array_keys($this->_elements) as $key) {
 338                  $elementName = $this->_elements[$key]->getName();
 339                  if ($index == $elementName) {
 340                      if ($this->_appendName) {
 341                          $elementName = $this->getName().'['.$elementName.']';
 342                      }
 343                      break;
 344                  } elseif ($this->_appendName && $this->getName().'['.$elementName.']' == $index) {
 345                      break;
 346                  }
 347              }
 348          }
 349          return $elementName;
 350      } //end func getElementName
 351  
 352      // }}}
 353      // {{{ getFrozenHtml()
 354  
 355      /**
 356       * Returns the value of field without HTML tags
 357       *
 358       * @since     1.3
 359       * @access    public
 360       * @return    string
 361       */
 362      function getFrozenHtml()
 363      {
 364          $flags = array();
 365          $this->_createElementsIfNotExist();
 366          foreach (array_keys($this->_elements) as $key) {
 367              if (false === ($flags[$key] = $this->_elements[$key]->isFrozen())) {
 368                  $this->_elements[$key]->freeze();
 369              }
 370          }
 371          $html = $this->toHtml();
 372          foreach (array_keys($this->_elements) as $key) {
 373              if (!$flags[$key]) {
 374                  $this->_elements[$key]->unfreeze();
 375              }
 376          }
 377          return $html;
 378      } //end func getFrozenHtml
 379  
 380      // }}}
 381      // {{{ onQuickFormEvent()
 382  
 383      /**
 384       * Called by HTML_QuickForm whenever form event is made on this element
 385       *
 386       * @param     string    $event  Name of event
 387       * @param     mixed     $arg    event arguments
 388       * @param     object    $caller calling object
 389       * @since     1.0
 390       * @access    public
 391       * @return    void
 392       */
 393      function onQuickFormEvent($event, $arg, &$caller)
 394      {
 395          switch ($event) {
 396              case 'updateValue':
 397                  $this->_createElementsIfNotExist();
 398                  foreach (array_keys($this->_elements) as $key) {
 399                      if ($this->_appendName) {
 400                          $elementName = $this->_elements[$key]->getName();
 401                          if (is_null($elementName)) {
 402                              $this->_elements[$key]->setName($this->getName());
 403                          } elseif ('' === $elementName) {
 404                              $this->_elements[$key]->setName($this->getName() . '[' . $key . ']');
 405                          } else {
 406                              $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']');
 407                          }
 408                      }
 409                      $this->_elements[$key]->onQuickFormEvent('updateValue', $arg, $caller);
 410                      if ($this->_appendName) {
 411                          $this->_elements[$key]->setName($elementName);
 412                      }
 413                  }
 414                  break;
 415  
 416              default:
 417                  parent::onQuickFormEvent($event, $arg, $caller);
 418          }
 419          return true;
 420      } // end func onQuickFormEvent
 421  
 422      // }}}
 423      // {{{ accept()
 424  
 425     /**
 426      * Accepts a renderer
 427      *
 428      * @param object     An HTML_QuickForm_Renderer object
 429      * @param bool       Whether a group is required
 430      * @param string     An error message associated with a group
 431      * @access public
 432      * @return void
 433      */
 434      function accept(&$renderer, $required = false, $error = null)
 435      {
 436          $this->_createElementsIfNotExist();
 437          $renderer->startGroup($this, $required, $error);
 438          $name = $this->getName();
 439          foreach (array_keys($this->_elements) as $key) {
 440              $element =& $this->_elements[$key];
 441  
 442              if ($this->_appendName) {
 443                  $elementName = $element->getName();
 444                  if (isset($elementName)) {
 445                      $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']');
 446                  } else {
 447                      $element->setName($name);
 448                  }
 449              }
 450  
 451              $required = !$element->isFrozen() && in_array($element->getName(), $this->_required);
 452  
 453              $element->accept($renderer, $required);
 454  
 455              // restore the element's name
 456              if ($this->_appendName) {
 457                  $element->setName($elementName);
 458              }
 459          }
 460          $renderer->finishGroup($this);
 461      } // end func accept
 462  
 463      // }}}
 464      // {{{ exportValue()
 465  
 466     /**
 467      * As usual, to get the group's value we access its elements and call
 468      * their exportValue() methods
 469      */
 470      function exportValue(&$submitValues, $assoc = false)
 471      {
 472          $value = null;
 473          foreach (array_keys($this->_elements) as $key) {
 474              $elementName = $this->_elements[$key]->getName();
 475              if ($this->_appendName) {
 476                  if (is_null($elementName)) {
 477                      $this->_elements[$key]->setName($this->getName());
 478                  } elseif ('' === $elementName) {
 479                      $this->_elements[$key]->setName($this->getName() . '[' . $key . ']');
 480                  } else {
 481                      $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']');
 482                  }
 483              }
 484              $v = $this->_elements[$key]->exportValue($submitValues, $assoc);
 485              if ($this->_appendName) {
 486                  $this->_elements[$key]->setName($elementName);
 487              }
 488              if (null !== $v) {
 489                  // Make $value an array, we will use it like one
 490                  if (null === $value) {
 491                      $value = array();
 492                  }
 493                  if ($assoc) {
 494                      // just like HTML_QuickForm::exportValues()
 495                      $value = HTML_QuickForm::arrayMerge($value, $v);
 496                  } else {
 497                      // just like getValue(), but should work OK every time here
 498                      if (is_null($elementName)) {
 499                          $value = $v;
 500                      } elseif ('' === $elementName) {
 501                          $value[] = $v;
 502                      } else {
 503                          $value[$elementName] = $v;
 504                      }
 505                  }
 506              }
 507          }
 508          // do not pass the value through _prepareValue, we took care of this already
 509          return $value;
 510      }
 511  
 512      // }}}
 513      // {{{ _createElements()
 514  
 515     /**
 516      * Creates the group's elements.
 517      *
 518      * This should be overriden by child classes that need to create their
 519      * elements. The method will be called automatically when needed, calling
 520      * it from the constructor is discouraged as the constructor is usually
 521      * called _twice_ on element creation, first time with _no_ parameters.
 522      *
 523      * @access private
 524      * @abstract
 525      */
 526      function _createElements()
 527      {
 528          // abstract
 529      }
 530  
 531      // }}}
 532      // {{{ _createElementsIfNotExist()
 533  
 534     /**
 535      * A wrapper around _createElements()
 536      *
 537      * This method calls _createElements() if the group's _elements array
 538      * is empty. It also performs some updates, e.g. freezes the created
 539      * elements if the group is already frozen.
 540      *
 541      * @access private
 542      */
 543      function _createElementsIfNotExist()
 544      {
 545          if (empty($this->_elements)) {
 546              $this->_createElements();
 547              if ($this->_flagFrozen) {
 548                  $this->freeze();
 549              }
 550          }
 551      }
 552  
 553      // }}}
 554      // {{{ freeze()
 555  
 556      function freeze()
 557      {
 558          parent::freeze();
 559          foreach (array_keys($this->_elements) as $key) {
 560              $this->_elements[$key]->freeze();
 561          }
 562      }
 563  
 564      // }}}
 565      // {{{ unfreeze()
 566  
 567      function unfreeze()
 568      {
 569          parent::unfreeze();
 570          foreach (array_keys($this->_elements) as $key) {
 571              $this->_elements[$key]->unfreeze();
 572          }
 573      }
 574  
 575      // }}}
 576      // {{{ setPersistantFreeze()
 577  
 578      function setPersistantFreeze($persistant = false)
 579      {
 580          parent::setPersistantFreeze($persistant);
 581          foreach (array_keys($this->_elements) as $key) {
 582              $this->_elements[$key]->setPersistantFreeze($persistant);
 583          }
 584      }
 585  
 586      // }}}
 587  } //end class HTML_QuickForm_group
 588  ?>