From bc53e4bca0bd59026cf33d0ce95697660254c9ca Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 28 Nov 2019 16:20:09 +0100 Subject: [PATCH] [Validator] Fix auto-mapping constraints should not be validated --- .../Tests/Validator/DoctrineLoaderTest.php | 16 ++++--- .../Doctrine/Validator/DoctrineLoader.php | 18 ++++---- src/Symfony/Bridge/Doctrine/composer.json | 4 +- .../Validator/Mapping/AutoMappingStrategy.php | 42 +++++++++++++++++++ .../Validator/Mapping/GenericMetadata.php | 31 ++++++++++++++ .../Mapping/Loader/AutoMappingTrait.php | 13 ++---- .../Mapping/Loader/PropertyInfoLoader.php | 19 ++++----- .../Mapping/Loader/PropertyInfoLoaderTest.php | 12 ++++-- 8 files changed, 115 insertions(+), 40 deletions(-) create mode 100644 src/Symfony/Component/Validator/Mapping/AutoMappingStrategy.php diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php index 2c87b870a8e77..5ca0ea3bf61ed 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php @@ -21,11 +21,12 @@ use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderParentEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\DoctrineLoader; -use Symfony\Component\Validator\Constraints\DisableAutoMapping; use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\CascadingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AutoMappingTrait; +use Symfony\Component\Validator\Mapping\PropertyMetadata; use Symfony\Component\Validator\Mapping\TraversalStrategy; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Validation; @@ -141,11 +142,12 @@ public function testLoadClassMetadata() $this->assertInstanceOf(Length::class, $textFieldConstraints[0]); $this->assertSame(1000, $textFieldConstraints[0]->max); + /** @var PropertyMetadata[] $noAutoMappingMetadata */ $noAutoMappingMetadata = $classMetadata->getPropertyMetadata('noAutoMapping'); $this->assertCount(1, $noAutoMappingMetadata); $noAutoMappingConstraints = $noAutoMappingMetadata[0]->getConstraints(); - $this->assertCount(1, $noAutoMappingConstraints); - $this->assertInstanceOf(DisableAutoMapping::class, $noAutoMappingConstraints[0]); + $this->assertCount(0, $noAutoMappingConstraints); + $this->assertSame(AutoMappingStrategy::DISABLED, $noAutoMappingMetadata[0]->getAutoMappingStrategy()); } public function testFieldMappingsConfiguration() @@ -207,13 +209,15 @@ public function testClassNoAutoMapping() $classMetadata = $validator->getMetadataFor(new DoctrineLoaderNoAutoMappingEntity()); $classConstraints = $classMetadata->getConstraints(); - $this->assertCount(1, $classConstraints); - $this->assertInstanceOf(DisableAutoMapping::class, $classConstraints[0]); + $this->assertCount(0, $classConstraints); + $this->assertSame(AutoMappingStrategy::DISABLED, $classMetadata->getAutoMappingStrategy()); $maxLengthMetadata = $classMetadata->getPropertyMetadata('maxLength'); $this->assertEmpty($maxLengthMetadata); + /** @var PropertyMetadata[] $autoMappingExplicitlyEnabledMetadata */ $autoMappingExplicitlyEnabledMetadata = $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled'); - $this->assertCount(2, $autoMappingExplicitlyEnabledMetadata[0]->constraints); + $this->assertCount(1, $autoMappingExplicitlyEnabledMetadata[0]->constraints); + $this->assertSame(AutoMappingStrategy::ENABLED, $autoMappingExplicitlyEnabledMetadata[0]->getAutoMappingStrategy()); } } diff --git a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php index 7cfde6515ccc8..8a153c551676b 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php +++ b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php @@ -16,10 +16,9 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\MappingException as OrmMappingException; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; -use Symfony\Component\Validator\Constraints\DisableAutoMapping; -use Symfony\Component\Validator\Constraints\EnableAutoMapping; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\Valid; +use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AutoMappingTrait; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; @@ -76,13 +75,16 @@ public function loadClassMetadata(ClassMetadata $metadata): bool $enabledForProperty = $enabledForClass; $lengthConstraint = null; foreach ($metadata->getPropertyMetadata($mapping['fieldName']) as $propertyMetadata) { + // Enabling or disabling auto-mapping explicitly always takes precedence + if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) { + continue 2; + } + if (AutoMappingStrategy::ENABLED === $propertyMetadata->getAutoMappingStrategy()) { + $enabledForProperty = true; + } + foreach ($propertyMetadata->getConstraints() as $constraint) { - // Enabling or disabling auto-mapping explicitly always takes precedence - if ($constraint instanceof DisableAutoMapping) { - continue 3; - } elseif ($constraint instanceof EnableAutoMapping) { - $enabledForProperty = true; - } elseif ($constraint instanceof Length) { + if ($constraint instanceof Length) { $lengthConstraint = $constraint; } } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 8c2d65c72801d..dbb51aca3c6a9 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -35,7 +35,7 @@ "symfony/proxy-manager-bridge": "^3.4|^4.0|^5.0", "symfony/security-core": "^4.4|^5.0", "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/validator": "^4.4|^5.0", + "symfony/validator": "^4.4.1|^5.0.1", "symfony/var-dumper": "^3.4|^4.0|^5.0", "symfony/translation": "^3.4|^4.0|^5.0", "doctrine/annotations": "~1.7", @@ -53,7 +53,7 @@ "symfony/http-kernel": "<4.3.7", "symfony/messenger": "<4.3", "symfony/security-core": "<4.4", - "symfony/validator": "<4.4" + "symfony/validator": "<4.4.1|<5.0.1,>=5.0" }, "suggest": { "symfony/form": "", diff --git a/src/Symfony/Component/Validator/Mapping/AutoMappingStrategy.php b/src/Symfony/Component/Validator/Mapping/AutoMappingStrategy.php new file mode 100644 index 0000000000000..4012ddcff9c05 --- /dev/null +++ b/src/Symfony/Component/Validator/Mapping/AutoMappingStrategy.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Mapping; + +/** + * Specifies how the auto-mapping feature should behave. + * + * @author Maxime Steinhausser + */ +final class AutoMappingStrategy +{ + /** + * Nothing explicitly set, rely on auto-mapping configured regex. + */ + public const NONE = 0; + + /** + * Explicitly enabled. + */ + public const ENABLED = 1; + + /** + * Explicitly disabled. + */ + public const DISABLED = 2; + + /** + * Not instantiable. + */ + private function __construct() + { + } +} diff --git a/src/Symfony/Component/Validator/Mapping/GenericMetadata.php b/src/Symfony/Component/Validator/Mapping/GenericMetadata.php index 43db82ecca0c9..40e447a6f4dde 100644 --- a/src/Symfony/Component/Validator/Mapping/GenericMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/GenericMetadata.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\DisableAutoMapping; +use Symfony\Component\Validator\Constraints\EnableAutoMapping; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Traverse; @@ -75,6 +77,19 @@ class GenericMetadata implements MetadataInterface */ public $traversalStrategy = TraversalStrategy::NONE; + /** + * Is auto-mapping enabled? + * + * @var int + * + * @see AutoMappingStrategy + * + * @internal This property is public in order to reduce the size of the + * class' serialized representation. Do not access it. Use + * {@link getAutoMappingStrategy()} instead. + */ + public $autoMappingStrategy = AutoMappingStrategy::NONE; + /** * Returns the names of the properties that should be serialized. * @@ -87,6 +102,7 @@ public function __sleep() 'constraintsByGroup', 'cascadingStrategy', 'traversalStrategy', + 'autoMappingStrategy', ]; } @@ -139,6 +155,13 @@ public function addConstraint(Constraint $constraint) return $this; } + if ($constraint instanceof DisableAutoMapping || $constraint instanceof EnableAutoMapping) { + $this->autoMappingStrategy = $constraint instanceof EnableAutoMapping ? AutoMappingStrategy::ENABLED : AutoMappingStrategy::DISABLED; + + // The constraint is not added + return $this; + } + $this->constraints[] = $constraint; foreach ($constraint->groups as $group) { @@ -213,6 +236,14 @@ public function getTraversalStrategy() return $this->traversalStrategy; } + /** + * @see AutoMappingStrategy + */ + public function getAutoMappingStrategy(): int + { + return $this->autoMappingStrategy; + } + private function configureLengthConstraints(array $constraints): void { $allowEmptyString = true; diff --git a/src/Symfony/Component/Validator/Mapping/Loader/AutoMappingTrait.php b/src/Symfony/Component/Validator/Mapping/Loader/AutoMappingTrait.php index 1c21810763557..66508823234e1 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/AutoMappingTrait.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/AutoMappingTrait.php @@ -11,8 +11,7 @@ namespace Symfony\Component\Validator\Mapping\Loader; -use Symfony\Component\Validator\Constraints\DisableAutoMapping; -use Symfony\Component\Validator\Constraints\EnableAutoMapping; +use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; /** @@ -25,14 +24,8 @@ trait AutoMappingTrait private function isAutoMappingEnabledForClass(ClassMetadata $metadata, string $classValidatorRegexp = null): bool { // Check if AutoMapping constraint is set first - foreach ($metadata->getConstraints() as $constraint) { - if ($constraint instanceof DisableAutoMapping) { - return false; - } - - if ($constraint instanceof EnableAutoMapping) { - return true; - } + if (AutoMappingStrategy::NONE !== $strategy = $metadata->getAutoMappingStrategy()) { + return AutoMappingStrategy::ENABLED === $strategy; } // Fallback on the config diff --git a/src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php index e2ad9cb9ec9e5..530348c638448 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/PropertyInfoLoader.php @@ -16,11 +16,10 @@ use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\PropertyInfo\Type as PropertyInfoType; use Symfony\Component\Validator\Constraints\All; -use Symfony\Component\Validator\Constraints\DisableAutoMapping; -use Symfony\Component\Validator\Constraints\EnableAutoMapping; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Type; +use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; /** @@ -77,16 +76,16 @@ public function loadClassMetadata(ClassMetadata $metadata): bool $hasNotBlankConstraint = false; $allConstraint = null; foreach ($metadata->getPropertyMetadata($property) as $propertyMetadata) { - foreach ($propertyMetadata->getConstraints() as $constraint) { - // Enabling or disabling auto-mapping explicitly always takes precedence - if ($constraint instanceof DisableAutoMapping) { - continue 3; - } + // Enabling or disabling auto-mapping explicitly always takes precedence + if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) { + continue 2; + } - if ($constraint instanceof EnableAutoMapping) { - $enabledForProperty = true; - } + if (AutoMappingStrategy::ENABLED === $propertyMetadata->getAutoMappingStrategy()) { + $enabledForProperty = true; + } + foreach ($propertyMetadata->getConstraints() as $constraint) { if ($constraint instanceof Type) { $hasTypeConstraint = true; } elseif ($constraint instanceof NotNull) { diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index 8e122dcdd872e..755797c21ef63 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -15,13 +15,14 @@ use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraints\All; -use Symfony\Component\Validator\Constraints\DisableAutoMapping; use Symfony\Component\Validator\Constraints\Iban; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Type as TypeConstraint; +use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; +use Symfony\Component\Validator\Mapping\PropertyMetadata; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\PropertyInfoLoaderEntity; use Symfony\Component\Validator\Tests\Fixtures\PropertyInfoLoaderNoAutoMappingEntity; @@ -164,11 +165,12 @@ public function testLoadClassMetadata() $readOnlyMetadata = $classMetadata->getPropertyMetadata('readOnly'); $this->assertEmpty($readOnlyMetadata); + /** @var PropertyMetadata[] $noAutoMappingMetadata */ $noAutoMappingMetadata = $classMetadata->getPropertyMetadata('noAutoMapping'); $this->assertCount(1, $noAutoMappingMetadata); + $this->assertSame(AutoMappingStrategy::DISABLED, $noAutoMappingMetadata[0]->getAutoMappingStrategy()); $noAutoMappingConstraints = $noAutoMappingMetadata[0]->getConstraints(); - $this->assertCount(1, $noAutoMappingConstraints); - $this->assertInstanceOf(DisableAutoMapping::class, $noAutoMappingConstraints[0]); + $this->assertCount(0, $noAutoMappingConstraints, 'DisableAutoMapping constraint is not added in the list'); } /** @@ -222,8 +224,10 @@ public function testClassNoAutoMapping() ->getValidator() ; + /** @var ClassMetadata $classMetadata */ $classMetadata = $validator->getMetadataFor(new PropertyInfoLoaderNoAutoMappingEntity()); $this->assertEmpty($classMetadata->getPropertyMetadata('string')); - $this->assertCount(3, $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled')[0]->constraints); + $this->assertCount(2, $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled')[0]->constraints); + $this->assertSame(AutoMappingStrategy::ENABLED, $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled')[0]->getAutoMappingStrategy()); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy