xref: /dokuwiki/inc/Form/Form.php (revision 64744a10c5578602141ae2977274eec3fcff1f44)
1<?php
2namespace dokuwiki\Form;
3
4/**
5 * Class Form
6 *
7 * Represents the whole Form. This is what you work on, and add Elements to
8 *
9 * @package dokuwiki\Form
10 */
11class Form extends Element {
12
13    /**
14     * @var array name value pairs for hidden values
15     */
16    protected $hidden = array();
17
18    /**
19     * @var Element[] the elements of the form
20     */
21    protected $elements = array();
22
23    /**
24     * Creates a new, empty form with some default attributes
25     *
26     * @param array $attributes
27     */
28    public function __construct($attributes = array()) {
29        global $ID;
30
31        parent::__construct('form', $attributes);
32
33        // use the current URL as default action
34        if(!$this->attr('action')) {
35            $get = $_GET;
36            if(isset($get['id'])) unset($get['id']);
37            $self = wl($ID, $get, false, '&'); //attributes are escaped later
38            $this->attr('action', $self);
39        }
40
41        // post is default
42        if(!$this->attr('method')) {
43            $this->attr('method', 'post');
44        }
45
46        // we like UTF-8
47        if(!$this->attr('accept-charset')) {
48            $this->attr('accept-charset', 'utf-8');
49        }
50
51        // add the security token by default
52        $this->setHiddenField('sectok', getSecurityToken());
53
54        // identify this as a new form based form in HTML
55        $this->addClass('doku_form');
56    }
57
58    /**
59     * Sets a hidden field
60     *
61     * @param $name
62     * @param $value
63     * @return $this
64     */
65    public function setHiddenField($name, $value) {
66        $this->hidden[$name] = $value;
67        return $this;
68    }
69
70    #region Element adding functions
71
72    /**
73     * Adds an element to the end of the form
74     *
75     * @param Element $element
76     * @param int $pos 0-based position in the form, -1 for at the end
77     * @return Element
78     */
79    public function addElement(Element $element, $pos = -1) {
80        if(is_a($element, 'Doku_Form2')) throw new \InvalidArgumentException('You can\'t add a form to a form');
81        if($pos < 0) {
82            $this->elements[] = $element;
83        } else {
84            array_splice($this->elements, $pos, 0, array($element));
85        }
86        return $element;
87    }
88
89    /**
90     * Adds a text input field
91     *
92     * @param $name
93     * @param $label
94     * @param int $pos
95     * @return InputElement
96     */
97    public function addTextInput($name, $label = '', $pos = -1) {
98        return $this->addElement(new InputElement('text', $name, $label), $pos);
99    }
100
101    /**
102     * Adds a password input field
103     *
104     * @param $name
105     * @param $label
106     * @param int $pos
107     * @return InputElement
108     */
109    public function addPasswordInput($name, $label = '', $pos = -1) {
110        return $this->addElement(new InputElement('password', $name, $label), $pos);
111    }
112
113    /**
114     * Adds a radio button field
115     *
116     * @param $name
117     * @param $label
118     * @param int $pos
119     * @return CheckableElement
120     */
121    public function addRadioButton($name, $label = '', $pos = -1) {
122        return $this->addElement(new CheckableElement('radio', $name, $label), $pos);
123    }
124
125    /**
126     * Adds a checkbox field
127     *
128     * @param $name
129     * @param $label
130     * @param int $pos
131     * @return CheckableElement
132     */
133    public function addCheckbox($name, $label = '', $pos = -1) {
134        return $this->addElement(new CheckableElement('checkbox', $name, $label), $pos);
135    }
136
137    /**
138     * Adds a textarea field
139     *
140     * @param $name
141     * @param $label
142     * @param int $pos
143     * @return TextareaElement
144     */
145    public function addTextarea($name, $label = '', $pos = -1) {
146        return $this->addElement(new TextareaElement($name, $label), $pos);
147    }
148
149    /**
150     * Add fixed HTML to the form
151     *
152     * @param $html
153     * @param int $pos
154     * @return HTMLElement
155     */
156    public function addHTML($html, $pos = -1) {
157        return $this->addElement(new HTMLElement($html), $pos);
158    }
159
160    /**
161     * Add a closed HTML tag to the form
162     *
163     * @param $tag
164     * @param int $pos
165     * @return TagElement
166     */
167    public function addTag($tag, $pos = -1) {
168        return $this->addElement(new TagElement($tag), $pos);
169    }
170
171    /**
172     * Add an open HTML tag to the form
173     *
174     * Be sure to close it again!
175     *
176     * @param $tag
177     * @param int $pos
178     * @return TagOpenElement
179     */
180    public function addTagOpen($tag, $pos = -1) {
181        return $this->addElement(new TagOpenElement($tag), $pos);
182    }
183
184    /**
185     * Add a closing HTML tag to the form
186     *
187     * Be sure it had been opened before
188     *
189     * @param $tag
190     * @param int $pos
191     * @return TagCloseElement
192     */
193    public function addTagClose($tag, $pos = -1) {
194        return $this->addElement(new TagCloseElement($tag), $pos);
195    }
196
197
198    /**
199     * Open a Fieldset
200     *
201     * @param $legend
202     * @param int $pos
203     * @return FieldsetOpenElement
204     */
205    public function addFieldsetOpen($legend='', $pos = -1) {
206        return $this->addElement(new FieldsetOpenElement($legend), $pos);
207    }
208
209    /**
210     * Close a fieldset
211     *
212     * @param int $pos
213     * @return TagCloseElement
214     */
215    public function addFieldsetClose($pos = -1) {
216        return $this->addElement(new FieldsetCloseElement(), $pos);
217    }
218
219    #endregion
220
221    protected function balanceFieldsets() {
222        //todo implement!
223    }
224
225    /**
226     * The HTML representation of the whole form
227     *
228     * @return string
229     */
230    public function toHTML() {
231        $this->balanceFieldsets();
232
233        $html = '<form ' . buildAttributes($this->attrs()) . '>' . DOKU_LF;
234
235        foreach($this->hidden as $name => $value) {
236            $html .= '<input type="hidden" name="' . $name . '" value="' . formText($value) . '" />' . DOKU_LF;
237        }
238
239        foreach($this->elements as $element) {
240            $html .= $element->toHTML() . DOKU_LF;
241        }
242
243        $html .= '</form>' . DOKU_LF;
244
245        return $html;
246    }
247}
248