[Form] Split the option "modifiable" of the "collection" type into "allow_add" and "allow_delete"
This commit is contained in:
parent
bf1dfbbe99
commit
3cc5d9f4cd
18
UPDATE.md
18
UPDATE.md
@ -89,6 +89,24 @@ beta1 to beta2
|
||||
|
||||
app/Resources/translations/catalogue.fr.xml
|
||||
|
||||
* The option "modifiable" of the "collection" form type was split into two
|
||||
options "allow_add" and "allow_delete".
|
||||
|
||||
Before:
|
||||
|
||||
$builder->add('tags', 'collection', array(
|
||||
'type' => 'text',
|
||||
'modifiable' => true,
|
||||
));
|
||||
|
||||
After:
|
||||
|
||||
$builder->add('tags', 'collection', array(
|
||||
'type' => 'text',
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
));
|
||||
|
||||
PR12 to beta1
|
||||
-------------
|
||||
|
||||
|
@ -38,13 +38,14 @@ class ResizeFormListener implements EventSubscriberInterface
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $resizeOnBind;
|
||||
private $allowAdd;
|
||||
|
||||
public function __construct(FormFactoryInterface $factory, $type, $resizeOnBind = false)
|
||||
public function __construct(FormFactoryInterface $factory, $type, $allowAdd = false, $allowDelete = false)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
$this->type = $type;
|
||||
$this->resizeOnBind = $resizeOnBind;
|
||||
$this->allowAdd = $allowAdd;
|
||||
$this->allowDelete = $allowDelete;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
@ -71,7 +72,7 @@ class ResizeFormListener implements EventSubscriberInterface
|
||||
|
||||
// First remove all rows except for the prototype row
|
||||
foreach ($form as $name => $child) {
|
||||
if (!($this->resizeOnBind && '$$name$$' === $name)) {
|
||||
if (!($this->allowAdd && '$$name$$' === $name)) {
|
||||
$form->remove($name);
|
||||
}
|
||||
}
|
||||
@ -86,10 +87,6 @@ class ResizeFormListener implements EventSubscriberInterface
|
||||
|
||||
public function preBind(DataEvent $event)
|
||||
{
|
||||
if (!$this->resizeOnBind) {
|
||||
return;
|
||||
}
|
||||
|
||||
$form = $event->getForm();
|
||||
$data = $event->getData();
|
||||
|
||||
@ -102,13 +99,16 @@ class ResizeFormListener implements EventSubscriberInterface
|
||||
}
|
||||
|
||||
// Remove all empty rows except for the prototype row
|
||||
if ($this->allowDelete) {
|
||||
foreach ($form as $name => $child) {
|
||||
if (!isset($data[$name]) && '$$name$$' !== $name) {
|
||||
$form->remove($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add all additional rows
|
||||
if ($this->allowAdd) {
|
||||
foreach ($data as $name => $value) {
|
||||
if (!$form->has($name)) {
|
||||
$form->add($this->factory->createNamed($this->type, $name, null, array(
|
||||
@ -117,13 +117,10 @@ class ResizeFormListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onBindNormData(FilterDataEvent $event)
|
||||
{
|
||||
if (!$this->resizeOnBind) {
|
||||
return;
|
||||
}
|
||||
|
||||
$form = $event->getForm();
|
||||
$data = $event->getData();
|
||||
|
||||
@ -135,11 +132,13 @@ class ResizeFormListener implements EventSubscriberInterface
|
||||
throw new UnexpectedTypeException($data, 'array or \Traversable');
|
||||
}
|
||||
|
||||
if ($this->allowDelete) {
|
||||
foreach ($data as $name => $child) {
|
||||
if (!$form->has($name)) {
|
||||
unset($data[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$event->setData($data);
|
||||
}
|
||||
|
@ -13,13 +13,15 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
|
||||
|
||||
class CollectionType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
if ($options['modifiable'] && $options['prototype']) {
|
||||
if ($options['allow_add'] && $options['prototype']) {
|
||||
$builder->add('$$name$$', $options['type'], array(
|
||||
'property_path' => false,
|
||||
'required' => false,
|
||||
@ -27,15 +29,24 @@ class CollectionType extends AbstractType
|
||||
}
|
||||
|
||||
$listener = new ResizeFormListener($builder->getFormFactory(),
|
||||
$options['type'], $options['modifiable']);
|
||||
$options['type'], $options['allow_add'], $options['allow_delete']);
|
||||
|
||||
$builder->addEventSubscriber($listener);
|
||||
$builder->addEventSubscriber($listener)
|
||||
->setAttribute('allow_add', $options['allow_add'])
|
||||
->setAttribute('allow_delete', $options['allow_delete']);
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form)
|
||||
{
|
||||
$view->set('allow_add', $form->getAttribute('allow_add'));
|
||||
$view->set('allow_delete', $form->getAttribute('allow_delete'));
|
||||
}
|
||||
|
||||
public function getDefaultOptions(array $options)
|
||||
{
|
||||
return array(
|
||||
'modifiable' => false,
|
||||
'allow_add' => false,
|
||||
'allow_delete' => false,
|
||||
'prototype' => true,
|
||||
'type' => 'text',
|
||||
);
|
||||
|
@ -59,7 +59,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$data = array(1 => 'string', 2 => 'string');
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->preSetData($event);
|
||||
|
||||
$this->assertFalse($this->form->has('0'));
|
||||
@ -67,25 +67,25 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue($this->form->has('2'));
|
||||
}
|
||||
|
||||
public function testPreSetDataRemovesPrototypeRowIfNotResizeOnBind()
|
||||
public function testPreSetDataRemovesPrototypeRowIfNotAllowAdd()
|
||||
{
|
||||
$this->form->add($this->getForm('$$name$$'));
|
||||
|
||||
$data = array();
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->preSetData($event);
|
||||
|
||||
$this->assertFalse($this->form->has('$$name$$'));
|
||||
}
|
||||
|
||||
public function testPreSetDataDoesNotRemovePrototypeRowIfResizeOnBind()
|
||||
public function testPreSetDataDoesNotRemovePrototypeRowIfAllowAdd()
|
||||
{
|
||||
$this->form->add($this->getForm('$$name$$'));
|
||||
|
||||
$data = array();
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true, false);
|
||||
$listener->preSetData($event);
|
||||
|
||||
$this->assertTrue($this->form->has('$$name$$'));
|
||||
@ -98,7 +98,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$data = 'no array or traversable';
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->preSetData($event);
|
||||
}
|
||||
|
||||
@ -108,28 +108,40 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$data = null;
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->preSetData($event);
|
||||
}
|
||||
|
||||
public function testPreBindResizesFormIfResizable()
|
||||
public function testPreBindResizesUpIfAllowAdd()
|
||||
{
|
||||
$this->form->add($this->getForm('0'));
|
||||
|
||||
$this->factory->expects($this->once())
|
||||
->method('createNamed')
|
||||
->with('text', 1, null, array('property_path' => '[1]'))
|
||||
->will($this->returnValue($this->getForm('1')));
|
||||
|
||||
$data = array(0 => 'string', 1 => 'string');
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true, false);
|
||||
$listener->preBind($event);
|
||||
|
||||
$this->assertTrue($this->form->has('0'));
|
||||
$this->assertTrue($this->form->has('1'));
|
||||
}
|
||||
|
||||
public function testPreBindResizesDownIfAllowDelete()
|
||||
{
|
||||
$this->form->add($this->getForm('0'));
|
||||
$this->form->add($this->getForm('1'));
|
||||
|
||||
$this->factory->expects($this->once())
|
||||
->method('createNamed')
|
||||
->with('text', 2, null, array('property_path' => '[2]'))
|
||||
->will($this->returnValue($this->getForm('2')));
|
||||
|
||||
$data = array(0 => 'string', 2 => 'string');
|
||||
$data = array(0 => 'string');
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, true);
|
||||
$listener->preBind($event);
|
||||
|
||||
$this->assertTrue($this->form->has('0'));
|
||||
$this->assertFalse($this->form->has('1'));
|
||||
$this->assertTrue($this->form->has('2'));
|
||||
}
|
||||
|
||||
// fix for https://github.com/symfony/symfony/pull/493
|
||||
@ -139,20 +151,20 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$data = array();
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, true);
|
||||
$listener->preBind($event);
|
||||
|
||||
$this->assertFalse($this->form->has('0'));
|
||||
}
|
||||
|
||||
public function testPreBindDoesNothingIfNotResizable()
|
||||
public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete()
|
||||
{
|
||||
$this->form->add($this->getForm('0'));
|
||||
$this->form->add($this->getForm('1'));
|
||||
|
||||
$data = array(0 => 'string', 2 => 'string');
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->preBind($event);
|
||||
|
||||
$this->assertTrue($this->form->has('0'));
|
||||
@ -167,7 +179,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$data = 'no array or traversable';
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->preBind($event);
|
||||
}
|
||||
|
||||
@ -177,7 +189,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$data = null;
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, true);
|
||||
$listener->preBind($event);
|
||||
|
||||
$this->assertFalse($this->form->has('1'));
|
||||
@ -190,31 +202,31 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$data = '';
|
||||
$event = new DataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, true);
|
||||
$listener->preBind($event);
|
||||
|
||||
$this->assertFalse($this->form->has('1'));
|
||||
}
|
||||
|
||||
public function testOnBindNormDataRemovesEntriesMissingInTheFormIfResizable()
|
||||
public function testOnBindNormDataRemovesEntriesMissingInTheFormIfAllowDelete()
|
||||
{
|
||||
$this->form->add($this->getForm('1'));
|
||||
|
||||
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
|
||||
$event = new FilterDataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, true);
|
||||
$listener->onBindNormData($event);
|
||||
|
||||
$this->assertEquals(array(1 => 'second'), $event->getData());
|
||||
}
|
||||
|
||||
public function testOnBindNormDataDoesNothingIfNotResizable()
|
||||
public function testOnBindNormDataDoesNothingIfNotAllowDelete()
|
||||
{
|
||||
$this->form->add($this->getForm('1'));
|
||||
|
||||
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
|
||||
$event = new FilterDataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->onBindNormData($event);
|
||||
|
||||
$this->assertEquals($data, $event->getData());
|
||||
@ -227,7 +239,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$data = 'no array or traversable';
|
||||
$event = new FilterDataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, false);
|
||||
$listener->onBindNormData($event);
|
||||
}
|
||||
|
||||
@ -237,7 +249,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$data = null;
|
||||
$event = new FilterDataEvent($this->form, $data);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', true);
|
||||
$listener = new ResizeFormListener($this->factory, 'text', false, true);
|
||||
$listener->onBindNormData($event);
|
||||
|
||||
$this->assertEquals(array(), $event->getData());
|
||||
|
@ -45,15 +45,15 @@ class CollectionFormTest extends TypeTestCase
|
||||
$this->assertEquals('foo@baz.com', $form[0]->getData());
|
||||
}
|
||||
|
||||
public function testSetDataAdjustsSizeIfModifiable()
|
||||
public function testSetDataAddsPrototypeIfAllowAdd()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'modifiable' => true,
|
||||
'allow_add' => true,
|
||||
'prototype' => true,
|
||||
));
|
||||
$form->setData(array('foo@foo.com', 'foo@bar.com'));
|
||||
|
||||
$form->setData(array('foo@foo.com', 'foo@bar.com'));
|
||||
$this->assertTrue($form[0] instanceof Form);
|
||||
$this->assertTrue($form[1] instanceof Form);
|
||||
$this->assertTrue($form['$$name$$'] instanceof Form);
|
||||
@ -75,20 +75,6 @@ class CollectionFormTest extends TypeTestCase
|
||||
$form->setData(new \stdClass());
|
||||
}
|
||||
|
||||
public function testModifiableCollectionsContainExtraForm()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'modifiable' => true,
|
||||
'prototype' => true,
|
||||
));
|
||||
$form->setData(array('foo@bar.com'));
|
||||
|
||||
$this->assertTrue($form['0'] instanceof Form);
|
||||
$this->assertTrue($form['$$name$$'] instanceof Form);
|
||||
$this->assertEquals(2, count($form));
|
||||
}
|
||||
|
||||
public function testNotResizedIfBoundWithMissingData()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
@ -103,11 +89,11 @@ class CollectionFormTest extends TypeTestCase
|
||||
$this->assertEquals(null, $form[1]->getData());
|
||||
}
|
||||
|
||||
public function testResizedIfBoundWithMissingDataAndModifiable()
|
||||
public function testResizedDownIfBoundWithMissingDataAndAllowDelete()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'modifiable' => true,
|
||||
'allow_delete' => true,
|
||||
));
|
||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||
$form->bind(array('foo@bar.com'));
|
||||
@ -115,6 +101,7 @@ class CollectionFormTest extends TypeTestCase
|
||||
$this->assertTrue($form->has('0'));
|
||||
$this->assertFalse($form->has('1'));
|
||||
$this->assertEquals('foo@bar.com', $form[0]->getData());
|
||||
$this->assertEquals(array('foo@bar.com'), $form->getData());
|
||||
}
|
||||
|
||||
public function testNotResizedIfBoundWithExtraData()
|
||||
@ -130,11 +117,11 @@ class CollectionFormTest extends TypeTestCase
|
||||
$this->assertEquals('foo@foo.com', $form[0]->getData());
|
||||
}
|
||||
|
||||
public function testResizedUpIfBoundWithExtraDataAndModifiable()
|
||||
public function testResizedUpIfBoundWithExtraDataAndAllowAdd()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'modifiable' => true,
|
||||
'allow_add' => true,
|
||||
));
|
||||
$form->setData(array('foo@bar.com'));
|
||||
$form->bind(array('foo@foo.com', 'bar@bar.com'));
|
||||
@ -146,29 +133,14 @@ class CollectionFormTest extends TypeTestCase
|
||||
$this->assertEquals(array('foo@foo.com', 'bar@bar.com'), $form->getData());
|
||||
}
|
||||
|
||||
public function testModifableButNoPrototype()
|
||||
public function testAllowAddButNoPrototype()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'modifiable' => true,
|
||||
'allow_add' => true,
|
||||
'prototype' => false,
|
||||
));
|
||||
|
||||
$this->assertFalse($form->has('$$name$$'));
|
||||
}
|
||||
|
||||
public function testResizedDownIfBoundWithLessDataAndModifiable()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'modifiable' => true,
|
||||
));
|
||||
$form->setData(array('foo@bar.com', 'bar@bar.com'));
|
||||
$form->bind(array('foo@foo.com'));
|
||||
|
||||
$this->assertTrue($form->has('0'));
|
||||
$this->assertFalse($form->has('1'));
|
||||
$this->assertEquals('foo@foo.com', $form[0]->getData());
|
||||
$this->assertEquals(array('foo@foo.com'), $form->getData());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user