Skip to content

Commit 63087e5

Browse files
committed
bug symfony#20762 [Form] Fix FormDataCollector (nicolas-grekas, Padam87)
This PR was merged into the 3.2 branch. Discussion ---------- [Form] Fix FormDataCollector | Q | A | ------------- | --- | Branch? | 3.2 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#20698 | License | MIT | Doc PR | - Alternative to symfony#20707 Commits ------- 50400c4 [Form] Add failing test for data collector bug 164a20c [Form] Fix FormDataCollector
2 parents 456e68b + 50400c4 commit 63087e5

File tree

2 files changed

+123
-19
lines changed

2 files changed

+123
-19
lines changed

src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -209,19 +209,15 @@ public function collectViewVariables(FormView $view)
209209
*/
210210
public function buildPreliminaryFormTree(FormInterface $form)
211211
{
212-
$this->data['forms'][$form->getName()] = array();
213-
214-
$this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()], $this->data['forms_by_hash']);
212+
$this->data['forms'][$form->getName()] = &$this->recursiveBuildPreliminaryFormTree($form, $this->data['forms_by_hash']);
215213
}
216214

217215
/**
218216
* {@inheritdoc}
219217
*/
220218
public function buildFinalFormTree(FormInterface $form, FormView $view)
221219
{
222-
$this->data['forms'][$form->getName()] = array();
223-
224-
$this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()], $this->data['forms_by_hash']);
220+
$this->data['forms'][$form->getName()] = &$this->recursiveBuildFinalFormTree($form, $view, $this->data['forms_by_hash']);
225221
}
226222

227223
/**
@@ -258,7 +254,7 @@ public function serialize()
258254
case 'resolved_options':
259255
case 'default_data':
260256
case 'submitted_data':
261-
if ($v) {
257+
if ($v && is_array($v)) {
262258
$form[$k] = array_map($cloneVar, $v);
263259
}
264260
break;
@@ -354,26 +350,25 @@ protected function cloneVar($var, $isClass = false)
354350
return $cache = $this->cloner->cloneVar($var);
355351
}
356352

357-
private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output, array &$outputByHash)
353+
private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash)
358354
{
359355
$hash = spl_object_hash($form);
360356

357+
$output = &$outputByHash[$hash];
361358
$output = isset($this->dataByForm[$hash])
362359
? $this->dataByForm[$hash]
363360
: array();
364361

365-
$outputByHash[$hash] = &$output;
366-
367362
$output['children'] = array();
368363

369364
foreach ($form as $name => $child) {
370-
$output['children'][$name] = array();
371-
372-
$this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name], $outputByHash);
365+
$output['children'][$name] = &$this->recursiveBuildPreliminaryFormTree($child, $outputByHash);
373366
}
367+
368+
return $output;
374369
}
375370

376-
private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output, array &$outputByHash)
371+
private function &recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, array &$outputByHash)
377372
{
378373
$viewHash = spl_object_hash($view);
379374
$formHash = null;
@@ -386,6 +381,9 @@ private function recursiveBuildFinalFormTree(FormInterface $form = null, FormVie
386381
// corresponding FormInterface instance for its view in a different way
387382
$formHash = $this->formsByView[$viewHash];
388383
}
384+
if (null !== $formHash) {
385+
$output = &$outputByHash[$formHash];
386+
}
389387

390388
$output = isset($this->dataByView[$viewHash])
391389
? $this->dataByView[$viewHash]
@@ -398,8 +396,6 @@ private function recursiveBuildFinalFormTree(FormInterface $form = null, FormVie
398396
? $this->dataByForm[$formHash]
399397
: array()
400398
);
401-
402-
$outputByHash[$formHash] = &$output;
403399
}
404400

405401
$output['children'] = array();
@@ -411,9 +407,9 @@ private function recursiveBuildFinalFormTree(FormInterface $form = null, FormVie
411407
? $form->get($name)
412408
: null;
413409

414-
$output['children'][$name] = array();
415-
416-
$this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name], $outputByHash);
410+
$output['children'][$name] = &$this->recursiveBuildFinalFormTree($childForm, $childView, $outputByHash);
417411
}
412+
413+
return $output;
418414
}
419415
}

src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,114 @@ public function testBuildFinalFormTree()
342342
), $this->dataCollector->getData());
343343
}
344344

345+
public function testSerializeWithFormAddedMultipleTimes()
346+
{
347+
$form1 = $this->createForm('form1');
348+
$form2 = $this->createForm('form2');
349+
$child1 = $this->createForm('child1');
350+
351+
$form1View = new FormView();
352+
$form2View = new FormView();
353+
$child1View = new FormView();
354+
$child1View->vars['is_selected'] = function ($choice, array $values) {
355+
return in_array($choice, $values, true);
356+
};
357+
358+
$form1->add($child1);
359+
$form2->add($child1);
360+
361+
$form1View->children['child1'] = $child1View;
362+
$form2View->children['child1'] = $child1View;
363+
364+
$this->dataExtractor->expects($this->at(0))
365+
->method('extractConfiguration')
366+
->with($form1)
367+
->will($this->returnValue(array('config' => 'foo')));
368+
$this->dataExtractor->expects($this->at(1))
369+
->method('extractConfiguration')
370+
->with($child1)
371+
->will($this->returnValue(array('config' => 'bar')));
372+
373+
$this->dataExtractor->expects($this->at(2))
374+
->method('extractDefaultData')
375+
->with($form1)
376+
->will($this->returnValue(array('default_data' => 'foo')));
377+
$this->dataExtractor->expects($this->at(3))
378+
->method('extractDefaultData')
379+
->with($child1)
380+
->will($this->returnValue(array('default_data' => 'bar')));
381+
382+
$this->dataExtractor->expects($this->at(4))
383+
->method('extractSubmittedData')
384+
->with($form1)
385+
->will($this->returnValue(array('submitted_data' => 'foo')));
386+
$this->dataExtractor->expects($this->at(5))
387+
->method('extractSubmittedData')
388+
->with($child1)
389+
->will($this->returnValue(array('submitted_data' => 'bar')));
390+
391+
$this->dataExtractor->expects($this->at(6))
392+
->method('extractViewVariables')
393+
->with($form1View)
394+
->will($this->returnValue(array('view_vars' => 'foo')));
395+
396+
$this->dataExtractor->expects($this->at(7))
397+
->method('extractViewVariables')
398+
->with($child1View)
399+
->will($this->returnValue(array('view_vars' => $child1View->vars)));
400+
401+
$this->dataExtractor->expects($this->at(8))
402+
->method('extractConfiguration')
403+
->with($form2)
404+
->will($this->returnValue(array('config' => 'foo')));
405+
$this->dataExtractor->expects($this->at(9))
406+
->method('extractConfiguration')
407+
->with($child1)
408+
->will($this->returnValue(array('config' => 'bar')));
409+
410+
$this->dataExtractor->expects($this->at(10))
411+
->method('extractDefaultData')
412+
->with($form2)
413+
->will($this->returnValue(array('default_data' => 'foo')));
414+
$this->dataExtractor->expects($this->at(11))
415+
->method('extractDefaultData')
416+
->with($child1)
417+
->will($this->returnValue(array('default_data' => 'bar')));
418+
419+
$this->dataExtractor->expects($this->at(12))
420+
->method('extractSubmittedData')
421+
->with($form2)
422+
->will($this->returnValue(array('submitted_data' => 'foo')));
423+
$this->dataExtractor->expects($this->at(13))
424+
->method('extractSubmittedData')
425+
->with($child1)
426+
->will($this->returnValue(array('submitted_data' => 'bar')));
427+
428+
$this->dataExtractor->expects($this->at(14))
429+
->method('extractViewVariables')
430+
->with($form2View)
431+
->will($this->returnValue(array('view_vars' => 'foo')));
432+
433+
$this->dataExtractor->expects($this->at(15))
434+
->method('extractViewVariables')
435+
->with($child1View)
436+
->will($this->returnValue(array('view_vars' => $child1View->vars)));
437+
438+
$this->dataCollector->collectConfiguration($form1);
439+
$this->dataCollector->collectDefaultData($form1);
440+
$this->dataCollector->collectSubmittedData($form1);
441+
$this->dataCollector->collectViewVariables($form1View);
442+
$this->dataCollector->buildFinalFormTree($form1, $form1View);
443+
444+
$this->dataCollector->collectConfiguration($form2);
445+
$this->dataCollector->collectDefaultData($form2);
446+
$this->dataCollector->collectSubmittedData($form2);
447+
$this->dataCollector->collectViewVariables($form2View);
448+
$this->dataCollector->buildFinalFormTree($form2, $form2View);
449+
450+
$this->dataCollector->serialize();
451+
}
452+
345453
public function testFinalFormReliesOnFormViewStructure()
346454
{
347455
$this->form->add($child1 = $this->createForm('first'));

0 commit comments

Comments
 (0)