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

Commit f770d2d

Browse files
committed
Required Validator
1 parent a46714e commit f770d2d

File tree

6 files changed

+173
-77
lines changed

6 files changed

+173
-77
lines changed

src/ArrayInput.php

+3-5
Original file line numberDiff line numberDiff line change
@@ -63,24 +63,22 @@ public function isValid($context = null)
6363
$hasValue = $this->hasValue();
6464
$required = $this->isRequired();
6565
$hasFallback = $this->hasFallback();
66+
$values = $this->getValue();
6667

6768
if (! $hasValue && $hasFallback) {
6869
$this->setValue($this->getFallbackValue());
6970
return true;
7071
}
7172

7273
if (! $hasValue && $required) {
73-
if ($this->errorMessage === null) {
74-
$this->errorMessage = $this->prepareRequiredValidationFailureMessage();
75-
}
76-
return false;
74+
$this->injectRequiredValidator();
75+
$values = [$this];
7776
}
7877

7978
if (!$this->continueIfEmpty() && !$this->allowEmpty()) {
8079
$this->injectNotEmptyValidator();
8180
}
8281
$validator = $this->getValidatorChain();
83-
$values = $this->getValue();
8482
$result = true;
8583
foreach ($values as $value) {
8684
$empty = ($value === null || $value === '' || $value === []);

src/FileInput.php

+3-5
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,15 @@ public function isValid($context = null)
118118
$required = $this->isRequired();
119119
$allowEmpty = $this->allowEmpty();
120120
$continueIfEmpty = $this->continueIfEmpty();
121+
$validator = $this->getValidatorChain();
121122

122123
if (! $hasValue && ! $required) {
123124
return true;
124125
}
125126

126127
if (! $hasValue && $required && ! $this->hasFallback()) {
127-
if ($this->errorMessage === null) {
128-
$this->errorMessage = $this->prepareRequiredValidationFailureMessage();
129-
}
130-
return false;
128+
$this->injectRequiredValidator();
129+
return $validator->isValid($this);
131130
}
132131

133132
if ($empty && ! $required && ! $continueIfEmpty) {
@@ -139,7 +138,6 @@ public function isValid($context = null)
139138
}
140139

141140
$this->injectUploadValidator();
142-
$validator = $this->getValidatorChain();
143141
//$value = $this->getValue(); // Do not run the filters yet for File uploads (see getValue())
144142

145143
if (!is_array($rawValue)) {

src/Input.php

+27-13
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class Input implements
5959
*/
6060
protected $notEmptyValidator = false;
6161

62+
/**
63+
* @var bool If required validator is in the validator chain.
64+
*/
65+
protected $requiredValidator = false;
66+
6267
/**
6368
* @var bool
6469
*/
@@ -403,10 +408,8 @@ public function isValid($context = null)
403408
}
404409

405410
if (! $hasValue && $required) {
406-
if ($this->errorMessage === null) {
407-
$this->errorMessage = $this->prepareRequiredValidationFailureMessage();
408-
}
409-
return false;
411+
$this->injectRequiredValidator();
412+
$value = $this;
410413
}
411414

412415
if ($empty && ! $required && ! $continueIfEmpty) {
@@ -485,16 +488,27 @@ protected function injectNotEmptyValidator()
485488
}
486489

487490
/**
488-
* Create and return the validation failure message for required input.
489-
*
490-
* @return string[]
491+
* @return void
491492
*/
492-
protected function prepareRequiredValidationFailureMessage()
493+
protected function injectRequiredValidator()
493494
{
494-
$notEmpty = new NotEmpty();
495-
$templates = $notEmpty->getOption('messageTemplates');
496-
return [
497-
NotEmpty::IS_EMPTY => $templates[NotEmpty::IS_EMPTY],
498-
];
495+
if ($this->requiredValidator) {
496+
return;
497+
}
498+
499+
$chain = $this->getValidatorChain();
500+
501+
// Check if Required validator is already in chain
502+
$validators = $chain->getValidators();
503+
foreach ($validators as $validator) {
504+
if ($validator['instance'] instanceof Validator\Required) {
505+
$this->requiredValidator = true;
506+
return;
507+
}
508+
}
509+
510+
$this->requiredValidator = true;
511+
512+
$chain->prependValidator(new Validator\Required(), true);
499513
}
500514
}

src/Validator/Required.php

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Zend\InputFilter\Validator;
4+
5+
use Zend\InputFilter\Input;
6+
use Zend\Validator\AbstractValidator;
7+
8+
class Required extends AbstractValidator
9+
{
10+
const INVALID = 'inputInvalid';
11+
const REQUIRED = 'inputRequired';
12+
13+
/**
14+
* @var string[]
15+
*/
16+
protected $messageTemplates = [
17+
self::INVALID => 'Invalid type given. Zend\InputFilter\Input is required',
18+
self::REQUIRED => 'Value is required',
19+
];
20+
21+
/**
22+
* {@inheritDoc}
23+
*/
24+
public function isValid($value)
25+
{
26+
if (!($value instanceof Input)) {
27+
$this->error(self::INVALID);
28+
return false;
29+
}
30+
31+
$input = $value;
32+
33+
if ($input->hasValue()) { // If has value then all is ok
34+
return true;
35+
}
36+
37+
if ($input->isRequired()) { // It's Required and value was not set.
38+
$this->error(self::REQUIRED);
39+
return false;
40+
}
41+
42+
return true;
43+
}
44+
}

test/InputTest.php

+8-54
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,6 @@ public function setUp()
3434
$this->input = new Input('foo');
3535
}
3636

37-
public function assertRequiredValidationErrorMessage(Input $input, $message = '')
38-
{
39-
$message = $message ?: 'Expected failure message for required input';
40-
$message .= ';';
41-
42-
$messages = $input->getMessages();
43-
$this->assertInternalType('array', $messages, $message . ' non-array messages array');
44-
45-
$notEmpty = new NotEmptyValidator();
46-
$messageTemplates = $notEmpty->getOption('messageTemplates');
47-
$this->assertSame([
48-
NotEmptyValidator::IS_EMPTY => $messageTemplates[NotEmptyValidator::IS_EMPTY],
49-
], $messages, $message . ' missing NotEmpty::IS_EMPTY key and/or contains additional messages');
50-
}
51-
5237
public function testConstructorRequiresAName()
5338
{
5439
$this->assertEquals('foo', $this->input->getName());
@@ -183,59 +168,28 @@ public function testRequiredWithoutFallbackAndValueNotSetThenFail()
183168
$input = $this->input;
184169
$input->setRequired(true);
185170

186-
$this->assertFalse(
187-
$input->isValid(),
188-
'isValid() should be return always false when no fallback value, is required, and not data is set.'
189-
);
190-
$this->assertRequiredValidationErrorMessage($input);
191-
}
192-
193-
public function testRequiredWithoutFallbackAndValueNotSetThenFailReturnsCustomErrorMessageWhenSet()
194-
{
195-
$input = $this->input;
196-
$input->setRequired(true);
197-
$input->setErrorMessage('FAILED TO VALIDATE');
171+
$expectedMessages = [
172+
'inputRequired' => 'Value is required',
173+
];
198174

199175
$this->assertFalse(
200176
$input->isValid(),
201177
'isValid() should be return always false when no fallback value, is required, and not data is set.'
202178
);
203-
$this->assertSame(['FAILED TO VALIDATE'], $input->getMessages());
179+
$this->assertEquals($expectedMessages, $input->getMessages(), 'getMessages() value not match');
204180
}
205181

206-
/**
207-
* @group 28
208-
* @group 60
209-
*/
210-
public function testRequiredWithoutFallbackAndValueNotSetProvidesNotEmptyValidatorIsEmptyErrorMessage()
211-
{
212-
$input = $this->input;
213-
$input->setRequired(true);
214-
215-
$this->assertFalse(
216-
$input->isValid(),
217-
'isValid() should always return false when no fallback value is present, '
218-
. 'the input is required, and no data is set.'
219-
);
220-
$this->assertRequiredValidationErrorMessage($input);
221-
}
222-
223-
/**
224-
* @group 28
225-
* @group 60
226-
*/
227-
public function testRequiredWithoutFallbackAndValueNotSetProvidesCustomErrorMessageWhenSet()
182+
public function testRequiredWithoutFallbackAndValueNotSetThenFailWithCustomErrorMessage()
228183
{
229184
$input = $this->input;
230185
$input->setRequired(true);
231-
$input->setErrorMessage('FAILED TO VALIDATE');
186+
$input->setErrorMessage('fooErrorMessage');
232187

233188
$this->assertFalse(
234189
$input->isValid(),
235-
'isValid() should always return false when no fallback value is present, '
236-
. 'the input is required, and no data is set.'
190+
'isValid() should be return always false when no fallback value, is required, and not data is set.'
237191
);
238-
$this->assertSame(['FAILED TO VALIDATE'], $input->getMessages());
192+
$this->assertEquals(['fooErrorMessage'], $input->getMessages(), 'getMessages() value not match');
239193
}
240194

241195
public function testNotRequiredWithoutFallbackAndValueNotSetThenIsValid()

test/Validator/RequiredTest.php

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace ZendTest\InputFilter\Validator;
4+
5+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
6+
use PHPUnit_Framework_TestCase as TestCase;
7+
use Zend\InputFilter\Input;
8+
use Zend\InputFilter\Validator\Required;
9+
10+
/**
11+
* @covers Zend\InputFilter\Validator\Required
12+
*/
13+
class RequiredTest extends TestCase
14+
{
15+
/**
16+
* @var Required
17+
*/
18+
protected $validator;
19+
20+
protected function setUp()
21+
{
22+
$this->validator = new Required();
23+
}
24+
25+
/**
26+
* @dataProvider inputProvider
27+
*/
28+
public function testValid($input, $expectedIsValid, $expectedMessages)
29+
{
30+
$this->assertEquals(
31+
$expectedIsValid,
32+
$this->validator->isValid($input),
33+
'isValid() value not match. Detail: ' . json_encode($this->validator->getMessages())
34+
);
35+
36+
$this->assertEquals(
37+
$expectedMessages,
38+
$this->validator->getMessages(),
39+
'getMessages() value not match.'
40+
);
41+
}
42+
43+
public function inputProvider()
44+
{
45+
$requiredMsg = [
46+
Required::REQUIRED => 'Value is required',
47+
];
48+
$invalidMsg = [
49+
Required::INVALID => 'Invalid type given. Zend\InputFilter\Input is required',
50+
];
51+
52+
$required = true;
53+
$hasValue = true;
54+
55+
// @codingStandardsIgnoreStart
56+
return [
57+
// Description => [$input, isValid, getMessages]
58+
'Invalid type' => [new \stdClass() , false, $invalidMsg],
59+
'Required: T. Value: Set' => [$this->createInputMock($required, $hasValue), true , []],
60+
'Required: T. Value: Not set' => [$this->createInputMock($required, !$hasValue), false, $requiredMsg],
61+
'Required: F. Value: set' => [$this->createInputMock(!$required, $hasValue), true , []],
62+
'Required: F. Value: Not set' => [$this->createInputMock(!$required, !$hasValue), true , []],
63+
];
64+
// @codingStandardsIgnoreEnd
65+
}
66+
67+
/**
68+
* @param bool $required
69+
* @param bool $hasValue
70+
*
71+
* @return Input|MockObject
72+
*/
73+
protected function createInputMock($required, $hasValue)
74+
{
75+
/** @var Input|MockObject $input */
76+
$input = $this->getMock(Input::class);
77+
78+
$input->method('isRequired')
79+
->willReturn($required)
80+
;
81+
82+
$input->method('hasValue')
83+
->willReturn($hasValue)
84+
;
85+
86+
return $input;
87+
}
88+
}

0 commit comments

Comments
 (0)