ZF-9679: Method isValid() carries validated Values to SubForms

Description

I have a Zend Dojo Form named test including an element namend id.

This form also has a subform named subform. Latter uses array notation. (Note: using the method setIsArray(true) will not affect the issue!)

In this subform I have an element named id too. It is a MultiCheckbox. The options include the keys 1 and 2 (NOT 3!).

Actions: - Get the id element from the base form test. Set its value to 3. - Don't choose any option on the id element in the subform subform. - Submit Form.

Expected behaviours: - The id element from the base form test is set to 3. - The id element from the subform subform is validated true. - Form is valid!

Actual behaviour: - The id element from the base form test is set to 3. - The id element from the subform subform is ALSO SET TO 3. Since this option does not exist

it validates false. - Form is invalid!

Debugging:

The id element from the base form test: The dump on the element on line 46 shows the correct element. The other id element is never shown. Since the value is set correctely everything seems to work fine here.

Form values: Dumping the form values in line 58 shows that the setValue(3) Method has also addresses the value to the wrong id element in the subform.

Conclusion: There seems to be a problem with the set methods on elements in a subform that share the same name as in the base form or maybe even other subforms.

Further problematics: If the original id element was set to a value that IS AN OPTION of the MultiCheckbox the form would have been valid - even if NO OPTION was checked.

Note: Checking an option will override the value 3 and the form will be correct.

The Code:


<?php
class Issues_MultiCheckboxController extends Zend_Controller_Action
{
    public function init()
    {
        $form = new Zend_Dojo_Form();
        $form->setName('test')
             ->setAction('/issues/multi-checkbox/save/')
             ->setMethod(Zend_Form::METHOD_POST);

        /**
         * Create subform with an element named `id` too - but in an array named `subform`
         */
        $subForm = new Zend_Dojo_Form_SubForm();
        $subForm->setIsArray(true);

        $fooElement = new Zend_Form_Element_MultiCheckbox('id');
        $fooElement->setLabel('Allowed options: 1, 2');
        $fooElement->setMultiOptions(array(
            '1' => 'yes',
            '2' => 'no'
        ));
        #$fooElement->setRequired(true);
        $subForm->addElement($fooElement);

        $form->addSubForm($subForm, 'subform');

        /**
         * Create primary element named `id` too - its value will be set afterwards to 3
         */
        $barElement = new Zend_Form_Element_Hidden('id');
        $barElement->setDecorators(array('ViewHelper'));
        $form->addElement($barElement);

        $sendElement = new Zend_Dojo_Form_Element_SubmitButton('send');
        $sendElement->setLabel('Send');
        $sendElement->setIgnore(true);
        $form->addElement($sendElement);

        $this->view->form = $form;
    }

    public function editAction()
    {
        $barElement = $this->view->form->getElement('id');
        Zend_Debug::dump($barElement);
        $barElement->setValue(3);
    }

    public function saveAction()
    {
        if (!$this->view->form->isValid($this->getRequest()->getPost())) {
            echo "Form not valid";
            $this->render('edit');
        }

        $values = $this->view->form->getValues(true);
        Zend_Debug::dump($values);
    }
}

Correctly generated HTML:


Allowed options: 1, 2 yes
no
 

Comments

This patch fixes the Issue, Unit Test included


Index: tests/Zend/Form/FormTest.php
===================================================================
--- tests/Zend/Form/FormTest.php    (Revision 21858)
+++ tests/Zend/Form/FormTest.php    (Arbeitskopie)
@@ -1184,6 +1184,22 @@
         $this->assertTrue($this->form->isValid($data));
     }
 
+    /**
+     * @group ZF-9679
+     */
+    public function testIsValidDiscardsValidatedValues()
+    {
+        $this->form->addElement('text', 'foo');
+        $this->form->addSubForm(new Zend_Form_SubForm(), 'bar')
+                   ->bar->addElement('text', 'foo')
+                        ->foo->setAllowEmpty(true)
+                             ->addValidator('Identical',
+                                            true,
+                                            '');
+
+        $this->assertTrue($this->form->isValid(array('foo' => 'foo Value')));
+    }
+
     // Sub forms
 
     public function testCanAddAndRetrieveSingleSubForm()
Index: library/Zend/Form.php
===================================================================
--- library/Zend/Form.php   (Revision 21858)
+++ library/Zend/Form.php   (Arbeitskopie)
@@ -2057,6 +2057,7 @@
                 $valid = $element->isValid(null, $data) && $valid;
             } else {
                 $valid = $element->isValid($data[$key], $data) && $valid;
+                unset($data[$key]);
             }
         }
         foreach ($this->getSubForms() as $key => $form) {

This is the similar to ZF-9666

This Issue duplicates as of now the Issue ZF-9607, which also has given a patch with Unit Tests.