8000 [Validator] Implemented handling of arrays and Traversables in Legacy… · symfony/symfony@ee1adad · GitHub
[go: up one dir, main page]

Skip to content

Commit ee1adad

Browse files
committed
[Validator] Implemented handling of arrays and Traversables in LegacyExecutionContext::validate()
1 parent 09f744b commit ee1adad

File tree

7 files changed

+163
-8
lines changed

7 files changed

+163
-8
lines changed

src/Symfony/Component/Validator/Context/LegacyExecutionContext.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff 8000 line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\Validator\Context;
1313

1414
use Symfony\Component\Translation\TranslatorInterface;
15+
use Symfony\Component\Validator\Constraints\Traverse;
16+
use Symfony\Component\Validator\Constraints\Valid;
1517
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1618
use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;
1719
use Symfony\Component\Validator\Group\GroupManagerInterface;
@@ -100,7 +102,33 @@ public function addViolationAt($subPath, $message, array $parameters = array(),
100102
*/
101103
public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false)
102104
{
103-
// TODO handle $traverse and $deep
105+
if (is_array($value)) {
106+
$constraint = new Traverse(array(
107+
'traverse' => true,
108+
'deep' => $deep,
109+
));
110+
111+
return $this
112+
->getValidator()
113+
->inContext($this)
114+
->atPath($subPath)
115+
->validateValue($value, $constraint, $groups)
116+
;
117+
}
118+
119+
if ($traverse && $value instanceof \Traversable) {
120+
$constraints = array(
121+
new Valid(),
122+
new Traverse(array('traverse' => true, 'deep' => $deep)),
123+
);
124+
125+
return $this
126+
->getValidator()
127+
->inContext($this)
128+
->atPath($subPath)
129+
->validateValue($value, $constraints, $groups)
130+
;
131+
}
104132

105133
return $this
106134
->getValidator()

src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Validator\Constraints\Callback;
1616
use Symfony\Component\Validator\Constraints\GroupSequence;
1717
use Symfony\Component\Validator\ConstraintViolationInterface;
18+
use Symfony\Component\Validator\Context\ExecutionContext;
1819
use Symfony\Component\Validator\ExecutionContextInterface;
1920
use Symfony\Component\Validator\MetadataFactoryInterface;
2021
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
@@ -1416,6 +1417,100 @@ public function testReplaceDefaultGroupWithArrayFromGroupSequenceProvider()
14161417
$this->assertSame('Violation in Group 2', $violations[0]->getMessage());
14171418
}
14181419

1420+
public function testValidateInContext()
1421+
{
1422+
$test = $this;
1423+
$entity = new Entity();
1424+
$entity->reference = new Reference();
1425+
1426+
$callback1 = function ($value, ExecutionContextInterface $context) {
1427+
$context->validate($value->reference, 'subpath');
1428+
};
1429+
1430+
$callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
1431+
$test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
1432+
$test->assertNull($context->getPropertyName());
1433+
$test->assertSame('subpath', $context->getPropertyPath());
1434+
$test->assertSame('Group', $context->getGroup());
1435+
$test->assertSame($test->referenceMetadata, $context->getMetadata());
1436+
$test->assertSame($test->metadataFactory, $context->getMetadataFactory());
1437+
$test->assertSame($entity, $context->getRoot());
1438+
$test->assertSame($entity->reference, $context->getValue());
1439+
$test->assertSame($entity->reference, $value);
1440+
1441+
$context->addViolation('Message %param%', array('%param%' => 'value'));
1442+
};
1443+
1444+
$this->metadata->addConstraint(new Callback(array(
1445+
'callback' => $callback1,
1446+
'groups' => 'Group',
1447+
)));
1448+
$this->referenceMetadata->addConstraint(new Callback(array(
1449+
'callback' => $callback2,
1450+
'groups' => 'Group',
1451+
)));
1452+
1453+
$violations = $this->validator->validate($entity, 'Group');
1454+
1455+
/** @var ConstraintViolationInterface[] $violations */
1456+
$this->assertCount(1, $violations);
1457+
$this->assertSame('Message value', $violations[0]->getMessage());
1458+
$this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
1459+
$this->assertSame(array('%param%' => 'value'), $violations[0]->getMessageParameters());
1460+
$this->assertSame('subpath', $violations[0]->getPropertyPath());
1461+
$this->assertSame($entity, $violations[0]->getRoot());
1462+
$this->assertSame($entity->reference, $violations[0]->getInvalidValue());
1463+
$this->assertNull($violations[0]->getMessagePluralization());
1464+
$this->assertNull($violations[0]->getCode());
1465+
}
1466+
1467+
public function testValidateArrayInContext()
1468+
{
1469+
$test = $this;
1470+
$entity = new Entity();
1471+
$entity->reference = new Reference();
1472+
1473+
$callback1 = function ($value, ExecutionContextInterface $context) {
1474+
$context->validate(array('key' => $value->reference), 'subpath');
1475+
};
1476+
1477+
$callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
1478+
$test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
1479+
$test->assertNull($context->getPropertyName());
1480+
$test->assertSame('subpath[key]', $context->getPropertyPath());
1481+
$test->assertSame('Group', $context->getGroup());
1482+
$test->assertSame($test->referenceMetadata, $context->getMetadata());
1483+
$test->assertSame($test->metadataFactory, $context->getMetadataFactory());
1484+
$test->assertSame($entity, $context->getRoot());
1485+
$test->assertSame($entity->reference, $context->getValue());
1486+
$test->assertSame($entity->reference, $value);
1487+
1488+
$context->addViolation('Message %param%', array('%param%' => 'value'));
1489+
};
1490+
1491+
$this->metadata->addConstraint(new Callback(array(
1492+
'callback' => $callback1,
1493+
'groups' => 'Group',
1494+
)));
1495+
$this->referenceMetadata->addConstraint(new Callback(array(
1496+
'callback' => $callback2,
1497+
'groups' => 'Group',
1498+
)));
1499+
1500+
$violations = $this->validator->validate($entity, 'Group');
1501+
1502+
/** @var ConstraintViolationInterface[] $violations */
1503+
$this->assertCount(1, $violations);
1504+
$this->assertSame('Message value', $violations[0]->getMessage());
1505+
$this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
1506+
$this->assertSame(array('%param%' => 'value'), $violations[0]->getMessageParameters());
1507+
$this->assertSame('subpath[key]', $violations[0]->getPropertyPath());
1508+
$this->assertSame($entity, $violations[0]->getRoot());
1509+
$this->assertSame($entity->reference, $violations[0]->getInvalidValue());
1510+
$this->assertNull($violations[0]->getMessagePluralization());
1511+
$this->assertNull($violations[0]->getCode());
1512+
}
1513+
14191514
public function testGetMetadataFactory()
14201515
{
14211516
$this->assertSame($this->metadataFactory, $this->validator->getMetadataFactory());

src/Symfony/Component/Validator/Validator/AbstractValidator.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
namespace Symfony\Component\Validator\Validator;
1313

1414
use Symfony\Component\Validator\Constraint;
15-
use Symfony\Component\Validator\Constraints\Traverse;
1615
use Symfony\Component\Validator\Context\ExecutionContextInterface;
17-
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
1816
use Symfony\Component\Validator\Exception\ValidatorException;
1917
use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
2018
use Symfony\Component\Validator\Mapping\GenericMetadata;

src/Symfony/Component/Validator/Validator/ContextualValidator.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Validator;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Constraints\Traverse;
1516
use Symfony\Component\Validator\ConstraintViolationListInterface;
1617
use Symfony\Component\Validator\Context\ExecutionContextInterface;
1718
use Symfony\Component\Validator\Context\ExecutionContextManagerInterface;
@@ -41,6 +42,8 @@ public function __construct(NodeTraverserInterface $nodeTraverser, MetadataFacto
4142
public function atPath($subPath)
4243
{
4344
$this->defaultPropertyPath = $this->context->getPropertyPath($subPath);
45+
46+
return $this;
4447
}
4548

4649
/**
@@ -62,6 +65,18 @@ public function validateObject($object, $groups = null)
6265
return $this->context->getViolations();
6366
}
6467

68+
public function validateCollection($collection, $groups = null, $deep = false)
69+
{
70+
$constraint = new Traverse(array(
71+
'traverse' => true,
72+
'deep' => $deep,
73+
));
74+
75+
$this->traverseValue($collection, $constraint, $groups);
76+
77+
return $this->context->getViolations();
78+
}
79+
6580
/**
6681
* Validates a property of a value against its current value.
6782
*

src/Symfony/Component/Validator/Validator/LegacyValidator.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,21 @@ class LegacyValidator extends Validator implements LegacyValidatorInterface
2424
public function validate($value, $groups = null, $traverse = false, $deep = false)
2525
{
2626
if (is_array($value)) {
27-
return $this->validateValue($value, new Traverse(array(
27+
$constraint = new Traverse(array(
2828
'traverse' => true,
2929
'deep' => $deep,
30-
)), $groups);
30+
));
31+
32+
return $this->validateValue($value, $constraint, $groups);
3133
}
3234

3335
if ($traverse && $value instanceof \Traversable) {
34-
return $this->validateValue($value, array(
36+
$constraints = array(
3537
new Valid(),
3638
new Traverse(array('traverse' => true, 'deep' => $deep)),
37-
), $groups);
39+
);
40+
41+
return $this->validateValue($value, $constraints, $groups);
3842
}
3943

4044
return $this->validateObject($value, $groups);

src/Symfony/Component/Validator/Validator/Validator.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Validator\Validator;
1313

14+
use Symfony\Component\Validator\Constraints\Traverse;
1415
use Symfony\Component\Validator\Context\ExecutionContextManagerInterface;
1516
use Symfony\Component\Validator\NodeTraverser\NodeTraverserInterface;
1617
use Symfony\Component\Validator\MetadataFactoryInterface;
@@ -42,6 +43,20 @@ public function validateObject($object, $groups = null)
4243
return $this->contextManager->stopContext()->getViolations();
4344
}
4445

46+
public function validateCollection($collection, $groups = null, $deep = false)
47+
{
48+
$this->contextManager->startContext($collection);
49+
50+
$constraint = new Traverse(array(
51+
'traverse' => true,
52+
'deep' => $deep,
53+
));
54+
55+
$this->traverseValue($collection, $constraint, $groups);
56+
57+
return $this->contextManager->stopContext()->getViolations();
58+
}
59+
4560
public function validateProperty($object, $propertyName, $groups = null)
4661
{
4762
$this->contextManager->startContext($object);

src/Symfony/Component/Validator/Validator/ValidatorInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ interface ValidatorInterface
3535
*/
3636
public function validateObject($object, $groups = null);
3737

38-
// public function validateCollection($collection, $groups = null);
38+
public function validateCollection($collection, $groups = null, $deep = false);
3939

4040
/**
4141
* Validates a property of a value against its current value.

0 commit comments

Comments
 (0)
0