diff --git a/library/vendor/ipl/Html/Form.php b/library/vendor/ipl/Html/Form.php
new file mode 100644
index 00000000..1374a755
--- /dev/null
+++ b/library/vendor/ipl/Html/Form.php
@@ -0,0 +1,294 @@
+request = $request;
+
+ if ($this->getAction() === null) {
+ $this->setAction($request->getUrl());
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return Request|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * @param Request $request
+ * @return $this
+ */
+ public function handleRequest(Request $request)
+ {
+ $this->setRequest($request);
+ if ($this->hasBeenSent()) {
+ $this->populate($request->getParams());
+ }
+
+ $this->ensureAssembled();
+ if ($this->hasBeenSubmitted()) {
+ if ($this->isValid()) {
+ $this->onSuccess();
+ } else {
+ $this->onError();
+ }
+ } elseif ($this->hasBeenSent()) {
+ $this->validatePartial();
+ }
+
+ return $this;
+ }
+
+ public function onSuccess()
+ {
+ // $this->redirectOnSuccess();
+ }
+
+ public function onError()
+ {
+ /**
+ $error = Html::tag('p', ['class' => 'error'], 'ERROR: ');
+ foreach ($this->getElements() as $element) {
+ foreach ($element->getMessages() as $message) {
+ $error->add(sprintf('%s: %s', $element->getName(), $message));
+ }
+ }
+
+ $this->add($error);
+ */
+ }
+
+ // TODO: onElementRegistered
+ public function onRegisteredElement($name, BaseFormElement $element)
+ {
+ if ($element instanceof SubmitElement && ! $this->hasSubmitButton()) {
+ $this->setSubmitButton($element);
+ }
+
+ if (array_key_exists($name, $this->populatedValues)) {
+ $element->setValue($this->populatedValues[$name]);
+ }
+ }
+
+ public function isValid()
+ {
+ if ($this->isValid === null) {
+ $this->validate();
+ }
+
+ return $this->isValid;
+ }
+
+ public function validate()
+ {
+ $valid = true;
+ foreach ($this->elements as $element) {
+ if ($element->isRequired() && ! $element->hasValue()) {
+ $element->addMessage('This field is required');
+ $valid = false;
+ continue;
+ }
+ if (! $element->isValid()) {
+ $valid = false;
+ }
+ }
+
+ $this->isValid = $valid;
+ }
+
+ public function validatePartial()
+ {
+ foreach ($this->getElements() as $element) {
+ if ($element->hasValue()) {
+ $element->validate();
+ }
+ }
+ }
+
+ public function getValue($name, $default = null)
+ {
+ if ($this->hasElement($name)) {
+ return $this->getElement($name)->getValue();
+ } else {
+ return $default;
+ }
+ }
+
+ public function getValues()
+ {
+ $values = [];
+ foreach ($this->getElements() as $element) {
+ if (! $element->isIgnored()) {
+ $values[] = $element->getValue();
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasBeenSent()
+ {
+ if ($this->request === null) {
+ return false;
+ }
+
+ if ($this->request->getMethod() !== $this->getMethod()) {
+ return false;
+ }
+
+ // TODO: Check form name element
+
+ return true;
+ }
+
+ public function getSuccessUrl()
+ {
+ return $this->getAction();
+ }
+
+ public function redirectOnSuccess()
+ {
+ $this->request->getResponse()->redirectAndExit($this->getSuccessUrl());
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasBeenSubmitted()
+ {
+ if ($this->hasSubmitButton()) {
+ return $this->getSubmitButton()->hasBeenPressed();
+ } else {
+ return $this->hasBeenSent();
+ }
+ }
+
+ public function getSubmitButton()
+ {
+ return $this->submitButton;
+ }
+
+ public function hasSubmitButton()
+ {
+ return $this->submitButton !== null;
+ }
+
+ public function setSubmitButton(SubmitElement $element)
+ {
+ $this->submitButton = $element;
+
+ return $this;
+ }
+
+ public function populate($values)
+ {
+ foreach ($values as $name => $value) {
+ $this->populatedValues[$name] = $value;
+ if ($this->hasElement($name)) {
+ try {
+ $element = $this->getElement($name);
+ } catch (InvalidArgumentException $exception) {
+ // This will not happen, as we checked for hasElement
+ }
+
+ $element->setValue($value);
+ }
+ }
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMethod()
+ {
+ $method = $this->getAttributes()->get('method')->getValue();
+ if ($method === null) {
+ // WRONG. Problem:
+ // right now we get the method in assemble, that's too late.
+ // TODO: fix this via getMethodAttribute callback
+ return 'POST';
+ }
+
+ return $method;
+ }
+
+ /**
+ * @param $method
+ * @return $this
+ */
+ public function setMethod($method)
+ {
+ $this->getAttributes()->set('method', strtoupper($method));
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAction()
+ {
+ return $this->getAttributes()->get('action')->getValue();
+ }
+
+ /**
+ * @param $action
+ * @return $this
+ */
+ public function setAction($action)
+ {
+ $this->getAttributes()->set('action', $action);
+
+ return $this;
+ }
+}
diff --git a/library/vendor/ipl/Html/FormDecorator/DdDtDecorator.php b/library/vendor/ipl/Html/FormDecorator/DdDtDecorator.php
new file mode 100644
index 00000000..dd2ca54f
--- /dev/null
+++ b/library/vendor/ipl/Html/FormDecorator/DdDtDecorator.php
@@ -0,0 +1,134 @@
+wrapped = $document;
+ $document->addWrapper($newWrapper);
+
+ return $newWrapper;
+ }
+
+ protected function renderLabel()
+ {
+ if ($this->wrapped instanceof BaseFormElement) {
+ $label = $this->wrapped->getLabel();
+ if (strlen($label)) {
+ return Html::tag('label', null, $label);
+ }
+ }
+
+ return null;
+ }
+
+ public function XXrenderAttributes()
+ {
+ // TODO: only when sent?!
+ if ($this->wrapped instanceof BaseFormElement) {
+ if (! $this->wrapped->isValid()) {
+ $this->getAttributes()->add('class', 'errors');
+ }
+ }
+
+ return parent::renderAttributes();
+ }
+
+ protected function renderDescription()
+ {
+ if ($this->wrapped instanceof BaseFormElement) {
+ $description = $this->wrapped->getDescription();
+ if (strlen($description)) {
+ return Html::tag('p', ['class' => 'description'], $description);
+ }
+ }
+
+ return null;
+ }
+
+ protected function renderErrors()
+ {
+ if ($this->wrapped instanceof BaseFormElement) {
+ $errors = [];
+ foreach ($this->wrapped->getMessages() as $message) {
+ $errors[] = Html::tag('p', ['class' => 'error'], $message);
+ }
+
+ if (! empty($errors)) {
+ return $errors;
+ }
+ }
+
+ return null;
+ }
+
+ public function add($content)
+ {
+ if ($content !== $this->wrapped) {
+ parent::add($content);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @throws \Icinga\Exception\IcingaException
+ */
+ protected function assemble()
+ {
+ $this->add([$this->dt(), $this->dd()]);
+ $this->ready = true;
+ }
+
+ public function dt()
+ {
+ if ($this->dt === null) {
+ $this->dt = Html::tag('dt', null, $this->renderLabel());
+ }
+
+ return $this->dt;
+ }
+
+ /**
+ * @return \dipl\Html\HtmlElement
+ * @throws \Icinga\Exception\IcingaException
+ * @throws \Icinga\Exception\ProgrammingError
+ */
+ public function dd()
+ {
+ if ($this->dd === null) {
+ $this->dd = Html::tag('dd', null, [
+ $this->wrapped,
+ $this->renderErrors(),
+ $this->renderDescription()
+ ]);
+ }
+
+ return $this->dd;
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/BaseFormElement.php b/library/vendor/ipl/Html/FormElement/BaseFormElement.php
new file mode 100644
index 00000000..8e7ba602
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/BaseFormElement.php
@@ -0,0 +1,279 @@
+getAttributes()
+ ->registerAttributeCallback('label', [$this, 'getNoAttribute'], [$this, 'setLabel'])
+ ->registerAttributeCallback('name', [$this, 'getNameAttribute'], [$this, 'setName'])
+ ->registerAttributeCallback('value', [$this, 'getValueAttribute'], [$this, 'setValue'])
+ ->registerAttributeCallback('description', [$this, 'getNoAttribute'], [$this, 'setDescription'])
+ ->registerAttributeCallback('validators', null, [$this, 'setValidators'])
+ ->registerAttributeCallback('required', [$this, 'getRequiredAttribute'], [$this, 'setRequired']);
+ if ($attributes !== null) {
+ $this->addAttributes($attributes);
+ }
+ $this->setName($name);
+ }
+
+ /**
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * @param string $description
+ * @return $this
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLabel()
+ {
+ return $this->label;
+ }
+
+ /**
+ * @param string $label
+ * @return $this
+ */
+ public function setLabel($label)
+ {
+ $this->label = $label;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param string $name
+ * @return $this
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * @param $value
+ * @return $this
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+ $this->isValid = null;
+
+ return $this;
+ }
+
+ public function isRequired()
+ {
+ return $this->required;
+ }
+
+ public function setRequired($required = true)
+ {
+ $this->required = (bool) $required;
+
+ return $this;
+ }
+
+ public function isIgnored()
+ {
+ return $this->ignored;
+ }
+
+ public function setIgnored($ignored = true)
+ {
+ $this->required = (bool) $ignored;
+
+ return $this;
+ }
+
+ /**
+ * @return Attribute|string
+ */
+ public function getNameAttribute()
+ {
+ return $this->getName();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getValueAttribute()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * @return null
+ */
+ public function getNoAttribute()
+ {
+ return null;
+ }
+
+ /**
+ * @return null|Attribute
+ */
+ public function getRequiredAttribute()
+ {
+ if ($this->isRequired()) {
+ return new Attribute('required', true);
+ }
+
+ return null;
+ }
+
+ /**
+ * @return ValidatorInterface[]
+ */
+ public function getValidators()
+ {
+ return $this->validators;
+ }
+
+ /**
+ * @param array $validators
+ */
+ public function setValidators(array $validators)
+ {
+ $this->validators = [];
+ foreach ($validators as $validator => $options) {
+ if (! $validator instanceof ValidatorInterface) {
+ $validator = $this->createValidator($validator, $options);
+ }
+
+ $this->validators[] = $validator;
+ }
+ }
+
+ /**
+ * @param $name
+ * @param $options
+ * @return ValidatorInterface
+ */
+ public function createValidator($name, $options)
+ {
+ $class = 'ipl\\Validator\\' . ucfirst($name) . 'Validator';
+ if (class_exists($class)) {
+ return new $class($options);
+ } else {
+ throw new InvalidArgumentException(
+ 'Unable to create Validator: %s',
+ $name
+ );
+ }
+ }
+
+ public function hasValue()
+ {
+ $value = $this->getValue();
+
+ return $value !== null && $value !== '' && $value !== [];
+ }
+
+ /**
+ * @return bool
+ */
+ public function isValid()
+ {
+ if ($this->isValid === null) {
+ $this->validate();
+ }
+
+ return $this->isValid;
+ }
+
+ /**
+ * @return $this
+ */
+ public function validate()
+ {
+ $isValid = true;
+
+ foreach ($this->getValidators() as $validator) {
+ if (! $validator->isValid($this->getValue())) {
+ $isValid = false;
+ foreach ($validator->getMessages() as $message) {
+ $this->addMessage($message);
+ }
+ }
+ }
+
+ $this->isValid = $isValid;
+
+ return $this;
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/FormElementContainer.php b/library/vendor/ipl/Html/FormElement/FormElementContainer.php
new file mode 100644
index 00000000..5dc5ae6e
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/FormElementContainer.php
@@ -0,0 +1,157 @@
+elements;
+ }
+
+ /**
+ * @param $name
+ * @return BaseFormElement
+ */
+ public function getElement($name)
+ {
+ if (! array_key_exists($name, $this->elements)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Trying to get inexistant element "%s"',
+ $name
+ ));
+ }
+ return $this->elements[$name];
+ }
+
+ /**
+ * @param string|BaseFormElement $element
+ * @return bool
+ */
+ public function hasElement($element)
+ {
+ if (is_string($element)) {
+ return array_key_exists($element, $this->elements);
+ } elseif ($element instanceof BaseFormElement) {
+ return in_array($element, $this->elements, true);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @param string $name
+ * @param string|BaseFormElement $type
+ * @param array|null $options
+ * @return $this
+ */
+ public function addElement($name, $type = null, $options = null)
+ {
+ $this->registerElement($name, $type, $options);
+
+ if ($this instanceof BaseHtmlElement) {
+ $element = $this->decorate($this->getElement($name));
+ }
+ //...
+
+ $this->add($element);
+
+ return $this;
+ }
+
+ protected function decorate(BaseFormElement $element)
+ {
+ if ($this->hasDefaultElementDecorator()) {
+ $this->getDefaultElementDecorator()->wrap($element);
+ }
+
+ return $element;
+ }
+
+ /**
+ * @param string $name
+ * @param string|BaseFormElement $type
+ * @param array|null $options
+ * @return $this
+ */
+ public function registerElement($name, $type = null, $options = null)
+ {
+ if (is_string($type)) {
+ $type = $this->createElement($name, $type, $options);
+ }
+
+ $this->elements[$name] = $type;
+
+ if (method_exists($this, 'onRegisteredElement')) {
+ $this->onRegisteredElement($name, $type);
+ }
+
+ return $this;
+ }
+
+ /**
+ * TODO: Add PluginLoader
+ *
+ * @param $name
+ * @param $type
+ * @param $options
+ * @return BaseFormElement
+ */
+ public function createElement($name, $type, $attributes = null)
+ {
+ $class = __NAMESPACE__ . '\\' . ucfirst($type) . 'Element';
+ if (class_exists($class)) {
+ /** @var BaseFormElement $element */
+ $element = new $class($name);
+ if ($attributes !== null) {
+ $element->addAttributes($attributes);
+ }
+
+ return $element;
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ 'Unable to create Form Element, no such type: %s',
+ $type
+ ));
+ }
+ }
+
+ /**
+ * @param FormElementContainer $form
+ */
+ public function addElementsFrom(FormElementContainer $form)
+ {
+ foreach ($form->getElements() as $name => $element) {
+ $this->addElement($element);
+ }
+ }
+
+ public function setDefaultElementDecorator(BaseHtmlElement $decorator)
+ {
+ $this->defaultElementDecorator = $decorator;
+
+ return $this;
+ }
+
+ public function hasDefaultElementDecorator()
+ {
+ return $this->defaultElementDecorator !== null;
+ }
+
+ /**
+ * @return BaseHtmlElement
+ */
+ public function getDefaultElementDecorator()
+ {
+ return $this->defaultElementDecorator;
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/HiddenElement.php b/library/vendor/ipl/Html/FormElement/HiddenElement.php
new file mode 100644
index 00000000..9c440419
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/HiddenElement.php
@@ -0,0 +1,8 @@
+getAttributes()->registerAttributeCallback('type', [$this, 'getTypeAttribute']);
+ }
+
+ /**
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return Attribute
+ */
+ public function getTypeAttribute()
+ {
+ return new Attribute('type', $this->getType());
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/SelectElement.php b/library/vendor/ipl/Html/FormElement/SelectElement.php
new file mode 100644
index 00000000..964966c5
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/SelectElement.php
@@ -0,0 +1,46 @@
+getAttributes()->registerAttributeCallback(
+ 'options',
+ null,
+ [$this, 'setOptions']
+ );
+ }
+
+ /**
+ * @param array $options
+ * @return $this
+ */
+ public function setOptions(array $options)
+ {
+ foreach ($options as $value => $label) {
+ $this->options[$value] = new SelectOption($value, $label);
+ }
+
+ return $this;
+ }
+
+ protected function assemble()
+ {
+ $currentValue = $this->getValue();
+ foreach ($this->options as $value => $option) {
+ if ($value == $currentValue) {
+ $option->getAttributes()->set('selected', true);
+ }
+
+ $this->add($option);
+ }
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/SelectOption.php b/library/vendor/ipl/Html/FormElement/SelectOption.php
new file mode 100644
index 00000000..7ef50548
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/SelectOption.php
@@ -0,0 +1,43 @@
+add($label);
+ $this->getAttributes()->add('value', $value);
+ }
+
+ /**
+ * @param $label
+ * @return $this
+ */
+ public function setLabel($label)
+ {
+ $this->setContent($label);
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/SubmitElement.php b/library/vendor/ipl/Html/FormElement/SubmitElement.php
new file mode 100644
index 00000000..8ed79926
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/SubmitElement.php
@@ -0,0 +1,47 @@
+buttonLabel = $label;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getButtonLabel()
+ {
+ if ($this->buttonLabel === null) {
+ return $this->getName();
+ } else {
+ return $this->buttonLabel;
+ }
+ }
+
+ /**
+ * @return mixed|static
+ */
+ public function getValueAttribute()
+ {
+ return new Attribute('value', $this->getButtonLabel());
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasBeenPressed()
+ {
+ return $this->getButtonLabel() === $this->getValue();
+ }
+}
diff --git a/library/vendor/ipl/Html/FormElement/TextElement.php b/library/vendor/ipl/Html/FormElement/TextElement.php
new file mode 100644
index 00000000..560d4c21
--- /dev/null
+++ b/library/vendor/ipl/Html/FormElement/TextElement.php
@@ -0,0 +1,8 @@
+settings = [
+ 'max' => $max
+ ];
+ }
+ }
+
+ public function isValid($value)
+ {
+ if ($value > $this->getSetting('max', PHP_INT_MAX)) {
+ $this->clearMessages();
+
+ return true;
+ } else {
+ $this->addMessage(
+ $this->translate('%s is not greater than %d'),
+ $value,
+ $this->getSetting('max', PHP_INT_MAX)
+ );
+
+ return false;
+ }
+ }
+}
diff --git a/library/vendor/ipl/Validator/MessageContainer.php b/library/vendor/ipl/Validator/MessageContainer.php
new file mode 100644
index 00000000..202fd441
--- /dev/null
+++ b/library/vendor/ipl/Validator/MessageContainer.php
@@ -0,0 +1,38 @@
+messages;
+ }
+
+ public function addMessage($message)
+ {
+ $args = func_get_args();
+ array_shift($args);
+ if (empty($args)) {
+ $this->messages[] = $message;
+ } else {
+ $this->messages[] = vsprintf($message, $args);
+ }
+
+ return $this;
+ }
+
+ public function setMessages(array $messages)
+ {
+ $this->messages = $messages;
+
+ return $this;
+ }
+
+ public function clearMessages()
+ {
+ return $this->setMessages([]);
+ }
+}
diff --git a/library/vendor/ipl/Validator/SimpleValidator.php b/library/vendor/ipl/Validator/SimpleValidator.php
new file mode 100644
index 00000000..4ee7efe4
--- /dev/null
+++ b/library/vendor/ipl/Validator/SimpleValidator.php
@@ -0,0 +1,24 @@
+settings = $settings;
+ }
+
+ public function getSetting($name, $default = null)
+ {
+ if (array_key_exists($name, $this->settings)) {
+ return $this->settings[$name];
+ } else {
+ return $default;
+ }
+ }
+}
diff --git a/library/vendor/ipl/Validator/ValidatorInterface.php b/library/vendor/ipl/Validator/ValidatorInterface.php
new file mode 100644
index 00000000..8ac33f29
--- /dev/null
+++ b/library/vendor/ipl/Validator/ValidatorInterface.php
@@ -0,0 +1,18 @@
+