Issues

ZF-11142: Filter Input throws wrong not empty message error when validating

Description

I couldn't find any previous bugs like this, so hopefully it's not a duplicate. The problem is that, if you have two validators where the first uses NotEmpty and the second one doesn't, it throws the NotEmpty error of the first.

Here's an example. Suppose you have these validators:

 
$validators = array(
    'field1'    => array(
            'NotEmpty', 'Float',
            'presence'  => 'required',
            'messages'  => array(
                'Field1 is empty',
                array(
                    Zend_Validate_Float::NOT_FLOAT => "Field1 must be a number."
                )
            )
        ),
    'field2'    => array(
            'presence' => 'required'
        )
);

Your input to this is a valid float for field1 and an empty string for field2. You run it through Zend_Filter_Input, and it doesn't validate. If you get the messages for field2, it'll return: [field1] => Array ( [isEmpty] => Field1 is empty. ) It also seems to ignore any defaults set in an $options for Zend_Filter_Input.

FWIW, my guess is the issue lies in Zend/Filter/Input.php::878-879.

Comments

Bart, just to clarify: the problem isn't in the NotEmpty validator - it's in the one following it.

Thanks for watching! I realize the problem is in the combination. However, when I put together a UnitTest to verify the bug, I use a very simple form with two fields and a NotEmpty validator on the first element. Nothing else, just to isolate the problem you described.

To my surprise, the form validates regardless of the values passed into it. So I now have a problem: is that a bug or something I am doing wrong in the test. In any case, it is obviously not the best way to test, because it involves a form, which does not give us the desired isolation level for this test.

Then I also wondered what Zend_Filter_Input actually does in this context? Are you using the validators to configure the input filter? You probably do, so I will have to narrow my test function around this scenario. It is also something I did not do before, so my next step will be figuring out the desired behavior with validators that do work.

I created a unit test for this issue that should reproduce it, but it passes. So I will resolve this as 'not a bug'.

It did not look into the default options being ignored. There are also quite a few other 'issues' I encountered during testing that I would like to investigate further.

Here is my unit test:


/**
 * @group ZF-11142
 */
public function testTwoValidatorsInChainShowCorrectError()
{
    require_once 'Zend/Validate/NotEmpty.php';
    require_once 'Zend/Validate/Float.php';
    $validators = array(
        'field1'    => array(
                'NotEmpty', 'Float',
                'presence'  => 'required',
                'messages'  => array(
                    'Field1 is empty',
                    array(
                        Zend_Validate_Float::NOT_FLOAT => 
                        "Field1 must be a number."
                    )
                )
            ),
        'field2'    => array(
                'presence' => 'required'
            )
    );
    
    $data = array('field1' => 0.0, 'field2' => 'text');
    $input = new Zend_Filter_Input(null, $validators, $data);
    $input->hasValid();
    $messages = $input->getMessages();
    $this->assertSame(  'Field1 is empty', 
                        $messages['field1'][Zend_Validate_NotEmpty::IS_EMPTY], 
                        'custom message not shown');
    $this->assertSame(0, count($messages['field2']));
}

resolved as not an issue

I read more carefully in the bug description (again) and I added a second test that actually confirms the bug. Sorry for the confusion.

Heh, that's alright. Sorry I didn't respond to your earlier question; things got really busy. Anyway, let me know how it turns out. Thanks again for relooking at this.

Finally, I confirmed and fixed this one. It is too late at night now to create a patch, I will try to supply one tomorrow.

I also found a complete section of code, with the "$unifiedMessages" that I could disable without getting any failures in the UnitTests. So wether this is undertested functionality, or it is completely pointless code. Maybe Ralph can look at my comments in Zend_Filter_Input, once I have provided the patch and the UnitTest.

The key to solving this problem was in the suggested lines of code. The default Not empty message must be preserved and restored before re-entering the loop of $_validationRules. Otherwise, the not empty message of any given NotEmpty validator will persist in any required field that comes after it.

Workaround If for now, anyone wants a workaround: provide your NotEmpty validators as the last ones in the chain and you will not have a problem.

Added a patch for the unit test for Zend_Filter_Input that add a test case that proves this bug and a patch that fixes the bug.

I the fixing patch I chose to preserve the default not empty message in a variable and restore it at the end of each iteration over the validation rules. Other approaches may be possible, but this works.

Changed from bug to patch.

Assigned it back to Ralph. Ralph, could you try the patches and review them? I can commit them, but I read on the wiki that the component owner should commit.

I will commit them if you are simply to busy in about a week or so...

This issue seems to be a duplicate or at least related to ZF-9289

Fix is in svn now

Thanks for fixing Reopening for integration into ZF2

Fixed for ZF2 with GH-267