[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:
parent
fe85bbdb06
commit
a30a679135
|
@ -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
|
||||
|
||||
|
|
|
@ -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!
|
||||
}
|
||||
|
|
|
@ -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 .= '.';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
));
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Reference in New Issue