From 03b880fed06c0d1f77196b6de22d7a6dd277cd8c Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 13 Dec 2012 15:18:14 +0100 Subject: [PATCH] [Form] Fixed treatment of countables and traversables in Form::isEmpty() --- src/Symfony/Component/Form/Form.php | 6 +- src/Symfony/Component/Form/FormInterface.php | 2 +- .../Component/Form/Tests/SimpleFormTest.php | 81 +++++++++++++++++-- 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index ec3d5393a8..8f115e963c 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -684,7 +684,11 @@ class Form implements \IteratorAggregate, FormInterface } } - return FormUtil::isEmpty($this->modelData) || array() === $this->modelData; + return FormUtil::isEmpty($this->modelData) || + // arrays, countables + 0 === count($this->modelData) || + // traversables that are not countable + ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)); } /** diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index 682c6a727f..9051aba51e 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -98,7 +98,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Updates the form with default data. * - * @param array $modelData The data formatted as expected for the underlying object + * @param mixed $modelData The data formatted as expected for the underlying object * * @return FormInterface The form instance * diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index 3a590b7509..20dee8f8f4 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -16,13 +16,42 @@ use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\FormConfigBuilder; -use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\Form\Tests\Fixtures\FixedFilterListener; +class SimpleFormTest_Countable implements \Countable +{ + private $count; + + public function __construct($count) + { + $this->count = $count; + } + + public function count() + { + return $this->count; + } +} + +class SimpleFormTest_Traversable implements \IteratorAggregate +{ + private $iterator; + + public function __construct($count) + { + $this->iterator = new \ArrayIterator($count > 0 ? array_fill(0, $count, 'Foo') : array()); + } + + public function getIterator() + { + return $this->iterator; + } +} + class SimpleFormTest extends AbstractFormTest { public function testDataIsInitializedToConfiguredValue() @@ -68,7 +97,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */ public function testBindThrowsExceptionIfAlreadyBound() { @@ -173,6 +202,42 @@ class SimpleFormTest extends AbstractFormTest $this->assertTrue($this->form->isEmpty()); } + public function testEmptyIfEmptyCountable() + { + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Countable', $this->dispatcher)); + + $this->form->setData(new SimpleFormTest_Countable(0)); + + $this->assertTrue($this->form->isEmpty()); + } + + public function testNotEmptyIfFilledCountable() + { + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Countable', $this->dispatcher)); + + $this->form->setData(new SimpleFormTest_Countable(1)); + + $this->assertFalse($this->form->isEmpty()); + } + + public function testEmptyIfEmptyTraversable() + { + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Traversable', $this->dispatcher)); + + $this->form->setData(new SimpleFormTest_Traversable(0)); + + $this->assertTrue($this->form->isEmpty()); + } + + public function testNotEmptyIfFilledTraversable() + { + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Traversable', $this->dispatcher)); + + $this->form->setData(new SimpleFormTest_Traversable(1)); + + $this->assertFalse($this->form->isEmpty()); + } + public function testEmptyIfNull() { $this->form->setData(null); @@ -240,7 +305,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */ public function testSetParentThrowsExceptionIfAlreadyBound() { @@ -262,7 +327,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */ public function testSetDataThrowsExceptionIfAlreadyBound() { @@ -674,7 +739,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException * @expectedExceptionMessage A form with an empty name cannot have a parent form. */ public function testFormCannotHaveEmptyNameNotInRootLevel() @@ -720,7 +785,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testViewDataMustNotBeObjectIfDataClassIsNull() { @@ -750,7 +815,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testViewDataMustBeObjectIfDataClassIsSet() { @@ -765,7 +830,7 @@ class SimpleFormTest extends AbstractFormTest } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testSetDataCannotInvokeItself() {