xref: /dokuwiki/inc/Form/DropdownElement.php (revision d785a180a0a5f99f363c10269a59f0ac012c3ee6)
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