Skip to content

Commit 82624ad

Browse files
Merge branch '4.3' into 4.4
* 4.3: [OptionsResolve] Revert change in tests for a not-merged change in code [HttpClient] fix handling of 3xx with no Location header - ignore Content-Length when no body is expected [Workflow] Made the configuration more robust for the 'property' key [Security/Core] make NativePasswordEncoder use sodium to validate passwords when possible #30432 fix an error message fix paths to detect code owners [HttpClient] ignore the body of responses to HEAD requests [Validator] Ensure numeric subpaths do not cause errors on PHP 7.4 [SecurityBundle] Fix wrong assertion Remove unused local variables in tests [Yaml][Parser] Remove the getLastLineNumberBeforeDeprecation() internal unused method Make sure to collect child forms created on *_SET_DATA events [WebProfilerBundle] Improve display in Email panel for dark theme do not render errors for checkboxes twice
2 parents d40acaa + 1134c09 commit 82624ad

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

Extension/DataCollector/FormDataCollector.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ public function collectDefaultData(FormInterface $form)
131131
$hash = spl_object_hash($form);
132132

133133
if (!isset($this->dataByForm[$hash])) {
134-
$this->dataByForm[$hash] = [];
134+
// field was created by form event
135+
$this->collectConfiguration($form);
135136
}
136137

137138
$this->dataByForm[$hash] = array_replace(

Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,10 @@ public function testTransformRequiresValidDateTime()
181181

182182
public function testTransformWrapsIntlErrors()
183183
{
184-
$transformer = new DateTimeToLocalizedStringTransformer();
185-
186184
$this->markTestIncomplete('Checking for intl errors needs to be reimplemented');
187185

186+
$transformer = new DateTimeToLocalizedStringTransformer();
187+
188188
// HOW TO REPRODUCE?
189189
190190
//$this->expectException('Symfony\Component\Form\Extension\Core\DataTransformer\TransformationFailedException');

Tests/Extension/DataCollector/FormDataCollectorTest.php

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,20 @@
1313

1414
use PHPUnit\Framework\MockObject\MockObject;
1515
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\EventDispatcher\EventDispatcher;
17+
use Symfony\Component\Form\Extension\Core\CoreExtension;
18+
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
19+
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
20+
use Symfony\Component\Form\Extension\Core\Type\FormType;
21+
use Symfony\Component\Form\Extension\Core\Type\TextType;
1622
use Symfony\Component\Form\Extension\DataCollector\FormDataCollector;
1723
use Symfony\Component\Form\Form;
1824
use Symfony\Component\Form\FormBuilder;
25+
use Symfony\Component\Form\FormFactory;
26+
use Symfony\Component\Form\FormInterface;
27+
use Symfony\Component\Form\FormRegistry;
1928
use Symfony\Component\Form\FormView;
29+
use Symfony\Component\Form\ResolvedFormTypeFactory;
2030

2131
class FormDataCollectorTest extends TestCase
2232
{
@@ -69,9 +79,9 @@ protected function setUp(): void
6979
{
7080
$this->dataExtractor = $this->getMockBuilder('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface')->getMock();
7181
$this->dataCollector = new FormDataCollector($this->dataExtractor);
72-
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
73-
$this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
74-
$this->dataMapper = $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock();
82+
$this->dispatcher = new EventDispatcher();
83+
$this->factory = new FormFactory(new FormRegistry([new CoreExtension()], new ResolvedFormTypeFactory()));
84+
$this->dataMapper = new PropertyPathMapper();
7585
$this->form = $this->createForm('name');
7686
$this->childForm = $this->createForm('child');
7787
$this->view = new FormView();
@@ -726,6 +736,56 @@ public function testReset()
726736
);
727737
}
728738

739+
public function testCollectMissingDataFromChildFormAddedOnFormEvents()
740+
{
741+
$form = $this->factory->createNamedBuilder('root', FormType::class, ['items' => null])
742+
->add('items', CollectionType::class, [
743+
'entry_type' => TextType::class,
744+
'allow_add' => true,
745+
// data is locked and modelData (null) is different to the
746+
// configured data, so modifications of the configured data
747+
// won't be allowed at this point. It also means *_SET_DATA
748+
// events won't dispatched either. Therefore, no child form
749+
// is created during the mapping of data to the form.
750+
'data' => ['foo'],
751+
])
752+
->getForm()
753+
;
754+
$this->dataExtractor->expects($extractConfiguration = $this->exactly(4))
755+
->method('extractConfiguration')
756+
->willReturn([])
757+
;
758+
$this->dataExtractor->expects($extractDefaultData = $this->exactly(4))
759+
->method('extractDefaultData')
760+
->willReturnCallback(static function (FormInterface $form) {
761+
// this simulate the call in extractDefaultData() method
762+
// where (if defaultDataSet is false) it fires *_SET_DATA
763+
// events, adding the form related to the configured data
764+
$form->getNormData();
765+
766+
return [];
767+
})
768+
;
769+
$this->dataExtractor->expects($this->exactly(4))
770+
->method('extractSubmittedData')
771+
->willReturn([])
772+
;
773+
774+
$this->dataCollector->collectConfiguration($form);
775+
$this->assertSame(2, $extractConfiguration->getInvocationCount(), 'only "root" and "items" forms were collected, the "items" children do not exist yet.');
776+
777+
$this->dataCollector->collectDefaultData($form);
778+
$this->assertSame(3, $extractConfiguration->getInvocationCount(), 'extracted missing configuration of the "items" children ["0" => foo].');
779+
$this->assertSame(3, $extractDefaultData->getInvocationCount());
780+
$this->assertSame(['foo'], $form->get('items')->getData());
781+
782+
$form->submit(['items' => ['foo', 'bar']]);
783+
$this->dataCollector->collectSubmittedData($form);
784+
$this->assertSame(4, $extractConfiguration->getInvocationCount(), 'extracted missing configuration of the "items" children ["1" => bar].');
785+
$this->assertSame(4, $extractDefaultData->getInvocationCount(), 'extracted missing default data of the "items" children ["1" => bar].');
786+
$this->assertSame(['foo', 'bar'], $form->get('items')->getData());
787+
}
788+
729789
private function createForm($name)
730790
{
731791
$builder = new FormBuilder($name, null, $this->dispatcher, $this->factory);

0 commit comments

Comments
 (0)