summaryrefslogtreecommitdiffstats
path: root/vendor/ipl/html/src/FormDecorator
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ipl/html/src/FormDecorator')
-rw-r--r--vendor/ipl/html/src/FormDecorator/CallbackDecorator.php41
-rw-r--r--vendor/ipl/html/src/FormDecorator/DdDtDecorator.php140
-rw-r--r--vendor/ipl/html/src/FormDecorator/DecoratorInterface.php19
-rw-r--r--vendor/ipl/html/src/FormDecorator/DivDecorator.php156
4 files changed, 356 insertions, 0 deletions
diff --git a/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php b/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
new file mode 100644
index 0000000..1048bfb
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace ipl\Html\FormDecorator;
+
+use Closure;
+use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecorator;
+use ipl\Html\HtmlDocument;
+
+class CallbackDecorator extends HtmlDocument implements FormElementDecorator
+{
+ /** @var Closure The decorating callback */
+ protected $callback;
+
+ /** @var FormElement The decorated form element */
+ protected $formElement;
+
+ /**
+ * Create a new CallbackDecorator
+ *
+ * @param Closure $callback
+ */
+ public function __construct(Closure $callback)
+ {
+ $this->callback = $callback;
+ }
+
+ public function decorate(FormElement $formElement)
+ {
+ $decorator = clone $this;
+
+ $decorator->formElement = $formElement;
+
+ $formElement->prependWrapper($decorator);
+ }
+
+ protected function assemble()
+ {
+ call_user_func($this->callback, $this->formElement, $this);
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php b/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
new file mode 100644
index 0000000..9cfec20
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace ipl\Html\FormDecorator;
+
+use ipl\Html\BaseHtmlElement;
+use ipl\Html\FormElement\BaseFormElement;
+use ipl\Html\Html;
+use ipl\Html\ValidHtml;
+
+class DdDtDecorator extends BaseHtmlElement implements DecoratorInterface
+{
+ protected $tag = 'dl';
+
+ protected $dt;
+
+ protected $dd;
+
+ /** @var BaseFormElement */
+ protected $wrappedElement;
+
+ protected $ready = false;
+
+ /**
+ * @param BaseFormElement $element
+ * @return static
+ */
+ public function decorate(BaseFormElement $element)
+ {
+ // TODO: ignore hidden?
+ $newWrapper = clone($this);
+ $newWrapper->wrappedElement = $element;
+ $element->prependWrapper($newWrapper);
+
+ return $newWrapper;
+ }
+
+ protected function renderLabel()
+ {
+ if ($this->wrappedElement instanceof BaseFormElement) {
+ $label = $this->wrappedElement->getLabel();
+ if ($label) {
+ return Html::tag('label', null, $label);
+ }
+ }
+
+ return null;
+ }
+
+ public function getAttributes()
+ {
+ $attributes = parent::getAttributes();
+
+ if ($this->wrappedElement->hasBeenValidated() && ! $this->wrappedElement->isValid()) {
+ $classes = $attributes->get('class')->getValue();
+ if (
+ empty($classes)
+ || (is_array($classes) && ! in_array('errors', $classes))
+ || (is_string($classes) && $classes !== 'errors')
+ ) {
+ $attributes->add('class', 'errors');
+ }
+ }
+
+ return $attributes;
+ }
+
+ protected function renderDescription()
+ {
+ if ($this->wrappedElement instanceof BaseFormElement) {
+ $description = $this->wrappedElement->getDescription();
+ if ($description) {
+ return Html::tag('p', ['class' => 'description'], $description);
+ }
+ }
+
+ return null;
+ }
+
+ protected function renderErrors()
+ {
+ if ($this->wrappedElement instanceof BaseFormElement) {
+ $errors = [];
+ foreach ($this->wrappedElement->getMessages() as $message) {
+ $errors[] = Html::tag('p', ['class' => 'error'], $message);
+ }
+
+ if (! empty($errors)) {
+ return $errors;
+ }
+ }
+
+ return null;
+ }
+
+ public function addHtml(ValidHtml ...$content)
+ {
+ // TODO: is this required?
+ if (! in_array($this->wrappedElement, $content, true)) {
+ parent::addHtml(...$content);
+ }
+
+ return $this;
+ }
+
+ protected function assemble()
+ {
+ $this->addHtml($this->dt(), $this->dd());
+ $this->ready = true;
+ }
+
+ protected function dt()
+ {
+ if ($this->dt === null) {
+ $this->dt = Html::tag('dt', null, $this->renderLabel());
+ }
+
+ return $this->dt;
+ }
+
+ /**
+ * @return \ipl\Html\HtmlElement
+ */
+ protected function dd()
+ {
+ if ($this->dd === null) {
+ $this->dd = Html::tag('dd', null, [
+ $this->wrappedElement,
+ $this->renderErrors(),
+ $this->renderDescription()
+ ]);
+ }
+
+ return $this->dd;
+ }
+
+ public function __destruct()
+ {
+ $this->wrapper = null;
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php b/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
new file mode 100644
index 0000000..1ed1a38
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace ipl\Html\FormDecorator;
+
+use ipl\Html\Contract\FormElementDecorator;
+use ipl\Html\FormElement\BaseFormElement;
+
+/** @deprecated Use {@link FormElementDecorator} instead */
+interface DecoratorInterface
+{
+ /**
+ * Set the form element to decorate
+ *
+ * @param BaseFormElement $formElement
+ *
+ * @return static
+ */
+ public function decorate(BaseFormElement $formElement);
+}
diff --git a/vendor/ipl/html/src/FormDecorator/DivDecorator.php b/vendor/ipl/html/src/FormDecorator/DivDecorator.php
new file mode 100644
index 0000000..4935f01
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecorator/DivDecorator.php
@@ -0,0 +1,156 @@
+<?php
+
+namespace ipl\Html\FormDecorator;
+
+use ipl\Html\Attributes;
+use ipl\Html\BaseHtmlElement;
+use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecorator;
+use ipl\Html\Contract\FormSubmitElement;
+use ipl\Html\FormElement\FieldsetElement;
+use ipl\Html\FormElement\HiddenElement;
+use ipl\Html\Html;
+use ipl\Html\HtmlElement;
+use ipl\Html\Text;
+
+/**
+ * Form element decorator based on div elements
+ */
+class DivDecorator extends BaseHtmlElement implements FormElementDecorator
+{
+ /** @var string CSS class to use for submit elements */
+ public const SUBMIT_ELEMENT_CLASS = 'form-control';
+
+ /** @var string CSS class to use for all input elements */
+ public const INPUT_ELEMENT_CLASS = 'form-element';
+
+ /** @var string CSS class to use for form descriptions */
+ public const DESCRIPTION_CLASS = 'form-element-description';
+
+ /** @var string CSS class to use for form errors */
+ public const ERROR_CLASS = 'form-element-errors';
+
+ /** @var string CSS class to set on the decorator if the element has errors */
+ public const ERROR_HINT_CLASS = 'has-error';
+
+ /** @var FormElement The decorated form element */
+ protected $formElement;
+
+ protected $tag = 'div';
+
+ public function decorate(FormElement $formElement)
+ {
+ if ($formElement instanceof HiddenElement) {
+ return;
+ }
+
+ $decorator = clone $this;
+
+ /**
+ * Wrapper logic can be overridden to propagate the decorator.
+ * So here we make sure that a yet unbound decorator is passed.
+ *
+ * {@see FieldsetElement::setWrapper()}
+ */
+ $formElement->prependWrapper($decorator);
+
+ $decorator->formElement = $formElement;
+
+ $classes = [static::INPUT_ELEMENT_CLASS];
+ if ($formElement instanceof FormSubmitElement) {
+ $classes[] = static::SUBMIT_ELEMENT_CLASS;
+ }
+
+ $decorator->getAttributes()->add('class', $classes);
+ }
+
+ protected function assembleDescription()
+ {
+ $description = $this->formElement->getDescription();
+
+ if ($description !== null) {
+ $descriptionId = null;
+ if ($this->formElement->getAttributes()->has('id')) {
+ $descriptionId = 'desc_' . $this->formElement->getAttributes()->get('id')->getValue();
+ $this->formElement->getAttributes()->set('aria-describedby', $descriptionId);
+ }
+
+ return Html::tag('p', ['id' => $descriptionId, 'class' => static::DESCRIPTION_CLASS], $description);
+ }
+
+ return null;
+ }
+
+ protected function assembleElement()
+ {
+ if ($this->formElement->isRequired()) {
+ $this->formElement->getAttributes()->set('aria-required', 'true');
+ }
+
+ return $this->formElement->ensureAssembled();
+ }
+
+ protected function assembleErrors()
+ {
+ $errors = new HtmlElement('ul', Attributes::create(['class' => static::ERROR_CLASS]));
+
+ foreach ($this->formElement->getMessages() as $message) {
+ $errors->addHtml(
+ new HtmlElement('li', Attributes::create(['class' => static::ERROR_CLASS]), Text::create($message))
+ );
+ }
+
+ if (! $errors->isEmpty()) {
+ return $errors;
+ }
+
+ return null;
+ }
+
+ protected function assembleLabel()
+ {
+ $label = $this->formElement->getLabel();
+
+ if ($label !== null) {
+ if ($this->formElement instanceof FieldsetElement) {
+ return new HtmlElement('legend', null, Text::create($label));
+ } else {
+ $attributes = null;
+ if ($this->formElement->getAttributes()->has('id')) {
+ $attributes = new Attributes(['for' => $this->formElement->getAttributes()->get('id')->getValue()]);
+ }
+
+ return Html::tag('label', $attributes, $label);
+ }
+ }
+
+ return null;
+ }
+
+ protected function assemble()
+ {
+ if ($this->formElement->hasBeenValidated() && ! $this->formElement->isValid()) {
+ $this->getAttributes()->add('class', static::ERROR_HINT_CLASS);
+ }
+
+ if ($this->formElement instanceof FieldsetElement) {
+ $element = $this->assembleElement();
+ $element->prependHtml(...Html::wantHtmlList([
+ $this->assembleLabel(),
+ $this->assembleDescription()
+ ]));
+
+ $this->addHtml(...Html::wantHtmlList([
+ $element,
+ $this->assembleErrors()
+ ]));
+ } else {
+ $this->addHtml(...Html::wantHtmlList([
+ $this->assembleLabel(),
+ $this->assembleElement(),
+ $this->assembleDescription(),
+ $this->assembleErrors()
+ ]));
+ }
+ }
+}