bug #11645 [Form] Fixed ValidatorExtension to work with the 2.5 Validation API (webmozart)

This PR was merged into the 2.5 branch.

Discussion
----------

[Form] Fixed ValidatorExtension to work with the 2.5 Validation API

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #11606
| License       | MIT
| Doc PR        | -

The ValidatorExtension::loadTypeGuesser() method used to fail because the method `getMetadataFactory()` does not exist anymore on the new `ValidatorInterface`. This was fixed easily, because `ValidatorInterface` now extends `ClassMetadataFactory`.

Commits
-------

ff74f4e [Form] Fixed ValidatorExtension to work with the 2.5 Validation API
This commit is contained in:
Bernhard Schussek 2014-08-15 11:42:11 +02:00
commit cf8b4e253b
2 changed files with 60 additions and 63 deletions

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Form\Extension\Validator;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
use Symfony\Component\Form\AbstractExtension;
use Symfony\Component\Validator\Constraints\Valid;
@ -29,23 +30,19 @@ class ValidatorExtension extends AbstractExtension
/**
* @param ValidatorInterface|LegacyValidatorInterface $validator
*
* @throws UnexpectedTypeException If $validator is invalid
*/
public function __construct($validator)
{
// since validator apiVersion 2.5
// 2.5 API
if ($validator instanceof ValidatorInterface) {
$this->validator = $validator;
/** @var $metadata ClassMetadata */
$metadata = $this->validator->getMetadataFor('Symfony\Component\Form\Form');
// until validator apiVersion 2.4
$metadata = $validator->getMetadataFor('Symfony\Component\Form\Form');
// 2.4 API
} elseif ($validator instanceof LegacyValidatorInterface) {
$this->validator = $validator;
/** @var $metadata ClassMetadata */
$metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form');
$metadata = $validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form');
} else {
throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface');
throw new UnexpectedTypeException($validator, 'Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface');
}
// Register the form constraints in the validator programmatically.
@ -53,13 +50,22 @@ class ValidatorExtension extends AbstractExtension
// the DIC, where the XML file is loaded automatically. Thus the following
// code must be kept synchronized with validation.xml
/** @var $metadata ClassMetadata */
$metadata->addConstraint(new Form());
$metadata->addPropertyConstraint('children', new Valid());
$this->validator = $validator;
}
public function loadTypeGuesser()
{
return new ValidatorTypeGuesser($this->validator->getMetadataFactory());
// 2.4 API
if ($this->validator instanceof LegacyValidatorInterface) {
return new ValidatorTypeGuesser($this->validator->getMetadataFactory());
}
// 2.5 API - ValidatorInterface extends MetadataFactoryInterface
return new ValidatorTypeGuesser($this->validator);
}
protected function loadTypeExtensions()

View File

@ -15,79 +15,70 @@ use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase
{
public function testValidatorInterfaceSinceSymfony25()
public function test2Dot5ValidationApi()
{
$classMetaData = $this->createClassMetaDataMock();
// Mock of ValidatorInterface since apiVersion 2.5
$validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface');
$metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')
->disableOriginalConstructor()
->getMock();
$validator
->expects($this->once())
$validator->expects($this->once())
->method('getMetadataFor')
->with($this->identicalTo('Symfony\Component\Form\Form'))
->will($this->returnValue($classMetaData))
;
->will($this->returnValue($metadata));
$validatorExtension = new ValidatorExtension($validator);
$this->assertAttributeSame($validator, 'validator', $validatorExtension);
// Verify that the constraints are added
$metadata->expects($this->once())
->method('addConstraint')
->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form'));
$metadata->expects($this->once())
->method('addPropertyConstraint')
->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid'));
$extension = new ValidatorExtension($validator);
$guesser = $extension->loadTypeGuesser();
$this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser);
}
public function testValidatorInterfaceUntilSymfony24()
public function test2Dot4ValidationApi()
{
$classMetaData = $this->createClassMetaDataMock();
$factory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
$validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
$metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')
->disableOriginalConstructor()
->getMock();
$metaDataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
$validator->expects($this->any())
->method('getMetadataFactory')
->will($this->returnValue($factory));
$metaDataFactory
->expects($this->once())
$factory->expects($this->once())
->method('getMetadataFor')
->with($this->identicalTo('Symfony\Component\Form\Form'))
->will($this->returnValue($classMetaData))
;
->will($this->returnValue($metadata));
// Mock of ValidatorInterface until apiVersion 2.4
$validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
// Verify that the constraints are added
$metadata->expects($this->once())
->method('addConstraint')
->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form'));
$validator
->expects($this->once())
->method('getMetadataFactory')
->will($this->returnValue($metaDataFactory))
;
$metadata->expects($this->once())
->method('addPropertyConstraint')
->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid'));
$validatorExtension = new ValidatorExtension($validator);
$this->assertAttributeSame($validator, 'validator', $validatorExtension);
$extension = new ValidatorExtension($validator);
$guesser = $extension->loadTypeGuesser();
$this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser);
}
/**
* @expectedException \InvalidArgumentException
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testInvalidValidatorInterface()
{
new ValidatorExtension(null);
}
/**
* @return mixed
*/
private function createClassMetaDataMock()
{
$classMetaData = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')
->disableOriginalConstructor()
->getMock();
$classMetaData
->expects($this->once())
->method('addConstraint')
->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form'));
$classMetaData
->expects($this->once())
->method('addPropertyConstraint')
->with(
$this->identicalTo('children'),
$this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid')
);
return $classMetaData;
}
}