[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/Form/ -> DropdownElement.php (source)

   1  <?php
   2  namespace dokuwiki\Form;
   3  
   4  /**
   5   * Class DropdownElement
   6   *
   7   * Represents a HTML select. Please note that this does not support multiple selected options!
   8   *
   9   * @package dokuwiki\Form
  10   */
  11  class DropdownElement extends InputElement {
  12  
  13      /** @var array OptGroup[] */
  14      protected $optGroups = array();
  15  
  16      /**
  17       * @param string $name The name of this form element
  18       * @param array  $options The available options
  19       * @param string $label The label text for this element (will be autoescaped)
  20       */
  21      public function __construct($name, $options, $label = '') {
  22          parent::__construct('dropdown', $name, $label);
  23          $this->rmattr('type');
  24          $this->optGroups[''] = new OptGroup(null, $options);
  25          $this->val('');
  26      }
  27  
  28      /**
  29       * Add an `<optgroup>` and respective options
  30       *
  31       * @param string $label
  32       * @param array  $options
  33       * @return OptGroup a reference to the added optgroup
  34       * @throws \Exception
  35       */
  36      public function addOptGroup($label, $options) {
  37          if (empty($label)) {
  38              throw new \InvalidArgumentException(hsc('<optgroup> must have a label!'));
  39          }
  40          $this->optGroups[$label] = new OptGroup($label, $options);
  41          return end($this->optGroups);
  42      }
  43  
  44      /**
  45       * Set or get the optgroups of an Dropdown-Element.
  46       *
  47       * optgroups have to be given as associative array
  48       *   * the key being the label of the group
  49       *   * the value being an array of options as defined in @see OptGroup::options()
  50       *
  51       * @param null|array $optGroups
  52       * @return OptGroup[]|DropdownElement
  53       */
  54      public function optGroups($optGroups = null) {
  55          if($optGroups === null) {
  56              return $this->optGroups;
  57          }
  58          if (!is_array($optGroups)) {
  59              throw new \InvalidArgumentException(hsc('Argument must be an associative array of label => [options]!'));
  60          }
  61          $this->optGroups = array();
  62          foreach ($optGroups as $label => $options) {
  63              $this->addOptGroup($label, $options);
  64          }
  65          return $this;
  66      }
  67  
  68      /**
  69       * Get or set the options of the Dropdown
  70       *
  71       * Options can be given as associative array (value => label) or as an
  72       * indexd array (label = value) or as an array of arrays. In the latter
  73       * case an element has to look as follows:
  74       * option-value => array (
  75       *                 'label' => option-label,
  76       *                 'attrs' => array (
  77       *                                    attr-key => attr-value, ...
  78       *                                  )
  79       *                 )
  80       *
  81       * @param null|array $options
  82       * @return $this|array
  83       */
  84      public function options($options = null) {
  85          if ($options === null) {
  86              return $this->optGroups['']->options();
  87          }
  88          $this->optGroups[''] = new OptGroup(null, $options);
  89          return $this;
  90      }
  91  
  92      /**
  93       * Gets or sets an attribute
  94       *
  95       * When no $value is given, the current content of the attribute is returned.
  96       * An empty string is returned for unset attributes.
  97       *
  98       * When a $value is given, the content is set to that value and the Element
  99       * itself is returned for easy chaining
 100       *
 101       * @param string $name Name of the attribute to access
 102       * @param null|string $value New value to set
 103       * @return string|$this
 104       */
 105      public function attr($name, $value = null) {
 106          if(strtolower($name) == 'multiple') {
 107              throw new \InvalidArgumentException(
 108                  'Sorry, the dropdown element does not support the "multiple" attribute'
 109              );
 110          }
 111          return parent::attr($name, $value);
 112      }
 113  
 114      /**
 115       * Get or set the current value
 116       *
 117       * When setting a value that is not defined in the options, the value is ignored
 118       * and the first option's value is selected instead
 119       *
 120       * @param null|string $value The value to set
 121       * @return $this|string
 122       */
 123      public function val($value = null) {
 124          if($value === null) return $this->value;
 125  
 126          $value_exists = $this->setValueInOptGroups($value);
 127  
 128          if($value_exists) {
 129              $this->value = $value;
 130          } else {
 131              // unknown value set, select first option instead
 132              $this->value = $this->getFirstOption();
 133              $this->setValueInOptGroups($this->value);
 134          }
 135  
 136          return $this;
 137      }
 138  
 139      /**
 140       * Returns the first options as it will be rendered in HTML
 141       *
 142       * @return string
 143       */
 144      protected function getFirstOption() {
 145          $options = $this->options();
 146          if (!empty($options)) {
 147              $keys = array_keys($options);
 148              return (string) array_shift($keys);
 149          }
 150          foreach ($this->optGroups as $optGroup) {
 151              $options = $optGroup->options();
 152              if (!empty($options)) {
 153                  $keys = array_keys($options);
 154                  return (string) array_shift($keys);
 155              }
 156          }
 157      }
 158  
 159      /**
 160       * Set the value in the OptGroups, including the optgroup for the options without optgroup.
 161       *
 162       * @param string $value
 163       * @return bool
 164       */
 165      protected function setValueInOptGroups($value) {
 166          $value_exists = false;
 167          /** @var OptGroup $optGroup */
 168          foreach ($this->optGroups as $optGroup) {
 169              $value_exists = $optGroup->storeValue($value) || $value_exists;
 170              if ($value_exists) {
 171                  $value = null;
 172              }
 173          }
 174          return $value_exists;
 175      }
 176  
 177      /**
 178       * Create the HTML for the select it self
 179       *
 180       * @return string
 181       */
 182      protected function mainElementHTML() {
 183          if($this->useInput) $this->prefillInput();
 184  
 185          $html = '<select ' . buildAttributes($this->attrs()) . '>';
 186          $html = array_reduce(
 187              $this->optGroups,
 188              function ($html, OptGroup $optGroup) {
 189                  return $html . $optGroup->toHTML();
 190              },
 191              $html
 192          );
 193          $html .= '</select>';
 194  
 195          return $html;
 196      }
 197  
 198  }