Explorar el Código

[Form] Improved test coverage of Form. The emptyValue closure now receives the Form instance to use form data when constructing new objects

Bernhard Schussek hace 14 años
padre
commit
35d9b7f800
Se han modificado 2 ficheros con 146 adiciones y 86 borrados
  1. 14 11
      src/Symfony/Component/Form/Form.php
  2. 132 75
      tests/Symfony/Tests/Component/Form/FormTest.php

+ 14 - 11
src/Symfony/Component/Form/Form.php

@@ -406,7 +406,7 @@ class Form implements \IteratorAggregate, FormInterface
         $clientData = $event->getData();
 
         if (count($this->children) > 0) {
-            if (empty($clientData)) {
+            if (null === $clientData || '' === $clientData) {
                 $clientData = array();
             }
 
@@ -428,23 +428,26 @@ class Form implements \IteratorAggregate, FormInterface
                 }
             }
 
-            // Merge form data from children into existing client data
+            // If we have a data mapper, use old client data and merge
+            // data from the children into it later
             if ($this->dataMapper) {
                 $clientData = $this->getClientData();
+            }
+        }
 
-                // Create new structure to write the values into
-                if (null === $clientData || '' === $clientData) {
-                    $clientData = $this->emptyData;
-
-                    if ($clientData instanceof \Closure) {
-                        $clientData = $clientData->__invoke();
-                    }
-                }
+        if (null === $clientData || '' === $clientData) {
+            $clientData = $this->emptyData;
 
-                $this->dataMapper->mapFormsToData($this->children, $clientData);
+            if ($clientData instanceof \Closure) {
+                $clientData = $clientData->__invoke($this);
             }
         }
 
+        // Merge form data from children into existing client data
+        if (count($this->children) > 0 && $this->dataMapper) {
+            $this->dataMapper->mapFormsToData($this->children, $clientData);
+        }
+
         try {
             // Normalize data to unified representation
             $normData = $this->clientToNorm($clientData);

+ 132 - 75
tests/Symfony/Tests/Component/Form/FormTest.php

@@ -409,81 +409,6 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($this->form->isBound());
     }
 
-    public function testAddMapsClientDataToForm()
-    {
-        $mapper = $this->getDataMapper();
-        $form = $this->getBuilder()
-            ->setDataMapper($mapper)
-            ->setClientTransformer(new FixedDataTransformer(array(
-                '' => '',
-                'foo' => 'bar',
-            )))
-            ->setData('foo')
-            ->getForm();
-
-        $child = $this->getBuilder()->getForm();
-        $mapper->expects($this->once())
-            ->method('mapDataToForm')
-            ->with('bar', $child);
-
-        $form->add($child);
-    }
-
-    public function testSetDataMapsClientDataToChildren()
-    {
-        $mapper = $this->getDataMapper();
-        $child1 = $this->getBuilder('firstName')->getForm();
-        $child2 = $this->getBuilder('lastName')->getForm();
-        $form = $this->getBuilder()
-            ->setDataMapper($mapper)
-            ->setClientTransformer(new FixedDataTransformer(array(
-                '' => '',
-                'foo' => 'bar',
-            )))
-            ->getForm();
-
-        $form->add($child1);
-        $form->add($child2);
-
-        $mapper->expects($this->once())
-            ->method('mapDataToForms')
-            ->with('bar', array('firstName' => $child1, 'lastName' => $child2));
-
-        $form->setData('foo');
-    }
-
-    public function testBindMapsBoundChildrenOntoExistingClientData()
-    {
-        $test = $this;
-        $mapper = $this->getDataMapper();
-        $child1 = $this->getBuilder('firstName')->getForm();
-        $child2 = $this->getBuilder('lastName')->getForm();
-        $form = $this->getBuilder()
-            ->setDataMapper($mapper)
-            ->setClientTransformer(new FixedDataTransformer(array(
-                '' => '',
-                'foo' => 'bar',
-            )))
-            ->setData('foo')
-            ->getForm();
-
-        $form->add($child1);
-        $form->add($child2);
-
-        $mapper->expects($this->once())
-            ->method('mapFormsToData')
-            ->with(array('firstName' => $child1, 'lastName' => $child2), 'bar')
-            ->will($this->returnCallback(function ($children, $bar) use ($test) {
-                $test->assertEquals('Bernhard', $children['firstName']->getData());
-                $test->assertEquals('Schussek', $children['lastName']->getData());
-            }));
-
-        $form->bind(array(
-            'firstName' => 'Bernhard',
-            'lastName' => 'Schussek',
-        ));
-    }
-
     public function testSetDataExecutesTransformationChain()
     {
         // use real event dispatcher now
@@ -570,6 +495,138 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($form->isSynchronized());
     }
 
+    public function testEmptyDataCreatedBeforeTransforming()
+    {
+        $form = $this->getBuilder()
+            ->setEmptyData('foo')
+            ->setClientTransformer(new FixedDataTransformer(array(
+                '' => '',
+                // direction is reversed!
+                'bar' => 'foo',
+            )))
+            ->getForm();
+
+        $form->bind('');
+
+        $this->assertEquals('bar', $form->getData());
+    }
+
+    public function testEmptyDataFromClosure()
+    {
+        $test = $this;
+        $form = $this->getBuilder()
+            ->setEmptyData(function ($form) use ($test) {
+                // the form instance is passed to the closure to allow use
+                // of form data when creating the empty value
+                $test->assertInstanceOf('Symfony\Component\Form\FormInterface', $form);
+
+                return 'foo';
+            })
+            ->setClientTransformer(new FixedDataTransformer(array(
+                '' => '',
+                // direction is reversed!
+                'bar' => 'foo',
+            )))
+            ->getForm();
+
+        $form->bind('');
+
+        $this->assertEquals('bar', $form->getData());
+    }
+
+    public function testAddMapsClientDataToForm()
+    {
+        $mapper = $this->getDataMapper();
+        $form = $this->getBuilder()
+            ->setDataMapper($mapper)
+            ->setClientTransformer(new FixedDataTransformer(array(
+                '' => '',
+                'foo' => 'bar',
+            )))
+            ->setData('foo')
+            ->getForm();
+
+        $child = $this->getBuilder()->getForm();
+        $mapper->expects($this->once())
+            ->method('mapDataToForm')
+            ->with('bar', $child);
+
+        $form->add($child);
+    }
+
+    public function testSetDataMapsClientDataToChildren()
+    {
+        $mapper = $this->getDataMapper();
+        $form = $this->getBuilder()
+            ->setDataMapper($mapper)
+            ->setClientTransformer(new FixedDataTransformer(array(
+                '' => '',
+                'foo' => 'bar',
+            )))
+            ->getForm();
+
+        $form->add($child1 = $this->getBuilder('firstName')->getForm());
+        $form->add($child2 = $this->getBuilder('lastName')->getForm());
+
+        $mapper->expects($this->once())
+            ->method('mapDataToForms')
+            ->with('bar', array('firstName' => $child1, 'lastName' => $child2));
+
+        $form->setData('foo');
+    }
+
+    public function testBindMapsBoundChildrenOntoExistingClientData()
+    {
+        $test = $this;
+        $mapper = $this->getDataMapper();
+        $form = $this->getBuilder()
+            ->setDataMapper($mapper)
+            ->setClientTransformer(new FixedDataTransformer(array(
+                '' => '',
+                'foo' => 'bar',
+            )))
+            ->setData('foo')
+            ->getForm();
+
+        $form->add($child1 = $this->getBuilder('firstName')->getForm());
+        $form->add($child2 = $this->getBuilder('lastName')->getForm());
+
+        $mapper->expects($this->once())
+            ->method('mapFormsToData')
+            ->with(array('firstName' => $child1, 'lastName' => $child2), 'bar')
+            ->will($this->returnCallback(function ($children, $bar) use ($test) {
+                $test->assertEquals('Bernhard', $children['firstName']->getData());
+                $test->assertEquals('Schussek', $children['lastName']->getData());
+            }));
+
+        $form->bind(array(
+            'firstName' => 'Bernhard',
+            'lastName' => 'Schussek',
+        ));
+    }
+
+    public function testBindMapsBoundChildrenOntoEmptyData()
+    {
+        $test = $this;
+        $mapper = $this->getDataMapper();
+        $object = new \stdClass();
+        $form = $this->getBuilder()
+            ->setDataMapper($mapper)
+            ->setEmptyData($object)
+            ->setData(null)
+            ->getForm();
+
+        $form->add($child = $this->getBuilder('name')->getForm());
+
+        $mapper->expects($this->once())
+            ->method('mapFormsToData')
+            ->with(array('name' => $child), $object);
+
+        $form->bind(array(
+            'name' => 'Bernhard',
+        ));
+    }
+
     public function testBindValidatesAfterTransformation()
     {
         $test = $this;