Bläddra i källkod

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

Bernhard Schussek 14 år sedan
förälder
incheckning
35d9b7f800
2 ändrade filer med 146 tillägg och 86 borttagningar
  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;