Skip to content

Commit e7dc5e1

Browse files
committed
[Validator] Autovalidation: skip readonly props
1 parent 6c5faef commit e7dc5e1

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
<service id="validator.property_info_loader" class="Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader">
7272
<argument type="service" id="property_info" />
7373
<argument type="service" id="property_info" />
74+
<argument type="service" id="property_info" />
7475

7576
<tag name="validator.auto_mapper" />
7677
</service>

src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Validator\Mapping\Loader;
1313

14+
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
1415
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
1516
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
1617
use Symfony\Component\PropertyInfo\Type as PropertyInfoType;
@@ -29,12 +30,14 @@ final class PropertyInfoLoader implements LoaderInterface
2930
{
3031
private $listExtractor;
3132
private $typeExtractor;
33+
private $accessExtractor;
3234
private $classValidatorRegexp;
3335

34-
public function __construct(PropertyListExtractorInterface $listExtractor, PropertyTypeExtractorInterface $typeExtractor, string $classValidatorRegexp = null)
36+
public function __construct(PropertyListExtractorInterface $listExtractor, PropertyTypeExtractorInterface $typeExtractor, PropertyAccessExtractorInterface $accessExtractor, string $classValidatorRegexp = null)
3537
{
3638
$this->listExtractor = $listExtractor;
3739
$this->typeExtractor = $typeExtractor;
40+
$this->accessExtractor = $accessExtractor;
3841
$this->classValidatorRegexp = $classValidatorRegexp;
3942
}
4043

@@ -53,6 +56,10 @@ public function loadClassMetadata(ClassMetadata $metadata)
5356
}
5457

5558
foreach ($properties as $property) {
59+
if (false === $this->accessExtractor->isWritable($className, $property)) {
60+
continue;
61+
}
62+
5663
$types = $this->typeExtractor->getTypes($className, $property);
5764
if (null === $types) {
5865
continue;

src/Symfony/Component/Validator/Tests/Fixtures/PropertyInfoLoaderEntity.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ class PropertyInfoLoaderEntity
4646
* })
4747
*/
4848
public $alreadyPartiallyMappedCollection;
49+
50+
public $readOnly;
4951
}

src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function testLoadClassMetadata()
4545
'alreadyMappedNotNull',
4646
'alreadyMappedNotBlank',
4747
'alreadyPartiallyMappedCollection',
48+
'readOnly',
4849
])
4950
;
5051
$propertyInfoStub
@@ -58,11 +59,27 @@ public function testLoadClassMetadata()
5859
[new Type(Type::BUILTIN_TYPE_FLOAT, true)], // The existing constraint is float
5960
[new Type(Type::BUILTIN_TYPE_STRING, true)],
6061
[new Type(Type::BUILTIN_TYPE_STRING, true)],
61-
[new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, null, new Type(Type::BUILTIN_TYPE_FLOAT))]
62+
[new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, null, new Type(Type::BUILTIN_TYPE_FLOAT))],
63+
[new Type(Type::BUILTIN_TYPE_STRING)]
64+
))
65+
;
66+
$propertyInfoStub
67+
->method('isWritable')
68+
->will($this->onConsecutiveCalls(
69+
true,
70+
true,
71+
true,
72+
true,
73+
true,
74+
true,
75+
true,
76+
true,
77+
true,
78+
false
6279
))
6380
;
6481

65-
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub);
82+
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub);
6683

6784
$validator = Validation::createValidatorBuilder()
6885
->enableAnnotationMapping()
@@ -137,6 +154,9 @@ public function testLoadClassMetadata()
137154
$this->assertSame('string', $alreadyPartiallyMappedCollectionConstraints[0]->constraints[0]->type);
138155
$this->assertInstanceOf(Iban::class, $alreadyPartiallyMappedCollectionConstraints[0]->constraints[1]);
139156
$this->assertInstanceOf(NotNull::class, $alreadyPartiallyMappedCollectionConstraints[0]->constraints[2]);
157+
158+
$readOnlyMetadata = $classMetadata->getPropertyMetadata('readOnly');
159+
$this->assertEmpty($readOnlyMetadata);
140160
}
141161

142162
/**
@@ -154,7 +174,7 @@ public function testClassValidator(bool $expected, string $classValidatorRegexp
154174
->willReturn([new Type(Type::BUILTIN_TYPE_STRING)])
155175
;
156176

157-
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $classValidatorRegexp);
177+
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub, $classValidatorRegexp);
158178

159179
$classMetadata = new ClassMetadata(PropertyInfoLoaderEntity::class);
160180
$this->assertSame($expected, $propertyInfoLoader->loadClassMetadata($classMetadata));

0 commit comments

Comments
 (0)