Skip to content

Commit e1ccfe3

Browse files
fix PRE_SET_DATA error
1 parent 8392534 commit e1ccfe3

File tree

3 files changed

+52
-30
lines changed

3 files changed

+52
-30
lines changed

src/Symfony/Component/Form/Form.php

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Symfony\Component\Form\Exception\UnexpectedTypeException;
2525
use Symfony\Component\Form\Extension\Core\Type\TextType;
2626
use Symfony\Component\Form\Util\FormUtil;
27+
use Symfony\Component\Form\Util\InheritDataAwareFilter;
2728
use Symfony\Component\Form\Util\InheritDataAwareIterator;
2829
use Symfony\Component\Form\Util\OrderedHashMap;
2930
use Symfony\Component\PropertyAccess\PropertyPath;
@@ -282,11 +283,13 @@ public function setData(mixed $modelData): static
282283

283284
$this->lockSetData = true;
284285

285-
// Collecting $this + all children with "inherit_data" option
286-
$thisModelDataAwareForms = $this->getSameModelAwareForms($this);
286+
// Collecting $this + all children with "inherit_data" option TRUE
287+
$thisModelDataAwareFormsIterator = new \AppendIterator();
288+
$thisModelDataAwareFormsIterator->append(new \ArrayIterator([$this]));
289+
$thisModelDataAwareFormsIterator->append(new InheritDataAwareFilter(new InheritDataAwareIterator($this->children)));
287290

288291
// Hook to change content of the model data before transformation and mapping children
289-
foreach ($thisModelDataAwareForms as $form) {
292+
foreach ($thisModelDataAwareFormsIterator as $form) {
290293
$dispatcher = $form->getConfig()->getEventDispatcher();
291294
if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) {
292295
$event = new PreSetDataEvent($form, $modelData);
@@ -327,7 +330,8 @@ public function setData(mixed $modelData): static
327330
// Update child forms from the data (unless their config data is locked)
328331
$this->config->getDataMapper()->mapDataToForms($viewData, new \RecursiveIteratorIterator(new InheritDataAwareIterator($this->children)));
329332
}
330-
foreach ($thisModelDataAwareForms as $form) {
333+
334+
foreach ($thisModelDataAwareFormsIterator as $form) {
331335
$dispatcher = $form->getConfig()->getEventDispatcher();
332336
if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) {
333337
$event = new PostSetDataEvent($form, $modelData);
@@ -472,8 +476,13 @@ public function submit(mixed $submittedData, bool $clearMissing = true): static
472476
$this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, array given.');
473477
}
474478

475-
// Collecting $this + all children with "inherit_data" option only if $this is not using "inherit_data" option
476-
$thisModelDataAwareForms = !$this->getConfig()->getInheritData() ? $this->getSameModelAwareForms($this) : [];
479+
$thisModelDataAwareFormsIterator = new \AppendIterator();
480+
481+
// Collecting $this + all children with "inherit_data" option TRUE only if $this has "inherit_data" option FALSE to avoid to dispatch events two times.
482+
if (!$this->getConfig()->getInheritData()) {
483+
$thisModelDataAwareFormsIterator->append(new \ArrayIterator(['' => $this]));
484+
$thisModelDataAwareFormsIterator->append(new InheritDataAwareFilter(new InheritDataAwareIterator($this->children)));
485+
}
477486

478487
$modelData = null;
479488
$normData = null;
@@ -485,10 +494,16 @@ public function submit(mixed $submittedData, bool $clearMissing = true): static
485494
}
486495

487496
// Hook to change content of the data submitted by the browser
488-
foreach ($thisModelDataAwareForms as $form) {
497+
foreach ($thisModelDataAwareFormsIterator as $name => $form) {
489498
$dispatcher = $form->getConfig()->getEventDispatcher();
490499
if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) {
491-
$event = new PreSubmitEvent($form, $submittedData);
500+
$eventSubmittedData = null;
501+
if (empty($name)) {
502+
$eventSubmittedData = $submittedData;
503+
} elseif (\array_key_exists($name, $submittedData)) {
504+
$eventSubmittedData = $submittedData[$name];
505+
}
506+
$event = new PreSubmitEvent($form, $eventSubmittedData);
492507
$dispatcher->dispatch($event, FormEvents::PRE_SUBMIT);
493508
$submittedData = $event->getData();
494509
}
@@ -574,7 +589,7 @@ public function submit(mixed $submittedData, bool $clearMissing = true): static
574589

575590
// Hook to change content of the data in the normalized
576591
// representation
577-
foreach ($thisModelDataAwareForms as $form) {
592+
foreach ($thisModelDataAwareFormsIterator as $form) {
578593
$dispatcher = $form->getConfig()->getEventDispatcher();
579594
if ($dispatcher->hasListeners(FormEvents::SUBMIT)) {
580595
$event = new SubmitEvent($form, $normData);
@@ -604,7 +619,7 @@ public function submit(mixed $submittedData, bool $clearMissing = true): static
604619
$this->normData = $normData;
605620
$this->viewData = $viewData;
606621

607-
foreach ($thisModelDataAwareForms as $form) {
622+
foreach ($thisModelDataAwareFormsIterator as $form) {
608623
$dispatcher = $form->getConfig()->getEventDispatcher();
609624
if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) {
610625
$event = new PostSubmitEvent($form, $viewData);
@@ -615,22 +630,6 @@ public function submit(mixed $submittedData, bool $clearMissing = true): static
615630
return $this;
616631
}
617632

618-
/**
619-
* @return array<FormInterface>
620-
*/
621-
private function getSameModelAwareForms(self $form): array
622-
{
623-
return array_reduce(iterator_to_array($form->children),
624-
static function (array $children, FormInterface $child): array {
625-
if ($child->getConfig()->getInheritData()) {
626-
$children[] = $child;
627-
}
628-
629-
return $children;
630-
}, [$form]
631-
);
632-
}
633-
634633
public function addError(FormError $error): static
635634
{
636635
if (null === $error->getOrigin()) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ public function testSortingViewChildrenBasedOnPriorityOption()
865865

866866
public function testSetDataEventsDispatchedToChildrenWithInheritDataConfigured()
867867
{
868-
$data = ['child' => 'child_value'];
868+
$data = ['child' => 'foo'];
869869
$calledEvents = [];
870870
$form = $this->factory->createNamedBuilder('form', self::TESTED_TYPE, $data)
871871
->add(
@@ -882,7 +882,7 @@ public function testSetDataEventsDispatchedToChildrenWithInheritDataConfigured()
882882
})
883883
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use (&$calledEvents) {
884884
$calledEvents[] = FormEvents::PRE_SUBMIT;
885-
$this->assertSame($event->getData(), $event->getForm()->getData());
885+
$this->assertNotNull($event->getData());
886886
})
887887
->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use (&$calledEvents) {
888888
$calledEvents[] = FormEvents::SUBMIT;
@@ -896,8 +896,8 @@ public function testSetDataEventsDispatchedToChildrenWithInheritDataConfigured()
896896
->getForm();
897897
$this->assertTrue($form->get('inherit_data_type')->has('child'));
898898
$this->assertTrue($form->get('inherit_data_type')->has('child2'));
899-
$this->assertSame('child_value', $form->get('inherit_data_type')->get('child')->getData());
900-
$this->assertSame('child_value', $form->get('inherit_data_type')->get('child2')->getData());
899+
$this->assertSame('foo', $form->get('inherit_data_type')->get('child')->getData());
900+
$this->assertSame('foo', $form->get('inherit_data_type')->get('child2')->getData());
901901
$errorMessage = '"%s" event has not been called on form child with "inherit_data" option.';
902902
$form->submit($data);
903903
$this->assertContains(FormEvents::PRE_SET_DATA, $calledEvents, sprintf($errorMessage, FormEvents::PRE_SET_DATA));
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
/**
13+
* @author Cristoforo Cervino <cristoforo.cervino@me.com>
14+
*/
15+
namespace Symfony\Component\Form\Util;
16+
17+
class InheritDataAwareFilter extends \FilterIterator
18+
{
19+
public function accept(): bool
20+
{
21+
return (bool) $this->current()->getConfig()->getInheritData();
22+
}
23+
}

0 commit comments

Comments
 (0)