Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Required aria attribute #68

Merged
merged 27 commits into from Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c01197c
Make quick draft for html-like rules
xepozz Jan 7, 2021
103434e
Apply fixes from StyleCI
samdark Jan 7, 2021
357079b
Add new html options decorators
xepozz Jan 8, 2021
ba3b1da
Fix input name
xepozz Jan 8, 2021
c864779
Override input's options with user's options
xepozz Jan 8, 2021
8dd6146
Merge remote-tracking branch 'origin/html-like-rules' into html-like-…
xepozz Jan 8, 2021
2657c7f
Apply fixes from StyleCI
samdark Jan 8, 2021
bd9caae
Override input's options with user's options
xepozz Jan 8, 2021
a02cde4
Change type when number rule used
xepozz Jan 8, 2021
6eea734
Fix tests
xepozz Jan 8, 2021
50d27af
Merge remote-tracking branch 'origin/html-like-rules' into html-like-…
xepozz Jan 8, 2021
fadeb69
Add email html options
xepozz Jan 8, 2021
00f2fda
Add aria-required support via RequiredHtmlOptions, fix tests
xepozz Jan 8, 2021
70be142
Apply fixes from StyleCI
samdark Jan 8, 2021
9931f7e
Rename interfaces
xepozz Jan 8, 2021
d5e4ed3
Merge remote-tracking branch 'origin/required-aria-attribute' into re…
xepozz Jan 8, 2021
1f5b961
Move phpdoc to interface
samdark Jan 23, 2021
e904c86
Finalize HTML options
samdark Jan 23, 2021
5f487aa
Add phpdoc for interface
samdark Jan 23, 2021
e7d57b6
Normalize regex pattern
xepozz Jan 24, 2021
8af6ea8
Fix regexp patterns
xepozz Jan 24, 2021
b243091
Fix regexp patterns
xepozz Jan 24, 2021
d446690
Merge branch 'html-like-rules' into required-aria-attribute
xepozz Jan 24, 2021
99ec2b3
Rename ValidatorAwareTrait to RuleAwareTrait and rename properties
xepozz Jan 24, 2021
34ec5af
Merge branch 'master' into required-aria-attribute
xepozz Jan 24, 2021
aa07a9a
Fix tests
xepozz Jan 24, 2021
b85883f
Fix CR
xepozz Jan 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 5 additions & 33 deletions src/FormModel.php
Expand Up @@ -7,6 +7,7 @@
use Closure;
use InvalidArgumentException;
use ReflectionClass;
use Yiisoft\Form\HtmlOptions\HtmlOptionsProvider;
use Yiisoft\Strings\Inflector;
use Yiisoft\Strings\StringHelper;
use Yiisoft\Validator\Rule\Required;
Expand Down Expand Up @@ -45,6 +46,9 @@ public function isAttributeRequired(string $attribute): bool
if ($validator instanceof Required) {
return true;
}
if ($validator instanceof HtmlOptionsProvider && (bool)($validator->getHtmlOptions()['required'] ?? false)) {
samdark marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
}

return false;
Expand Down Expand Up @@ -235,39 +239,7 @@ public function addError(string $attribute, string $error): void
$this->attributesErrors[$attribute][] = $error;
}

/**
* Returns the validation rules for attributes.
*
* Validation rules are used by {@see \Yiisoft\Validator\Validator} to check if attribute values are valid.
* Child classes may override this method to declare different validation rules.
*
* Each rule is an array with the following structure:
*
* ```php
* public function rules(): array
* {
* return [
* 'login' => $this->loginRules()
* ];
* }
*
* private function loginRules(): array
* {
* return [
* new \Yiisoft\Validator\Rule\Required(),
* (new \Yiisoft\Validator\Rule\HasLength())
* ->min(4)
* ->max(40)
* ->tooShortMessage('Is too short.')
* ->tooLongMessage('Is too long.'),
* new \Yiisoft\Validator\Rule\Email()
* ];
* }
* ```
*
* @return array validation rules
*/
protected function rules(): array
public function rules(): array
{
return [];
}
Expand Down
34 changes: 34 additions & 0 deletions src/FormModelInterface.php
Expand Up @@ -209,6 +209,40 @@ public function formName(): string;
*/
public function load(array $data, ?string $formName = null): bool;

/**
* Returns the validation rules for attributes.
*
* Validation rules are used by {@see \Yiisoft\Validator\Validator} to check if attribute values are valid.
* Child classes may override this method to declare different validation rules.
*
* Each rule is an array with the following structure:
*
* ```php
* public function rules(): array
* {
* return [
* 'login' => $this->loginRules()
* ];
* }
*
* private function loginRules(): array
* {
* return [
* new \Yiisoft\Validator\Rule\Required(),
* (new \Yiisoft\Validator\Rule\HasLength())
* ->min(4)
* ->max(40)
* ->tooShortMessage('Is too short.')
* ->tooLongMessage('Is too long.'),
* new \Yiisoft\Validator\Rule\Email()
* ];
* }
* ```
*
* @return array Validation rules.
*/
public function rules(): array;

/**
* Performs the data validation.
*
Expand Down
25 changes: 25 additions & 0 deletions src/HtmlOptions/EmailHtmlOptions.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

use Yiisoft\Validator\Rule\Email;
use Yiisoft\Validator\RuleInterface;

final class EmailHtmlOptions implements HtmlOptionsProvider, RuleInterface
{
use RuleAwareTrait;

public function __construct(Email $rule)
{
$this->rule = $rule;
}

public function getHtmlOptions(): array
{
return [
'type' => 'email',
];
}
}
27 changes: 27 additions & 0 deletions src/HtmlOptions/HasLengthHtmlOptions.php
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

use Yiisoft\Validator\Rule\HasLength;
use Yiisoft\Validator\RuleInterface;

final class HasLengthHtmlOptions implements HtmlOptionsProvider, RuleInterface
{
use RuleAwareTrait;

public function __construct(HasLength $rule)
{
$this->rule = $rule;
}

public function getHtmlOptions(): array
{
$options = $this->rule->getOptions();
xepozz marked this conversation as resolved.
Show resolved Hide resolved
return [
'minlength' => $options['min'],
'maxlength' => $options['max'],
];
}
}
16 changes: 16 additions & 0 deletions src/HtmlOptions/HtmlOptionsProvider.php
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

/**
* Provides options for HTML input tags.
*/
interface HtmlOptionsProvider
{
/**
* @return array Options for HTML input tags in `['optionName' => 'optionValue']` format.
*/
public function getHtmlOptions(): array;
}
27 changes: 27 additions & 0 deletions src/HtmlOptions/MatchRegularExpressionHtmlOptions.php
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

use Yiisoft\Html\Html;
use Yiisoft\Validator\Rule\MatchRegularExpression;
use Yiisoft\Validator\RuleInterface;

final class MatchRegularExpressionHtmlOptions implements HtmlOptionsProvider, RuleInterface
{
use RuleAwareTrait;

public function __construct(MatchRegularExpression $rule)
{
$this->rule = $rule;
}

public function getHtmlOptions(): array
{
$options = $this->rule->getOptions();
xepozz marked this conversation as resolved.
Show resolved Hide resolved
return [
'pattern' => Html::normalizeRegexpPattern($options['pattern']),
];
}
}
28 changes: 28 additions & 0 deletions src/HtmlOptions/NumberHtmlOptions.php
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\RuleInterface;

final class NumberHtmlOptions implements HtmlOptionsProvider, RuleInterface
{
use RuleAwareTrait;

public function __construct(Number $rule)
{
$this->rule = $rule;
}

public function getHtmlOptions(): array
{
$options = $this->rule->getOptions();
xepozz marked this conversation as resolved.
Show resolved Hide resolved
return [
'type' => 'number',
'min' => $options['min'],
'max' => $options['max'],
];
}
}
35 changes: 35 additions & 0 deletions src/HtmlOptions/RequiredHtmlOptions.php
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

use Yiisoft\Validator\Rule\Required;
use Yiisoft\Validator\RuleInterface;

final class RequiredHtmlOptions implements HtmlOptionsProvider, RuleInterface
{
use RuleAwareTrait;

private bool $ariaAttribute = false;

public function __construct(Required $rule)
{
$this->rule = $rule;
}

public function withAriaAttribute(bool $value): self
samdark marked this conversation as resolved.
Show resolved Hide resolved
{
$new = clone $this;
$new->ariaAttribute = $value;
return $new;
}

public function getHtmlOptions(): array
{
return [
'required' => true,
'aria-required' => $this->ariaAttribute ? 'true' : false,
];
}
}
19 changes: 19 additions & 0 deletions src/HtmlOptions/RuleAwareTrait.php
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Form\HtmlOptions;

use Yiisoft\Validator\DataSetInterface;
use Yiisoft\Validator\ParametrizedRuleInterface;
use Yiisoft\Validator\Result;

trait RuleAwareTrait
{
protected ParametrizedRuleInterface $rule;

public function validate($value, DataSetInterface $dataSet = null, bool $previousRulesErrored = false): Result
{
return $this->rule->validate($value, $dataSet, $previousRulesErrored);
}
}
25 changes: 10 additions & 15 deletions src/Widget/Field.php
Expand Up @@ -11,7 +11,6 @@
use Yiisoft\Form\Helper\HtmlForm;
use Yiisoft\Html\Html;
use Yiisoft\Widget\Widget;

use function array_merge;
use function strtr;

Expand Down Expand Up @@ -284,7 +283,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)
Expand Down Expand Up @@ -323,7 +322,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)
Expand Down Expand Up @@ -359,7 +358,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}'] = '';
Expand Down Expand Up @@ -398,7 +397,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)
Expand Down Expand Up @@ -436,7 +435,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)
Expand Down Expand Up @@ -472,7 +471,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)
Expand Down Expand Up @@ -622,7 +621,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)
Expand Down Expand Up @@ -663,7 +662,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)
Expand Down Expand Up @@ -697,7 +696,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()
Expand Down Expand Up @@ -735,7 +734,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()
Expand Down Expand Up @@ -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';
}
Expand Down