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

Validate empty with context #4165

Merged
14 changes: 10 additions & 4 deletions library/Zend/InputFilter/BaseInputFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,10 @@ protected function validateInputs(array $inputs)
&& $input->isRequired()
&& $input->allowEmpty()
) {
$this->validInputs[$name] = $input;
continue;
if (!$input->allowEmpty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zburnham Should this be if (!$input->continueIfEmpty()) {?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, MWOP seemed to think it was ok, but I'll definitely take a look, more
eyes on the code and all that.

Z

On May 4, 2013, at 6:24 PM, Daniel Gimenes notifications@github.com wrote:

In library/Zend/InputFilter/BaseInputFilter.php:

@@ -187,8 +187,10 @@ protected function validateInputs(array $inputs)
&& $input->isRequired()
&& $input->allowEmpty()
) {

  •            $this->validInputs[$name] = $input;
    
  •            continue;
    
  •            if (!$input->allowEmpty()) {
    

@zburnham https://github.com/zburnham Should this be if
(!$input->continueIfEmpty()) {?


Reply to this email directly or view it on
GitHubhttps://github.com//pull/4165/files#r4085890
.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See line 188.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: #4426.

$this->validInputs[$name] = $input;
continue;
}
}

// key exists, is null, input is not required; valid
Expand Down Expand Up @@ -223,14 +225,18 @@ protected function validateInputs(array $inputs)
}

// key exists, empty string, input is required, allows empty; valid
// if continueIfEmpty is false, otherwise validation continues
if ($dataExists
&& '' === $this->data[$name]
&& $input instanceof InputInterface
&& $input instanceof EmptyContextInterface
&& $input->isRequired()
&& $input->allowEmpty()
) {
$this->validInputs[$name] = $input;
continue;
if (!$input->continueIfEmpty()) {
$this->validInputs[$name] = $input;
continue;
}
}

// key exists, is array representing file, no file present, input not
Expand Down
17 changes: 17 additions & 0 deletions library/Zend/InputFilter/EmptyContextInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\InputFilter;

interface EmptyContextInterface
{
public function setContinueIfEmpty($continueIfEmpty);

public function continueIfEmpty();
}
3 changes: 3 additions & 0 deletions library/Zend/InputFilter/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ public function createInput($inputSpecification)
$input->setRequired(!$value);
}
break;
case 'continue_if_empty':
$input->setContinueIfEmpty($inputSpecification['continue_if_empty']);
break;
case 'fallback_value':
$input->setFallbackValue($value);
break;
Expand Down
32 changes: 30 additions & 2 deletions library/Zend/InputFilter/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@
use Zend\Validator\ValidatorChain;
use Zend\Validator\NotEmpty;

class Input implements InputInterface
class Input implements InputInterface, EmptyContextInterface
{
/**
* @var bool
*/
protected $allowEmpty = false;

/**
* @var bool
*/
protected $continueIfEmpty = false;

/**
* @var bool
Expand Down Expand Up @@ -89,6 +94,16 @@ public function setBreakOnFailure($breakOnFailure)
$this->breakOnFailure = (bool) $breakOnFailure;
return $this;
}

/**
* @param bool $continueIfEmpty
* @return \Zend\InputFilter\Input
*/
public function setContinueIfEmpty($continueIfEmpty)
{
$this->continueIfEmpty = (bool) $continueIfEmpty;
return $this;
}

/**
* @param string|null $errorMessage
Expand Down Expand Up @@ -175,6 +190,14 @@ public function breakOnFailure()
{
return $this->breakOnFailure;
}

/**
* @return bool
*/
public function continueIfEmpty()
{
return $this->continueIfEmpty;
}

/**
* @return string|null
Expand Down Expand Up @@ -274,7 +297,12 @@ public function merge(InputInterface $input)
*/
public function isValid($context = null)
{
$this->injectNotEmptyValidator();
// Empty value needs further validation if continueIfEmpty is set
// so don't inject NotEmpty validator which would always
// mark that as false
if (!$this->continueIfEmpty()) {
$this->injectNotEmptyValidator();
}
$validator = $this->getValidatorChain();
$value = $this->getValue();
$result = $validator->isValid($value, $context);
Expand Down
2 changes: 2 additions & 0 deletions library/Zend/InputFilter/InputInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface InputInterface
{
public function setAllowEmpty($allowEmpty);
public function setBreakOnFailure($breakOnFailure);
public function setContinueIfEmpty($continueIfEmpty);
public function setErrorMessage($errorMessage);
public function setFilterChain(FilterChain $filterChain);
public function setName($name);
Expand All @@ -26,6 +27,7 @@ public function merge(InputInterface $input);

public function allowEmpty();
public function breakOnFailure();
public function continueIfEmpty();
public function getErrorMessage();
public function getFilterChain();
public function getName();
Expand Down
49 changes: 48 additions & 1 deletion tests/ZendTest/InputFilter/BaseInputFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,11 @@ public function testValidationAllowsEmptyValuesToRequiredInputWhenAllowEmptyFlag
$filter->add($foo, '')
->add($bar, 'bar');

$data = array('bar' => 124);
$data = array(
'bar' => 124,
'foo' => '',
);

$filter->setData($data);

$this->assertTrue($filter->isValid());
Expand Down Expand Up @@ -559,6 +563,49 @@ public function testValidationMarksInputInvalidWhenRequiredAndAllowEmptyFlagIsFa

$this->assertFalse($filter->isValid());
}

public static function contextDataProvider()
{
return array(
array('', 'y', true),
array('', 'n', false),
);
}

/**
* Idea here is that an empty field may or may not be valid based on
* context.
*/
/**
* @dataProvider contextDataProvider()
*/
public function testValidationMarksInputValidWhenAllowEmptyFlagIsTrueAndContinueIfEmptyIsTrueAndContextValidatesEmptyField($allowEmpty, $blankIsValid, $valid)
{
// $this->markTestSkipped();

$filter = new InputFilter();

$data = array (
'allowEmpty' => $allowEmpty,
'blankIsValid' => $blankIsValid,
);

$allowEmpty = new Input();
$allowEmpty->setAllowEmpty(true)
->setContinueIfEmpty(true);

$blankIsValid = new Input();
$blankIsValid->getValidatorChain()->attach(new Validator\Callback(function($value, $context) {
return ('y' === $value && empty($context['allowEmpty']));
}));

$filter->add($allowEmpty, 'allowEmpty')
->add($blankIsValid, 'blankIsValid');
$filter->setData($data);
// die(var_dump($filter->get('blankIsValid')));

$this->assertSame($valid, $filter->isValid());
}

public function testCanRetrieveRawValuesIndividuallyWithoutValidating()
{
Expand Down
22 changes: 20 additions & 2 deletions tests/ZendTest/InputFilter/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,17 @@ public function testFactoryWillCreateInputWithSuggestedName()
$this->assertInstanceOf('Zend\InputFilter\InputInterface', $input);
$this->assertEquals('foo', $input->getName());
}

public function testFactoryWillCreateInputWithContinueIfEmptyFlag()
{
$factory = new Factory();
$input = $factory->createInput(array(
'name' => 'foo',
'continue_if_empty' => true,
));
$this->assertInstanceOf('Zend\InputFilter\InputInterface', $input);
$this->assertTrue($input->continueIfEmpty());
}

public function testFactoryAcceptsInputInterface()
{
Expand Down Expand Up @@ -339,11 +350,15 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi
'type' => 'ZendTest\InputFilter\TestAsset\CustomInput',
'name' => 'bat',
),
'zomg' => array(
'name' => 'zomg',
'continue_if_empty' => true,
),
));
$this->assertInstanceOf('Zend\InputFilter\InputFilter', $inputFilter);
$this->assertEquals(4, count($inputFilter));
$this->assertEquals(5, count($inputFilter));

foreach (array('foo', 'bar', 'baz', 'bat') as $name) {
foreach (array('foo', 'bar', 'baz', 'bat', 'zomg') as $name) {
$input = $inputFilter->get($name);

switch ($name) {
Expand Down Expand Up @@ -373,6 +388,9 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi
$this->assertInstanceOf('ZendTest\InputFilter\TestAsset\CustomInput', $input);
$this->assertEquals('bat', $input->getName());
break;
case 'zomg':
$this->assertInstanceOf('Zend\InputFilter\Input', $input);
$this->assertTrue($input->continueIfEmpty());
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions tests/ZendTest/InputFilter/InputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,30 @@ public function testAllowEmptyFlagIsMutable()
$input->setAllowEmpty(true);
$this->assertTrue($input->allowEmpty());
}

public function testContinueIfEmptyFlagIsFalseByDefault()
{
$input = new Input('foo');
$this->assertFalse($input->continueIfEmpty());
}

public function testContinueIfEmptyFlagIsMutable()
{
$input = new Input('foo');
$input->setContinueIfEmpty(true);
$this->assertTrue($input->continueIfEmpty());
}

public function testNotEmptyValidatorNotInjectedIfContinueIfEmptyIsTrue()
{
$input = new Input('foo');
$input->setContinueIfEmpty(true);
$input->setValue('');
$input->isValid();
$validators = $input->getValidatorChain()
->getValidators();
$this->assertTrue(0 == count($validators));
}

public function testValueIsNullByDefault()
{
Expand Down