Skip to content

Commit dbeb261

Browse files
committed
Merge branch '5.4' into 6.4
* 5.4: detect wrong e-mail validation modes read form values using the chain data accessor [Validator] Review Bulgarian (bg) translation Reviewed italian translation Fix french translation call substr() with integer offsets review: FR translation Update spanish and catalan translations Updated id=113 Arabic translation. symfony#53771 Updated validator Lithuanian translations review: translation RU [PropertyInfo] Fix PHPStan properties type in trait [Validator] review validators.lv.xlf Review translation
2 parents 7c2f5a7 + 868eb11 commit dbeb261

File tree

22 files changed

+158
-56
lines changed

22 files changed

+158
-56
lines changed

src/Symfony/Component/Form/Extension/Core/DataAccessor/PropertyPathAccessor.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
namespace Symfony\Component\Form\Extension\Core\DataAccessor;
1313

1414
use Symfony\Component\Form\DataAccessorInterface;
15+
use Symfony\Component\Form\DataMapperInterface;
1516
use Symfony\Component\Form\Exception\AccessException;
17+
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
1618
use Symfony\Component\Form\FormInterface;
1719
use Symfony\Component\PropertyAccess\Exception\AccessException as PropertyAccessException;
1820
use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
@@ -51,15 +53,25 @@ public function setValue(object|array &$data, mixed $value, FormInterface $form)
5153
throw new AccessException('Unable to write the given value as no property path is defined.');
5254
}
5355

56+
$getValue = function () use ($data, $form, $propertyPath) {
57+
$dataMapper = $this->getDataMapper($form);
58+
59+
if ($dataMapper instanceof DataMapper && null !== $dataAccessor = $dataMapper->getDataAccessor()) {
60+
return $dataAccessor->getValue($data, $form);
61+
}
62+
63+
return $this->getPropertyValue($data, $propertyPath);
64+
};
65+
5466
// If the field is of type DateTimeInterface and the data is the same skip the update to
5567
// keep the original object hash
56-
if ($value instanceof \DateTimeInterface && $value == $this->getPropertyValue($data, $propertyPath)) {
68+
if ($value instanceof \DateTimeInterface && $value == $getValue()) {
5769
return;
5870
}
5971

6072
// If the data is identical to the value in $data, we are
6173
// dealing with a reference
62-
if (!\is_object($data) || !$form->getConfig()->getByReference() || $value !== $this->getPropertyValue($data, $propertyPath)) {
74+
if (!\is_object($data) || !$form->getConfig()->getByReference() || $value !== $getValue()) {
6375
$this->propertyAccessor->setValue($data, $propertyPath, $value);
6476
}
6577
}
@@ -93,4 +105,13 @@ private function getPropertyValue(object|array $data, PropertyPathInterface $pro
93105
return null;
94106
}
95107
}
108+
109+
private function getDataMapper(FormInterface $form): ?DataMapperInterface
110+
{
111+
do {
112+
$dataMapper = $form->getConfig()->getDataMapper();
113+
} while (null === $dataMapper && null !== $form = $form->getParent());
114+
115+
return $dataMapper;
116+
}
96117
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,12 @@ public function mapFormsToData(\Traversable $forms, mixed &$data): void
7474
}
7575
}
7676
}
77+
78+
/**
79+
* @internal
80+
*/
81+
public function getDataAccessor(): DataAccessorInterface
82+
{
83+
return $this->dataAccessor;
84+
}
7785
}

src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/DataMapperTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor;
1717
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
1818
use Symfony\Component\Form\Extension\Core\Type\DateType;
19+
use Symfony\Component\Form\Extension\Core\Type\FormType;
20+
use Symfony\Component\Form\Extension\Core\Type\TextType;
1921
use Symfony\Component\Form\Form;
2022
use Symfony\Component\Form\FormConfigBuilder;
2123
use Symfony\Component\Form\FormFactoryBuilder;
@@ -403,6 +405,25 @@ public function testMapFormsToDataMapsDateTimeInstanceToArrayIfNotSetBefore()
403405

404406
$this->assertEquals(['date' => new \DateTime('2022-08-04', new \DateTimeZone('UTC'))], $form->getData());
405407
}
408+
409+
public function testMapFormToDataWithOnlyGetterConfigured()
410+
{
411+
$person = new DummyPerson('foo');
412+
$form = (new FormFactoryBuilder())
413+
->getFormFactory()
414+
->createBuilder(FormType::class, $person)
415+
->add('name', TextType::class, [
416+
'getter' => function (DummyPerson $person) {
417+
return $person->myName();
418+
},
419+
])
420+
->getForm();
421+
$form->submit([
422+
'name' => 'bar',
423+
]);
424+
425+
$this->assertSame('bar', $person->myName());
426+
}
406427
}
407428

408429
class SubmittedForm extends Form
@@ -439,4 +460,9 @@ public function rename($name): void
439460
{
440461
$this->name = $name;
441462
}
463+
464+
public function setName($name): void
465+
{
466+
$this->name = $name;
467+
}
442468
}

src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@ private function getDocBlockFromProperty(string $class, string $property): ?arra
232232
return null;
233233
}
234234

235+
$reflector = $reflectionProperty->getDeclaringClass();
236+
237+
foreach ($reflector->getTraits() as $trait) {
238+
if ($trait->hasProperty($property)) {
239+
return $this->getDocBlockFromProperty($trait->getName(), $property);
240+
}
241+
}
242+
235243
// Type can be inside property docblock as `@var`
236244
$rawDocNode = $reflectionProperty->getDocComment();
237245
$phpDocNode = $rawDocNode ? $this->getPhpDocNode($rawDocNode) : null;

src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy;
2222
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80PromotedDummy;
2323
use Symfony\Component\PropertyInfo\Tests\Fixtures\RootDummy\RootDummyItem;
24+
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\AnotherNamespace\DummyInAnotherNamespace;
2425
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait;
2526
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait;
2627
use Symfony\Component\PropertyInfo\Type;
@@ -306,6 +307,7 @@ public static function propertiesDefinedByTraitsProvider(): array
306307
['propertyInTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)],
307308
['propertyInTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)],
308309
['propertyInTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)],
310+
['dummyInAnotherNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyInAnotherNamespace::class)],
309311
];
310312
}
311313

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\AnotherNamespace;
4+
5+
class DummyInAnotherNamespace
6+
{
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\AnotherNamespace;
4+
5+
trait DummyTraitInAnotherNamespace
6+
{
7+
/**
8+
* @var DummyInAnotherNamespace
9+
*/
10+
public $dummyInAnotherNamespace;
11+
}

src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsingTrait.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
namespace Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage;
1313

14+
use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\AnotherNamespace\DummyTraitInAnotherNamespace;
15+
1416
class DummyUsingTrait
1517
{
1618
use DummyTrait;
19+
use DummyTraitInAnotherNamespace;
1720
}

src/Symfony/Component/Validator/Constraints/Email.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ public function __construct(
6868
throw new InvalidArgumentException('The "mode" parameter value is not valid.');
6969
}
7070

71+
if (null !== $mode && !\in_array($mode, self::$validationModes, true)) {
72+
throw new InvalidArgumentException('The "mode" parameter value is not valid.');
73+
}
74+
7175
parent::__construct($options, $groups, $payload);
7276

7377
$this->message = $message ?? $this->message;

src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@
440440
</trans-unit>
441441
<trans-unit id="113">
442442
<source>This URL is missing a top-level domain.</source>
443-
<target state="needs-review-translation">هذا الرابط يفتقر إلى نطاق أعلى مستوى.</target>
443+
<target>هذا الرابط يفتقر إلى نطاق المستوى الأعلى.</target>
444444
</trans-unit>
445445
</body>
446446
</file>

0 commit comments

Comments
 (0)