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