[Validator] Only traverse arrays that are cascaded into
This commit is contained in:
parent
0c8e8a50b0
commit
7db9200279
@ -68,7 +68,7 @@ class Collection extends Composite
|
||||
}
|
||||
|
||||
if (!$field instanceof Optional && !$field instanceof Required) {
|
||||
$this->fields[$fieldName] = $field = new Required($field);
|
||||
$this->fields[$fieldName] = new Required($field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -589,6 +589,30 @@ abstract class AbstractValidatorTest extends TestCase
|
||||
$this->assertNull($violations[0]->getCode());
|
||||
}
|
||||
|
||||
public function testOnlyCascadedArraysAreTraversed()
|
||||
{
|
||||
$entity = new Entity();
|
||||
$entity->reference = ['key' => new Reference()];
|
||||
|
||||
$callback = function ($value, ExecutionContextInterface $context) {
|
||||
$context->addViolation('Message %param%', ['%param%' => 'value']);
|
||||
};
|
||||
|
||||
$this->metadata->addPropertyConstraint('reference', new Callback([
|
||||
'callback' => function () {},
|
||||
'groups' => 'Group',
|
||||
]));
|
||||
$this->referenceMetadata->addConstraint(new Callback([
|
||||
'callback' => $callback,
|
||||
'groups' => 'Group',
|
||||
]));
|
||||
|
||||
$violations = $this->validate($entity, null, 'Group');
|
||||
|
||||
/* @var ConstraintViolationInterface[] $violations */
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
|
||||
public function testArrayTraversalCannotBeDisabled()
|
||||
{
|
||||
$entity = new Entity();
|
||||
|
@ -352,24 +352,18 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
|
||||
* Validates each object in a collection against the constraints defined
|
||||
* for their classes.
|
||||
*
|
||||
* If the parameter $recursive is set to true, nested {@link \Traversable}
|
||||
* objects are iterated as well. Nested arrays are always iterated,
|
||||
* regardless of the value of $recursive.
|
||||
* Nested arrays are also iterated.
|
||||
*
|
||||
* @param iterable $collection The collection
|
||||
* @param string $propertyPath The current property path
|
||||
* @param (string|GroupSequence)[] $groups The validated groups
|
||||
* @param ExecutionContextInterface $context The current execution context
|
||||
*
|
||||
* @see ClassNode
|
||||
* @see CollectionNode
|
||||
*/
|
||||
private function validateEachObjectIn($collection, $propertyPath, array $groups, ExecutionContextInterface $context)
|
||||
{
|
||||
foreach ($collection as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
// Arrays are always cascaded, independent of the specified
|
||||
// traversal strategy
|
||||
// Also traverse nested arrays
|
||||
$this->validateEachObjectIn(
|
||||
$value,
|
||||
$propertyPath.'['.$key.']',
|
||||
@ -599,7 +593,8 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
|
||||
* in the passed metadata object. Then, if the value is an instance of
|
||||
* {@link \Traversable} and the selected traversal strategy permits it,
|
||||
* the value is traversed and each nested object validated against its own
|
||||
* constraints. Arrays are always traversed.
|
||||
* constraints. If the value is an array, it is traversed regardless of
|
||||
* the given strategy.
|
||||
*
|
||||
* @param mixed $value The validated value
|
||||
* @param object|null $object The current object
|
||||
@ -658,8 +653,8 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
|
||||
|
||||
$cascadingStrategy = $metadata->getCascadingStrategy();
|
||||
|
||||
// Quit unless we have an array or a cascaded object
|
||||
if (!\is_array($value) && !($cascadingStrategy & CascadingStrategy::CASCADE)) {
|
||||
// Quit unless we cascade
|
||||
if (!($cascadingStrategy & CascadingStrategy::CASCADE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user