[Form] Fixed treatment of countables and traversables in Form::isEmpty()

This commit is contained in:
Bernhard Schussek 2012-12-13 15:18:14 +01:00
parent 6e499a368b
commit 03b880fed0
3 changed files with 79 additions and 10 deletions

View File

@ -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));
}
/**

View File

@ -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
*

View File

@ -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()
{