ZF-8038: Zend_Filter_LocalizedToNormalized performs in a non-intuitive way

Description

Zend_Filter_LocalizedToNormalized does not behave in an intuitive manner.

Example 1 When passing in a value such as 23,555.0 the value returned is 23555.0 which is acceptable.

Expected

Commas are stripped out

Example 2 When passing in a malformed numeric value from a form such as 23.05.1 the class returns a date.

Expected:

i) Return value should be 23.05 with extra characters removed.

ii) Alternatively the class should be configurable to return a value with all but the first decimal point removed. 23.051

Conclusion

The fact that the class returns unexpected data makes it unsafe to use when validating Numeric or Date data.

The class should either be removed from the framework or redesigned to remove the inherently confused design issues.

Comments

When you need to validate numbers or dates then use Validators. Filters are not Validators, and they should not be used with unvalidated content.

When you give a localized value to this filter then it will be normalized. And when the value is detected as localized date, then you will get a normalized date in return.

Use Zend_Validate_Float/Int/Digits to get sure if the value is a number.

The response misses the point completely.

No attempt was made to use the class as a validator - it is supposed to be a Filter.

The Zend Filters make modifications to the data and the modifications occur Before Validation.

If a value is normalized it should be passed in as a number and returned as a number. This class looks at the format of the data passed in and then makes some assumptions based on that structure.

This means that the user will receive an unexpected response when passing in numeric data from a form that has to be filtered.

The data is not being normalised it is being interpreted, modified and cast to a different form. This is wrong and it is a bug.

"Filters are not Validators, and they should not be used with unvalidated content."

Actually, they definitely should be used on unvalidated content:

From the ZF Docs site (http://framework.zend.com/manual/en/…): It's often useful and/or necessary to perform some normalization on input prior to validation ... [and] run your validations on what remains to ensure the submission is valid. ... These operations may be performed using Zend_Filter.

One of the major uses of Zend_Filter is to filter-out unwanted stuff, like commas in numbers, before validation. Zend_Validate_Digits will fail if there's a comma in the number, which is why one should run the number through a Zend_Filter first.

There's no way a filter should return a Zend_Date, or any other complex object - it should return what it's given with some stuff stripped-out, that's all.

{quote} One of the major uses of Zend_Filter is to filter-out unwanted stuff, like commas in numbers, before validation. {quote}

Exactly this is done. But filters do not only "Filter out"... they can also be used to filter content in a way where you apply somthing and it is changed according to specified rules. And this is done within Zend_Filter_LocalizedToNormalized. An algorithm is processed which changes the content.

See for example the Compress filters... nothing is filtered out, but a defined algorithm is processed on the content.

Btw: Zend_Filter does not return Zend_Date or any objects. Please inform yourself before throwing out conclusions on issues which other persons have filled.

And regarding false input and validation.

When the above noted false input is filtered it will return a normalized date because of the 2 "." seperators. When you would process a validation on Digits or Int or Float then the value would not pass validation.

So even if validation is done afterwards, all would work as expected, because the false input will not pass as number. It is returned as normalized date and not as normalized number... so the behaviour is correct when validation would have been applied.

Zend_Filter does not return Zend_Date or any objects

No it returns an array which is just as bad. The input data is a string from a form which is then 'interpreted' and depending on the results of this it the returns either a number or an array containing date information.

Case

This is an input for a numeric field We'll ignore the fact that 'precision => 2' effectively hints that the value will be a number.

$oColourInput = new Zend_Form_Element_Text($sColourRateName, array( 'decorators' => $this->aDecoratorsElementInlineNoLabel, 'filters' => array( new Zend_Filter_LocalizedToNormalized(array('precision' => 2)) ), 'validators' => array(new Zend_Validate_Float()) ) );

When the above noted false input is filtered it will return a normalized date because of the 2 "." seperators. When you would process a validation on Digits or Int or Float then the value would not pass validation.

Effectively you are suggesting a workaround here because validation will fail because the Digits/Int/Float classes will fail when passed an array.

In the long run it would be far better to have separate classes for normalising inputs from number or date fields. It is extremely disconcerting to have input of one type 'automagically' converted to another.

Re. Please inform yourself before throwing out conclusions on issues which other persons have filled. Personally I welcome comments from anyone with programming knowhow and experience