Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c59889e

Browse filesBrowse files
ph-fritschexabbuh
authored andcommitted
silently ignore uninitialized properties when mapping data to forms
1 parent c0181c7 commit c59889e
Copy full SHA for c59889e

File tree

3 files changed

+64
-5
lines changed
Filter options

3 files changed

+64
-5
lines changed

‎src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php
+21-3Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Symfony\Component\Form\DataMapperInterface;
1515
use Symfony\Component\Form\Exception\UnexpectedTypeException;
16+
use Symfony\Component\PropertyAccess\Exception\AccessException;
17+
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
1618
use Symfony\Component\PropertyAccess\PropertyAccess;
1719
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
1820

@@ -46,7 +48,7 @@ public function mapDataToForms($data, $forms)
4648
$config = $form->getConfig();
4749

4850
if (!$empty && null !== $propertyPath && $config->getMapped()) {
49-
$form->setData($this->propertyAccessor->getValue($data, $propertyPath));
51+
$form->setData($this->getPropertyValue($data, $propertyPath));
5052
} else {
5153
$form->setData($config->getData());
5254
}
@@ -76,16 +78,32 @@ public function mapFormsToData($forms, &$data)
7678
$propertyValue = $form->getData();
7779
// If the field is of type DateTimeInterface and the data is the same skip the update to
7880
// keep the original object hash
79-
if ($propertyValue instanceof \DateTimeInterface && $propertyValue == $this->propertyAccessor->getValue($data, $propertyPath)) {
81+
if ($propertyValue instanceof \DateTimeInterface && $propertyValue == $this->getPropertyValue($data, $propertyPath)) {
8082
continue;
8183
}
8284

8385
// If the data is identical to the value in $data, we are
8486
// dealing with a reference
85-
if (!\is_object($data) || !$config->getByReference() || $propertyValue !== $this->propertyAccessor->getValue($data, $propertyPath)) {
87+
if (!\is_object($data) || !$config->getByReference() || $propertyValue !== $this->getPropertyValue($data, $propertyPath)) {
8688
$this->propertyAccessor->setValue($data, $propertyPath, $propertyValue);
8789
}
8890
}
8991
}
9092
}
93+
94+
private function getPropertyValue($data, $propertyPath)
95+
{
96+
try {
97+
return $this->propertyAccessor->getValue($data, $propertyPath);
98+
} catch (AccessException $e) {
99+
if (!$e instanceof UninitializedPropertyException
100+
// For versions without UninitializedPropertyException check the exception message
101+
&& (class_exists(UninitializedPropertyException::class) || false === strpos($e->getMessage(), 'You should initialize it'))
102+
) {
103+
throw $e;
104+
}
105+
106+
return null;
107+
}
108+
}
91109
}

‎src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php
+35-2Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
1818
use Symfony\Component\Form\Form;
1919
use Symfony\Component\Form\FormConfigBuilder;
20+
use Symfony\Component\Form\Tests\Fixtures\TypehintedPropertiesCar;
2021
use Symfony\Component\PropertyAccess\PropertyAccess;
2122
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
2223
use Symfony\Component\PropertyAccess\PropertyPath;
@@ -113,6 +114,23 @@ public function testMapDataToFormsIgnoresUnmapped()
113114
$this->assertNull($form->getData());
114115
}
115116

117+
/**
118+
* @requires PHP 7.4
119+
*/
120+
public function testMapDataToFormsIgnoresUninitializedProperties()
121+
{
122+
$engineForm = new Form(new FormConfigBuilder('engine', null, $this->dispatcher));
123+
$colorForm = new Form(new FormConfigBuilder('color', null, $this->dispatcher));
124+
125+
$car = new TypehintedPropertiesCar();
126+
$car->engine = 'BMW';
127+
128+
$this->mapper->mapDataToForms($car, [$engineForm, $colorForm]);
129+
130+
$this->assertSame($car->engine, $engineForm->getData());
131+
$this->assertNull($colorForm->getData());
132+
}
133+
116134
public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull()
117135
{
118136
$default = new \stdClass();
@@ -293,13 +311,28 @@ public function testMapFormsToDataIgnoresDisabled()
293311
$config->setPropertyPath($propertyPath);
294312
$config->setData($engine);
295313
$config->setDisabled(true);
296-
$form = new Form($config);
314+
$form = new SubmittedForm($config);
297315

298316
$this->mapper->mapFormsToData([$form], $car);
299317

300318
$this->assertSame($initialEngine, $car->engine);
301319
}
302320

321+
/**
322+
* @requires PHP 7.4
323+
*/
324+
public function testMapFormsToUninitializedProperties()
325+
{
326+
$car = new TypehintedPropertiesCar();
327+
$config = new FormConfigBuilder('engine', null, $this->dispatcher);
328+
$config->setData('BMW');
329+
$form = new SubmittedForm($config);
330+
331+
$this->mapper->mapFormsToData([$form], $car);
332+
333+
$this->assertSame('BMW', $car->engine);
334+
}
335+
303336
/**
304337
* @dataProvider provideDate
305338
*/
@@ -339,7 +372,7 @@ public function isSubmitted()
339372
}
340373
}
341374

342-
class NotSynchronizedForm extends Form
375+
class NotSynchronizedForm extends SubmittedForm
343376
{
344377
public function isSynchronized()
345378
{
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace Symfony\Component\Form\Tests\Fixtures;
3+
4+
class TypehintedPropertiesCar
5+
{
6+
public ?string $engine;
7+
public ?string $color;
8+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.