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