xref: /dokuwiki/inc/Form/Form.php (revision 64744a10c5578602141ae2977274eec3fcff1f44)
112a4e4d1SAndreas Gohr<?php
212a4e4d1SAndreas Gohrnamespace dokuwiki\Form;
312a4e4d1SAndreas Gohr
412a4e4d1SAndreas Gohr/**
512a4e4d1SAndreas Gohr * Class Form
612a4e4d1SAndreas Gohr *
712a4e4d1SAndreas Gohr * Represents the whole Form. This is what you work on, and add Elements to
812a4e4d1SAndreas Gohr *
912a4e4d1SAndreas Gohr * @package dokuwiki\Form
1012a4e4d1SAndreas Gohr */
1112a4e4d1SAndreas Gohrclass Form extends Element {
1212a4e4d1SAndreas Gohr
1312a4e4d1SAndreas Gohr    /**
1412a4e4d1SAndreas Gohr     * @var array name value pairs for hidden values
1512a4e4d1SAndreas Gohr     */
1612a4e4d1SAndreas Gohr    protected $hidden = array();
1712a4e4d1SAndreas Gohr
1812a4e4d1SAndreas Gohr    /**
1912a4e4d1SAndreas Gohr     * @var Element[] the elements of the form
2012a4e4d1SAndreas Gohr     */
2112a4e4d1SAndreas Gohr    protected $elements = array();
2212a4e4d1SAndreas Gohr
2312a4e4d1SAndreas Gohr    /**
2412a4e4d1SAndreas Gohr     * Creates a new, empty form with some default attributes
2512a4e4d1SAndreas Gohr     *
2612a4e4d1SAndreas Gohr     * @param array $attributes
2712a4e4d1SAndreas Gohr     */
2812a4e4d1SAndreas Gohr    public function __construct($attributes = array()) {
2912a4e4d1SAndreas Gohr        global $ID;
3012a4e4d1SAndreas Gohr
3112a4e4d1SAndreas Gohr        parent::__construct('form', $attributes);
3212a4e4d1SAndreas Gohr
3312a4e4d1SAndreas Gohr        // use the current URL as default action
3412a4e4d1SAndreas Gohr        if(!$this->attr('action')) {
3512a4e4d1SAndreas Gohr            $get = $_GET;
3612a4e4d1SAndreas Gohr            if(isset($get['id'])) unset($get['id']);
376d0ceaf9SAndreas Gohr            $self = wl($ID, $get, false, '&'); //attributes are escaped later
3812a4e4d1SAndreas Gohr            $this->attr('action', $self);
3912a4e4d1SAndreas Gohr        }
4012a4e4d1SAndreas Gohr
4112a4e4d1SAndreas Gohr        // post is default
4212a4e4d1SAndreas Gohr        if(!$this->attr('method')) {
4312a4e4d1SAndreas Gohr            $this->attr('method', 'post');
4412a4e4d1SAndreas Gohr        }
4512a4e4d1SAndreas Gohr
4612a4e4d1SAndreas Gohr        // we like UTF-8
4712a4e4d1SAndreas Gohr        if(!$this->attr('accept-charset')) {
4812a4e4d1SAndreas Gohr            $this->attr('accept-charset', 'utf-8');
4912a4e4d1SAndreas Gohr        }
5012a4e4d1SAndreas Gohr
5112a4e4d1SAndreas Gohr        // add the security token by default
5212a4e4d1SAndreas Gohr        $this->setHiddenField('sectok', getSecurityToken());
5312a4e4d1SAndreas Gohr
546d0ceaf9SAndreas Gohr        // identify this as a new form based form in HTML
556d0ceaf9SAndreas Gohr        $this->addClass('doku_form');
5612a4e4d1SAndreas Gohr    }
5712a4e4d1SAndreas Gohr
5812a4e4d1SAndreas Gohr    /**
5912a4e4d1SAndreas Gohr     * Sets a hidden field
6012a4e4d1SAndreas Gohr     *
6112a4e4d1SAndreas Gohr     * @param $name
6212a4e4d1SAndreas Gohr     * @param $value
6312a4e4d1SAndreas Gohr     * @return $this
6412a4e4d1SAndreas Gohr     */
6512a4e4d1SAndreas Gohr    public function setHiddenField($name, $value) {
6612a4e4d1SAndreas Gohr        $this->hidden[$name] = $value;
6712a4e4d1SAndreas Gohr        return $this;
6812a4e4d1SAndreas Gohr    }
6912a4e4d1SAndreas Gohr
70*64744a10SAndreas Gohr    #region Element adding functions
71*64744a10SAndreas Gohr
7212a4e4d1SAndreas Gohr    /**
7312a4e4d1SAndreas Gohr     * Adds an element to the end of the form
7412a4e4d1SAndreas Gohr     *
7512a4e4d1SAndreas Gohr     * @param Element $element
7612a4e4d1SAndreas Gohr     * @param int $pos 0-based position in the form, -1 for at the end
7712a4e4d1SAndreas Gohr     * @return Element
7812a4e4d1SAndreas Gohr     */
7912a4e4d1SAndreas Gohr    public function addElement(Element $element, $pos = -1) {
8012a4e4d1SAndreas Gohr        if(is_a($element, 'Doku_Form2')) throw new \InvalidArgumentException('You can\'t add a form to a form');
8112a4e4d1SAndreas Gohr        if($pos < 0) {
8212a4e4d1SAndreas Gohr            $this->elements[] = $element;
8312a4e4d1SAndreas Gohr        } else {
8412a4e4d1SAndreas Gohr            array_splice($this->elements, $pos, 0, array($element));
8512a4e4d1SAndreas Gohr        }
8612a4e4d1SAndreas Gohr        return $element;
8712a4e4d1SAndreas Gohr    }
8812a4e4d1SAndreas Gohr
8912a4e4d1SAndreas Gohr    /**
9012a4e4d1SAndreas Gohr     * Adds a text input field
9112a4e4d1SAndreas Gohr     *
9212a4e4d1SAndreas Gohr     * @param $name
9312a4e4d1SAndreas Gohr     * @param $label
9412a4e4d1SAndreas Gohr     * @param int $pos
9512a4e4d1SAndreas Gohr     * @return InputElement
9612a4e4d1SAndreas Gohr     */
97de19515fSAndreas Gohr    public function addTextInput($name, $label = '', $pos = -1) {
9812a4e4d1SAndreas Gohr        return $this->addElement(new InputElement('text', $name, $label), $pos);
9912a4e4d1SAndreas Gohr    }
10012a4e4d1SAndreas Gohr
10112a4e4d1SAndreas Gohr    /**
10212a4e4d1SAndreas Gohr     * Adds a password input field
10312a4e4d1SAndreas Gohr     *
10412a4e4d1SAndreas Gohr     * @param $name
10512a4e4d1SAndreas Gohr     * @param $label
10612a4e4d1SAndreas Gohr     * @param int $pos
10712a4e4d1SAndreas Gohr     * @return InputElement
10812a4e4d1SAndreas Gohr     */
109de19515fSAndreas Gohr    public function addPasswordInput($name, $label = '', $pos = -1) {
11012a4e4d1SAndreas Gohr        return $this->addElement(new InputElement('password', $name, $label), $pos);
11112a4e4d1SAndreas Gohr    }
11212a4e4d1SAndreas Gohr
11312a4e4d1SAndreas Gohr    /**
11412a4e4d1SAndreas Gohr     * Adds a radio button field
11512a4e4d1SAndreas Gohr     *
11612a4e4d1SAndreas Gohr     * @param $name
11712a4e4d1SAndreas Gohr     * @param $label
11812a4e4d1SAndreas Gohr     * @param int $pos
11912a4e4d1SAndreas Gohr     * @return CheckableElement
12012a4e4d1SAndreas Gohr     */
121de19515fSAndreas Gohr    public function addRadioButton($name, $label = '', $pos = -1) {
12212a4e4d1SAndreas Gohr        return $this->addElement(new CheckableElement('radio', $name, $label), $pos);
12312a4e4d1SAndreas Gohr    }
12412a4e4d1SAndreas Gohr
12512a4e4d1SAndreas Gohr    /**
12612a4e4d1SAndreas Gohr     * Adds a checkbox field
12712a4e4d1SAndreas Gohr     *
12812a4e4d1SAndreas Gohr     * @param $name
12912a4e4d1SAndreas Gohr     * @param $label
13012a4e4d1SAndreas Gohr     * @param int $pos
13112a4e4d1SAndreas Gohr     * @return CheckableElement
13212a4e4d1SAndreas Gohr     */
133de19515fSAndreas Gohr    public function addCheckbox($name, $label = '', $pos = -1) {
13412a4e4d1SAndreas Gohr        return $this->addElement(new CheckableElement('checkbox', $name, $label), $pos);
13512a4e4d1SAndreas Gohr    }
13612a4e4d1SAndreas Gohr
13712a4e4d1SAndreas Gohr    /**
13812a4e4d1SAndreas Gohr     * Adds a textarea field
13912a4e4d1SAndreas Gohr     *
14012a4e4d1SAndreas Gohr     * @param $name
14112a4e4d1SAndreas Gohr     * @param $label
14212a4e4d1SAndreas Gohr     * @param int $pos
14312a4e4d1SAndreas Gohr     * @return TextareaElement
14412a4e4d1SAndreas Gohr     */
145de19515fSAndreas Gohr    public function addTextarea($name, $label = '', $pos = -1) {
14612a4e4d1SAndreas Gohr        return $this->addElement(new TextareaElement($name, $label), $pos);
14712a4e4d1SAndreas Gohr    }
14812a4e4d1SAndreas Gohr
14912a4e4d1SAndreas Gohr    /**
150de19515fSAndreas Gohr     * Add fixed HTML to the form
151de19515fSAndreas Gohr     *
152de19515fSAndreas Gohr     * @param $html
153de19515fSAndreas Gohr     * @param int $pos
154*64744a10SAndreas Gohr     * @return HTMLElement
155de19515fSAndreas Gohr     */
156de19515fSAndreas Gohr    public function addHTML($html, $pos = -1) {
157de19515fSAndreas Gohr        return $this->addElement(new HTMLElement($html), $pos);
158de19515fSAndreas Gohr    }
159de19515fSAndreas Gohr
160*64744a10SAndreas Gohr    /**
161*64744a10SAndreas Gohr     * Add a closed HTML tag to the form
162*64744a10SAndreas Gohr     *
163*64744a10SAndreas Gohr     * @param $tag
164*64744a10SAndreas Gohr     * @param int $pos
165*64744a10SAndreas Gohr     * @return TagElement
166*64744a10SAndreas Gohr     */
167*64744a10SAndreas Gohr    public function addTag($tag, $pos = -1) {
168*64744a10SAndreas Gohr        return $this->addElement(new TagElement($tag), $pos);
169*64744a10SAndreas Gohr    }
170*64744a10SAndreas Gohr
171*64744a10SAndreas Gohr    /**
172*64744a10SAndreas Gohr     * Add an open HTML tag to the form
173*64744a10SAndreas Gohr     *
174*64744a10SAndreas Gohr     * Be sure to close it again!
175*64744a10SAndreas Gohr     *
176*64744a10SAndreas Gohr     * @param $tag
177*64744a10SAndreas Gohr     * @param int $pos
178*64744a10SAndreas Gohr     * @return TagOpenElement
179*64744a10SAndreas Gohr     */
180*64744a10SAndreas Gohr    public function addTagOpen($tag, $pos = -1) {
181*64744a10SAndreas Gohr        return $this->addElement(new TagOpenElement($tag), $pos);
182*64744a10SAndreas Gohr    }
183*64744a10SAndreas Gohr
184*64744a10SAndreas Gohr    /**
185*64744a10SAndreas Gohr     * Add a closing HTML tag to the form
186*64744a10SAndreas Gohr     *
187*64744a10SAndreas Gohr     * Be sure it had been opened before
188*64744a10SAndreas Gohr     *
189*64744a10SAndreas Gohr     * @param $tag
190*64744a10SAndreas Gohr     * @param int $pos
191*64744a10SAndreas Gohr     * @return TagCloseElement
192*64744a10SAndreas Gohr     */
193*64744a10SAndreas Gohr    public function addTagClose($tag, $pos = -1) {
194*64744a10SAndreas Gohr        return $this->addElement(new TagCloseElement($tag), $pos);
195*64744a10SAndreas Gohr    }
196*64744a10SAndreas Gohr
197*64744a10SAndreas Gohr
198*64744a10SAndreas Gohr    /**
199*64744a10SAndreas Gohr     * Open a Fieldset
200*64744a10SAndreas Gohr     *
201*64744a10SAndreas Gohr     * @param $legend
202*64744a10SAndreas Gohr     * @param int $pos
203*64744a10SAndreas Gohr     * @return FieldsetOpenElement
204*64744a10SAndreas Gohr     */
205*64744a10SAndreas Gohr    public function addFieldsetOpen($legend='', $pos = -1) {
206*64744a10SAndreas Gohr        return $this->addElement(new FieldsetOpenElement($legend), $pos);
207*64744a10SAndreas Gohr    }
208*64744a10SAndreas Gohr
209*64744a10SAndreas Gohr    /**
210*64744a10SAndreas Gohr     * Close a fieldset
211*64744a10SAndreas Gohr     *
212*64744a10SAndreas Gohr     * @param int $pos
213*64744a10SAndreas Gohr     * @return TagCloseElement
214*64744a10SAndreas Gohr     */
215*64744a10SAndreas Gohr    public function addFieldsetClose($pos = -1) {
216*64744a10SAndreas Gohr        return $this->addElement(new FieldsetCloseElement(), $pos);
217*64744a10SAndreas Gohr    }
218*64744a10SAndreas Gohr
219*64744a10SAndreas Gohr    #endregion
220*64744a10SAndreas Gohr
221de19515fSAndreas Gohr    protected function balanceFieldsets() {
222de19515fSAndreas Gohr        //todo implement!
223de19515fSAndreas Gohr    }
224de19515fSAndreas Gohr
225de19515fSAndreas Gohr    /**
22612a4e4d1SAndreas Gohr     * The HTML representation of the whole form
22712a4e4d1SAndreas Gohr     *
22812a4e4d1SAndreas Gohr     * @return string
22912a4e4d1SAndreas Gohr     */
23012a4e4d1SAndreas Gohr    public function toHTML() {
231de19515fSAndreas Gohr        $this->balanceFieldsets();
232de19515fSAndreas Gohr
23312a4e4d1SAndreas Gohr        $html = '<form ' . buildAttributes($this->attrs()) . '>' . DOKU_LF;
23412a4e4d1SAndreas Gohr
23512a4e4d1SAndreas Gohr        foreach($this->hidden as $name => $value) {
23612a4e4d1SAndreas Gohr            $html .= '<input type="hidden" name="' . $name . '" value="' . formText($value) . '" />' . DOKU_LF;
23712a4e4d1SAndreas Gohr        }
23812a4e4d1SAndreas Gohr
23912a4e4d1SAndreas Gohr        foreach($this->elements as $element) {
24012a4e4d1SAndreas Gohr            $html .= $element->toHTML() . DOKU_LF;
24112a4e4d1SAndreas Gohr        }
24212a4e4d1SAndreas Gohr
24312a4e4d1SAndreas Gohr        $html .= '</form>' . DOKU_LF;
24412a4e4d1SAndreas Gohr
24512a4e4d1SAndreas Gohr        return $html;
24612a4e4d1SAndreas Gohr    }
24712a4e4d1SAndreas Gohr}
248