Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4c91f52

Browse files
committed
[Validator] Fixed calling getters before resolving groups
1 parent a562ba2 commit 4c91f52

File tree

5 files changed

+103
-3
lines changed

5 files changed

+103
-3
lines changed

src/Symfony/Component/Validator/Context/ExecutionContext.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Validator\Mapping\MetadataInterface;
2121
use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
2222
use Symfony\Component\Validator\Util\PropertyPath;
23+
use Symfony\Component\Validator\Validator\LazyProperty;
2324
use Symfony\Component\Validator\Validator\ValidatorInterface;
2425
use Symfony\Component\Validator\Violation\ConstraintViolationBuilder;
2526

@@ -187,7 +188,7 @@ public function addViolation($message, array $parameters = [])
187188
$parameters,
188189
$this->root,
189190
$this->propertyPath,
190-
$this->value,
191+
$this->getValue(),
191192
null,
192193
null,
193194
$this->constraint
@@ -206,7 +207,7 @@ public function buildViolation($message, array $parameters = [])
206207
$parameters,
207208
$this->root,
208209
$this->propertyPath,
209-
$this->value,
210+
$this->getValue(),
210211
$this->translator,
211212
$this->translationDomain
212213
);
@@ -241,6 +242,10 @@ public function getRoot()
241242
*/
242243
public function getValue()
243244
{
245+
if ($this->value instanceof LazyProperty) {
246+
return $this->value->getPropertyValue();
247+
}
248+
244249
return $this->value;
245250
}
246251

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Fixtures;
13+
14+
use Symfony\Component\Validator\Constraints as Assert;
15+
16+
class EntityWithGroupedConstraintOnMethods
17+
{
18+
public $bar;
19+
20+
public function isValidInFoo()
21+
{
22+
return false;
23+
}
24+
25+
public function getBar()
26+
{
27+
throw new \Exception('Should not be called');
28+
}
29+
}

src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@
1414
use Symfony\Component\Translation\IdentityTranslator;
1515
use Symfony\Component\Validator\Constraints\All;
1616
use Symfony\Component\Validator\Constraints\Collection;
17+
use Symfony\Component\Validator\Constraints\GroupSequence;
18+
use Symfony\Component\Validator\Constraints\IsTrue;
1719
use Symfony\Component\Validator\Constraints\Length;
1820
use Symfony\Component\Validator\Constraints\NotBlank;
21+
use Symfony\Component\Validator\Constraints\NotNull;
1922
use Symfony\Component\Validator\ConstraintValidatorFactory;
2023
use Symfony\Component\Validator\Context\ExecutionContextFactory;
24+
use Symfony\Component\Validator\Mapping\ClassMetadata;
2125
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
2226
use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA;
2327
use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB;
2428
use Symfony\Component\Validator\Tests\Fixtures\Entity;
29+
use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods;
2530
use Symfony\Component\Validator\Validator\RecursiveValidator;
2631

2732
class RecursiveValidatorTest extends AbstractTest
@@ -117,6 +122,23 @@ public function testCollectionConstraintValidateAllGroupsForNestedConstraints()
117122
$this->assertInstanceOf(NotBlank::class, $violations->get(1)->getConstraint());
118123
}
119124

125+
public function testGroupedMethodConstraintValidateInSequence()
126+
{
127+
$metadata = new ClassMetadata(EntityWithGroupedConstraintOnMethods::class);
128+
$metadata->addGetterMethodConstraint('validInFoo', 'isValidInFoo', new IsTrue(['groups' => 'Foo']));
129+
$metadata->addGetterMethodConstraint('bar', 'getBar', new NotNull(['groups' => 'Bar']));
130+
131+
$this->metadataFactory->addMetadata($metadata);
132+
133+
$entity = new EntityWithGroupedConstraintOnMethods();
134+
$groups = new GroupSequence(['EntityWithGroupedConstraintOnMethods', 'Foo', 'Bar']);
135+
136+
$violations = $this->validator->validate($entity, null, $groups);
137+
138+
$this->assertCount(1, $violations);
139+
$this->assertInstanceOf(IsTrue::class, $violations->get(0)->getConstraint());
140+
}
141+
120142
public function testAllConstraintValidateAllGroupsForNestedConstraints()
121143
{
122144
$this->metadata->addPropertyConstraint('data', new All(['constraints' => [
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Validator;
13+
14+
/**
15+
* A wrapper for a callable initializing a property from a getter.
16+
*
17+
* @internal
18+
*/
19+
class LazyProperty
20+
{
21+
private $propertyValueCallback;
22+
23+
public function __construct(\Closure $propertyValueCallback)
24+
{
25+
$this->propertyValueCallback = $propertyValueCallback;
26+
}
27+
28+
public function getPropertyValue()
29+
{
30+
return \call_user_func($this->propertyValueCallback);
31+
}
32+
}

src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
2727
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
2828
use Symfony\Component\Validator\Mapping\GenericMetadata;
29+
use Symfony\Component\Validator\Mapping\GetterMetadata;
2930
use Symfony\Component\Validator\Mapping\MetadataInterface;
3031
use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
3132
use Symfony\Component\Validator\Mapping\TraversalStrategy;
@@ -534,7 +535,13 @@ private function validateClassNode($object, $cacheKey, ClassMetadataInterface $m
534535
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)));
535536
}
536537

537-
$propertyValue = $propertyMetadata->getPropertyValue($object);
538+
if ($propertyMetadata instanceof GetterMetadata) {
539+
$propertyValue = new LazyProperty(static function () use ($propertyMetadata, $object) {
540+
return $propertyMetadata->getPropertyValue($object);
541+
});
542+
} else {
543+
$propertyValue = $propertyMetadata->getPropertyValue($object);
544+
}
538545

539546
$this->validateGenericNode(
540547
$propertyValue,
@@ -798,6 +805,11 @@ private function validateInGroup($value, $cacheKey, MetadataInterface $metadata,
798805

799806
$validator = $this->validatorFactory->getInstance($constraint);
800807
$validator->initialize($context);
808+
809+
if ($value instanceof LazyProperty) {
810+
$value = $value->getPropertyValue();
811+
}
812+
801813
$validator->validate($value, $constraint);
802814
}
803815
}

0 commit comments

Comments
 (0)