This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/tests/Symfony/Tests/Component/Validator/ValidatorTest.php
Fabien Potencier 6b9a355fb0 merged branch blogsh/dynamic_constraints (PR #3114)
Commits
-------

92f820a Renamed registerConstraints to loadDynamicValidatorMetadata
dd12ff8 CS fix, getConstraints renamed
09c1911 [Validator] Improved dynamic constraints
54cb6e4 [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.
2012-01-22 10:26:39 +01:00

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()
);
}
}