ZF-4780: Form_Element_File->addValidator('Extension', true, 'txt') doesn't work

Description


$subForm->createElement('file', 'txt')
->setDestination($options['tmp'])
->addFilter('Rename', $options['tmp'] . '/' . md5(microtime(true)))
->setRequired(true)
->addValidator('Count', false, 1) // ensure only 1 file
->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
//->addValidator('FilesSize', true, '1MB')
->addValidator('Extension', true, 'txt'), // only JPEG, PNG, and GIFs

Every upload has error ($form->getErrors('txt')) like this: "The file 'readme.txt' was not found"

'FilesSize' Validator seems to doesn't work too :P

If I uncomment above validator, I've got: * One or more files can not be read * The file 'readme.txt' was not found

Why I've got 2 errors, while I've true in $breakChainOnFailure? Why I've errros? :)

Comments

Please do not double enter issues.

Please try out trunk r12267 and not 1.7pre when you have issues. There has been much changed in the last 4 weeks.

As I said in other issue, I've using newest trunk. Sorry for mistake in bug description.

So which does not work... the header declares Extension does not work. But in your description you declare that FilesSize valdiator does not work as also in your code example.

Which validator does not work ? Please give the $_FILES array after submittion.

Related to breakchain... it does only break the chain for the single file element, but not for other elements. So when you validate two elements by calling $form->isValid() you will get one error for each element.

And please give the code you use afterwards for validation and retrievment of the files.

Doesn't work 'FilesSize' and 'Extension' too. {quote} Related to breakchain... it does only break the chain for the single file element, but not for other elements. So when you validate two elements by calling $form->isValid() you will get one error for each element. {quote} This is for one element... {quote} * One or more files can not be read * The file 'readme.txt' was not found {quote} validation code, only:


$postValues = $this->getRequest()->getPost();
if (!empty($postValues)) {
              // some commented code here
    if ($form->isValid($postValues)) {
                  // some commented code here
              }
              // some commented code here
}

Dumps after validation code $_FILES:


array(2) {
  ["file1"]=>
  array(5) {
    ["name"]=>
    string(10) "movies.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\php76A2.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(303)
  }
  ["file2"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\php76A3.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
}

form->getErrors()


array(4) {
  ["file1"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["file2"]=>
  array(0) {
  }
  ["submit"]=>
  array(0) {
  }
}

$form->getValues()


array(4) {
  ["file1"]=>
  NULL
  ["file2"]=>
  string(32) "b55377db56f87f64bf6d6f68962eed63"
  ["submit"]=>
  string(5) "Submit"
}

There is something wrong...

Your first code creates a file element named "txt". But your $_FILES array declares that the elements are named "file1" and "file2".

This does not match... eighter the first code you gave is wrong, or the $_FILES array is not from the above code.

Please give the correct code and $_FILES array for investigation.

Huh, what difference? I've changed form element names... Full code, perfect simply:


public function indexAction()
    {
        $form = new Zend_Form();
        $form
            ->setAction('/admin/')
            ->setMethod(Zend_Form::METHOD_POST)
            ->setAttrib('enctype', 'multipart/form-data')
            ->addElements(array(
                $form->createElement('file', 'txt')
                    ->setDestination('../tmp')
                    ->addFilter('Rename', '../tmp/' . md5(microtime(true)))
                    ->setRequired(true)
                    ->addValidator('Count', false, 1) // ensure only 1 file
                    ->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
                    ->addValidator('FilesSize', true, '10MB')
                    ->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
                $form->createElement('submit', 'submit')
        ));

        $postValues = $this->getRequest()->getPost();
        if (!empty($postValues) && $form->isValid($postValues)) {
        }
        var_dump($_FILES, $form->getErrors(), $form->getValues());
        $this->view->form = $form;
    }

output of var_dump:


array(1) {
  ["txt"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpA427.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
}
array(2) {
  ["txt"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["submit"]=>
  array(0) {
  }
}
array(2) {
  ["txt"]=>
  NULL
  ["submit"]=>
  string(6) "submit"
}

For example the difference that in your code you only declare one single file element and in your returned $_FILES array there are 2 file elements ?

So there is one problem with your code...

You can not getPost() and then validate the elements when there has nothing be posted. According to manual you have previously to check with isPost().

This has nothing to do with the file element but with generic form handling. I am no forms expert as this is not my component but even I can say that validation on empty elements will ALWAYS FAIL.

But it doesn't matter. Additionaly I've got Notice, when I trying to get $form->getValues(); in my form (see code below) without submit data (just GET).


Notice: Undefined index: name in C:\Program Files\wamp\www\public_html\karaoke\library\Zend\File\Transfer\Adapter\Abstract.php on line 1224

I've form, deeply inserted in my application and I should copy you half of my files. So to simpliest this, I change some of fields to copy you point. Here you are 2 files, but bug is same, and there isn't difference, that you add 1, 2 or 50 files.


    public function indexAction()
    {
        $form = new Zend_Form();
        $form
            ->setAction('/admin/')
            ->setMethod(Zend_Form::METHOD_POST)
            ->setAttrib('enctype', 'multipart/form-data')
            ->addElements(array(
                $form->createElement('file', 'txt')
                    ->setDestination('../tmp')
                    ->addFilter('Rename', '../tmp/' . md5(microtime(true)))
                    ->setRequired(true)
                    ->addValidator('Count', false, 1) // ensure only 1 file
                    ->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
                    ->addValidator('FilesSize', true, '10MB')
                    ->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
                    $form->createElement('file', 'doc')
                        ->setLabel('Plik kar')
                        ->setDestination('../tmp')
                        ->addFilter('Rename', '../tmp/' . md5(microtime(true)))
                        ->setRequired(true)
                        ->addValidator('Count', false, 1),
                $form->createElement('submit', 'submit')
        ));

        $postValues = $this->getRequest()->getPost();
        if (!empty($postValues) && $form->isValid($postValues)) {
        }
        var_dump($_FILES, $form->getErrors(), $form->getValues());
        $this->view->form = $form;
    }

array(2) {
  ["txt"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpAFBE.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
  ["doc"]=>
  array(5) {
    ["name"]=>
    string(13) "formularz.doc"
    ["type"]=>
    string(18) "application/msword"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpAFBF.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(64512)
  }
}
array(3) {
  ["txt"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["doc"]=>
  array(0) {
  }
  ["submit"]=>
  array(0) {
  }
}
array(3) {
  ["txt"]=>
  NULL
  ["doc"]=>
  string(32) "83b62560437c8b21f1614892f1a027af"
  ["submit"]=>
  string(6) "submit"
}

{quote}You can not getPost() and then validate the elements when there has nothing be posted. According to manual you have previously to check with isPost().{quote} I don't understand. you mean


$postValues = $this->getRequest()->getPost();
        if (!empty($postValues) && $form->isValid($postValues)) {
        }

as what?


if ($this->getRequest()->isPost()) {
        if ($form->isValid($this->getRequest()->getPost())) {
        }
}

? Is it not the same?

When there were no difference I would not have asked... Still you can not validating non existing input... this will always fail as I already wrote.

``` empty($postValues) - ok, this could be not the same as $this->getRequest()->isPost(), but in this example is.

And, as you know, if first element in tuple, ie. a & b is false, so php leave it (see Boolean algebra), even NOT check second element. I can't find differences, or I'm blind. Could you tell me, where it is?

PS Code above doesn't work too. It has same dump output as main.

<?php echo $form->render(new Zend_View());?>

It works both with newest trunk.

Fixed within trunk >r12272

Changing issues in preparation for the 1.7.0 release.