From c01197cccfc812d64db2bb32fb955e9ba4fc4b71 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 02:58:17 +0300 Subject: [PATCH 01/22] Make quick draft for html-like rules --- src/FormModel.php | 2 +- src/FormModelInterface.php | 2 ++ src/HtmlOptions/HtmlOptionsProvider.php | 9 +++++++ src/HtmlOptions/NumberHtmlOptions.php | 25 +++++++++++++++++++ src/Widget/Input.php | 9 ++++++- tests/FormModelTest.php | 2 +- tests/HtmlOptions/FieldInputTest.php | 32 ++++++++++++++++++++++++ tests/Stub/HtmlOptionsForm.php | 33 +++++++++++++++++++++++++ tests/Stub/LoginForm.php | 2 +- tests/Stub/PersonalForm.php | 2 +- 10 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 src/HtmlOptions/HtmlOptionsProvider.php create mode 100644 src/HtmlOptions/NumberHtmlOptions.php create mode 100644 tests/HtmlOptions/FieldInputTest.php create mode 100644 tests/Stub/HtmlOptionsForm.php diff --git a/src/FormModel.php b/src/FormModel.php index a1bbb3835..59ad4cfa2 100644 --- a/src/FormModel.php +++ b/src/FormModel.php @@ -274,7 +274,7 @@ public function addError(string $attribute, string $error): void * * @return array validation rules */ - protected function rules(): array + public function rules(): array { return []; } diff --git a/src/FormModelInterface.php b/src/FormModelInterface.php index 23a2a7054..e243d0cb4 100644 --- a/src/FormModelInterface.php +++ b/src/FormModelInterface.php @@ -208,6 +208,8 @@ public function formName(): string; */ public function load(array $data, ?string $formName = null): bool; + public function rules(): array; + /** * Performs the data validation. * diff --git a/src/HtmlOptions/HtmlOptionsProvider.php b/src/HtmlOptions/HtmlOptionsProvider.php new file mode 100644 index 000000000..06e304c20 --- /dev/null +++ b/src/HtmlOptions/HtmlOptionsProvider.php @@ -0,0 +1,9 @@ +validator = $validator; + } + + public function getHtmlOptions(): array + { + $options = $this->validator->getOptions(); + return [ + 'min' => $options['min'], + 'max' => $options['max'], + ]; + } +} diff --git a/src/Widget/Input.php b/src/Widget/Input.php index 5746024ba..ea49f6daf 100644 --- a/src/Widget/Input.php +++ b/src/Widget/Input.php @@ -7,6 +7,7 @@ use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Form\FormModelInterface; use Yiisoft\Form\Helper\HtmlForm; +use Yiisoft\Form\HtmlOptions\HtmlOptionsProvider; use Yiisoft\Html\Html; use Yiisoft\Widget\Widget; @@ -57,7 +58,13 @@ public function config(FormModelInterface $data, string $attribute, array $optio $new = clone $this; $new->data = $data; $new->attribute = $attribute; - $new->options = $options; + $rules = $data->rules()[$attribute] ?? []; + foreach ($rules as $rule) { + if ($rule instanceof HtmlOptionsProvider) { + $this->options = array_merge($this->options, $rule->getHtmlOptions()); + } + } + $new->options = array_merge($this->options, $options); return $new; } diff --git a/tests/FormModelTest.php b/tests/FormModelTest.php index d6d6f9f30..3db4b98b9 100644 --- a/tests/FormModelTest.php +++ b/tests/FormModelTest.php @@ -351,7 +351,7 @@ public function attributeHints(): array ]; } - protected function rules(): array + public function rules(): array { return [ 'id' => new Required(), diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php new file mode 100644 index 000000000..f7671b956 --- /dev/null +++ b/tests/HtmlOptions/FieldInputTest.php @@ -0,0 +1,32 @@ + + + + +
+ +HTML; + $html = Field::widget() + ->config($data, 'name') + ->input('name') + ->run(); + $this->assertEqualsWithoutLE($expected, $html); + } + +} diff --git a/tests/Stub/HtmlOptionsForm.php b/tests/Stub/HtmlOptionsForm.php new file mode 100644 index 000000000..0052e4b66 --- /dev/null +++ b/tests/Stub/HtmlOptionsForm.php @@ -0,0 +1,33 @@ + [ + new NumberHtmlOptions( + (new Number()) + ->min(4)->tooSmallMessage('Is too small.') + ->max(5)->tooBigMessage('Is too big.') + ), + ], + ]; + } +} diff --git a/tests/Stub/LoginForm.php b/tests/Stub/LoginForm.php index 057377a30..cdb27f9e8 100644 --- a/tests/Stub/LoginForm.php +++ b/tests/Stub/LoginForm.php @@ -69,7 +69,7 @@ public function attributeLabels(): array ]; } - protected function rules(): array + public function rules(): array { return [ 'login' => $this->loginRules(), diff --git a/tests/Stub/PersonalForm.php b/tests/Stub/PersonalForm.php index dc97bed6e..d0c99e074 100644 --- a/tests/Stub/PersonalForm.php +++ b/tests/Stub/PersonalForm.php @@ -54,7 +54,7 @@ public function customErrorWithIcon(): string return '(✖) This is custom error message.'; } - protected function rules(): array + public function rules(): array { return [ 'name' => [new Required(), (new HasLength())->min(4)->tooShortMessage('Is too short.')], From 103434e07b60527b1c073c15ed416c0e4d1fb4dd Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 7 Jan 2021 23:58:33 +0000 Subject: [PATCH 02/22] Apply fixes from StyleCI --- src/HtmlOptions/HtmlOptionsProvider.php | 3 ++- src/HtmlOptions/NumberHtmlOptions.php | 1 + tests/HtmlOptions/FieldInputTest.php | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/HtmlOptions/HtmlOptionsProvider.php b/src/HtmlOptions/HtmlOptionsProvider.php index 06e304c20..494bb5085 100644 --- a/src/HtmlOptions/HtmlOptionsProvider.php +++ b/src/HtmlOptions/HtmlOptionsProvider.php @@ -1,9 +1,10 @@ run(); $this->assertEqualsWithoutLE($expected, $html); } - } From 357079b5c0ad4d44cd1358776cae4a99d6d3aab3 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:18:40 +0300 Subject: [PATCH 03/22] Add new html options decorators --- src/HtmlOptions/HasLengthHtmlOptions.php | 26 ++++++ .../MatchRegularExpressionHtmlOptions.php | 25 ++++++ src/HtmlOptions/RequiredHtmlOptions.php | 24 ++++++ tests/HtmlOptions/FieldInputTest.php | 85 ++++++++++++++++--- tests/Stub/HtmlOptionsForm.php | 67 +++++++++++++-- 5 files changed, 207 insertions(+), 20 deletions(-) create mode 100644 src/HtmlOptions/HasLengthHtmlOptions.php create mode 100644 src/HtmlOptions/MatchRegularExpressionHtmlOptions.php create mode 100644 src/HtmlOptions/RequiredHtmlOptions.php diff --git a/src/HtmlOptions/HasLengthHtmlOptions.php b/src/HtmlOptions/HasLengthHtmlOptions.php new file mode 100644 index 000000000..c758d4dd5 --- /dev/null +++ b/src/HtmlOptions/HasLengthHtmlOptions.php @@ -0,0 +1,26 @@ +validator = $validator; + } + + public function getHtmlOptions(): array + { + $options = $this->validator->getOptions(); + return [ + 'minlength' => $options['min'], + 'maxlength' => $options['max'], + ]; + } +} diff --git a/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php b/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php new file mode 100644 index 000000000..f222ad12a --- /dev/null +++ b/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php @@ -0,0 +1,25 @@ +validator = $validator; + } + + public function getHtmlOptions(): array + { + $options = $this->validator->getOptions(); + return [ + 'pattern' => $options['pattern'], + ]; + } +} diff --git a/src/HtmlOptions/RequiredHtmlOptions.php b/src/HtmlOptions/RequiredHtmlOptions.php new file mode 100644 index 000000000..8e4c8ed79 --- /dev/null +++ b/src/HtmlOptions/RequiredHtmlOptions.php @@ -0,0 +1,24 @@ +validator = $validator; + } + + public function getHtmlOptions(): array + { + return [ + 'required' => true, + ]; + } +} diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php index f7671b956..8b272f270 100644 --- a/tests/HtmlOptions/FieldInputTest.php +++ b/tests/HtmlOptions/FieldInputTest.php @@ -10,23 +10,82 @@ final class FieldInputTest extends TestCase { - public function testFieldsInput(): void + /** + * @dataProvider htmlOptionsDataProvider + * @param string $propertyName + * @param string $expectedHtml + * @throws \Yiisoft\Factory\Exceptions\InvalidConfigException + */ + public function testFieldsInput(string $propertyName, string $expectedHtml): void { $data = new HtmlOptionsForm(); - $expected = <<<'HTML' -
- - - -
-
-HTML; - $html = Field::widget() - ->config($data, 'name') - ->input('name') + $actualHtml = Field::widget() + ->config($data, $propertyName) + ->input($propertyName) ->run(); - $this->assertEqualsWithoutLE($expected, $html); + $this->assertEqualsWithoutLE($expectedHtml, $actualHtml); + } + + public function htmlOptionsDataProvider(): array + { + return [ + 'number' => [ + 'number', + <<<'HTML' +
+ + + +
+
+ HTML, + ], + 'hasLength' => [ + 'hasLength', + <<<'HTML' +
+ + + +
+
+ HTML, + ], + 'required' => [ + 'required', + <<<'HTML' +
+ + + +
+
+ HTML, + ], + 'pattern' => [ + 'pattern', + <<<'HTML' +
+ + + +
+
+ HTML, + ], + 'combined' => [ + 'combined', + <<<'HTML' +
+ + + +
+
+ HTML, + ], + ]; } } diff --git a/tests/Stub/HtmlOptionsForm.php b/tests/Stub/HtmlOptionsForm.php index 0052e4b66..f5633905a 100644 --- a/tests/Stub/HtmlOptionsForm.php +++ b/tests/Stub/HtmlOptionsForm.php @@ -5,13 +5,23 @@ namespace Yiisoft\Form\Tests\Stub; use Yiisoft\Form\FormModel; +use Yiisoft\Form\HtmlOptions\HasLengthHtmlOptions; +use Yiisoft\Form\HtmlOptions\MatchRegularExpressionHtmlOptions; use Yiisoft\Form\HtmlOptions\NumberHtmlOptions; +use Yiisoft\Form\HtmlOptions\RequiredHtmlOptions; use Yiisoft\Form\Tests\ValidatorFactoryMock; +use Yiisoft\Validator\Rule\HasLength; +use Yiisoft\Validator\Rule\MatchRegularExpression; use Yiisoft\Validator\Rule\Number; +use Yiisoft\Validator\Rule\Required; final class HtmlOptionsForm extends FormModel { - private string $name = ''; + private string $number = ''; + private string $hasLength = ''; + private string $required = ''; + private string $pattern = ''; + private string $combined = ''; public function __construct() { @@ -21,13 +31,56 @@ public function __construct() public function rules(): array { return [ - 'name' => [ - new NumberHtmlOptions( - (new Number()) - ->min(4)->tooSmallMessage('Is too small.') - ->max(5)->tooBigMessage('Is too big.') - ), + 'number' => [ + $this->getNumberHtmlOptions(), + ], + 'hasLength' => [ + $this->getHasLengthHtmlOptions(), + ], + 'required' => [ + $this->getRequiredHtmlOptions(), + ], + 'pattern' => [ + $this->getMatchRegularExpressionHtmlOptions(), + ], + 'combined' => [ + $this->getNumberHtmlOptions(), + $this->getHasLengthHtmlOptions(), + $this->getRequiredHtmlOptions(), + $this->getMatchRegularExpressionHtmlOptions(), ], ]; } + + private function getMatchRegularExpressionHtmlOptions(): MatchRegularExpressionHtmlOptions + { + return new MatchRegularExpressionHtmlOptions( + new MatchRegularExpression('\w+') + ); + } + + private function getRequiredHtmlOptions(): RequiredHtmlOptions + { + return new RequiredHtmlOptions( + new Required() + ); + } + + private function getHasLengthHtmlOptions(): HasLengthHtmlOptions + { + return new HasLengthHtmlOptions( + (new HasLength()) + ->min(4)->tooShortMessage('Is too short.') + ->max(5)->tooLongMessage('Is too long.') + ); + } + + private function getNumberHtmlOptions(): NumberHtmlOptions + { + return new NumberHtmlOptions( + (new Number()) + ->min(4)->tooSmallMessage('Is too small.') + ->max(5)->tooBigMessage('Is too big.') + ); + } } From ba3b1da1918cb6a4f7dfeccd17c3b0f9b46596f5 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:25:04 +0300 Subject: [PATCH 04/22] Fix input name --- tests/HtmlOptions/FieldInputTest.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php index 8b272f270..5b344a17e 100644 --- a/tests/HtmlOptions/FieldInputTest.php +++ b/tests/HtmlOptions/FieldInputTest.php @@ -22,7 +22,6 @@ public function testFieldsInput(string $propertyName, string $expectedHtml): voi $actualHtml = Field::widget() ->config($data, $propertyName) - ->input($propertyName) ->run(); $this->assertEqualsWithoutLE($expectedHtml, $actualHtml); } @@ -35,7 +34,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
@@ -46,7 +45,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
@@ -57,7 +56,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
@@ -68,7 +67,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
@@ -79,7 +78,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
From c864779addfa0ea1f5eb20e8003a3278035d9547 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:25:27 +0300 Subject: [PATCH 05/22] Override input's options with user's options --- src/Widget/Field.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Widget/Field.php b/src/Widget/Field.php index 8daafa954..713b21e41 100644 --- a/src/Widget/Field.php +++ b/src/Widget/Field.php @@ -284,7 +284,7 @@ public function input(string $type, array $options = []): self unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = Input::widget() ->type($type) From 2657c7f999ca864137b9fa77072c7104fa2343e8 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 8 Jan 2021 11:25:54 +0000 Subject: [PATCH 06/22] Apply fixes from StyleCI --- tests/HtmlOptions/FieldInputTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php index ac327e73b..f458baab9 100644 --- a/tests/HtmlOptions/FieldInputTest.php +++ b/tests/HtmlOptions/FieldInputTest.php @@ -12,8 +12,10 @@ final class FieldInputTest extends TestCase { /** * @dataProvider htmlOptionsDataProvider + * * @param string $propertyName * @param string $expectedHtml + * * @throws \Yiisoft\Factory\Exceptions\InvalidConfigException */ public function testFieldsInput(string $propertyName, string $expectedHtml): void From bd9caae8cd83b0c6ad8b87fd6708bca92d57f1fd Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:33:49 +0300 Subject: [PATCH 07/22] Override input's options with user's options --- src/Widget/Field.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Widget/Field.php b/src/Widget/Field.php index 713b21e41..a728e2b68 100644 --- a/src/Widget/Field.php +++ b/src/Widget/Field.php @@ -323,7 +323,7 @@ public function textInput(array $options = []): self unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = TextInput::widget() ->config($new->data, $new->attribute, $new->inputOptions) @@ -359,7 +359,7 @@ public function hiddenInput(array $options = []): self unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{label}'] = ''; $this->parts['{hint}'] = ''; @@ -398,7 +398,7 @@ public function passwordInput(array $options = []): self unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = PasswordInput::widget() ->config($new->data, $new->attribute, $new->inputOptions) @@ -436,7 +436,7 @@ public function fileInput(array $options = [], bool $withoutHiddenInput = false) unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = FileInput::widget() ->config($new->data, $new->attribute, $new->inputOptions) @@ -472,7 +472,7 @@ public function textArea(array $options = []): self unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = TextArea::widget() ->config($new->data, $new->attribute, $new->inputOptions) @@ -622,7 +622,7 @@ public function dropDownList(array $items, array $options = []): self unset($options['class']); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = DropDownList::widget() ->config($new->data, $new->attribute, $new->inputOptions) @@ -663,7 +663,7 @@ public function listBox(array $items, array $options = []): self $new->setForInLabel($options); $new->setAriaAttributes($options); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $this->parts['{input}'] = ListBox::widget() ->config($new->data, $new->attribute, $new->inputOptions) @@ -697,7 +697,7 @@ public function checkboxList(array $items, array $options = []): self $new->setForInLabel($options); $new->setAriaAttributes($options); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $new->skipForInLabel = true; $this->parts['{input}'] = CheckBoxList::widget() @@ -735,7 +735,7 @@ public function radioList(array $items, array $options = []): self $new->addErrorCssClassToInput(); $new->addSuccessCssClassToInput(); $new->setInputRole($options); - $new->inputOptions = array_merge($options, $new->inputOptions); + $new->inputOptions = array_merge($new->inputOptions, $options); $new->skipForInLabel = true; $this->parts['{input}'] = RadioList::widget() From a02cde4c6d8669bfab90068d07ab8c382bdd12a7 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:34:16 +0300 Subject: [PATCH 08/22] Change type when number rule used --- src/HtmlOptions/NumberHtmlOptions.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/HtmlOptions/NumberHtmlOptions.php b/src/HtmlOptions/NumberHtmlOptions.php index ab0270f94..7192cb08e 100644 --- a/src/HtmlOptions/NumberHtmlOptions.php +++ b/src/HtmlOptions/NumberHtmlOptions.php @@ -19,6 +19,7 @@ public function getHtmlOptions(): array { $options = $this->validator->getOptions(); return [ + 'type' => 'number', 'min' => $options['min'], 'max' => $options['max'], ]; From 6eea7347180733f5f3737bafbeda33133d6863eb Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:34:23 +0300 Subject: [PATCH 09/22] Fix tests --- tests/HtmlOptions/FieldInputTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php index ac327e73b..3a53b104f 100644 --- a/tests/HtmlOptions/FieldInputTest.php +++ b/tests/HtmlOptions/FieldInputTest.php @@ -34,7 +34,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
@@ -78,7 +78,7 @@ public function htmlOptionsDataProvider(): array <<<'HTML'
- +
From fadeb69cf34978b5b73ed1ab724ad44d3e90f662 Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 14:48:24 +0300 Subject: [PATCH 10/22] Add email html options --- src/HtmlOptions/EmailHtmlOptions.php | 24 ++++++++++++++++++++++++ tests/HtmlOptions/FieldInputTest.php | 14 +++++++++++++- tests/Stub/HtmlOptionsForm.php | 13 +++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/HtmlOptions/EmailHtmlOptions.php diff --git a/src/HtmlOptions/EmailHtmlOptions.php b/src/HtmlOptions/EmailHtmlOptions.php new file mode 100644 index 000000000..baccf687f --- /dev/null +++ b/src/HtmlOptions/EmailHtmlOptions.php @@ -0,0 +1,24 @@ +validator = $validator; + } + + public function getHtmlOptions(): array + { + return [ + 'type' => 'email', + ]; + } +} diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php index 1982dc8bd..70e8c4c1b 100644 --- a/tests/HtmlOptions/FieldInputTest.php +++ b/tests/HtmlOptions/FieldInputTest.php @@ -4,6 +4,7 @@ namespace Yiisoft\Form\Tests\HtmlOptions; +use Yiisoft\Factory\Exceptions\InvalidConfigException; use Yiisoft\Form\Tests\Stub\HtmlOptionsForm; use Yiisoft\Form\Tests\TestCase; use Yiisoft\Form\Widget\Field; @@ -16,7 +17,7 @@ final class FieldInputTest extends TestCase * @param string $propertyName * @param string $expectedHtml * - * @throws \Yiisoft\Factory\Exceptions\InvalidConfigException + * @throws InvalidConfigException */ public function testFieldsInput(string $propertyName, string $expectedHtml): void { @@ -75,6 +76,17 @@ public function htmlOptionsDataProvider(): array HTML, ], + 'email' => [ + 'email', + <<<'HTML' + + HTML, + ], 'combined' => [ 'combined', <<<'HTML' diff --git a/tests/Stub/HtmlOptionsForm.php b/tests/Stub/HtmlOptionsForm.php index f5633905a..f6ec0b566 100644 --- a/tests/Stub/HtmlOptionsForm.php +++ b/tests/Stub/HtmlOptionsForm.php @@ -5,11 +5,13 @@ namespace Yiisoft\Form\Tests\Stub; use Yiisoft\Form\FormModel; +use Yiisoft\Form\HtmlOptions\EmailHtmlOptions; use Yiisoft\Form\HtmlOptions\HasLengthHtmlOptions; use Yiisoft\Form\HtmlOptions\MatchRegularExpressionHtmlOptions; use Yiisoft\Form\HtmlOptions\NumberHtmlOptions; use Yiisoft\Form\HtmlOptions\RequiredHtmlOptions; use Yiisoft\Form\Tests\ValidatorFactoryMock; +use Yiisoft\Validator\Rule\Email; use Yiisoft\Validator\Rule\HasLength; use Yiisoft\Validator\Rule\MatchRegularExpression; use Yiisoft\Validator\Rule\Number; @@ -21,6 +23,7 @@ final class HtmlOptionsForm extends FormModel private string $hasLength = ''; private string $required = ''; private string $pattern = ''; + private string $email = ''; private string $combined = ''; public function __construct() @@ -43,6 +46,9 @@ public function rules(): array 'pattern' => [ $this->getMatchRegularExpressionHtmlOptions(), ], + 'email' => [ + $this->getEmailHtmlOptions(), + ], 'combined' => [ $this->getNumberHtmlOptions(), $this->getHasLengthHtmlOptions(), @@ -59,6 +65,13 @@ private function getMatchRegularExpressionHtmlOptions(): MatchRegularExpressionH ); } + private function getEmailHtmlOptions(): EmailHtmlOptions + { + return new EmailHtmlOptions( + new Email() + ); + } + private function getRequiredHtmlOptions(): RequiredHtmlOptions { return new RequiredHtmlOptions( From 00f2fda2f1c09f709020a319b70e7d3e5d4f261e Mon Sep 17 00:00:00 2001 From: Dmitry Derepko Date: Fri, 8 Jan 2021 17:27:06 +0300 Subject: [PATCH 11/22] Add aria-required support via RequiredHtmlOptions, fix tests --- src/FormModel.php | 7 +++-- src/HtmlOptions/EmailHtmlOptions.php | 5 ++-- src/HtmlOptions/HasLengthHtmlOptions.php | 5 ++-- .../MatchRegularExpressionHtmlOptions.php | 5 ++-- src/HtmlOptions/NumberHtmlOptions.php | 5 ++-- src/HtmlOptions/RequiredHtmlOptions.php | 15 +++++++++-- src/HtmlOptions/ValidatorAwareTrait.php | 18 +++++++++++++ src/Widget/Field.php | 5 ---- tests/HtmlOptions/FieldInputTest.php | 4 +-- tests/Stub/PersonalForm.php | 3 ++- tests/Widget/FieldErrorTest.php | 4 +-- tests/Widget/FieldHintTest.php | 6 ++--- tests/Widget/FieldPasswordInputTest.php | 6 ++--- tests/Widget/FieldSuccessTest.php | 4 +-- tests/Widget/FieldTest.php | 6 ++--- tests/Widget/FieldTextInputTest.php | 6 ++--- tests/Widget/FormTest.php | 10 +++---- tests/Widget/PasswordInputTest.php | 26 +++++++++---------- tests/Widget/TextInputTest.php | 13 ++++++++++ 19 files changed, 99 insertions(+), 54 deletions(-) create mode 100644 src/HtmlOptions/ValidatorAwareTrait.php diff --git a/src/FormModel.php b/src/FormModel.php index 59ad4cfa2..677e77083 100644 --- a/src/FormModel.php +++ b/src/FormModel.php @@ -5,13 +5,13 @@ namespace Yiisoft\Form; use Closure; -use ReflectionClass; use InvalidArgumentException; +use ReflectionClass; +use Yiisoft\Form\HtmlOptions\HtmlOptionsProvider; use Yiisoft\Strings\Inflector; use Yiisoft\Strings\StringHelper; use Yiisoft\Validator\Rule\Required; use Yiisoft\Validator\ValidatorFactoryInterface; - use function array_key_exists; use function array_merge; use function explode; @@ -50,6 +50,9 @@ public function isAttributeRequired(string $attribute): bool if ($validator instanceof Required) { return true; } + if ($validator instanceof HtmlOptionsProvider && (bool)($validator->getHtmlOptions()['required'] ?? false)) { + return true; + } } return false; diff --git a/src/HtmlOptions/EmailHtmlOptions.php b/src/HtmlOptions/EmailHtmlOptions.php index baccf687f..b4160bfba 100644 --- a/src/HtmlOptions/EmailHtmlOptions.php +++ b/src/HtmlOptions/EmailHtmlOptions.php @@ -5,10 +5,11 @@ namespace Yiisoft\Form\HtmlOptions; use Yiisoft\Validator\Rule\Email; +use Yiisoft\Validator\ValidatorRuleInterface; -class EmailHtmlOptions implements HtmlOptionsProvider +class EmailHtmlOptions implements HtmlOptionsProvider, ValidatorRuleInterface { - private Email $validator; + use ValidatorAwareTrait; public function __construct(Email $validator) { diff --git a/src/HtmlOptions/HasLengthHtmlOptions.php b/src/HtmlOptions/HasLengthHtmlOptions.php index c758d4dd5..d4941ccb7 100644 --- a/src/HtmlOptions/HasLengthHtmlOptions.php +++ b/src/HtmlOptions/HasLengthHtmlOptions.php @@ -5,10 +5,11 @@ namespace Yiisoft\Form\HtmlOptions; use Yiisoft\Validator\Rule\HasLength; +use Yiisoft\Validator\ValidatorRuleInterface; -class HasLengthHtmlOptions implements HtmlOptionsProvider +class HasLengthHtmlOptions implements HtmlOptionsProvider, ValidatorRuleInterface { - private HasLength $validator; + use ValidatorAwareTrait; public function __construct(HasLength $validator) { diff --git a/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php b/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php index f222ad12a..b1494bc30 100644 --- a/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php +++ b/src/HtmlOptions/MatchRegularExpressionHtmlOptions.php @@ -5,10 +5,11 @@ namespace Yiisoft\Form\HtmlOptions; use Yiisoft\Validator\Rule\MatchRegularExpression; +use Yiisoft\Validator\ValidatorRuleInterface; -class MatchRegularExpressionHtmlOptions implements HtmlOptionsProvider +class MatchRegularExpressionHtmlOptions implements HtmlOptionsProvider, ValidatorRuleInterface { - private MatchRegularExpression $validator; + use ValidatorAwareTrait; public function __construct(MatchRegularExpression $validator) { diff --git a/src/HtmlOptions/NumberHtmlOptions.php b/src/HtmlOptions/NumberHtmlOptions.php index 7192cb08e..7a05bc140 100644 --- a/src/HtmlOptions/NumberHtmlOptions.php +++ b/src/HtmlOptions/NumberHtmlOptions.php @@ -5,10 +5,11 @@ namespace Yiisoft\Form\HtmlOptions; use Yiisoft\Validator\Rule\Number; +use Yiisoft\Validator\ValidatorRuleInterface; -class NumberHtmlOptions implements HtmlOptionsProvider +class NumberHtmlOptions implements HtmlOptionsProvider, ValidatorRuleInterface { - private Number $validator; + use ValidatorAwareTrait; public function __construct(Number $validator) { diff --git a/src/HtmlOptions/RequiredHtmlOptions.php b/src/HtmlOptions/RequiredHtmlOptions.php index 8e4c8ed79..bcd2e5e9b 100644 --- a/src/HtmlOptions/RequiredHtmlOptions.php +++ b/src/HtmlOptions/RequiredHtmlOptions.php @@ -5,20 +5,31 @@ namespace Yiisoft\Form\HtmlOptions; use Yiisoft\Validator\Rule\Required; +use Yiisoft\Validator\ValidatorRuleInterface; -class RequiredHtmlOptions implements HtmlOptionsProvider +class RequiredHtmlOptions implements HtmlOptionsProvider, ValidatorRuleInterface { - private Required $validator; + use ValidatorAwareTrait; + + private bool $ariaAttribute = false; public function __construct(Required $validator) { $this->validator = $validator; } + public function withAriaAttribute(bool $value): self + { + $new = clone $this; + $new->ariaAttribute = $value; + return $new; + } + public function getHtmlOptions(): array { return [ 'required' => true, + 'aria-required' => $this->ariaAttribute ? 'true' : false, ]; } } diff --git a/src/HtmlOptions/ValidatorAwareTrait.php b/src/HtmlOptions/ValidatorAwareTrait.php new file mode 100644 index 000000000..271650103 --- /dev/null +++ b/src/HtmlOptions/ValidatorAwareTrait.php @@ -0,0 +1,18 @@ +validator->validate($value, $dataSet, $previousRulesErrored); + } +} diff --git a/src/Widget/Field.php b/src/Widget/Field.php index a728e2b68..ca0bdf080 100644 --- a/src/Widget/Field.php +++ b/src/Widget/Field.php @@ -11,7 +11,6 @@ use Yiisoft\Form\Helper\HtmlForm; use Yiisoft\Html\Html; use Yiisoft\Widget\Widget; - use function array_merge; use function strtr; @@ -971,10 +970,6 @@ private function setForInLabel(array $options = []): void private function setAriaAttributes(array $options = []): void { if ($this->ariaAttribute) { - if (!isset($options['aria-required']) && $this->data->isAttributeRequired($this->attribute)) { - $this->inputOptions['aria-required'] = 'true'; - } - if (!isset($options['aria-invalid']) && $this->data->hasErrors($this->attribute)) { $this->inputOptions['aria-invalid'] = 'true'; } diff --git a/tests/HtmlOptions/FieldInputTest.php b/tests/HtmlOptions/FieldInputTest.php index 70e8c4c1b..e49c2d444 100644 --- a/tests/HtmlOptions/FieldInputTest.php +++ b/tests/HtmlOptions/FieldInputTest.php @@ -58,7 +58,7 @@ public function htmlOptionsDataProvider(): array 'required', <<<'HTML'
- +
@@ -91,7 +91,7 @@ public function htmlOptionsDataProvider(): array 'combined', <<<'HTML'
- +
diff --git a/tests/Stub/PersonalForm.php b/tests/Stub/PersonalForm.php index d0c99e074..97ce8eddf 100644 --- a/tests/Stub/PersonalForm.php +++ b/tests/Stub/PersonalForm.php @@ -5,6 +5,7 @@ namespace Yiisoft\Form\Tests\Stub; use Yiisoft\Form\FormModel; +use Yiisoft\Form\HtmlOptions\RequiredHtmlOptions; use Yiisoft\Form\Tests\ValidatorFactoryMock; use Yiisoft\Validator\Rule\Email; use Yiisoft\Validator\Rule\HasLength; @@ -60,7 +61,7 @@ public function rules(): array 'name' => [new Required(), (new HasLength())->min(4)->tooShortMessage('Is too short.')], 'email' => [new Email()], 'password' => [ - new Required(), + (new RequiredHtmlOptions(new Required()))->withAriaAttribute(true), (new MatchRegularExpression("/(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}/")) ->message( 'Must contain at least one number and one uppercase and lowercase letter, and at least 8 or ' . diff --git a/tests/Widget/FieldErrorTest.php b/tests/Widget/FieldErrorTest.php index 21dd0097b..ba07fce09 100644 --- a/tests/Widget/FieldErrorTest.php +++ b/tests/Widget/FieldErrorTest.php @@ -19,7 +19,7 @@ public function testFieldError(): void $expected = <<<'HTML'
- +
Write your first name.
Is too short.
@@ -40,7 +40,7 @@ public function testFieldErrorOptions(): void $expected = <<<'HTML'
- +
Write your first name.
Is too short.
diff --git a/tests/Widget/FieldHintTest.php b/tests/Widget/FieldHintTest.php index 8cd62b4a4..e1f7453d8 100644 --- a/tests/Widget/FieldHintTest.php +++ b/tests/Widget/FieldHintTest.php @@ -17,7 +17,7 @@ public function testFieldsHint(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -35,7 +35,7 @@ public function testFieldHintCustom(): void $expected = <<<'HTML'
- +
Custom hint.
@@ -54,7 +54,7 @@ public function testFieldAnyHint(): void $expected = <<<'HTML'
- +
diff --git a/tests/Widget/FieldPasswordInputTest.php b/tests/Widget/FieldPasswordInputTest.php index e27327aeb..b31cf488e 100644 --- a/tests/Widget/FieldPasswordInputTest.php +++ b/tests/Widget/FieldPasswordInputTest.php @@ -20,7 +20,7 @@ public function testFieldsPasswordInput(): void $expected = <<<'HTML'
- +
Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters.
@@ -39,7 +39,7 @@ public function testFieldsPasswordInputWithLabelCustom(): void $expected = <<<'HTML'
- +
@@ -59,7 +59,7 @@ public function testFieldsPasswordInputAnyLabel(): void $expected = <<<'HTML'
- +
diff --git a/tests/Widget/FieldSuccessTest.php b/tests/Widget/FieldSuccessTest.php index 6c122bad9..4c29def74 100644 --- a/tests/Widget/FieldSuccessTest.php +++ b/tests/Widget/FieldSuccessTest.php @@ -19,7 +19,7 @@ public function testFieldSuccess(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -40,7 +40,7 @@ public function testFieldErrorOptions(): void $expected = <<<'HTML'
- +
Write your first name.
diff --git a/tests/Widget/FieldTest.php b/tests/Widget/FieldTest.php index c09d9abbf..d5d4d8245 100644 --- a/tests/Widget/FieldTest.php +++ b/tests/Widget/FieldTest.php @@ -32,7 +32,7 @@ public function testFieldAriaAttributes(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -48,7 +48,7 @@ public function testFieldAriaAttributes(): void $expected = <<<'HTML'
- +
Write your first name.
Is too short.
@@ -66,7 +66,7 @@ public function testEnclosedByContainer(): void $expected = <<<'HTML' - +
Write your first name.
HTML; diff --git a/tests/Widget/FieldTextInputTest.php b/tests/Widget/FieldTextInputTest.php index 0f4e6c073..7c8362d58 100644 --- a/tests/Widget/FieldTextInputTest.php +++ b/tests/Widget/FieldTextInputTest.php @@ -17,7 +17,7 @@ public function testFieldTextInput(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -35,7 +35,7 @@ public function testFieldTextInputWithLabelCustom(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -54,7 +54,7 @@ public function testFieldTextInputAnyLabel(): void $expected = <<<'HTML'
- +
Write your first name.
diff --git a/tests/Widget/FormTest.php b/tests/Widget/FormTest.php index 4025a7fa3..18dffcc99 100644 --- a/tests/Widget/FormTest.php +++ b/tests/Widget/FormTest.php @@ -137,7 +137,7 @@ public function testFormsFieldsOptions(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -153,7 +153,7 @@ public function testFormsFieldsOptions(): void $expected = <<<'HTML'
- +
Write your first name.
@@ -237,7 +237,7 @@ public function testFormsFieldsValidationOnContainer(): void $expected = <<<'HTML'
- +
Write your first name.
Is too short.