From 2e1e2733a03b5142b582a2148a49a86ba9cb3288 Mon Sep 17 00:00:00 2001 From: Romain Monteil Date: Thu, 27 Oct 2022 15:03:37 +0200 Subject: [PATCH] [TwigBridge] Set Form ID on form element, prevent duplicate form element attributes --- .../Form/bootstrap_3_horizontal_layout.html.twig | 2 +- .../Resources/views/Form/form_div_layout.html.twig | 2 +- .../AbstractBootstrap3HorizontalLayoutTestCase.php | 8 ++++---- .../AbstractBootstrap4HorizontalLayoutTestCase.php | 8 ++++---- .../Tests/Extension/AbstractDivLayoutTestCase.php | 2 +- .../Twig/Tests/Extension/AbstractLayoutTestCase.php | 8 ++++---- .../Tests/Extension/AbstractTableLayoutTestCase.php | 2 +- .../Extension/FormExtensionBootstrap3LayoutTest.php | 4 ++-- .../Extension/FormExtensionBootstrap4LayoutTest.php | 4 ++-- .../Extension/FormExtensionBootstrap5LayoutTest.php | 4 ++-- .../Tests/Extension/FormExtensionDivLayoutTest.php | 4 ++-- .../Tests/Extension/FormExtensionTableLayoutTest.php | 4 ++-- .../Component/Form/Extension/Core/Type/BaseType.php | 10 +++++++--- .../Tests/Extension/Core/Type/ButtonTypeTest.php | 12 ++++++------ .../Form/Tests/Extension/Core/Type/FormTypeTest.php | 12 ++++++------ 15 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig index 49cd804398b5e..21ec93d7eef00 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig @@ -1,7 +1,7 @@ {% use "bootstrap_3_layout.html.twig" %} {% block form_start -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-horizontal')|trim}) %} + {% set row_attr = row_attr|merge({class: (row_attr.class|default('') ~ ' form-horizontal')|trim}) %} {{- parent() -}} {%- endblock form_start %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 1e421d5f9f5a9..33d39c1aa894d 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -404,7 +404,7 @@ {%- else -%} {% set form_method = "POST" %} {%- endif -%} -
+ {%- if form_method != method -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTestCase.php index 3a4104bb6adbd..599c990b60c7e 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTestCase.php @@ -142,7 +142,7 @@ public function testStartTag() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagWithOverriddenVars() @@ -157,7 +157,7 @@ public function testStartTagWithOverriddenVars() 'action' => 'http://foo.com/directory', ]); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagForMultipartForm() @@ -171,7 +171,7 @@ public function testStartTagForMultipartForm() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagWithExtraAttributes() @@ -182,7 +182,7 @@ public function testStartTagWithExtraAttributes() ]); $html = $this->renderStart($form->createView(), [ - 'attr' => ['class' => 'foobar'], + 'row_attr' => ['class' => 'foobar'], ]); $this->assertSame('', $html); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTestCase.php index 723559ee3d985..7f75c353a90ab 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTestCase.php @@ -193,7 +193,7 @@ public function testStartTag() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagWithOverriddenVars() @@ -208,7 +208,7 @@ public function testStartTagWithOverriddenVars() 'action' => 'http://foo.com/directory', ]); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagForMultipartForm() @@ -222,7 +222,7 @@ public function testStartTagForMultipartForm() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagWithExtraAttributes() @@ -233,7 +233,7 @@ public function testStartTagWithExtraAttributes() ]); $html = $this->renderStart($form->createView(), [ - 'attr' => ['class' => 'foobar'], + 'row_attr' => ['class' => 'foobar'], ]); $this->assertSame('', $html); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php index a02fca4bc54ca..4cca10754cae2 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php @@ -414,7 +414,7 @@ public function testForm() ] [@method="post"] [@action="http://example.com"] - [@class="my&class"] + [@id="form_name"] ' ); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php index f340b066ed884..83698ac6d229b 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php @@ -2374,7 +2374,7 @@ public function testStartTag() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagForPutRequest() @@ -2406,7 +2406,7 @@ public function testStartTagWithOverriddenVars() 'action' => 'http://foo.com/directory', ]); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagForMultipartForm() @@ -2420,7 +2420,7 @@ public function testStartTagForMultipartForm() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagWithExtraAttributes() @@ -2431,7 +2431,7 @@ public function testStartTagWithExtraAttributes() ]); $html = $this->renderStart($form->createView(), [ - 'attr' => ['class' => 'foobar'], + 'row_attr' => ['class' => 'foobar'], ]); $this->assertSame('', $html); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractTableLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractTableLayoutTestCase.php index c3cdb08e547e8..dcc43c3847436 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractTableLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractTableLayoutTestCase.php @@ -271,7 +271,7 @@ public function testForm() ] [@method="post"] [@action="http://example.com"] - [@class="my&class"] + [@id="form_name"] ' ); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 7c3742a7409b2..906ad4d556524 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -31,7 +31,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagHasActionAttributeWhenActionIsZero() @@ -43,7 +43,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testMoneyWidgetInIso() diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php index 5fdec71db05e9..0c571783e2fa9 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -36,7 +36,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagHasActionAttributeWhenActionIsZero() @@ -48,7 +48,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testMoneyWidgetInIso() diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php index ced0fe607174e..784e25a0e4348 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php @@ -38,7 +38,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty() $html = $this->renderStart($form->createView()); - self::assertSame('', $html); + self::assertSame('', $html); } public function testStartTagHasActionAttributeWhenActionIsZero() @@ -50,7 +50,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero() $html = $this->renderStart($form->createView()); - self::assertSame('', $html); + self::assertSame('', $html); } public function testMoneyWidgetInIso() diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index ad2627a238a18..fc5c2ee7c8dfb 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -103,7 +103,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagHasActionAttributeWhenActionIsZero() @@ -115,7 +115,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public static function isRootFormProvider(): array diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 2ab48be2aca8c..64a18180b7702 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -26,7 +26,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagHasActionAttributeWhenActionIsZero() @@ -38,7 +38,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testHelpAttr() diff --git a/src/Symfony/Component/Form/Extension/Core/Type/BaseType.php b/src/Symfony/Component/Form/Extension/Core/Type/BaseType.php index 68190c742fcb2..b1bc7a688f549 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/BaseType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/BaseType.php @@ -65,14 +65,16 @@ public function buildView(FormView $view, FormInterface $form, array $options): } $rootFormAttrOption = $form->getRoot()->getConfig()->getOption('form_attr'); + $rootFormName = $form->getRoot()->getName(); if ($options['form_attr'] || $rootFormAttrOption) { - $options['attr']['form'] = \is_string($rootFormAttrOption) ? $rootFormAttrOption : $form->getRoot()->getName(); - if (empty($options['attr']['form'])) { + if (true === $rootFormAttrOption && empty($rootFormName)) { throw new LogicException('"form_attr" option must be a string identifier on root form when it has no id.'); } + + $options['attr']['form'] = \is_string($rootFormAttrOption) ? $rootFormAttrOption : 'form_'.$rootFormName; } } else { - $id = \is_string($options['form_attr']) ? $options['form_attr'] : $name; + $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; @@ -80,6 +82,8 @@ public function buildView(FormView $view, FormInterface $form, array $options): // form names, but not in HTML4 ID attributes. // https://www.w3.org/TR/html401/struct/global#adef-id $id = ltrim($id, '_0123456789'); + + $options['row_attr'] += ['id' => \is_string($options['form_attr']) ? $options['form_attr'] : 'form_'.$id]; } $blockPrefixes = []; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php index 0125631c582c6..6a366b006f8af 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php @@ -50,8 +50,8 @@ public function testFormAttrOnRoot() ->getForm() ->createView(); $this->assertArrayNotHasKey('form', $view->vars['attr']); - $this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']); - $this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']); } public function testFormAttrOnChild() @@ -65,7 +65,7 @@ public function testFormAttrOnChild() ->getForm() ->createView(); $this->assertArrayNotHasKey('form', $view->vars['attr']); - $this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']); $this->assertArrayNotHasKey('form', $view['child2']->vars['attr']); } @@ -95,8 +95,8 @@ public function testFormAttrAsStringWithNoId() ->getForm() ->createView(); $this->assertArrayNotHasKey('form', $view->vars['attr']); - $this->assertSame($stringId, $view->vars['id']); - $this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']); - $this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']); + $this->assertSame($stringId, $view->vars['row_attr']['id']); + $this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php index be89c559f6d3c..0bddca4bfb46c 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php @@ -785,8 +785,8 @@ public function testFormAttrOnRoot() ->getForm() ->createView(); $this->assertArrayNotHasKey('form', $view->vars['attr']); - $this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']); - $this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']); } public function testFormAttrOnChild() @@ -800,7 +800,7 @@ public function testFormAttrOnChild() ->getForm() ->createView(); $this->assertArrayNotHasKey('form', $view->vars['attr']); - $this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']); $this->assertArrayNotHasKey('form', $view['child2']->vars['attr']); } @@ -830,9 +830,9 @@ public function testFormAttrAsStringWithNoId() ->getForm() ->createView(); $this->assertArrayNotHasKey('form', $view->vars['attr']); - $this->assertSame($stringId, $view->vars['id']); - $this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']); - $this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']); + $this->assertSame($stringId, $view->vars['row_attr']['id']); + $this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']); + $this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']); } public function testSortingViewChildrenBasedOnPriorityOption()