Skip to content

Commit c49ae8f

Browse files
corphifabpot
authored andcommitted
[Validator] Only traverse arrays that are cascaded into
1 parent bc36700 commit c49ae8f

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

Constraints/Collection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ protected function initializeNestedConstraints()
6868
}
6969

7070
if (!$field instanceof Optional && !$field instanceof Required) {
71-
$this->fields[$fieldName] = $field = new Required($field);
71+
$this->fields[$fieldName] = new Required($field);
7272
}
7373
}
7474
}

Tests/Validator/AbstractValidatorTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,30 @@ public function testRecursiveArrayReference()
589589
$this->assertNull($violations[0]->getCode());
590590
}
591591

592+
public function testOnlyCascadedArraysAreTraversed()
593+
{
594+
$entity = new Entity();
595+
$entity->reference = ['key' => new Reference()];
596+
597+
$callback = function ($value, ExecutionContextInterface $context) {
598+
$context->addViolation('Message %param%', ['%param%' => 'value']);
599+
};
600+
601+
$this->metadata->addPropertyConstraint('reference', new Callback([
602+
'callback' => function () {},
603+
'groups' => 'Group',
604+
]));
605+
$this->referenceMetadata->addConstraint(new Callback([
606+
'callback' => $callback,
607+
'groups' => 'Group',
608+
]));
609+
610+
$violations = $this->validate($entity, null, 'Group');
611+
612+
/* @var ConstraintViolationInterface[] $violations */
613+
$this->assertCount(0, $violations);
614+
}
615+
592616
public function testArrayTraversalCannotBeDisabled()
593617
{
594618
$entity = new Entity();

Validator/RecursiveContextualValidator.php

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -352,24 +352,18 @@ private function validateObject($object, $propertyPath, array $groups, $traversa
352352
* Validates each object in a collection against the constraints defined
353353
* for their classes.
354354
*
355-
* If the parameter $recursive is set to true, nested {@link \Traversable}
356-
* objects are iterated as well. Nested arrays are always iterated,
357-
* regardless of the value of $recursive.
355+
* Nested arrays are also iterated.
358356
*
359357
* @param iterable $collection The collection
360358
* @param string $propertyPath The current property path
361359
* @param (string|GroupSequence)[] $groups The validated groups
362360
* @param ExecutionContextInterface $context The current execution context
363-
*
364-
* @see ClassNode
365-
* @see CollectionNode
366361
*/
367362
private function validateEachObjectIn($collection, $propertyPath, array $groups, ExecutionContextInterface $context)
368363
{
369364
foreach ($collection as $key => $value) {
370365
if (\is_array($value)) {
371-
// Arrays are always cascaded, independent of the specified
372-
// traversal strategy
366+
// Also traverse nested arrays
373367
$this->validateEachObjectIn(
374368
$value,
375369
$propertyPath.'['.$key.']',
@@ -599,7 +593,8 @@ private function validateClassNode($object, $cacheKey, ClassMetadataInterface $m
599593
* in the passed metadata object. Then, if the value is an instance of
600594
* {@link \Traversable} and the selected traversal strategy permits it,
601595
* the value is traversed and each nested object validated against its own
602-
* constraints. Arrays are always traversed.
596+
* constraints. If the value is an array, it is traversed regardless of
597+
* the given strategy.
603598
*
604599
* @param mixed $value The validated value
605600
* @param object|null $object The current object
@@ -658,8 +653,8 @@ private function validateGenericNode($value, $object, $cacheKey, MetadataInterfa
658653

659654
$cascadingStrategy = $metadata->getCascadingStrategy();
660655

661-
// Quit unless we have an array or a cascaded object
662-
if (!\is_array($value) && !($cascadingStrategy & CascadingStrategy::CASCADE)) {
656+
// Quit unless we cascade
657+
if (!($cascadingStrategy & CascadingStrategy::CASCADE)) {
663658
return;
664659
}
665660

0 commit comments

Comments
 (0)