summaryrefslogtreecommitdiff
path: root/platform/www/inc/Form/DropdownElement.php
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/inc/Form/DropdownElement.php')
-rw-r--r--platform/www/inc/Form/DropdownElement.php198
1 files changed, 198 insertions, 0 deletions
diff --git a/platform/www/inc/Form/DropdownElement.php b/platform/www/inc/Form/DropdownElement.php
new file mode 100644
index 0000000..51f4751
--- /dev/null
+++ b/platform/www/inc/Form/DropdownElement.php
@@ -0,0 +1,198 @@
+<?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;
+ }
+
+}