Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zend_Form_Element_File returns false on validation when not required

I have a Zend Form containing one file element amongst others.

    $this->addElement('file', 'image', array(
        'label'         => 'Upload Image:',
        'destination'   => APPLICATION_PATH . '/tmp/',
        'validators'    => array(
            array('count', true, array(
                'min'   => 1,
                'max'   => 1,
                'messages'  => array(
                    Zend_Validate_File_Count::TOO_FEW =>
                        'You must upload an image file',
                    Zend_Validate_File_Count::TOO_MANY =>
                        'You can only upload one image file'))),
            array('extension', true, array(
                'extention' => 'jpg,png,gif',
                'messages'  => array(
                    Zend_Validate_File_Extension::NOT_FOUND =>
                        'The file has an invalid extention (jpg,png,gif only)',
                    Zend_Validate_File_Extension::FALSE_EXTENSION =>
                        'The file has an invalid extention (jpg,png,gif only)'))),
            array('imageSize', true, array(
                'minheight' => self::IMAGEHEIGHT,
                'minwidth'  => self::IMAGEWIDTH,
                'maxheight' => self::IMAGEHEIGHT,
                'maxwidth'  => self::IMAGEWIDTH,
                'messages'  => array(
                    Zend_Validate_File_ImageSize::HEIGHT_TOO_BIG =>
                        'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall',
                    Zend_Validate_File_ImageSize::HEIGHT_TOO_SMALL =>
                        'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall',
                    Zend_Validate_File_ImageSize::WIDTH_TOO_BIG =>
                        'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide',
                    Zend_Validate_File_ImageSize::WIDTH_TOO_SMALL =>
                        'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide',
                    Zend_Validate_File_ImageSize::NOT_DETECTED =>
                        'The image dimensions cannot be detected',
                    Zend_Validate_File_ImageSize::NOT_READABLE =>
                        'The image dimensions cannot be read'))))
    ));

This file element is set to not required in a later piece of code. When I submit the form without a file attached the form validtion returns false, also when I look for the form errors with the getErrors() method no errors are reported. If I submit the form with an attachment everything works fine.

I have been googleing this for sometime but cannot find an answer. I hope that someone can shed some light as to why this is happening, I'm using ZF 1.11.11.

Thanks in advance.

Garry

EDIT

Here are some more code samples as requested.

These are the methods I use to validate the forms. I have marked the code I use as a workaround for the validation bug.

public function formValid(Array $params)
{
    if (is_null($this->_form))
        throw new Zend_Exception('You must first initialize the form');

    $formValid = $this->_validateForm($this->_form, $params);

    // Workaround for bug in validating file elements
    if (!$formValid) {
        if (!$this->_form->getMessages()) {
            $formValid = true;
            $this->_validValues = $this->_form->getValidValues($params);
        }
    }

    if ($formValid) {
        if ($this->_form instanceof Admin_Form_AddDirectSite || 
            $this->_form instanceof Admin_Form_EditDirectSite) {
                if (isset($this->_validValues['replaceImage'])) {
                    return $this->_form->getElement('image')->receive();
                } else {
                    return true;
                }
            } elseif ($this->_form instanceof Admin_Form_PromoteDirectSite) {
                $today = new Zend_Date();
                $expires = new zend_date($this->_validValues['DirectSitesHighlighted']['toDate']);
                if ($expires->isEarlier($today)) {
                    $this->_form->getSubForm('DirectSitesHighlighted')
                                ->getElement('toDate')
                                ->addError('The date must be in the future');
                    return false;
                } else {
                    return true;
                }
            } else {
                return true;
            }
    } else {
        return false;
    }
}

protected function _validateForm(Zend_Form $form, Array $params)
{
    if ($form->isValid($params)) {
        $this->_validValues = $form->getValidValues($params);
        return true;
    } else {
        $this->_validValues = null;
        return false;
    }
}

These are the functions I use to initialize the forms, there are two form classes sharing one abstract class.

public function initAddForm() 
{
    $this->_form = new Admin_Form_AddDirectSite();
    return $this;
}

public function initEditForm() 
{
    $this->_form = new Admin_Form_EditDirectSite();
    return $this;
}

And these are the three form classes.

class Admin_Form_AddDirectSite extends Admin_Form_DirectSites_Abstract
{
    public function init()
    {
        parent::init();

        $this->setAction('/admin/direct-sites/add');

        $this->setDecorators(array(
            array('ViewScript', array('viewScript' => 'forms/addDirectSites.phtml'))
        ));

        $this->getElement('image')->setRequired(true);

        $this->addElement('hidden', 'replaceImage', array(
            'required'      => true,
            'label'         => 'Replace Image:',
            'value'         => 1,
            'filters'       => array('Int'),
        ));
    }
}

class Admin_Form_EditDirectSite extends Admin_Form_DirectSites_Abstract
{
    public function init()
    {
        parent::init();

        $this->setAction('/admin/direct-sites/edit');

        $this->setDecorators(array(
            array('ViewScript', array('viewScript' => 'forms/editDirectSites.phtml'))
        ));

        $this->getElement('image')->setRequired(false);

        $this->addElement('checkbox', 'replaceImage', array(
            'required'      => false,
            'label'         => 'Replace Image:',
            'checked'       => false,
            'attribs'       => array(
                'title'         => 'Click to replace the image file'
            ),
            'filters'       => array('Int'),
            'validators'    => array(
                array('Int', true, array(
                    'messages'  => array(
                        Zend_Validate_Int::NOT_INT =>
                            'You must check to replace the image file'))))
        ));

        $this->addElement('hidden', 'directSiteId', array(
            'required'  => false,
            'vslue'     => null
        ));
    }
}

abstract class Admin_Form_DirectSites_Abstract extends Freedom_Zend_Form
{
    /**
     * Domain prefix http://www.
     * @var integer
     */
    const HTTPWWW = 1;

    /**
     * Domain prefix http://
     * @var integer
     */
    const HTTP = 2;

    /**
     * The image width in pixels
     * @var integer
     */
    const IMAGEWIDTH = 100;

    /**
     * The image height in pixels
     * @var integer
     */
    const IMAGEHEIGHT = 100;

    /**
     * Initialize the form
     * @see Zend_Form::init()
     */
    public function init()
    {
        $domainPrefix = array(
            self::HTTPWWW   => 'http://www.',
            self::HTTP      => 'http;//'
        );

        $genres = Model_Doctrine_GenresTable::getInstance()->getAllKeyPairs();

        $artworkMediums = Model_Doctrine_ArtworkMediumsTable::getInstance()->getAllKeyPairs();

        $this->setName('directSitesForm') // setup registration form
             ->setAttrib('id', 'directSitesForm')
             ->setMethod('post')
             ->setAttrib('class', 'directSitesForm')
             ->setEnctype(Zend_Form::ENCTYPE_MULTIPART);

        $this->addElementPrefixPath('Freedom_Zend', 'Freedom/Zend'); // add element prefix path
        $this->addPrefixPath('Freedom_Zend_Form', 'Freedom/Zend/Form'); // add form prefix path

        $directSitesDescription = new Zend_Form_SubForm();
        $directSitesTitle = new Zend_Form_SubForm();

        $this->addElement('text', 'domainName', array(
            'required'  => true,
            'label'     => 'Domain Name:',
            'attribs'   => array(
                'title'     => 'Please enter the url of the site',
                'size'      => 20,
                'maxlength' => 255
            ),
            'filters'       => array('StringTrim', 'StripTags', 'StripNewlines'),
            'validators'    => array(
                array('NotEmpty', true, array(
                        'messages' => array(
                            Zend_Validate_NotEmpty::IS_EMPTY =>
                                "You must specify the domain name"))),
                array('StringLength', true, array(
                        'min'   => 5,
                        'max' => 255,
                        'messages'  => array(
                            Zend_Validate_StringLength::INVALID =>
                                'Your URL must be between 5 and 255 characters in length',
                            Zend_Validate_StringLength::TOO_LONG =>
                                'Your URL must not contain more than 255 characters',
                            Zend_Validate_StringLength::TOO_SHORT =>
                                'Your URL must contain more than 5 characters'))))
        ));

        $this->addElement('radio', 'websitePrefix', array(
            'required'  => true,
            'label'     => 'Domain Prefix:',
            'attribs'   => array(
                'title'     => 'Please select the URL prefix for the domain name'
            ),
            'multiOptions'  => $domainPrefix,
            'value'     => self::HTTPWWW,
            'filters' => array('int'),
            'validators' => array(
                array('NotEmpty', true, array(
                    'messages' => array(
                        Zend_Validate_NotEmpty::IS_EMPTY =>
                            "You must select your agency's website URL",
                        Zend_Validate_NotEmpty::INVALID =>
                            "You must select your agency's website URL"))),
                array('InArray', true, array(
                    'haystack'  => array_keys($domainPrefix),
                    'messages' => array(
                        Zend_Validate_InArray::NOT_IN_ARRAY =>
                            "You must select your agency's website URL"))))
        ));

        $directSitesTitle->addElement('text', 'title', array(
            'required'  => true,
            'label'     => 'Title:',
            'attribs'   => array(
                'title'     => 'Please enter the name of the site',
                'size'      => 20,
                'maxlength' => 255
            ),
            'filters'       => array('StringTrim', 'StripTags', 'StripNewlines'),
            'validators'    => array(
                array('NotEmpty', true, array(
                        'messages' => array(
                            Zend_Validate_NotEmpty::IS_EMPTY =>
                                "You must specify the sites title"))),
                array('StringLength', true, array(
                        'min'   => 5,
                        'max' => 100,
                        'messages'  => array(
                            Zend_Validate_StringLength::INVALID =>
                                'Your title must be between 5 and 100 characters in length',
                            Zend_Validate_StringLength::TOO_LONG =>
                                'Your title must not contain more than 100 characters',
                            Zend_Validate_StringLength::TOO_SHORT =>
                                'Your title must contain more than 5 characters'))))
        ));

        $directSitesDescription->addElement('text', 'description', array(
            'required'  => true,
            'label'     => 'Description:',
            'attribs'   => array(
                'title'     => 'Please enter the description of the site',
                'size'      => 50,
                'maxlength' => 100
            ),
            'filters'       => array('StringTrim', 'StripTags', 'StripNewlines'),
            'validators'    => array(
                array('NotEmpty', true, array(
                        'messages' => array(
                            Zend_Validate_NotEmpty::IS_EMPTY =>
                                "You must specify the sites description"))),
                array('StringLength', true, array(
                        'min'   => 5,
                        'max' => 100,
                        'messages'  => array(
                            Zend_Validate_StringLength::INVALID =>
                                'Your sites description must be between 5 and 100 characters in length',
                            Zend_Validate_StringLength::TOO_LONG =>
                                'Your sites description must not contain more than 100 characters',
                            Zend_Validate_StringLength::TOO_SHORT =>
                                'Your sites description must contain more than 5 characters'))))
        ));

        $this->addElement('file', 'image', array(
            'label'         => 'Upload Image:',
            'destination'   => APPLICATION_PATH . '/tmp/',
            'validators'    => array(
                array('count', true, array(
                    'min'   => 0,
                    'max'   => 1,
                    'messages'  => array(
                        Zend_Validate_File_Count::TOO_FEW =>
                            'You must upload an image file',
                        Zend_Validate_File_Count::TOO_MANY =>
                            'You can only upload one image file'))),
                array('extension', true, array(
                    'extention' => 'jpg,png,gif',
                    'messages'  => array(
                        Zend_Validate_File_Extension::NOT_FOUND =>
                            'The file has an invalid extention (jpg,png,gif only)',
                        Zend_Validate_File_Extension::FALSE_EXTENSION =>
                            'The file has an invalid extention (jpg,png,gif only)'))),
                array('imageSize', true, array(
                    'minheight' => self::IMAGEHEIGHT,
                    'minwidth'  => self::IMAGEWIDTH,
                    'maxheight' => self::IMAGEHEIGHT,
                    'maxwidth'  => self::IMAGEWIDTH,
                    'messages'  => array(
                        Zend_Validate_File_ImageSize::HEIGHT_TOO_BIG =>
                            'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall',
                        Zend_Validate_File_ImageSize::HEIGHT_TOO_SMALL =>
                            'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall',
                        Zend_Validate_File_ImageSize::WIDTH_TOO_BIG =>
                            'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide',
                        Zend_Validate_File_ImageSize::WIDTH_TOO_SMALL =>
                            'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide',
                        Zend_Validate_File_ImageSize::NOT_DETECTED =>
                            'The image dimensions cannot be detected',
                        Zend_Validate_File_ImageSize::NOT_READABLE =>
                            'The image dimensions cannot be read'))))
        ));

        $this->addElement('multiCheckbox', 'Genres', array(
            'required'  => false,
            'label'     => 'Genres:',
            'attribs'   => array(
                'title'     => 'Please select the sites genres'
            ),
            'multiOptions'  => $genres,
            'filters' => array('int'),
            'validators' => array(
                array('NotEmpty', true, array(
                    'messages' => array(
                        Zend_Validate_NotEmpty::IS_EMPTY =>
                            "You must select the sites genres",
                        Zend_Validate_NotEmpty::INVALID =>
                            "You must select the sites genres"))),
                array('InArray', true, array(
                    'haystack'  => array_keys($genres),
                    'messages' => array(
                        Zend_Validate_InArray::NOT_IN_ARRAY =>
                            "You must select the sites genres"))))
        ));

        $this->addElement('multiCheckbox', 'ArtworkMediums', array(
            'required'  => false,
            'label'     => 'Artwork Mediums:',
            'attribs'   => array(
                'title'     => 'Please select the sites artwork mediums'
            ),
            'multiOptions'  => $artworkMediums,
            'filters' => array('int'),
            'validators' => array(
                array('NotEmpty', true, array(
                    'messages' => array(
                        Zend_Validate_NotEmpty::IS_EMPTY =>
                            "You must select the sites artwork mediums",
                        Zend_Validate_NotEmpty::INVALID =>
                            "You must select the sites artwork mediums"))),
                array('InArray', true, array(
                    'haystack'  => array_keys($artworkMediums),
                    'messages' => array(
                        Zend_Validate_InArray::NOT_IN_ARRAY =>
                            "You must select the sites artwork mediums"))))
        ));

        $this->addElement('submit', 'save', array(
            'label' => 'Save',
            'attribs'   => array(
                'title' => 'Save')
        ));

        $this->addSubForm($directSitesDescription, 'DirectSitesDescription')
             ->addSubForm($directSitesTitle, 'DirectSitesTitle');
    }
}
like image 697
Garry Avatar asked Nov 05 '22 05:11

Garry


2 Answers

All I can see is that your 'count' validator looks a little wonky, it looks like you are requiring a minimum of 1 file at all times. As to why there is no error message, I have no idea.
Might try setting 'min' => 0

array('count', true, array(
                'min'   => 1,
                'max'   => 1,
                'messages'  => array(
                    Zend_Validate_File_Count::TOO_FEW =>
                        'You must upload an image file',
                    Zend_Validate_File_Count::TOO_MANY =>
                        'You can only upload one image file'))),

Below is the API for Zend_Validate_File_Count constructor, see whole API at ZF 1.11 API

__construct( integer|array|\Zend_Config $options ) : void Sets validator options

Min limits the file count, when used with max=null it is the maximum file count It also accepts an array with the keys 'min' and 'max' If $options is a integer, it will be used as maximum file count As Array is accepts the following keys: 'min': Minimum filecount 'max': Maximum filecount Parameters Name Type Description $options integer|array|\Zend_Config Options for the adapter

like image 103
RockyFord Avatar answered Nov 10 '22 21:11

RockyFord


Double check to make sure that

enctype='multipart/form-data'

is included in the html form element. I spent two hours with the same issue. Turns out that was my problem.

like image 42
liz Avatar answered Nov 10 '22 21:11

liz