From 3a6861b22b405f6e804435c8ed10a05305f587d9 Mon Sep 17 00:00:00 2001 From: Brooke Bryan Date: Sun, 23 Aug 2020 21:41:51 +0100 Subject: [PATCH] Updated rendering & Correct BEM --- assets/form.css | 26 ++++--- composer.json | 1 + src/Csrf/CsrfDataHandler.php | 13 +--- src/DataHandlers/AbstractDataHandler.php | 20 +++-- src/DataHandlers/Interfaces/DataHandler.php | 10 ++- .../AbstractDataHandlerDecorator.php | 1 + src/Decorators/DefaultFormDecorator.php | 75 ++++++++++++++++++- src/Decorators/DefaultFormDecorator.phtml | 5 +- src/Form/FormSubmitDecorator.php | 4 +- tests/Csrf/CsrfFormTest.php | 2 +- tests/Decorators/FormSubmitDecoratorTest.php | 10 ++- tests/FormTest.php | 10 +-- 12 files changed, 133 insertions(+), 44 deletions(-) diff --git a/assets/form.css b/assets/form.css index 69cd57c..9ba2d18 100644 --- a/assets/form.css +++ b/assets/form.css @@ -1,15 +1,15 @@ -.p-form-field { +.p-form__field { padding: 5px; } -.p-form--label { +.p-form__label { padding: 2px 4px; } -.p-form--submit input, -.p-form--submit button, -.p-form--input input, -.p-form--input select { +.p-form__submit input, +.p-form__submit button, +.p-form__input input, +.p-form__input select { line-height: 16px; font-size: 16px; padding: 10px 10px; @@ -26,21 +26,25 @@ background-color: white; } -.p-form--submit input, -.p-form--submit button { +.p-form__submit input, +.p-form__submit button { background-color: #c3c3c3; color: #313131; border: 1px solid #8c8c8c; } -.p-form--submit input:active, -.p-form--submit button:active { +.p-form__submit input:active, +.p-form__submit button:active { background-color: #c3c3c3; color: #313131; border: 1px solid #8c8c8c; box-shadow: inset 0px 0px 3px #313131; } -.p-form--input .p-form--checkbox input { +.p-form__input .p-form__checkbox input { height: 16px; } + +.p-form__errors--hidden { + display: none; +} diff --git a/composer.json b/composer.json index 6fe6052..6b99109 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "php": ">=7.1", "packaged/glimpse": "^2.6", "packaged/ui": "^1.0", + "packaged-ui/bem-component": "~1.2", "packaged/validate": "^2.1" }, "require-dev": { diff --git a/src/Csrf/CsrfDataHandler.php b/src/Csrf/CsrfDataHandler.php index 12c3869..64852fe 100644 --- a/src/Csrf/CsrfDataHandler.php +++ b/src/Csrf/CsrfDataHandler.php @@ -1,11 +1,9 @@ addValidator(new CsrfValidator($this->_generatePassword(), $this->_expiryMins)); } - - protected function _defaultDecorator(): DataHandlerDecorator - { - $decorator = new HiddenInputDecorator(); - $decorator->setHandler($this); - return $decorator; - } } diff --git a/src/DataHandlers/AbstractDataHandler.php b/src/DataHandlers/AbstractDataHandler.php index c805209..be1833e 100644 --- a/src/DataHandlers/AbstractDataHandler.php +++ b/src/DataHandlers/AbstractDataHandler.php @@ -5,6 +5,8 @@ use Packaged\Form\DataHandlers\Interfaces\DataHandler; use Packaged\Form\Decorators\AbstractDataHandlerDecorator; use Packaged\Form\Decorators\Interfaces\DataHandlerDecorator; +use Packaged\Helpers\Strings; +use Packaged\SafeHtml\ISafeHtmlProducer; use Packaged\Validate\IValidator; use Packaged\Validate\ValidationException; use function array_merge; @@ -251,30 +253,30 @@ public function setDecorator(DataHandlerDecorator $decorator) abstract protected function _defaultDecorator(): DataHandlerDecorator; /** - * @return mixed + * @return string|null */ - public function getId() + public function getId(): ?string { return $this->_id; } /** - * @param mixed $id + * @param string $id * * @return AbstractDataHandler */ - public function setId($id) + public function setId(string $id) { $this->_id = $id; return $this; } /** - * @return mixed + * @return string */ public function getLabel() { - return $this->_label; + return $this->_label ?? Strings::titleize(Strings::splitOnCamelCase($this->getName())); } /** @@ -357,4 +359,10 @@ public function __toString() return $this->render(); } + public function getInput(): ?ISafeHtmlProducer + { + $dec = $this->getDecorator(); + $dec->render(); + return $dec->getInput(); + } } diff --git a/src/DataHandlers/Interfaces/DataHandler.php b/src/DataHandlers/Interfaces/DataHandler.php index bb315aa..d581e78 100644 --- a/src/DataHandlers/Interfaces/DataHandler.php +++ b/src/DataHandlers/Interfaces/DataHandler.php @@ -2,12 +2,16 @@ namespace Packaged\Form\DataHandlers\Interfaces; use Exception; -use Packaged\Form\Decorators\Interfaces\DataHandlerDecorator; +use Packaged\SafeHtml\ISafeHtmlProducer; use Packaged\Validate\IValidatable; use Packaged\Validate\ValidationException; interface DataHandler extends IValidatable { + public function getId(): ?string; + + public function setId(string $id); + /** * Validate the data, return true if valid, false if invalid * @@ -62,8 +66,6 @@ public function getValue(); */ public function setValue($value); - public function getDecorator(): DataHandlerDecorator; - public function getDefaultValue(); /** @@ -98,5 +100,5 @@ public function addError(ValidationException ...$errors); */ public function clearErrors(); - public function render(): string; + public function getInput(): ?ISafeHtmlProducer; } diff --git a/src/Decorators/AbstractDataHandlerDecorator.php b/src/Decorators/AbstractDataHandlerDecorator.php index 26124d2..811c7c6 100644 --- a/src/Decorators/AbstractDataHandlerDecorator.php +++ b/src/Decorators/AbstractDataHandlerDecorator.php @@ -130,6 +130,7 @@ protected function _configureInputElement(HtmlElement $input) if(!empty($id)) { + $this->_handler->setId($id); $input->setId($id); } diff --git a/src/Decorators/DefaultFormDecorator.php b/src/Decorators/DefaultFormDecorator.php index 0a1f7ba..9ebd474 100644 --- a/src/Decorators/DefaultFormDecorator.php +++ b/src/Decorators/DefaultFormDecorator.php @@ -1,9 +1,18 @@ addClass('p-form'); + $this->_bem = Bem::block('p-form'); + $this->addClass($this->_bem->asString()); + } + + public function bem(): Bem + { + return $this->_bem; } protected function _prepareForProduce(): HtmlElement @@ -50,4 +66,61 @@ protected function _getTemplatedPhtmlClassList() { return array_unique([get_class($this->getForm()), $this->_getTemplatedPhtmlClass(), self::class]); } + + public function renderHandler(DataHandler $handler): ISafeHtmlProducer + { + if($handler instanceof HiddenDataHandler) + { + return $handler->getInput(); + } + + //Pre render input, as the ID may be generated in this stage + $input = $this->_renderInput($handler)->produceSafeHTML(); + + return Div::create( + $this->_renderLabel($handler), + $this->_renderErrors($handler), + $input + )->addClass($this->bem()->getElementName('field')) + ->addClass(empty($handler->getErrors()) ? null : $this->bem()->getModifier('error', 'field')); + } + + protected function _renderLabel(DataHandler $handler): ?ISafeHtmlProducer + { + $label = $handler->getLabel(); + if($label === null || $label === '') + { + return null; + } + + return Div::create( + Label::create($label)->setAttribute('for', $handler->getId()) + )->addClass($this->bem()->getElementName('label')); + } + + protected function _renderErrors(DataHandler $handler): ?ISafeHtmlProducer + { + $errors = $handler->getErrors(); + if(empty($errors)) + { + return null; + } + + return Div::create( + empty($errors) ? null : + UnorderedList::create()->setContent(ListItem::collection(Objects::mpull($errors, 'getMessage'))) + )->addClass($this->bem()->getElementName('errors')) + ->addClass(empty($errors) ? $this->bem()->getModifier('hidden', 'errors') : null); //Hide when no errors + } + + protected function _renderInput(DataHandler $handler): ?ISafeHtmlProducer + { + $input = $handler->getInput(); + if($input === null) + { + return null; + } + + return Div::create($input)->addClass($this->bem()->getElementName('input')); + } } diff --git a/src/Decorators/DefaultFormDecorator.phtml b/src/Decorators/DefaultFormDecorator.phtml index 6fc377b..ff471fb 100644 --- a/src/Decorators/DefaultFormDecorator.phtml +++ b/src/Decorators/DefaultFormDecorator.phtml @@ -5,5 +5,8 @@ use Packaged\Form\Decorators\DefaultFormDecorator; -?>getForm()->getDataHandlers() as $handler): ?>getDecorator(); ?> +getForm()->getDataHandlers() as $handler): + ?>renderHandler($handler)->produceSafeHTML(); + ?>getForm()->getSubmitDecorator(); ?> diff --git a/src/Form/FormSubmitDecorator.php b/src/Form/FormSubmitDecorator.php index 1707396..ab51373 100644 --- a/src/Form/FormSubmitDecorator.php +++ b/src/Form/FormSubmitDecorator.php @@ -13,7 +13,7 @@ class FormSubmitDecorator extends AbstractDecorator public function __construct() { - $this->addClass('p-form-field'); + $this->addClass('p-form__field'); } public function setValue(string $value) @@ -29,7 +29,7 @@ protected function _getValue() protected function _getContentForRender() { - return Div::create($this->_input())->addClass('p-form--submit'); + return Div::create($this->_input())->addClass('p-form__submit'); } protected function _input() diff --git a/tests/Csrf/CsrfFormTest.php b/tests/Csrf/CsrfFormTest.php index 7776cff..be7af54 100644 --- a/tests/Csrf/CsrfFormTest.php +++ b/tests/Csrf/CsrfFormTest.php @@ -38,7 +38,7 @@ public function testRender() $form = new CsrfForm($secret); $html = $form->render(); $this->assertRegExp( - '/
<\/div><\/div><\/form>/', + '/
<\/div><\/div><\/form>/', $html ); } diff --git a/tests/Decorators/FormSubmitDecoratorTest.php b/tests/Decorators/FormSubmitDecoratorTest.php index 00c9072..84b4f23 100644 --- a/tests/Decorators/FormSubmitDecoratorTest.php +++ b/tests/Decorators/FormSubmitDecoratorTest.php @@ -10,8 +10,14 @@ class FormSubmitDecoratorTest extends TestCase public function testSubmitDecorator() { $dec = new FormSubmitDecorator(); - $this->assertEquals('
', $dec->render()); + $this->assertEquals( + '
', + $dec->render() + ); $dec->setValue('Press Here'); - $this->assertEquals('
', $dec->render()); + $this->assertEquals( + '
', + $dec->render() + ); } } diff --git a/tests/FormTest.php b/tests/FormTest.php index 223aca5..2dc2990 100644 --- a/tests/FormTest.php +++ b/tests/FormTest.php @@ -83,28 +83,28 @@ public function testRender() $form = new TestForm(); $form->getDecorator()->setId('vbn'); $this->assertRegExp( - '~
~', + '~
~', $form->render() ); $form->number = 4; $form->text = 'abc'; $this->assertRegExp( - '~
~', + '~
~', $form->render() ); $form->text->getDecorator()->getInput()->setId('myInput'); $form->getDecorator()->setId('abc')->setAttribute('data-test', true); $this->assertRegExp( - '~
~', + '~
~', $form->render() ); $this->assertTrue($form->getDecorator()->hasAttribute('data-test')); $form->getDecorator()->setId('abc')->removeAttribute('data-test'); $this->assertRegExp( - '~
~', + '~
~', $form->render() ); $this->assertfalse($form->getDecorator()->hasAttribute('data-test')); @@ -118,7 +118,7 @@ public function testRender() $decorator->getInput()->setId('myNum'); $form->validate(); $this->assertEquals( - '
  • must be a number
', + '
  • must be a number
', $form->render() ); }