Skip to content

Commit d9703d6

Browse files
committed
[Form] Added entry_filter option to collection type.
1 parent bafa8e2 commit d9703d6

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Form\FormEvent;
1616
use Symfony\Component\Form\Exception\UnexpectedTypeException;
1717
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18+
use Symfony\Component\Form\FormInterface;
1819

1920
/**
2021
* Resize a collection form element based on the data sent from the client.
@@ -52,13 +53,19 @@ class ResizeFormListener implements EventSubscriberInterface
5253
*/
5354
private $deleteEmpty;
5455

55-
public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false, $deleteEmpty = false)
56+
/**
57+
* @var callable|null
58+
*/
59+
private $entryFilter;
60+
61+
public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false, $deleteEmpty = false, callable $entryFilter = null)
5662
{
5763
$this->type = $type;
5864
$this->allowAdd = $allowAdd;
5965
$this->allowDelete = $allowDelete;
6066
$this->options = $options;
6167
$this->deleteEmpty = $deleteEmpty;
68+
$this->entryFilter = $entryFilter;
6269
}
6370

6471
public static function getSubscribedEvents()
@@ -149,13 +156,16 @@ public function onSubmit(FormEvent $event)
149156
}
150157

151158
if ($this->deleteEmpty) {
152-
$previousData = $event->getForm()->getData();
159+
$previousData = $form->getData();
160+
$entryFilter = $this->entryFilter;
153161
foreach ($form as $name => $child) {
162+
/* @var $child FormInterface */
154163
$isNew = !isset($previousData[$name]);
164+
$needRemove = $child->isEmpty() || (null !== $entryFilter && !$entryFilter($child->getData()));
155165

156166
// $isNew can only be true if allowAdd is true, so we don't
157167
// need to check allowAdd again
158-
if ($child->isEmpty() && ($isNew || $this->allowDelete)) {
168+
if ($needRemove && ($isNew || $this->allowDelete)) {
159169
unset($data[$name]);
160170
$form->remove($name);
161171
}

src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public function buildForm(FormBuilderInterface $builder, array $options)
4545
$options['entry_options'],
4646
$options['allow_add'],
4747
$options['allow_delete'],
48-
$options['delete_empty']
48+
$options['delete_empty'],
49+
$options['entry_filter']
4950
);
5051

5152
$builder->addEventSubscriber($resizeListener);
@@ -96,10 +97,12 @@ public function configureOptions(OptionsResolver $resolver)
9697
'prototype_name' => '__name__',
9798
'entry_type' => __NAMESPACE__.'\TextType',
9899
'entry_options' => array(),
100+
'entry_filter' => null,
99101
'delete_empty' => false,
100102
));
101103

102104
$resolver->setNormalizer('entry_options', $entryOptionsNormalizer);
105+
$resolver->setAllowedTypes('entry_filter', array('null', 'callable'));
103106
}
104107

105108
/**

src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ public function testResizedDownIfSubmittedWithEmptyDataAndDeleteEmpty()
110110
$this->assertEquals(array('foo@foo.com'), $form->getData());
111111
}
112112

113+
public function testResizedDownWithEntryFilter()
114+
{
115+
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\CollectionType', null, array(
116+
'entry_type' => 'Symfony\Component\Form\Tests\Fixtures\AuthorType',
117+
'allow_delete' => true,
118+
'delete_empty' => true,
119+
'entry_filter' => function ($obj) {
120+
return $obj instanceof Author && !empty($obj->firstName);
121+
},
122+
));
123+
124+
$form->setData(array(new Author('Bob'), new Author('Alice')));
125+
$form->submit(array(array('firstName' => 'Bob'), array('firstName' => '')));
126+
127+
$this->assertTrue($form->has('0'));
128+
$this->assertFalse($form->has('1'));
129+
$this->assertEquals(new Author('Bob'), $form[0]->getData());
130+
$this->assertEquals(array(new Author('Bob')), $form->getData());
131+
}
132+
113133
public function testDontAddEmptyDataIfDeleteEmpty()
114134
{
115135
$form = $this->factory->create(static::TESTED_TYPE, null, array(

src/Symfony/Component/Form/Tests/FormErrorIteratorTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111

1212
namespace Symfony\Component\Form\Tests;
1313

14+
use PHPUnit\Framework\TestCase;
1415
use Symfony\Component\EventDispatcher\EventDispatcher;
1516
use Symfony\Component\Form\FormBuilder;
1617
use Symfony\Component\Form\FormError;
1718
use Symfony\Component\Form\FormErrorIterator;
1819
use Symfony\Component\Validator\ConstraintViolation;
1920

20-
class FormErrorIteratorTest extends \PHPUnit_Framework_TestCase
21+
class FormErrorIteratorTest extends TestCase
2122
{
2223
/**
2324
* @dataProvider findByCodesProvider
@@ -32,7 +33,7 @@ public function testFindByCodes($code, $violationsCount)
3233
'form',
3334
null,
3435
new EventDispatcher(),
35-
$this->getMock('Symfony\Component\Form\FormFactoryInterface'),
36+
$this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(),
3637
array()
3738
);
3839

0 commit comments

Comments
 (0)