[Validator] Backported #11410 to 2.3: Object initializers are called only once per object
This commit is contained in:
parent
91e32f810b
commit
291cbf9efa
@ -35,6 +35,7 @@ class Entity extends EntityParent implements EntityInterface
|
||||
public $reference;
|
||||
private $internal;
|
||||
public $data = 'Overridden data';
|
||||
public $initialized = false;
|
||||
|
||||
public function __construct($internal = null)
|
||||
{
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Validator\Tests;
|
||||
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\ExecutionContextInterface;
|
||||
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
|
||||
use Symfony\Component\Validator\Constraints\Valid;
|
||||
use Symfony\Component\Validator\Tests\Fixtures\Reference;
|
||||
@ -561,4 +563,50 @@ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->visitor->validate($entity, 'Default', '');
|
||||
}
|
||||
|
||||
public function testInitializeObjectsOnFirstValidation()
|
||||
{
|
||||
$test = $this;
|
||||
$entity = new Entity();
|
||||
$entity->initialized = false;
|
||||
|
||||
// prepare initializers that set "initialized" to true
|
||||
$initializer1 = $this->getMock('Symfony\\Component\\Validator\\ObjectInitializerInterface');
|
||||
$initializer2 = $this->getMock('Symfony\\Component\\Validator\\ObjectInitializerInterface');
|
||||
|
||||
$initializer1->expects($this->once())
|
||||
->method('initialize')
|
||||
->with($entity)
|
||||
->will($this->returnCallback(function ($object) {
|
||||
$object->initialized = true;
|
||||
}));
|
||||
|
||||
$initializer2->expects($this->once())
|
||||
->method('initialize')
|
||||
->with($entity);
|
||||
|
||||
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator(), null, array(
|
||||
$initializer1,
|
||||
$initializer2
|
||||
));
|
||||
|
||||
// prepare constraint which
|
||||
// * checks that "initialized" is set to true
|
||||
// * validates the object again
|
||||
$callback = function ($object, ExecutionContextInterface $context) use ($test) {
|
||||
$test->assertTrue($object->initialized);
|
||||
|
||||
// validate again in same group
|
||||
$context->validate($object);
|
||||
|
||||
// validate again in other group
|
||||
$context->validate($object, '', 'SomeGroup');
|
||||
};
|
||||
|
||||
$this->metadata->addConstraint(new Callback(array($callback)));
|
||||
|
||||
$this->visitor->validate($entity, 'Default', '');
|
||||
|
||||
$this->assertTrue($entity->initialized);
|
||||
}
|
||||
}
|
||||
|
@ -127,10 +127,8 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember validating this object before starting and possibly
|
||||
// traversing the object graph
|
||||
$this->validatedObjects[$hash][$group] = true;
|
||||
|
||||
// Initialize if the object wasn't initialized before
|
||||
if (!isset($this->validatedObjects[$hash])) {
|
||||
foreach ($this->objectInitializers as $initializer) {
|
||||
if (!$initializer instanceof ObjectInitializerInterface) {
|
||||
throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
|
||||
@ -139,6 +137,11 @@ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionCo
|
||||
}
|
||||
}
|
||||
|
||||
// Remember validating this object before starting and possibly
|
||||
// traversing the object graph
|
||||
$this->validatedObjects[$hash][$group] = true;
|
||||
}
|
||||
|
||||
// Validate arrays recursively by default, otherwise every driver needs
|
||||
// to implement special handling for arrays.
|
||||
// https://github.com/symfony/symfony/issues/6246
|
||||
|
Reference in New Issue
Block a user