[Validator] Autovalidation: skip readonly props

This commit is contained in:
Kévin Dunglas 2019-05-12 11:42:24 +02:00
parent 6c5faef5cb
commit e7dc5e1045
No known key found for this signature in database
GPG Key ID: 4D04EBEF06AAF3A6
4 changed files with 34 additions and 4 deletions

View File

@ -71,6 +71,7 @@
<service id="validator.property_info_loader" class="Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader">
<argument type="service" id="property_info" />
<argument type="service" id="property_info" />
<argument type="service" id="property_info" />
<tag name="validator.auto_mapper" />
</service>

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Validator\Mapping\Loader;
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\PropertyInfo\Type as PropertyInfoType;
@ -29,12 +30,14 @@ final class PropertyInfoLoader implements LoaderInterface
{
private $listExtractor;
private $typeExtractor;
private $accessExtractor;
private $classValidatorRegexp;
public function __construct(PropertyListExtractorInterface $listExtractor, PropertyTypeExtractorInterface $typeExtractor, string $classValidatorRegexp = null)
public function __construct(PropertyListExtractorInterface $listExtractor, PropertyTypeExtractorInterface $typeExtractor, PropertyAccessExtractorInterface $accessExtractor, string $classValidatorRegexp = null)
{
$this->listExtractor = $listExtractor;
$this->typeExtractor = $typeExtractor;
$this->accessExtractor = $accessExtractor;
$this->classValidatorRegexp = $classValidatorRegexp;
}
@ -53,6 +56,10 @@ final class PropertyInfoLoader implements LoaderInterface
}
foreach ($properties as $property) {
if (false === $this->accessExtractor->isWritable($className, $property)) {
continue;
}
$types = $this->typeExtractor->getTypes($className, $property);
if (null === $types) {
continue;

View File

@ -46,4 +46,6 @@ class PropertyInfoLoaderEntity
* })
*/
public $alreadyPartiallyMappedCollection;
public $readOnly;
}

View File

@ -45,6 +45,7 @@ class PropertyInfoLoaderTest extends TestCase
'alreadyMappedNotNull',
'alreadyMappedNotBlank',
'alreadyPartiallyMappedCollection',
'readOnly',
])
;
$propertyInfoStub
@ -58,11 +59,27 @@ class PropertyInfoLoaderTest extends TestCase
[new Type(Type::BUILTIN_TYPE_FLOAT, true)], // The existing constraint is float
[new Type(Type::BUILTIN_TYPE_STRING, true)],
[new Type(Type::BUILTIN_TYPE_STRING, true)],
[new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, null, new Type(Type::BUILTIN_TYPE_FLOAT))]
[new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, null, new Type(Type::BUILTIN_TYPE_FLOAT))],
[new Type(Type::BUILTIN_TYPE_STRING)]
))
;
$propertyInfoStub
->method('isWritable')
->will($this->onConsecutiveCalls(
true,
true,
true,
true,
true,
true,
true,
true,
true,
false
))
;
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub);
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub);
$validator = Validation::createValidatorBuilder()
->enableAnnotationMapping()
@ -137,6 +154,9 @@ class PropertyInfoLoaderTest extends TestCase
$this->assertSame('string', $alreadyPartiallyMappedCollectionConstraints[0]->constraints[0]->type);
$this->assertInstanceOf(Iban::class, $alreadyPartiallyMappedCollectionConstraints[0]->constraints[1]);
$this->assertInstanceOf(NotNull::class, $alreadyPartiallyMappedCollectionConstraints[0]->constraints[2]);
$readOnlyMetadata = $classMetadata->getPropertyMetadata('readOnly');
$this->assertEmpty($readOnlyMetadata);
}
/**
@ -154,7 +174,7 @@ class PropertyInfoLoaderTest extends TestCase
->willReturn([new Type(Type::BUILTIN_TYPE_STRING)])
;
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $classValidatorRegexp);
$propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub, $classValidatorRegexp);
$classMetadata = new ClassMetadata(PropertyInfoLoaderEntity::class);
$this->assertSame($expected, $propertyInfoLoader->loadClassMetadata($classMetadata));