浏览代码

[Form] Moved creation logic of FormView to Form class

Bernhard Schussek 14 年之前
父节点
当前提交
276b23a344

+ 29 - 2
src/Symfony/Component/Form/Form.php

@@ -832,9 +832,36 @@ class Form implements \IteratorAggregate, FormInterface
         return $value;
     }
 
-    public function getView()
+    public function getView(FormView $parent = null)
     {
-        return new FormView($this);
+        if (null === $parent && $this->parent) {
+            $parent = $this->parent->getView();
+        }
+
+        $view = new FormView();
+
+        if (null !== $parent) {
+            $view->setParent($parent);
+        }
+
+        $types = (array) $this->types;
+        $childViews = array();
+
+        foreach ($types as $type) {
+            $type->buildView($view, $this);
+        }
+
+        foreach ($this->children as $key => $child) {
+            $childViews[$key] = $child->getView($view);
+        }
+
+        $view->setChildren($childViews);
+
+        foreach ($types as $type) {
+            $type->buildViewBottomUp($view, $this);
+        }
+
+        return $view;
     }
 
     /**

+ 1 - 1
src/Symfony/Component/Form/FormInterface.php

@@ -125,5 +125,5 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
 
     function isRoot();
 
-    function getView();
+    function getView(FormView $parent = null);
 }

+ 0 - 24
src/Symfony/Component/Form/FormView.php

@@ -36,30 +36,6 @@ class FormView implements \ArrayAccess, \IteratorAggregate
      */
     private $rendered = false;
 
-    public function __construct(FormInterface $form, self $parent = null)
-    {
-        $this->parent = $parent;
-
-        $types = (array) $form->getTypes();
-        $children = array();
-
-        $this->setVar('form', $this);
-
-        foreach ($types as $type) {
-            $type->buildView($this, $form);
-        }
-
-        foreach ($form as $key => $child) {
-            $children[$key] = new self($child, $this);
-        }
-
-        $this->setChildren($children);
-
-        foreach ($types as $type) {
-            $type->buildViewBottomUp($this, $form);
-        }
-    }
-
     public function setVar($name, $value)
     {
         $this->vars[$name] = $value;

+ 1 - 0
src/Symfony/Component/Form/Type/FieldType.php

@@ -77,6 +77,7 @@ class FieldType extends AbstractType
             $name = $form->getName();
         }
 
+        $view->setVar('form', $view);
         $view->setVar('id', $id);
         $view->setVar('name', $name);
         $view->setVar('errors', $form->getErrors());

+ 62 - 0
tests/Symfony/Tests/Component/Form/FormTest.php

@@ -15,6 +15,7 @@ require_once __DIR__.'/Fixtures/FixedDataTransformer.php';
 require_once __DIR__.'/Fixtures/FixedFilterListener.php';
 
 use Symfony\Component\Form\Form;
+use Symfony\Component\Form\FormView;
 use Symfony\Component\Form\FormBuilder;
 use Symfony\Component\Form\FormError;
 use Symfony\Component\Form\DataTransformer\TransformationFailedException;
@@ -864,6 +865,67 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $this->assertSame(array(), $form->getErrors());
     }
 
+    public function testGetView()
+    {
+        $test = $this;
+        $type1 = $this->getMock('Symfony\Component\Form\Type\FormTypeInterface');
+        $type2 = $this->getMock('Symfony\Component\Form\Type\FormTypeInterface');
+        $calls = array();
+
+        $type1->expects($this->once())
+            ->method('buildView')
+            ->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
+                $calls[] = 'type1::buildView';
+                $test->assertTrue($view->hasParent());
+                $test->assertFalse($view->hasChildren());
+            }));
+
+        $type2->expects($this->once())
+            ->method('buildView')
+            ->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
+                $calls[] = 'type2::buildView';
+                $test->assertTrue($view->hasParent());
+                $test->assertFalse($view->hasChildren());
+            }));
+
+        $type1->expects($this->once())
+            ->method('buildViewBottomUp')
+            ->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
+                $calls[] = 'type1::buildViewBottomUp';
+                $test->assertTrue($view->hasChildren());
+            }));
+
+        $type2->expects($this->once())
+            ->method('buildViewBottomUp')
+            ->will($this->returnCallback(function (FormView $view, Form $form) use ($test, &$calls) {
+                $calls[] = 'type2::buildViewBottomUp';
+                $test->assertTrue($view->hasChildren());
+            }));
+
+        $form = $this->getBuilder()->setTypes(array($type1, $type2))->getForm();
+        $form->setParent($this->getBuilder()->getForm());
+        $form->add($this->getBuilder()->getForm());
+
+        $form->getView();
+
+        $this->assertEquals(array(
+            0 => 'type1::buildView',
+            1 => 'type2::buildView',
+            2 => 'type1::buildViewBottomUp',
+            3 => 'type2::buildViewBottomUp',
+        ), $calls);
+    }
+
+    public function testGetViewAcceptsParent()
+    {
+        $parent = new FormView();
+
+        $form = $this->getBuilder()->getForm();
+        $view = $form->getView($parent);
+
+        $this->assertSame($parent, $view->getParent());
+    }
+
     protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null)
     {
         return new FormBuilder($name, $this->factory, $dispatcher ?: $this->dispatcher);