feature #20496 [Form] Allow pass filter callback to delete_empty option. (Koc)
This PR was merged into the 3.4 branch.
Discussion
----------
[Form] Allow pass filter callback to delete_empty option.
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | yes
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #13601, #13940, #22008, #22014
| License | MIT
| Doc PR | coming soon
Commits
-------
8630abe27a
[Form] Allow pass filter callback to delete_empty option.
This commit is contained in:
commit
c0d99d13c0
@ -48,7 +48,7 @@ class ResizeFormListener implements EventSubscriberInterface
|
|||||||
protected $allowDelete;
|
protected $allowDelete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool|callable
|
||||||
*/
|
*/
|
||||||
private $deleteEmpty;
|
private $deleteEmpty;
|
||||||
|
|
||||||
@ -148,14 +148,15 @@ class ResizeFormListener implements EventSubscriberInterface
|
|||||||
throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
|
throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->deleteEmpty) {
|
if ($entryFilter = $this->deleteEmpty) {
|
||||||
$previousData = $event->getForm()->getData();
|
$previousData = $form->getData();
|
||||||
foreach ($form as $name => $child) {
|
foreach ($form as $name => $child) {
|
||||||
$isNew = !isset($previousData[$name]);
|
$isNew = !isset($previousData[$name]);
|
||||||
|
$isEmpty = is_callable($entryFilter) ? $entryFilter($child->getData()) : $child->isEmpty();
|
||||||
|
|
||||||
// $isNew can only be true if allowAdd is true, so we don't
|
// $isNew can only be true if allowAdd is true, so we don't
|
||||||
// need to check allowAdd again
|
// need to check allowAdd again
|
||||||
if ($child->isEmpty() && ($isNew || $this->allowDelete)) {
|
if ($isEmpty && ($isNew || $this->allowDelete)) {
|
||||||
unset($data[$name]);
|
unset($data[$name]);
|
||||||
$form->remove($name);
|
$form->remove($name);
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,7 @@ class CollectionType extends AbstractType
|
|||||||
));
|
));
|
||||||
|
|
||||||
$resolver->setNormalizer('entry_options', $entryOptionsNormalizer);
|
$resolver->setNormalizer('entry_options', $entryOptionsNormalizer);
|
||||||
|
$resolver->setAllowedTypes('delete_empty', array('bool', 'callable'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
||||||
|
|
||||||
use Symfony\Component\Form\Tests\Fixtures\Author;
|
use Symfony\Component\Form\Tests\Fixtures\Author;
|
||||||
|
use Symfony\Component\Form\Tests\Fixtures\AuthorType;
|
||||||
|
|
||||||
class CollectionTypeTest extends BaseTypeTest
|
class CollectionTypeTest extends BaseTypeTest
|
||||||
{
|
{
|
||||||
@ -110,6 +111,49 @@ class CollectionTypeTest extends BaseTypeTest
|
|||||||
$this->assertEquals(array('foo@foo.com'), $form->getData());
|
$this->assertEquals(array('foo@foo.com'), $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testResizedDownWithDeleteEmptyCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||||
|
'entry_type' => AuthorType::class,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'delete_empty' => function (Author $obj = null) {
|
||||||
|
return null === $obj || empty($obj->firstName);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
$form->setData(array(new Author('Bob'), new Author('Alice')));
|
||||||
|
$form->submit(array(array('firstName' => 'Bob'), array('firstName' => '')));
|
||||||
|
|
||||||
|
$this->assertTrue($form->has('0'));
|
||||||
|
$this->assertFalse($form->has('1'));
|
||||||
|
$this->assertEquals(new Author('Bob'), $form[0]->getData());
|
||||||
|
$this->assertEquals(array(new Author('Bob')), $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResizedDownIfSubmittedWithCompoundEmptyDataDeleteEmptyAndNoDataClass()
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||||
|
'entry_type' => AuthorType::class,
|
||||||
|
// If the field is not required, no new Author will be created if the
|
||||||
|
// form is completely empty
|
||||||
|
'entry_options' => array('data_class' => null),
|
||||||
|
'allow_add' => true,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'delete_empty' => function ($author) {
|
||||||
|
return empty($author['firstName']);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
$form->setData(array(array('firstName' => 'first', 'lastName' => 'last')));
|
||||||
|
$form->submit(array(
|
||||||
|
array('firstName' => 's_first', 'lastName' => 's_last'),
|
||||||
|
array('firstName' => '', 'lastName' => ''),
|
||||||
|
));
|
||||||
|
$this->assertTrue($form->has('0'));
|
||||||
|
$this->assertFalse($form->has('1'));
|
||||||
|
$this->assertEquals(array('firstName' => 's_first', 'lastName' => 's_last'), $form[0]->getData());
|
||||||
|
$this->assertEquals(array(array('firstName' => 's_first', 'lastName' => 's_last')), $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
public function testDontAddEmptyDataIfDeleteEmpty()
|
public function testDontAddEmptyDataIfDeleteEmpty()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||||
|
Reference in New Issue
Block a user