[Validator] Made ExecutionContext immutable and introduced new class GlobalExecutionContext

A new ExecutionContext is now created everytime that GraphWalker::walkConstraint() is
launched. Because of this, a validator B launched from within a validator A can't break
A anymore by changing the context.

Because we have a new ExecutionContext for every constraint validation, there is no point
in modifying its state anymore. Because of this it is now immutable.
This commit is contained in:
Bernhard Schussek 2012-01-31 21:35:48 +01:00
parent fe85bbdb06
commit a30a679135
19 changed files with 558 additions and 387 deletions

View File

@ -299,6 +299,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
individual fields
* changed default value for `extraFieldsMessage` and `missingFieldsMessage`
in Collection constraint
* made ExecutionContext immutable
### Yaml

View File

@ -102,10 +102,7 @@ class UniqueEntityValidator extends ConstraintValidator
return true;
}
$oldPath = $this->context->getPropertyPath();
$this->context->setPropertyPath( empty($oldPath) ? $fields[0] : $oldPath.'.'.$fields[0]);
$this->context->addViolation($constraint->message, array(), $criteria[$fields[0]]);
$this->context->setPropertyPath($oldPath);
$this->context->addNestedViolationAt($fields[0], $constraint->message, array(), $criteria[$fields[0]]);
return true; // all true, we added the violation already!
}

View File

@ -111,10 +111,6 @@ class DelegatingValidator implements FormValidatorInterface
$propertyPath = $context->getPropertyPath();
$graphWalker = $context->getGraphWalker();
// The Execute constraint is called on class level, so we need to
// set the property manually
$context->setCurrentProperty('data');
// Adjust the property path accordingly
if (!empty($propertyPath)) {
$propertyPath .= '.';
@ -134,10 +130,6 @@ class DelegatingValidator implements FormValidatorInterface
$propertyPath = $context->getPropertyPath();
$graphWalker = $context->getGraphWalker();
// The Execute constraint is called on class level, so we need to
// set the property manually
$context->setCurrentProperty('children');
// Adjust the property path accordingly
if (!empty($propertyPath)) {
$propertyPath .= '.';

View File

@ -78,13 +78,13 @@ EOF;
/**
* Merge an existing ConstraintViolationList into this list.
*
* @param ConstraintViolationList $violations
* @param ConstraintViolationList $otherList
*
* @api
*/
public function addAll(ConstraintViolationList $violations)
public function addAll(ConstraintViolationList $otherList)
{
foreach ($violations->violations as $violation) {
foreach ($otherList->violations as $violation) {
$this->violations[] = $violation;
}
}

View File

@ -48,13 +48,6 @@ class CallbackValidator extends ConstraintValidator
}
$methods = $constraint->methods;
$context = $this->context;
// save context state
$currentClass = $context->getCurrentClass();
$currentProperty = $context->getCurrentProperty();
$group = $context->getGroup();
$propertyPath = $context->getPropertyPath();
foreach ($methods as $method) {
if (is_array($method) || $method instanceof \Closure) {
@ -62,20 +55,14 @@ class CallbackValidator extends ConstraintValidator
throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1]));
}
call_user_func($method, $object, $context);
call_user_func($method, $object, $this->context);
} else {
if (!method_exists($object, $method)) {
throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $method));
}
$object->$method($context);
$object->$method($this->context);
}
// restore context state
$context->setCurrentClass($currentClass);
$context->setCurrentProperty($currentProperty);
$context->setGroup($group);
$context->setPropertyPath($propertyPath);
}
return true;

View File

@ -68,7 +68,7 @@ class CollectionValidator extends ConstraintValidator
$walker->walkConstraint($constr, $value[$field], $group, $propertyPath.'['.$field.']');
}
} elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
$this->context->addViolationAt($propertyPath.'['.$field.']', $constraint->missingFieldsMessage, array(
$this->context->addNestedViolationAt('['.$field.']', $constraint->missingFieldsMessage, array(
'{{ field }}' => '"'.$field.'"'
), null);
$valid = false;
@ -78,7 +78,7 @@ class CollectionValidator extends ConstraintValidator
if (!$constraint->allowExtraFields) {
foreach ($value as $field => $fieldValue) {
if (!isset($constraint->fields[$field])) {
$this->context->addViolationAt($propertyPath.'['.$field.']', $constraint->extraFieldsMessage, array(
$this->context->addNestedViolationAt('['.$field.']', $constraint->extraFieldsMessage, array(
'{{ field }}' => '"'.$field.'"'
), $fieldValue);
$valid = false;

View File

@ -16,8 +16,10 @@ use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
/**
* Stores the state of the current node in the validation graph.
*
* This object is used by the GraphWalker to initialize validation of different
* items and keep track of the violations.
* This class is immutable by design.
*
* It is used by the GraphWalker to initialize validation of different items
* and keep track of the violations.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@gmail.com>
@ -26,60 +28,97 @@ use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
*/
class ExecutionContext
{
protected $root;
protected $propertyPath;
protected $class;
protected $property;
protected $value;
protected $group;
protected $violations;
protected $graphWalker;
protected $metadataFactory;
private $globalContext;
private $propertyPath;
private $value;
private $group;
private $class;
private $property;
public function __construct(
$root,
GraphWalker $graphWalker,
ClassMetadataFactoryInterface $metadataFactory
)
public function __construct(GlobalExecutionContext $globalContext, $value, $propertyPath, $group, $class = null, $property = null)
{
$this->root = $root;
$this->graphWalker = $graphWalker;
$this->metadataFactory = $metadataFactory;
$this->violations = new ConstraintViolationList();
$this->globalContext = $globalContext;
$this->value = $value;
$this->propertyPath = $propertyPath;
$this->group = $group;
$this->class = $class;
$this->property = $property;
}
public function __clone()
{
$this->violations = clone $this->violations;
$this->globalContext = clone $this->globalContext;
}
/**
* Adds a violation at the current node of the validation graph.
*
* @param string $message The error message.
* @param array $params The parameters parsed into the error message.
* @param mixed $invalidValue The invalid, validated value.
*
* @api
*/
public function addViolation($message, array $params = array(), $invalidValue = null)
{
$this->violations->add(new ConstraintViolation(
$this->globalContext->addViolation(new ConstraintViolation(
$message,
$params,
$this->root,
$this->globalContext->getRoot(),
$this->propertyPath,
// check using func_num_args() to allow passing null values
func_num_args() === 3 ? $invalidValue : $this->value
));
}
/**
* Adds a violation at the validation graph node with the given property
* path.
*
* @param string $propertyPath The property path for the violation.
* @param string $message The error message.
* @param array $params The parameters parsed into the error message.
* @param mixed $invalidValue The invalid, validated value.
*/
public function addViolationAt($propertyPath, $message, array $params = array(), $invalidValue = null)
{
$this->violations->add(new ConstraintViolation(
$this->globalContext->addViolation(new ConstraintViolation(
$message,
$params,
$this->root,
$this->globalContext->getRoot(),
$propertyPath,
// check using func_num_args() to allow passing null values
func_num_args() === 4 ? $invalidValue : $this->value
));
}
/**
* Adds a violation at the child of the current validation graph node with
* the given property path.
*
* @param string $childPropertyPath The property path of the child node.
* @param string $message The error message.
* @param array $params The parameters parsed into the error message.
* @param mixed $invalidValue The invalid, validated value.
*/
public function addNestedViolationAt($childPropertyPath, $message, array $params = array(), $invalidValue = null)
{
$propertyPath = $this->propertyPath;
if ('' !== $propertyPath && '' !== $childPropertyPath && '[' !== $childPropertyPath[0]) {
$propertyPath .= '.';
}
$this->globalContext->addViolation(new ConstraintViolation(
$message,
$params,
$this->globalContext->getRoot(),
$propertyPath . $childPropertyPath,
// check using func_num_args() to allow passing null values
func_num_args() === 4 ? $invalidValue : $this->value
));
}
/**
* @return ConstraintViolationList
*
@ -87,17 +126,12 @@ class ExecutionContext
*/
public function getViolations()
{
return $this->violations;
return $this->globalContext->getViolations();
}
public function getRoot()
{
return $this->root;
}
public function setPropertyPath($propertyPath)
{
$this->propertyPath = $propertyPath;
return $this->globalContext->getRoot();
}
public function getPropertyPath()
@ -105,41 +139,21 @@ class ExecutionContext
return $this->propertyPath;
}
public function setCurrentClass($class)
{
$this->class = $class;
}
public function getCurrentClass()
{
return $this->class;
}
public function setCurrentProperty($property)
{
$this->property = $property;
}
public function getCurrentProperty()
{
return $this->property;
}
public function setCurrentValue($value)
{
$this->value = $value;
}
public function getCurrentValue()
{
return $this->value;
}
public function setGroup($group)
{
$this->group = $group;
}
public function getGroup()
{
return $this->group;
@ -150,7 +164,7 @@ class ExecutionContext
*/
public function getGraphWalker()
{
return $this->graphWalker;
return $this->globalContext->getGraphWalker();
}
/**
@ -158,6 +172,6 @@ class ExecutionContext
*/
public function getMetadataFactory()
{
return $this->metadataFactory;
return $this->globalContext->getMetadataFactory();
}
}

View File

@ -0,0 +1,80 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Validator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
/**
* Stores the node-independent information of a validation run.
*
* This class is immutable by design, except for violation tracking.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class GlobalExecutionContext
{
private $root;
private $graphWalker;
private $metadataFactory;
private $violations;
public function __construct(
$root,
GraphWalker $graphWalker,
ClassMetadataFactoryInterface $metadataFactory
)
{
$this->root = $root;
$this->graphWalker = $graphWalker;
$this->metadataFactory = $metadataFactory;
$this->violations = new ConstraintViolationList();
}
public function __clone()
{
$this->violations = clone $this->violations;
}
public function addViolation(ConstraintViolation $violation)
{
$this->violations->add($violation);
}
/**
* @return ConstraintViolationList
*/
public function getViolations()
{
return $this->violations;
}
public function getRoot()
{
return $this->root;
}
/**
* @return GraphWalker
*/
public function getGraphWalker()
{
return $this->graphWalker;
}
/**
* @return ClassMetadataFactoryInterface
*/
public function getMetadataFactory()
{
return $this->metadataFactory;
}
}

View File

@ -27,15 +27,15 @@ use Symfony\Component\Validator\Mapping\MemberMetadata;
*/
class GraphWalker
{
protected $context;
protected $validatorFactory;
protected $metadataFactory;
protected $validatorInitializers = array();
protected $validatedObjects = array();
private $globalContext;
private $validatorFactory;
private $metadataFactory;
private $validatorInitializers = array();
private $validatedObjects = array();
public function __construct($root, ClassMetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $factory, array $validatorInitializers = array())
{
$this->context = new ExecutionContext($root, $this, $metadataFactory);
$this->globalContext = new GlobalExecutionContext($root, $this, $metadataFactory);
$this->validatorFactory = $factory;
$this->metadataFactory = $metadataFactory;
$this->validatorInitializers = $validatorInitializers;
@ -46,7 +46,7 @@ class GraphWalker
*/
public function getViolations()
{
return $this->context->getViolations();
return $this->globalContext->getViolations();
}
/**
@ -67,8 +67,6 @@ class GraphWalker
$initializer->initialize($object);
}
$this->context->setCurrentClass($metadata->getClassName());
if ($group === Constraint::DEFAULT_GROUP && $metadata->hasGroupSequence()) {
$groups = $metadata->getGroupSequence();
foreach ($groups as $group) {
@ -100,8 +98,10 @@ class GraphWalker
// traversing the object graph
$this->validatedObjects[$hash][$group] = true;
$currentClass = $metadata->getClassName();
foreach ($metadata->findConstraints($group) as $constraint) {
$this->walkConstraint($constraint, $object, $group, $propertyPath);
$this->walkConstraint($constraint, $object, $group, $propertyPath, $currentClass);
}
if (null !== $object) {
@ -129,11 +129,11 @@ class GraphWalker
protected function walkMember(MemberMetadata $metadata, $value, $group, $propertyPath, $propagatedGroup = null)
{
$this->context->setCurrentClass($metadata->getClassName());
$this->context->setCurrentProperty($metadata->getPropertyName());
$currentClass = $metadata->getClassName();
$currentProperty = $metadata->getPropertyName();
foreach ($metadata->findConstraints($group) as $constraint) {
$this->walkConstraint($constraint, $value, $group, $propertyPath);
$this->walkConstraint($constraint, $value, $group, $propertyPath, $currentClass, $currentProperty);
}
if ($metadata->isCascaded()) {
@ -164,15 +164,20 @@ class GraphWalker
}
}
public function walkConstraint(Constraint $constraint, $value, $group, $propertyPath)
public function walkConstraint(Constraint $constraint, $value, $group, $propertyPath, $currentClass = null, $currentProperty = null)
{
$validator = $this->validatorFactory->getInstance($constraint);
$this->context->setCurrentValue($value);
$this->context->setPropertyPath($propertyPath);
$this->context->setGroup($group);
$localContext = new ExecutionContext(
$this->globalContext,
$value,
$propertyPath,
$group,
$currentClass,
$currentProperty
);
$validator->initialize($this->context);
$validator->initialize($localContext);
if (!$validator->isValid($value, $constraint)) {
$messageTemplate = $validator->getMessageTemplate();
@ -180,15 +185,9 @@ class GraphWalker
// Somewhat ugly hack: Don't add a violation if no message is set.
// This is required if the validator added its violations directly
// to the context already
// to the globalContext already
if (!empty($messageTemplate)) {
// Resetting the property path. This is needed because some
// validators, like CollectionValidator, use the walker internally
// and so change the context.
$this->context->setCurrentValue($value);
$this->context->setPropertyPath($propertyPath);
$this->context->addViolation($messageTemplate, $messageParams);
$localContext->addViolation($messageTemplate, $messageParams);
}
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Tests\Component\Form\Extension\Validator\Validator;
use Symfony\Component\Validator\GlobalExecutionContext;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;
@ -63,6 +65,15 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
return $this->getMock('Symfony\Component\Form\DataTransformerInterface', array(), array(), '', false, false);
}
protected function getExecutionContext($propertyPath = null)
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$globalContext = new GlobalExecutionContext('Root', $graphWalker, $metadataFactory);
return new ExecutionContext($globalContext, null, $propertyPath, null, null, null);
}
protected function getConstraintViolation($propertyPath)
{
return new ConstraintViolation($this->message, $this->params, null, $propertyPath, null);
@ -589,9 +600,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormData()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder()
->setAttribute('validation_groups', array('group1', 'group2'))
@ -611,9 +621,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormDataCanHandleCallbackValidationGroups()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder()
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
@ -633,9 +642,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormDataCanHandleClosureValidationGroups()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder()
->setAttribute('validation_groups', function(FormInterface $form){
@ -657,10 +665,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormDataUsesInheritedValidationGroup()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context->setPropertyPath('path');
$context = $this->getExecutionContext('foo.bar');
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
@ -675,17 +681,15 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker->expects($this->once())
->method('walkReference')
->with($object, 'group', 'path.data', true);
->with($object, 'group', 'foo.bar.data', true);
DelegatingValidator::validateFormData($child, $context);
}
public function testValidateFormDataUsesInheritedCallbackValidationGroup()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context->setPropertyPath('path');
$context = $this->getExecutionContext('foo.bar');
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
@ -700,20 +704,18 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker->expects($this->at(0))
->method('walkReference')
->with($object, 'group1', 'path.data', true);
->with($object, 'group1', 'foo.bar.data', true);
$graphWalker->expects($this->at(1))
->method('walkReference')
->with($object, 'group2', 'path.data', true);
->with($object, 'group2', 'foo.bar.data', true);
DelegatingValidator::validateFormData($child, $context);
}
public function testValidateFormDataUsesInheritedClosureValidationGroup()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context->setPropertyPath('path');
$context = $this->getExecutionContext('foo.bar');
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
@ -730,46 +732,24 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker->expects($this->at(0))
->method('walkReference')
->with($object, 'group1', 'path.data', true);
->with($object, 'group1', 'foo.bar.data', true);
$graphWalker->expects($this->at(1))
->method('walkReference')
->with($object, 'group2', 'path.data', true);
->with($object, 'group2', 'foo.bar.data', true);
DelegatingValidator::validateFormData($child, $context);
}
public function testValidateFormDataAppendsPropertyPath()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context->setPropertyPath('path');
$context = $this->getExecutionContext('foo.bar');
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getForm();
$graphWalker->expects($this->once())
->method('walkReference')
->with($object, 'Default', 'path.data', true);
$form->setData($object);
DelegatingValidator::validateFormData($form, $context);
}
public function testValidateFormDataSetsCurrentPropertyToData()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$object = $this->getMock('\stdClass');
$form = $this->getForm();
$test = $this;
$graphWalker->expects($this->once())
->method('walkReference')
->will($this->returnCallback(function () use ($context, $test) {
$test->assertEquals('data', $context->getCurrentProperty());
}));
->with($object, 'Default', 'foo.bar.data', true);
$form->setData($object);
@ -778,9 +758,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormDataDoesNotWalkScalars()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$clientTransformer = $this->getMockTransformer();
$form = $this->getBuilder()
@ -801,9 +780,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormChildren()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$form = $this->getBuilder()
->setAttribute('cascade_validation', true)
->setAttribute('validation_groups', array('group1', 'group2'))
@ -821,10 +799,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
public function testValidateFormChildrenAppendsPropertyPath()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context->setPropertyPath('path');
$context = $this->getExecutionContext('foo.bar');
$graphWalker = $context->getGraphWalker();
$form = $this->getBuilder()
->setAttribute('cascade_validation', true)
->getForm();
@ -832,36 +808,15 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker->expects($this->once())
->method('walkReference')
->with($form->getChildren(), 'Default', 'path.children', true);
DelegatingValidator::validateFormChildren($form, $context);
}
public function testValidateFormChildrenSetsCurrentPropertyToData()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$form = $this->getBuilder()
->setAttribute('cascade_validation', true)
->getForm();
$form->add($this->getForm('firstName'));
$test = $this;
$graphWalker->expects($this->once())
->method('walkReference')
->will($this->returnCallback(function () use ($context, $test) {
$test->assertEquals('children', $context->getCurrentProperty());
}));
->with($form->getChildren(), 'Default', 'foo.bar.children', true);
DelegatingValidator::validateFormChildren($form, $context);
}
public function testValidateFormChildrenDoesNothingIfDisabled()
{
$graphWalker = $this->getMockGraphWalker();
$metadataFactory = $this->getMockMetadataFactory();
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$form = $this->getBuilder()
->setAttribute('cascade_validation', false)
->getForm();

View File

@ -0,0 +1,134 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Validator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
class ConstraintViolationListTest extends \PHPUnit_Framework_TestCase
{
protected $list;
protected function setUp()
{
$this->list = new ConstraintViolationList();
}
protected function tearDown()
{
$this->list = null;
}
public function testInit()
{
$this->assertCount(0, $this->list);
}
public function testInitWithViolations()
{
$violation = $this->getViolation('Error');
$this->list = new ConstraintViolationList(array($violation));
$this->assertCount(1, $this->list);
$this->assertSame($violation, $this->list[0]);
}
public function testAdd()
{
$violation = $this->getViolation('Error');
$this->list->add($violation);
$this->assertCount(1, $this->list);
$this->assertSame($violation, $this->list[0]);
}
public function testAddAll()
{
$violations = array(
10 => $this->getViolation('Error 1'),
20 => $this->getViolation('Error 2'),
30 => $this->getViolation('Error 3'),
);
$otherList = new ConstraintViolationList($violations);
$this->list->addAll($otherList);
$this->assertCount(3, $this->list);
$this->assertSame($violations[10], $this->list[0]);
$this->assertSame($violations[20], $this->list[1]);
$this->assertSame($violations[30], $this->list[2]);
}
public function testIterator()
{
$violations = array(
10 => $this->getViolation('Error 1'),
20 => $this->getViolation('Error 2'),
30 => $this->getViolation('Error 3'),
);
$this->list = new ConstraintViolationList($violations);
// indices are reset upon adding -> array_values()
$this->assertSame(array_values($violations), iterator_to_array($this->list));
}
public function testArrayAccess()
{
$violation = $this->getViolation('Error');
$this->list[] = $violation;
$this->assertSame($violation, $this->list[0]);
$this->assertTrue(isset($this->list[0]));
unset($this->list[0]);
$this->assertFalse(isset($this->list[0]));
$this->list[10] = $violation;
$this->assertSame($violation, $this->list[10]);
$this->assertTrue(isset($this->list[10]));
}
public function testToString()
{
$this->list = new ConstraintViolationList(array(
$this->getViolation('Error 1', 'Root'),
$this->getViolation('Error 2', 'Root', 'foo.bar'),
$this->getViolation('Error 3', 'Root', '[baz]'),
$this->getViolation('Error 4', '', 'foo.bar'),
$this->getViolation('Error 5', '', '[baz]'),
));
$expected = <<<EOF
Root:
Error 1
Root.foo.bar:
Error 2
Root[baz]:
Error 3
foo.bar:
Error 4
[baz]:
Error 5
EOF;
$this->assertEquals($expected, (string) $this->list);
}
protected function getViolation($message, $root = null, $propertyPath = null)
{
return new ConstraintViolation($message, array(), $root, $propertyPath, null);
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Tests\Component\Validator\Constraints;
use Symfony\Component\Validator\GlobalExecutionContext;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Min;
use Symfony\Component\Validator\Constraints\All;
@ -26,8 +28,9 @@ class AllValidatorTest extends \PHPUnit_Framework_TestCase
{
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
$globalContext = new GlobalExecutionContext('Root', $this->walker, $metadataFactory);
$this->context = new ExecutionContext('Root', $this->walker, $metadataFactory);
$this->context = new ExecutionContext($globalContext, null, 'foo', 'MyGroup', null, null);
$this->validator = new AllValidator();
$this->validator->initialize($this->context);
@ -57,9 +60,6 @@ class AllValidatorTest extends \PHPUnit_Framework_TestCase
*/
public function testWalkSingleConstraint($array)
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('foo');
$constraint = new Min(4);
foreach ($array as $key => $value) {
@ -76,9 +76,6 @@ class AllValidatorTest extends \PHPUnit_Framework_TestCase
*/
public function testWalkMultipleConstraints($array)
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('foo');
$constraint = new Min(4);
// can only test for twice the same constraint because PHPUnits mocking
// can't test method calls with different arguments

View File

@ -11,6 +11,7 @@
namespace Symfony\Tests\Component\Validator\Constraints;
use Symfony\Component\Validator\GlobalExecutionContext;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
@ -21,11 +22,6 @@ class CallbackValidatorTest_Class
{
public static function validateStatic($object, ExecutionContext $context)
{
$context->setCurrentClass('Foo');
$context->setCurrentProperty('bar');
$context->setGroup('mygroup');
$context->setPropertyPath('foo.bar');
$context->addViolation('Static message', array('parameter'), 'invalidValue');
}
}
@ -34,11 +30,6 @@ class CallbackValidatorTest_Object
{
public function validateOne(ExecutionContext $context)
{
$context->setCurrentClass('Foo');
$context->setCurrentProperty('bar');
$context->setGroup('mygroup');
$context->setPropertyPath('foo.bar');
$context->addViolation('My message', array('parameter'), 'invalidValue');
}
@ -58,13 +49,9 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
{
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
$globalContext = new GlobalExecutionContext('Root', $this->walker, $metadataFactory);
$this->context = new ExecutionContext('Root', $this->walker, $metadataFactory);
$this->context->setCurrentClass('InitialClass');
$this->context->setCurrentProperty('initialProperty');
$this->context->setGroup('InitialGroup');
$this->context->setPropertyPath('initial.property.path');
$this->context = new ExecutionContext($globalContext, 'value', 'foo.bar', 'Group', 'ClassName', 'propertyName');
$this->validator = new CallbackValidator();
$this->validator->initialize($this->context);
}
@ -97,10 +84,6 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
));
$this->assertEquals($violations, $this->context->getViolations());
$this->assertEquals('InitialClass', $this->context->getCurrentClass());
$this->assertEquals('initialProperty', $this->context->getCurrentProperty());
$this->assertEquals('InitialGroup', $this->context->getGroup());
$this->assertEquals('initial.property.path', $this->context->getPropertyPath());
}
public function testCallbackSingleStaticMethod()
@ -121,10 +104,6 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
));
$this->assertEquals($violations, $this->context->getViolations());
$this->assertEquals('InitialClass', $this->context->getCurrentClass());
$this->assertEquals('initialProperty', $this->context->getCurrentProperty());
$this->assertEquals('InitialGroup', $this->context->getGroup());
$this->assertEquals('initial.property.path', $this->context->getPropertyPath());
}
public function testCallbackMultipleMethods()
@ -143,13 +122,11 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
'foo.bar',
'invalidValue'
));
// context was reset
$violations->add(new ConstraintViolation(
'Other message',
array('other parameter'),
'Root',
'initial.property.path',
'foo.bar',
'otherInvalidValue'
));

View File

@ -11,6 +11,8 @@
namespace Symfony\Tests\Component\Validator\Constraints;
use Symfony\Component\Validator\GlobalExecutionContext;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\ChoiceValidator;
@ -33,8 +35,8 @@ class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
{
$walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
$factory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
$context = new ExecutionContext('root', $walker, $factory);
$context->setCurrentClass(__CLASS__);
$globalContext = new GlobalExecutionContext('root', $walker, $factory);
$context = new ExecutionContext($globalContext, null, null, null, __CLASS__, null);
$this->validator = new ChoiceValidator();
$this->validator->initialize($context);
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Tests\Component\Validator\Constraints;
use Symfony\Component\Validator\GlobalExecutionContext;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ExecutionContext;
@ -25,6 +27,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
{
protected $validator;
protected $walker;
protected $globalContext;
protected $context;
protected function setUp()
@ -32,7 +35,8 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
$this->context = new ExecutionContext('Root', $this->walker, $metadataFactory);
$this->globalContext = new GlobalExecutionContext('Root', $this->walker, $metadataFactory);
$this->context = new ExecutionContext($this->globalContext, 'value', 'bar', 'MyGroup', 'ClassName', 'propertyName');
$this->validator = new CollectionValidator();
$this->validator->initialize($this->context);
@ -42,6 +46,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
{
$this->validator = null;
$this->walker = null;
$this->globalContext = null;
$this->context = null;
}
@ -75,9 +80,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testWalkSingleConstraint()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('foo');
$constraint = new Min(4);
$array = array('foo' => 3);
@ -85,7 +87,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
foreach ($array as $key => $value) {
$this->walker->expects($this->once())
->method('walkConstraint')
->with($this->equalTo($constraint), $this->equalTo($value), $this->equalTo('MyGroup'), $this->equalTo('foo['.$key.']'));
->with($this->equalTo($constraint), $this->equalTo($value), $this->equalTo('MyGroup'), $this->equalTo('bar['.$key.']'));
}
$data = $this->prepareTestData($array);
@ -99,9 +101,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testWalkMultipleConstraints()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('foo');
$constraints = array(
new Min(4),
new NotNull(),
@ -112,7 +111,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
foreach ($constraints as $i => $constraint) {
$this->walker->expects($this->at($i))
->method('walkConstraint')
->with($this->equalTo($constraint), $this->equalTo($value), $this->equalTo('MyGroup'), $this->equalTo('foo['.$key.']'));
->with($this->equalTo($constraint), $this->equalTo($value), $this->equalTo('MyGroup'), $this->equalTo('bar['.$key.']'));
}
}
@ -132,9 +131,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
'baz' => 6,
));
$this->context->setCurrentValue($data);
$this->context->setPropertyPath('bar');
$this->assertFalse($this->validator->isValid($data, new Collection(array(
'fields' => array(
'foo' => new Min(4),
@ -186,8 +182,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testMissingFieldsDisallowed()
{
$data = $this->prepareTestData(array());
$this->context->setCurrentValue($data);
$this->context->setPropertyPath('bar');
$this->assertFalse($this->validator->isValid($data, new Collection(array(
'fields' => array(
@ -240,9 +234,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testOptionalFieldSingleConstraint()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('bar');
$array = array(
'foo' => 5,
);
@ -262,9 +253,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testOptionalFieldMultipleConstraints()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('bar');
$array = array(
'foo' => 5,
);
@ -309,9 +297,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testRequiredFieldSingleConstraint()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('bar');
$array = array(
'foo' => 5,
);
@ -331,9 +316,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
public function testRequiredFieldMultipleConstraints()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('bar');
$array = array(
'foo' => 5,
);

View File

@ -11,6 +11,8 @@
namespace Symfony\Tests\Component\Validator;
use Symfony\Component\Validator\GlobalExecutionContext;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
@ -21,34 +23,44 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
{
protected $walker;
protected $metadataFactory;
protected $globalContext;
protected $context;
protected function setUp()
{
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
$this->metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
$this->context = new ExecutionContext('Root', $this->walker, $this->metadataFactory);
$this->globalContext = new GlobalExecutionContext('Root', $this->walker, $this->metadataFactory);
$this->context = new ExecutionContext($this->globalContext, 'currentValue', 'foo.bar', 'Group', 'ClassName', 'propertyName');
}
protected function tearDown()
{
$this->walker = null;
$this->metadataFactory = null;
$this->globalContext = null;
$this->context = null;
}
public function testInit()
{
$this->assertCount(0, $this->context->getViolations());
$this->assertSame('Root', $this->context->getRoot());
$this->assertSame('foo.bar', $this->context->getPropertyPath());
$this->assertSame('ClassName', $this->context->getCurrentClass());
$this->assertSame('propertyName', $this->context->getCurrentProperty());
$this->assertSame('Group', $this->context->getGroup());
$this->assertSame($this->walker, $this->context->getGraphWalker());
$this->assertSame($this->metadataFactory, $this->context->getMetadataFactory());
}
public function testClone()
{
$clone = clone $this->context;
$this->assertNotSame($this->context, $clone);
$this->assertNotSame($this->context->getViolations(), $clone->getViolations());
}
public function testAddViolation()
{
$this->assertCount(0, $this->context->getViolations());
$this->context->setPropertyPath('foo.bar');
$this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');
$this->assertEquals(new ConstraintViolationList(array(
@ -64,10 +76,6 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationUsesPreconfiguredValueIfNotPassed()
{
$this->assertCount(0, $this->context->getViolations());
$this->context->setPropertyPath('foo.bar');
$this->context->setCurrentValue('invalid');
$this->context->addViolation('Error');
$this->assertEquals(new ConstraintViolationList(array(
@ -76,18 +84,13 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
array(),
'Root',
'foo.bar',
'invalid'
'currentValue'
),
)), $this->context->getViolations());
}
public function testAddViolationUsesPassedNulValue()
{
$this->assertCount(0, $this->context->getViolations());
$this->context->setPropertyPath('foo.bar');
$this->context->setCurrentValue('invalid');
// passed null value should override preconfigured value "invalid"
$this->context->addViolation('Error', array('foo' => 'bar'), null);
@ -104,10 +107,6 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAt()
{
$this->assertCount(0, $this->context->getViolations());
$this->context->setPropertyPath('foo.bar');
// override preconfigured property path
$this->context->addViolationAt('bar.baz', 'Error', array('foo' => 'bar'), 'invalid');
@ -124,10 +123,6 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
{
$this->assertCount(0, $this->context->getViolations());
$this->context->setPropertyPath('foo.bar');
$this->context->setCurrentValue('invalid');
$this->context->addViolationAt('bar.baz', 'Error');
$this->assertEquals(new ConstraintViolationList(array(
@ -136,18 +131,13 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
array(),
'Root',
'bar.baz',
'invalid'
'currentValue'
),
)), $this->context->getViolations());
}
public function testAddViolationAtUsesPassedNulValue()
{
$this->assertCount(0, $this->context->getViolations());
$this->context->setPropertyPath('foo.bar');
$this->context->setCurrentValue('invalid');
// passed null value should override preconfigured value "invalid"
$this->context->addViolationAt('bar.baz', 'Error', array('foo' => 'bar'), null);
@ -162,114 +152,100 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
)), $this->context->getViolations());
}
public function testGetViolations()
public function testAddNestedViolationAt()
{
$this->context->addViolation('', array(), '');
// override preconfigured property path
$this->context->addNestedViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');
$violations = $this->context->getViolations();
$this->assertCount(1, $violations);
$this->assertInstanceOf('Symfony\Component\Validator\ConstraintViolationList', $violations);
$this->assertInstanceOf('ArrayIterator', $violations->getIterator());
$this->assertTrue(isset($violations[0]));
$this->assertFalse(isset($violations[1]));
$violations[] = 'fake';
$this->assertEquals('fake', $violations[1]);
$this->assertTrue(isset($violations[1]));
unset($violations[1]);
$this->assertFalse(isset($violations[1]));
$violations[0] = 'fake';
$this->assertEquals('fake', $violations[0]);
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Error',
array('foo' => 'bar'),
'Root',
'foo.bar.bam.baz',
'invalid'
),
)), $this->context->getViolations());
}
public function testViolationsMerge()
public function testAddNestedViolationAtWithIndexPath()
{
$this->context->addViolation('Message 1', array(), '');
$this->context->addViolation('Message 2', array(), '');
// override preconfigured property path
$this->context->addNestedViolationAt('[bam]', 'Error', array('foo' => 'bar'), 'invalid');
$violations1 = $this->context->getViolations();
$this->context->addViolation('', array(), '');
$violations2 = $this->context->getViolations();
unset($violations2[1]);
$violations1->addAll($violations2);
$this->assertEmpty($violations1[2]->getMessage());
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Error',
array('foo' => 'bar'),
'Root',
'foo.bar[bam]',
'invalid'
),
)), $this->context->getViolations());
}
public function testViolationsAsString()
public function testAddNestedViolationAtWithEmptyPath()
{
$this->context->addViolation('Message 1', array(), '');
$this->context->addViolation('Message 2', array(), '');
// override preconfigured property path
$this->context->addNestedViolationAt('', 'Error', array('foo' => 'bar'), 'invalid');
$violations = $this->context->getViolations();
$expected = <<<EOF
Root:
Message 1
Root:
Message 2
EOF;
$this->assertEquals($expected, $violations->__toString());
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Error',
array('foo' => 'bar'),
'Root',
'foo.bar',
'invalid'
),
)), $this->context->getViolations());
}
public function testGetRoot()
public function testAddNestedViolationAtWithEmptyCurrentPropertyPath()
{
$this->assertEquals('Root', $this->context->getRoot());
$this->context = new ExecutionContext($this->globalContext, 'currentValue', '', 'Group', 'ClassName', 'propertyName');
// override preconfigured property path
$this->context->addNestedViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Error',
array('foo' => 'bar'),
'Root',
'bam.baz',
'invalid'
),
)), $this->context->getViolations());
}
public function testSetGetPropertyPath()
public function testAddNestedViolationAtUsesPreconfiguredValueIfNotPassed()
{
$this->context->setPropertyPath('property_path');
$this->context->addNestedViolationAt('bam.baz', 'Error');
$this->assertEquals('property_path', $this->context->getPropertyPath());
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Error',
array(),
'Root',
'foo.bar.bam.baz',
'currentValue'
),
)), $this->context->getViolations());
}
public function testSetGetCurrentClass()
public function testAddNestedViolationAtUsesPassedNulValue()
{
$this->context->setCurrentClass('current_class');
// passed null value should override preconfigured value "invalid"
$this->context->addNestedViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null);
$this->assertEquals('current_class', $this->context->getCurrentClass());
}
public function testSetGetCurrentProperty()
{
$this->context->setCurrentProperty('current_property');
$this->assertEquals('current_property', $this->context->getCurrentProperty());
}
public function testSetGetGroup()
{
$this->context->setGroup('group');
$this->assertEquals('group', $this->context->getGroup());
}
public function testGetGraphWalker()
{
$this->assertSame($this->walker, $this->context->getGraphWalker());
$this->assertInstanceOf(
'Symfony\Component\Validator\GraphWalker',
$this->context->getGraphWalker()
);
}
public function testGetMetadataFactory()
{
$this->assertSame($this->metadataFactory, $this->context->getMetadataFactory());
$this->assertInstanceOf(
'Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface',
$this->context->getMetadataFactory()
);
$this->assertEquals(new ConstraintViolationList(array(
new ConstraintViolation(
'Error',
array('foo' => 'bar'),
'Root',
'foo.bar.bam.baz',
null
),
)), $this->context->getViolations());
}
}

View File

@ -4,9 +4,19 @@ namespace Symfony\Tests\Component\Validator\Fixtures;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\ExecutionContext;
class ConstraintAValidator extends ConstraintValidator
{
static public $passedContext;
public function initialize(ExecutionContext $context)
{
parent::initialize($context);
self::$passedContext = $context;
}
public function isValid($value, Constraint $constraint)
{
if ('VALID' != $value) {

View File

@ -0,0 +1,63 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\Validator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\GlobalExecutionContext;
class GlobalExecutionContextTest extends \PHPUnit_Framework_TestCase
{
protected $walker;
protected $metadataFactory;
protected $context;
protected function setUp()
{
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
$this->metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
$this->context = new GlobalExecutionContext('Root', $this->walker, $this->metadataFactory);
}
protected function tearDown()
{
$this->walker = null;
$this->metadataFactory = null;
$this->context = null;
}
public function testInit()
{
$this->assertCount(0, $this->context->getViolations());
$this->assertSame('Root', $this->context->getRoot());
$this->assertSame($this->walker, $this->context->getGraphWalker());
$this->assertSame($this->metadataFactory, $this->context->getMetadataFactory());
}
public function testClone()
{
$clone = clone $this->context;
$this->assertNotSame($this->context->getViolations(), $clone->getViolations());
}
public function testAddViolation()
{
$violation = new ConstraintViolation('Error', array(), 'Root', 'foo.bar', 'invalid');
$this->context->addViolation($violation);
$this->assertEquals(new ConstraintViolationList(array($violation)), $this->context->getViolations());
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Tests\Component\Validator;
use Symfony\Tests\Component\Validator\Fixtures\ConstraintAValidator;
require_once __DIR__.'/Fixtures/Entity.php';
require_once __DIR__.'/Fixtures/Reference.php';
require_once __DIR__.'/Fixtures/ConstraintA.php';
@ -54,15 +56,17 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$this->metadata = null;
}
public function testWalkObjectUpdatesContext()
public function testWalkObjectPassesCorrectClassAndProperty()
{
$this->metadata->addConstraint(new ConstraintA());
$entity = new Entity();
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $this->getContext()->getCurrentClass());
$this->assertEquals($entity, $this->getContext()->getCurrentValue());
$context = ConstraintAValidator::$passedContext;
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $context->getCurrentClass());
$this->assertNull($context->getCurrentProperty());
}
public function testWalkObjectValidatesConstraints()
@ -214,15 +218,16 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($violations, $this->walker->getViolations());
}
public function testWalkPropertyUpdatesContext()
public function testWalkPropertyPassesCorrectClassAndProperty()
{
$this->metadata->addPropertyConstraint('firstName', new ConstraintA());
$this->walker->walkPropertyValue($this->metadata, 'firstName', 'value', 'Default', '');
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $this->getContext()->getCurrentClass());
$this->assertEquals('firstName', $this->getContext()->getCurrentProperty());
$this->assertEquals('value', $this->getContext()->getCurrentValue());
$context = ConstraintAValidator::$passedContext;
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $context->getCurrentClass());
$this->assertEquals('firstName', $context->getCurrentProperty());
}
public function testWalkPropertyValueValidatesConstraints()
@ -461,9 +466,9 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('collection[foo][bar]', $violations[0]->getPropertyPath());
}
protected function getContext()
protected function getProperty($property)
{
$p = new \ReflectionProperty($this->walker, 'context');
$p = new \ReflectionProperty($this->walker, $property);
$p->setAccessible(true);
return $p->getValue($this->walker);