Parcourir la source

ZF-9707: make belongTo work per expectations

- Patches by Christian Albrecht

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@21913 44c647ce-9c0f-0410-b52a-842ac1e357ba
matthew il y a 15 ans
Parent
commit
ade48ebb35
2 fichiers modifiés avec 170 ajouts et 16 suppressions
  1. 94 16
      library/Zend/Form.php
  2. 76 0
      tests/Zend/Form/FormTest.php

+ 94 - 16
library/Zend/Form.php

@@ -1226,12 +1226,20 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
      */
     public function setDefaults(array $defaults)
     {
+        $eBelongTo = null;
+
         if ($this->isArray()) {
-            $defaults = $this->_dissolveArrayValue($defaults, $this->getElementsBelongTo());
+            $eBelongTo = $this->getElementsBelongTo();
+            $defaults = $this->_dissolveArrayValue($defaults, $eBelongTo);
         }
         foreach ($this->getElements() as $name => $element) {
-            if (array_key_exists($name, $defaults)) {
-                $this->setDefault($name, $defaults[$name]);
+            $check = $defaults;
+            if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
+                $check = $this->_dissolveArrayValue($defaults, $belongsTo);
+            }
+            if (array_key_exists($name, $check)) {
+                $this->setDefault($name, $check[$name]);
+                $defaults = $this->_dissolveArrayUnsetKey($defaults, $belongsTo, $name);
             }
         }
         foreach ($this->getSubForms() as $name => $form) {
@@ -1301,9 +1309,22 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
     public function getValues($suppressArrayNotation = false)
     {
         $values = array();
+        $eBelongTo = null;
+        
+        if ($this->isArray()) {
+            $eBelongTo = $this->getElementsBelongTo();
+        }
+        
         foreach ($this->getElements() as $key => $element) {
             if (!$element->getIgnore()) {
-                $values[$key] = $element->getValue();
+                $merge = array();
+                if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
+                    if ('' !== (string)$belongsTo) {
+                        $key = $belongsTo . '[' . $key . ']';
+                    }
+                }
+                $merge = $this->_attachToArray($element->getValue(), $key);
+                $values = array_merge_recursive($values, $merge);
             }
         }
         foreach ($this->getSubForms() as $key => $subForm) {
@@ -1337,15 +1358,29 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
      */
     public function getValidValues($data, $suppressArrayNotation = false)
     {
+        $values = array();
+        $eBelongTo = null;
+
         if ($this->isArray()) {
-            $data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
+            $eBelongTo = $this->getElementsBelongTo();
+            $data = $this->_dissolveArrayValue($data, $eBelongTo);
         }
-        $values = array();
+        
         foreach ($this->getElements() as $key => $element) {
-            if (isset($data[$key])) {
-                if($element->isValid($data[$key], $data)) {
-                    $values[$key] = $element->getValue();
+            $check = $data;
+            if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
+                $check = $this->_dissolveArrayValue($data, $belongsTo);
+            }
+            if (isset($check[$key])) {
+                if($element->isValid($check[$key], $check)) {
+                    $merge = array();
+                    if ($belongsTo !== $eBelongTo && '' !== (string)$belongsTo) {
+                            $key = $belongsTo . '[' . $key . ']';
+                    }
+                    $merge = $this->_attachToArray($element->getValue(), $key);
+                    $values = array_merge_recursive($values, $merge);
                 }
+                $data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key);
             }
         }
         foreach ($this->getSubForms() as $key => $form) {
@@ -2012,6 +2047,34 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
     }
 
     /**
+     * Given an array, an optional arrayPath and a key this method
+     * dissolves the arrayPath and unsets the key within the array
+     * if it exists.
+     * 
+     * @param array $array 
+     * @param string|null $arrayPath
+     * @param string $key
+     * @return array
+     */
+    protected function _dissolveArrayUnsetKey($array, $arrayPath, $key)
+    {
+        $unset =& $array;
+        $path  = trim(strtr((string)$arrayPath, array('[' => '/', ']' => '')), '/');
+        $segs  = ('' !== $path) ? explode('/', $path) : array();
+        
+        foreach ($segs as $seg) {
+            if (!array_key_exists($seg, (array)$unset)) {
+                return $array;
+            }
+            $unset =& $unset[$seg];
+        }
+        if (array_key_exists($key, (array)$unset)) {
+            unset($unset[$key]);
+        }
+        return $array;
+    }
+
+    /**
      * Converts given arrayPath to an array and attaches given value at the end of it.
      *
      * @param  mixed $value The value to attach
@@ -2051,19 +2114,26 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
         }
         $translator = $this->getTranslator();
         $valid      = true;
+        $eBelongTo  = null;
 
         if ($this->isArray()) {
-            $data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
+            $eBelongTo = $this->getElementsBelongTo();
+            $data = $this->_dissolveArrayValue($data, $eBelongTo);
         }
 
         foreach ($this->getElements() as $key => $element) {
             if (null !== $translator && !$element->hasTranslator()) {
                 $element->setTranslator($translator);
             }
-            if (!isset($data[$key])) {
-                $valid = $element->isValid(null, $data) && $valid;
+            $check = $data;
+            if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
+                $check = $this->_dissolveArrayValue($data, $belongsTo);
+            }
+            if (!isset($check[$key])) {
+                $valid = $element->isValid(null, $check) && $valid;
             } else {
-                $valid = $element->isValid($data[$key], $data) && $valid;
+                $valid = $element->isValid($check[$key], $check) && $valid;
+                $data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key);
             }
         }
         foreach ($this->getSubForms() as $key => $form) {
@@ -2097,19 +2167,27 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
      */
     public function isValidPartial(array $data)
     {
+        $eBelongTo  = null;
+
         if ($this->isArray()) {
-            $data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
+            $eBelongTo = $this->getElementsBelongTo();
+            $data = $this->_dissolveArrayValue($data, $eBelongTo);
         }
 
         $translator        = $this->getTranslator();
         $valid             = true;
 
         foreach ($this->getElements() as $key => $element) {
-            if (isset($data[$key])) {
+            $check = $data;
+            if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
+                $check = $this->_dissolveArrayValue($data, $belongsTo);
+            }
+            if (isset($check[$key])) {
                 if (null !== $translator && !$element->hasTranslator()) {
                     $element->setTranslator($translator);
                 }
-                $valid = $element->isValid($data[$key], $data) && $valid;
+                $valid = $element->isValid($check[$key], $check) && $valid;
+                $data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key);
             }
         }
         foreach ($this->getSubForms() as $key => $form) {

+ 76 - 0
tests/Zend/Form/FormTest.php

@@ -1473,6 +1473,35 @@ class Zend_Form_FormTest extends PHPUnit_Framework_TestCase
         $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')));
+    }
+
+    /**
+     * @group ZF-9666
+     */
+    public function testSetDefaultsDiscardsPopulatedValues()
+    {
+        $this->form->addElement('text', 'foo');
+        $this->form->addSubForm(new Zend_Form_SubForm(), 'bar')
+                   ->bar->addElement('text', 'foo');
+
+        $this->form->populate(array('foo' => 'foo Value'));
+        $html = $this->form->setView($this->getView())
+                           ->render();
+        $this->assertEquals(1, preg_match_all('/foo Value/', $html, $matches));
+    }
+
     public function _setup9350()
     {
         $this->form->addSubForm(new Zend_Form_SubForm(), 'foo')
@@ -1679,6 +1708,53 @@ class Zend_Form_FormTest extends PHPUnit_Framework_TestCase
         $this->assertEquals($this->form->getValidValues($data['invalid']), $data['partial']);
     }
 
+    public function _setup9607()
+    {
+        $this->form->addElement('text', 'foo')
+                   ->foo->setBelongsTo('bar[quo]')
+                        ->setRequired(true)
+                        ->addValidator('Identical',
+                                       false,
+                                       'foo Value');
+
+        $data = array('valid' => array('bar' =>
+                                       array('quo' =>
+                                             array('foo' => 'foo Value'))));
+        return $data;
+    }
+
+    public function testIsValidWithBelongsTo()
+    {
+        $data = $this->_setup9607();
+        $this->assertTrue($this->form->isValid($data['valid']));
+    }
+
+    public function testIsValidPartialWithBelongsTo()
+    {
+        $data = $this->_setup9607();
+        $this->assertTrue($this->form->isValidPartial($data['valid']));
+        $this->assertSame('foo Value', $this->form->foo->getValue());
+    }
+  
+    public function testPopulateWithBelongsTo()
+    {
+        $data = $this->_setup9607();
+        $this->form->populate($data['valid']);
+        $this->assertSame('foo Value', $this->form->foo->getValue());
+    }
+  
+    public function testGetValuesWithBelongsTo()
+    {
+        $data = $this->_setup9607();
+        $this->form->populate($data['valid']);
+        $this->assertSame($data['valid'], $this->form->getValues());
+    }
+  
+    public function testGetValidValuesWithBelongsTo()
+    {
+        $data = $this->_setup9607();
+        $this->assertSame($data['valid'], $this->form->getValidValues($data['valid']));
+    }
 
     // Display groups