[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
|
individual fields
|
||||||
* changed default value for `extraFieldsMessage` and `missingFieldsMessage`
|
* changed default value for `extraFieldsMessage` and `missingFieldsMessage`
|
||||||
in Collection constraint
|
in Collection constraint
|
||||||
|
* made ExecutionContext immutable
|
||||||
|
|
||||||
### Yaml
|
### Yaml
|
||||||
|
|
||||||
|
|
|
@ -102,10 +102,7 @@ class UniqueEntityValidator extends ConstraintValidator
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oldPath = $this->context->getPropertyPath();
|
$this->context->addNestedViolationAt($fields[0], $constraint->message, array(), $criteria[$fields[0]]);
|
||||||
$this->context->setPropertyPath( empty($oldPath) ? $fields[0] : $oldPath.'.'.$fields[0]);
|
|
||||||
$this->context->addViolation($constraint->message, array(), $criteria[$fields[0]]);
|
|
||||||
$this->context->setPropertyPath($oldPath);
|
|
||||||
|
|
||||||
return true; // all true, we added the violation already!
|
return true; // all true, we added the violation already!
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,10 +111,6 @@ class DelegatingValidator implements FormValidatorInterface
|
||||||
$propertyPath = $context->getPropertyPath();
|
$propertyPath = $context->getPropertyPath();
|
||||||
$graphWalker = $context->getGraphWalker();
|
$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
|
// Adjust the property path accordingly
|
||||||
if (!empty($propertyPath)) {
|
if (!empty($propertyPath)) {
|
||||||
$propertyPath .= '.';
|
$propertyPath .= '.';
|
||||||
|
@ -134,10 +130,6 @@ class DelegatingValidator implements FormValidatorInterface
|
||||||
$propertyPath = $context->getPropertyPath();
|
$propertyPath = $context->getPropertyPath();
|
||||||
$graphWalker = $context->getGraphWalker();
|
$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
|
// Adjust the property path accordingly
|
||||||
if (!empty($propertyPath)) {
|
if (!empty($propertyPath)) {
|
||||||
$propertyPath .= '.';
|
$propertyPath .= '.';
|
||||||
|
|
|
@ -78,13 +78,13 @@ EOF;
|
||||||
/**
|
/**
|
||||||
* Merge an existing ConstraintViolationList into this list.
|
* Merge an existing ConstraintViolationList into this list.
|
||||||
*
|
*
|
||||||
* @param ConstraintViolationList $violations
|
* @param ConstraintViolationList $otherList
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function addAll(ConstraintViolationList $violations)
|
public function addAll(ConstraintViolationList $otherList)
|
||||||
{
|
{
|
||||||
foreach ($violations->violations as $violation) {
|
foreach ($otherList->violations as $violation) {
|
||||||
$this->violations[] = $violation;
|
$this->violations[] = $violation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,13 +48,6 @@ class CallbackValidator extends ConstraintValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
$methods = $constraint->methods;
|
$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) {
|
foreach ($methods as $method) {
|
||||||
if (is_array($method) || $method instanceof \Closure) {
|
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]));
|
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 {
|
} else {
|
||||||
if (!method_exists($object, $method)) {
|
if (!method_exists($object, $method)) {
|
||||||
throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $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;
|
return true;
|
||||||
|
|
|
@ -68,7 +68,7 @@ class CollectionValidator extends ConstraintValidator
|
||||||
$walker->walkConstraint($constr, $value[$field], $group, $propertyPath.'['.$field.']');
|
$walker->walkConstraint($constr, $value[$field], $group, $propertyPath.'['.$field.']');
|
||||||
}
|
}
|
||||||
} elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
|
} elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
|
||||||
$this->context->addViolationAt($propertyPath.'['.$field.']', $constraint->missingFieldsMessage, array(
|
$this->context->addNestedViolationAt('['.$field.']', $constraint->missingFieldsMessage, array(
|
||||||
'{{ field }}' => '"'.$field.'"'
|
'{{ field }}' => '"'.$field.'"'
|
||||||
), null);
|
), null);
|
||||||
$valid = false;
|
$valid = false;
|
||||||
|
@ -78,7 +78,7 @@ class CollectionValidator extends ConstraintValidator
|
||||||
if (!$constraint->allowExtraFields) {
|
if (!$constraint->allowExtraFields) {
|
||||||
foreach ($value as $field => $fieldValue) {
|
foreach ($value as $field => $fieldValue) {
|
||||||
if (!isset($constraint->fields[$field])) {
|
if (!isset($constraint->fields[$field])) {
|
||||||
$this->context->addViolationAt($propertyPath.'['.$field.']', $constraint->extraFieldsMessage, array(
|
$this->context->addNestedViolationAt('['.$field.']', $constraint->extraFieldsMessage, array(
|
||||||
'{{ field }}' => '"'.$field.'"'
|
'{{ field }}' => '"'.$field.'"'
|
||||||
), $fieldValue);
|
), $fieldValue);
|
||||||
$valid = false;
|
$valid = false;
|
||||||
|
|
|
@ -16,8 +16,10 @@ use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
|
||||||
/**
|
/**
|
||||||
* Stores the state of the current node in the validation graph.
|
* Stores the state of the current node in the validation graph.
|
||||||
*
|
*
|
||||||
* This object is used by the GraphWalker to initialize validation of different
|
* This class is immutable by design.
|
||||||
* items and keep track of the violations.
|
*
|
||||||
|
* 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 Fabien Potencier <fabien@symfony.com>
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
@ -26,60 +28,97 @@ use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
|
||||||
*/
|
*/
|
||||||
class ExecutionContext
|
class ExecutionContext
|
||||||
{
|
{
|
||||||
protected $root;
|
private $globalContext;
|
||||||
protected $propertyPath;
|
private $propertyPath;
|
||||||
protected $class;
|
private $value;
|
||||||
protected $property;
|
private $group;
|
||||||
protected $value;
|
private $class;
|
||||||
protected $group;
|
private $property;
|
||||||
protected $violations;
|
|
||||||
protected $graphWalker;
|
|
||||||
protected $metadataFactory;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(GlobalExecutionContext $globalContext, $value, $propertyPath, $group, $class = null, $property = null)
|
||||||
$root,
|
|
||||||
GraphWalker $graphWalker,
|
|
||||||
ClassMetadataFactoryInterface $metadataFactory
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
$this->root = $root;
|
$this->globalContext = $globalContext;
|
||||||
$this->graphWalker = $graphWalker;
|
$this->value = $value;
|
||||||
$this->metadataFactory = $metadataFactory;
|
$this->propertyPath = $propertyPath;
|
||||||
$this->violations = new ConstraintViolationList();
|
$this->group = $group;
|
||||||
|
$this->class = $class;
|
||||||
|
$this->property = $property;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __clone()
|
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
|
* @api
|
||||||
*/
|
*/
|
||||||
public function addViolation($message, array $params = array(), $invalidValue = null)
|
public function addViolation($message, array $params = array(), $invalidValue = null)
|
||||||
{
|
{
|
||||||
$this->violations->add(new ConstraintViolation(
|
$this->globalContext->addViolation(new ConstraintViolation(
|
||||||
$message,
|
$message,
|
||||||
$params,
|
$params,
|
||||||
$this->root,
|
$this->globalContext->getRoot(),
|
||||||
$this->propertyPath,
|
$this->propertyPath,
|
||||||
// check using func_num_args() to allow passing null values
|
// check using func_num_args() to allow passing null values
|
||||||
func_num_args() === 3 ? $invalidValue : $this->value
|
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)
|
public function addViolationAt($propertyPath, $message, array $params = array(), $invalidValue = null)
|
||||||
{
|
{
|
||||||
$this->violations->add(new ConstraintViolation(
|
$this->globalContext->addViolation(new ConstraintViolation(
|
||||||
$message,
|
$message,
|
||||||
$params,
|
$params,
|
||||||
$this->root,
|
$this->globalContext->getRoot(),
|
||||||
$propertyPath,
|
$propertyPath,
|
||||||
// check using func_num_args() to allow passing null values
|
// check using func_num_args() to allow passing null values
|
||||||
func_num_args() === 4 ? $invalidValue : $this->value
|
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
|
* @return ConstraintViolationList
|
||||||
*
|
*
|
||||||
|
@ -87,17 +126,12 @@ class ExecutionContext
|
||||||
*/
|
*/
|
||||||
public function getViolations()
|
public function getViolations()
|
||||||
{
|
{
|
||||||
return $this->violations;
|
return $this->globalContext->getViolations();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRoot()
|
public function getRoot()
|
||||||
{
|
{
|
||||||
return $this->root;
|
return $this->globalContext->getRoot();
|
||||||
}
|
|
||||||
|
|
||||||
public function setPropertyPath($propertyPath)
|
|
||||||
{
|
|
||||||
$this->propertyPath = $propertyPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPropertyPath()
|
public function getPropertyPath()
|
||||||
|
@ -105,41 +139,21 @@ class ExecutionContext
|
||||||
return $this->propertyPath;
|
return $this->propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCurrentClass($class)
|
|
||||||
{
|
|
||||||
$this->class = $class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCurrentClass()
|
public function getCurrentClass()
|
||||||
{
|
{
|
||||||
return $this->class;
|
return $this->class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCurrentProperty($property)
|
|
||||||
{
|
|
||||||
$this->property = $property;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCurrentProperty()
|
public function getCurrentProperty()
|
||||||
{
|
{
|
||||||
return $this->property;
|
return $this->property;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCurrentValue($value)
|
|
||||||
{
|
|
||||||
$this->value = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCurrentValue()
|
public function getCurrentValue()
|
||||||
{
|
{
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setGroup($group)
|
|
||||||
{
|
|
||||||
$this->group = $group;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGroup()
|
public function getGroup()
|
||||||
{
|
{
|
||||||
return $this->group;
|
return $this->group;
|
||||||
|
@ -150,7 +164,7 @@ class ExecutionContext
|
||||||
*/
|
*/
|
||||||
public function getGraphWalker()
|
public function getGraphWalker()
|
||||||
{
|
{
|
||||||
return $this->graphWalker;
|
return $this->globalContext->getGraphWalker();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,6 +172,6 @@ class ExecutionContext
|
||||||
*/
|
*/
|
||||||
public function getMetadataFactory()
|
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
|
class GraphWalker
|
||||||
{
|
{
|
||||||
protected $context;
|
private $globalContext;
|
||||||
protected $validatorFactory;
|
private $validatorFactory;
|
||||||
protected $metadataFactory;
|
private $metadataFactory;
|
||||||
protected $validatorInitializers = array();
|
private $validatorInitializers = array();
|
||||||
protected $validatedObjects = array();
|
private $validatedObjects = array();
|
||||||
|
|
||||||
public function __construct($root, ClassMetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $factory, array $validatorInitializers = 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->validatorFactory = $factory;
|
||||||
$this->metadataFactory = $metadataFactory;
|
$this->metadataFactory = $metadataFactory;
|
||||||
$this->validatorInitializers = $validatorInitializers;
|
$this->validatorInitializers = $validatorInitializers;
|
||||||
|
@ -46,7 +46,7 @@ class GraphWalker
|
||||||
*/
|
*/
|
||||||
public function getViolations()
|
public function getViolations()
|
||||||
{
|
{
|
||||||
return $this->context->getViolations();
|
return $this->globalContext->getViolations();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,8 +67,6 @@ class GraphWalker
|
||||||
$initializer->initialize($object);
|
$initializer->initialize($object);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->context->setCurrentClass($metadata->getClassName());
|
|
||||||
|
|
||||||
if ($group === Constraint::DEFAULT_GROUP && $metadata->hasGroupSequence()) {
|
if ($group === Constraint::DEFAULT_GROUP && $metadata->hasGroupSequence()) {
|
||||||
$groups = $metadata->getGroupSequence();
|
$groups = $metadata->getGroupSequence();
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
|
@ -100,8 +98,10 @@ class GraphWalker
|
||||||
// traversing the object graph
|
// traversing the object graph
|
||||||
$this->validatedObjects[$hash][$group] = true;
|
$this->validatedObjects[$hash][$group] = true;
|
||||||
|
|
||||||
|
$currentClass = $metadata->getClassName();
|
||||||
|
|
||||||
foreach ($metadata->findConstraints($group) as $constraint) {
|
foreach ($metadata->findConstraints($group) as $constraint) {
|
||||||
$this->walkConstraint($constraint, $object, $group, $propertyPath);
|
$this->walkConstraint($constraint, $object, $group, $propertyPath, $currentClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $object) {
|
if (null !== $object) {
|
||||||
|
@ -129,11 +129,11 @@ class GraphWalker
|
||||||
|
|
||||||
protected function walkMember(MemberMetadata $metadata, $value, $group, $propertyPath, $propagatedGroup = null)
|
protected function walkMember(MemberMetadata $metadata, $value, $group, $propertyPath, $propagatedGroup = null)
|
||||||
{
|
{
|
||||||
$this->context->setCurrentClass($metadata->getClassName());
|
$currentClass = $metadata->getClassName();
|
||||||
$this->context->setCurrentProperty($metadata->getPropertyName());
|
$currentProperty = $metadata->getPropertyName();
|
||||||
|
|
||||||
foreach ($metadata->findConstraints($group) as $constraint) {
|
foreach ($metadata->findConstraints($group) as $constraint) {
|
||||||
$this->walkConstraint($constraint, $value, $group, $propertyPath);
|
$this->walkConstraint($constraint, $value, $group, $propertyPath, $currentClass, $currentProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($metadata->isCascaded()) {
|
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);
|
$validator = $this->validatorFactory->getInstance($constraint);
|
||||||
|
|
||||||
$this->context->setCurrentValue($value);
|
$localContext = new ExecutionContext(
|
||||||
$this->context->setPropertyPath($propertyPath);
|
$this->globalContext,
|
||||||
$this->context->setGroup($group);
|
$value,
|
||||||
|
$propertyPath,
|
||||||
|
$group,
|
||||||
|
$currentClass,
|
||||||
|
$currentProperty
|
||||||
|
);
|
||||||
|
|
||||||
$validator->initialize($this->context);
|
$validator->initialize($localContext);
|
||||||
|
|
||||||
if (!$validator->isValid($value, $constraint)) {
|
if (!$validator->isValid($value, $constraint)) {
|
||||||
$messageTemplate = $validator->getMessageTemplate();
|
$messageTemplate = $validator->getMessageTemplate();
|
||||||
|
@ -180,15 +185,9 @@ class GraphWalker
|
||||||
|
|
||||||
// Somewhat ugly hack: Don't add a violation if no message is set.
|
// Somewhat ugly hack: Don't add a violation if no message is set.
|
||||||
// This is required if the validator added its violations directly
|
// This is required if the validator added its violations directly
|
||||||
// to the context already
|
// to the globalContext already
|
||||||
if (!empty($messageTemplate)) {
|
if (!empty($messageTemplate)) {
|
||||||
// Resetting the property path. This is needed because some
|
$localContext->addViolation($messageTemplate, $messageParams);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace Symfony\Tests\Component\Form\Extension\Validator\Validator;
|
namespace Symfony\Tests\Component\Form\Extension\Validator\Validator;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\GlobalExecutionContext;
|
||||||
|
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
use Symfony\Component\Form\FormBuilder;
|
use Symfony\Component\Form\FormBuilder;
|
||||||
use Symfony\Component\Form\FormError;
|
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);
|
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)
|
protected function getConstraintViolation($propertyPath)
|
||||||
{
|
{
|
||||||
return new ConstraintViolation($this->message, $this->params, null, $propertyPath, null);
|
return new ConstraintViolation($this->message, $this->params, null, $propertyPath, null);
|
||||||
|
@ -589,9 +600,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormData()
|
public function testValidateFormData()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext();
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setAttribute('validation_groups', array('group1', 'group2'))
|
->setAttribute('validation_groups', array('group1', 'group2'))
|
||||||
|
@ -611,9 +621,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormDataCanHandleCallbackValidationGroups()
|
public function testValidateFormDataCanHandleCallbackValidationGroups()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext();
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
|
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
|
||||||
|
@ -633,9 +642,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormDataCanHandleClosureValidationGroups()
|
public function testValidateFormDataCanHandleClosureValidationGroups()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext();
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setAttribute('validation_groups', function(FormInterface $form){
|
->setAttribute('validation_groups', function(FormInterface $form){
|
||||||
|
@ -657,10 +665,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormDataUsesInheritedValidationGroup()
|
public function testValidateFormDataUsesInheritedValidationGroup()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext('foo.bar');
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$context->setPropertyPath('path');
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
|
|
||||||
$parent = $this->getBuilder()
|
$parent = $this->getBuilder()
|
||||||
|
@ -675,17 +681,15 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$graphWalker->expects($this->once())
|
$graphWalker->expects($this->once())
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($object, 'group', 'path.data', true);
|
->with($object, 'group', 'foo.bar.data', true);
|
||||||
|
|
||||||
DelegatingValidator::validateFormData($child, $context);
|
DelegatingValidator::validateFormData($child, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidateFormDataUsesInheritedCallbackValidationGroup()
|
public function testValidateFormDataUsesInheritedCallbackValidationGroup()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext('foo.bar');
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$context->setPropertyPath('path');
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
|
|
||||||
$parent = $this->getBuilder()
|
$parent = $this->getBuilder()
|
||||||
|
@ -700,20 +704,18 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$graphWalker->expects($this->at(0))
|
$graphWalker->expects($this->at(0))
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($object, 'group1', 'path.data', true);
|
->with($object, 'group1', 'foo.bar.data', true);
|
||||||
$graphWalker->expects($this->at(1))
|
$graphWalker->expects($this->at(1))
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($object, 'group2', 'path.data', true);
|
->with($object, 'group2', 'foo.bar.data', true);
|
||||||
|
|
||||||
DelegatingValidator::validateFormData($child, $context);
|
DelegatingValidator::validateFormData($child, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidateFormDataUsesInheritedClosureValidationGroup()
|
public function testValidateFormDataUsesInheritedClosureValidationGroup()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext('foo.bar');
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$context->setPropertyPath('path');
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
|
|
||||||
$parent = $this->getBuilder()
|
$parent = $this->getBuilder()
|
||||||
|
@ -730,46 +732,24 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$graphWalker->expects($this->at(0))
|
$graphWalker->expects($this->at(0))
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($object, 'group1', 'path.data', true);
|
->with($object, 'group1', 'foo.bar.data', true);
|
||||||
$graphWalker->expects($this->at(1))
|
$graphWalker->expects($this->at(1))
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($object, 'group2', 'path.data', true);
|
->with($object, 'group2', 'foo.bar.data', true);
|
||||||
|
|
||||||
DelegatingValidator::validateFormData($child, $context);
|
DelegatingValidator::validateFormData($child, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidateFormDataAppendsPropertyPath()
|
public function testValidateFormDataAppendsPropertyPath()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext('foo.bar');
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$context->setPropertyPath('path');
|
|
||||||
$object = $this->getMock('\stdClass');
|
$object = $this->getMock('\stdClass');
|
||||||
$form = $this->getForm();
|
$form = $this->getForm();
|
||||||
|
|
||||||
$graphWalker->expects($this->once())
|
$graphWalker->expects($this->once())
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($object, 'Default', 'path.data', true);
|
->with($object, 'Default', 'foo.bar.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());
|
|
||||||
}));
|
|
||||||
|
|
||||||
$form->setData($object);
|
$form->setData($object);
|
||||||
|
|
||||||
|
@ -778,9 +758,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormDataDoesNotWalkScalars()
|
public function testValidateFormDataDoesNotWalkScalars()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext();
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$clientTransformer = $this->getMockTransformer();
|
$clientTransformer = $this->getMockTransformer();
|
||||||
|
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
|
@ -801,9 +780,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormChildren()
|
public function testValidateFormChildren()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext();
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setAttribute('cascade_validation', true)
|
->setAttribute('cascade_validation', true)
|
||||||
->setAttribute('validation_groups', array('group1', 'group2'))
|
->setAttribute('validation_groups', array('group1', 'group2'))
|
||||||
|
@ -821,10 +799,8 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testValidateFormChildrenAppendsPropertyPath()
|
public function testValidateFormChildrenAppendsPropertyPath()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext('foo.bar');
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$context->setPropertyPath('path');
|
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setAttribute('cascade_validation', true)
|
->setAttribute('cascade_validation', true)
|
||||||
->getForm();
|
->getForm();
|
||||||
|
@ -832,36 +808,15 @@ class DelegatingValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$graphWalker->expects($this->once())
|
$graphWalker->expects($this->once())
|
||||||
->method('walkReference')
|
->method('walkReference')
|
||||||
->with($form->getChildren(), 'Default', 'path.children', true);
|
->with($form->getChildren(), 'Default', 'foo.bar.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());
|
|
||||||
}));
|
|
||||||
|
|
||||||
DelegatingValidator::validateFormChildren($form, $context);
|
DelegatingValidator::validateFormChildren($form, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidateFormChildrenDoesNothingIfDisabled()
|
public function testValidateFormChildrenDoesNothingIfDisabled()
|
||||||
{
|
{
|
||||||
$graphWalker = $this->getMockGraphWalker();
|
$context = $this->getExecutionContext();
|
||||||
$metadataFactory = $this->getMockMetadataFactory();
|
$graphWalker = $context->getGraphWalker();
|
||||||
$context = new ExecutionContext('Root', $graphWalker, $metadataFactory);
|
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setAttribute('cascade_validation', false)
|
->setAttribute('cascade_validation', false)
|
||||||
->getForm();
|
->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;
|
namespace Symfony\Tests\Component\Validator\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\GlobalExecutionContext;
|
||||||
|
|
||||||
use Symfony\Component\Validator\ExecutionContext;
|
use Symfony\Component\Validator\ExecutionContext;
|
||||||
use Symfony\Component\Validator\Constraints\Min;
|
use Symfony\Component\Validator\Constraints\Min;
|
||||||
use Symfony\Component\Validator\Constraints\All;
|
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);
|
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
|
||||||
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
|
$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 = new AllValidator();
|
||||||
$this->validator->initialize($this->context);
|
$this->validator->initialize($this->context);
|
||||||
|
@ -57,9 +60,6 @@ class AllValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
public function testWalkSingleConstraint($array)
|
public function testWalkSingleConstraint($array)
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('foo');
|
|
||||||
|
|
||||||
$constraint = new Min(4);
|
$constraint = new Min(4);
|
||||||
|
|
||||||
foreach ($array as $key => $value) {
|
foreach ($array as $key => $value) {
|
||||||
|
@ -76,9 +76,6 @@ class AllValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
public function testWalkMultipleConstraints($array)
|
public function testWalkMultipleConstraints($array)
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('foo');
|
|
||||||
|
|
||||||
$constraint = new Min(4);
|
$constraint = new Min(4);
|
||||||
// can only test for twice the same constraint because PHPUnits mocking
|
// can only test for twice the same constraint because PHPUnits mocking
|
||||||
// can't test method calls with different arguments
|
// can't test method calls with different arguments
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace Symfony\Tests\Component\Validator\Constraints;
|
namespace Symfony\Tests\Component\Validator\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\GlobalExecutionContext;
|
||||||
use Symfony\Component\Validator\ExecutionContext;
|
use Symfony\Component\Validator\ExecutionContext;
|
||||||
use Symfony\Component\Validator\ConstraintViolation;
|
use Symfony\Component\Validator\ConstraintViolation;
|
||||||
use Symfony\Component\Validator\ConstraintViolationList;
|
use Symfony\Component\Validator\ConstraintViolationList;
|
||||||
|
@ -21,11 +22,6 @@ class CallbackValidatorTest_Class
|
||||||
{
|
{
|
||||||
public static function validateStatic($object, ExecutionContext $context)
|
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');
|
$context->addViolation('Static message', array('parameter'), 'invalidValue');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,11 +30,6 @@ class CallbackValidatorTest_Object
|
||||||
{
|
{
|
||||||
public function validateOne(ExecutionContext $context)
|
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');
|
$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);
|
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
|
||||||
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
|
$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, 'value', 'foo.bar', 'Group', 'ClassName', 'propertyName');
|
||||||
$this->context->setCurrentClass('InitialClass');
|
|
||||||
$this->context->setCurrentProperty('initialProperty');
|
|
||||||
$this->context->setGroup('InitialGroup');
|
|
||||||
$this->context->setPropertyPath('initial.property.path');
|
|
||||||
|
|
||||||
$this->validator = new CallbackValidator();
|
$this->validator = new CallbackValidator();
|
||||||
$this->validator->initialize($this->context);
|
$this->validator->initialize($this->context);
|
||||||
}
|
}
|
||||||
|
@ -97,10 +84,6 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertEquals($violations, $this->context->getViolations());
|
$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()
|
public function testCallbackSingleStaticMethod()
|
||||||
|
@ -121,10 +104,6 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertEquals($violations, $this->context->getViolations());
|
$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()
|
public function testCallbackMultipleMethods()
|
||||||
|
@ -143,13 +122,11 @@ class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
'foo.bar',
|
'foo.bar',
|
||||||
'invalidValue'
|
'invalidValue'
|
||||||
));
|
));
|
||||||
|
|
||||||
// context was reset
|
|
||||||
$violations->add(new ConstraintViolation(
|
$violations->add(new ConstraintViolation(
|
||||||
'Other message',
|
'Other message',
|
||||||
array('other parameter'),
|
array('other parameter'),
|
||||||
'Root',
|
'Root',
|
||||||
'initial.property.path',
|
'foo.bar',
|
||||||
'otherInvalidValue'
|
'otherInvalidValue'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace Symfony\Tests\Component\Validator\Constraints;
|
namespace Symfony\Tests\Component\Validator\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\GlobalExecutionContext;
|
||||||
|
|
||||||
use Symfony\Component\Validator\ExecutionContext;
|
use Symfony\Component\Validator\ExecutionContext;
|
||||||
use Symfony\Component\Validator\Constraints\Choice;
|
use Symfony\Component\Validator\Constraints\Choice;
|
||||||
use Symfony\Component\Validator\Constraints\ChoiceValidator;
|
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);
|
$walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
|
||||||
$factory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
|
$factory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
|
||||||
$context = new ExecutionContext('root', $walker, $factory);
|
$globalContext = new GlobalExecutionContext('root', $walker, $factory);
|
||||||
$context->setCurrentClass(__CLASS__);
|
$context = new ExecutionContext($globalContext, null, null, null, __CLASS__, null);
|
||||||
$this->validator = new ChoiceValidator();
|
$this->validator = new ChoiceValidator();
|
||||||
$this->validator->initialize($context);
|
$this->validator->initialize($context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace Symfony\Tests\Component\Validator\Constraints;
|
namespace Symfony\Tests\Component\Validator\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\GlobalExecutionContext;
|
||||||
|
|
||||||
use Symfony\Component\Validator\ConstraintViolation;
|
use Symfony\Component\Validator\ConstraintViolation;
|
||||||
use Symfony\Component\Validator\ConstraintViolationList;
|
use Symfony\Component\Validator\ConstraintViolationList;
|
||||||
use Symfony\Component\Validator\ExecutionContext;
|
use Symfony\Component\Validator\ExecutionContext;
|
||||||
|
@ -25,6 +27,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
protected $validator;
|
protected $validator;
|
||||||
protected $walker;
|
protected $walker;
|
||||||
|
protected $globalContext;
|
||||||
protected $context;
|
protected $context;
|
||||||
|
|
||||||
protected function setUp()
|
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);
|
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
|
||||||
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
|
$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 = new CollectionValidator();
|
||||||
$this->validator->initialize($this->context);
|
$this->validator->initialize($this->context);
|
||||||
|
@ -42,6 +46,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
$this->validator = null;
|
$this->validator = null;
|
||||||
$this->walker = null;
|
$this->walker = null;
|
||||||
|
$this->globalContext = null;
|
||||||
$this->context = null;
|
$this->context = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,9 +80,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testWalkSingleConstraint()
|
public function testWalkSingleConstraint()
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('foo');
|
|
||||||
|
|
||||||
$constraint = new Min(4);
|
$constraint = new Min(4);
|
||||||
|
|
||||||
$array = array('foo' => 3);
|
$array = array('foo' => 3);
|
||||||
|
@ -85,7 +87,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
foreach ($array as $key => $value) {
|
foreach ($array as $key => $value) {
|
||||||
$this->walker->expects($this->once())
|
$this->walker->expects($this->once())
|
||||||
->method('walkConstraint')
|
->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);
|
$data = $this->prepareTestData($array);
|
||||||
|
@ -99,9 +101,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testWalkMultipleConstraints()
|
public function testWalkMultipleConstraints()
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('foo');
|
|
||||||
|
|
||||||
$constraints = array(
|
$constraints = array(
|
||||||
new Min(4),
|
new Min(4),
|
||||||
new NotNull(),
|
new NotNull(),
|
||||||
|
@ -112,7 +111,7 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
foreach ($constraints as $i => $constraint) {
|
foreach ($constraints as $i => $constraint) {
|
||||||
$this->walker->expects($this->at($i))
|
$this->walker->expects($this->at($i))
|
||||||
->method('walkConstraint')
|
->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,
|
'baz' => 6,
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->context->setCurrentValue($data);
|
|
||||||
$this->context->setPropertyPath('bar');
|
|
||||||
|
|
||||||
$this->assertFalse($this->validator->isValid($data, new Collection(array(
|
$this->assertFalse($this->validator->isValid($data, new Collection(array(
|
||||||
'fields' => array(
|
'fields' => array(
|
||||||
'foo' => new Min(4),
|
'foo' => new Min(4),
|
||||||
|
@ -186,8 +182,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
public function testMissingFieldsDisallowed()
|
public function testMissingFieldsDisallowed()
|
||||||
{
|
{
|
||||||
$data = $this->prepareTestData(array());
|
$data = $this->prepareTestData(array());
|
||||||
$this->context->setCurrentValue($data);
|
|
||||||
$this->context->setPropertyPath('bar');
|
|
||||||
|
|
||||||
$this->assertFalse($this->validator->isValid($data, new Collection(array(
|
$this->assertFalse($this->validator->isValid($data, new Collection(array(
|
||||||
'fields' => array(
|
'fields' => array(
|
||||||
|
@ -240,9 +234,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testOptionalFieldSingleConstraint()
|
public function testOptionalFieldSingleConstraint()
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('bar');
|
|
||||||
|
|
||||||
$array = array(
|
$array = array(
|
||||||
'foo' => 5,
|
'foo' => 5,
|
||||||
);
|
);
|
||||||
|
@ -262,9 +253,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testOptionalFieldMultipleConstraints()
|
public function testOptionalFieldMultipleConstraints()
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('bar');
|
|
||||||
|
|
||||||
$array = array(
|
$array = array(
|
||||||
'foo' => 5,
|
'foo' => 5,
|
||||||
);
|
);
|
||||||
|
@ -309,9 +297,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testRequiredFieldSingleConstraint()
|
public function testRequiredFieldSingleConstraint()
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('bar');
|
|
||||||
|
|
||||||
$array = array(
|
$array = array(
|
||||||
'foo' => 5,
|
'foo' => 5,
|
||||||
);
|
);
|
||||||
|
@ -331,9 +316,6 @@ abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testRequiredFieldMultipleConstraints()
|
public function testRequiredFieldMultipleConstraints()
|
||||||
{
|
{
|
||||||
$this->context->setGroup('MyGroup');
|
|
||||||
$this->context->setPropertyPath('bar');
|
|
||||||
|
|
||||||
$array = array(
|
$array = array(
|
||||||
'foo' => 5,
|
'foo' => 5,
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace Symfony\Tests\Component\Validator;
|
namespace Symfony\Tests\Component\Validator;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\GlobalExecutionContext;
|
||||||
|
|
||||||
use Symfony\Component\Validator\ConstraintViolation;
|
use Symfony\Component\Validator\ConstraintViolation;
|
||||||
|
|
||||||
use Symfony\Component\Validator\ConstraintViolationList;
|
use Symfony\Component\Validator\ConstraintViolationList;
|
||||||
|
@ -21,34 +23,44 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
protected $walker;
|
protected $walker;
|
||||||
protected $metadataFactory;
|
protected $metadataFactory;
|
||||||
|
protected $globalContext;
|
||||||
protected $context;
|
protected $context;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
|
$this->walker = $this->getMock('Symfony\Component\Validator\GraphWalker', array(), array(), '', false);
|
||||||
$this->metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
|
$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()
|
protected function tearDown()
|
||||||
{
|
{
|
||||||
$this->walker = null;
|
$this->globalContext = null;
|
||||||
$this->metadataFactory = null;
|
|
||||||
$this->context = 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()
|
public function testClone()
|
||||||
{
|
{
|
||||||
$clone = clone $this->context;
|
$clone = clone $this->context;
|
||||||
|
|
||||||
$this->assertNotSame($this->context, $clone);
|
$this->assertNotSame($this->context->getViolations(), $clone->getViolations());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddViolation()
|
public function testAddViolation()
|
||||||
{
|
{
|
||||||
$this->assertCount(0, $this->context->getViolations());
|
|
||||||
|
|
||||||
$this->context->setPropertyPath('foo.bar');
|
|
||||||
$this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');
|
$this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');
|
||||||
|
|
||||||
$this->assertEquals(new ConstraintViolationList(array(
|
$this->assertEquals(new ConstraintViolationList(array(
|
||||||
|
@ -64,10 +76,6 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testAddViolationUsesPreconfiguredValueIfNotPassed()
|
public function testAddViolationUsesPreconfiguredValueIfNotPassed()
|
||||||
{
|
{
|
||||||
$this->assertCount(0, $this->context->getViolations());
|
|
||||||
|
|
||||||
$this->context->setPropertyPath('foo.bar');
|
|
||||||
$this->context->setCurrentValue('invalid');
|
|
||||||
$this->context->addViolation('Error');
|
$this->context->addViolation('Error');
|
||||||
|
|
||||||
$this->assertEquals(new ConstraintViolationList(array(
|
$this->assertEquals(new ConstraintViolationList(array(
|
||||||
|
@ -76,18 +84,13 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
array(),
|
array(),
|
||||||
'Root',
|
'Root',
|
||||||
'foo.bar',
|
'foo.bar',
|
||||||
'invalid'
|
'currentValue'
|
||||||
),
|
),
|
||||||
)), $this->context->getViolations());
|
)), $this->context->getViolations());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddViolationUsesPassedNulValue()
|
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"
|
// passed null value should override preconfigured value "invalid"
|
||||||
$this->context->addViolation('Error', array('foo' => 'bar'), null);
|
$this->context->addViolation('Error', array('foo' => 'bar'), null);
|
||||||
|
|
||||||
|
@ -104,10 +107,6 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testAddViolationAt()
|
public function testAddViolationAt()
|
||||||
{
|
{
|
||||||
$this->assertCount(0, $this->context->getViolations());
|
|
||||||
|
|
||||||
$this->context->setPropertyPath('foo.bar');
|
|
||||||
|
|
||||||
// override preconfigured property path
|
// override preconfigured property path
|
||||||
$this->context->addViolationAt('bar.baz', 'Error', array('foo' => 'bar'), 'invalid');
|
$this->context->addViolationAt('bar.baz', 'Error', array('foo' => 'bar'), 'invalid');
|
||||||
|
|
||||||
|
@ -124,10 +123,6 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
|
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->context->addViolationAt('bar.baz', 'Error');
|
||||||
|
|
||||||
$this->assertEquals(new ConstraintViolationList(array(
|
$this->assertEquals(new ConstraintViolationList(array(
|
||||||
|
@ -136,18 +131,13 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
array(),
|
array(),
|
||||||
'Root',
|
'Root',
|
||||||
'bar.baz',
|
'bar.baz',
|
||||||
'invalid'
|
'currentValue'
|
||||||
),
|
),
|
||||||
)), $this->context->getViolations());
|
)), $this->context->getViolations());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddViolationAtUsesPassedNulValue()
|
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"
|
// passed null value should override preconfigured value "invalid"
|
||||||
$this->context->addViolationAt('bar.baz', 'Error', array('foo' => 'bar'), null);
|
$this->context->addViolationAt('bar.baz', 'Error', array('foo' => 'bar'), null);
|
||||||
|
|
||||||
|
@ -162,114 +152,100 @@ class ExecutionContextTest extends \PHPUnit_Framework_TestCase
|
||||||
)), $this->context->getViolations());
|
)), $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->assertEquals(new ConstraintViolationList(array(
|
||||||
|
new ConstraintViolation(
|
||||||
$this->assertCount(1, $violations);
|
'Error',
|
||||||
$this->assertInstanceOf('Symfony\Component\Validator\ConstraintViolationList', $violations);
|
array('foo' => 'bar'),
|
||||||
|
'Root',
|
||||||
$this->assertInstanceOf('ArrayIterator', $violations->getIterator());
|
'foo.bar.bam.baz',
|
||||||
|
'invalid'
|
||||||
$this->assertTrue(isset($violations[0]));
|
),
|
||||||
$this->assertFalse(isset($violations[1]));
|
)), $this->context->getViolations());
|
||||||
|
|
||||||
$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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testViolationsMerge()
|
public function testAddNestedViolationAtWithIndexPath()
|
||||||
{
|
{
|
||||||
$this->context->addViolation('Message 1', array(), '');
|
// override preconfigured property path
|
||||||
$this->context->addViolation('Message 2', array(), '');
|
$this->context->addNestedViolationAt('[bam]', 'Error', array('foo' => 'bar'), 'invalid');
|
||||||
|
|
||||||
$violations1 = $this->context->getViolations();
|
$this->assertEquals(new ConstraintViolationList(array(
|
||||||
|
new ConstraintViolation(
|
||||||
$this->context->addViolation('', array(), '');
|
'Error',
|
||||||
|
array('foo' => 'bar'),
|
||||||
$violations2 = $this->context->getViolations();
|
'Root',
|
||||||
unset($violations2[1]);
|
'foo.bar[bam]',
|
||||||
|
'invalid'
|
||||||
$violations1->addAll($violations2);
|
),
|
||||||
|
)), $this->context->getViolations());
|
||||||
$this->assertEmpty($violations1[2]->getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testViolationsAsString()
|
public function testAddNestedViolationAtWithEmptyPath()
|
||||||
{
|
{
|
||||||
$this->context->addViolation('Message 1', array(), '');
|
// override preconfigured property path
|
||||||
$this->context->addViolation('Message 2', array(), '');
|
$this->context->addNestedViolationAt('', 'Error', array('foo' => 'bar'), 'invalid');
|
||||||
|
|
||||||
$violations = $this->context->getViolations();
|
$this->assertEquals(new ConstraintViolationList(array(
|
||||||
|
new ConstraintViolation(
|
||||||
$expected = <<<EOF
|
'Error',
|
||||||
Root:
|
array('foo' => 'bar'),
|
||||||
Message 1
|
'Root',
|
||||||
Root:
|
'foo.bar',
|
||||||
Message 2
|
'invalid'
|
||||||
|
),
|
||||||
EOF;
|
)), $this->context->getViolations());
|
||||||
|
|
||||||
$this->assertEquals($expected, $violations->__toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
$this->assertEquals(new ConstraintViolationList(array(
|
||||||
}
|
new ConstraintViolation(
|
||||||
|
'Error',
|
||||||
public function testSetGetCurrentProperty()
|
array('foo' => 'bar'),
|
||||||
{
|
'Root',
|
||||||
$this->context->setCurrentProperty('current_property');
|
'foo.bar.bam.baz',
|
||||||
|
null
|
||||||
$this->assertEquals('current_property', $this->context->getCurrentProperty());
|
),
|
||||||
}
|
)), $this->context->getViolations());
|
||||||
|
|
||||||
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()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,19 @@ namespace Symfony\Tests\Component\Validator\Fixtures;
|
||||||
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
use Symfony\Component\Validator\ExecutionContext;
|
||||||
|
|
||||||
class ConstraintAValidator extends ConstraintValidator
|
class ConstraintAValidator extends ConstraintValidator
|
||||||
{
|
{
|
||||||
|
static public $passedContext;
|
||||||
|
|
||||||
|
public function initialize(ExecutionContext $context)
|
||||||
|
{
|
||||||
|
parent::initialize($context);
|
||||||
|
|
||||||
|
self::$passedContext = $context;
|
||||||
|
}
|
||||||
|
|
||||||
public function isValid($value, Constraint $constraint)
|
public function isValid($value, Constraint $constraint)
|
||||||
{
|
{
|
||||||
if ('VALID' != $value) {
|
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;
|
namespace Symfony\Tests\Component\Validator;
|
||||||
|
|
||||||
|
use Symfony\Tests\Component\Validator\Fixtures\ConstraintAValidator;
|
||||||
|
|
||||||
require_once __DIR__.'/Fixtures/Entity.php';
|
require_once __DIR__.'/Fixtures/Entity.php';
|
||||||
require_once __DIR__.'/Fixtures/Reference.php';
|
require_once __DIR__.'/Fixtures/Reference.php';
|
||||||
require_once __DIR__.'/Fixtures/ConstraintA.php';
|
require_once __DIR__.'/Fixtures/ConstraintA.php';
|
||||||
|
@ -54,15 +56,17 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->metadata = null;
|
$this->metadata = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWalkObjectUpdatesContext()
|
public function testWalkObjectPassesCorrectClassAndProperty()
|
||||||
{
|
{
|
||||||
$this->metadata->addConstraint(new ConstraintA());
|
$this->metadata->addConstraint(new ConstraintA());
|
||||||
|
|
||||||
$entity = new Entity();
|
$entity = new Entity();
|
||||||
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
$this->walker->walkObject($this->metadata, $entity, 'Default', '');
|
||||||
|
|
||||||
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $this->getContext()->getCurrentClass());
|
$context = ConstraintAValidator::$passedContext;
|
||||||
$this->assertEquals($entity, $this->getContext()->getCurrentValue());
|
|
||||||
|
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $context->getCurrentClass());
|
||||||
|
$this->assertNull($context->getCurrentProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWalkObjectValidatesConstraints()
|
public function testWalkObjectValidatesConstraints()
|
||||||
|
@ -214,15 +218,16 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals($violations, $this->walker->getViolations());
|
$this->assertEquals($violations, $this->walker->getViolations());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWalkPropertyUpdatesContext()
|
public function testWalkPropertyPassesCorrectClassAndProperty()
|
||||||
{
|
{
|
||||||
$this->metadata->addPropertyConstraint('firstName', new ConstraintA());
|
$this->metadata->addPropertyConstraint('firstName', new ConstraintA());
|
||||||
|
|
||||||
$this->walker->walkPropertyValue($this->metadata, 'firstName', 'value', 'Default', '');
|
$this->walker->walkPropertyValue($this->metadata, 'firstName', 'value', 'Default', '');
|
||||||
|
|
||||||
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $this->getContext()->getCurrentClass());
|
$context = ConstraintAValidator::$passedContext;
|
||||||
$this->assertEquals('firstName', $this->getContext()->getCurrentProperty());
|
|
||||||
$this->assertEquals('value', $this->getContext()->getCurrentValue());
|
$this->assertEquals('Symfony\Tests\Component\Validator\Fixtures\Entity', $context->getCurrentClass());
|
||||||
|
$this->assertEquals('firstName', $context->getCurrentProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWalkPropertyValueValidatesConstraints()
|
public function testWalkPropertyValueValidatesConstraints()
|
||||||
|
@ -461,9 +466,9 @@ class GraphWalkerTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals('collection[foo][bar]', $violations[0]->getPropertyPath());
|
$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);
|
$p->setAccessible(true);
|
||||||
|
|
||||||
return $p->getValue($this->walker);
|
return $p->getValue($this->walker);
|
||||||
|
|
Reference in New Issue