[Validator] Each object is now only validated once for a given group

This commit is contained in:
Bernhard Schussek 2011-01-19 15:57:40 +01:00
parent d52ae8e103
commit 2d7c47e488
3 changed files with 69 additions and 18 deletions

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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();