8000 fixxed #94 'Missing required failure message for CollectionInputFilter' issue by ruzann · Pull Request #170 · zendframework/zend-inputfilter · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

fixxed #94 'Missing required failure message for CollectionInputFilter' issue #170

Merged
merged 4 commits into from
Dec 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ All notable changes to this project will be documented in this file, in reverse

### Added

- Nothing.
- [#170](https://github.com/zendframework/zend-inputfilter/pull/170) adds the ability to set a "required" message on a `CollectionInputFilter`.
By default, such instances will lazy-load a `NotEmpty` validator, and use its
messages to report that the collection was empty if it is marked as required.
If you wish to set a different message, you have two options:

- provide a custom `NotEmpty` validator via the new method
`setNotEmptyValidator()`.

- if using a factory, provide the key `required_message` as a sibling to
`required`, containing the custom message. This will replace the typical
`IS_EMPTY` message.

### Changed

Expand Down
63 changes: 59 additions & 4 deletions src/CollectionInputFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Zend\InputFilter;

use Traversable;
use Zend\Validator\NotEmpty;

class CollectionInputFilter extends InputFilter
{
Expand Down Expand Up @@ -43,6 +44,11 @@ class CollectionInputFilter extends InputFilter
*/
protected $inputFilter;

/**
* @var NotEmpty
*/
protected $notEmptyValidator;

/**
* Set the input filter to use when looping the data
*
Expand Down Expand Up @@ -164,6 +170,39 @@ public function setData($data)
return $this;
}

/**
* Retrieve the NotEmpty validator to use for failed "required" validations.
*
* This validator will be used to produce a validation failure message in
* cases where the collection is empty but required.
*
* @return NotEmpty
*/
public function getNotEmptyValidator()
{
if ($this->notEmptyValidator === null) {
$this->notEmptyValidator = new NotEmpty();
}

return $this->notEmptyValidator;
}

/**
* Set the NotEmpty validator to use for failed "required" validations.
*
* This validator will be used to produce a validation failure message in
* cases where the collection is empty but required.
*
* @param NotEmpty $notEmptyValidator
* @return $this
*/
public function setNotEmptyValidator(NotEmpty $notEmptyValidator)
{
$this->notEmptyValidator = $notEmptyValidator;

return $this;
}

/**
* {@inheritdoc}
* @param mixed $context Ignored, but present to retain signature compatibility.
Expand All @@ -174,10 +213,9 @@ public function isValid($context = null)
$inputFilter = $this->getInputFilter();
$valid = true;

if ($this->getCount() < 1) {
if ($this->isRequired) {
$valid = false;
}
if ($this->getCount() < 1 && $this->isRequired) {
$this->collectionMessages[] = $this->prepareRequiredValidationFailureMessage();
$valid = false;
}

if (count($this->data) < $this->getCount()) {
Expand Down Expand Up @@ -295,4 +333,21 @@ public function getUnknown()

return $unknownInputs;
}

/**
* @return array<string, string>
*/
protected function prepareRequiredValidationFailureMessage()
{
$notEmptyValidator = $this->getNotEmptyValidator();
$templates = $notEmptyValidator->getOption('messageTemplates');
$message = $templates[NotEmpty::IS_EMPTY];
$translator = $notEmptyValidator->getTranslator();

return [
NotEmpty::IS_EMPTY => $translator
? $translator->translate($message, $notEmptyValidator->getTranslatorTextDomain())
: $message,
];
}
}
3 changes: 3 additions & 0 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,9 @@ public function createInputFilter($inputFilterSpecification)
if (isset($inputFilterSpecification['required'])) {
$inputFilter->setIsRequired($inputFilterSpecification['required']);
}
if (isset($inputFilterSpecification['required_message'])) {
$inputFilter->getNotEmptyValidator()->setMessage($inputFilterSpecification['required_message']);
}
return $inputFilter;
}

Expand Down
32 changes: 31 additions & 1 deletion test/CollectionInputFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public function dataVsValidProvider()
'Required: F, Count: N, Valid: T' => [!$isRequired, null, $colRaw, $validIF , $colRaw, $colFiltered, true , []],
'Required: F, Count: N, Valid: F' => [!$isRequired, null, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages],
'Required: F, Count: +1, Valid: F' => [!$isRequired, 2, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages],
'Required: T, Data: [], Valid: X' => [ $isRequired, null, [] , $noValidIF, [] , [] , false, []],
'Required: T, Data: [], Valid: X' => [ $isRequired, null, [] , $noValidIF, [] , [] , false, [['isEmpty' => 'Value is required and can\'t be empty']]],
'Required: F, Data: [], Valid: X' => [!$isRequired, null, [] , $noValidIF, [] , [] , true , []],
];
// @codingStandardsIgnoreEnd
Expand Down Expand Up @@ -735,4 +735,34 @@ public function testDuplicatedErrorMessages()
],
], $inputFilter->getMessages());
}

public function testLazyLoadsANotEmptyValidatorWhenNoneProvided()
{
$this->assertInstanceOf(NotEmpty::class, $this->inputFilter->getNotEmptyValidator());
}

public function testAllowsComposingANotEmptyValidator()
{
$notEmptyValidator = new NotEmpty();
$this->inputFilter->setNotEmptyValidator($notEmptyValidator);
$this->assertSame($notEmptyValidator, $this->inputFilter->getNotEmptyValidator());
}

public function testUsesMessageFromComposedNotEmptyValidatorWhenRequiredButCollectionIsEmpty()
{
$message = 'this is the validation message';
$notEmptyValidator = new NotEmpty();
$notEmptyValidator->setMessage($message);

$this->inputFilter->setIsRequired(true);
$this->inputFilter->setNotEmptyValidator($notEmptyValidator);

$this->inputFilter->setData([]);

$this->assertFalse($this->inputFilter->isValid());

$this->assertEquals([
[NotEmpty::IS_EMPTY => $message],
], $this->inputFilter->getMessages());
}
}
22 changes: 22 additions & 0 deletions test/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,28 @@ public function testWhenCreateInputPullsInputFromThePluginManagerItMustNotOverwr
$this->assertSame($input->reveal(), $factory->createInput($spec));
}

public function testFactoryCanCreateCollectionInputFilterWithRequiredMessage()
{
$factory = $this->createDefaultFactory();
$message = 'this is the validation message';

/** @var CollectionInputFilter $inputFilter */
$inputFilter = $factory->createInputFilter([
'type' => CollectionInputFilter::class,
'required' => true,
'required_message' => $message,
'inputfilter' => new InputFilter(),
'count' => 3,
]);

$this->assertInstanceOf(CollectionInputFilter::class, $inputFilter);

$notEmptyValidator = $inputFilter->getNotEmptyValidator();
$messageTemplates = $notEmptyValidator->getMessageTemplates();
$this->assertArrayHasKey(Validator\NotEmpty::IS_EMPTY, $messageTemplates);
$this->assertSame($message, $messageTemplates[Validator\NotEmpty::IS_EMPTY]);
}

/**
* @return Factory
*/
Expand Down
0