zendframework / zend-inputfilter

InputFilter component from Zend Framework
BSD 3-Clause "New" or "Revised" License
64 stars 50 forks source link

Zend\Filter\FilterChain::$filters get replicated if same input filter instance is used to filter an array of data #80

Closed mesaugat closed 7 years ago

mesaugat commented 8 years ago

Reference zendframework/zf2#7645

Same filters are being applied to the data multiple times, if same InputFilter instance is used to validate/filter multiple data (array).

For instance, the data is an array like this:

$emails = [
    [
        'email' => 'firstemail@sdfs.com',
        'id' => ' '
    ],
    [
        'email' => 'secondemail@sdfs.com',
        'id' => ' '
    ],
    [
        'email' => 'thirdemail@sdfs.com',
        'id' => ' '
    ],
];

The EmailFilter used is:

class EmailFilter extends AbstractFilter
{

    public function init()
    {

        $this->add([
            'name' => 'email',
            'required' => true,
            'filters' => [
                ['name' => 'ToNull'],
                ['name' => 'StripTags'],
                ['name' => 'StringTrim'],
            ],
            'validators' => [
                [
                    'name' => 'EmailAddress',
                    'options' => [
                        'encoding' => 'UTF-8'
                    ]
                ],
                [
                    'name' => 'NotEmpty'
                ],
            ]
        ]);

        /* id */
        $this->add([
            'name' => 'id',
            'required' => false,
            'filters' => [
                ['name' => 'StripTags'],
                ['name' => 'StringTrim'],
            ],
            'validators' => [
                [
                    'name' => 'IsInt'
                ]
            ]
        ]);
    }

So, now I'm trying to validate each of the item of the array using the EmailFilter:

$filtered = [];
foreach ($emails as $email) {
    $filter->setData($email);
    if (!$this->isValid()) {
        // failed validation
    } else {
        $filtered[] = $filter->getValues();
    }
}

Running this code will replicate the value of FilterChain::$filters for each of these iteration.

For the first iteration, the filters applied to data i.e. returned by FilterChain->getFilters() would be:

"input: email"
"2 => Zend\Filter\ToNull"
"1 => Zend\Filter\StripTags"
"0 => Zend\Filter\StringTrim"

"input: id"
"1 => Zend\Filter\StripTags"
"0 => Zend\Filter\StringTrim"

In the second iteration, you can see the same filters are being applied for both of the inputs: email and id 2 times:

"input: email"
"5 => Zend\Filter\ToNull"
"4 => Zend\Filter\StripTags"
"3 => Zend\Filter\StringTrim"
"2 => Zend\Filter\ToNull"
"1 => Zend\Filter\StripTags"
"0 => Zend\Filter\StringTrim"

"input: id"
"3 => Zend\Filter\StripTags"
"2 => Zend\Filter\StringTrim"
"1 => Zend\Filter\StripTags"
"0 => Zend\Filter\StringTrim"

In the third iteration, the filters are being applied to the data 3 times:

"input: email"
"8 => Zend\Filter\ToNull"
"7 => Zend\Filter\StripTags"
"6 => Zend\Filter\StringTrim"
"5 => Zend\Filter\ToNull"
"4 => Zend\Filter\StripTags"
"3 => Zend\Filter\StringTrim"
"2 => Zend\Filter\ToNull"
"1 => Zend\Filter\StripTags"
"0 => Zend\Filter\StringTrim"

"input: id"
"5 => Zend\Filter\StripTags"
"4 => Zend\Filter\StringTrim"
"3 => Zend\Filter\StripTags"
"2 => Zend\Filter\StringTrim"
"1 => Zend\Filter\StripTags"
"0 => Zend\Filter\StringTrim"

Is there anything wrong here or is this an issue with the filters?

mesaugat commented 8 years ago

anyone ?? @weierophinney @Maks3w @samsonasik

Maks3w commented 8 years ago

Since this should be fixed once the component is refactored as stateless classes I prefer don't expend time in research the source of this behavior.

However if you or any other find how to fix it I'll merge the propsed fix early.