Skip to content

Instantly share code, notes, and snippets.

@bakura10
Last active August 29, 2015 14:01
Show Gist options
  • Save bakura10/e35887640ef00942476c to your computer and use it in GitHub Desktop.
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' => 'test@example.com', 'first_name' => ' Michaël '],
'result_raw_data' => ['email' => 'test@example.com', 'first_name' => ' Michaël '],
'result_filtered_data' => ['email' => 'test@example.com', 'first_name' => 'Michaël'],
'result_unknown_data' => [],
'is_valid' => true
],
// Validate all with first_name not given
[
'validation_group' => InputCollection::VALIDATE_ALL,
'data' => ['email' => 'test@example.com'],
'result_raw_data' => ['email' => 'test@example.com'],
'result_filtered_data' => ['email' => 'test@example.com'],
'result_unknown_data' => [],
'is_valid' => true
],
// Validate all with unknown value
[
'validation_group' => InputCollection::VALIDATE_ALL,
'data' => ['email' => 'test@example.com', 'unknown' => 'value'],
'result_raw_data' => ['email' => 'test@example.com'],
'result_filtered_data' => ['email' => 'test@example.com'],
'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' => 'test@example.com', 'first_name' => 'Michaël'],
'result_raw_data' => ['email' => 'test@example.com'],
'result_filtered_data' => ['email' => 'test@example.com'],
'result_unknown_data' => [],
'is_valid' => true
],
// Validate only one field with a nested input collection
[
'validation_group' => InputCollection::VALIDATE_ALL,
'data' => ['email' => 'test@example.com', 'address' => ['city' => 'a']],
'result_raw_data' => ['email' => 'test@example.com', 'address' => ['city' => 'a']],
'result_filtered_data' => ['email' => 'test@example.com'],
'result_unknown_data' => [],
'is_valid' => false
],
// Validate two fields with a nested input collection
[
'validation_group' => InputCollection::VALIDATE_ALL,
'data' => ['email' => 'test@example.com', 'address' => ['city' => ' abc ']],
'result_raw_data' => ['email' => 'test@example.com', 'address' => ['city' => ' abc ']],
'result_filtered_data' => ['email' => 'test@example.com', 'address' => ['city' => 'abc']],
'result_unknown_data' => [],
'is_valid' => true
],
// Assert can have unknown field in nested inputs
[
'validation_group' => InputCollection::VALIDATE_ALL,
'data' => ['email' => 'test@example.com', 'address' => ['unknown' => 'abc']],
'result_raw_data' => ['email' => 'test@example.com'],
'result_filtered_data' => ['email' => 'test@example.com'],
'result_unknown_data' => ['address' => ['unknown' => 'abc']],
'is_valid' => true
],
// Assert that validation group applies to nested inputs
[
'validation_group' => ['address' => ['city']],
'data' => ['email' => 'test@example.com', '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());
}
@juriansluiman
Copy link

@bakura10 regarding PATCH, with the Restful controller's I usually do this:

public function patch($id, $data)
{
    $group  = array_keys($data);
    $filter = $this->getInputFilter();
    $filter->setValidationGroup($group);

    return $this->update($id, $data);
}

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() and update() 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.

@bakura10
Copy link
Author

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.

@juriansluiman
Copy link

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.

@bakura10
Copy link
Author

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?

@juriansluiman
Copy link

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 :)

@texdc
Copy link

texdc commented May 27, 2014

Correct :)

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment