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

Commit 6648b93

Browse files
committed
Required Validator
1 parent 1cd1aa7 commit 6648b93

File tree

6 files changed

+163
-78
lines changed

6 files changed

+163
-78
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

+23-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,23 @@ 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+
$chain = $this->getValidatorChain();
496+
497+
// Check if Required validator is already in chain
498+
$validators = $chain->getValidators();
499+
foreach ($validators as $validator) {
500+
if ($validator['instance'] instanceof Validator\Required) {
501+
$this->requiredValidator = true;
502+
return;
503+
}
504+
}
505+
506+
$this->requiredValidator = true;
507+
508+
$chain->prependValidator(new Validator\Required(), true);
499509
}
500510
}

src/Validator/Required.php

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
public function isValid($value)
22+
{
23+
if (!($value instanceof Input)) {
24+
$this->error(self::INVALID);
25+
return false;
26+
}
27+
28+
$input = $value;
29+
30+
if ($input->hasValue()) { // If has value then all is ok
31+
return true;
32+
}
33+
34+
if ($input->isRequired()) { // It's Required and value was not set.
35+
$this->error(self::REQUIRED);
36+
return false;
37+
}
38+
39+
return true;
40+
}
41+
}

test/InputTest.php

+8-55
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use Zend\InputFilter\Input;
1818
use Zend\InputFilter\InputInterface;
1919
use Zend\Validator;
20-
use Zend\Validator\NotEmpty;
2120
use Zend\Validator\ValidatorChain;
2221

2322
/**
@@ -35,21 +34,6 @@ public function setUp()
3534
$this->input = new Input('foo');
3635
}
3736

38-
public function assertRequiredValidationErrorMessage($input, $message = '')
39-
{
40-
$message = $message ?: 'Expected failure message for required input';
41-
$message .= ';';
42-
43-
$messages = $input->getMessages();
44-
$this->assertInternalType('array', $messages, $message . ' non-array messages array');
45-
46-
$notEmpty = new NotEmpty();
47-
$messageTemplates = $notEmpty->getOption('messageTemplates');
48-
$this->assertSame([
49-
NotEmpty::IS_EMPTY => $messageTemplates[NotEmpty::IS_EMPTY],
50-
], $messages, $message . ' missing NotEmpty::IS_EMPTY key and/or contains additional messages');
51-
}
52-
5337
public function testConstructorRequiresAName()
5438
{
5539
$this->assertEquals('foo', $this->input->getName());
@@ -184,59 +168,28 @@ public function testRequiredWithoutFallbackAndValueNotSetThenFail()
184168
$input = $this->input;
185169
$input->setRequired(true);
186170

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

200175
$this->assertFalse(
201176
$input->isValid(),
202177
'isValid() should be return always false when no fallback value, is required, and not data is set.'
203178
);
204-
$this->assertSame(['FAILED TO VALIDATE'], $input->getMessages());
179+
$this->assertEquals($expectedMessages, $input->getMessages(), 'getMessages() value not match');
205180
}
206181

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

234188
$this->assertFalse(
235189
$input->isValid(),
236-
'isValid() should always return false when no fallback value is present, '
237-
. '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.'
238191
);
239-
$this->assertSame(['FAILED TO VALIDATE'], $input->getMessages());
192+
$this->assertEquals(['fooErrorMessage'], $input->getMessages(), 'getMessages() value not match');
240193
}
241194

242195
public function testNotRequiredWithoutFallbackAndValueNotSetThenIsValid()

test/Validator/RequiredTest.php

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
// @codingStandardsIgnoreStart
53+
return [
54+
// Description => [$input, isValid, getMessages]
55+
'Invalid type' => [new \stdClass() , false, $invalidMsg],
56+
'Required: T. Value: Set' => [$this->createInputMock(true, true) , true , []],
57+
'Required: T. Value: Not set' => [$this->createInputMock(true, false) , false, $requiredMsg],
58+
'Required: F. Value: set' => [$this->createInputMock(false, true) , true , []],
59+
'Required: F. Value: Not set' => [$this->createInputMock(false, false), true , []],
60+
];
61+
// @codingStandardsIgnoreEnd
62+
}
63+
64+
/**
65+
* @param bool $required
66+
* @param bool $hasValue
67+
*
68+
* @return Input|MockObject
69+
*/
70+
protected function createInputMock($required, $hasValue)
71+
{
72+
/** @var Input|MockObject $input */
73+
$input = $this->getMock(Input::class);
74+
75+
$input->method('isRequired')
76+
->willReturn($required)
77+
;
78+
79+
$input->method('hasValue')
80+
->willReturn($hasValue)
81+
;
82+
83+
return $input;
84+
}
85+
}

0 commit comments

Comments
 (0)