Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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