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