Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fc251db

Browse filesBrowse files
committed
bug #10410 [Form] Fix "Array was modified outside object" in ResizeFormListener. (Chekote)
This PR was squashed before being merged into the 2.3 branch (closes #10410). Discussion ---------- [Form] Fix "Array was modified outside object" in ResizeFormListener. | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #10405 | License | MIT | Doc PR | This is the second pull request for this issue. The history of this is as follows: Original Fix was added Feb 11th under Pull Request #10232. Users began complaining of Doctrine ArrayCollection not being updated in forms. Revert was added Feb 15th under Pull Request #10269. Issue #10405 was opened on 7th Mar for the original bug. Pull Request #10269 has a failing test that illustrates users concerns. I have added failing tests to this pull request to illustrate the problems described in #10405. All tests now pass, and all forms of $data are now supported, including arrays, DoctrineCollection, ArrayObject, and other IteratorAggregates. __Details as follows:__ The onSubmit() method of the ResizeFormListener class is assuming the data is an array, and calling unset directly inside a foreach. This works fine in most scenarios, but if data is an instance of IteratorAggregate that is iterating over $data by reference, it breaks with the following error: Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener::onSubmit(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in ./vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php line 142 This is because the foreach loop is using an Iterator in the background, but the ResizeFormListener has unset the underlying data directly, causing the value that the Iterators internal pointer is pointing to to change. The Iterator provided by IteratorAggregate may or may not have the ability to modify it's underlying data. So it is not possible to rely on the Iterator to modify the data. Instead, it is simpler to avoid modifying $data at all while we are iterating over it. So instead, we simply iterate over $data once to determine the keys we need to delete, and store them. Then we iterate over the keys and delete them from $data. Commits ------- aa63fae [Form] Fix "Array was modified outside object" in ResizeFormListener.
2 parents 65f0242 + aa63fae commit fc251db
Copy full SHA for fc251db

File tree

Expand file treeCollapse file tree

2 files changed

+21
-2
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+21
-2
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,17 @@ public function onSubmit(FormEvent $event)
139139
// The data mapper only adds, but does not remove items, so do this
140140
// here
141141
if ($this->allowDelete) {
142+
$toDelete = array();
143+
142144
foreach ($data as $name => $child) {
143145
if (!$form->has($name)) {
144-
unset($data[$name]);
146+
$toDelete[] = $name;
145147
}
146148
}
149+
150+
foreach ($toDelete as $name) {
151+
unset($data[$name]);
152+
}
147153
}
148154

149155
$event->setData($data);

‎src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php
+14-1Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,20 @@ public function testOnSubmitNormDataDealsWithNullData()
254254
$this->assertEquals(array(), $event->getData());
255255
}
256256

257-
public function testOnSubmitDealsWithIteratorAggregate()
257+
public function testOnSubmitDealsWithObjectBackedIteratorAggregate()
258+
{
259+
$this->form->add($this->getForm('1'));
260+
261+
$data = new \ArrayObject(array(0 => 'first', 1 => 'second', 2 => 'third'));
262+
$event = new FormEvent($this->form, $data);
263+
$listener = new ResizeFormListener('text', array(), false, true);
264+
$listener->onSubmit($event);
265+
266+
$this->assertArrayNotHasKey(0, $event->getData());
267+
$this->assertArrayNotHasKey(2, $event->getData());
268+
}
269+
270+
public function testOnSubmitDealsWithArrayBackedIteratorAggregate()
258271
{
259272
$this->form->add($this->getForm('1'));
260273

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.