112a4e4d1SAndreas Gohr<?php 29d01c1d9SSatoshi Sahara 312a4e4d1SAndreas Gohrnamespace dokuwiki\Form; 412a4e4d1SAndreas Gohr 566e555e2SSatoshi Saharause dokuwiki\Extension\Event; 666e555e2SSatoshi Sahara 712a4e4d1SAndreas Gohr/** 812a4e4d1SAndreas Gohr * Class Form 912a4e4d1SAndreas Gohr * 1012a4e4d1SAndreas Gohr * Represents the whole Form. This is what you work on, and add Elements to 1112a4e4d1SAndreas Gohr * 1212a4e4d1SAndreas Gohr * @package dokuwiki\Form 1312a4e4d1SAndreas Gohr */ 149d01c1d9SSatoshi Saharaclass Form extends Element 159d01c1d9SSatoshi Sahara{ 1612a4e4d1SAndreas Gohr /** 1712a4e4d1SAndreas Gohr * @var array name value pairs for hidden values 1812a4e4d1SAndreas Gohr */ 1912a4e4d1SAndreas Gohr protected $hidden = array(); 2012a4e4d1SAndreas Gohr 2112a4e4d1SAndreas Gohr /** 2212a4e4d1SAndreas Gohr * @var Element[] the elements of the form 2312a4e4d1SAndreas Gohr */ 2412a4e4d1SAndreas Gohr protected $elements = array(); 2512a4e4d1SAndreas Gohr 2612a4e4d1SAndreas Gohr /** 2712a4e4d1SAndreas Gohr * Creates a new, empty form with some default attributes 2812a4e4d1SAndreas Gohr * 2912a4e4d1SAndreas Gohr * @param array $attributes 307fa270bcSMichael Große * @param bool $unsafe if true, then the security token is ommited 3112a4e4d1SAndreas Gohr */ 329d01c1d9SSatoshi Sahara public function __construct($attributes = array(), $unsafe = false) 339d01c1d9SSatoshi Sahara { 3412a4e4d1SAndreas Gohr global $ID; 3512a4e4d1SAndreas Gohr 3612a4e4d1SAndreas Gohr parent::__construct('form', $attributes); 3712a4e4d1SAndreas Gohr 3812a4e4d1SAndreas Gohr // use the current URL as default action 3912a4e4d1SAndreas Gohr if (!$this->attr('action')) { 4012a4e4d1SAndreas Gohr $get = $_GET; 4112a4e4d1SAndreas Gohr if (isset($get['id'])) unset($get['id']); 426d0ceaf9SAndreas Gohr $self = wl($ID, $get, false, '&'); //attributes are escaped later 4312a4e4d1SAndreas Gohr $this->attr('action', $self); 4412a4e4d1SAndreas Gohr } 4512a4e4d1SAndreas Gohr 4612a4e4d1SAndreas Gohr // post is default 4712a4e4d1SAndreas Gohr if (!$this->attr('method')) { 4812a4e4d1SAndreas Gohr $this->attr('method', 'post'); 4912a4e4d1SAndreas Gohr } 5012a4e4d1SAndreas Gohr 5112a4e4d1SAndreas Gohr // we like UTF-8 5212a4e4d1SAndreas Gohr if (!$this->attr('accept-charset')) { 5312a4e4d1SAndreas Gohr $this->attr('accept-charset', 'utf-8'); 5412a4e4d1SAndreas Gohr } 5512a4e4d1SAndreas Gohr 5612a4e4d1SAndreas Gohr // add the security token by default 577fa270bcSMichael Große if (!$unsafe) { 5812a4e4d1SAndreas Gohr $this->setHiddenField('sectok', getSecurityToken()); 597fa270bcSMichael Große } 6012a4e4d1SAndreas Gohr 616d0ceaf9SAndreas Gohr // identify this as a new form based form in HTML 626d0ceaf9SAndreas Gohr $this->addClass('doku_form'); 6312a4e4d1SAndreas Gohr } 6412a4e4d1SAndreas Gohr 6512a4e4d1SAndreas Gohr /** 6612a4e4d1SAndreas Gohr * Sets a hidden field 6712a4e4d1SAndreas Gohr * 687ec97767SGerrit Uitslag * @param string $name 697ec97767SGerrit Uitslag * @param string $value 7012a4e4d1SAndreas Gohr * @return $this 7112a4e4d1SAndreas Gohr */ 729d01c1d9SSatoshi Sahara public function setHiddenField($name, $value) 739d01c1d9SSatoshi Sahara { 7412a4e4d1SAndreas Gohr $this->hidden[$name] = $value; 7512a4e4d1SAndreas Gohr return $this; 7612a4e4d1SAndreas Gohr } 7712a4e4d1SAndreas Gohr 78ef0c211bSAndreas Gohr #region element query function 7964744a10SAndreas Gohr 8012a4e4d1SAndreas Gohr /** 81ef0c211bSAndreas Gohr * Returns the numbers of elements in the form 82ef0c211bSAndreas Gohr * 83ef0c211bSAndreas Gohr * @return int 84ef0c211bSAndreas Gohr */ 859d01c1d9SSatoshi Sahara public function elementCount() 869d01c1d9SSatoshi Sahara { 87ef0c211bSAndreas Gohr return count($this->elements); 88ef0c211bSAndreas Gohr } 89ef0c211bSAndreas Gohr 90ef0c211bSAndreas Gohr /** 915facb9bcSMichael Große * Get the position of the element in the form or false if it is not in the form 925facb9bcSMichael Große * 9364159a61SAndreas Gohr * Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates 9464159a61SAndreas Gohr * to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the 9564159a61SAndreas Gohr * return value of this function. 965facb9bcSMichael Große * 975facb9bcSMichael Große * @param Element $element 985facb9bcSMichael Große * 995facb9bcSMichael Große * @return false|int 1005facb9bcSMichael Große */ 1015facb9bcSMichael Große public function getElementPosition(Element $element) 1025facb9bcSMichael Große { 1035facb9bcSMichael Große return array_search($element, $this->elements, true); 1045facb9bcSMichael Große } 1055facb9bcSMichael Große 1065facb9bcSMichael Große /** 107ef0c211bSAndreas Gohr * Returns a reference to the element at a position. 108ef0c211bSAndreas Gohr * A position out-of-bounds will return either the 109ef0c211bSAndreas Gohr * first (underflow) or last (overflow) element. 110ef0c211bSAndreas Gohr * 1117ec97767SGerrit Uitslag * @param int $pos 112ef0c211bSAndreas Gohr * @return Element 113ef0c211bSAndreas Gohr */ 1149d01c1d9SSatoshi Sahara public function getElementAt($pos) 1159d01c1d9SSatoshi Sahara { 116ef0c211bSAndreas Gohr if ($pos < 0) $pos = count($this->elements) + $pos; 117ef0c211bSAndreas Gohr if ($pos < 0) $pos = 0; 118ef0c211bSAndreas Gohr if ($pos >= count($this->elements)) $pos = count($this->elements) - 1; 119ef0c211bSAndreas Gohr return $this->elements[$pos]; 120ef0c211bSAndreas Gohr } 121ef0c211bSAndreas Gohr 122ef0c211bSAndreas Gohr /** 123ef0c211bSAndreas Gohr * Gets the position of the first of a type of element 124ef0c211bSAndreas Gohr * 125ef0c211bSAndreas Gohr * @param string $type Element type to look for. 126ef0c211bSAndreas Gohr * @param int $offset search from this position onward 127ef0c211bSAndreas Gohr * @return false|int position of element if found, otherwise false 128ef0c211bSAndreas Gohr */ 1299d01c1d9SSatoshi Sahara public function findPositionByType($type, $offset = 0) 1309d01c1d9SSatoshi Sahara { 131ef0c211bSAndreas Gohr $len = $this->elementCount(); 132ef0c211bSAndreas Gohr for ($pos = $offset; $pos < $len; $pos++) { 133ef0c211bSAndreas Gohr if ($this->elements[$pos]->getType() == $type) { 134ef0c211bSAndreas Gohr return $pos; 135ef0c211bSAndreas Gohr } 136ef0c211bSAndreas Gohr } 137ef0c211bSAndreas Gohr return false; 138ef0c211bSAndreas Gohr } 139ef0c211bSAndreas Gohr 140ef0c211bSAndreas Gohr /** 141ef0c211bSAndreas Gohr * Gets the position of the first element matching the attribute 142ef0c211bSAndreas Gohr * 143ef0c211bSAndreas Gohr * @param string $name Name of the attribute 144ef0c211bSAndreas Gohr * @param string $value Value the attribute should have 145ef0c211bSAndreas Gohr * @param int $offset search from this position onward 146ef0c211bSAndreas Gohr * @return false|int position of element if found, otherwise false 147ef0c211bSAndreas Gohr */ 1489d01c1d9SSatoshi Sahara public function findPositionByAttribute($name, $value, $offset = 0) 1499d01c1d9SSatoshi Sahara { 150ef0c211bSAndreas Gohr $len = $this->elementCount(); 151ef0c211bSAndreas Gohr for ($pos = $offset; $pos < $len; $pos++) { 152ef0c211bSAndreas Gohr if ($this->elements[$pos]->attr($name) == $value) { 153ef0c211bSAndreas Gohr return $pos; 154ef0c211bSAndreas Gohr } 155ef0c211bSAndreas Gohr } 156ef0c211bSAndreas Gohr return false; 157ef0c211bSAndreas Gohr } 158ef0c211bSAndreas Gohr 159ef0c211bSAndreas Gohr #endregion 160ef0c211bSAndreas Gohr 161ef0c211bSAndreas Gohr #region Element positioning functions 162ef0c211bSAndreas Gohr 163ef0c211bSAndreas Gohr /** 164ef0c211bSAndreas Gohr * Adds or inserts an element to the form 16512a4e4d1SAndreas Gohr * 16612a4e4d1SAndreas Gohr * @param Element $element 16712a4e4d1SAndreas Gohr * @param int $pos 0-based position in the form, -1 for at the end 16812a4e4d1SAndreas Gohr * @return Element 16912a4e4d1SAndreas Gohr */ 1709d01c1d9SSatoshi Sahara public function addElement(Element $element, $pos = -1) 1719d01c1d9SSatoshi Sahara { 17264159a61SAndreas Gohr if (is_a($element, '\dokuwiki\Form\Form')) throw new \InvalidArgumentException( 17364159a61SAndreas Gohr 'You can\'t add a form to a form' 17464159a61SAndreas Gohr ); 17512a4e4d1SAndreas Gohr if ($pos < 0) { 17612a4e4d1SAndreas Gohr $this->elements[] = $element; 17712a4e4d1SAndreas Gohr } else { 17812a4e4d1SAndreas Gohr array_splice($this->elements, $pos, 0, array($element)); 17912a4e4d1SAndreas Gohr } 18012a4e4d1SAndreas Gohr return $element; 18112a4e4d1SAndreas Gohr } 18212a4e4d1SAndreas Gohr 18312a4e4d1SAndreas Gohr /** 184ef0c211bSAndreas Gohr * Replaces an existing element with a new one 185ef0c211bSAndreas Gohr * 186ef0c211bSAndreas Gohr * @param Element $element the new element 1877ec97767SGerrit Uitslag * @param int $pos 0-based position of the element to replace 188ef0c211bSAndreas Gohr */ 1899d01c1d9SSatoshi Sahara public function replaceElement(Element $element, $pos) 1909d01c1d9SSatoshi Sahara { 19164159a61SAndreas Gohr if (is_a($element, '\dokuwiki\Form\Form')) throw new \InvalidArgumentException( 19264159a61SAndreas Gohr 'You can\'t add a form to a form' 19364159a61SAndreas Gohr ); 194ef0c211bSAndreas Gohr array_splice($this->elements, $pos, 1, array($element)); 195ef0c211bSAndreas Gohr } 196ef0c211bSAndreas Gohr 197ef0c211bSAndreas Gohr /** 198ef0c211bSAndreas Gohr * Remove an element from the form completely 199ef0c211bSAndreas Gohr * 2007ec97767SGerrit Uitslag * @param int $pos 0-based position of the element to remove 201ef0c211bSAndreas Gohr */ 2029d01c1d9SSatoshi Sahara public function removeElement($pos) 2039d01c1d9SSatoshi Sahara { 204ef0c211bSAndreas Gohr array_splice($this->elements, $pos, 1); 205ef0c211bSAndreas Gohr } 206ef0c211bSAndreas Gohr 207ef0c211bSAndreas Gohr #endregion 208ef0c211bSAndreas Gohr 209ef0c211bSAndreas Gohr #region Element adding functions 210ef0c211bSAndreas Gohr 211ef0c211bSAndreas Gohr /** 21212a4e4d1SAndreas Gohr * Adds a text 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 */ 2199d01c1d9SSatoshi Sahara public function addTextInput($name, $label = '', $pos = -1) 2209d01c1d9SSatoshi Sahara { 22112a4e4d1SAndreas Gohr return $this->addElement(new InputElement('text', $name, $label), $pos); 22212a4e4d1SAndreas Gohr } 22312a4e4d1SAndreas Gohr 22412a4e4d1SAndreas Gohr /** 22512a4e4d1SAndreas Gohr * Adds a password input field 22612a4e4d1SAndreas Gohr * 2277ec97767SGerrit Uitslag * @param string $name 2287ec97767SGerrit Uitslag * @param string $label 22912a4e4d1SAndreas Gohr * @param int $pos 23012a4e4d1SAndreas Gohr * @return InputElement 23112a4e4d1SAndreas Gohr */ 2329d01c1d9SSatoshi Sahara public function addPasswordInput($name, $label = '', $pos = -1) 2339d01c1d9SSatoshi Sahara { 23412a4e4d1SAndreas Gohr return $this->addElement(new InputElement('password', $name, $label), $pos); 23512a4e4d1SAndreas Gohr } 23612a4e4d1SAndreas Gohr 23712a4e4d1SAndreas Gohr /** 23812a4e4d1SAndreas Gohr * Adds a radio button field 23912a4e4d1SAndreas Gohr * 2407ec97767SGerrit Uitslag * @param string $name 2417ec97767SGerrit Uitslag * @param string $label 24212a4e4d1SAndreas Gohr * @param int $pos 24312a4e4d1SAndreas Gohr * @return CheckableElement 24412a4e4d1SAndreas Gohr */ 2459d01c1d9SSatoshi Sahara public function addRadioButton($name, $label = '', $pos = -1) 2469d01c1d9SSatoshi Sahara { 24712a4e4d1SAndreas Gohr return $this->addElement(new CheckableElement('radio', $name, $label), $pos); 24812a4e4d1SAndreas Gohr } 24912a4e4d1SAndreas Gohr 25012a4e4d1SAndreas Gohr /** 25112a4e4d1SAndreas Gohr * Adds a checkbox field 25212a4e4d1SAndreas Gohr * 2537ec97767SGerrit Uitslag * @param string $name 2547ec97767SGerrit Uitslag * @param string $label 25512a4e4d1SAndreas Gohr * @param int $pos 25612a4e4d1SAndreas Gohr * @return CheckableElement 25712a4e4d1SAndreas Gohr */ 2589d01c1d9SSatoshi Sahara public function addCheckbox($name, $label = '', $pos = -1) 2599d01c1d9SSatoshi Sahara { 26012a4e4d1SAndreas Gohr return $this->addElement(new CheckableElement('checkbox', $name, $label), $pos); 26112a4e4d1SAndreas Gohr } 26212a4e4d1SAndreas Gohr 26312a4e4d1SAndreas Gohr /** 2648638ead5SAndreas Gohr * Adds a dropdown field 2658638ead5SAndreas Gohr * 2667ec97767SGerrit Uitslag * @param string $name 2678638ead5SAndreas Gohr * @param array $options 2688638ead5SAndreas Gohr * @param string $label 2698638ead5SAndreas Gohr * @param int $pos 2708638ead5SAndreas Gohr * @return DropdownElement 2718638ead5SAndreas Gohr */ 2729d01c1d9SSatoshi Sahara public function addDropdown($name, $options, $label = '', $pos = -1) 2739d01c1d9SSatoshi Sahara { 2748638ead5SAndreas Gohr return $this->addElement(new DropdownElement($name, $options, $label), $pos); 2758638ead5SAndreas Gohr } 2768638ead5SAndreas Gohr 2778638ead5SAndreas Gohr /** 27812a4e4d1SAndreas Gohr * Adds a textarea field 27912a4e4d1SAndreas Gohr * 2807ec97767SGerrit Uitslag * @param string $name 2817ec97767SGerrit Uitslag * @param string $label 28212a4e4d1SAndreas Gohr * @param int $pos 28312a4e4d1SAndreas Gohr * @return TextareaElement 28412a4e4d1SAndreas Gohr */ 2859d01c1d9SSatoshi Sahara public function addTextarea($name, $label = '', $pos = -1) 2869d01c1d9SSatoshi Sahara { 28712a4e4d1SAndreas Gohr return $this->addElement(new TextareaElement($name, $label), $pos); 28812a4e4d1SAndreas Gohr } 28912a4e4d1SAndreas Gohr 29012a4e4d1SAndreas Gohr /** 2918f0df229SAndreas Gohr * Adds a simple button, escapes the content for you 2928f0df229SAndreas Gohr * 2938f0df229SAndreas Gohr * @param string $name 2948f0df229SAndreas Gohr * @param string $content 2958f0df229SAndreas Gohr * @param int $pos 2968f0df229SAndreas Gohr * @return Element 2978f0df229SAndreas Gohr */ 2989d01c1d9SSatoshi Sahara public function addButton($name, $content, $pos = -1) 2999d01c1d9SSatoshi Sahara { 3008f0df229SAndreas Gohr return $this->addElement(new ButtonElement($name, hsc($content)), $pos); 3018f0df229SAndreas Gohr } 3028f0df229SAndreas Gohr 3038f0df229SAndreas Gohr /** 3048f0df229SAndreas Gohr * Adds a simple button, allows HTML for content 3058f0df229SAndreas Gohr * 3068f0df229SAndreas Gohr * @param string $name 3078f0df229SAndreas Gohr * @param string $html 3088f0df229SAndreas Gohr * @param int $pos 3098f0df229SAndreas Gohr * @return Element 3108f0df229SAndreas Gohr */ 3119d01c1d9SSatoshi Sahara public function addButtonHTML($name, $html, $pos = -1) 3129d01c1d9SSatoshi Sahara { 3138f0df229SAndreas Gohr return $this->addElement(new ButtonElement($name, $html), $pos); 3148f0df229SAndreas Gohr } 3158f0df229SAndreas Gohr 3168f0df229SAndreas Gohr /** 317a453c16bSAndreas Gohr * Adds a label referencing another input element, escapes the label for you 318a453c16bSAndreas Gohr * 3197ec97767SGerrit Uitslag * @param string $label 320a453c16bSAndreas Gohr * @param string $for 321a453c16bSAndreas Gohr * @param int $pos 322a453c16bSAndreas Gohr * @return Element 323a453c16bSAndreas Gohr */ 3249d01c1d9SSatoshi Sahara public function addLabel($label, $for='', $pos = -1) 3259d01c1d9SSatoshi Sahara { 326a453c16bSAndreas Gohr return $this->addLabelHTML(hsc($label), $for, $pos); 327a453c16bSAndreas Gohr } 328a453c16bSAndreas Gohr 329a453c16bSAndreas Gohr /** 330a453c16bSAndreas Gohr * Adds a label referencing another input element, allows HTML for content 331a453c16bSAndreas Gohr * 332a453c16bSAndreas Gohr * @param string $content 333a453c16bSAndreas Gohr * @param string|Element $for 334a453c16bSAndreas Gohr * @param int $pos 335a453c16bSAndreas Gohr * @return Element 336a453c16bSAndreas Gohr */ 3379d01c1d9SSatoshi Sahara public function addLabelHTML($content, $for='', $pos = -1) 3389d01c1d9SSatoshi Sahara { 339a453c16bSAndreas Gohr $element = new LabelElement(hsc($content)); 340a453c16bSAndreas Gohr 341a453c16bSAndreas Gohr if (is_a($for, '\dokuwiki\Form\Element')) { 342a453c16bSAndreas Gohr /** @var Element $for */ 343a453c16bSAndreas Gohr $for = $for->id(); 344a453c16bSAndreas Gohr } 345a453c16bSAndreas Gohr $for = (string) $for; 346a453c16bSAndreas Gohr if ($for !== '') { 347a453c16bSAndreas Gohr $element->attr('for', $for); 348a453c16bSAndreas Gohr } 349a453c16bSAndreas Gohr 350a453c16bSAndreas Gohr return $this->addElement($element, $pos); 351a453c16bSAndreas Gohr } 352a453c16bSAndreas Gohr 353a453c16bSAndreas Gohr /** 354de19515fSAndreas Gohr * Add fixed HTML to the form 355de19515fSAndreas Gohr * 3567ec97767SGerrit Uitslag * @param string $html 357de19515fSAndreas Gohr * @param int $pos 35864744a10SAndreas Gohr * @return HTMLElement 359de19515fSAndreas Gohr */ 3609d01c1d9SSatoshi Sahara public function addHTML($html, $pos = -1) 3619d01c1d9SSatoshi Sahara { 362de19515fSAndreas Gohr return $this->addElement(new HTMLElement($html), $pos); 363de19515fSAndreas Gohr } 364de19515fSAndreas Gohr 36564744a10SAndreas Gohr /** 36664744a10SAndreas Gohr * Add a closed HTML tag to the form 36764744a10SAndreas Gohr * 3687ec97767SGerrit Uitslag * @param string $tag 36964744a10SAndreas Gohr * @param int $pos 37064744a10SAndreas Gohr * @return TagElement 37164744a10SAndreas Gohr */ 3729d01c1d9SSatoshi Sahara public function addTag($tag, $pos = -1) 3739d01c1d9SSatoshi Sahara { 37464744a10SAndreas Gohr return $this->addElement(new TagElement($tag), $pos); 37564744a10SAndreas Gohr } 37664744a10SAndreas Gohr 37764744a10SAndreas Gohr /** 37864744a10SAndreas Gohr * Add an open HTML tag to the form 37964744a10SAndreas Gohr * 38064744a10SAndreas Gohr * Be sure to close it again! 38164744a10SAndreas Gohr * 3827ec97767SGerrit Uitslag * @param string $tag 38364744a10SAndreas Gohr * @param int $pos 38464744a10SAndreas Gohr * @return TagOpenElement 38564744a10SAndreas Gohr */ 3869d01c1d9SSatoshi Sahara public function addTagOpen($tag, $pos = -1) 3879d01c1d9SSatoshi Sahara { 38864744a10SAndreas Gohr return $this->addElement(new TagOpenElement($tag), $pos); 38964744a10SAndreas Gohr } 39064744a10SAndreas Gohr 39164744a10SAndreas Gohr /** 39264744a10SAndreas Gohr * Add a closing HTML tag to the form 39364744a10SAndreas Gohr * 39464744a10SAndreas Gohr * Be sure it had been opened before 39564744a10SAndreas Gohr * 3967ec97767SGerrit Uitslag * @param string $tag 39764744a10SAndreas Gohr * @param int $pos 39864744a10SAndreas Gohr * @return TagCloseElement 39964744a10SAndreas Gohr */ 4009d01c1d9SSatoshi Sahara public function addTagClose($tag, $pos = -1) 4019d01c1d9SSatoshi Sahara { 40264744a10SAndreas Gohr return $this->addElement(new TagCloseElement($tag), $pos); 40364744a10SAndreas Gohr } 40464744a10SAndreas Gohr 40564744a10SAndreas Gohr /** 40664744a10SAndreas Gohr * Open a Fieldset 40764744a10SAndreas Gohr * 4087ec97767SGerrit Uitslag * @param string $legend 40964744a10SAndreas Gohr * @param int $pos 41064744a10SAndreas Gohr * @return FieldsetOpenElement 41164744a10SAndreas Gohr */ 4129d01c1d9SSatoshi Sahara public function addFieldsetOpen($legend = '', $pos = -1) 4139d01c1d9SSatoshi Sahara { 41464744a10SAndreas Gohr return $this->addElement(new FieldsetOpenElement($legend), $pos); 41564744a10SAndreas Gohr } 41664744a10SAndreas Gohr 41764744a10SAndreas Gohr /** 41864744a10SAndreas Gohr * Close a fieldset 41964744a10SAndreas Gohr * 42064744a10SAndreas Gohr * @param int $pos 42164744a10SAndreas Gohr * @return TagCloseElement 42264744a10SAndreas Gohr */ 4239d01c1d9SSatoshi Sahara public function addFieldsetClose($pos = -1) 4249d01c1d9SSatoshi Sahara { 42564744a10SAndreas Gohr return $this->addElement(new FieldsetCloseElement(), $pos); 42664744a10SAndreas Gohr } 42764744a10SAndreas Gohr 42864744a10SAndreas Gohr #endregion 42964744a10SAndreas Gohr 4301f5d8b65SAndreas Gohr /** 4311f5d8b65SAndreas Gohr * Adjust the elements so that fieldset open and closes are matching 4321f5d8b65SAndreas Gohr */ 4339d01c1d9SSatoshi Sahara protected function balanceFieldsets() 4349d01c1d9SSatoshi Sahara { 4351f5d8b65SAndreas Gohr $lastclose = 0; 4361f5d8b65SAndreas Gohr $isopen = false; 4371f5d8b65SAndreas Gohr $len = count($this->elements); 4381f5d8b65SAndreas Gohr 4391f5d8b65SAndreas Gohr for ($pos = 0; $pos < $len; $pos++) { 4401f5d8b65SAndreas Gohr $type = $this->elements[$pos]->getType(); 4411f5d8b65SAndreas Gohr if ($type == 'fieldsetopen') { 4421f5d8b65SAndreas Gohr if ($isopen) { 44380b13baaSGerrit Uitslag //close previous fieldset 4441f5d8b65SAndreas Gohr $this->addFieldsetClose($pos); 4451f5d8b65SAndreas Gohr $lastclose = $pos + 1; 4461f5d8b65SAndreas Gohr $pos++; 4471f5d8b65SAndreas Gohr $len++; 4481f5d8b65SAndreas Gohr } 4491f5d8b65SAndreas Gohr $isopen = true; 4501f5d8b65SAndreas Gohr } elseif ($type == 'fieldsetclose') { 4511f5d8b65SAndreas Gohr if (!$isopen) { 4521f5d8b65SAndreas Gohr // make sure there was a fieldsetopen 4531f5d8b65SAndreas Gohr // either right after the last close or at the begining 4541f5d8b65SAndreas Gohr $this->addFieldsetOpen('', $lastclose); 4551f5d8b65SAndreas Gohr $len++; 4561f5d8b65SAndreas Gohr $pos++; 4571f5d8b65SAndreas Gohr } 4581f5d8b65SAndreas Gohr $lastclose = $pos; 4591f5d8b65SAndreas Gohr $isopen = false; 4601f5d8b65SAndreas Gohr } 4611f5d8b65SAndreas Gohr } 4621f5d8b65SAndreas Gohr 4631f5d8b65SAndreas Gohr // close open fieldset at the end 4641f5d8b65SAndreas Gohr if ($isopen) { 4651f5d8b65SAndreas Gohr $this->addFieldsetClose(); 4661f5d8b65SAndreas Gohr } 467de19515fSAndreas Gohr } 468de19515fSAndreas Gohr 469de19515fSAndreas Gohr /** 47012a4e4d1SAndreas Gohr * The HTML representation of the whole form 47112a4e4d1SAndreas Gohr * 472*c6977b3aSSatoshi Sahara * @param string $eventName (optional) name of the event: FORM_{$name}_OUTPUT 47312a4e4d1SAndreas Gohr * @return string 47412a4e4d1SAndreas Gohr */ 4750dd35558SSatoshi Sahara public function toHTML($eventName = null) 4769d01c1d9SSatoshi Sahara { 477de19515fSAndreas Gohr $this->balanceFieldsets(); 478de19515fSAndreas Gohr 4790dd35558SSatoshi Sahara // trigger event to provide an opportunity to modify this form 4800dd35558SSatoshi Sahara if (isset($eventName)) { 481*c6977b3aSSatoshi Sahara $eventName = 'FORM_'.strtoupper($eventName).'_OUTPUT'; 4820dd35558SSatoshi Sahara Event::createAndTrigger($eventName, $this, null, false); 4830dd35558SSatoshi Sahara } 4840dd35558SSatoshi Sahara 48501e3f2b3SMichael Große $html = '<form '. buildAttributes($this->attrs()) .'>'; 48612a4e4d1SAndreas Gohr 48712a4e4d1SAndreas Gohr foreach ($this->hidden as $name => $value) { 48801e3f2b3SMichael Große $html .= '<input type="hidden" name="'. $name .'" value="'. formText($value) .'" />'; 48912a4e4d1SAndreas Gohr } 49012a4e4d1SAndreas Gohr 49112a4e4d1SAndreas Gohr foreach ($this->elements as $element) { 49201e3f2b3SMichael Große $html .= $element->toHTML(); 49312a4e4d1SAndreas Gohr } 49412a4e4d1SAndreas Gohr 49501e3f2b3SMichael Große $html .= '</form>'; 49612a4e4d1SAndreas Gohr 49712a4e4d1SAndreas Gohr return $html; 49812a4e4d1SAndreas Gohr } 49912a4e4d1SAndreas Gohr} 500