Permalink
Browse files

[Validator] Fixed: @Valid does not recurse the traversal of collectio…

…ns anymore by default
  • Loading branch information...
1 parent a0bfe45 commit f333cf61becabca3f343768d96bdf96c9e4ab704 @webmozart webmozart committed May 18, 2012
Showing with 94 additions and 3 deletions.
  1. +3 −0 CHANGELOG.md
  2. +2 −0 Constraints/Valid.php
  3. +4 −3 GraphWalker.php
  4. +14 −0 Mapping/MemberMetadata.php
  5. +71 −0 Tests/GraphWalkerTest.php
View
@@ -20,3 +20,6 @@ CHANGELOG
* [BC BREAK] ConstraintValidatorInterface method `isValid` has been renamed to
`validate`, its return value was dropped. ConstraintValidator still contains
`isValid` for BC
+ * [BC BREAK] collections in fields annotated with `Valid` are not traversed
+ recursively anymore by default. `Valid` contains a new property `deep`
+ which enables the BC behavior.
View
@@ -21,4 +21,6 @@
class Valid extends Constraint
{
public $traverse = true;
+
+ public $deep = false;
}
View
@@ -137,11 +137,11 @@ protected function walkMember(MemberMetadata $metadata, $value, $group, $propert
}
if ($metadata->isCascaded()) {
- $this->walkReference($value, $propagatedGroup ?: $group, $propertyPath, $metadata->isCollectionCascaded());
+ $this->walkReference($value, $propagatedGroup ?: $group, $propertyPath, $metadata->isCollectionCascaded(), $metadata->isCollectionCascadedDeeply());
}
}
- public function walkReference($value, $group, $propertyPath, $traverse)
+ public function walkReference($value, $group, $propertyPath, $traverse, $deep = false)
{
if (null !== $value) {
if (!is_object($value) && !is_array($value)) {
@@ -152,7 +152,8 @@ public function walkReference($value, $group, $propertyPath, $traverse)
foreach ($value as $key => $element) {
// Ignore any scalar values in the collection
if (is_object($element) || is_array($element)) {
- $this->walkReference($element, $group, $propertyPath.'['.$key.']', $traverse);
+ // Only repeat the traversal if $deep is set
+ $this->walkReference($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
}
}
}
View
@@ -22,6 +22,7 @@
public $property;
public $cascaded = false;
public $collectionCascaded = false;
+ public $collectionCascadedDeeply = false;
private $reflMember;
/**
@@ -52,7 +53,9 @@ public function addConstraint(Constraint $constraint)
if ($constraint instanceof Valid) {
$this->cascaded = true;
+ /* @var Valid $constraint */
$this->collectionCascaded = $constraint->traverse;
+ $this->collectionCascadedDeeply = $constraint->deep;
} else {
parent::addConstraint($constraint);
}
@@ -157,6 +160,17 @@ public function isCollectionCascaded()
}
/**
+ * Returns whether arrays or traversable objects stored in this member
+ * should be traversed recursively for inner arrays/traversable objects
+ *
+ * @return Boolean
+ */
+ public function isCollectionCascadedDeeply()
+ {
+ return $this->collectionCascadedDeeply;
+ }
+
+ /**
* Returns the value of this property in the given object
*
* @param object $object The object
View
@@ -357,6 +357,77 @@ public function testWalkCascadedPropertyDoesNotValidateTraversableIfDisabled()
$this->assertEquals($violations, $this->walker->getViolations());
}
+ public function testWalkCascadedPropertyDoesNotRecurseByDefault()
+ {
+ $entity = new Entity();
+ $entityMetadata = new ClassMetadata(get_class($entity));
+ $this->factory->addClassMetadata($entityMetadata);
+ $this->factory->addClassMetadata(new ClassMetadata('ArrayIterator'));
+
+ // add a constraint for the entity that always fails
+ $entityMetadata->addConstraint(new FailingConstraint());
+
+ // validate iterator when validating the property "reference"
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $this->walker->walkPropertyValue(
+ $this->metadata,
+ 'reference',
+ new \ArrayIterator(array(
+ // The inner iterator should not be traversed by default
+ 'key' => new \ArrayIterator(array(
+ 'nested' => $entity,
+ )),
+ )),
+ 'Default',
+ 'path'
+ );
+
+ $violations = new ConstraintViolationList();
+
+ $this->assertEquals($violations, $this->walker->getViolations());
+ }
+
+ public function testWalkCascadedPropertyRecursesIfDeepIsSet()
+ {
+ $entity = new Entity();
+ $entityMetadata = new ClassMetadata(get_class($entity));
+ $this->factory->addClassMetadata($entityMetadata);
+ $this->factory->addClassMetadata(new ClassMetadata('ArrayIterator'));
+
+ // add a constraint for the entity that always fails
+ $entityMetadata->addConstraint(new FailingConstraint());
+
+ // validate iterator when validating the property "reference"
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'deep' => true,
+ )));
+
+ $this->walker->walkPropertyValue(
+ $this->metadata,
+ 'reference',
+ new \ArrayIterator(array(
+ // The inner iterator should now be traversed
+ 'key' => new \ArrayIterator(array(
+ 'nested' => $entity,
+ )),
+ )),
+ 'Default',
+ 'path'
+ );
+
+ $violations = new ConstraintViolationList();
+ $violations->add(new ConstraintViolation(
+ 'Failed',
+ array(),
+ 'Root',
+ 'path[key][nested]',
+ $entity
+ ));
+
+ $this->assertEquals($violations, $this->walker->getViolations());
+ }
+
public function testWalkCascadedPropertyDoesNotValidateNestedScalarValues()
{
// validate array when validating the property "reference"

0 comments on commit f333cf6

Please sign in to comment.