xref: /dokuwiki/inc/Form/DropdownElement.php (revision 693978b15d5f708046101ecbae3e3474a819b874)
18638ead5SAndreas Gohr<?php
28638ead5SAndreas Gohrnamespace dokuwiki\Form;
38638ead5SAndreas Gohr
48638ead5SAndreas Gohr/**
58638ead5SAndreas Gohr * Class DropdownElement
68638ead5SAndreas Gohr *
78638ead5SAndreas Gohr * Represents a HTML select. Please note that this does not support multiple selected options!
88638ead5SAndreas Gohr *
98638ead5SAndreas Gohr * @package dokuwiki\Form
108638ead5SAndreas Gohr */
118638ead5SAndreas Gohrclass DropdownElement extends InputElement {
128638ead5SAndreas Gohr
138638ead5SAndreas Gohr    protected $options = array();
148638ead5SAndreas Gohr
158638ead5SAndreas Gohr    protected $value = '';
168638ead5SAndreas Gohr
178638ead5SAndreas Gohr    /**
188638ead5SAndreas Gohr     * @param string $name The name of this form element
198638ead5SAndreas Gohr     * @param string $options The available options
208638ead5SAndreas Gohr     * @param string $label The label text for this element (will be autoescaped)
218638ead5SAndreas Gohr     */
228638ead5SAndreas Gohr    public function __construct($name, $options, $label = '') {
238638ead5SAndreas Gohr        parent::__construct('dropdown', $name, $label);
24*693978b1SMichael Grosse        $this->rmattr('type');
258638ead5SAndreas Gohr        $this->options($options);
268638ead5SAndreas Gohr    }
278638ead5SAndreas Gohr
288638ead5SAndreas Gohr    /**
298638ead5SAndreas Gohr     * Get or set the options of the Dropdown
308638ead5SAndreas Gohr     *
318638ead5SAndreas Gohr     * Options can be given as associative array (value => label) or as an
32795955b2SMichael Grosse     * indexd array (label = value) or as an array of arrays. In the latter
33795955b2SMichael Grosse     * case an element has to look as follows:
34795955b2SMichael Grosse     * option-value => array (
35795955b2SMichael Grosse     *                 'label' => option-label,
36795955b2SMichael Grosse     *                 'attrs' => array (
37795955b2SMichael Grosse     *                                    attr-key => attr-value, ...
38795955b2SMichael Grosse     *                                  )
39795955b2SMichael Grosse     *                 )
408638ead5SAndreas Gohr     *
418638ead5SAndreas Gohr     * @param null|array $options
428638ead5SAndreas Gohr     * @return $this|array
438638ead5SAndreas Gohr     */
448638ead5SAndreas Gohr    public function options($options = null) {
458638ead5SAndreas Gohr        if($options === null) return $this->options;
468638ead5SAndreas Gohr        if(!is_array($options)) throw new \InvalidArgumentException('Options have to be an array');
478638ead5SAndreas Gohr        $this->options = array();
488638ead5SAndreas Gohr
498638ead5SAndreas Gohr        foreach($options as $key => $val) {
508638ead5SAndreas Gohr            if(is_int($key)) {
51795955b2SMichael Grosse                $this->options[$val] = array('label' => (string) $val);
52795955b2SMichael Grosse            } elseif (!is_array($val)) {
53795955b2SMichael Grosse                $this->options[$key] = array('label' => (string) $val);
548638ead5SAndreas Gohr            } else {
554d28a626SMichael Grosse                if (!key_exists('label', $val)) throw new \InvalidArgumentException('If option is given as array, it has to have a "label"-key!');
56795955b2SMichael Grosse                $this->options[$key] = $val;
578638ead5SAndreas Gohr            }
588638ead5SAndreas Gohr        }
598638ead5SAndreas Gohr        $this->val(''); // set default value (empty or first)
608638ead5SAndreas Gohr        return $this;
618638ead5SAndreas Gohr    }
628638ead5SAndreas Gohr
638638ead5SAndreas Gohr    /**
648638ead5SAndreas Gohr     * Gets or sets an attribute
658638ead5SAndreas Gohr     *
668638ead5SAndreas Gohr     * When no $value is given, the current content of the attribute is returned.
678638ead5SAndreas Gohr     * An empty string is returned for unset attributes.
688638ead5SAndreas Gohr     *
698638ead5SAndreas Gohr     * When a $value is given, the content is set to that value and the Element
708638ead5SAndreas Gohr     * itself is returned for easy chaining
718638ead5SAndreas Gohr     *
728638ead5SAndreas Gohr     * @param string $name Name of the attribute to access
738638ead5SAndreas Gohr     * @param null|string $value New value to set
748638ead5SAndreas Gohr     * @return string|$this
758638ead5SAndreas Gohr     */
768638ead5SAndreas Gohr    public function attr($name, $value = null) {
778638ead5SAndreas Gohr        if(strtolower($name) == 'multiple') {
788638ead5SAndreas Gohr            throw new \InvalidArgumentException('Sorry, the dropdown element does not support the "multiple" attribute');
798638ead5SAndreas Gohr        }
808638ead5SAndreas Gohr        return parent::attr($name, $value);
818638ead5SAndreas Gohr    }
828638ead5SAndreas Gohr
838638ead5SAndreas Gohr    /**
848638ead5SAndreas Gohr     * Get or set the current value
858638ead5SAndreas Gohr     *
868638ead5SAndreas Gohr     * When setting a value that is not defined in the options, the value is ignored
878638ead5SAndreas Gohr     * and the first option's value is selected instead
888638ead5SAndreas Gohr     *
898638ead5SAndreas Gohr     * @param null|string $value The value to set
908638ead5SAndreas Gohr     * @return $this|string
918638ead5SAndreas Gohr     */
928638ead5SAndreas Gohr    public function val($value = null) {
938638ead5SAndreas Gohr        if($value === null) return $this->value;
948638ead5SAndreas Gohr
958638ead5SAndreas Gohr        if(isset($this->options[$value])) {
968638ead5SAndreas Gohr            $this->value = $value;
978638ead5SAndreas Gohr        } else {
988638ead5SAndreas Gohr            // unknown value set, select first option instead
998638ead5SAndreas Gohr            $keys = array_keys($this->options);
1008638ead5SAndreas Gohr            $this->value = (string) array_shift($keys);
1018638ead5SAndreas Gohr        }
1028638ead5SAndreas Gohr
1038638ead5SAndreas Gohr        return $this;
1048638ead5SAndreas Gohr    }
1058638ead5SAndreas Gohr
1068638ead5SAndreas Gohr    /**
1078638ead5SAndreas Gohr     * Create the HTML for the select it self
1088638ead5SAndreas Gohr     *
1098638ead5SAndreas Gohr     * @return string
1108638ead5SAndreas Gohr     */
1118638ead5SAndreas Gohr    protected function mainElementHTML() {
1128638ead5SAndreas Gohr        if($this->useInput) $this->prefillInput();
1138638ead5SAndreas Gohr
1148638ead5SAndreas Gohr        $html = '<select ' . buildAttributes($this->attrs()) . '>';
1158638ead5SAndreas Gohr        foreach($this->options as $key => $val) {
1168638ead5SAndreas Gohr            $selected = ($key == $this->value) ? ' selected="selected"' : '';
117af642354SMichael Grosse            $attrs = '';
118795955b2SMichael Grosse            if (is_array($val['attrs'])) {
119af642354SMichael Grosse                array_walk($val['attrs'],function (&$aval, $akey){$aval = hsc($akey).'="'.hsc($aval).'"';});
120795955b2SMichael Grosse                $attrs = join(' ', $val['attrs']);
121795955b2SMichael Grosse            }
122795955b2SMichael Grosse            $html .= '<option' . $selected . ' value="' . hsc($key) . '" '.$attrs.'>' . hsc($val['label']) . '</option>';
1238638ead5SAndreas Gohr        }
1248638ead5SAndreas Gohr        $html .= '</select>';
1258638ead5SAndreas Gohr
1268638ead5SAndreas Gohr        return $html;
1278638ead5SAndreas Gohr    }
1288638ead5SAndreas Gohr
1298638ead5SAndreas Gohr}
130