[Form] Fixed: Empty forms can be compound too
This commit is contained in:
parent
85977649a4
commit
45d967e95e
@ -24,7 +24,7 @@ class PropertyPathMapper implements DataMapperInterface
|
||||
public function mapDataToForms($data, array $forms)
|
||||
{
|
||||
if (!empty($data) && !is_array($data) && !is_object($data)) {
|
||||
throw new UnexpectedTypeException($data, 'Object, array or empty');
|
||||
throw new UnexpectedTypeException($data, 'object, array or empty');
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
|
@ -42,6 +42,7 @@ class FormType extends AbstractType
|
||||
->setMapped($options['mapped'])
|
||||
->setByReference($options['by_reference'])
|
||||
->setVirtual($options['virtual'])
|
||||
->setCompound($options['compound'])
|
||||
->setData($options['data'])
|
||||
->setDataMapper(new PropertyPathMapper())
|
||||
;
|
||||
@ -116,7 +117,7 @@ class FormType extends AbstractType
|
||||
'multipart' => false,
|
||||
'attr' => $options['attr'],
|
||||
'label_attr' => $options['label_attr'],
|
||||
'compound' => $options['compound'],
|
||||
'compound' => $form->getConfig()->getCompound(),
|
||||
'types' => $types,
|
||||
'translation_domain' => $translationDomain,
|
||||
));
|
||||
@ -160,7 +161,7 @@ class FormType extends AbstractType
|
||||
}
|
||||
|
||||
return function (FormInterface $form) {
|
||||
return count($form) > 0 ? array() : '';
|
||||
return $form->getConfig()->getCompound() ? array() : '';
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -345,7 +345,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$viewData = $this->normToView($normData);
|
||||
|
||||
// Validate if view data matches data class (unless empty)
|
||||
if (!empty($viewData)) {
|
||||
if ('' !== $viewData && null !== $viewData) {
|
||||
$dataClass = $this->config->getDataClass();
|
||||
|
||||
$actualType = is_object($viewData) ? 'an instance of class ' . get_class($viewData) : ' a(n) ' . gettype($viewData);
|
||||
@ -378,7 +378,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$this->viewData = $viewData;
|
||||
$this->synchronized = true;
|
||||
|
||||
if (count($this->children) > 0 && $this->config->getDataMapper()) {
|
||||
if ($this->config->getCompound() && $this->config->getDataMapper()) {
|
||||
// Update child forms from the data
|
||||
$this->config->getDataMapper()->mapDataToForms($viewData, $this->children);
|
||||
}
|
||||
@ -477,37 +477,42 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$this->config->getEventDispatcher()->dispatch(FormEvents::BIND_CLIENT_DATA, $event);
|
||||
$submittedData = $event->getData();
|
||||
|
||||
// Build the data in the view format
|
||||
$viewData = $submittedData;
|
||||
|
||||
if (count($this->children) > 0) {
|
||||
if (null === $viewData || '' === $viewData) {
|
||||
$viewData = array();
|
||||
// Check whether the form is compound.
|
||||
// This check is preferrable over checking the number of children,
|
||||
// since forms without children may also be compound.
|
||||
// (think of empty collection forms)
|
||||
if ($this->config->getCompound()) {
|
||||
if (null === $submittedData || '' === $submittedData) {
|
||||
$submittedData = array();
|
||||
}
|
||||
|
||||
if (!is_array($viewData)) {
|
||||
throw new UnexpectedTypeException($viewData, 'array');
|
||||
if (!is_array($submittedData)) {
|
||||
throw new UnexpectedTypeException($submittedData, 'array');
|
||||
}
|
||||
|
||||
foreach ($this->children as $name => $child) {
|
||||
if (!isset($viewData[$name])) {
|
||||
$viewData[$name] = null;
|
||||
if (!isset($submittedData[$name])) {
|
||||
$submittedData[$name] = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($viewData as $name => $value) {
|
||||
foreach ($submittedData as $name => $value) {
|
||||
if ($this->has($name)) {
|
||||
$this->children[$name]->bind($value);
|
||||
} else {
|
||||
$extraData[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a data mapper, use old view data and merge
|
||||
// data from the children into it later
|
||||
if ($this->config->getDataMapper()) {
|
||||
$viewData = $this->getViewData();
|
||||
}
|
||||
|
||||
// By default, the submitted data is also the data in view format
|
||||
$viewData = $submittedData;
|
||||
|
||||
// If the form is compound, the default data in view format
|
||||
// is reused. The data of the children is merged into this
|
||||
// default data using the data mapper.
|
||||
if ($this->config->getCompound() && $this->config->getDataMapper()) {
|
||||
$viewData = $this->getViewData();
|
||||
}
|
||||
|
||||
if (null === $viewData || '' === $viewData) {
|
||||
@ -522,7 +527,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
}
|
||||
|
||||
// Merge form data from children into existing view data
|
||||
if (count($this->children) > 0 && $this->config->getDataMapper() && null !== $viewData) {
|
||||
if ($this->config->getCompound() && $this->config->getDataMapper() && null !== $viewData) {
|
||||
$this->config->getDataMapper()->mapFormsToData($this->children, $viewData);
|
||||
}
|
||||
|
||||
@ -542,7 +547,6 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$this->config->getEventDispatcher()->dispatch(FormEvents::BIND_NORM_DATA, $event);
|
||||
$normData = $event->getData();
|
||||
|
||||
|
||||
// Synchronize representations - must not change the content!
|
||||
$modelData = $this->normToModel($normData);
|
||||
$viewData = $this->normToView($normData);
|
||||
@ -591,7 +595,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
// Form bound without name
|
||||
$params = $request->request->all();
|
||||
$files = $request->files->all();
|
||||
} elseif (count($this->children) > 0) {
|
||||
} elseif ($this->config->getCompound()) {
|
||||
// Form bound with name and children
|
||||
$params = $request->request->get($name, array());
|
||||
$files = $request->files->get($name, array());
|
||||
@ -841,6 +845,10 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
throw new AlreadyBoundException('You cannot add children to a bound form');
|
||||
}
|
||||
|
||||
if (!$this->config->getCompound()) {
|
||||
throw new FormException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?');
|
||||
}
|
||||
|
||||
$this->children[$child->getName()] = $child;
|
||||
|
||||
$child->setParent($this);
|
||||
|
@ -53,6 +53,11 @@ class FormConfig implements FormConfigEditorInterface
|
||||
*/
|
||||
private $virtual = false;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $compound = true;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@ -356,6 +361,14 @@ class FormConfig implements FormConfigEditorInterface
|
||||
return $this->virtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCompound()
|
||||
{
|
||||
return $this->compound;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -632,6 +645,16 @@ class FormConfig implements FormConfigEditorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCompound($compound)
|
||||
{
|
||||
$this->compound = $compound;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -199,6 +199,17 @@ interface FormConfigEditorInterface extends FormConfigInterface
|
||||
*/
|
||||
function setVirtual($virtual);
|
||||
|
||||
/**
|
||||
* Sets whether the form should be compound.
|
||||
*
|
||||
* @param Boolean $compound Whether the form should be compound.
|
||||
*
|
||||
* @return self The configuration object.
|
||||
*
|
||||
* @see FormConfigInterface::getCompound()
|
||||
*/
|
||||
function setCompound($compound);
|
||||
|
||||
/**
|
||||
* Set the types.
|
||||
*
|
||||
|
@ -65,6 +65,17 @@ interface FormConfigInterface
|
||||
*/
|
||||
function getVirtual();
|
||||
|
||||
/**
|
||||
* Returns whether the form is compound.
|
||||
*
|
||||
* This property is independent of whether the form actually has
|
||||
* children. A form can be compound and have no children at all, like
|
||||
* for example an empty collection form.
|
||||
*
|
||||
* @return Boolean Whether the form is compound.
|
||||
*/
|
||||
function getCompound();
|
||||
|
||||
/**
|
||||
* Returns the form types used to construct the form.
|
||||
*
|
||||
|
@ -18,7 +18,7 @@ class CollectionTypeTest extends TypeTestCase
|
||||
public function testContainsNoChildByDefault()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
));
|
||||
|
||||
$this->assertCount(0, $form);
|
||||
@ -27,7 +27,7 @@ class CollectionTypeTest extends TypeTestCase
|
||||
public function testSetDataAdjustsSize()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
'options' => array(
|
||||
'max_length' => 20,
|
||||
),
|
||||
@ -53,7 +53,7 @@ class CollectionTypeTest extends TypeTestCase
|
||||
public function testThrowsExceptionIfObjectIsNotTraversable()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
));
|
||||
$this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
|
||||
$form->setData(new \stdClass());
|
||||
@ -62,7 +62,7 @@ class CollectionTypeTest extends TypeTestCase
|
||||
public function testNotResizedIfBoundWithMissingData()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
));
|
||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||
$form->bind(array('foo@bar.com'));
|
||||
@ -70,13 +70,13 @@ class CollectionTypeTest extends TypeTestCase
|
||||
$this->assertTrue($form->has('0'));
|
||||
$this->assertTrue($form->has('1'));
|
||||
$this->assertEquals('foo@bar.com', $form[0]->getData());
|
||||
$this->assertNull($form[1]->getData());
|
||||
$this->assertEquals('', $form[1]->getData());
|
||||
}
|
||||
|
||||
public function testResizedDownIfBoundWithMissingDataAndAllowDelete()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
'allow_delete' => true,
|
||||
));
|
||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||
@ -91,7 +91,7 @@ class CollectionTypeTest extends TypeTestCase
|
||||
public function testNotResizedIfBoundWithExtraData()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
));
|
||||
$form->setData(array('foo@bar.com'));
|
||||
$form->bind(array('foo@foo.com', 'bar@bar.com'));
|
||||
@ -104,7 +104,7 @@ class CollectionTypeTest extends TypeTestCase
|
||||
public function testResizedUpIfBoundWithExtraDataAndAllowAdd()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
'allow_add' => true,
|
||||
));
|
||||
$form->setData(array('foo@bar.com'));
|
||||
|
@ -77,6 +77,7 @@ class FormTypeTest extends TypeTestCase
|
||||
null => '',
|
||||
'reverse[a]' => 'a',
|
||||
)))
|
||||
->setCompound(false)
|
||||
->getForm();
|
||||
|
||||
$form->bind(' a ');
|
||||
@ -92,6 +93,7 @@ class FormTypeTest extends TypeTestCase
|
||||
null => '',
|
||||
'reverse[ a ]' => ' a ',
|
||||
)))
|
||||
->setCompound(false)
|
||||
->getForm();
|
||||
|
||||
$form->bind(' a ');
|
||||
@ -235,8 +237,8 @@ class FormTypeTest extends TypeTestCase
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('lastName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
$form->add($this->factory->createNamed('lastName', 'text'));
|
||||
|
||||
$form->setData(null);
|
||||
// partially empty, still an object is created
|
||||
@ -256,8 +258,8 @@ class FormTypeTest extends TypeTestCase
|
||||
'data' => new Author(),
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('lastName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
$form->add($this->factory->createNamed('lastName', 'text'));
|
||||
|
||||
$form->setData(null);
|
||||
// partially empty, still an object is created
|
||||
@ -276,7 +278,7 @@ class FormTypeTest extends TypeTestCase
|
||||
'data_class' => null,
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => 'Bernhard'));
|
||||
@ -290,8 +292,8 @@ class FormTypeTest extends TypeTestCase
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('lastName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
$form->add($this->factory->createNamed('lastName', 'text'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => '', 'lastName' => ''));
|
||||
@ -305,8 +307,8 @@ class FormTypeTest extends TypeTestCase
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'required' => true,
|
||||
));
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('lastName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
$form->add($this->factory->createNamed('lastName', 'text'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => '', 'lastName' => ''));
|
||||
@ -320,7 +322,7 @@ class FormTypeTest extends TypeTestCase
|
||||
public function testBindWithEmptyDataStoresArrayIfNoClassAvailable()
|
||||
{
|
||||
$form = $this->factory->create('form');
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => 'Bernhard'));
|
||||
@ -328,7 +330,7 @@ class FormTypeTest extends TypeTestCase
|
||||
$this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyDataPassesEmptyStringToTransformerIfNoChildren()
|
||||
public function testBindWithEmptyDataPassesEmptyStringToTransformerIfNotCompound()
|
||||
{
|
||||
$form = $this->factory->createBuilder('form')
|
||||
->addViewTransformer(new FixedDataTransformer(array(
|
||||
@ -337,6 +339,7 @@ class FormTypeTest extends TypeTestCase
|
||||
// required to test that bind(null) is converted to ''
|
||||
'empty' => '',
|
||||
)))
|
||||
->setCompound(false)
|
||||
->getForm();
|
||||
|
||||
$form->bind(null);
|
||||
@ -352,7 +355,7 @@ class FormTypeTest extends TypeTestCase
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'empty_data' => $author,
|
||||
));
|
||||
$form->add($this->factory->createNamed('firstName', 'form'));
|
||||
$form->add($this->factory->createNamed('firstName', 'text'));
|
||||
|
||||
$form->bind(array('firstName' => 'Bernhard'));
|
||||
|
||||
@ -360,34 +363,31 @@ class FormTypeTest extends TypeTestCase
|
||||
$this->assertEquals('Bernhard', $author->firstName);
|
||||
}
|
||||
|
||||
public function provideZeros()
|
||||
{
|
||||
return array(
|
||||
array(0, '0'),
|
||||
array('0', '0'),
|
||||
array('00000', '00000'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideZeros
|
||||
* @see https://github.com/symfony/symfony/issues/1986
|
||||
*/
|
||||
public function testSetDataThroughParamsWithZero()
|
||||
public function testSetDataThroughParamsWithZero($data, $dataAsString)
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('data' => 0));
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data' => $data,
|
||||
'compound' => false,
|
||||
));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertFalse($form->isEmpty());
|
||||
|
||||
$this->assertSame('0', $view->getVar('value'));
|
||||
$this->assertSame('0', $form->getData());
|
||||
|
||||
$form = $this->factory->create('form', null, array('data' => '0'));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertFalse($form->isEmpty());
|
||||
|
||||
$this->assertSame('0', $view->getVar('value'));
|
||||
$this->assertSame('0', $form->getData());
|
||||
|
||||
$form = $this->factory->create('form', null, array('data' => '00000'));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertFalse($form->isEmpty());
|
||||
|
||||
$this->assertSame('00000', $view->getVar('value'));
|
||||
$this->assertSame('00000', $form->getData());
|
||||
$this->assertSame($dataAsString, $view->getVar('value'));
|
||||
$this->assertSame($dataAsString, $form->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -412,7 +412,7 @@ class FormTypeTest extends TypeTestCase
|
||||
$builder->add('reference', 'form', array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
));
|
||||
$builder->get('reference')->add('firstName', 'form');
|
||||
$builder->get('reference')->add('firstName', 'text');
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
@ -435,7 +435,7 @@ class FormTypeTest extends TypeTestCase
|
||||
$builder->add('referenceCopy', 'form', array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
));
|
||||
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||
$builder->get('referenceCopy')->add('firstName', 'text');
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form['referenceCopy']->setData($newReference); // new author object
|
||||
@ -459,7 +459,7 @@ class FormTypeTest extends TypeTestCase
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'by_reference' => false
|
||||
));
|
||||
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||
$builder->get('referenceCopy')->add('firstName', 'text');
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
|
@ -21,7 +21,7 @@ class RepeatedTypeTest extends TypeTestCase
|
||||
parent::setUp();
|
||||
|
||||
$this->form = $this->factory->create('repeated', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
));
|
||||
$this->form->setData(null);
|
||||
}
|
||||
@ -37,7 +37,7 @@ class RepeatedTypeTest extends TypeTestCase
|
||||
public function testSetOptions()
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
'options' => array('label' => 'Global'),
|
||||
));
|
||||
|
||||
@ -51,7 +51,7 @@ class RepeatedTypeTest extends TypeTestCase
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
// the global required value cannot be overriden
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
'first_options' => array('label' => 'Test', 'required' => false),
|
||||
'second_options' => array('label' => 'Test2')
|
||||
));
|
||||
@ -66,7 +66,7 @@ class RepeatedTypeTest extends TypeTestCase
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
'required' => false,
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
));
|
||||
|
||||
$this->assertFalse($form['first']->isRequired());
|
||||
@ -76,7 +76,7 @@ class RepeatedTypeTest extends TypeTestCase
|
||||
public function testSetOptionsPerChildAndOverwrite()
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
'type' => 'form',
|
||||
'type' => 'text',
|
||||
'options' => array('label' => 'Label'),
|
||||
'second_options' => array('label' => 'Second label')
|
||||
));
|
||||
|
@ -148,12 +148,14 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
|
||||
->will($this->returnValue($valid));
|
||||
|
||||
$form = $this->factory
|
||||
->create('form', null, array(
|
||||
->createBuilder('form', null, array(
|
||||
'csrf_field_name' => 'csrf',
|
||||
'csrf_provider' => $this->csrfProvider,
|
||||
'intention' => '%INTENTION%',
|
||||
'compound' => true,
|
||||
));
|
||||
))
|
||||
->add('child', 'text')
|
||||
->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
'child' => 'foobar',
|
||||
@ -173,12 +175,14 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
|
||||
->method('isCsrfTokenValid');
|
||||
|
||||
$form = $this->factory
|
||||
->create('form', null, array(
|
||||
->createBuilder('form', null, array(
|
||||
'csrf_field_name' => 'csrf',
|
||||
'csrf_provider' => $this->csrfProvider,
|
||||
'intention' => '%INTENTION%',
|
||||
'compound' => true,
|
||||
));
|
||||
))
|
||||
->add('child', 'text')
|
||||
->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
'child' => 'foobar',
|
||||
|
@ -31,8 +31,6 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
private $factory;
|
||||
|
||||
private $builder;
|
||||
|
||||
private $form;
|
||||
|
||||
protected function setUp()
|
||||
@ -279,14 +277,15 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testValidIfBound()
|
||||
{
|
||||
$this->form->bind('foobar');
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
$form->bind('foobar');
|
||||
|
||||
$this->assertTrue($this->form->isValid());
|
||||
$this->assertTrue($form->isValid());
|
||||
}
|
||||
|
||||
public function testValidIfBoundAndDisabled()
|
||||
{
|
||||
$form = $this->getBuilder()->setDisabled(true)->getForm();
|
||||
$form = $this->getBuilder()->setCompound(false)->setDisabled(true)->getForm();
|
||||
$form->bind('foobar');
|
||||
|
||||
$this->assertTrue($form->isValid());
|
||||
@ -318,10 +317,11 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testNotValidIfErrors()
|
||||
{
|
||||
$this->form->bind('foobar');
|
||||
$this->form->addError(new FormError('Error!'));
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
$form->bind('foobar');
|
||||
$form->addError(new FormError('Error!'));
|
||||
|
||||
$this->assertFalse($this->form->isValid());
|
||||
$this->assertFalse($form->isValid());
|
||||
}
|
||||
|
||||
public function testNotValidIfChildNotValid()
|
||||
@ -403,7 +403,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testRemoveThrowsExceptionIfAlreadyBound()
|
||||
{
|
||||
$this->form->add($this->getBuilder('foo')->getForm());
|
||||
$this->form->add($this->getBuilder('foo')->setCompound(false)->getForm());
|
||||
$this->form->bind(array('foo' => 'bar'));
|
||||
$this->form->remove('foo');
|
||||
}
|
||||
@ -445,9 +445,10 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testBound()
|
||||
{
|
||||
$this->form->bind('foobar');
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
$form->bind('foobar');
|
||||
|
||||
$this->assertTrue($this->form->isBound());
|
||||
$this->assertTrue($form->isBound());
|
||||
}
|
||||
|
||||
public function testNotBound()
|
||||
@ -586,7 +587,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testSetDataConvertsNullToStringIfNoTransformer()
|
||||
{
|
||||
$form = $this->getBuilder()->getForm();
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
|
||||
$form->setData(null);
|
||||
|
||||
@ -597,7 +598,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testBindConvertsEmptyToNullIfNoTransformer()
|
||||
{
|
||||
$form = $this->getBuilder()->getForm();
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
|
||||
$form->bind('');
|
||||
|
||||
@ -641,6 +642,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
public function testBindExecutesViewTransformersInReverseOrder()
|
||||
{
|
||||
$form = $this->getBuilder()
|
||||
->setCompound(false)
|
||||
->addViewTransformer(new FixedDataTransformer(array(
|
||||
'' => '',
|
||||
'third' => 'second',
|
||||
@ -659,6 +661,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
public function testBindExecutesModelTransformersInOrder()
|
||||
{
|
||||
$form = $this->getBuilder()
|
||||
->setCompound(false)
|
||||
->addModelTransformer(new FixedDataTransformer(array(
|
||||
'' => '',
|
||||
'second' => 'first',
|
||||
@ -681,9 +684,10 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testSynchronizedAfterBinding()
|
||||
{
|
||||
$this->form->bind('foobar');
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
$form->bind('foobar');
|
||||
|
||||
$this->assertTrue($this->form->isSynchronized());
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
public function testNotSynchronizedIfTransformationFailed()
|
||||
@ -694,6 +698,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
->will($this->throwException(new TransformationFailedException()));
|
||||
|
||||
$form = $this->getBuilder()
|
||||
->setCompound(false)
|
||||
->addViewTransformer($transformer)
|
||||
->getForm();
|
||||
|
||||
@ -705,6 +710,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
public function testEmptyDataCreatedBeforeTransforming()
|
||||
{
|
||||
$form = $this->getBuilder()
|
||||
->setCompound(false)
|
||||
->setEmptyData('foo')
|
||||
->addViewTransformer(new FixedDataTransformer(array(
|
||||
'' => '',
|
||||
@ -722,6 +728,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$test = $this;
|
||||
$form = $this->getBuilder()
|
||||
->setCompound(false)
|
||||
->setEmptyData(function ($form) use ($test) {
|
||||
// the form instance is passed to the closure to allow use
|
||||
// of form data when creating the empty value
|
||||
@ -795,8 +802,8 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
->setData('foo')
|
||||
->getForm();
|
||||
|
||||
$form->add($child1 = $this->getBuilder('firstName')->getForm());
|
||||
$form->add($child2 = $this->getBuilder('lastName')->getForm());
|
||||
$form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm());
|
||||
$form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm());
|
||||
|
||||
$mapper->expects($this->once())
|
||||
->method('mapFormsToData')
|
||||
@ -812,9 +819,25 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
));
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/symfony/symfony/issues/4480
|
||||
*/
|
||||
public function testBindRestoresViewDataIfCompoundAndEmpty()
|
||||
{
|
||||
$mapper = $this->getDataMapper();
|
||||
$object = new \stdClass();
|
||||
$form = $this->getBuilder('name', null, 'stdClass')
|
||||
->setDataMapper($mapper)
|
||||
->setData($object)
|
||||
->getForm();
|
||||
|
||||
$form->bind(array());
|
||||
|
||||
$this->assertSame($object, $form->getData());
|
||||
}
|
||||
|
||||
public function testBindMapsBoundChildrenOntoEmptyData()
|
||||
{
|
||||
$test = $this;
|
||||
$mapper = $this->getDataMapper();
|
||||
$object = new \stdClass();
|
||||
$form = $this->getBuilder()
|
||||
@ -823,7 +846,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
->setData(null)
|
||||
->getForm();
|
||||
|
||||
$form->add($child = $this->getBuilder('name')->getForm());
|
||||
$form->add($child = $this->getBuilder('name')->setCompound(false)->getForm());
|
||||
|
||||
$mapper->expects($this->once())
|
||||
->method('mapFormsToData')
|
||||
@ -839,6 +862,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
$test = $this;
|
||||
$validator = $this->getFormValidator();
|
||||
$form = $this->getBuilder()
|
||||
->setCompound(false)
|
||||
->addValidator($validator)
|
||||
->getForm();
|
||||
|
||||
@ -896,8 +920,8 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
));
|
||||
|
||||
$form = $this->getBuilder('author')->getForm();
|
||||
$form->add($this->getBuilder('name')->getForm());
|
||||
$form->add($this->getBuilder('image')->getForm());
|
||||
$form->add($this->getBuilder('name')->setCompound(false)->getForm());
|
||||
$form->add($this->getBuilder('image')->setCompound(false)->getForm());
|
||||
|
||||
$form->bindRequest($request);
|
||||
|
||||
@ -941,8 +965,8 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
));
|
||||
|
||||
$form = $this->getBuilder('')->getForm();
|
||||
$form->add($this->getBuilder('name')->getForm());
|
||||
$form->add($this->getBuilder('image')->getForm());
|
||||
$form->add($this->getBuilder('name')->setCompound(false)->getForm());
|
||||
$form->add($this->getBuilder('image')->setCompound(false)->getForm());
|
||||
|
||||
$form->bindRequest($request);
|
||||
|
||||
@ -981,7 +1005,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => $method,
|
||||
));
|
||||
|
||||
$form = $this->getBuilder('image')->getForm();
|
||||
$form = $this->getBuilder('image')->setCompound(false)->getForm();
|
||||
|
||||
$form->bindRequest($request);
|
||||
|
||||
@ -1012,7 +1036,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => $method,
|
||||
));
|
||||
|
||||
$form = $this->getBuilder('name')->getForm();
|
||||
$form = $this->getBuilder('name')->setCompound(false)->getForm();
|
||||
|
||||
$form->bindRequest($request);
|
||||
|
||||
@ -1039,8 +1063,8 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
));
|
||||
|
||||
$form = $this->getBuilder('author')->getForm();
|
||||
$form->add($this->getBuilder('firstName')->getForm());
|
||||
$form->add($this->getBuilder('lastName')->getForm());
|
||||
$form->add($this->getBuilder('firstName')->setCompound(false)->getForm());
|
||||
$form->add($this->getBuilder('lastName')->setCompound(false)->getForm());
|
||||
|
||||
$form->bindRequest($request);
|
||||
|
||||
@ -1065,8 +1089,8 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
));
|
||||
|
||||
$form = $this->getBuilder('')->getForm();
|
||||
$form->add($this->getBuilder('firstName')->getForm());
|
||||
$form->add($this->getBuilder('lastName')->getForm());
|
||||
$form->add($this->getBuilder('firstName')->setCompound(false)->getForm());
|
||||
$form->add($this->getBuilder('lastName')->setCompound(false)->getForm());
|
||||
|
||||
$form->bindRequest($request);
|
||||
|
||||
@ -1077,7 +1101,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testBindResetsErrors()
|
||||
{
|
||||
$form = $this->getBuilder()->getForm();
|
||||
$form = $this->getBuilder()->setCompound(false)->getForm();
|
||||
$form->addError(new FormError('Error!'));
|
||||
$form->bind('foobar');
|
||||
|
||||
|
@ -52,6 +52,11 @@ class UnmodifiableFormConfig implements FormConfigInterface
|
||||
*/
|
||||
private $virtual;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $compound;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@ -135,6 +140,7 @@ class UnmodifiableFormConfig implements FormConfigInterface
|
||||
$this->mapped = $config->getMapped();
|
||||
$this->byReference = $config->getByReference();
|
||||
$this->virtual = $config->getVirtual();
|
||||
$this->compound = $config->getCompound();
|
||||
$this->types = $config->getTypes();
|
||||
$this->clientTransformers = $config->getViewTransformers();
|
||||
$this->normTransformers = $config->getModelTransformers();
|
||||
@ -198,6 +204,14 @@ class UnmodifiableFormConfig implements FormConfigInterface
|
||||
return $this->virtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCompound()
|
||||
{
|
||||
return $this->compound;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
Reference in New Issue
Block a user