-
-
Save bakura10/e35887640ef00942476c to your computer and use it in GitHub Desktop.
<?php | |
class MyInputFilter extends InputFilter | |
{ | |
public function __construct() | |
{ | |
$this->add(['name' => 'example', 'required' => false]); | |
$this->add(['name' => 'foo', 'required' => false]); | |
$this->add(['name' => 'bar', 'required' => false]); | |
} | |
} | |
$inputFilter = new MyInputFilter(); | |
$inputFilter->setData(['foo' => 'myValue', 'unknown' => 'lolzor']); | |
if ($inputFilter->isValid()) { | |
$values = $inputFilter->getValues(); | |
// Do you expect (1) ['example' => null, 'foo' => 'myValue', 'bar' => null] | |
// OR (2) : ['example' => null, 'foo' => 'myValue', 'bar' => null, 'unknown' => 'lolzor'] | |
// OR (3) : ['foo' => 'myValue'] | |
// OR (4) : ['foo' => 'myValue', 'unknown' => 'lolzor'] | |
} | |
// Currently, ZF2 does (1), I personally expect it to do (3), with getUnknown returning unknown fields |
<?php | |
public function dataProvider() | |
{ | |
return [ | |
// Validate none | |
[ | |
'validation_group' => InputCollection::VALIDATE_NONE, | |
'data' => [], | |
'result_raw_data' => [], | |
'result_filtered_data' => [], | |
'result_unknown_data' => [], | |
'is_valid' => true | |
], | |
// Validate all | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['email' => '[email protected]', 'first_name' => ' Michaël '], | |
'result_raw_data' => ['email' => '[email protected]', 'first_name' => ' Michaël '], | |
'result_filtered_data' => ['email' => '[email protected]', 'first_name' => 'Michaël'], | |
'result_unknown_data' => [], | |
'is_valid' => true | |
], | |
// Validate all with first_name not given | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['email' => '[email protected]'], | |
'result_raw_data' => ['email' => '[email protected]'], | |
'result_filtered_data' => ['email' => '[email protected]'], | |
'result_unknown_data' => [], | |
'is_valid' => true | |
], | |
// Validate all with unknown value | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['email' => '[email protected]', 'unknown' => 'value'], | |
'result_raw_data' => ['email' => '[email protected]'], | |
'result_filtered_data' => ['email' => '[email protected]'], | |
'result_unknown_data' => ['unknown' => 'value'], | |
'is_valid' => true | |
], | |
// Assert fails if required input is not present | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['first_name' => 'Michaël'], | |
'result_raw_data' => ['first_name' => 'Michaël'], | |
'result_filtered_data' => ['first_name' => 'Michaël'], | |
'result_unknown_data' => [], | |
'is_valid' => false | |
], | |
// Validate only one field (with validation group) without unknown fields | |
[ | |
'validation_group' => ['email'], | |
'data' => ['email' => '[email protected]', 'first_name' => 'Michaël'], | |
'result_raw_data' => ['email' => '[email protected]'], | |
'result_filtered_data' => ['email' => '[email protected]'], | |
'result_unknown_data' => [], | |
'is_valid' => true | |
], | |
// Validate only one field with a nested input collection | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['email' => '[email protected]', 'address' => ['city' => 'a']], | |
'result_raw_data' => ['email' => '[email protected]', 'address' => ['city' => 'a']], | |
'result_filtered_data' => ['email' => '[email protected]'], | |
'result_unknown_data' => [], | |
'is_valid' => false | |
], | |
// Validate two fields with a nested input collection | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['email' => '[email protected]', 'address' => ['city' => ' abc ']], | |
'result_raw_data' => ['email' => '[email protected]', 'address' => ['city' => ' abc ']], | |
'result_filtered_data' => ['email' => '[email protected]', 'address' => ['city' => 'abc']], | |
'result_unknown_data' => [], | |
'is_valid' => true | |
], | |
// Assert can have unknown field in nested inputs | |
[ | |
'validation_group' => InputCollection::VALIDATE_ALL, | |
'data' => ['email' => '[email protected]', 'address' => ['unknown' => 'abc']], | |
'result_raw_data' => ['email' => '[email protected]'], | |
'result_filtered_data' => ['email' => '[email protected]'], | |
'result_unknown_data' => ['address' => ['unknown' => 'abc']], | |
'is_valid' => true | |
], | |
// Assert that validation group applies to nested inputs | |
[ | |
'validation_group' => ['address' => ['city']], | |
'data' => ['email' => '[email protected]', 'address' => ['city' => ' abc ']], | |
'result_raw_data' => ['address' => ['city' => ' abc ']], | |
'result_filtered_data' => ['address' => ['city' => 'abc']], | |
'result_unknown_data' => [], | |
'is_valid' => true | |
] | |
]; | |
} | |
/** | |
* @dataProvider dataProvider | |
*/ | |
public function testBehaviour( | |
$validationGroup, | |
array $data, | |
array $resultRawData, | |
array $resultFilteredData, | |
array $resultUnknownData, | |
$isValid | |
) { | |
$inputCollection = new InputCollection(); | |
$inputCollection->setName('user'); | |
// We add one input that is required, one that is optional, and a nested input collection | |
$input1 = new Input(); | |
$input1->setName('email'); | |
$input1->setRequired(true); | |
$input2 = new Input(); | |
$input2->setName('first_name'); | |
$input2->getFilterChain()->attachByName(StringTrim::class); | |
$addressInputCollection = new InputCollection(); | |
$addressInputCollection->setName('address'); | |
$input3 = new Input(); | |
$input3->setName('city'); | |
$input3->getFilterChain()->attachByName(StringTrim::class); | |
$input3->getValidatorChain()->attachByName(StringLength::class, ['min' => 2]); | |
$addressInputCollection->addInput($input3); | |
$inputCollection->addInput($input1); | |
$inputCollection->addInput($input2); | |
$inputCollection->addInput($addressInputCollection); | |
$inputCollection->setValidationGroup($validationGroup); | |
$result = $inputCollection->runAgainst($data); | |
$this->assertEquals($isValid, $result->isValid()); | |
$this->assertEquals($resultRawData, $result->getRawData()); | |
$this->assertEquals($resultFilteredData, $result->getData()); | |
$this->assertEquals($resultUnknownData, $result->getUnknownData()); | |
} |
I have updated this file with a few unit tests that show my expected behavior. Does everyone agree with that?
@juriansluiman > That is a nice trick, actually.
The only thing I wonder about is why you want to return the "unknown" data. Is there a use case for it?
Also, for the scenario "// Validate only one field (with validation group) without unknown fields": you provide a field email
and first_name
. The validation group is set to email
and the unknown fields are null. I have no real scenario for the unkown fields, but I'd rather argue that if you provide such feature, it would also return first_name
in that case.
So: $result->getUnknownData()
will return all data which didn't came through the filter. This is including input filters which are excluded from the collection by its validation group.
first_name is not an unknown field because it is indeed set in the input filter. I have few cases for unknown data but I know that this is something that was asked by a lot of people in ZF and was added to ZF2.1 iirc, so I suppose there is a use case!
So: $result->getUnknownData() will return all data which didn't came through the filter. This is including input filters which are excluded from the collection by its validation group.
That makes sense. What you mean is that, once you set a validation group, everything that DO NOT belong to the validation group (even if it has been set as an input collection element) should be considered like an unknown field?
That makes sense. What you mean is that, once you set a validation group, everything that DO NOT belong to the validation group (even if it has been set as an input collection element) should be considered like an unknown field?
Correct :)
Correct :)
👍
@bakura10 regarding PATCH, with the Restful controller's I usually do this:
And therefore reusing the actual PUT logic from the controller. This has helped me a lot, with only two drawback: the input filter must be injected into the controller (a good thing) but then holds state between the
patch()
andupdate()
call. But well, I didn't consider that much of a waste. Furthermore, it breaks when you send more fields than defined in the input filter. But I guess you could diff it against all input filter elements.