8000 [Validator] Backported #11410 to 2.3: Object initializers are called … · symfony/symfony@291cbf9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 291cbf9

Browse files
committed
[Validator] Backported #11410 to 2.3: Object initializers are called only once per object
1 parent 91e32f8 commit 291cbf9

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

src/Symfony/Component/Validator/Tests/Fixtures/Entity.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Entity extends EntityParent implements EntityInterface
3535
public $reference;
3636
private $internal;
3737
public $data = 'Overridden data';
38+
public $initialized = false;
3839

3940
public function __construct($internal = null)
4041
{

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Validator\Tests;
1313

14+
use Symfony\Component\Validator\Constraints\Callback;
15+
use Symfony\Component\Validator\ExecutionContextInterface;
1416
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
1517
use Symfony\Component\Validator\Constraints\Valid;
1618
use Symfony\Component\Validator\Tests\Fixtures\Reference;
@@ -561,4 +563,50 @@ public function testValidateCascadedPropertyRequiresObjectOrArray()
561563

562564
$this->visitor->validate($entity, 'Default', '');
563565
}
566+
567+
public function testInitializeObjectsOnFirstValidation()
568+
{
569+
$test = $this;
570+
$entity = new Entity();
571+
$entity->initialized = false;
572+
573+
// prepare initializers that set "initialized" to true
574+
$initializer1 = $this->getMock('Symfony\\Component\\Validator\\ObjectInitializerInterface');
575+
$initializer2 = $this->getMock('Symfony\\Component\\Validator\\ObjectInitializerInterface');
576+
577+
$initializer1->expects($this->once())
578+
->method('initialize')
579+
->with($entity)
580+
->will($this->returnCallback(function ($object) {
581+
$object->initialized = true;
582+
}));
583+
584+
$initializer2->expects($this->once())
585+
->method('initialize')
586+
->with($entity);
587+
588+
$this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator(), null, array(
589+
$initializer1,
590+
$initializer2
591+
));
592+
593+
// prepare constraint which
594+
// * checks that "initialized" is set to true
595+
// * validates the object again
596+
$callback = function ($object, ExecutionContextInterface $context) use ($test) {
597+
$test->assertTrue($object->initialized);
598+
599+
// validate again in same group
600+
$context->validate($object);
601+
602+
// validate again in other group
603+
$context->validate($object, '', 'SomeGroup');
604+
};
605+
606+
$this->metadata->addConstraint(new Callback(array($callback)));
607+
608+
$this->visitor->validate($entity, 'Default', '');
609+
610+
$this->assertTrue($entity->initialized);
611+
}
564612
}

src/Symfony/Component/Validator/ValidationVisitor.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,19 @@ public function validate($value, $group, $propertyPath, $traverse = false, $deep
127127
return;
128128
}
129129

130+
// Initialize if the object wasn't initialized before
131+
if (!isset($this->validatedObjects[$hash])) {
132+
foreach ($this->objectInitializers as $initializer) {
133+
if (!$initializer instanceof ObjectInitializerInterface) {
134+
throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
135+
}
136+
$initializer->initialize($value);
137+
}
138+
}
139+
130140
// Remember validating this object before starting and possibly
131141
// traversing the object graph
132142
$this->validatedObjects[$hash][$group] = true;
133-
134-
foreach ($this->objectInitializers as $initializer) {
135-
if (!$initializer instanceof ObjectInitializerInterface) {
136-
throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
137-
}
138-
$initializer->initialize($value);
139-
}
140143
}
141144

142145
// Validate arrays recursively by default, otherwise every driver needs

0 commit comments

Comments
 (0)
0