Issues

ZF-6708: Zend_Filter_Input skips ALLOW_EMPTY metacommand processing if any validator is applied to the field

Description

Zend_Filter_Input skips ALLOW_EMPTY metacommand processing if any validator is applied to the field:


/**
 * @param array $validatorRule
 * @return void
 */
protected function _validateRule(array $validatorRule)
{
    ....
    /**
     * Evaluate the inputs against the validator chain.
     */
    if (count((array) $validatorRule[self::FIELDS]) > 1) {
        if (!$validatorRule[self::VALIDATOR_CHAIN]->isValid($data)) {
            $this->_invalidMessages[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getMessages();
            $this->_invalidErrors[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getErrors();
            return;
        }
    ....

foreach ($field as $value) {
    if (empty($value)) {
        if ($validatorRule[self::ALLOW_EMPTY] == true) {
            continue;
        }
        if ($validatorRule[self::VALIDATOR_CHAIN_COUNT] == 0) {
            $notEmptyValidator = $this->_getValidator('NotEmpty');
            $notEmptyValidator->setMessage($this->_getNotEmptyMessage($validatorRule[self::RULE], $fieldKey));
            $validatorRule[self::VALIDATOR_CHAIN]->addValidator($notEmptyValidator);
        }
    }

Comments

That was probably done to avoid 'empty value' messages duplication since these messages may come from Validators as well as from Zend_Filter_Input::ALLOW_EMPTY metacommand.

There are two options: * Zend_Filter_Input should interact with Validators in terms of messages semantics and skip their 'empty string' messages. * Throw all messages. So user will be responsibile to turn on Zend_Filter_Input::ALLOW_EMPTY (which is off by default) for specified field.

Right behavior is to skip any validation and throw NOT_EMPTY_MESSAGE if empty value is not allowed, but present.

Fixed

I think this may have introduced a backwards compatibility break. Scenario:

 
$validation = array(
  'offset' => array (
     'digits',
     'presence' => 'required'
  )
)

$params = new Zend_Filter_Input(null, $validation, $this->_getAllParams());

Prior to this change, integer values of zero would correctly pass. After this change a zero value results in an empty field error.

Behavior now fixed in trunk and 1.9 release branch; integer 0 is now considered non-empty by the NotEmpty validator.

This fix with the NotEmpty validator has caused me nothing but trouble as it has broken a number of my forms. I used the fact that 0 in PHP is considered empty to validate lists where element 0 is a title thus not required.

I feel that the NotEmpty validator should behave in exactly the same way as the php function empty() with regards to integer 0. For the time being I have extended the notEmpty validator to disallow integer 0.

Should we fix this or implement another validator to cover such situations?