xref: /dokuwiki/inc/Form/OptGroup.php (revision 010cc795432919ae75a87c9929011326173f26bf)
1<?php
2
3namespace dokuwiki\Form;
4
5class OptGroup extends Element
6{
7    protected $options = [];
8    protected $values = [];
9
10    /**
11     * @param string $label The label text for this element (will be autoescaped)
12     * @param array $options The available options
13     */
14    public function __construct($label, $options)
15    {
16        parent::__construct('optGroup', array('label' => $label));
17        $this->options($options);
18    }
19
20    /**
21     * Store the given values so they can be used during rendering
22     *
23     * This is intended to be only called from within DropdownElement::val()
24     *
25     * @param string[] $values the values to set
26     * @return string[] the values that have been set (options exist)
27     * @see DropdownElement::val()
28     */
29    public function storeValues($values)
30    {
31        $this->values = [];
32        foreach ($values as $value) {
33            if(isset($this->options[$value])) {
34                $this->values[] = $value;
35            }
36        }
37
38        return $this->values;
39    }
40
41    /**
42     * Get or set the options of the optgroup
43     *
44     * Options can be given as associative array (value => label) or as an
45     * indexd array (label = value) or as an array of arrays. In the latter
46     * case an element has to look as follows:
47     * option-value => array (
48     *                 'label' => option-label,
49     *                 'attrs' => array (
50     *                                    attr-key => attr-value, ...
51     *                                  )
52     *                 )
53     *
54     * @param null|array $options
55     * @return $this|array
56     */
57    public function options($options = null)
58    {
59        if ($options === null) return $this->options;
60        if (!is_array($options)) throw new \InvalidArgumentException('Options have to be an array');
61        $this->options = array();
62        foreach ($options as $key => $val) {
63            if (is_array($val)) {
64                if (!key_exists('label', $val)) {
65                    throw new \InvalidArgumentException(
66                        'If option is given as array, it has to have a "label"-key!'
67                    );
68                }
69                if (key_exists('attrs', $val) && is_array($val['attrs']) && key_exists('selected', $val['attrs'])) {
70                    throw new \InvalidArgumentException(
71                        'Please use function "DropdownElement::val()" to set the selected option'
72                    );
73                }
74                $this->options[$key] = $val;
75            } elseif (is_int($key)) {
76                $this->options[$val] = array('label' => (string)$val);
77            } else {
78                $this->options[$key] = array('label' => (string)$val);
79            }
80        }
81        return $this;
82    }
83
84    /**
85     * The HTML representation of this element
86     *
87     * @return string
88     */
89    public function toHTML()
90    {
91        if ($this->attributes['label'] === null) {
92            return $this->renderOptions();
93        }
94        $html = '<optgroup ' . buildAttributes($this->attrs()) . '>';
95        $html .= $this->renderOptions();
96        $html .= '</optgroup>';
97        return $html;
98    }
99
100    /**
101     * @return string
102     */
103    protected function renderOptions()
104    {
105        $html = '';
106        foreach ($this->options as $key => $val) {
107            $selected = in_array((string)$key, $this->values) ? ' selected="selected"' : '';
108            $attrs = '';
109            if (!empty($val['attrs']) && is_array($val['attrs'])) {
110                $attrs = buildAttributes($val['attrs']);
111            }
112            $html .= '<option' . $selected . ' value="' . hsc($key) . '" ' . $attrs . '>';
113            $html .= hsc($val['label']);
114            $html .= '</option>';
115        }
116        return $html;
117    }
118}
119