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

Commit f48098a

Browse files
committed
Merge branch 'feature/170-required-collection-message' into develop
Close #170 Fixes #94
2 parents 68b5d93 + 9fd3546 commit f48098a

File tree

5 files changed

+126
-6
lines changed

5 files changed

+126
-6
lines changed

CHANGELOG.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,17 @@ All notable changes to this project will be documented in this file, in reverse
66

77
### Added
88

9-
- Nothing.
9+
- [#170](https://github.com/zendframework/zend-inputfilter/pull/170) adds the ability to set a "required" message on a `CollectionInputFilter`.
10+
By default, such instances will lazy-load a `NotEmpty` validator, and use its
11+
messages to report that the collection was empty if it is marked as required.
12+
If you wish to set a different message, you have two options:
13+
14+
- provide a custom `NotEmpty` validator via the new method
15+
`setNotEmptyValidator()`.
16+
17+
- if using a factory, provide the key `required_message` as a sibling to
18+
`required`, containing the custom message. This will replace the typical
19+
`IS_EMPTY` message.
1020

1121
### Changed
1222

src/CollectionInputFilter.php

+59-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace Zend\InputFilter;
1111

1212
use Traversable;
13+
use Zend\Validator\NotEmpty;
1314

1415
class CollectionInputFilter extends InputFilter
1516
{
@@ -43,6 +44,11 @@ class CollectionInputFilter extends InputFilter
4344
*/
4445
protected $inputFilter;
4546

47+
/**
48+
* @var NotEmpty
49+
*/
50+
protected $notEmptyValidator;
51+
4652
/**
4753
* Set the input filter to use when looping the data
4854
*
@@ -164,6 +170,39 @@ public function setData($data)
164170
return $this;
165171
}
166172

173+
/**
174+
* Retrieve the NotEmpty validator to use for failed "required" validations.
175+
*
176+
* This validator will be used to produce a validation failure message in
177+
* cases where the collection is empty but required.
178+
*
179+
* @return NotEmpty
180+
*/
181+
public function getNotEmptyValidator()
182+
{
183+
if ($this->notEmptyValidator === null) {
184+
$this->notEmptyValidator = new NotEmpty();
185+
}
186+
187+
return $this->notEmptyValidator;
188+
}
189+
190+
/**
191+
* Set the NotEmpty validator to use for failed "required" validations.
192+
*
193+
* This validator will be used to produce a validation failure message in
194+
* cases where the collection is empty but required.
195+
*
196+
* @param NotEmpty $notEmptyValidator
197+
* @return $this
198+
*/
199+
public function setNotEmptyValidator(NotEmpty $notEmptyValidator)
200+
{
201+
$this->notEmptyValidator = $notEmptyValidator;
202+
203+
return $this;
204+
}
205+
167206
/**
168207
* {@inheritdoc}
169208
* @param mixed $context Ignored, but present to retain signature compatibility.
@@ -174,10 +213,9 @@ public function isValid($context = null)
174213
$inputFilter = $this->getInputFilter();
175214
$valid = true;
176215

177-
if ($this->getCount() < 1) {
178-
if ($this->isRequired) {
179-
$valid = false;
180-
}
216+
if ($this->getCount() < 1 && $this->isRequired) {
217+
$this->collectionMessages[] = $this->prepareRequiredValidationFailureMessage();
218+
$valid = false;
181219
}
182220

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

296334
return $unknownInputs;
297335
}
336+
337+
/**
338+
* @return array<string, string>
339+
*/
340+
protected function prepareRequiredValidationFailureMessage()
341+
{
342+
$notEmptyValidator = $this->getNotEmptyValidator();
343+
$templates = $notEmptyValidator->getOption('messageTemplates');
344+
$message = $templates[NotEmpty::IS_EMPTY];
345+
$translator = $notEmptyValidator->getTranslator();
346+
347+
return [
348+
NotEmpty::IS_EMPTY => $translator
349+
? $translator->translate($message, $notEmptyValidator->getTranslatorTextDomain())
350+
: $message,
351+
];
352+
}
298353
}

src/Factory.php

+3
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ public function createInputFilter($inputFilterSpecification)
319319
if (isset($inputFilterSpecification['required'])) {
320320
$inputFilter->setIsRequired($inputFilterSpecification['required']);
321321
}
322+
if (isset($inputFilterSpecification['required_message'])) {
323+
$inputFilter->getNotEmptyValidator()->setMessage($inputFilterSpecification['required_message']);
324+
}
322325
return $inputFilter;
323326
}
324327

test/CollectionInputFilterTest.php

+31-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public function dataVsValidProvider()
171171
'Required: F, Count: N, Valid: T' => [!$isRequired, null, $colRaw, $validIF , $colRaw, $colFiltered, true , []],
172172
'Required: F, Count: N, Valid: F' => [!$isRequired, null, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages],
173173
'Required: F, Count: +1, Valid: F' => [!$isRequired, 2, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages],
174-
'Required: T, Data: [], Valid: X' => [ $isRequired, null, [] , $noValidIF, [] , [] , false, []],
174+
'Required: T, Data: [], Valid: X' => [ $isRequired, null, [] , $noValidIF, [] , [] , false, [['isEmpty' => 'Value is required and can\'t be empty']]],
175175
'Required: F, Data: [], Valid: X' => [!$isRequired, null, [] , $noValidIF, [] , [] , true , []],
176176
];
177177
// @codingStandardsIgnoreEnd
@@ -735,4 +735,34 @@ public function testDuplicatedErrorMessages()
735735
],
736736
], $inputFilter->getMessages());
737737
}
738+
739+
public function testLazyLoadsANotEmptyValidatorWhenNoneProvided()
740+
{
741+
$this->assertInstanceOf(NotEmpty::class, $this->inputFilter->getNotEmptyValidator());
742+
}
743+
744+
public function testAllowsComposingANotEmptyValidator()
745+
{
746+
$notEmptyValidator = new NotEmpty();
747+
$this->inputFilter->setNotEmptyValidator($notEmptyValidator);
748+
$this->assertSame($notEmptyValidator, $this->inputFilter->getNotEmptyValidator());
749+
}
750+
751+
public function testUsesMessageFromComposedNotEmptyValidatorWhenRequiredButCollectionIsEmpty()
752+
{
753+
$message = 'this is the validation message';
754+
$notEmptyValidator = new NotEmpty();
755+
$notEmptyValidator->setMessage($message);
756+
757+
$this->inputFilter->setIsRequired(true);
758+
$this->inputFilter->setNotEmptyValidator($notEmptyValidator);
759+
760+
$this->inputFilter->setData([]);
761+
762+
$this->assertFalse($this->inputFilter->isValid());
763+
764+
$this->assertEquals([
765+
[NotEmpty::IS_EMPTY => $message],
766+
], $this->inputFilter->getMessages());
767+
}
738768
}

test/FactoryTest.php

+22
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,28 @@ public function testWhenCreateInputPullsInputFromThePluginManagerItMustNotOverwr
10381038
$this->assertSame($input->reveal(), $factory->createInput($spec));
10391039
}
10401040

1041+
public function testFactoryCanCreateCollectionInputFilterWithRequiredMessage()
1042+
{
1043+
$factory = $this->createDefaultFactory();
1044+
$message = 'this is the validation message';
1045+
1046+
/** @var CollectionInputFilter $inputFilter */
1047+
$inputFilter = $factory->createInputFilter([
1048+
'type' => CollectionInputFilter::class,
1049+
'required' => true,
1050+
'required_message' => $message,
1051+
'inputfilter' => new InputFilter(),
1052+
'count' => 3,
1053+
]);
1054+
1055+
$this->assertInstanceOf(CollectionInputFilter::class, $inputFilter);
1056+
1057+
$notEmptyValidator = $inputFilter->getNotEmptyValidator();
1058+
$messageTemplates = $notEmptyValidator->getMessageTemplates();
1059+
$this->assertArrayHasKey(Validator\NotEmpty::IS_EMPTY, $messageTemplates);
1060+
$this->assertSame($message, $messageTemplates[Validator\NotEmpty::IS_EMPTY]);
1061+
}
1062+
10411063
/**
10421064
* @return Factory
10431065
*/

0 commit comments

Comments
 (0)