Issues

ZF-9407: Zend_Form::getValidValues() does not respect ElementsBelongTo

Description

Zend_Form getValidValues is not aware of elementsBelongTo and therefor does not return the values from Elements which are appended to a SubForm which has set elementsBelongTo.

This patch is a combination of ZF-9348 (!$form->isArray()), ZF-9361 (setDefaults() with ElementsBelongTo), and the working getValues() method, where i copied the _attachToArray() method from

This patch fixes the issue, Unit Test included


Index: tests/Zend/Form/FormTest.php
===================================================================
--- tests/Zend/Form/FormTest.php        (Revision 21667)
+++ tests/Zend/Form/FormTest.php        (Arbeitskopie)
@@ -1473,7 +1473,26 @@
         $this->assertTrue($this->form->isValid($data));
     }
 
+    public function testGetValidValuesWithElementsBelongTo()
+    {
+        $this->form->addSubForm(new Zend_Form_SubForm(), 'foo')
+                   ->foo->setElementsBelongTo('foo[foo]')
+                        ->addSubForm(new Zend_Form_SubForm(), 'foo')
+                        ->foo->setIsArray(false)
+                             ->addElement('text', 'foo')
+                             ->foo->addValidator('Identical',
+                                                 false,
+                                                 array('foo Value'));
 
+        $foo = array('foo' =>
+                     array('foo' =>
+                           array('foo' =>
+                                 array('foo' => 'foo Value'))));
+
+        $this->assertSame($this->form->getValidValues($foo), $foo);
+    }
+
+
     // Display groups
 
     public function testCanAddAndRetrieveSingleDisplayGroups()
Index: library/Zend/Form.php
===================================================================
--- library/Zend/Form.php       (Revision 21667)
+++ library/Zend/Form.php       (Arbeitskopie)
@@ -1323,10 +1323,14 @@
      * values to persist them.
      *
      * @param  array $data
+     * @param  bool $suppressArrayNotation
      * @return array
      */
-    public function getValidValues($data)
+    public function getValidValues($data, $suppressArrayNotation = false)
     {
+        if ($this->isArray()) {
+            $data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
+        }
         $values = array();
         foreach ($this->getElements() as $key => $element) {
             if (isset($data[$key])) {
@@ -1336,10 +1340,16 @@
             }
         }
         foreach ($this->getSubForms() as $key => $form) {
-            if (isset($data[$key])) {
+            if (isset($data[$key]) && !$form->isArray()) {
                 $values[$key] = $form->getValidValues($data[$key]);
+            } else {
+                $fValues = $this->_attachToArray($form->getValidValues($data, true), $form->getElementsBelongTo());
+                $values = array_merge($values, $fValues);
             }
         }
+        if (!$suppressArrayNotation && $this->isArray()) {
+            $values = $this->_attachToArray($values, $this->getElementsBelongTo());
+        }
 
         return $values;
     }

Comments

Updated the Test, included checks against !$form->isArray() and equal-Name-Chain like learned in ZF-9348.

Extending the TestCase a bit revealed another problem, namely that getValidValues() with the above patch returns empty SubForm Arrays with keys from ElementsBelongTo or the name of the SubForm, i guess this is not wanted, so here is the updated Patch.


Index: tests/Zend/Form/FormTest.php
===================================================================
--- tests/Zend/Form/FormTest.php        (Revision 21667)
+++ tests/Zend/Form/FormTest.php        (Arbeitskopie)
@@ -1473,7 +1473,58 @@
         $this->assertTrue($this->form->isValid($data));
     }
 
+    public function _setup9350()
+    {
+        $this->form->addSubForm(new Zend_Form_SubForm(), 'foo')
+                   ->foo->setElementsBelongTo('foo[foo]')
+                        ->addSubForm(new Zend_Form_SubForm(), 'foo')
+                        ->foo->setIsArray(false)
+                             ->addElement('text', 'foo')
+                             ->foo->addValidator('Identical',
+                                                 false,
+                                                 array('foo Value'));
 
+        $this->form->foo->addSubForm(new Zend_Form_SubForm(), 'baz')
+                   ->baz->setIsArray(false)
+                        ->addSubForm(new Zend_Form_SubForm(), 'baz')
+                        ->baz->setElementsBelongTo('baz[baz]')
+                             ->addElement('text', 'baz')
+                             ->baz->addValidator('Identical',
+                                                 false,
+                                                 array('baz Value'));
+
+        $data = array('valid' => array('foo' =>
+                                       array('foo' =>
+                                             array('foo' =>
+                                                   array('foo' => 'foo Value'),
+                                                   'baz' => 
+                                                   array('baz' => 
+                                                         array('baz' =>
+                                                               array('baz' => 'baz Value')))))),
+                      'invalid' => array('foo' =>
+                                         array('foo' =>
+                                               array('foo' =>
+                                                     array('foo' => 'foo Invalid'),
+                                                     'baz' => 
+                                                     array('baz' => 
+                                                           array('baz' =>
+                                                                 array('baz' => 'baz Value')))))),
+                      'partial' => array('foo' =>
+                                       array('foo' =>
+                                             array('baz' => 
+                                                   array('baz' => 
+                                                         array('baz' =>
+                                                               array('baz' => 'baz Value')))))));
+        return $data;
+    }
+
+    public function testGetValidValuesWithElementsBelongTo()
+    {
+        $data = $this->_setup9350();
+        $this->assertSame($this->form->getValidValues($data['invalid']), $data['partial']);
+    }
+
+
     // Display groups
 
     public function testCanAddAndRetrieveSingleDisplayGroups()
Index: library/Zend/Form.php
===================================================================
--- library/Zend/Form.php       (Revision 21667)
+++ library/Zend/Form.php       (Arbeitskopie)
@@ -1323,10 +1323,14 @@
      * values to persist them.
      *
      * @param  array $data
+     * @param  bool $suppressArrayNotation
      * @return array
      */
-    public function getValidValues($data)
+    public function getValidValues($data, $suppressArrayNotation = false)
     {
+        if ($this->isArray()) {
+            $data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
+        }
         $values = array();
         foreach ($this->getElements() as $key => $element) {
             if (isset($data[$key])) {
@@ -1336,10 +1340,22 @@
             }
         }
         foreach ($this->getSubForms() as $key => $form) {
-            if (isset($data[$key])) {
-                $values[$key] = $form->getValidValues($data[$key]);
+            if (isset($data[$key]) && !$form->isArray()) {
+                $tmp = $form->getValidValues($data[$key]);
+                if (!empty($tmp)) {
+                    $values[$key] = $tmp;
+                }
+            } else {
+                $tmp = $form->getValidValues($data, true);
+                if (!empty($tmp)) {
+                    $fValues = $this->_attachToArray($tmp, $form->getElementsBelongTo());
+                    $values = array_merge($values, $fValues);
+                }
             }
         }
+        if (!$suppressArrayNotation && $this->isArray() && !empty($values)) {
+            $values = $this->_attachToArray($values, $this->getElementsBelongTo());
+        }
 
         return $values;
     }

Patch (from comment) applied to trunk and 1.10 release branch.