about summary refs log tree commit diff stats
path: root/wiki/inc/Form/DropdownElement.php
diff options
context:
space:
mode:
authorahriman <ahriman@falte.red>2018-12-03 19:22:25 -0500
committerahriman <ahriman@falte.red>2018-12-03 19:22:25 -0500
commit0ae8cbf5c0b1a198b963490985b7738392ebcb97 (patch)
treeb2c77ae72c6b717e2b97492065196ac5ffb2d9e2 /wiki/inc/Form/DropdownElement.php
parentf57f6cc5a2d159f90168d292437dc4bd8cd7f934 (diff)
downloadsite-0ae8cbf5c0b1a198b963490985b7738392ebcb97.tar.gz
installed dokuwiki, added to navbar, updated news
Diffstat (limited to 'wiki/inc/Form/DropdownElement.php')
-rw-r--r--wiki/inc/Form/DropdownElement.php190
1 files changed, 190 insertions, 0 deletions
diff --git a/wiki/inc/Form/DropdownElement.php b/wiki/inc/Form/DropdownElement.php
new file mode 100644
index 0000000..023b67d
--- /dev/null
+++ b/wiki/inc/Form/DropdownElement.php
@@ -0,0 +1,190 @@
+<?php
+namespace dokuwiki\Form;
+
+/**
+ * Class DropdownElement
+ *
+ * Represents a HTML select. Please note that this does not support multiple selected options!
+ *
+ * @package dokuwiki\Form
+ */
+class DropdownElement extends InputElement {
+
+    /** @var array OptGroup[] */
+    protected $optGroups = array();
+
+    /**
+     * @param string $name The name of this form element
+     * @param array  $options The available options
+     * @param string $label The label text for this element (will be autoescaped)
+     */
+    public function __construct($name, $options, $label = '') {
+        parent::__construct('dropdown', $name, $label);
+        $this->rmattr('type');
+        $this->optGroups[''] = new OptGroup(null, $options);
+        $this->val('');
+    }
+
+    /**
+     * Add an `<optgroup>` and respective options
+     *
+     * @param string $label
+     * @param array  $options
+     * @return OptGroup a reference to the added optgroup
+     * @throws \Exception
+     */
+    public function addOptGroup($label, $options) {
+        if (empty($label)) {
+            throw new \InvalidArgumentException(hsc('<optgroup> must have a label!'));
+        }
+        $this->optGroups[$label] = new OptGroup($label, $options);
+        return end($this->optGroups);
+    }
+
+    /**
+     * Set or get the optgroups of an Dropdown-Element.
+     *
+     * optgroups have to be given as associative array
+     *   * the key being the label of the group
+     *   * the value being an array of options as defined in @see OptGroup::options()
+     *
+     * @param null|array $optGroups
+     * @return OptGroup[]|DropdownElement
+     */
+    public function optGroups($optGroups = null) {
+        if($optGroups === null) {
+            return $this->optGroups;
+        }
+        if (!is_array($optGroups)) {
+            throw new \InvalidArgumentException(hsc('Argument must be an associative array of label => [options]!'));
+        }
+        $this->optGroups = array();
+        foreach ($optGroups as $label => $options) {
+            $this->addOptGroup($label, $options);
+        }
+        return $this;
+    }
+
+    /**
+     * Get or set the options of the Dropdown
+     *
+     * Options can be given as associative array (value => label) or as an
+     * indexd array (label = value) or as an array of arrays. In the latter
+     * case an element has to look as follows:
+     * option-value => array (
+     *                 'label' => option-label,
+     *                 'attrs' => array (
+     *                                    attr-key => attr-value, ...
+     *                                  )
+     *                 )
+     *
+     * @param null|array $options
+     * @return $this|array
+     */
+    public function options($options = null) {
+        if ($options === null) {
+            return $this->optGroups['']->options();
+        }
+        $this->optGroups[''] = new OptGroup(null, $options);
+        return $this;
+    }
+
+    /**
+     * Gets or sets an attribute
+     *
+     * When no $value is given, the current content of the attribute is returned.
+     * An empty string is returned for unset attributes.
+     *
+     * When a $value is given, the content is set to that value and the Element
+     * itself is returned for easy chaining
+     *
+     * @param string $name Name of the attribute to access
+     * @param null|string $value New value to set
+     * @return string|$this
+     */
+    public function attr($name, $value = null) {
+        if(strtolower($name) == 'multiple') {
+            throw new \InvalidArgumentException('Sorry, the dropdown element does not support the "multiple" attribute');
+        }
+        return parent::attr($name, $value);
+    }
+
+    /**
+     * Get or set the current value
+     *
+     * When setting a value that is not defined in the options, the value is ignored
+     * and the first option's value is selected instead
+     *
+     * @param null|string $value The value to set
+     * @return $this|string
+     */
+    public function val($value = null) {
+        if($value === null) return $this->value;
+
+        $value_exists = $this->setValueInOptGroups($value);
+
+        if($value_exists) {
+            $this->value = $value;
+        } else {
+            // unknown value set, select first option instead
+            $this->value = $this->getFirstOption();
+            $this->setValueInOptGroups($this->value);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns the first options as it will be rendered in HTML
+     *
+     * @return string
+     */
+    protected function getFirstOption() {
+        $options = $this->options();
+        if (!empty($options)) {
+            $keys = array_keys($options);
+            return (string) array_shift($keys);
+        }
+        foreach ($this->optGroups as $optGroup) {
+            $options = $optGroup->options();
+            if (!empty($options)) {
+                $keys = array_keys($options);
+                return (string) array_shift($keys);
+            }
+        }
+    }
+
+    /**
+     * Set the value in the OptGroups, including the optgroup for the options without optgroup.
+     *
+     * @param string $value
+     * @return bool
+     */
+    protected function setValueInOptGroups($value) {
+        $value_exists = false;
+        /** @var OptGroup $optGroup */
+        foreach ($this->optGroups as $optGroup) {
+            $value_exists = $optGroup->storeValue($value) || $value_exists;
+            if ($value_exists) {
+                $value = null;
+            }
+        }
+        return $value_exists;
+    }
+
+    /**
+     * Create the HTML for the select it self
+     *
+     * @return string
+     */
+    protected function mainElementHTML() {
+        if($this->useInput) $this->prefillInput();
+
+        $html = '<select ' . buildAttributes($this->attrs()) . '>';
+        $html = array_reduce($this->optGroups, function($html, OptGroup $optGroup) {return $html . $optGroup->toHTML();}, $html);
+        $html .= '</select>';
+
+        return $html;
+    }
+
+}