xref: /dokuwiki/inc/Form/DropdownElement.php (revision 4d28a626ef5a77790a07ded4d81cd3efb3bebb98)
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);
248638ead5SAndreas Gohr        $this->options($options);
258638ead5SAndreas Gohr    }
268638ead5SAndreas Gohr
278638ead5SAndreas Gohr    /**
288638ead5SAndreas Gohr     * Get or set the options of the Dropdown
298638ead5SAndreas Gohr     *
308638ead5SAndreas Gohr     * Options can be given as associative array (value => label) or as an
31795955b2SMichael Grosse     * indexd array (label = value) or as an array of arrays. In the latter
32795955b2SMichael Grosse     * case an element has to look as follows:
33795955b2SMichael Grosse     * option-value => array (
34795955b2SMichael Grosse     *                 'label' => option-label,
35795955b2SMichael Grosse     *                 'attrs' => array (
36795955b2SMichael Grosse     *                                    attr-key => attr-value, ...
37795955b2SMichael Grosse     *                                  )
38795955b2SMichael Grosse     *                 )
398638ead5SAndreas Gohr     *
408638ead5SAndreas Gohr     * @param null|array $options
418638ead5SAndreas Gohr     * @return $this|array
428638ead5SAndreas Gohr     */
438638ead5SAndreas Gohr    public function options($options = null) {
448638ead5SAndreas Gohr        if($options === null) return $this->options;
458638ead5SAndreas Gohr        if(!is_array($options)) throw new \InvalidArgumentException('Options have to be an array');
468638ead5SAndreas Gohr        $this->options = array();
478638ead5SAndreas Gohr
488638ead5SAndreas Gohr        foreach($options as $key => $val) {
498638ead5SAndreas Gohr            if(is_int($key)) {
50795955b2SMichael Grosse                $this->options[$val] = array('label' => (string) $val);
51795955b2SMichael Grosse            } elseif (!is_array($val)) {
52795955b2SMichael Grosse                $this->options[$key] = array('label' => (string) $val);
538638ead5SAndreas Gohr            } else {
54*4d28a626SMichael Grosse                if (!key_exists('label', $val)) throw new \InvalidArgumentException('If option is given as array, it has to have a "label"-key!');
55795955b2SMichael Grosse                $this->options[$key] = $val;
568638ead5SAndreas Gohr            }
578638ead5SAndreas Gohr        }
588638ead5SAndreas Gohr        $this->val(''); // set default value (empty or first)
598638ead5SAndreas Gohr        return $this;
608638ead5SAndreas Gohr    }
618638ead5SAndreas Gohr
628638ead5SAndreas Gohr    /**
638638ead5SAndreas Gohr     * Gets or sets an attribute
648638ead5SAndreas Gohr     *
658638ead5SAndreas Gohr     * When no $value is given, the current content of the attribute is returned.
668638ead5SAndreas Gohr     * An empty string is returned for unset attributes.
678638ead5SAndreas Gohr     *
688638ead5SAndreas Gohr     * When a $value is given, the content is set to that value and the Element
698638ead5SAndreas Gohr     * itself is returned for easy chaining
708638ead5SAndreas Gohr     *
718638ead5SAndreas Gohr     * @param string $name Name of the attribute to access
728638ead5SAndreas Gohr     * @param null|string $value New value to set
738638ead5SAndreas Gohr     * @return string|$this
748638ead5SAndreas Gohr     */
758638ead5SAndreas Gohr    public function attr($name, $value = null) {
768638ead5SAndreas Gohr        if(strtolower($name) == 'multiple') {
778638ead5SAndreas Gohr            throw new \InvalidArgumentException('Sorry, the dropdown element does not support the "multiple" attribute');
788638ead5SAndreas Gohr        }
798638ead5SAndreas Gohr        return parent::attr($name, $value);
808638ead5SAndreas Gohr    }
818638ead5SAndreas Gohr
828638ead5SAndreas Gohr    /**
838638ead5SAndreas Gohr     * Get or set the current value
848638ead5SAndreas Gohr     *
858638ead5SAndreas Gohr     * When setting a value that is not defined in the options, the value is ignored
868638ead5SAndreas Gohr     * and the first option's value is selected instead
878638ead5SAndreas Gohr     *
888638ead5SAndreas Gohr     * @param null|string $value The value to set
898638ead5SAndreas Gohr     * @return $this|string
908638ead5SAndreas Gohr     */
918638ead5SAndreas Gohr    public function val($value = null) {
928638ead5SAndreas Gohr        if($value === null) return $this->value;
938638ead5SAndreas Gohr
948638ead5SAndreas Gohr        if(isset($this->options[$value])) {
958638ead5SAndreas Gohr            $this->value = $value;
968638ead5SAndreas Gohr        } else {
978638ead5SAndreas Gohr            // unknown value set, select first option instead
988638ead5SAndreas Gohr            $keys = array_keys($this->options);
998638ead5SAndreas Gohr            $this->value = (string) array_shift($keys);
1008638ead5SAndreas Gohr        }
1018638ead5SAndreas Gohr
1028638ead5SAndreas Gohr        return $this;
1038638ead5SAndreas Gohr    }
1048638ead5SAndreas Gohr
1058638ead5SAndreas Gohr    /**
1068638ead5SAndreas Gohr     * Create the HTML for the select it self
1078638ead5SAndreas Gohr     *
1088638ead5SAndreas Gohr     * @return string
1098638ead5SAndreas Gohr     */
1108638ead5SAndreas Gohr    protected function mainElementHTML() {
1118638ead5SAndreas Gohr        if($this->useInput) $this->prefillInput();
1128638ead5SAndreas Gohr
1138638ead5SAndreas Gohr        $html = '<select ' . buildAttributes($this->attrs()) . '>';
1148638ead5SAndreas Gohr        foreach($this->options as $key => $val) {
1158638ead5SAndreas Gohr            $selected = ($key == $this->value) ? ' selected="selected"' : '';
116795955b2SMichael Grosse            if (is_array($val['attrs'])) {
117*4d28a626SMichael Grosse                array_walk($val['attrs'],function (&$aval, $akey){$aval = hsc($akey)."='".hsc($aval)."'";});
118795955b2SMichael Grosse                $attrs = join(' ', $val['attrs']);
119795955b2SMichael Grosse            }
120795955b2SMichael Grosse            $html .= '<option' . $selected . ' value="' . hsc($key) . '" '.$attrs.'>' . hsc($val['label']) . '</option>';
1218638ead5SAndreas Gohr        }
1228638ead5SAndreas Gohr        $html .= '</select>';
1238638ead5SAndreas Gohr
1248638ead5SAndreas Gohr        return $html;
1258638ead5SAndreas Gohr    }
1268638ead5SAndreas Gohr
1278638ead5SAndreas Gohr}
128