| 
							- <?php
 - 
 - namespace dokuwiki\Form;
 - 
 - use dokuwiki\Extension\Event;
 - 
 - /**
 -  * Class Form
 -  *
 -  * Represents the whole Form. This is what you work on, and add Elements to
 -  *
 -  * @package dokuwiki\Form
 -  */
 - class Form extends Element
 - {
 -     /**
 -      * @var array name value pairs for hidden values
 -      */
 -     protected $hidden = [];
 - 
 -     /**
 -      * @var Element[] the elements of the form
 -      */
 -     protected $elements = [];
 - 
 -     /**
 -      * Creates a new, empty form with some default attributes
 -      *
 -      * @param array $attributes
 -      * @param bool  $unsafe     if true, then the security token is ommited
 -      */
 -     public function __construct($attributes = [], $unsafe = false)
 -     {
 -         global $ID;
 - 
 -         parent::__construct('form', $attributes);
 - 
 -         // use the current URL as default action
 -         if (!$this->attr('action')) {
 -             $get = $_GET;
 -             if (isset($get['id'])) unset($get['id']);
 -             $self = wl($ID, $get, false, '&'); //attributes are escaped later
 -             $this->attr('action', $self);
 -         }
 - 
 -         // post is default
 -         if (!$this->attr('method')) {
 -             $this->attr('method', 'post');
 -         }
 - 
 -         // we like UTF-8
 -         if (!$this->attr('accept-charset')) {
 -             $this->attr('accept-charset', 'utf-8');
 -         }
 - 
 -         // add the security token by default
 -         if (!$unsafe) {
 -             $this->setHiddenField('sectok', getSecurityToken());
 -         }
 - 
 -         // identify this as a new form based form in HTML
 -         $this->addClass('doku_form');
 -     }
 - 
 -     /**
 -      * Sets a hidden field
 -      *
 -      * @param string $name
 -      * @param string $value
 -      * @return $this
 -      */
 -     public function setHiddenField($name, $value)
 -     {
 -         $this->hidden[$name] = $value;
 -         return $this;
 -     }
 - 
 -     #region element query function
 - 
 -     /**
 -      * Returns the numbers of elements in the form
 -      *
 -      * @return int
 -      */
 -     public function elementCount()
 -     {
 -         return count($this->elements);
 -     }
 - 
 -     /**
 -      * Get the position of the element in the form or false if it is not in the form
 -      *
 -      * Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates
 -      * to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the
 -      * return value of this function.
 -      *
 -      * @param Element $element
 -      *
 -      * @return false|int
 -      */
 -     public function getElementPosition(Element $element)
 -     {
 -         return array_search($element, $this->elements, true);
 -     }
 - 
 -     /**
 -      * Returns a reference to the element at a position.
 -      * A position out-of-bounds will return either the
 -      * first (underflow) or last (overflow) element.
 -      *
 -      * @param int $pos
 -      * @return Element
 -      */
 -     public function getElementAt($pos)
 -     {
 -         if ($pos < 0) $pos = count($this->elements) + $pos;
 -         if ($pos < 0) $pos = 0;
 -         if ($pos >= count($this->elements)) $pos = count($this->elements) - 1;
 -         return $this->elements[$pos];
 -     }
 - 
 -     /**
 -      * Gets the position of the first of a type of element
 -      *
 -      * @param string $type Element type to look for.
 -      * @param int $offset search from this position onward
 -      * @return false|int position of element if found, otherwise false
 -      */
 -     public function findPositionByType($type, $offset = 0)
 -     {
 -         $len = $this->elementCount();
 -         for ($pos = $offset; $pos < $len; $pos++) {
 -             if ($this->elements[$pos]->getType() == $type) {
 -                 return $pos;
 -             }
 -         }
 -         return false;
 -     }
 - 
 -     /**
 -      * Gets the position of the first element matching the attribute
 -      *
 -      * @param string $name Name of the attribute
 -      * @param string $value Value the attribute should have
 -      * @param int $offset search from this position onward
 -      * @return false|int position of element if found, otherwise false
 -      */
 -     public function findPositionByAttribute($name, $value, $offset = 0)
 -     {
 -         $len = $this->elementCount();
 -         for ($pos = $offset; $pos < $len; $pos++) {
 -             if ($this->elements[$pos]->attr($name) == $value) {
 -                 return $pos;
 -             }
 -         }
 -         return false;
 -     }
 - 
 -     #endregion
 - 
 -     #region Element positioning functions
 - 
 -     /**
 -      * Adds or inserts an element to the form
 -      *
 -      * @param Element $element
 -      * @param int $pos 0-based position in the form, -1 for at the end
 -      * @return Element
 -      */
 -     public function addElement(Element $element, $pos = -1)
 -     {
 -         if (is_a($element, '\dokuwiki\Form\Form')) throw new \InvalidArgumentException(
 -             'You can\'t add a form to a form'
 -         );
 -         if ($pos < 0) {
 -             $this->elements[] = $element;
 -         } else {
 -             array_splice($this->elements, $pos, 0, [$element]);
 -         }
 -         return $element;
 -     }
 - 
 -     /**
 -      * Replaces an existing element with a new one
 -      *
 -      * @param Element $element the new element
 -      * @param int $pos 0-based position of the element to replace
 -      */
 -     public function replaceElement(Element $element, $pos)
 -     {
 -         if (is_a($element, '\dokuwiki\Form\Form')) throw new \InvalidArgumentException(
 -             'You can\'t add a form to a form'
 -         );
 -         array_splice($this->elements, $pos, 1, [$element]);
 -     }
 - 
 -     /**
 -      * Remove an element from the form completely
 -      *
 -      * @param int $pos 0-based position of the element to remove
 -      */
 -     public function removeElement($pos)
 -     {
 -         array_splice($this->elements, $pos, 1);
 -     }
 - 
 -     #endregion
 - 
 -     #region Element adding functions
 - 
 -     /**
 -      * Adds a text input field
 -      *
 -      * @param string $name
 -      * @param string $label
 -      * @param int $pos
 -      * @return InputElement
 -      */
 -     public function addTextInput($name, $label = '', $pos = -1)
 -     {
 -         return $this->addElement(new InputElement('text', $name, $label), $pos);
 -     }
 - 
 -     /**
 -      * Adds a password input field
 -      *
 -      * @param string $name
 -      * @param string $label
 -      * @param int $pos
 -      * @return InputElement
 -      */
 -     public function addPasswordInput($name, $label = '', $pos = -1)
 -     {
 -         return $this->addElement(new InputElement('password', $name, $label), $pos);
 -     }
 - 
 -     /**
 -      * Adds a radio button field
 -      *
 -      * @param string $name
 -      * @param string $label
 -      * @param int $pos
 -      * @return CheckableElement
 -      */
 -     public function addRadioButton($name, $label = '', $pos = -1)
 -     {
 -         return $this->addElement(new CheckableElement('radio', $name, $label), $pos);
 -     }
 - 
 -     /**
 -      * Adds a checkbox field
 -      *
 -      * @param string $name
 -      * @param string $label
 -      * @param int $pos
 -      * @return CheckableElement
 -      */
 -     public function addCheckbox($name, $label = '', $pos = -1)
 -     {
 -         return $this->addElement(new CheckableElement('checkbox', $name, $label), $pos);
 -     }
 - 
 -     /**
 -      * Adds a dropdown field
 -      *
 -      * @param string $name
 -      * @param array $options
 -      * @param string $label
 -      * @param int $pos
 -      * @return DropdownElement
 -      */
 -     public function addDropdown($name, $options, $label = '', $pos = -1)
 -     {
 -         return $this->addElement(new DropdownElement($name, $options, $label), $pos);
 -     }
 - 
 -     /**
 -      * Adds a textarea field
 -      *
 -      * @param string $name
 -      * @param string $label
 -      * @param int $pos
 -      * @return TextareaElement
 -      */
 -     public function addTextarea($name, $label = '', $pos = -1)
 -     {
 -         return $this->addElement(new TextareaElement($name, $label), $pos);
 -     }
 - 
 -     /**
 -      * Adds a simple button, escapes the content for you
 -      *
 -      * @param string $name
 -      * @param string $content
 -      * @param int $pos
 -      * @return Element
 -      */
 -     public function addButton($name, $content, $pos = -1)
 -     {
 -         return $this->addElement(new ButtonElement($name, hsc($content)), $pos);
 -     }
 - 
 -     /**
 -      * Adds a simple button, allows HTML for content
 -      *
 -      * @param string $name
 -      * @param string $html
 -      * @param int $pos
 -      * @return Element
 -      */
 -     public function addButtonHTML($name, $html, $pos = -1)
 -     {
 -         return $this->addElement(new ButtonElement($name, $html), $pos);
 -     }
 - 
 -     /**
 -      * Adds a label referencing another input element, escapes the label for you
 -      *
 -      * @param string $label
 -      * @param string $for
 -      * @param int $pos
 -      * @return Element
 -      */
 -     public function addLabel($label, $for = '', $pos = -1)
 -     {
 -         return $this->addLabelHTML(hsc($label), $for, $pos);
 -     }
 - 
 -     /**
 -      * Adds a label referencing another input element, allows HTML for content
 -      *
 -      * @param string $content
 -      * @param string|Element $for
 -      * @param int $pos
 -      * @return Element
 -      */
 -     public function addLabelHTML($content, $for = '', $pos = -1)
 -     {
 -         $element = new LabelElement($content);
 - 
 -         if (is_a($for, '\dokuwiki\Form\Element')) {
 -             /** @var Element $for */
 -             $for = $for->id();
 -         }
 -         $for = (string) $for;
 -         if ($for !== '') {
 -             $element->attr('for', $for);
 -         }
 - 
 -         return $this->addElement($element, $pos);
 -     }
 - 
 -     /**
 -      * Add fixed HTML to the form
 -      *
 -      * @param string $html
 -      * @param int $pos
 -      * @return HTMLElement
 -      */
 -     public function addHTML($html, $pos = -1)
 -     {
 -         return $this->addElement(new HTMLElement($html), $pos);
 -     }
 - 
 -     /**
 -      * Add a closed HTML tag to the form
 -      *
 -      * @param string $tag
 -      * @param int $pos
 -      * @return TagElement
 -      */
 -     public function addTag($tag, $pos = -1)
 -     {
 -         return $this->addElement(new TagElement($tag), $pos);
 -     }
 - 
 -     /**
 -      * Add an open HTML tag to the form
 -      *
 -      * Be sure to close it again!
 -      *
 -      * @param string $tag
 -      * @param int $pos
 -      * @return TagOpenElement
 -      */
 -     public function addTagOpen($tag, $pos = -1)
 -     {
 -         return $this->addElement(new TagOpenElement($tag), $pos);
 -     }
 - 
 -     /**
 -      * Add a closing HTML tag to the form
 -      *
 -      * Be sure it had been opened before
 -      *
 -      * @param string $tag
 -      * @param int $pos
 -      * @return TagCloseElement
 -      */
 -     public function addTagClose($tag, $pos = -1)
 -     {
 -         return $this->addElement(new TagCloseElement($tag), $pos);
 -     }
 - 
 -     /**
 -      * Open a Fieldset
 -      *
 -      * @param string $legend
 -      * @param int $pos
 -      * @return FieldsetOpenElement
 -      */
 -     public function addFieldsetOpen($legend = '', $pos = -1)
 -     {
 -         return $this->addElement(new FieldsetOpenElement($legend), $pos);
 -     }
 - 
 -     /**
 -      * Close a fieldset
 -      *
 -      * @param int $pos
 -      * @return TagCloseElement
 -      */
 -     public function addFieldsetClose($pos = -1)
 -     {
 -         return $this->addElement(new FieldsetCloseElement(), $pos);
 -     }
 - 
 -     #endregion
 - 
 -     /**
 -      * Adjust the elements so that fieldset open and closes are matching
 -      */
 -     protected function balanceFieldsets()
 -     {
 -         $lastclose = 0;
 -         $isopen = false;
 -         $len = count($this->elements);
 - 
 -         for ($pos = 0; $pos < $len; $pos++) {
 -             $type = $this->elements[$pos]->getType();
 -             if ($type == 'fieldsetopen') {
 -                 if ($isopen) {
 -                     //close previous fieldset
 -                     $this->addFieldsetClose($pos);
 -                     $lastclose = $pos + 1;
 -                     $pos++;
 -                     $len++;
 -                 }
 -                 $isopen = true;
 -             } elseif ($type == 'fieldsetclose') {
 -                 if (!$isopen) {
 -                     // make sure there was a fieldsetopen
 -                     // either right after the last close or at the begining
 -                     $this->addFieldsetOpen('', $lastclose);
 -                     $len++;
 -                     $pos++;
 -                 }
 -                 $lastclose = $pos;
 -                 $isopen = false;
 -             }
 -         }
 - 
 -         // close open fieldset at the end
 -         if ($isopen) {
 -             $this->addFieldsetClose();
 -         }
 -     }
 - 
 -     /**
 -      * The HTML representation of the whole form
 -      *
 -      * @param string $eventName  (optional) name of the event: FORM_{$name}_OUTPUT
 -      * @return string
 -      */
 -     public function toHTML($eventName = null)
 -     {
 -         $this->balanceFieldsets();
 - 
 -         // trigger event to provide an opportunity to modify this form
 -         if (isset($eventName)) {
 -             $eventName = 'FORM_' . strtoupper($eventName) . '_OUTPUT';
 -             Event::createAndTrigger($eventName, $this, null, false);
 -         }
 - 
 -         $html = '<form ' . buildAttributes($this->attrs()) . '>';
 - 
 -         foreach ($this->hidden as $name => $value) {
 -             $html .= '<input type="hidden" name="' . $name . '" value="' . formText($value) . '" />';
 -         }
 - 
 -         foreach ($this->elements as $element) {
 -             $html .= $element->toHTML();
 -         }
 - 
 -         $html .= '</form>';
 - 
 -         return $html;
 -     }
 - }
 
 
  |