Skip to content

Commit fe12153

Browse files
committed
[TwigBridge] Set Form ID on form element, prevent duplicate form element attributes
1 parent ad72245 commit fe12153

15 files changed

+45
-41
lines changed

src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% use "bootstrap_3_layout.html.twig" %}
22

33
{% block form_start -%}
4-
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-horizontal')|trim}) %}
4+
{% set row_attr = row_attr|merge({class: (row_attr.class|default('') ~ ' form-horizontal')|trim}) %}
55
{{- parent() -}}
66
{%- endblock form_start %}
77

src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@
400400
{%- else -%}
401401
{% set form_method = "POST" %}
402402
{%- endif -%}
403-
<form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{{ block('attributes') }}{% if multipart %} enctype="multipart/form-data"{% endif %}>
403+
<form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{% with { attr: row_attr} %}{{ block('attributes') }}{% endwith %}{% if multipart %} enctype="multipart/form-data"{% endif %}>
404404
{%- if form_method != method -%}
405405
<input type="hidden" name="_method" value="{{ method }}" />
406406
{%- endif -%}

src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTestCase.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public function testStartTag()
142142

143143
$html = $this->renderStart($form->createView());
144144

145-
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="form-horizontal">', $html);
145+
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" id="form_form" class="form-horizontal">', $html);
146146
}
147147

148148
public function testStartTagWithOverriddenVars()
@@ -157,7 +157,7 @@ public function testStartTagWithOverriddenVars()
157157
'action' => 'http://foo.com/directory',
158158
]);
159159

160-
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory" class="form-horizontal">', $html);
160+
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory" id="form_form" class="form-horizontal">', $html);
161161
}
162162

163163
public function testStartTagForMultipartForm()
@@ -171,7 +171,7 @@ public function testStartTagForMultipartForm()
171171

172172
$html = $this->renderStart($form->createView());
173173

174-
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="form-horizontal" enctype="multipart/form-data">', $html);
174+
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" id="form_form" class="form-horizontal" enctype="multipart/form-data">', $html);
175175
}
176176

177177
public function testStartTagWithExtraAttributes()
@@ -182,7 +182,7 @@ public function testStartTagWithExtraAttributes()
182182
]);
183183

184184
$html = $this->renderStart($form->createView(), [
185-
'attr' => ['class' => 'foobar'],
185+
'row_attr' => ['class' => 'foobar'],
186186
]);
187187

188188
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar form-horizontal">', $html);

src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTestCase.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ public function testStartTag()
193193

194194
$html = $this->renderStart($form->createView());
195195

196-
$this->assertSame('<form name="form" method="get" action="http://example.com/directory">', $html);
196+
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" id="form_form">', $html);
197197
}
198198

199199
public function testStartTagWithOverriddenVars()
@@ -208,7 +208,7 @@ public function testStartTagWithOverriddenVars()
208208
'action' => 'http://foo.com/directory',
209209
]);
210210

211-
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory">', $html);
211+
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory" id="form_form">', $html);
212212
}
213213

214214
public function testStartTagForMultipartForm()
@@ -222,7 +222,7 @@ public function testStartTagForMultipartForm()
222222

223223
$html = $this->renderStart($form->createView());
224224

225-
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" enctype="multipart/form-data">', $html);
225+
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" id="form_form" enctype="multipart/form-data">', $html);
226226
}
227227

228228
public function testStartTagWithExtraAttributes()
@@ -233,7 +233,7 @@ public function testStartTagWithExtraAttributes()
233233
]);
234234

235235
$html = $this->renderStart($form->createView(), [
236-
'attr' => ['class' => 'foobar'],
236+
'row_attr' => ['class' => 'foobar'],
237237
]);
238238

239239
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar">', $html);

src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ public function testForm()
414414
]
415415
[@method="post"]
416416
[@action="http://example.com"]
417-
[@class="my&class"]
417+
[@id="form_name"]
418418
'
419419
);
420420
}

src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,7 +2437,7 @@ public function testStartTag()
24372437

24382438
$html = $this->renderStart($form->createView());
24392439

2440-
$this->assertSame('<form name="form" method="get" action="http://example.com/directory">', $html);
2440+
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" id="form_form">', $html);
24412441
}
24422442

24432443
public function testStartTagForPutRequest()
@@ -2469,7 +2469,7 @@ public function testStartTagWithOverriddenVars()
24692469
'action' => 'http://foo.com/directory',
24702470
]);
24712471

2472-
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory">', $html);
2472+
$this->assertSame('<form name="form" method="post" action="http://foo.com/directory" id="form_form">', $html);
24732473
}
24742474

24752475
public function testStartTagForMultipartForm()
@@ -2483,7 +2483,7 @@ public function testStartTagForMultipartForm()
24832483

24842484
$html = $this->renderStart($form->createView());
24852485

2486-
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" enctype="multipart/form-data">', $html);
2486+
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" id="form_form" enctype="multipart/form-data">', $html);
24872487
}
24882488

24892489
public function testStartTagWithExtraAttributes()
@@ -2494,7 +2494,7 @@ public function testStartTagWithExtraAttributes()
24942494
]);
24952495

24962496
$html = $this->renderStart($form->createView(), [
2497-
'attr' => ['class' => 'foobar'],
2497+
'row_attr' => ['class' => 'foobar'],
24982498
]);
24992499

25002500
$this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar">', $html);

src/Symfony/Bridge/Twig/Tests/Extension/AbstractTableLayoutTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public function testForm()
271271
]
272272
[@method="post"]
273273
[@action="http://example.com"]
274-
[@class="my&class"]
274+
[@id="form_name"]
275275
'
276276
);
277277
}

src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
5757

5858
$html = $this->renderStart($form->createView());
5959

60-
$this->assertSame('<form name="form" method="get">', $html);
60+
$this->assertSame('<form name="form" method="get" id="form_form">', $html);
6161
}
6262

6363
public function testStartTagHasActionAttributeWhenActionIsZero()
@@ -69,7 +69,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero()
6969

7070
$html = $this->renderStart($form->createView());
7171

72-
$this->assertSame('<form name="form" method="get" action="0">', $html);
72+
$this->assertSame('<form name="form" method="get" action="0" id="form_form">', $html);
7373
}
7474

7575
public function testMoneyWidgetInIso()

src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
6262

6363
$html = $this->renderStart($form->createView());
6464

65-
$this->assertSame('<form name="form" method="get">', $html);
65+
$this->assertSame('<form name="form" method="get" id="form_form">', $html);
6666
}
6767

6868
public function testStartTagHasActionAttributeWhenActionIsZero()
@@ -74,7 +74,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero()
7474

7575
$html = $this->renderStart($form->createView());
7676

77-
$this->assertSame('<form name="form" method="get" action="0">', $html);
77+
$this->assertSame('<form name="form" method="get" action="0" id="form_form">', $html);
7878
}
7979

8080
public function testMoneyWidgetInIso()

src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
6464

6565
$html = $this->renderStart($form->createView());
6666

67-
self::assertSame('<form name="form" method="get">', $html);
67+
self::assertSame('<form name="form" method="get" id="form_form">', $html);
6868
}
6969

7070
public function testStartTagHasActionAttributeWhenActionIsZero()
@@ -76,7 +76,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero()
7676

7777
$html = $this->renderStart($form->createView());
7878

79-
self::assertSame('<form name="form" method="get" action="0">', $html);
79+
self::assertSame('<form name="form" method="get" action="0" id="form_form">', $html);
8080
}
8181

8282
public function testMoneyWidgetInIso()

src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
131131

132132
$html = $this->renderStart($form->createView());
133133

134-
$this->assertSame('<form name="form" method="get">', $html);
134+
$this->assertSame('<form name="form" method="get" id="form_form">', $html);
135135
}
136136

137137
public function testStartTagHasActionAttributeWhenActionIsZero()
@@ -143,7 +143,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero()
143143

144144
$html = $this->renderStart($form->createView());
145145

146-
$this->assertSame('<form name="form" method="get" action="0">', $html);
146+
$this->assertSame('<form name="form" method="get" action="0" id="form_form">', $html);
147147
}
148148

149149
public static function isRootFormProvider()

src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
5858

5959
$html = $this->renderStart($form->createView());
6060

61-
$this->assertSame('<form name="form" method="get">', $html);
61+
$this->assertSame('<form name="form" method="get" id="form_form">', $html);
6262
}
6363

6464
public function testStartTagHasActionAttributeWhenActionIsZero()
@@ -70,7 +70,7 @@ public function testStartTagHasActionAttributeWhenActionIsZero()
7070

7171
$html = $this->renderStart($form->createView());
7272

73-
$this->assertSame('<form name="form" method="get" action="0">', $html);
73+
$this->assertSame('<form name="form" method="get" action="0" id="form_form">', $html);
7474
}
7575

7676
public function testHelpAttr()

src/Symfony/Component/Form/Extension/Core/Type/BaseType.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,25 @@ public function buildView(FormView $view, FormInterface $form, array $options)
7171
}
7272

7373
$rootFormAttrOption = $form->getRoot()->getConfig()->getOption('form_attr');
74+
$rootFormName = $form->getRoot()->getName();
7475
if ($options['form_attr'] || $rootFormAttrOption) {
75-
$options['attr']['form'] = \is_string($rootFormAttrOption) ? $rootFormAttrOption : $form->getRoot()->getName();
76-
if (empty($options['attr']['form'])) {
76+
if (true === $rootFormAttrOption && empty($rootFormName)) {
7777
throw new LogicException('"form_attr" option must be a string identifier on root form when it has no id.');
7878
}
79+
80+
$options['attr']['form'] = \is_string($rootFormAttrOption) ? $rootFormAttrOption : 'form_'.$rootFormName;
7981
}
8082
} else {
81-
$id = \is_string($options['form_attr']) ? $options['form_attr'] : $name;
83+
$id = $name;
8284
$fullName = $name;
8385
$uniqueBlockPrefix = '_'.$blockName;
8486

8587
// Strip leading underscores and digits. These are allowed in
8688
// form names, but not in HTML4 ID attributes.
8789
// https://www.w3.org/TR/html401/struct/global#adef-id
8890
$id = ltrim($id, '_0123456789');
91+
92+
$options['row_attr'] += ['id' => \is_string($options['form_attr']) ? $options['form_attr'] : 'form_'.$id];
8993
}
9094

9195
$blockPrefixes = [];

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public function testFormAttrOnRoot()
5050
->getForm()
5151
->createView();
5252
$this->assertArrayNotHasKey('form', $view->vars['attr']);
53-
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
54-
$this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']);
53+
$this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']);
54+
$this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']);
5555
}
5656

5757
public function testFormAttrOnChild()
@@ -65,7 +65,7 @@ public function testFormAttrOnChild()
6565
->getForm()
6666
->createView();
6767
$this->assertArrayNotHasKey('form', $view->vars['attr']);
68-
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
68+
$this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']);
6969
$this->assertArrayNotHasKey('form', $view['child2']->vars['attr']);
7070
}
7171

@@ -95,8 +95,8 @@ public function testFormAttrAsStringWithNoId()
9595
->getForm()
9696
->createView();
9797
$this->assertArrayNotHasKey('form', $view->vars['attr']);
98-
$this->assertSame($stringId, $view->vars['id']);
99-
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
100-
$this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']);
98+
$this->assertSame($stringId, $view->vars['row_attr']['id']);
99+
$this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']);
100+
$this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']);
101101
}
102102
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -785,8 +785,8 @@ public function testFormAttrOnRoot()
785785
->getForm()
786786
->createView();
787787
$this->assertArrayNotHasKey('form', $view->vars['attr']);
788-
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
789-
$this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']);
788+
$this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']);
789+
$this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']);
790790
}
791791

792792
public function testFormAttrOnChild()
@@ -800,7 +800,7 @@ public function testFormAttrOnChild()
800800
->getForm()
801801
->createView();
802802
$this->assertArrayNotHasKey('form', $view->vars['attr']);
803-
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
803+
$this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']);
804804
$this->assertArrayNotHasKey('form', $view['child2']->vars['attr']);
805805
}
806806

@@ -830,9 +830,9 @@ public function testFormAttrAsStringWithNoId()
830830
->getForm()
831831
->createView();
832832
$this->assertArrayNotHasKey('form', $view->vars['attr']);
833-
$this->assertSame($stringId, $view->vars['id']);
834-
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
835-
$this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']);
833+
$this->assertSame($stringId, $view->vars['row_attr']['id']);
834+
$this->assertSame($view->vars['row_attr']['id'], $view['child1']->vars['attr']['form']);
835+
$this->assertSame($view->vars['row_attr']['id'], $view['child2']->vars['attr']['form']);
836836
}
837837

838838
public function testSortingViewChildrenBasedOnPriorityOption()

0 commit comments

Comments
 (0)