1<?php 2namespace 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 */ 11class DropdownElement extends InputElement { 12 13 protected $options = array(); 14 15 protected $value = ''; 16 17 /** 18 * @param string $name The name of this form element 19 * @param string $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 parent::__construct('dropdown', $name, $label); 24 $this->options($options); 25 } 26 27 /** 28 * Get or set the options of the Dropdown 29 * 30 * Options can be given as associative array (value => label) or as an 31 * indexd array (label = value) or as an array of arrays. In the latter 32 * case an element has to look as follows: 33 * option-value => array ( 34 * 'label' => option-label, 35 * 'attrs' => array ( 36 * attr-key => attr-value, ... 37 * ) 38 * ) 39 * 40 * @param null|array $options 41 * @return $this|array 42 */ 43 public function options($options = null) { 44 if($options === null) return $this->options; 45 if(!is_array($options)) throw new \InvalidArgumentException('Options have to be an array'); 46 $this->options = array(); 47 48 foreach($options as $key => $val) { 49 if(is_int($key)) { 50 $this->options[$val] = array('label' => (string) $val); 51 } elseif (!is_array($val)) { 52 $this->options[$key] = array('label' => (string) $val); 53 } else { 54 if (!key_exists('label', $val)) throw new \InvalidArgumentException('If option is given as array, it has to have a "label"-key!'); 55 $this->options[$key] = $val; 56 } 57 } 58 $this->val(''); // set default value (empty or first) 59 return $this; 60 } 61 62 /** 63 * Gets or sets an attribute 64 * 65 * When no $value is given, the current content of the attribute is returned. 66 * An empty string is returned for unset attributes. 67 * 68 * When a $value is given, the content is set to that value and the Element 69 * itself is returned for easy chaining 70 * 71 * @param string $name Name of the attribute to access 72 * @param null|string $value New value to set 73 * @return string|$this 74 */ 75 public function attr($name, $value = null) { 76 if(strtolower($name) == 'multiple') { 77 throw new \InvalidArgumentException('Sorry, the dropdown element does not support the "multiple" attribute'); 78 } 79 return parent::attr($name, $value); 80 } 81 82 /** 83 * Get or set the current value 84 * 85 * When setting a value that is not defined in the options, the value is ignored 86 * and the first option's value is selected instead 87 * 88 * @param null|string $value The value to set 89 * @return $this|string 90 */ 91 public function val($value = null) { 92 if($value === null) return $this->value; 93 94 if(isset($this->options[$value])) { 95 $this->value = $value; 96 } else { 97 // unknown value set, select first option instead 98 $keys = array_keys($this->options); 99 $this->value = (string) array_shift($keys); 100 } 101 102 return $this; 103 } 104 105 /** 106 * Create the HTML for the select it self 107 * 108 * @return string 109 */ 110 protected function mainElementHTML() { 111 if($this->useInput) $this->prefillInput(); 112 113 $html = '<select ' . buildAttributes($this->attrs()) . '>'; 114 foreach($this->options as $key => $val) { 115 $selected = ($key == $this->value) ? ' selected="selected"' : ''; 116 $attrs = ''; 117 if (is_array($val['attrs'])) { 118 array_walk($val['attrs'],function (&$aval, $akey){$aval = hsc($akey).'="'.hsc($aval).'"';}); 119 $attrs = join(' ', $val['attrs']); 120 } 121 $html .= '<option' . $selected . ' value="' . hsc($key) . '" '.$attrs.'>' . hsc($val['label']) . '</option>'; 122 } 123 $html .= '</select>'; 124 125 return $html; 126 } 127 128} 129