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 277fa270bcSMichael Große * @param bool $unsafe if true, then the security token is ommited 2812a4e4d1SAndreas Gohr */ 297fa270bcSMichael Große public function __construct($attributes = array(), $unsafe = false) { 3012a4e4d1SAndreas Gohr global $ID; 3112a4e4d1SAndreas Gohr 3212a4e4d1SAndreas Gohr parent::__construct('form', $attributes); 3312a4e4d1SAndreas Gohr 3412a4e4d1SAndreas Gohr // use the current URL as default action 3512a4e4d1SAndreas Gohr if(!$this->attr('action')) { 3612a4e4d1SAndreas Gohr $get = $_GET; 3712a4e4d1SAndreas Gohr if(isset($get['id'])) unset($get['id']); 386d0ceaf9SAndreas Gohr $self = wl($ID, $get, false, '&'); //attributes are escaped later 3912a4e4d1SAndreas Gohr $this->attr('action', $self); 4012a4e4d1SAndreas Gohr } 4112a4e4d1SAndreas Gohr 4212a4e4d1SAndreas Gohr // post is default 4312a4e4d1SAndreas Gohr if(!$this->attr('method')) { 4412a4e4d1SAndreas Gohr $this->attr('method', 'post'); 4512a4e4d1SAndreas Gohr } 4612a4e4d1SAndreas Gohr 4712a4e4d1SAndreas Gohr // we like UTF-8 4812a4e4d1SAndreas Gohr if(!$this->attr('accept-charset')) { 4912a4e4d1SAndreas Gohr $this->attr('accept-charset', 'utf-8'); 5012a4e4d1SAndreas Gohr } 5112a4e4d1SAndreas Gohr 5212a4e4d1SAndreas Gohr // add the security token by default 537fa270bcSMichael Große if (!$unsafe) { 5412a4e4d1SAndreas Gohr $this->setHiddenField('sectok', getSecurityToken()); 557fa270bcSMichael Große } 5612a4e4d1SAndreas Gohr 576d0ceaf9SAndreas Gohr // identify this as a new form based form in HTML 586d0ceaf9SAndreas Gohr $this->addClass('doku_form'); 5912a4e4d1SAndreas Gohr } 6012a4e4d1SAndreas Gohr 6112a4e4d1SAndreas Gohr /** 6212a4e4d1SAndreas Gohr * Sets a hidden field 6312a4e4d1SAndreas Gohr * 647ec97767SGerrit Uitslag * @param string $name 657ec97767SGerrit Uitslag * @param string $value 6612a4e4d1SAndreas Gohr * @return $this 6712a4e4d1SAndreas Gohr */ 6812a4e4d1SAndreas Gohr public function setHiddenField($name, $value) { 6912a4e4d1SAndreas Gohr $this->hidden[$name] = $value; 7012a4e4d1SAndreas Gohr return $this; 7112a4e4d1SAndreas Gohr } 7212a4e4d1SAndreas Gohr 73ef0c211bSAndreas Gohr #region element query function 7464744a10SAndreas Gohr 7512a4e4d1SAndreas Gohr /** 76ef0c211bSAndreas Gohr * Returns the numbers of elements in the form 77ef0c211bSAndreas Gohr * 78ef0c211bSAndreas Gohr * @return int 79ef0c211bSAndreas Gohr */ 80ef0c211bSAndreas Gohr public function elementCount() { 81ef0c211bSAndreas Gohr return count($this->elements); 82ef0c211bSAndreas Gohr } 83ef0c211bSAndreas Gohr 84ef0c211bSAndreas Gohr /** 855facb9bcSMichael Große * Get the position of the element in the form or false if it is not in the form 865facb9bcSMichael Große * 87*64159a61SAndreas Gohr * Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates 88*64159a61SAndreas Gohr * to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the 89*64159a61SAndreas Gohr * return value of this function. 905facb9bcSMichael Große * 915facb9bcSMichael Große * @param Element $element 925facb9bcSMichael Große * 935facb9bcSMichael Große * @return false|int 945facb9bcSMichael Große */ 955facb9bcSMichael Große public function getElementPosition(Element $element) 965facb9bcSMichael Große { 975facb9bcSMichael Große return array_search($element, $this->elements, true); 985facb9bcSMichael Große } 995facb9bcSMichael Große 1005facb9bcSMichael Große /** 101ef0c211bSAndreas Gohr * Returns a reference to the element at a position. 102ef0c211bSAndreas Gohr * A position out-of-bounds will return either the 103ef0c211bSAndreas Gohr * first (underflow) or last (overflow) element. 104ef0c211bSAndreas Gohr * 1057ec97767SGerrit Uitslag * @param int $pos 106ef0c211bSAndreas Gohr * @return Element 107ef0c211bSAndreas Gohr */ 108ef0c211bSAndreas Gohr public function getElementAt($pos) { 109ef0c211bSAndreas Gohr if($pos < 0) $pos = count($this->elements) + $pos; 110ef0c211bSAndreas Gohr if($pos < 0) $pos = 0; 111ef0c211bSAndreas Gohr if($pos >= count($this->elements)) $pos = count($this->elements) - 1; 112ef0c211bSAndreas Gohr return $this->elements[$pos]; 113ef0c211bSAndreas Gohr } 114ef0c211bSAndreas Gohr 115ef0c211bSAndreas Gohr /** 116ef0c211bSAndreas Gohr * Gets the position of the first of a type of element 117ef0c211bSAndreas Gohr * 118ef0c211bSAndreas Gohr * @param string $type Element type to look for. 119ef0c211bSAndreas Gohr * @param int $offset search from this position onward 120ef0c211bSAndreas Gohr * @return false|int position of element if found, otherwise false 121ef0c211bSAndreas Gohr */ 122ef0c211bSAndreas Gohr public function findPositionByType($type, $offset = 0) { 123ef0c211bSAndreas Gohr $len = $this->elementCount(); 124ef0c211bSAndreas Gohr for($pos = $offset; $pos < $len; $pos++) { 125ef0c211bSAndreas Gohr if($this->elements[$pos]->getType() == $type) { 126ef0c211bSAndreas Gohr return $pos; 127ef0c211bSAndreas Gohr } 128ef0c211bSAndreas Gohr } 129ef0c211bSAndreas Gohr return false; 130ef0c211bSAndreas Gohr } 131ef0c211bSAndreas Gohr 132ef0c211bSAndreas Gohr /** 133ef0c211bSAndreas Gohr * Gets the position of the first element matching the attribute 134ef0c211bSAndreas Gohr * 135ef0c211bSAndreas Gohr * @param string $name Name of the attribute 136ef0c211bSAndreas Gohr * @param string $value Value the attribute should have 137ef0c211bSAndreas Gohr * @param int $offset search from this position onward 138ef0c211bSAndreas Gohr * @return false|int position of element if found, otherwise false 139ef0c211bSAndreas Gohr */ 140ef0c211bSAndreas Gohr public function findPositionByAttribute($name, $value, $offset = 0) { 141ef0c211bSAndreas Gohr $len = $this->elementCount(); 142ef0c211bSAndreas Gohr for($pos = $offset; $pos < $len; $pos++) { 143ef0c211bSAndreas Gohr if($this->elements[$pos]->attr($name) == $value) { 144ef0c211bSAndreas Gohr return $pos; 145ef0c211bSAndreas Gohr } 146ef0c211bSAndreas Gohr } 147ef0c211bSAndreas Gohr return false; 148ef0c211bSAndreas Gohr } 149ef0c211bSAndreas Gohr 150ef0c211bSAndreas Gohr #endregion 151ef0c211bSAndreas Gohr 152ef0c211bSAndreas Gohr #region Element positioning functions 153ef0c211bSAndreas Gohr 154ef0c211bSAndreas Gohr /** 155ef0c211bSAndreas Gohr * Adds or inserts an element to the form 15612a4e4d1SAndreas Gohr * 15712a4e4d1SAndreas Gohr * @param Element $element 15812a4e4d1SAndreas Gohr * @param int $pos 0-based position in the form, -1 for at the end 15912a4e4d1SAndreas Gohr * @return Element 16012a4e4d1SAndreas Gohr */ 16112a4e4d1SAndreas Gohr public function addElement(Element $element, $pos = -1) { 162*64159a61SAndreas Gohr if(is_a($element, '\dokuwiki\Form\Form')) throw new \InvalidArgumentException( 163*64159a61SAndreas Gohr 'You can\'t add a form to a form' 164*64159a61SAndreas Gohr ); 16512a4e4d1SAndreas Gohr if($pos < 0) { 16612a4e4d1SAndreas Gohr $this->elements[] = $element; 16712a4e4d1SAndreas Gohr } else { 16812a4e4d1SAndreas Gohr array_splice($this->elements, $pos, 0, array($element)); 16912a4e4d1SAndreas Gohr } 17012a4e4d1SAndreas Gohr return $element; 17112a4e4d1SAndreas Gohr } 17212a4e4d1SAndreas Gohr 17312a4e4d1SAndreas Gohr /** 174ef0c211bSAndreas Gohr * Replaces an existing element with a new one 175ef0c211bSAndreas Gohr * 176ef0c211bSAndreas Gohr * @param Element $element the new element 1777ec97767SGerrit Uitslag * @param int $pos 0-based position of the element to replace 178ef0c211bSAndreas Gohr */ 179ef0c211bSAndreas Gohr public function replaceElement(Element $element, $pos) { 180*64159a61SAndreas Gohr if(is_a($element, '\dokuwiki\Form\Form')) throw new \InvalidArgumentException( 181*64159a61SAndreas Gohr 'You can\'t add a form to a form' 182*64159a61SAndreas Gohr ); 183ef0c211bSAndreas Gohr array_splice($this->elements, $pos, 1, array($element)); 184ef0c211bSAndreas Gohr } 185ef0c211bSAndreas Gohr 186ef0c211bSAndreas Gohr /** 187ef0c211bSAndreas Gohr * Remove an element from the form completely 188ef0c211bSAndreas Gohr * 1897ec97767SGerrit Uitslag * @param int $pos 0-based position of the element to remove 190ef0c211bSAndreas Gohr */ 191ef0c211bSAndreas Gohr public function removeElement($pos) { 192ef0c211bSAndreas Gohr array_splice($this->elements, $pos, 1); 193ef0c211bSAndreas Gohr } 194ef0c211bSAndreas Gohr 195ef0c211bSAndreas Gohr #endregion 196ef0c211bSAndreas Gohr 197ef0c211bSAndreas Gohr #region Element adding functions 198ef0c211bSAndreas Gohr 199ef0c211bSAndreas Gohr /** 20012a4e4d1SAndreas Gohr * Adds a text input field 20112a4e4d1SAndreas Gohr * 2027ec97767SGerrit Uitslag * @param string $name 2037ec97767SGerrit Uitslag * @param string $label 20412a4e4d1SAndreas Gohr * @param int $pos 20512a4e4d1SAndreas Gohr * @return InputElement 20612a4e4d1SAndreas Gohr */ 207de19515fSAndreas Gohr public function addTextInput($name, $label = '', $pos = -1) { 20812a4e4d1SAndreas Gohr return $this->addElement(new InputElement('text', $name, $label), $pos); 20912a4e4d1SAndreas Gohr } 21012a4e4d1SAndreas Gohr 21112a4e4d1SAndreas Gohr /** 21212a4e4d1SAndreas Gohr * Adds a password input field 21312a4e4d1SAndreas Gohr * 2147ec97767SGerrit Uitslag * @param string $name 2157ec97767SGerrit Uitslag * @param string $label 21612a4e4d1SAndreas Gohr * @param int $pos 21712a4e4d1SAndreas Gohr * @return InputElement 21812a4e4d1SAndreas Gohr */ 219de19515fSAndreas Gohr public function addPasswordInput($name, $label = '', $pos = -1) { 22012a4e4d1SAndreas Gohr return $this->addElement(new InputElement('password', $name, $label), $pos); 22112a4e4d1SAndreas Gohr } 22212a4e4d1SAndreas Gohr 22312a4e4d1SAndreas Gohr /** 22412a4e4d1SAndreas Gohr * Adds a radio button field 22512a4e4d1SAndreas Gohr * 2267ec97767SGerrit Uitslag * @param string $name 2277ec97767SGerrit Uitslag * @param string $label 22812a4e4d1SAndreas Gohr * @param int $pos 22912a4e4d1SAndreas Gohr * @return CheckableElement 23012a4e4d1SAndreas Gohr */ 231de19515fSAndreas Gohr public function addRadioButton($name, $label = '', $pos = -1) { 23212a4e4d1SAndreas Gohr return $this->addElement(new CheckableElement('radio', $name, $label), $pos); 23312a4e4d1SAndreas Gohr } 23412a4e4d1SAndreas Gohr 23512a4e4d1SAndreas Gohr /** 23612a4e4d1SAndreas Gohr * Adds a checkbox field 23712a4e4d1SAndreas Gohr * 2387ec97767SGerrit Uitslag * @param string $name 2397ec97767SGerrit Uitslag * @param string $label 24012a4e4d1SAndreas Gohr * @param int $pos 24112a4e4d1SAndreas Gohr * @return CheckableElement 24212a4e4d1SAndreas Gohr */ 243de19515fSAndreas Gohr public function addCheckbox($name, $label = '', $pos = -1) { 24412a4e4d1SAndreas Gohr return $this->addElement(new CheckableElement('checkbox', $name, $label), $pos); 24512a4e4d1SAndreas Gohr } 24612a4e4d1SAndreas Gohr 24712a4e4d1SAndreas Gohr /** 2488638ead5SAndreas Gohr * Adds a dropdown field 2498638ead5SAndreas Gohr * 2507ec97767SGerrit Uitslag * @param string $name 2518638ead5SAndreas Gohr * @param array $options 2528638ead5SAndreas Gohr * @param string $label 2538638ead5SAndreas Gohr * @param int $pos 2548638ead5SAndreas Gohr * @return DropdownElement 2558638ead5SAndreas Gohr */ 2568638ead5SAndreas Gohr public function addDropdown($name, $options, $label = '', $pos = -1) { 2578638ead5SAndreas Gohr return $this->addElement(new DropdownElement($name, $options, $label), $pos); 2588638ead5SAndreas Gohr } 2598638ead5SAndreas Gohr 2608638ead5SAndreas Gohr /** 26112a4e4d1SAndreas Gohr * Adds a textarea field 26212a4e4d1SAndreas Gohr * 2637ec97767SGerrit Uitslag * @param string $name 2647ec97767SGerrit Uitslag * @param string $label 26512a4e4d1SAndreas Gohr * @param int $pos 26612a4e4d1SAndreas Gohr * @return TextareaElement 26712a4e4d1SAndreas Gohr */ 268de19515fSAndreas Gohr public function addTextarea($name, $label = '', $pos = -1) { 26912a4e4d1SAndreas Gohr return $this->addElement(new TextareaElement($name, $label), $pos); 27012a4e4d1SAndreas Gohr } 27112a4e4d1SAndreas Gohr 27212a4e4d1SAndreas Gohr /** 2738f0df229SAndreas Gohr * Adds a simple button, escapes the content for you 2748f0df229SAndreas Gohr * 2758f0df229SAndreas Gohr * @param string $name 2768f0df229SAndreas Gohr * @param string $content 2778f0df229SAndreas Gohr * @param int $pos 2788f0df229SAndreas Gohr * @return Element 2798f0df229SAndreas Gohr */ 2808f0df229SAndreas Gohr public function addButton($name, $content, $pos = -1) { 2818f0df229SAndreas Gohr return $this->addElement(new ButtonElement($name, hsc($content)), $pos); 2828f0df229SAndreas Gohr } 2838f0df229SAndreas Gohr 2848f0df229SAndreas Gohr /** 2858f0df229SAndreas Gohr * Adds a simple button, allows HTML for content 2868f0df229SAndreas Gohr * 2878f0df229SAndreas Gohr * @param string $name 2888f0df229SAndreas Gohr * @param string $html 2898f0df229SAndreas Gohr * @param int $pos 2908f0df229SAndreas Gohr * @return Element 2918f0df229SAndreas Gohr */ 2928f0df229SAndreas Gohr public function addButtonHTML($name, $html, $pos = -1) { 2938f0df229SAndreas Gohr return $this->addElement(new ButtonElement($name, $html), $pos); 2948f0df229SAndreas Gohr } 2958f0df229SAndreas Gohr 2968f0df229SAndreas Gohr /** 297a453c16bSAndreas Gohr * Adds a label referencing another input element, escapes the label for you 298a453c16bSAndreas Gohr * 2997ec97767SGerrit Uitslag * @param string $label 300a453c16bSAndreas Gohr * @param string $for 301a453c16bSAndreas Gohr * @param int $pos 302a453c16bSAndreas Gohr * @return Element 303a453c16bSAndreas Gohr */ 304a453c16bSAndreas Gohr public function addLabel($label, $for='', $pos = -1) { 305a453c16bSAndreas Gohr return $this->addLabelHTML(hsc($label), $for, $pos); 306a453c16bSAndreas Gohr } 307a453c16bSAndreas Gohr 308a453c16bSAndreas Gohr /** 309a453c16bSAndreas Gohr * Adds a label referencing another input element, allows HTML for content 310a453c16bSAndreas Gohr * 311a453c16bSAndreas Gohr * @param string $content 312a453c16bSAndreas Gohr * @param string|Element $for 313a453c16bSAndreas Gohr * @param int $pos 314a453c16bSAndreas Gohr * @return Element 315a453c16bSAndreas Gohr */ 316a453c16bSAndreas Gohr public function addLabelHTML($content, $for='', $pos = -1) { 317a453c16bSAndreas Gohr $element = new LabelElement(hsc($content)); 318a453c16bSAndreas Gohr 319a453c16bSAndreas Gohr if(is_a($for, '\dokuwiki\Form\Element')) { 320a453c16bSAndreas Gohr /** @var Element $for */ 321a453c16bSAndreas Gohr $for = $for->id(); 322a453c16bSAndreas Gohr } 323a453c16bSAndreas Gohr $for = (string) $for; 324a453c16bSAndreas Gohr if($for !== '') { 325a453c16bSAndreas Gohr $element->attr('for', $for); 326a453c16bSAndreas Gohr } 327a453c16bSAndreas Gohr 328a453c16bSAndreas Gohr return $this->addElement($element, $pos); 329a453c16bSAndreas Gohr } 330a453c16bSAndreas Gohr 331a453c16bSAndreas Gohr /** 332de19515fSAndreas Gohr * Add fixed HTML to the form 333de19515fSAndreas Gohr * 3347ec97767SGerrit Uitslag * @param string $html 335de19515fSAndreas Gohr * @param int $pos 33664744a10SAndreas Gohr * @return HTMLElement 337de19515fSAndreas Gohr */ 338de19515fSAndreas Gohr public function addHTML($html, $pos = -1) { 339de19515fSAndreas Gohr return $this->addElement(new HTMLElement($html), $pos); 340de19515fSAndreas Gohr } 341de19515fSAndreas Gohr 34264744a10SAndreas Gohr /** 34364744a10SAndreas Gohr * Add a closed HTML tag to the form 34464744a10SAndreas Gohr * 3457ec97767SGerrit Uitslag * @param string $tag 34664744a10SAndreas Gohr * @param int $pos 34764744a10SAndreas Gohr * @return TagElement 34864744a10SAndreas Gohr */ 34964744a10SAndreas Gohr public function addTag($tag, $pos = -1) { 35064744a10SAndreas Gohr return $this->addElement(new TagElement($tag), $pos); 35164744a10SAndreas Gohr } 35264744a10SAndreas Gohr 35364744a10SAndreas Gohr /** 35464744a10SAndreas Gohr * Add an open HTML tag to the form 35564744a10SAndreas Gohr * 35664744a10SAndreas Gohr * Be sure to close it again! 35764744a10SAndreas Gohr * 3587ec97767SGerrit Uitslag * @param string $tag 35964744a10SAndreas Gohr * @param int $pos 36064744a10SAndreas Gohr * @return TagOpenElement 36164744a10SAndreas Gohr */ 36264744a10SAndreas Gohr public function addTagOpen($tag, $pos = -1) { 36364744a10SAndreas Gohr return $this->addElement(new TagOpenElement($tag), $pos); 36464744a10SAndreas Gohr } 36564744a10SAndreas Gohr 36664744a10SAndreas Gohr /** 36764744a10SAndreas Gohr * Add a closing HTML tag to the form 36864744a10SAndreas Gohr * 36964744a10SAndreas Gohr * Be sure it had been opened before 37064744a10SAndreas Gohr * 3717ec97767SGerrit Uitslag * @param string $tag 37264744a10SAndreas Gohr * @param int $pos 37364744a10SAndreas Gohr * @return TagCloseElement 37464744a10SAndreas Gohr */ 37564744a10SAndreas Gohr public function addTagClose($tag, $pos = -1) { 37664744a10SAndreas Gohr return $this->addElement(new TagCloseElement($tag), $pos); 37764744a10SAndreas Gohr } 37864744a10SAndreas Gohr 37964744a10SAndreas Gohr /** 38064744a10SAndreas Gohr * Open a Fieldset 38164744a10SAndreas Gohr * 3827ec97767SGerrit Uitslag * @param string $legend 38364744a10SAndreas Gohr * @param int $pos 38464744a10SAndreas Gohr * @return FieldsetOpenElement 38564744a10SAndreas Gohr */ 38664744a10SAndreas Gohr public function addFieldsetOpen($legend = '', $pos = -1) { 38764744a10SAndreas Gohr return $this->addElement(new FieldsetOpenElement($legend), $pos); 38864744a10SAndreas Gohr } 38964744a10SAndreas Gohr 39064744a10SAndreas Gohr /** 39164744a10SAndreas Gohr * Close a fieldset 39264744a10SAndreas Gohr * 39364744a10SAndreas Gohr * @param int $pos 39464744a10SAndreas Gohr * @return TagCloseElement 39564744a10SAndreas Gohr */ 39664744a10SAndreas Gohr public function addFieldsetClose($pos = -1) { 39764744a10SAndreas Gohr return $this->addElement(new FieldsetCloseElement(), $pos); 39864744a10SAndreas Gohr } 39964744a10SAndreas Gohr 40064744a10SAndreas Gohr #endregion 40164744a10SAndreas Gohr 4021f5d8b65SAndreas Gohr /** 4031f5d8b65SAndreas Gohr * Adjust the elements so that fieldset open and closes are matching 4041f5d8b65SAndreas Gohr */ 405de19515fSAndreas Gohr protected function balanceFieldsets() { 4061f5d8b65SAndreas Gohr $lastclose = 0; 4071f5d8b65SAndreas Gohr $isopen = false; 4081f5d8b65SAndreas Gohr $len = count($this->elements); 4091f5d8b65SAndreas Gohr 4101f5d8b65SAndreas Gohr for($pos = 0; $pos < $len; $pos++) { 4111f5d8b65SAndreas Gohr $type = $this->elements[$pos]->getType(); 4121f5d8b65SAndreas Gohr if($type == 'fieldsetopen') { 4131f5d8b65SAndreas Gohr if($isopen) { 41480b13baaSGerrit Uitslag //close previous fieldset 4151f5d8b65SAndreas Gohr $this->addFieldsetClose($pos); 4161f5d8b65SAndreas Gohr $lastclose = $pos + 1; 4171f5d8b65SAndreas Gohr $pos++; 4181f5d8b65SAndreas Gohr $len++; 4191f5d8b65SAndreas Gohr } 4201f5d8b65SAndreas Gohr $isopen = true; 4211f5d8b65SAndreas Gohr } else if($type == 'fieldsetclose') { 4221f5d8b65SAndreas Gohr if(!$isopen) { 4231f5d8b65SAndreas Gohr // make sure there was a fieldsetopen 4241f5d8b65SAndreas Gohr // either right after the last close or at the begining 4251f5d8b65SAndreas Gohr $this->addFieldsetOpen('', $lastclose); 4261f5d8b65SAndreas Gohr $len++; 4271f5d8b65SAndreas Gohr $pos++; 4281f5d8b65SAndreas Gohr } 4291f5d8b65SAndreas Gohr $lastclose = $pos; 4301f5d8b65SAndreas Gohr $isopen = false; 4311f5d8b65SAndreas Gohr } 4321f5d8b65SAndreas Gohr } 4331f5d8b65SAndreas Gohr 4341f5d8b65SAndreas Gohr // close open fieldset at the end 4351f5d8b65SAndreas Gohr if($isopen) { 4361f5d8b65SAndreas Gohr $this->addFieldsetClose(); 4371f5d8b65SAndreas Gohr } 438de19515fSAndreas Gohr } 439de19515fSAndreas Gohr 440de19515fSAndreas Gohr /** 44112a4e4d1SAndreas Gohr * The HTML representation of the whole form 44212a4e4d1SAndreas Gohr * 44312a4e4d1SAndreas Gohr * @return string 44412a4e4d1SAndreas Gohr */ 44512a4e4d1SAndreas Gohr public function toHTML() { 446de19515fSAndreas Gohr $this->balanceFieldsets(); 447de19515fSAndreas Gohr 44801e3f2b3SMichael Große $html = '<form ' . buildAttributes($this->attrs()) . '>'; 44912a4e4d1SAndreas Gohr 45012a4e4d1SAndreas Gohr foreach($this->hidden as $name => $value) { 45101e3f2b3SMichael Große $html .= '<input type="hidden" name="' . $name . '" value="' . formText($value) . '" />'; 45212a4e4d1SAndreas Gohr } 45312a4e4d1SAndreas Gohr 45412a4e4d1SAndreas Gohr foreach($this->elements as $element) { 45501e3f2b3SMichael Große $html .= $element->toHTML(); 45612a4e4d1SAndreas Gohr } 45712a4e4d1SAndreas Gohr 45801e3f2b3SMichael Große $html .= '</form>'; 45912a4e4d1SAndreas Gohr 46012a4e4d1SAndreas Gohr return $html; 46112a4e4d1SAndreas Gohr } 46212a4e4d1SAndreas Gohr} 463