diff --git a/src/Symfony/Component/Validator/Context/ExecutionContext.php b/src/Symfony/Component/Validator/Context/ExecutionContext.php index 7ca9caa80fefb..44427c8489cca 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContext.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContext.php @@ -20,6 +20,7 @@ use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Mapping\PropertyMetadataInterface; use Symfony\Component\Validator\Util\PropertyPath; +use Symfony\Component\Validator\Validator\LazyProperty; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Violation\ConstraintViolationBuilder; @@ -187,7 +188,7 @@ public function addViolation($message, array $parameters = []) $parameters, $this->root, $this->propertyPath, - $this->value, + $this->getValue(), null, null, $this->constraint @@ -206,7 +207,7 @@ public function buildViolation($message, array $parameters = []) $parameters, $this->root, $this->propertyPath, - $this->value, + $this->getValue(), $this->translator, $this->translationDomain ); @@ -241,6 +242,10 @@ public function getRoot() */ public function getValue() { + if ($this->value instanceof LazyProperty) { + return $this->value->getPropertyValue(); + } + return $this->value; } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php new file mode 100644 index 0000000000000..89cae29f050c7 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +class EntityWithGroupedConstraintOnMethods +{ + public $bar; + + public function isValidInFoo() + { + return false; + } + + public function getBar() + { + throw new \Exception('Should not be called'); + } +} diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index 8109b6b9bfd4d..31871c3f9a1ed 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -14,14 +14,19 @@ use Symfony\Component\Translation\IdentityTranslator; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\GroupSequence; +use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\Context\ExecutionContextFactory; +use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB; use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods; use Symfony\Component\Validator\Validator\RecursiveValidator; class RecursiveValidatorTest extends AbstractTest @@ -117,6 +122,25 @@ public function testCollectionConstraintValidateAllGroupsForNestedConstraints() $this->assertInstanceOf(NotBlank::class, $violations->get(1)->getConstraint()); } + public function testGroupedMethodConstraintValidateInSequence() + { + $metadata = new ClassMetadata(EntityWithGroupedConstraintOnMethods::class); + $metadata->addPropertyConstraint('bar', new NotNull(['groups' => 'Foo'])); + $metadata->addGetterMethodConstraint('validInFoo', 'isValidInFoo', new IsTrue(['groups' => 'Foo'])); + $metadata->addGetterMethodConstraint('bar', 'getBar', new NotNull(['groups' => 'Bar'])); + + $this->metadataFactory->addMetadata($metadata); + + $entity = new EntityWithGroupedConstraintOnMethods(); + $groups = new GroupSequence(['EntityWithGroupedConstraintOnMethods', 'Foo', 'Bar']); + + $violations = $this->validator->validate($entity, null, $groups); + + $this->assertCount(2, $violations); + $this->assertInstanceOf(NotNull::class, $violations->get(0)->getConstraint()); + $this->assertInstanceOf(IsTrue::class, $violations->get(1)->getConstraint()); + } + public function testAllConstraintValidateAllGroupsForNestedConstraints() { $this->metadata->addPropertyConstraint('data', new All(['constraints' => [ diff --git a/src/Symfony/Component/Validator/Validator/LazyProperty.php b/src/Symfony/Component/Validator/Validator/LazyProperty.php new file mode 100644 index 0000000000000..a0799963c150f --- /dev/null +++ b/src/Symfony/Component/Validator/Validator/LazyProperty.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Validator; + +/** + * A wrapper for a callable initializing a property from a getter. + * + * @internal + */ +class LazyProperty +{ + private $propertyValueCallback; + + public function __construct(\Closure $propertyValueCallback) + { + $this->propertyValueCallback = $propertyValueCallback; + } + + public function getPropertyValue() + { + return \call_user_func($this->propertyValueCallback); + } +} diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index dc139c36d4254..dd96247b4cf85 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -26,6 +26,7 @@ use Symfony\Component\Validator\Mapping\ClassMetadataInterface; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Mapping\GenericMetadata; +use Symfony\Component\Validator\Mapping\GetterMetadata; use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Mapping\PropertyMetadataInterface; use Symfony\Component\Validator\Mapping\TraversalStrategy; @@ -534,7 +535,13 @@ private function validateClassNode($object, $cacheKey, ClassMetadataInterface $m throw new UnsupportedMetadataException(sprintf('The property metadata instances should implement "Symfony\Component\Validator\Mapping\PropertyMetadataInterface", got: "%s".', \is_object($propertyMetadata) ? \get_class($propertyMetadata) : \gettype($propertyMetadata))); } - $propertyValue = $propertyMetadata->getPropertyValue($object); + if ($propertyMetadata instanceof GetterMetadata) { + $propertyValue = new LazyProperty(static function () use ($propertyMetadata, $object) { + return $propertyMetadata->getPropertyValue($object); + }); + } else { + $propertyValue = $propertyMetadata->getPropertyValue($object); + } $this->validateGenericNode( $propertyValue, @@ -798,6 +805,11 @@ private function validateInGroup($value, $cacheKey, MetadataInterface $metadata, $validator = $this->validatorFactory->getInstance($constraint); $validator->initialize($context); + + if ($value instanceof LazyProperty) { + $value = $value->getPropertyValue(); + } + $validator->validate($value, $constraint); } } 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