-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[Form] Fixed potential BC break on submitting data to disabled child form #38025
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -508,22 +508,24 @@ public function submit($submittedData, bool $clearMissing = true) | |
$dispatcher = $this->config->getEventDispatcher(); | ||
|
||
// Obviously, a disabled form should not change its data upon submission. | ||
if ($this->isDisabled() && $this->isRoot()) { | ||
if ($this->isDisabled()) { | ||
$this->submitted = true; | ||
|
||
if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { | ||
$event = new FormEvent($this, $submittedData); | ||
$dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); | ||
} | ||
if ($this->isRoot()) { | ||
if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { | ||
$event = new FormEvent($this, $submittedData); | ||
$dispatcher->dispatch($event, FormEvents::PRE_SUBMIT); | ||
} | ||
|
||
if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { | ||
$event = new FormEvent($this, $this->getNormData()); | ||
$dispatcher->dispatch(FormEvents::SUBMIT, $event); | ||
} | ||
if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { | ||
$event = new FormEvent($this, $this->getNormData()); | ||
$dispatcher->dispatch($event, FormEvents::SUBMIT); | ||
} | ||
|
||
if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { | ||
$event = new FormEvent($this, $this->getViewData()); | ||
$dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); | ||
if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { | ||
$event = new FormEvent($this, $this->getViewData()); | ||
$dispatcher->dispatch($event, FormEvents::POST_SUBMIT); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment here. |
||
} | ||
} | ||
|
||
return $this; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -22,11 +22,14 @@ | |||||
use Symfony\Component\Form\FormBuilderInterface; | ||||||
use Symfony\Component\Form\FormFactoryBuilder; | ||||||
use Symfony\Component\OptionsResolver\OptionsResolver; | ||||||
use Symfony\Component\Validator\Constraints\Callback; | ||||||
use Symfony\Component\Validator\Constraints\Collection; | ||||||
use Symfony\Component\Validator\Constraints\Expression; | ||||||
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; | ||||||
use Symfony\Component\Validator\Constraints\GroupSequence; | ||||||
use Symfony\Component\Validator\Constraints\Length; | ||||||
use Symfony\Component\Validator\Constraints\NotBlank; | ||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface; | ||||||
use Symfony\Component\Validator\Mapping\ClassMetadata; | ||||||
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; | ||||||
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; | ||||||
|
@@ -386,6 +389,41 @@ function () { | |||||
$this->assertFalse($form->get('field2')->isValid()); | ||||||
$this->assertCount(1, $form->get('field2')->getErrors()); | ||||||
} | ||||||
|
||||||
public function testDisabledFormIsInvalidIfRootFormValidationFails() | ||||||
{ | ||||||
$form = $this->formFactory | ||||||
->createBuilder(FormType::class, ['field1' => 0], [ | ||||||
'constraints' => new Callback(['callback' => static function ($data, ExecutionContextInterface $context) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even though constraints violation linked to the root form are working correctly. |
||||||
if ($data['field1'] < 1) { | ||||||
$context->addViolation('Invalid'); | ||||||
} | ||||||
}]), | ||||||
]) | ||||||
->setDisabled(true) | ||||||
->add('field1') | ||||||
->getForm(); | ||||||
|
||||||
$form->submit(null); | ||||||
|
||||||
$this->assertTrue($form->isSubmitted()); | ||||||
$this->assertFalse($form->isValid()); | ||||||
$this->assertCount(1, $form->getErrors()); | ||||||
} | ||||||
|
||||||
public function testDisabledFormIsInvalidIfChildrenValidationFails() | ||||||
{ | ||||||
$form = $this->formFactory->createBuilder(FormType::class, ['field1' => 0]) | ||||||
->setDisabled(true) | ||||||
->add('field1', null, ['constraints' => new GreaterThanOrEqual(1)]) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems this kind of validation (tied directly to the form field) doesn't work because form fields will require to be marked as submitted too: symfony/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php Lines 85 to 86 in 4e0b7e5
and currently only the root form is being marked as "submitted". |
||||||
->getForm(); | ||||||
|
||||||
$form->submit(null); | ||||||
|
||||||
$this->assertTrue($form->isSubmitted()); | ||||||
$this->assertFalse($form->isValid()); | ||||||
$this->assertCount(1, $form->get('field1')->getErrors()); | ||||||
} | ||||||
} | ||||||
|
||||||
class Foo | ||||||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added another test covering this case where the underlying object has been changed. This shouldn't happen if the entire form is disabled. Also this would break BC.
https://travis-ci.org/github/symfony/symfony/jobs/723435931#L3539