bug #20745 [Validator] add class name to the cache key (Simperfit)

This PR was squashed before being merged into the 3.1 branch (closes #20745).

Discussion
----------

[Validator] add class name to the cache key

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |  #20685
| License       | MIT
| Doc PR        |

Adding the class name to the cache key to avoid collision

Commits
-------

1681fc9 [Validator] add class name to the cache key
This commit is contained in:
Nicolas Grekas 2016-12-08 16:05:14 +01:00
commit bf9f5f0a25
6 changed files with 148 additions and 3 deletions

View File

@ -0,0 +1,30 @@
<?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\Constraints\Fixtures;
use Symfony\Component\Validator\Constraints as Assert;
class ChildA
{
/**
* @Assert\Valid
* @Assert\NotNull
* @Assert\NotBlank
*/
public $name;
/**
* @var ChildB
* @Assert\Valid
* @Assert\NotNull
*/
public $childB;
}

View File

@ -0,0 +1,29 @@
<?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\Constraints\Fixtures;
use Symfony\Component\Validator\Constraints as Assert;
class ChildB
{
/**
* @Assert\Valid
* @Assert\NotBlank
*/
public $name;
/**
* @var ChildA
* @Assert\Valid
* @Assert\NotBlank
*/
public $childA;
}

View File

@ -33,6 +33,14 @@ class Entity extends EntityParent implements EntityInterfaceB
* @Assert\Choice(choices={"A", "B"}, message="Must be one of %choices%")
*/
public $firstName;
/**
* @Assert\Valid
*/
public $childA;
/**
* @Assert\Valid
*/
public $childB;
protected $lastName;
public $reference;
public $reference2;
@ -97,4 +105,36 @@ class Entity extends EntityParent implements EntityInterfaceB
public static function validateMeStatic($object, ExecutionContextInterface $context)
{
}
/**
* @return mixed
*/
public function getChildA()
{
return $this->childA;
}
/**
* @param mixed $childA
*/
public function setChildA($childA)
{
$this->childA = $childA;
}
/**
* @return mixed
*/
public function getChildB()
{
return $this->childB;
}
/**
* @param mixed $childB
*/
public function setChildB($childB)
{
$this->childB = $childB;
}
}

View File

@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
@ -67,6 +68,8 @@ class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
'message' => 'Must be one of %choices%',
'choices' => array('A', 'B'),
)));
$expected->addPropertyConstraint('childA', new Valid());
$expected->addPropertyConstraint('childB', new Valid());
$expected->addGetterConstraint('lastName', new NotNull());
$expected->addGetterConstraint('valid', new IsTrue());
$expected->addGetterConstraint('permissions', new IsTrue());
@ -137,6 +140,8 @@ class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
'message' => 'Must be one of %choices%',
'choices' => array('A', 'B'),
)));
$expected->addPropertyConstraint('childA', new Valid());
$expected->addPropertyConstraint('childB', new Valid());
$expected->addGetterConstraint('lastName', new NotNull());
$expected->addGetterConstraint('valid', new IsTrue());
$expected->addGetterConstraint('permissions', new IsTrue());

View File

@ -15,6 +15,8 @@ use Symfony\Component\Translation\IdentityTranslator;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Context\ExecutionContextFactory;
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\Validator\RecursiveValidator;
@ -34,6 +36,45 @@ class RecursiveValidatorTest extends AbstractTest
public function testEmptyGroupsArrayDoesNotTriggerDeprecation()
{
$entity = new Entity();
$childA = new ChildA();
$childB = new ChildB();
$childA->name = false;
$childB->name = 'fake';
$entity->childA = array($childA);
$entity->childB = array($childB);
$validatorContext = $this->getMock('Symfony\Component\Validator\Validator\ContextualValidatorInterface');
$validatorContext
->expects($this->once())
->method('validate')
->with($entity, null, array())
->willReturnSelf();
$validator = $this
->getMockBuilder('Symfony\Component\Validator\Validator\RecursiveValidator')
->disableOriginalConstructor()
->setMethods(array('startContext'))
->getMock();
$validator
->expects($this->once())
->method('startContext')
->willReturn($validatorContext);
$validator->validate($entity, null, array());
}
public function testRelationBetweenChildAAndChildB()
{
$entity = new Entity();
$childA = new ChildA();
$childB = new ChildB();
$childA->childB = $childB;
$childB->childA = $childA;
$childA->name = false;
$childB->name = 'fake';
$entity->childA = array($childA);
$entity->childB = array($childB);
$validatorContext = $this->getMock('Symfony\Component\Validator\Validator\ContextualValidatorInterface');
$validatorContext

View File

@ -224,7 +224,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
$this->validateGenericNode(
$propertyValue,
$object,
$cacheKey.':'.$propertyName,
$cacheKey.':'.get_class($object).':'.$propertyName,
$propertyMetadata,
$propertyPath,
$groups,
@ -280,7 +280,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
$this->validateGenericNode(
$value,
$object,
$cacheKey.':'.$propertyName,
$cacheKey.':'.get_class($object).':'.$propertyName,
$propertyMetadata,
$propertyPath,
$groups,
@ -589,7 +589,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
$this->validateGenericNode(
$propertyValue,
$object,
$cacheKey.':'.$propertyName,
$cacheKey.':'.get_class($object).':'.$propertyName,
$propertyMetadata,
PropertyPath::append($propertyPath, $propertyName),
$groups,