summaryrefslogtreecommitdiffstats
path: root/vendor/ipl/html/src/FormElement/FormElements.php
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:30:08 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:30:08 +0000
commit4ce65d59ca91871cfd126497158200a818720bce (patch)
treee277def01fc7eba7dbc21c4a4ae5576e8aa2cf1f /vendor/ipl/html/src/FormElement/FormElements.php
parentInitial commit. (diff)
downloadicinga-php-library-4ce65d59ca91871cfd126497158200a818720bce.tar.xz
icinga-php-library-4ce65d59ca91871cfd126497158200a818720bce.zip
Adding upstream version 0.13.1.upstream/0.13.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ipl/html/src/FormElement/FormElements.php')
-rw-r--r--vendor/ipl/html/src/FormElement/FormElements.php509
1 files changed, 509 insertions, 0 deletions
diff --git a/vendor/ipl/html/src/FormElement/FormElements.php b/vendor/ipl/html/src/FormElement/FormElements.php
new file mode 100644
index 0000000..4a2c598
--- /dev/null
+++ b/vendor/ipl/html/src/FormElement/FormElements.php
@@ -0,0 +1,509 @@
+<?php
+
+namespace ipl\Html\FormElement;
+
+use InvalidArgumentException;
+use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecorator;
+use ipl\Html\Contract\ValueCandidates;
+use ipl\Html\Form;
+use ipl\Html\FormDecorator\DecoratorInterface;
+use ipl\Html\ValidHtml;
+use ipl\Stdlib\Events;
+use ipl\Stdlib\Plugins;
+use UnexpectedValueException;
+
+use function ipl\Stdlib\get_php_type;
+
+trait FormElements
+{
+ use Events;
+ use Plugins;
+
+ /** @var FormElementDecorator|null */
+ private $defaultElementDecorator;
+
+ /** @var bool Whether the default element decorator loader has been registered */
+ protected $defaultElementDecoratorLoaderRegistered = false;
+
+ /** @var bool Whether the default element loader has been registered */
+ protected $defaultElementLoaderRegistered = false;
+
+ /** @var FormElement[] */
+ private $elements = [];
+
+ /** @var array<string, array<int, mixed>> */
+ private $populatedValues = [];
+
+ /**
+ * Get all elements
+ *
+ * @return FormElement[]
+ */
+ public function getElements()
+ {
+ return $this->elements;
+ }
+
+ /**
+ * Get whether the given element exists
+ *
+ * @param string|FormElement $element
+ *
+ * @return bool
+ */
+ public function hasElement($element)
+ {
+ if (is_string($element)) {
+ return array_key_exists($element, $this->elements);
+ }
+
+ if ($element instanceof FormElement) {
+ return in_array($element, $this->elements, true);
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the element by the given name
+ *
+ * @param string $name
+ *
+ * @return FormElement
+ *
+ * @throws InvalidArgumentException If no element with the given name exists
+ */
+ public function getElement($name)
+ {
+ if (! array_key_exists($name, $this->elements)) {
+ throw new InvalidArgumentException(sprintf(
+ "Can't get element '%s'. Element does not exist",
+ $name
+ ));
+ }
+
+ return $this->elements[$name];
+ }
+
+ /**
+ * Add an element
+ *
+ * @param string|FormElement $typeOrElement Type of the element as string or an instance of FormElement
+ * @param string $name Name of the element
+ * @param mixed $options Element options as key-value pairs
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If $typeOrElement is neither a string nor an instance of FormElement
+ * or if $typeOrElement is a string and $name is not set
+ * or if $typeOrElement is a string but type is unknown
+ * or if $typeOrElement is an instance of FormElement but does not have a name
+ */
+ public function addElement($typeOrElement, $name = null, $options = null)
+ {
+ if (is_string($typeOrElement)) {
+ if ($name === null) {
+ throw new InvalidArgumentException(sprintf(
+ '%s expects parameter 2 to be set if parameter 1 is a string',
+ __METHOD__
+ ));
+ }
+
+ $element = $this->createElement($typeOrElement, $name, $options);
+ } elseif ($typeOrElement instanceof FormElement) {
+ $element = $typeOrElement;
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ '%s() expects parameter 1 to be a string or an instance of %s, %s given',
+ __METHOD__,
+ FormElement::class,
+ get_php_type($typeOrElement)
+ ));
+ }
+
+ $this
+ ->registerElement($element) // registerElement() must be called first because of the name check
+ ->decorate($element)
+ ->addHtml($element);
+
+ return $this;
+ }
+
+ /**
+ * Create an element
+ *
+ * @param string $type Type of the element
+ * @param string $name Name of the element
+ * @param mixed $options Element options as key-value pairs
+ *
+ * @return FormElement
+ *
+ * @throws InvalidArgumentException If the type of the element is unknown
+ */
+ public function createElement($type, $name, $options = null)
+ {
+ $this->ensureDefaultElementLoaderRegistered();
+
+ $class = $this->loadPlugin('element', $type);
+
+ if (! $class) {
+ throw new InvalidArgumentException(sprintf(
+ "Can't create element of unknown type '%s",
+ $type
+ ));
+ }
+
+ /** @var FormElement $element */
+ $element = new $class($name);
+
+ if ($options !== null) {
+ $element->addAttributes($options);
+ }
+
+ return $element;
+ }
+
+ /**
+ * Register an element
+ *
+ * Registers the element for value and validation handling but does not add it to the render stack.
+ *
+ * @param FormElement $element
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If $element does not provide a name
+ */
+ public function registerElement(FormElement $element)
+ {
+ $name = $element->getName();
+
+ if ($name === null) {
+ throw new InvalidArgumentException(sprintf(
+ '%s expects the element to provide a name',
+ __METHOD__
+ ));
+ }
+
+ $this->elements[$name] = $element;
+
+ if (array_key_exists($name, $this->populatedValues)) {
+ $element->setValue($this->populatedValues[$name][count($this->populatedValues[$name]) - 1]);
+
+ if ($element instanceof ValueCandidates) {
+ $element->setValueCandidates($this->populatedValues[$name]);
+ }
+ }
+
+ $this->onElementRegistered($element);
+ $this->emit(Form::ON_ELEMENT_REGISTERED, [$element]);
+
+ return $this;
+ }
+
+ /**
+ * Get whether a default element decorator exists
+ *
+ * @return bool
+ */
+ public function hasDefaultElementDecorator()
+ {
+ return $this->defaultElementDecorator !== null;
+ }
+
+ /**
+ * Get the default element decorator, if any
+ *
+ * @return FormElementDecorator|null
+ */
+ public function getDefaultElementDecorator()
+ {
+ return $this->defaultElementDecorator;
+ }
+
+ /**
+ * Set the default element decorator
+ *
+ * If $decorator is a string, the decorator will be automatically created from a registered decorator loader.
+ * A loader for the namespace ipl\\Html\\FormDecorator is automatically registered by default.
+ * See {@link addDecoratorLoader()} for registering a custom loader.
+ *
+ * @param FormElementDecorator|string $decorator
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If $decorator is a string and can't be loaded from registered decorator loaders
+ * or if a decorator loader does not return an instance of
+ * {@link FormElementDecorator}
+ */
+ public function setDefaultElementDecorator($decorator)
+ {
+ if ($decorator instanceof FormElementDecorator || $decorator instanceof DecoratorInterface) {
+ $this->defaultElementDecorator = $decorator;
+ } else {
+ $this->ensureDefaultElementDecoratorLoaderRegistered();
+
+ $class = $this->loadPlugin('decorator', $decorator);
+ if (! $class) {
+ throw new InvalidArgumentException(sprintf(
+ "Can't create decorator of unknown type '%s",
+ $decorator
+ ));
+ }
+
+ $d = new $class();
+ if (! $d instanceof FormElementDecorator && ! $d instanceof DecoratorInterface) {
+ throw new InvalidArgumentException(sprintf(
+ "Expected instance of %s for decorator '%s',"
+ . " got %s from a decorator loader instead",
+ FormElementDecorator::class,
+ $decorator,
+ get_php_type($d)
+ ));
+ }
+
+ $this->defaultElementDecorator = $d;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the value of the element specified by name
+ *
+ * Returns $default if the element does not exist or has no value.
+ *
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getValue($name, $default = null)
+ {
+ if ($this->hasElement($name)) {
+ $value = $this->getElement($name)->getValue();
+ if ($value !== null) {
+ return $value;
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Get the values for all but ignored elements
+ *
+ * @return array Values as name-value pairs
+ */
+ public function getValues()
+ {
+ $values = [];
+ foreach ($this->getElements() as $element) {
+ if (! $element->isIgnored()) {
+ $values[$element->getName()] = $element->getValue();
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * Populate values of registered elements
+ *
+ * @param iterable<string, mixed> $values Values as name-value pairs
+ *
+ * @return $this
+ */
+ public function populate($values)
+ {
+ foreach ($values as $name => $value) {
+ $this->populatedValues[$name][] = $value;
+ if ($this->hasElement($name)) {
+ $this->getElement($name)->setValue($value);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the populated value of the element specified by name
+ *
+ * Returns $default if there is no populated value for this element.
+ *
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getPopulatedValue($name, $default = null)
+ {
+ return isset($this->populatedValues[$name])
+ ? $this->populatedValues[$name][count($this->populatedValues[$name]) - 1]
+ : $default;
+ }
+
+ /**
+ * Clear populated value of the given element
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function clearPopulatedValue($name)
+ {
+ if (isset($this->populatedValues[$name])) {
+ unset($this->populatedValues[$name]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add all elements from the given element collection
+ *
+ * @param Form $form
+ *
+ * @return $this
+ */
+ public function addElementsFrom($form)
+ {
+ foreach ($form->getElements() as $element) {
+ $this->addElement($element);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a decorator loader
+ *
+ * @param string $namespace Namespace of the decorators
+ * @param string $postfix Decorator name postfix, if any
+ *
+ * @return $this
+ */
+ public function addDecoratorLoader($namespace, $postfix = null)
+ {
+ $this->addPluginLoader('decorator', $namespace, $postfix);
+
+ return $this;
+ }
+
+ /**
+ * Add an element loader
+ *
+ * @param string $namespace Namespace of the elements
+ * @param string $postfix Element name postfix, if any
+ *
+ * @return $this
+ */
+ public function addElementLoader($namespace, $postfix = null)
+ {
+ $this->addPluginLoader('element', $namespace, $postfix);
+
+ return $this;
+ }
+
+ /**
+ * Ensure that our default element decorator loader is registered
+ *
+ * @return $this
+ */
+ protected function ensureDefaultElementDecoratorLoaderRegistered()
+ {
+ if (! $this->defaultElementDecoratorLoaderRegistered) {
+ $this->addDefaultPluginLoader(
+ 'decorator',
+ 'ipl\\Html\\FormDecorator',
+ 'Decorator'
+ );
+
+ $this->defaultElementDecoratorLoaderRegistered = true;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Ensure that our default element loader is registered
+ *
+ * @return $this
+ */
+ protected function ensureDefaultElementLoaderRegistered()
+ {
+ if (! $this->defaultElementLoaderRegistered) {
+ $this->addDefaultPluginLoader('element', __NAMESPACE__, 'Element');
+
+ $this->defaultElementLoaderRegistered = true;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Decorate the given element
+ *
+ * @param FormElement $element
+ *
+ * @return $this
+ *
+ * @throws UnexpectedValueException If the default decorator is set but not an instance of
+ * {@link FormElementDecorator}
+ */
+ protected function decorate(FormElement $element)
+ {
+ if ($this->hasDefaultElementDecorator()) {
+ $decorator = $this->getDefaultElementDecorator();
+
+ if (! $decorator instanceof FormElementDecorator && ! $decorator instanceof DecoratorInterface) {
+ throw new UnexpectedValueException(sprintf(
+ '%s expects the default decorator to be an instance of %s, got %s instead',
+ __METHOD__,
+ FormElementDecorator::class,
+ get_php_type($decorator)
+ ));
+ }
+
+ $decorator->decorate($element);
+ }
+
+ return $this;
+ }
+
+ public function isValidEvent($event)
+ {
+ return in_array($event, [
+ Form::ON_SUCCESS,
+ Form::ON_SENT,
+ Form::ON_ERROR,
+ Form::ON_REQUEST,
+ Form::ON_VALIDATE,
+ Form::ON_ELEMENT_REGISTERED,
+ ]);
+ }
+
+ public function remove(ValidHtml $elementOrHtml)
+ {
+ if ($elementOrHtml instanceof FormElement) {
+ if ($this->hasElement($elementOrHtml)) {
+ $name = array_search($elementOrHtml, $this->elements, true);
+ if ($name !== false) {
+ unset($this->elements[$name]);
+ }
+ }
+ }
+
+ return parent::remove($elementOrHtml);
+ }
+
+ /**
+ * Handler which is called after an element has been registered
+ *
+ * @param FormElement $element
+ */
+ protected function onElementRegistered(FormElement $element)
+ {
+ }
+}