Skip to content

Commit

Permalink
Add input validation classes (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Jun 7, 2022
1 parent 94344ca commit 86ce1f0
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 9 deletions.
11 changes: 11 additions & 0 deletions src/Field/Base/DateTimeInputField.php
Expand Up @@ -183,4 +183,15 @@ protected function prepareContainerAttributes(array &$attributes): void
);
}
}

protected function prepareInputAttributes(array &$attributes): void
{
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
8 changes: 6 additions & 2 deletions src/Field/Base/ValidationClass/ValidationClassInterface.php
Expand Up @@ -6,7 +6,11 @@

interface ValidationClassInterface
{
public function invalidClass(string $class): self;
public function invalidClass(?string $class): self;

public function validClass(string $class): self;
public function validClass(?string $class): self;

public function inputInvalidClass(?string $class): self;

public function inputValidClass(?string $class): self;
}
62 changes: 57 additions & 5 deletions src/Field/Base/ValidationClass/ValidationClassTrait.php
Expand Up @@ -8,12 +8,14 @@
use Yiisoft\Html\Html;

/**
* @psalm-require-extends \Yiisoft\Form\Field\Base\BaseField
* @psalm-require-extends \Yiisoft\Form\Field\Base\PartsField
*/
trait ValidationClassTrait
{
private ?string $invalidClass = null;
private ?string $validClass = null;
private ?string $inputInvalidClass = null;
private ?string $inputValidClass = null;

/**
* Set invalid CSS class.
Expand All @@ -35,23 +37,73 @@ public function validClass(?string $class): self
return $new;
}

/**
* Set invalid CSS class for input tag.
*/
public function inputInvalidClass(?string $class): self
{
$new = clone $this;
$new->inputInvalidClass = $class;
return $new;
}

/**
* Set valid CSS class for input tag.
*/
public function inputValidClass(?string $class): self
{
$new = clone $this;
$new->inputValidClass = $class;
return $new;
}

protected function addValidationClassToAttributes(
array &$attributes,
FormModelInterface $formModel,
string $attributeName,
): void {
$this->addClassesToAttributes(
$attributes,
$formModel,
$attributeName,
$this->invalidClass,
$this->validClass,
);
}

protected function addInputValidationClassToAttributes(
array &$attributes,
FormModelInterface $formModel,
string $attributeName,
): void {
$this->addClassesToAttributes(
$attributes,
$formModel,
$attributeName,
$this->inputInvalidClass,
$this->inputValidClass,
);
}

private function addClassesToAttributes(
array &$attributes,
FormModelInterface $formModel,
string $attributeName,
?string $invalidClass,
?string $validClass,
): void {
if (!$formModel->isValidated()) {
return;
}

$hasErrors = $formModel->getFormErrors()->hasErrors($attributeName);

if ($hasErrors && $this->invalidClass !== null) {
Html::addCssClass($attributes, $this->invalidClass);
if ($hasErrors && $invalidClass !== null) {
Html::addCssClass($attributes, $invalidClass);
}

if (!$hasErrors && $this->validClass !== null) {
Html::addCssClass($attributes, $this->validClass);
if (!$hasErrors && $validClass !== null) {
Html::addCssClass($attributes, $validClass);
}
}
}
11 changes: 11 additions & 0 deletions src/Field/Checkbox.php
Expand Up @@ -289,4 +289,15 @@ protected function prepareContainerAttributes(array &$attributes): void
);
}
}

protected function prepareInputAttributes(array &$attributes): void
{
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Email.php
Expand Up @@ -260,5 +260,12 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
11 changes: 11 additions & 0 deletions src/Field/File.php
Expand Up @@ -204,4 +204,15 @@ protected function prepareContainerAttributes(array &$attributes): void
);
}
}

protected function prepareInputAttributes(array &$attributes): void
{
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Number.php
Expand Up @@ -212,5 +212,12 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Password.php
Expand Up @@ -251,5 +251,12 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
11 changes: 11 additions & 0 deletions src/Field/Range.php
Expand Up @@ -242,4 +242,15 @@ protected function prepareContainerAttributes(array &$attributes): void
);
}
}

protected function prepareInputAttributes(array &$attributes): void
{
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
11 changes: 11 additions & 0 deletions src/Field/Select.php
Expand Up @@ -303,4 +303,15 @@ protected function prepareContainerAttributes(array &$attributes): void
);
}
}

protected function prepareInputAttributes(array &$attributes): void
{
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Telephone.php
Expand Up @@ -246,5 +246,12 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Text.php
Expand Up @@ -262,5 +262,12 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Textarea.php
Expand Up @@ -268,5 +268,12 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}
}
7 changes: 7 additions & 0 deletions src/Field/Url.php
Expand Up @@ -260,6 +260,13 @@ protected function prepareContainerAttributes(array &$attributes): void
protected function prepareInputAttributes(array &$attributes): void
{
$this->preparePlaceholderInInputAttributes($attributes);
if ($this->hasFormModelAndAttribute()) {
$this->addInputValidationClassToAttributes(
$attributes,
$this->getFormModel(),
$this->getFormAttributeName(),
);
}
}

private function generateSchemePattern(string $scheme): string
Expand Down
8 changes: 8 additions & 0 deletions src/FieldFactory.php
Expand Up @@ -66,6 +66,8 @@ public function __construct(
private ?bool $usePlaceholder = null,
private ?string $validClass = null,
private ?string $invalidClass = null,
private ?string $inputValidClass = null,
private ?string $inputInvalidClass = null,
private ?bool $enrichmentFromRules = null,
private array $fieldConfigs = [],
) {
Expand Down Expand Up @@ -358,6 +360,12 @@ private function makeFieldConfig(string $class): array
if ($this->invalidClass !== null) {
$config['invalidClass()'] = [$this->invalidClass];
}
if ($this->inputValidClass !== null) {
$config['inputValidClass()'] = [$this->inputValidClass];
}
if ($this->inputInvalidClass !== null) {
$config['inputInvalidClass()'] = [$this->inputInvalidClass];
}
}

return $config;
Expand Down
37 changes: 37 additions & 0 deletions tests/Field/TextTest.php
Expand Up @@ -616,6 +616,43 @@ public function testValidClass(): void
$this->assertSame($expected, $result);
}

public function testInputInvalidClass(): void
{
$expected = <<<'HTML'
<div>
<label for="textform-company">Company</label>
<input type="text" id="textform-company" class="invalid" name="TextForm[company]" value>
<div>Value cannot be blank.</div>
</div>
HTML;

$result = Text::widget()
->inputInvalidClass('invalid')
->inputValidClass('valid')
->formAttribute(TextForm::validated(), 'company')
->render();

$this->assertSame($expected, $result);
}

public function testInputValidClass(): void
{
$expected = <<<'HTML'
<div>
<label for="textform-job">Job</label>
<input type="text" id="textform-job" class="valid" name="TextForm[job]" value>
</div>
HTML;

$result = Text::widget()
->inputInvalidClass('invalid')
->inputValidClass('valid')
->formAttribute(TextForm::validated(), 'job')
->render();

$this->assertSame($expected, $result);
}

public function dataEnrichmentFromRules(): array
{
return [
Expand Down
27 changes: 27 additions & 0 deletions tests/FieldFactoryTest.php
Expand Up @@ -234,6 +234,33 @@ public function dataText(): array
],
'company',
],
[
<<<'HTML'
<div class="wrapper">
<label for="textform-job">Job</label>
<input type="text" id="textform-job" class="valid" name="TextForm[job]" value>
</div>
HTML,
[
'inputValidClass' => 'valid',
'containerAttributes' => ['class' => 'wrapper'],
],
'job',
],
[
<<<'HTML'
<div class="wrapper">
<label for="textform-company">Company</label>
<input type="text" id="textform-company" class="invalid" name="TextForm[company]" value>
<div>Value cannot be blank.</div>
</div>
HTML,
[
'inputInvalidClass' => 'invalid',
'containerAttributes' => ['class' => 'wrapper'],
],
'company',
],
[
<<<'HTML'
<div>
Expand Down
4 changes: 2 additions & 2 deletions tests/Support/StubPartsField.php
Expand Up @@ -8,7 +8,7 @@

final class StubPartsField extends PartsField
{
private string $inputHtml = '';
private ?string $inputHtml = null;

public function setInputHtml(string $html): self
{
Expand All @@ -18,6 +18,6 @@ public function setInputHtml(string $html): self

protected function generateInput(): string
{
return $this->inputHtml;
return $this->inputHtml ?? parent::generateInput();
}
}

0 comments on commit 86ce1f0

Please sign in to comment.