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

Delegate to InputInterface::isValid when data not exists #30

Merged
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
28 changes: 26 additions & 2 deletions src/ArrayInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ public function setValue($value)
return parent::setValue($value);
}

/**
* {@inheritdoc}
*/
public function resetValue()
{
$this->value = [];
$this->hasValue = false;
return $this;
}

/**
* @return array
*/
Expand All @@ -50,6 +60,20 @@ public function getValue()
*/
public function isValid($context = null)
{
$hasValue = $this->hasValue();
$required = $this->isRequired();
$hasFallback = $this->hasFallback();

if (! $hasValue && $hasFallback) {
$this->setValue($this->getFallbackValue());
return true;
}

if (! $hasValue && $required) {
$this->setErrorMessage('Value is required');
return false;
}

if (!$this->continueIfEmpty() && !$this->allowEmpty()) {
$this->injectNotEmptyValidator();
}
Expand All @@ -64,9 +88,9 @@ public function isValid($context = null)
}
$result = $validator->isValid($value, $context);
if (!$result) {
if ($this->hasFallback()) {
if ($hasFallback) {
$this->setValue($this->getFallbackValue());
$result = true;
return true;
}
break;
}
Expand Down
37 changes: 6 additions & 31 deletions src/BaseInputFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,43 +254,13 @@ protected function validateInputs(array $inputs, $data = [], $context = null)
continue;
}

$hasFallback = ($input instanceof Input && $input->hasFallback());

// If input is optional (not required), and value is not set, then ignore.
if (!array_key_exists($name, $data)
&& !$input->isRequired()
) {
continue;
}

// If the value is required, not present in the data set, and
// has no fallback, validation fails.
if (!array_key_exists($name, $data)
&& $input->isRequired()
&& !$hasFallback
) {
$input->setErrorMessage('Value is required');
$this->invalidInputs[$name] = $input;

if ($input->breakOnFailure()) {
return false;
}

$valid = false;
continue;
}

// If the value is required, not present in the data set, and
// has a fallback, validation passes, and we set the input
// value to the fallback.
if (!array_key_exists($name, $data)
&& $input->isRequired()
&& $hasFallback
) {
$input->setValue($input->getFallbackValue());
continue;
}

// Make sure we have a value (empty) for validation of context
if (!array_key_exists($name, $data)) {
$data[$name] = null;
Expand Down Expand Up @@ -545,7 +515,7 @@ protected function populate()
$input->clearRawValues();
}

if (!isset($this->data[$name])) {
if (!array_key_exists($name, $this->data)) {
// No value; clear value in this input
if ($input instanceof InputFilterInterface) {
$input->setData([]);
Expand All @@ -557,6 +527,11 @@ protected function populate()
continue;
}

if ($input instanceof Input) {
$input->resetValue();
continue;
}

$input->setValue(null);
continue;
}
Expand Down
6 changes: 6 additions & 0 deletions src/FileInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,17 @@ public function isEmptyFile($rawValue)
public function isValid($context = null)
{
$rawValue = $this->getRawValue();
$hasValue = $this->hasValue();
$empty = $this->isEmptyFile($rawValue);
$required = $this->isRequired();
$allowEmpty = $this->allowEmpty();
$continueIfEmpty = $this->continueIfEmpty();

if (! $hasValue && $required && ! $this->hasFallback()) {
$this->setErrorMessage('Value is required');
return false;
}

if ($empty && ! $required && ! $continueIfEmpty) {
return true;
}
Expand Down
61 changes: 61 additions & 0 deletions src/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ class Input implements
*/
protected $value;

/**
* Flag for distinguish when $value contains a real `null` or the PHP default property value.
*
* PHP gives to all properties a default value of `null` unless other default value is set.
*
* @var bool
*/
protected $hasValue = false;

/**
* @var mixed
*/
Expand Down Expand Up @@ -163,12 +172,36 @@ public function setValidatorChain(ValidatorChain $validatorChain)
}

/**
* Set the input value.
*
* If you want to remove/unset the current value use {@link Input::resetValue()}.
*
* @see Input::getValue() For retrieve the input value.
* @see Input::hasValue() For to know if input value was set.
* @see Input::resetValue() For reset the input value to the default state.
*
* @param mixed $value
* @return Input
*/
public function setValue($value)
{
$this->value = $value;
$this->hasValue = true;
return $this;
}

/**
* Reset input value to the default state.
*
* @see Input::hasValue() For to know if input value was set.
* @see Input::setValue() For set a new value.
*
* @return Input
*/
public function resetValue()
{
$this->value = null;
$this->hasValue = false;
return $this;
}

Expand Down Expand Up @@ -270,6 +303,23 @@ public function getValue()
return $filter->filter($this->value);
}

/**
* Flag for inform if input value was set.
*
* This flag used for distinguish when {@link Input::getValue()} will return a real `null` value or the PHP default
* value.
*
* @see Input::getValue() For retrieve the input value.
* @see Input::setValue() For set a new value.
* @see Input::resetValue() For reset the input value to the default state.
*
* @return bool
*/
public function hasValue()
{
return $this->hasValue;
}

/**
* @return mixed
*/
Expand Down Expand Up @@ -321,11 +371,22 @@ public function merge(InputInterface $input)
public function isValid($context = null)
{
$value = $this->getValue();
$hasValue = $this->hasValue();
$empty = ($value === null || $value === '' || $value === []);
$required = $this->isRequired();
$allowEmpty = $this->allowEmpty();
$continueIfEmpty = $this->continueIfEmpty();

if (! $hasValue && $this->hasFallback()) {
$this->setValue($this->getFallbackValue());
return true;
}

if (! $hasValue && $required) {
$this->setErrorMessage('Value is required');
return false;
}

if ($empty && ! $required && ! $continueIfEmpty) {
return true;
}
Expand Down
45 changes: 12 additions & 33 deletions test/ArrayInputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,39 +187,6 @@ public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain()
$this->assertEquals($notEmptyMock, $validators[1]['instance']);
}

public function dataFallbackValue()
{
return [
[
'fallbackValue' => []
],
[
'fallbackValue' => [''],
],
[
'fallbackValue' => [null],
],
[
'fallbackValue' => ['some value'],
],
];
}

/**
* @dataProvider dataFallbackValue
*/
public function testFallbackValue($fallbackValue)
{
$this->input->setFallbackValue($fallbackValue);
$validator = new Validator\Date();
$this->input->getValidatorChain()->attach($validator);
$this->input->setValue(['123']); // not a date

$this->assertTrue($this->input->isValid());
$this->assertEmpty($this->input->getMessages());
$this->assertSame($fallbackValue, $this->input->getValue());
}

public function emptyValuesProvider()
{
return [
Expand All @@ -246,4 +213,16 @@ public function testNotAllowEmptyWithFilterConvertsEmptyToNonEmptyIsValid()
}));
$this->assertTrue($this->input->isValid());
}

public function fallbackValueVsIsValidProvider()
{
$dataSets = parent::fallbackValueVsIsValidProvider();
array_walk($dataSets, function (&$set) {
$set[1] = [$set[1]]; // Wrap fallback value into an array.
$set[2] = [$set[2]]; // Wrap value into an array.
$set[4] = [$set[4]]; // Wrap expected value into an array.
});

return $dataSets;
}
}
80 changes: 0 additions & 80 deletions test/BaseInputFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1035,86 +1035,6 @@ public function testEmptyValuePassedForRequiredButAllowedEmptyInputShouldMarkInp
$this->assertTrue($filter->isValid(), 'Empty value should mark input filter as valid');
}

/**
* @group 10
*/
public function testMissingRequiredWithFallbackShouldMarkInputValid()
{
$foo = new Input('foo');
$foo->setRequired(true);
$foo->setAllowEmpty(false);

$bar = new Input('bar');
$bar->setRequired(true);
$bar->setFallbackValue('baz');

$filter = new InputFilter();
$filter->add($foo);
$filter->add($bar);

$filter->setData(['foo' => 'xyz']);
$this->assertTrue($filter->isValid(), 'Missing input with fallback value should mark input filter as valid');
$data = $filter->getValues();
$this->assertArrayHasKey('bar', $data);
$this->assertEquals($bar->getFallbackValue(), $data['bar']);
}

/**
* @group 10
*/
public function testMissingRequiredThatAllowsEmptyWithFallbackShouldMarkInputValid()
{
$foo = new Input('foo');
$foo->setRequired(true);
$foo->setAllowEmpty(false);

$bar = new Input('bar');
$bar->setRequired(true);
$bar->setAllowEmpty(true);
$bar->setFallbackValue('baz');

$filter = new InputFilter();
$filter->add($foo);
$filter->add($bar);

$filter->setData(['foo' => 'xyz']);
$this->assertTrue($filter->isValid(), 'Missing input with fallback value should mark input filter as valid');
$data = $filter->getValues();
$this->assertArrayHasKey('bar', $data);
$this->assertEquals($bar->getFallbackValue(), $data['bar']);
$this->assertArrayNotHasKey('bar', $filter->getValidInput());
$this->assertArrayNotHasKey('bar', $filter->getInvalidInput());
}

/**
* @group 10
*/
public function testEmptyRequiredValueWithFallbackShouldMarkInputValid()
{
$foo = new Input('foo');
$foo->setRequired(true);
$foo->setAllowEmpty(false);

$bar = new Input('bar');
$bar->setRequired(true);
$bar->setFallbackValue('baz');

$filter = new InputFilter();
$filter->add($foo);
$filter->add($bar);

$filter->setData([
'foo' => 'xyz',
'bar' => null,
]);
$this->assertTrue($filter->isValid(), 'Empty input with fallback value should mark input filter as valid');
$data = $filter->getValues();
$this->assertArrayHasKey('bar', $data);
$this->assertEquals($bar->getFallbackValue(), $data['bar']);
$this->assertArrayHasKey('bar', $filter->getValidInput());
$this->assertArrayNotHasKey('bar', $filter->getInvalidInput());
}

/**
* @group 15
*/
Expand Down
Loading