6b9a355fb0
Commits -------92f820a
Renamed registerConstraints to loadDynamicValidatorMetadatadd12ff8
CS fix, getConstraints renamed09c1911
[Validator] Improved dynamic constraints54cb6e4
[Validator] Added dynamic constraints Discussion ---------- [Validator] Dynamic constraints Bug fix: no Feature addition: yes Backwards compatibility break: no Symfony2 tests pass: yes By now the Validator component is based on a per-class configuration of constraints, but in some cases it might be neccessary to add new constraints dynamically at runtime. This pull request adds a "ConstraintProviderInterface" to the Validator component. If an object is validated that implements this interface the method "getConstraints" is used to add dynamic constraints: class User implements ConstraintProviderInterface { protected $isPremium; protected $paymentInformation; public function getConstraints(ClassMetadata $metadata) { if ($this->isPremium) { $metadata->addPropertyConstraint('paymentInformation', new NotBlank()); } } } --------------------------------------------------------------------------- by alexandresalome at 2012-01-15T11:20:04Z Related to #1151 --------------------------------------------------------------------------- by canni at 2012-01-16T09:22:28Z 👍 --------------------------------------------------------------------------- by bschussek at 2012-01-16T12:32:44Z I think this is a good addition. I think we still have a naming problem though. When constraints are loaded using a static method, the default name for the loader method is `loadValidatorMetadata`. Since the method for dynamic constraint loading is basically the same, I think the two names should be related. Solution (1): Rename the method in your interface to `loadDynamicValidatorMetadata`. Ugly and long. class MyClass implements ConstraintProviderInterface { public static loadValidatorMetadata(ClassMetadata $metadata) ... public loadDynamicValidatorMetadata(ClassMetadata $metadata) ... } Solution (2): Rename the default method name in `StaticMethodLoader` to `registerConstraints` and adjust the docs. Breaks BC. class MyClass implements ConstraintProviderInterface { public static registerConstraints(ClassMetadata $metadata) ... public registerDynamicConstraints(ClassMetadata $metadata) ... } @fabpot: Are we allowed to break BC here? If not, we should probably stick to (1). --------------------------------------------------------------------------- by fabpot at 2012-01-16T12:36:14Z I would prefer to not break BC if possible. --------------------------------------------------------------------------- by blogsh at 2012-01-16T15:25:46Z So "loadDynamicValidatorMetadata" would be the best solution? --------------------------------------------------------------------------- by althaus at 2012-01-17T13:39:19Z >So "loadDynamicValidatorMetadata" would be the best solution? Sounds fine for me based on @bschussek's comment.
198 lines
6.1 KiB
PHP
198 lines
6.1 KiB
PHP
<?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;
|
|
|
|
require_once __DIR__.'/Fixtures/Entity.php';
|
|
require_once __DIR__.'/Fixtures/FailingConstraint.php';
|
|
require_once __DIR__.'/Fixtures/FailingConstraintValidator.php';
|
|
require_once __DIR__.'/Fixtures/FakeClassMetadataFactory.php';
|
|
require_once __DIR__.'/Fixtures/DynamicConstraintsEntity.php';
|
|
|
|
use Symfony\Tests\Component\Validator\Fixtures\Entity;
|
|
use Symfony\Tests\Component\Validator\Fixtures\FakeClassMetadataFactory;
|
|
use Symfony\Tests\Component\Validator\Fixtures\FailingConstraint;
|
|
use Symfony\Tests\Component\Validator\Fixtures\DynamicConstraintsEntity;
|
|
use Symfony\Component\Validator\Validator;
|
|
use Symfony\Component\Validator\ConstraintViolation;
|
|
use Symfony\Component\Validator\ConstraintViolationList;
|
|
use Symfony\Component\Validator\ConstraintValidatorFactory;
|
|
use Symfony\Component\Validator\Mapping\ClassMetadata;
|
|
|
|
class ValidatorTest extends \PHPUnit_Framework_TestCase
|
|
{
|
|
protected $factory;
|
|
protected $validator;
|
|
|
|
protected function setUp()
|
|
{
|
|
$this->factory = new FakeClassMetadataFactory();
|
|
$this->validator = new Validator($this->factory, new ConstraintValidatorFactory());
|
|
}
|
|
|
|
protected function tearDown()
|
|
{
|
|
$this->factory = null;
|
|
$this->validator = null;
|
|
}
|
|
|
|
public function testValidate_defaultGroup()
|
|
{
|
|
$entity = new Entity();
|
|
$metadata = new ClassMetadata(get_class($entity));
|
|
$metadata->addPropertyConstraint('firstName', new FailingConstraint());
|
|
$metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
|
|
'groups' => 'Custom',
|
|
)));
|
|
$this->factory->addClassMetadata($metadata);
|
|
|
|
// Only the constraint of group "Default" failed
|
|
$violations = new ConstraintViolationList();
|
|
$violations->add(new ConstraintViolation(
|
|
'',
|
|
array(),
|
|
$entity,
|
|
'firstName',
|
|
''
|
|
));
|
|
|
|
$this->assertEquals($violations, $this->validator->validate($entity));
|
|
}
|
|
|
|
public function testValidate_oneGroup()
|
|
{
|
|
$entity = new Entity();
|
|
$metadata = new ClassMetadata(get_class($entity));
|
|
$metadata->addPropertyConstraint('firstName', new FailingConstraint());
|
|
$metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
|
|
'groups' => 'Custom',
|
|
)));
|
|
$this->factory->addClassMetadata($metadata);
|
|
|
|
// Only the constraint of group "Custom" failed
|
|
$violations = new ConstraintViolationList();
|
|
$violations->add(new ConstraintViolation(
|
|
'',
|
|
array(),
|
|
$entity,
|
|
'lastName',
|
|
''
|
|
));
|
|
|
|
$this->assertEquals($violations, $this->validator->validate($entity, 'Custom'));
|
|
}
|
|
|
|
public function testValidate_multipleGroups()
|
|
{
|
|
$entity = new Entity();
|
|
$metadata = new ClassMetadata(get_class($entity));
|
|
$metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
|
|
'groups' => 'First',
|
|
)));
|
|
$metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
|
|
'groups' => 'Second',
|
|
)));
|
|
$this->factory->addClassMetadata($metadata);
|
|
|
|
// The constraints of both groups failed
|
|
$violations = new ConstraintViolationList();
|
|
$violations->add(new ConstraintViolation(
|
|
'',
|
|
array(),
|
|
$entity,
|
|
'firstName',
|
|
''
|
|
));
|
|
$violations->add(new ConstraintViolation(
|
|
'',
|
|
array(),
|
|
$entity,
|
|
'lastName',
|
|
''
|
|
));
|
|
|
|
$result = $this->validator->validate($entity, array('First', 'Second'));
|
|
|
|
$this->assertEquals($violations, $result);
|
|
}
|
|
|
|
public function testValidate_constraintProvider()
|
|
{
|
|
$entity = new DynamicConstraintsEntity();
|
|
$metadata = new ClassMetadata(get_class($entity));
|
|
$this->factory->addClassMetadata($metadata);
|
|
|
|
$entity->setValidation(true);
|
|
|
|
$violations = new ConstraintViolationList();
|
|
$violations->add(new ConstraintViolation(
|
|
'',
|
|
array(),
|
|
$entity,
|
|
'firstValue',
|
|
''
|
|
));
|
|
$violations->add(new ConstraintViolation(
|
|
'',
|
|
array(),
|
|
$entity,
|
|
'secondValue',
|
|
''
|
|
));
|
|
|
|
$this->assertEquals($violations, $this->validator->validate($entity));
|
|
|
|
$entity->setValidation(false);
|
|
|
|
$violations = new ConstraintViolationList();
|
|
$this->assertEquals($violations, $this->validator->validate($entity));
|
|
}
|
|
|
|
public function testValidateProperty()
|
|
{
|
|
$entity = new Entity();
|
|
$metadata = new ClassMetadata(get_class($entity));
|
|
$metadata->addPropertyConstraint('firstName', new FailingConstraint());
|
|
$this->factory->addClassMetadata($metadata);
|
|
|
|
$result = $this->validator->validateProperty($entity, 'firstName');
|
|
|
|
$this->assertCount(1, $result);
|
|
}
|
|
|
|
public function testValidatePropertyValue()
|
|
{
|
|
$entity = new Entity();
|
|
$metadata = new ClassMetadata(get_class($entity));
|
|
$metadata->addPropertyConstraint('firstName', new FailingConstraint());
|
|
$this->factory->addClassMetadata($metadata);
|
|
|
|
$result = $this->validator->validatePropertyValue(get_class($entity), 'firstName', 'Bernhard');
|
|
|
|
$this->assertCount(1, $result);
|
|
}
|
|
|
|
public function testValidateValue()
|
|
{
|
|
$result = $this->validator->validateValue('Bernhard', new FailingConstraint());
|
|
|
|
$this->assertCount(1, $result);
|
|
}
|
|
|
|
public function testGetMetadataFactory()
|
|
{
|
|
$this->assertInstanceOf(
|
|
'Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface',
|
|
$this->validator->getMetadataFactory()
|
|
);
|
|
}
|
|
}
|