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