[Validator] Each object is now only validated once for a given group
This commit is contained in:
parent
d52ae8e103
commit
2d7c47e488
@ -32,6 +32,7 @@ class GraphWalker
|
||||
protected $context;
|
||||
protected $validatorFactory;
|
||||
protected $metadataFactory;
|
||||
protected $validatedObjects = array();
|
||||
|
||||
public function __construct($root, ClassMetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $factory)
|
||||
{
|
||||
@ -57,26 +58,41 @@ class GraphWalker
|
||||
* @param string $group The validator group to use for validation
|
||||
* @param string $propertyPath
|
||||
*/
|
||||
public function walkClass(ClassMetadata $metadata, $object, $group, $propertyPath)
|
||||
public function walkObject(ClassMetadata $metadata, $object, $group, $propertyPath)
|
||||
{
|
||||
$this->context->setCurrentClass($metadata->getClassName());
|
||||
|
||||
if ($group === Constraint::DEFAULT_GROUP && $metadata->hasGroupSequence()) {
|
||||
$groups = $metadata->getGroupSequence();
|
||||
foreach ($groups as $group) {
|
||||
$this->walkClassForGroup($metadata, $object, $group, $propertyPath, Constraint::DEFAULT_GROUP);
|
||||
$this->walkObjectForGroup($metadata, $object, $group, $propertyPath, Constraint::DEFAULT_GROUP);
|
||||
|
||||
if (count($this->getViolations()) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->walkClassForGroup($metadata, $object, $group, $propertyPath);
|
||||
$this->walkObjectForGroup($metadata, $object, $group, $propertyPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected function walkClassForGroup(ClassMetadata $metadata, $object, $group, $propertyPath, $propagatedGroup = null)
|
||||
protected function walkObjectForGroup(ClassMetadata $metadata, $object, $group, $propertyPath, $propagatedGroup = null)
|
||||
{
|
||||
$hash = spl_object_hash($object);
|
||||
|
||||
// Exit, if the object is already validated for the current group
|
||||
if (isset($this->validatedObjects[$hash])) {
|
||||
if (isset($this->validatedObjects[$hash][$group])) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$this->validatedObjects[$hash] = array();
|
||||
}
|
||||
|
||||
// Remember validating this object before starting and possibly
|
||||
// traversing the object graph
|
||||
$this->validatedObjects[$hash][$group] = true;
|
||||
|
||||
foreach ($metadata->findConstraints($group) as $constraint) {
|
||||
$this->walkConstraint($constraint, $object, $group, $propertyPath);
|
||||
}
|
||||
@ -128,7 +144,7 @@ class GraphWalker
|
||||
throw new UnexpectedTypeException($value, 'object or array');
|
||||
} else {
|
||||
$metadata = $this->metadataFactory->getClassMetadata(get_class($value));
|
||||
$this->walkClass($metadata, $value, $group, $propertyPath);
|
||||
$this->walkObject($metadata, $value, $group, $propertyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class Validator implements ValidatorInterface
|
||||
$metadata = $this->metadataFactory->getClassMetadata(get_class($object));
|
||||
|
||||
$walk = function(GraphWalker $walker, $group) use ($metadata, $object) {
|
||||
return $walker->walkClass($metadata, $object, $group, '');
|
||||
return $walker->walkObject($metadata, $object, $group, '');
|
||||
};
|
||||
|
||||
return $this->validateGraph($object, $walk, $groups);
|
||||
|
@ -46,34 +46,69 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->metadata = new ClassMetadata(self::CLASSNAME);
|
||||
}
|
||||
|
||||
public function testWalkClassValidatesConstraints()
|
||||
public function testWalkObjectValidatesConstraints()
|
||||
{
|
||||
$this->metadata->addConstraint(new ConstraintA());
|
||||
|
||||
$this->walker->walkClass($this->metadata, new Entity(), 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
|
||||
|
||||
$this->assertEquals(1, count($this->walker->getViolations()));
|
||||
}
|
||||
|
||||
public function testWalkClassValidatesPropertyConstraints()
|
||||
public function testWalkObjectTwiceValidatesConstraintsOnce()
|
||||
{
|
||||
$this->metadata->addConstraint(new ConstraintA());
|
||||
|
||||
$entity = new Entity();
|
||||
|
||||
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
||||
|
||||
$this->assertEquals(1, count($this->walker->getViolations()));
|
||||
}
|
||||
|
||||
public function testWalkDifferentObjectsValidatesTwice()
|
||||
{
|
||||
$this->metadata->addConstraint(new ConstraintA());
|
||||
|
||||
$this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
|
||||
|
||||
$this->assertEquals(2, count($this->walker->getViolations()));
|
||||
}
|
||||
|
||||
public function testWalkObjectTwiceInDifferentGroupsValidatesTwice()
|
||||
{
|
||||
$this->metadata->addConstraint(new ConstraintA());
|
||||
$this->metadata->addConstraint(new ConstraintA(array('groups' => 'Custom')));
|
||||
|
||||
$entity = new Entity();
|
||||
|
||||
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, $entity, 'Custom', '');
|
||||
|
||||
$this->assertEquals(2, count($this->walker->getViolations()));
|
||||
}
|
||||
|
||||
public function testWalkObjectValidatesPropertyConstraints()
|
||||
{
|
||||
$this->metadata->addPropertyConstraint('firstName', new ConstraintA());
|
||||
|
||||
$this->walker->walkClass($this->metadata, new Entity(), 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
|
||||
|
||||
$this->assertEquals(1, count($this->walker->getViolations()));
|
||||
}
|
||||
|
||||
public function testWalkClassValidatesGetterConstraints()
|
||||
public function testWalkObjectValidatesGetterConstraints()
|
||||
{
|
||||
$this->metadata->addGetterConstraint('lastName', new ConstraintA());
|
||||
|
||||
$this->walker->walkClass($this->metadata, new Entity(), 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
|
||||
|
||||
$this->assertEquals(1, count($this->walker->getViolations()));
|
||||
}
|
||||
|
||||
public function testWalkClassInDefaultGroupTraversesGroupSequence()
|
||||
public function testWalkObjectInDefaultGroupTraversesGroupSequence()
|
||||
{
|
||||
$entity = new Entity();
|
||||
|
||||
@ -85,7 +120,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||
)));
|
||||
$this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));
|
||||
|
||||
$this->walker->walkClass($this->metadata, $entity, 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
||||
|
||||
// After validation of group "First" failed, no more group was
|
||||
// validated
|
||||
@ -101,7 +136,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($violations, $this->walker->getViolations());
|
||||
}
|
||||
|
||||
public function testWalkClassInGroupSequencePropagatesDefaultGroup()
|
||||
public function testWalkObjectInGroupSequencePropagatesDefaultGroup()
|
||||
{
|
||||
$entity = new Entity();
|
||||
$entity->reference = new Reference();
|
||||
@ -117,7 +152,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||
)));
|
||||
$this->factory->addClassMetadata($referenceMetadata);
|
||||
|
||||
$this->walker->walkClass($this->metadata, $entity, 'Default', '');
|
||||
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
||||
|
||||
// The validation of the reference's FailingConstraint in group
|
||||
// "Default" was launched
|
||||
@ -133,7 +168,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($violations, $this->walker->getViolations());
|
||||
}
|
||||
|
||||
public function testWalkClassInOtherGroupTraversesNoGroupSequence()
|
||||
public function testWalkObjectInOtherGroupTraversesNoGroupSequence()
|
||||
{
|
||||
$entity = new Entity();
|
||||
|
||||
@ -145,7 +180,7 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||
)));
|
||||
$this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));
|
||||
|
||||
$this->walker->walkClass($this->metadata, $entity, $this->metadata->getDefaultGroup(), '');
|
||||
$this->walker->walkObject($this->metadata, $entity, $this->metadata->getDefaultGroup(), '');
|
||||
|
||||
// Only group "Second" was validated
|
||||
$violations = new ConstraintViolationList();
|
||||
|
Reference in New Issue
Block a user