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