xref: /dokuwiki/inc/Form/InputElement.php (revision 6d0ceaf93ca31dfb83fd4325ef2eecd9cef733c0)
1<?php
2namespace dokuwiki\Form;
3
4/**
5 * Class InputElement
6 *
7 * Base class for all input elements. Uses a wrapping label.
8 *
9 * @todo figure out how to make wrapping or related label configurable
10 * @package dokuwiki\Form
11 */
12class InputElement extends Element {
13    /**
14     * @var Label
15     */
16    protected $label;
17
18    /**
19     * @var bool if the element should reflect posted values
20     */
21    protected $useInput = true;
22
23    /**
24     * @param string $type The type of this element
25     * @param string $name The name of this form element
26     * @param string $label The label text for this element
27     */
28    public function __construct($type, $name, $label) {
29        parent::__construct($type, array('name' => $name));
30        $this->attr('name', $name);
31        $this->label = new Label($label);
32    }
33
34    /**
35     * Should the user sent input be used to initialize the input field
36     *
37     * The default is true. Any set values will be overwritten by the INPUT
38     * provided values.
39     *
40     * @param bool $useinput
41     * @return $this
42     */
43    public function useInput($useinput) {
44        $this->useInput = (bool) $useinput;
45        return $this;
46    }
47
48    /**
49     * Get or set the element's ID
50     *
51     * @param null|string $id
52     * @return string|$this
53     */
54    public function id($id = null) {
55        $this->label->attr('for', $id);
56        return parent::id($id);
57    }
58
59    /**
60     * Adds a class to the class attribute
61     *
62     * This is the preferred method of setting the element's class
63     *
64     * @param string $class the new class to add
65     * @return $this
66     */
67    public function addClass($class) {
68        $this->label->addClass($class);
69        return parent::addClass($class);
70    }
71
72    /**
73     * Figures out how to access the value for this field from INPUT data
74     *
75     * The element's name could have been given as a simple string ('foo')
76     * or in array notation ('foo[bar]').
77     *
78     * Note: this function only handles one level of arrays. If your data
79     * is nested deeper, you should call useInput(false) and set the
80     * correct value yourself
81     *
82     * @return array name and array key (null if not an array)
83     */
84    protected function getInputName() {
85        $name = $this->attr('name');
86        parse_str("$name=1", $parsed);
87
88        $name = array_keys($parsed);
89        $name = array_shift($name);
90
91        if(is_array($parsed[$name])) {
92            $key = array_keys($parsed[$name]);
93            $key = array_shift($key);
94        } else {
95            $key = null;
96        }
97
98        return array($name, $key);
99    }
100
101    /**
102     * Handles the useInput flag and set the value attribute accordingly
103     */
104    protected function prefillInput() {
105        global $INPUT;
106
107        list($name, $key) = $this->getInputName();
108        if(!$INPUT->has($name)) return;
109
110        if($key === null) {
111            $value = $INPUT->str($name);
112        } else {
113            $value = $INPUT->arr($name);
114            if(isset($value[$key])) {
115                $value = $value[$key];
116            } else {
117                $value = '';
118            }
119        }
120        if($value !== '') {
121            $this->val($value);
122        }
123    }
124
125    /**
126     * The HTML representation of this element
127     *
128     * @return string
129     */
130    protected function mainElementHTML() {
131        if($this->useInput) $this->prefillInput();
132        return '<input ' . buildAttributes($this->attrs()) . ' />';
133    }
134
135    /**
136     * The HTML representation of this element wrapped in a label
137     *
138     * @return string
139     */
140    public function toHTML() {
141        return '<label ' . buildAttributes($this->label->attrs()) . '>' . DOKU_LF .
142        '<span>' . hsc($this->label->label) . '</span>' . DOKU_LF .
143        $this->mainElementHTML() . DOKU_LF .
144        '</label>';
145    }
146}
147