[Validator] Renamed Condition to Expression and added possibility to set it onto properties
This commit is contained in:
parent
a3b3a78237
commit
d4ebbfd02d
@ -48,6 +48,9 @@ class FrameworkExtension extends Extension
|
|||||||
// will be used and everything will still work as expected.
|
// will be used and everything will still work as expected.
|
||||||
$loader->load('translation.xml');
|
$loader->load('translation.xml');
|
||||||
|
|
||||||
|
// Property access is used by both the Form and the Validator component
|
||||||
|
$loader->load('property_access.xml');
|
||||||
|
|
||||||
$loader->load('debug_prod.xml');
|
$loader->load('debug_prod.xml');
|
||||||
|
|
||||||
if ($container->getParameter('kernel.debug')) {
|
if ($container->getParameter('kernel.debug')) {
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
<parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
|
<parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
|
||||||
<parameter key="form.extension.class">Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension</parameter>
|
<parameter key="form.extension.class">Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension</parameter>
|
||||||
<parameter key="form.type_guesser.validator.class">Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser</parameter>
|
<parameter key="form.type_guesser.validator.class">Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser</parameter>
|
||||||
<parameter key="property_accessor.class">Symfony\Component\PropertyAccess\PropertyAccessor</parameter>
|
|
||||||
</parameters>
|
</parameters>
|
||||||
|
|
||||||
<services>
|
<services>
|
||||||
@ -54,9 +53,6 @@
|
|||||||
<argument type="service" id="validator.mapping.class_metadata_factory" />
|
<argument type="service" id="validator.mapping.class_metadata_factory" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- PropertyAccessor -->
|
|
||||||
<service id="property_accessor" class="%property_accessor.class%" />
|
|
||||||
|
|
||||||
<!-- CoreExtension -->
|
<!-- CoreExtension -->
|
||||||
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
|
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
|
||||||
<argument type="service" id="property_accessor"/>
|
<argument type="service" id="property_accessor"/>
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
|
|
||||||
|
<parameters>
|
||||||
|
<parameter key="property_accessor.class">Symfony\Component\PropertyAccess\PropertyAccessor</parameter>
|
||||||
|
</parameters>
|
||||||
|
|
||||||
|
<services>
|
||||||
|
<service id="property_accessor" class="%property_accessor.class%" />
|
||||||
|
</services>
|
||||||
|
</container>
|
@ -17,6 +17,7 @@
|
|||||||
<parameter key="validator.validator_factory.class">Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory</parameter>
|
<parameter key="validator.validator_factory.class">Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory</parameter>
|
||||||
<parameter key="validator.mapping.loader.xml_files_loader.mapping_files" type="collection" />
|
<parameter key="validator.mapping.loader.xml_files_loader.mapping_files" type="collection" />
|
||||||
<parameter key="validator.mapping.loader.yaml_files_loader.mapping_files" type="collection" />
|
<parameter key="validator.mapping.loader.yaml_files_loader.mapping_files" type="collection" />
|
||||||
|
<parameter key="validator.expression.class">Symfony\Component\Validator\Constraints\ExpressionValidator</parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
|
|
||||||
<services>
|
<services>
|
||||||
@ -63,5 +64,10 @@
|
|||||||
<service id="validator.mapping.loader.yaml_files_loader" class="%validator.mapping.loader.yaml_files_loader.class%" public="false">
|
<service id="validator.mapping.loader.yaml_files_loader" class="%validator.mapping.loader.yaml_files_loader.class%" public="false">
|
||||||
<argument>%validator.mapping.loader.yaml_files_loader.mapping_files%</argument>
|
<argument>%validator.mapping.loader.yaml_files_loader.mapping_files%</argument>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="validator.expression" class="%validator.expression.class%">
|
||||||
|
<argument type="service" id="property_accessor" />
|
||||||
|
<tag name="validator.constraint_validator" alias="validator.expression" />
|
||||||
|
</service>
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator;
|
namespace Symfony\Component\Validator;
|
||||||
|
|
||||||
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
|
use Symfony\Component\Validator\Constraints\ExpressionValidator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of the ConstraintValidatorFactoryInterface.
|
* Default implementation of the ConstraintValidatorFactoryInterface.
|
||||||
@ -20,11 +21,23 @@ use Symfony\Component\Validator\Constraint;
|
|||||||
* This enforces the convention that the validatedBy() method on any
|
* This enforces the convention that the validatedBy() method on any
|
||||||
* Constrain will return the class name of the ConstraintValidator that
|
* Constrain will return the class name of the ConstraintValidator that
|
||||||
* should validate the Constraint.
|
* should validate the Constraint.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
*/
|
*/
|
||||||
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
||||||
{
|
{
|
||||||
protected $validators = array();
|
protected $validators = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PropertyAccessorInterface
|
||||||
|
*/
|
||||||
|
private $propertyAccessor;
|
||||||
|
|
||||||
|
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
|
||||||
|
{
|
||||||
|
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@ -32,8 +45,19 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
|||||||
{
|
{
|
||||||
$className = $constraint->validatedBy();
|
$className = $constraint->validatedBy();
|
||||||
|
|
||||||
if (!isset($this->validators[$className]) || $className === 'Symfony\Component\Validator\Constraints\CollectionValidator') {
|
// The second condition is a hack that is needed when CollectionValidator
|
||||||
$this->validators[$className] = new $className();
|
// calls itself recursively (Collection constraints can be nested).
|
||||||
|
// Since the context of the validator is overwritten when initialize()
|
||||||
|
// is called for the nested constraint, the outer validator is
|
||||||
|
// acting on the wrong context when the nested validation terminates.
|
||||||
|
//
|
||||||
|
// A better solution - which should be approached in Symfony 3.0 - is to
|
||||||
|
// remove the initialize() method and pass the context as last argument
|
||||||
|
// to validate() instead.
|
||||||
|
if (!isset($this->validators[$className]) || 'Symfony\Component\Validator\Constraints\CollectionValidator' === $className) {
|
||||||
|
$this->validators[$className] = 'validator.expression' === $className
|
||||||
|
? new ExpressionValidator($this->propertyAccessor)
|
||||||
|
: new $className();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->validators[$className];
|
return $this->validators[$className];
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
<?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\Constraints;
|
|
||||||
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
|
||||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
|
||||||
*/
|
|
||||||
class ConditionValidator extends ConstraintValidator
|
|
||||||
{
|
|
||||||
private $expressionLanguage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function validate($object, Constraint $constraint)
|
|
||||||
{
|
|
||||||
if (null === $object) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->getExpressionLanguage()->evaluate($constraint->condition, array('this' => $object))) {
|
|
||||||
$this->context->addViolation($constraint->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getExpressionLanguage()
|
|
||||||
{
|
|
||||||
if (null === $this->expressionLanguage) {
|
|
||||||
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
|
|
||||||
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
|
||||||
}
|
|
||||||
$this->expressionLanguage = new ExpressionLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->expressionLanguage;
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,18 +17,19 @@ use Symfony\Component\Validator\Constraint;
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
*/
|
*/
|
||||||
class Condition extends Constraint
|
class Expression extends Constraint
|
||||||
{
|
{
|
||||||
public $message = 'This value is not valid.';
|
public $message = 'This value is not valid.';
|
||||||
public $condition;
|
public $expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function getDefaultOption()
|
public function getDefaultOption()
|
||||||
{
|
{
|
||||||
return 'condition';
|
return 'expression';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,13 +37,22 @@ class Condition extends Constraint
|
|||||||
*/
|
*/
|
||||||
public function getRequiredOptions()
|
public function getRequiredOptions()
|
||||||
{
|
{
|
||||||
return array('condition');
|
return array('expression');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function getTargets()
|
public function getTargets()
|
||||||
{
|
{
|
||||||
return self::CLASS_CONSTRAINT;
|
return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function validatedBy()
|
||||||
|
{
|
||||||
|
return 'validator.expression';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?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\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyPath;
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||||
|
use Symfony\Component\Validator\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Bernhard Schussek <bschussek@symfony.com>
|
||||||
|
*/
|
||||||
|
class ExpressionValidator extends ConstraintValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PropertyAccessorInterface
|
||||||
|
*/
|
||||||
|
private $propertyAccessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExpressionLanguage
|
||||||
|
*/
|
||||||
|
private $expressionLanguage;
|
||||||
|
|
||||||
|
public function __construct(PropertyAccessorInterface $propertyAccessor)
|
||||||
|
{
|
||||||
|
$this->propertyAccessor = $propertyAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function validate($value, Constraint $constraint)
|
||||||
|
{
|
||||||
|
if (null === $value || '' === $value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$variables = array();
|
||||||
|
|
||||||
|
if (null === $this->context->getPropertyName()) {
|
||||||
|
$variables['this'] = $value;
|
||||||
|
} else {
|
||||||
|
// Extract the object that the property belongs to from the object
|
||||||
|
// graph
|
||||||
|
$path = new PropertyPath($this->context->getPropertyPath());
|
||||||
|
$parentPath = $path->getParent();
|
||||||
|
$root = $this->context->getRoot();
|
||||||
|
|
||||||
|
$variables['value'] = $value;
|
||||||
|
$variables['this'] = $parentPath ? $this->propertyAccessor->getValue($root, $parentPath) : $root;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
|
||||||
|
$this->context->addViolation($constraint->message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getExpressionLanguage()
|
||||||
|
{
|
||||||
|
if (null === $this->expressionLanguage) {
|
||||||
|
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
|
||||||
|
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||||
|
}
|
||||||
|
$this->expressionLanguage = new ExpressionLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->expressionLanguage;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?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\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base RuntimeException for the Validator component.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,197 @@
|
|||||||
|
<?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\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
|
use Symfony\Component\Validator\Constraints\Expression;
|
||||||
|
use Symfony\Component\Validator\Constraints\ExpressionValidator;
|
||||||
|
|
||||||
|
class ExpressionValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $context;
|
||||||
|
protected $validator;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
|
||||||
|
$this->validator = new ExpressionValidator(PropertyAccess::createPropertyAccessor());
|
||||||
|
$this->validator->initialize($this->context);
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getClassName')
|
||||||
|
->will($this->returnValue(__CLASS__));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$this->context = null;
|
||||||
|
$this->validator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNullIsValid()
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate(null, new Expression('value == 1'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyStringIsValid()
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate('', new Expression('value == 1'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSucceedingExpressionAtObjectLevel()
|
||||||
|
{
|
||||||
|
$constraint = new Expression('this.property == 1');
|
||||||
|
|
||||||
|
$object = (object) array('property' => '1');
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyName')
|
||||||
|
->will($this->returnValue(null));
|
||||||
|
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate($object, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailingExpressionAtObjectLevel()
|
||||||
|
{
|
||||||
|
$constraint = new Expression(array(
|
||||||
|
'expression' => 'this.property == 1',
|
||||||
|
'message' => 'myMessage',
|
||||||
|
));
|
||||||
|
|
||||||
|
$object = (object) array('property' => '2');
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyName')
|
||||||
|
->will($this->returnValue(null));
|
||||||
|
|
||||||
|
$this->context->expects($this->once())
|
||||||
|
->method('addViolation')
|
||||||
|
->with('myMessage');
|
||||||
|
|
||||||
|
$this->validator->validate($object, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSucceedingExpressionAtPropertyLevel()
|
||||||
|
{
|
||||||
|
$constraint = new Expression('value == this.expected');
|
||||||
|
|
||||||
|
$object = (object) array('expected' => '1');
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyName')
|
||||||
|
->will($this->returnValue('property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyPath')
|
||||||
|
->will($this->returnValue('property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getRoot')
|
||||||
|
->will($this->returnValue($object));
|
||||||
|
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate('1', $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailingExpressionAtPropertyLevel()
|
||||||
|
{
|
||||||
|
$constraint = new Expression(array(
|
||||||
|
'expression' => 'value == this.expected',
|
||||||
|
'message' => 'myMessage',
|
||||||
|
));
|
||||||
|
|
||||||
|
$object = (object) array('expected' => '1');
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyName')
|
||||||
|
->will($this->returnValue('property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyPath')
|
||||||
|
->will($this->returnValue('property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getRoot')
|
||||||
|
->will($this->returnValue($object));
|
||||||
|
|
||||||
|
$this->context->expects($this->once())
|
||||||
|
->method('addViolation')
|
||||||
|
->with('myMessage');
|
||||||
|
|
||||||
|
$this->validator->validate('2', $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSucceedingExpressionAtNestedPropertyLevel()
|
||||||
|
{
|
||||||
|
$constraint = new Expression('value == this.expected');
|
||||||
|
|
||||||
|
$object = (object) array('expected' => '1');
|
||||||
|
$root = (object) array('nested' => $object);
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyName')
|
||||||
|
->will($this->returnValue('property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyPath')
|
||||||
|
->will($this->returnValue('nested.property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getRoot')
|
||||||
|
->will($this->returnValue($root));
|
||||||
|
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate('1', $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailingExpressionAtNestedPropertyLevel()
|
||||||
|
{
|
||||||
|
$constraint = new Expression(array(
|
||||||
|
'expression' => 'value == this.expected',
|
||||||
|
'message' => 'myMessage',
|
||||||
|
));
|
||||||
|
|
||||||
|
$object = (object) array('expected' => '1');
|
||||||
|
$root = (object) array('nested' => $object);
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyName')
|
||||||
|
->will($this->returnValue('property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getPropertyPath')
|
||||||
|
->will($this->returnValue('nested.property'));
|
||||||
|
|
||||||
|
$this->context->expects($this->any())
|
||||||
|
->method('getRoot')
|
||||||
|
->will($this->returnValue($root));
|
||||||
|
|
||||||
|
$this->context->expects($this->once())
|
||||||
|
->method('addViolation')
|
||||||
|
->with('myMessage');
|
||||||
|
|
||||||
|
$this->validator->validate('2', $constraint);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator;
|
namespace Symfony\Component\Validator;
|
||||||
|
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
|
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
|
||||||
use Symfony\Component\Validator\Exception\ValidatorException;
|
use Symfony\Component\Validator\Exception\ValidatorException;
|
||||||
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
|
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
|
||||||
@ -84,6 +86,11 @@ class ValidatorBuilder implements ValidatorBuilderInterface
|
|||||||
*/
|
*/
|
||||||
private $translationDomain;
|
private $translationDomain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PropertyAccessorInterface
|
||||||
|
*/
|
||||||
|
private $propertyAccessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -253,6 +260,10 @@ class ValidatorBuilder implements ValidatorBuilderInterface
|
|||||||
*/
|
*/
|
||||||
public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory)
|
public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory)
|
||||||
{
|
{
|
||||||
|
if (null !== $this->propertyAccessor) {
|
||||||
|
throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().');
|
||||||
|
}
|
||||||
|
|
||||||
$this->validatorFactory = $validatorFactory;
|
$this->validatorFactory = $validatorFactory;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -278,6 +289,20 @@ class ValidatorBuilder implements ValidatorBuilderInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor)
|
||||||
|
{
|
||||||
|
if (null !== $this->validatorFactory) {
|
||||||
|
throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->propertyAccessor = $propertyAccessor;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -319,7 +344,8 @@ class ValidatorBuilder implements ValidatorBuilderInterface
|
|||||||
$metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache);
|
$metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
$validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory();
|
$propertyAccessor = $this->propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||||
|
$validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($propertyAccessor);
|
||||||
$translator = $this->translator ?: new DefaultTranslator();
|
$translator = $this->translator ?: new DefaultTranslator();
|
||||||
|
|
||||||
return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers);
|
return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator;
|
namespace Symfony\Component\Validator;
|
||||||
|
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
|
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Component\Translation\TranslatorInterface;
|
||||||
use Doctrine\Common\Annotations\Reader;
|
use Doctrine\Common\Annotations\Reader;
|
||||||
@ -159,6 +160,15 @@ interface ValidatorBuilderInterface
|
|||||||
*/
|
*/
|
||||||
public function setTranslationDomain($translationDomain);
|
public function setTranslationDomain($translationDomain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the property accessor for resolving property paths.
|
||||||
|
*
|
||||||
|
* @param PropertyAccessorInterface $propertyAccessor The property accessor.
|
||||||
|
*
|
||||||
|
* @return ValidatorBuilderInterface The builder object.
|
||||||
|
*/
|
||||||
|
public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds and returns a new validator object.
|
* Builds and returns a new validator object.
|
||||||
*
|
*
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3",
|
"php": ">=5.3.3",
|
||||||
"symfony/translation": "~2.0"
|
"symfony/translation": "~2.0",
|
||||||
|
"symfony/property-access": "~2.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/http-foundation": "~2.1",
|
"symfony/http-foundation": "~2.1",
|
||||||
|
Reference in New Issue
Block a user