user1191247
user1191247

Reputation: 12973

Zend Framework validation and/or filtering issue

I am having a problem with the filtering and validation of the form below. If the two mobile numbers are entered in national format (07777654321) the form validation fails, but if they are entered in international format (447777654321) it validates. My understanding is that the filters will be applied first so when identical is applied both mobile and mobile_confirm should have been processed with the same set of filters.

So if I enter 07777654321 into both fields it will get filtered to 447777654321 in both fields which should then validate. Where am I going wrong.

I am using ZF 1.11.3.

<?php

class Test_Form_Check extends Zend_Form
{

    public function init()
    {

        $mobile= new Zend_Form_Element_Text( 'mobile' );
        $mobile->addFilter(new Test_Filter_MobileFilter('44'))
                ->addValidator(new Test_Validate_Mobile())
                ->setRequired( true );

        $mobile1= new Zend_Form_Element_Text( 'mobile_confirm' );
        $mobile1->addFilter(new Test_Filter_MobileFilter('44'))
                ->addValidator(new Test_Validate_Mobile())
                ->addValidator('Identical', false, array('token' => 'mobile', 'messages' => 'Mobile numbers do not match.'))
                ->setRequired( true );

        $Add = new Zend_Form_Element_Submit('Add');
        $Add->setLabel('Submit');

        $this->addElement($mobile)
                ->addElement($mobile1)
                ->addElement( $Add );

    }
}


class Test_Validate_Mobile extends Zend_Validate_Abstract
{
    const NOT_DIGITS   = 'notDigits';
    const STRING_EMPTY = 'digitsStringEmpty';
    const INVALID      = 'digitsInvalid';
    const INVALIDPHONE = 'phonenumberinvalid';

    protected static $_filter = null;

    protected $_messageTemplates = array(
        self::NOT_DIGITS   => "'%value%' must contain only digits",
        self::STRING_EMPTY => "'%value%' is an empty string",
        self::INVALID      => "Invalid type given. String, integer or float expected",
        self::INVALIDPHONE => "Invalid number, try with country code",
    );


    public function isValid($value)
    {
        if (!is_string($value) && !is_int($value) && !is_float($value)) {
            $this->_error(self::INVALID);
            return false;
        }

        if (!preg_match('/^(447)[0-9]{9}$/', $value)) {
            $this->_error(self::INVALIDPHONE);
            return false;
        }

        $this->_setValue((string) $value);

        if ('' === $this->_value) {
            $this->_error(self::STRING_EMPTY);
            return false;
        }

        if (null === self::$_filter) {
            require_once 'Zend/Filter/Digits.php';
            self::$_filter = new Zend_Filter_Digits();
        }

        if ($this->_value !== self::$_filter->filter($this->_value)) {
            $this->_error(self::NOT_DIGITS);
            return false;
        }

        return true;
    }
}


class Test_Filter_MobileFilter implements Zend_Filter_Interface
{
    /**
    * Default country code
    *
    * @var string
    */
    protected $_def_country = '44';

    public function __construct($options = null)
    {
        if ($options !== null) {
            if (is_string($options) && is_numeric($options)) {
                $this->_def_country = $options;
            }
            else {
                require_once 'Zend/Filter/Exception.php';
                throw new Zend_Filter_Exception('Options not valid country code');
            }
        }
    }

    public function filter($value)
    {
        if (!empty($value)) {
            $replace = array(' ','+','-','(',')');

            $value = str_replace($replace, '', $value);
            $value = preg_replace('/\A0/', $this->_def_country, $value);

        }
        return $value;
    }

}

I will be very grateful for any help with this. It is driving me round the bend.

Upvotes: 1

Views: 773

Answers (1)

b.b3rn4rd
b.b3rn4rd

Reputation: 8840

I guess problem is with Zend_Validate_Identical validator , it uses unfiltered raw value from $_POST. Just quick fix:

class My_Validate_Identical extends Zend_Validate_Identical
{
    /**
     *
     * @var Zend_Form_Element 
     */
    protected $_element = null;

    public function __construct($token = null)
    {
        if (is_array($token) && array_key_exists('element', $token)) {
            $this->_element = $token['element'];
        }
        parent::__construct($token);
    }
    public function isValid($value, $context = null)
    {
        $context[$this->getToken()] = $this->_element->getValue();
        return parent::isValid($value, $context);
    }    
}

Attaching validator:

$mobile1->addValidator(new My_Validate_Identical(array(
                'token' => 'mobile', 
                'messages' => 'Mobile numbers do not match.',
                'element' => $mobile
                )))

Hope this helps :)

Upvotes: 3

Related Questions