[Validator] Fixed calling getters before resolving groups
This commit is contained in:
parent
a562ba23df
commit
edcfd600aa
@ -20,6 +20,7 @@ use Symfony\Component\Validator\Mapping\MemberMetadata;
|
|||||||
use Symfony\Component\Validator\Mapping\MetadataInterface;
|
use Symfony\Component\Validator\Mapping\MetadataInterface;
|
||||||
use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
|
use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
|
||||||
use Symfony\Component\Validator\Util\PropertyPath;
|
use Symfony\Component\Validator\Util\PropertyPath;
|
||||||
|
use Symfony\Component\Validator\Validator\LazyProperty;
|
||||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
use Symfony\Component\Validator\Violation\ConstraintViolationBuilder;
|
use Symfony\Component\Validator\Violation\ConstraintViolationBuilder;
|
||||||
|
|
||||||
@ -187,7 +188,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||||||
$parameters,
|
$parameters,
|
||||||
$this->root,
|
$this->root,
|
||||||
$this->propertyPath,
|
$this->propertyPath,
|
||||||
$this->value,
|
$this->getValue(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
$this->constraint
|
$this->constraint
|
||||||
@ -206,7 +207,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||||||
$parameters,
|
$parameters,
|
||||||
$this->root,
|
$this->root,
|
||||||
$this->propertyPath,
|
$this->propertyPath,
|
||||||
$this->value,
|
$this->getValue(),
|
||||||
$this->translator,
|
$this->translator,
|
||||||
$this->translationDomain
|
$this->translationDomain
|
||||||
);
|
);
|
||||||
@ -241,6 +242,10 @@ class ExecutionContext implements ExecutionContextInterface
|
|||||||
*/
|
*/
|
||||||
public function getValue()
|
public function getValue()
|
||||||
{
|
{
|
||||||
|
if ($this->value instanceof LazyProperty) {
|
||||||
|
return $this->value->getPropertyValue();
|
||||||
|
}
|
||||||
|
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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');
|
||||||
|
}
|
||||||
|
}
|
@ -14,14 +14,19 @@ namespace Symfony\Component\Validator\Tests\Validator;
|
|||||||
use Symfony\Component\Translation\IdentityTranslator;
|
use Symfony\Component\Translation\IdentityTranslator;
|
||||||
use Symfony\Component\Validator\Constraints\All;
|
use Symfony\Component\Validator\Constraints\All;
|
||||||
use Symfony\Component\Validator\Constraints\Collection;
|
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\Length;
|
||||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotNull;
|
||||||
use Symfony\Component\Validator\ConstraintValidatorFactory;
|
use Symfony\Component\Validator\ConstraintValidatorFactory;
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextFactory;
|
use Symfony\Component\Validator\Context\ExecutionContextFactory;
|
||||||
|
use Symfony\Component\Validator\Mapping\ClassMetadata;
|
||||||
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
|
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
|
||||||
use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA;
|
use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA;
|
||||||
use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB;
|
use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB;
|
||||||
use Symfony\Component\Validator\Tests\Fixtures\Entity;
|
use Symfony\Component\Validator\Tests\Fixtures\Entity;
|
||||||
|
use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods;
|
||||||
use Symfony\Component\Validator\Validator\RecursiveValidator;
|
use Symfony\Component\Validator\Validator\RecursiveValidator;
|
||||||
|
|
||||||
class RecursiveValidatorTest extends AbstractTest
|
class RecursiveValidatorTest extends AbstractTest
|
||||||
@ -117,6 +122,25 @@ class RecursiveValidatorTest extends AbstractTest
|
|||||||
$this->assertInstanceOf(NotBlank::class, $violations->get(1)->getConstraint());
|
$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()
|
public function testAllConstraintValidateAllGroupsForNestedConstraints()
|
||||||
{
|
{
|
||||||
$this->metadata->addPropertyConstraint('data', new All(['constraints' => [
|
$this->metadata->addPropertyConstraint('data', new All(['constraints' => [
|
||||||
|
32
src/Symfony/Component/Validator/Validator/LazyProperty.php
Normal file
32
src/Symfony/Component/Validator/Validator/LazyProperty.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ use Symfony\Component\Validator\Mapping\CascadingStrategy;
|
|||||||
use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
|
use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
|
||||||
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
|
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
|
||||||
use Symfony\Component\Validator\Mapping\GenericMetadata;
|
use Symfony\Component\Validator\Mapping\GenericMetadata;
|
||||||
|
use Symfony\Component\Validator\Mapping\GetterMetadata;
|
||||||
use Symfony\Component\Validator\Mapping\MetadataInterface;
|
use Symfony\Component\Validator\Mapping\MetadataInterface;
|
||||||
use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
|
use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
|
||||||
use Symfony\Component\Validator\Mapping\TraversalStrategy;
|
use Symfony\Component\Validator\Mapping\TraversalStrategy;
|
||||||
@ -534,7 +535,13 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
|
|||||||
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)));
|
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($propertyMetadata instanceof GetterMetadata) {
|
||||||
|
$propertyValue = new LazyProperty(static function () use ($propertyMetadata, $object) {
|
||||||
|
return $propertyMetadata->getPropertyValue($object);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
$propertyValue = $propertyMetadata->getPropertyValue($object);
|
$propertyValue = $propertyMetadata->getPropertyValue($object);
|
||||||
|
}
|
||||||
|
|
||||||
$this->validateGenericNode(
|
$this->validateGenericNode(
|
||||||
$propertyValue,
|
$propertyValue,
|
||||||
@ -798,6 +805,11 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
|
|||||||
|
|
||||||
$validator = $this->validatorFactory->getInstance($constraint);
|
$validator = $this->validatorFactory->getInstance($constraint);
|
||||||
$validator->initialize($context);
|
$validator->initialize($context);
|
||||||
|
|
||||||
|
if ($value instanceof LazyProperty) {
|
||||||
|
$value = $value->getPropertyValue();
|
||||||
|
}
|
||||||
|
|
||||||
$validator->validate($value, $constraint);
|
$validator->validate($value, $constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user