8000 merged branch kepten/ticket_6239 (PR #8197) · symfony/symfony@0ebb8bc · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ebb8bc

committed
merged branch kepten/ticket_6239 (PR #8197)
This PR was squashed before being merged into the 2.3 branch (closes #8197). Discussion ---------- [DomCrawler] fixed HTML5 form attribute handling Fixed HTML5 form attribute handling and improved a test case to test more thoroughly | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #6239 | License | MIT | Doc PR | no Commits ------- 04e730e [DomCrawler] fixed HTML5 form attribute handling
2 parents 5e4b24a + 04e730e commit 0ebb8bc

File tree

2 files changed

+71
-26
lines changed

2 files changed

+71
-26
lines changed

src/Symfony/Component/DomCrawler/Form.php

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -367,46 +367,59 @@ protected function setNode(\DOMNode $node)
367367
$this->node = $node;
368368
}
369369

370+
/**
371+
* Adds form elements related to this form.
372+
*
373+
* Creates an internal copy of the submitted 'button' element and
374+
* the form node or the entire document depending on whether we need
375+
* to find non-descendant elements through HTML5 'form' attribute.
376+
*/
370377
private function initialize()
371378
{
372379
$this->fields = new FormFieldRegistry();
373380

374381
$document = new \DOMDocument('1.0', 'UTF-8');
375-
$node = $document->importNode($this->node, true);
376-
$button = $document->importNode($this->button, true);
377-
$root = $document->appendChild($document->createElement('_root'));
378-
$root->appendChild($node);
379-
$root->appendChild($button);
380382
$xpath = new \DOMXPath($document);
383+
$root = $document->appendChild($document->createElement('_root'));
381384

382-
// add descendant elements to the form
383-
$fieldNodes = $xpath->query('descendant::input | descendant::button | descendant::textarea | descendant::select', $root);
384-
foreach ($fieldNodes as $node) {
385-
$this->addField($node, $button);
385+
// add submitted button if it has a valid name
386+
if ($this->button->hasAttribute('name') && $this->button->getAttribute('name')) {
387+
$this->set(new Field\InputFormField($document->importNode($this->button, true)));
386388
}
387389

388-
// find form elements corresponding to the current form by the HTML5 form attribute
390+
// find form elements corresponding to the current form
389391
if ($this->node->hasAttribute('id')) {
392+
// traverse through the whole document
393+
$node = $document->importNode($this->node->ownerDocument->documentElement, true);
394+
$root->appendChild($node);
395+
396+
// corresponding elements are either descendants or have a matching HTML5 form attribute
390397
$formId = Crawler::xpathLiteral($this->node->getAttribute('id'));
391-
$xpath = new \DOMXPath($this->node->ownerDocument);
392-
$fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%s] | descendant::textarea[@form=%s] | descendant::select[@form=%s]', $formId, $formId, $formId, $formId));
398+
$fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%s] | descendant::textarea[@form=%s] | descendant::select[@form=%s] | //form[@id=%s]/input[not(@form)] | //form[@id=%s]/button[not(@form)] | //form[@id=%s]/textarea[not(@form)] | //form[@id=%s]/select[not(@form)]', $formId, $formId, $formId, $formId, $formId, $formId, $formId, $formId), $root);
393399
foreach ($fieldNodes as $node) {
394-
$this->addField($node, $button);
400+
$this->addField($node);
401+
}
402+
} else {
403+
// parent form has no id, add descendant elements only
404+
$node = $document->importNode($this->node, true);
405+
$root->appendChild($node);
406+
407+
// descendant elements with form attribute are not part of this form
408+
$fieldNodes = $xpath->query('descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)]', $root);
409+
foreach ($fieldNodes as $node) {
410+
$this->addField($node);
395411
}
396412
}
397413
}
398414

399-
private function addField(\DOMNode $node, \DOMNode $button)
415+
private function addField(\DOMNode $node)
400416
{
401417
if (!$node->hasAttribute('name') || !$node->getAttribute('name')) {
402418
return;
403419
}
404420

405421
$nodeName = $node->nodeName;
406-
407-
if ($node === $button) {
408-
$this->set(new Field\InputFormField($node));
409-
} elseif ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == $node->getAttribute('type')) {
422+
if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == $node->getAttribute('type')) {
410423
$this->set(new Field\ChoiceFormField($node));
411424
} elseif ('input' == $nodeName && 'radio' == $node->getAttribute('type')) {
412425
if ($this->has($node->getAttribute('name'))) {

src/Symfony/Component/DomCrawler/Tests/FormTest.php

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,21 +90,53 @@ public function testConstructorHandlesFormAttribute()
9090
$dom = new \DOMDocument();
9191
$dom->loadHTML('
9292
<html>
93-
<form id="bar">
94-
<input type="submit" form="bar" />
93+
<form id="form_1" action="" method="POST">
94+
<input type="checkbox" name="apples[]" value="1" checked />
95+
<input form="form_2" type="checkbox" name="oranges[]" value="1" checked />
96+
<input form="form_1" type="hidden" name="form_name" value="form_1" />
97+
<input form="form_1" type="submit" name="button_1" value="Capture fields" />
98+
<button form="form_2" type="submit" name="button_2">Submit form_2</button>
99+
</form>
100+
<input form="form_1" type="checkbox" name="apples[]" value="2" checked />
101+
<form id="form_2" action="" method="POST">
102+
<input type="checkbox" name="oranges[]" value="2" checked />
103+
<input type="checkbox" name="oranges[]" value="3" checked />
104+
<input form="form_2" type="hidden" name="form_name" value="form_2" />
105+
<input form="form_1" type="hidden" name="outer_field" value="success" />
106+
<button form="form_1" type="submit" name="button_3">Submit from outside the form</button>
95107
</form>
96-
<input type="submit" form="bar" />
97108
<button />
98109
</html>
99110
');
100111

101-
$nodes = $dom->getElementsByTagName('input');
112+
$inputElements = $dom->getElementsByTagName('input');
113+
$buttonElements = $dom->getElementsByTagName('button');
102114

103-
$form = new Form($nodes->item(0), 'http://example.com');
104-
$this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
115+
// Tests if submit buttons are correctly assigned to forms
116+
$form1 = new Form($buttonElements->item(1), 'http://example.com');
117+
$this->assertSame($dom->getElementsByTagName('form')->item(0), $form1->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
118+
119+
$form1 = new Form($inputElements->item(3), 'http://example.com');
120+
$this->assertSame($dom->getElementsByTagName('form')->item(0), $form1->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
121+
122+
$form2 = new Form($buttonElements->item(0), 'http://example.com');
123+
$this->assertSame($dom->getElementsByTagName('form')->item(1), $form2->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
124+
125+
// Tests if form elements are correctly assigned to forms
126+
$values1 = array(
127+
'apples' => array('1', '2'),
128+
'form_name' => 'form_1',
129+
'button_1' => 'Capture fields',
130+
'outer_field' => 'success'
131+
);
132+
$values2 = array(
133+
'oranges' => array('1', '2', '3'),
134+
'form_name' => 'form_2',
135+
'button_2' => '',
136+
);
137+
$this->assertEquals($values1, $form1->getPhpValues(), 'HTML5-compliant form attribute handled incorrectly');
138+
$this->assertEquals($values2, $form2->getPhpValues(), 'HTML5-compliant form attribute handled incorrectly');
105139

106-
$form = new Form($nodes->item(1), 'http://example.com');
107-
$this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), 'HTML5-compliant form attribute handled incorrectly');
108140
}
109141

110142
public function testMultiValuedFields()

0 commit comments

Comments
 (0)
0