Skip to content

Commit

Permalink
[Form] Fixed treatment of countables and traversables in Form::isEmpty()
Browse files Browse the repository at this point in the history
  • Loading branch information
webmozart committed Dec 13, 2012
1 parent 6e499a3 commit 03b880f
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 10 deletions.
6 changes: 5 additions & 1 deletion src/Symfony/Component/Form/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,11 @@ public function isEmpty()
}
}

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));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Form/FormInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public function getErrors();
/**
* 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
*
Expand Down
81 changes: 73 additions & 8 deletions src/Symfony/Component/Form/Tests/SimpleFormTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,42 @@
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()
Expand Down Expand Up @@ -68,7 +97,7 @@ public function testDataIsInitializedFromBind()
}

/**
* @expectedException Symfony\Component\Form\Exception\AlreadyBoundException
* @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException
*/
public function testBindThrowsExceptionIfAlreadyBound()
{
Expand Down Expand Up @@ -173,6 +202,42 @@ public function testEmptyIfEmptyArray()
$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);
Expand Down Expand Up @@ -240,7 +305,7 @@ public function testHasNoErrors()
}

/**
* @expectedException Symfony\Component\Form\Exception\AlreadyBoundException
* @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException
*/
public function testSetParentThrowsExceptionIfAlreadyBound()
{
Expand All @@ -262,7 +327,7 @@ public function testNotBound()
}

/**
* @expectedException Symfony\Component\Form\Exception\AlreadyBoundException
* @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException
*/
public function testSetDataThrowsExceptionIfAlreadyBound()
{
Expand Down Expand Up @@ -674,7 +739,7 @@ public function testSetNullParentWorksWithEmptyName()
}

/**
* @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()
Expand Down Expand Up @@ -720,7 +785,7 @@ public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull(
}

/**
* @expectedException Symfony\Component\Form\Exception\FormException
* @expectedException \Symfony\Component\Form\Exception\FormException
*/
public function testViewDataMustNotBeObjectIfDataClassIsNull()
{
Expand Down Expand Up @@ -750,7 +815,7 @@ public function testViewDataMayBeArrayAccessIfDataClassIsNull()
}

/**
* @expectedException Symfony\Component\Form\Exception\FormException
* @expectedException \Symfony\Component\Form\Exception\FormException
*/
public function testViewDataMustBeObjectIfDataClassIsSet()
{
Expand All @@ -765,7 +830,7 @@ public function testViewDataMustBeObjectIfDataClassIsSet()
}

/**
* @expectedException Symfony\Component\Form\Exception\FormException
* @expectedException \Symfony\Component\Form\Exception\FormException
*/
public function testSetDataCannotInvokeItself()
{
Expand Down

0 comments on commit 03b880f

Please sign in to comment.