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