Skip to content

Commit

Permalink
Fix "Array was modified outside object" in ResizeFormListener.
Browse files Browse the repository at this point in the history
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, 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 Iterator and data to be out of sync. When the data is an instance of IteratorAggregate, the loop should use the iterator directly and not rely on foreach.

The onSubmit method has been updated accordingly.
  • Loading branch information
Chekote authored and fabpot committed Feb 11, 2014
1 parent a1813cb commit e62c0b5
Showing 1 changed file with 15 additions and 3 deletions.
Expand Up @@ -139,9 +139,21 @@ public function onSubmit(FormEvent $event)
// The data mapper only adds, but does not remove items, so do this
// here
if ($this->allowDelete) {
foreach ($data as $name => $child) {
if (!$form->has($name)) {
unset($data[$name]);
if ($data instanceof \IteratorAggregate) {
$iter = $data->getIterator();
while ($iter->valid()) {
$name = $iter->key();
if ($form->has($name)) {
$iter->next();
} else {
$iter->offsetUnset($name);
}
}
} else {
foreach ($data as $name => $child) {
if (!$form->has($name)) {
unset($data[$name]);
}
}
}
}
Expand Down

0 comments on commit e62c0b5

Please sign in to comment.