[FrameworkBundle] Implemented configuration to select the desired Validator API

This commit is contained in:
Bernhard Schussek 2014-03-18 17:36:12 +01:00
parent 0946dbe7a0
commit 9b204c9354
21 changed files with 264 additions and 103 deletions

View File

@ -19,15 +19,17 @@ class AddValidatorInitializersPass implements CompilerPassInterface
{ {
public function process(ContainerBuilder $container) public function process(ContainerBuilder $container)
{ {
if (!$container->hasDefinition('validator')) { if (!$container->hasDefinition('validator.builder')) {
return; return;
} }
$validatorBuilder = $container->getDefinition('validator.builder');
$initializers = array(); $initializers = array();
foreach ($container->findTaggedServiceIds('validator.initializer') as $id => $attributes) { foreach ($container->findTaggedServiceIds('validator.initializer') as $id => $attributes) {
$initializers[] = new Reference($id); $initializers[] = new Reference($id);
} }
$container->getDefinition('validator')->replaceArgument(4, $initializers); $validatorBuilder->addMethodCall('addObjectInitializers', array($initializers));
} }
} }

View File

@ -444,8 +444,25 @@ class Configuration implements ConfigurationInterface
->children() ->children()
->scalarNode('cache')->end() ->scalarNode('cache')->end()
->booleanNode('enable_annotations')->defaultFalse()->end() ->booleanNode('enable_annotations')->defaultFalse()->end()
->arrayNode('static_method')
->defaultValue(array('loadClassMetadata'))
->prototype('scalar')->end()
->treatFalseLike(array())
->validate()
->ifTrue(function ($v) { return !is_array($v); })
->then(function ($v) { return (array) $v; })
->end()
->end()
->scalarNode('translation_domain')->defaultValue('validators')->end() ->scalarNode('translation_domain')->defaultValue('validators')->end()
->booleanNode('strict_email')->defaultFalse()->end() ->booleanNode('strict_email')->defaultFalse()->end()
->enumNode('api')
->values(array('2.4', '2.5', '2.5-bc', 'auto'))
->defaultValue('auto')
->beforeNormalization()
->ifTrue(function ($v) { return is_scalar($v); })
->then(function ($v) { return (string) $v; })
->end()
->end()
->end() ->end()
->end() ->end()
->end() ->end()

View File

@ -21,6 +21,7 @@ use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\FileLocator;
use Symfony\Component\Validator\Validation;
/** /**
* FrameworkExtension. * FrameworkExtension.
@ -674,27 +675,57 @@ class FrameworkExtension extends Extension
$loader->load('validator.xml'); $loader->load('validator.xml');
$validatorBuilder = $container->getDefinition('validator.builder');
$container->setParameter('validator.translation_domain', $config['translation_domain']); $container->setParameter('validator.translation_domain', $config['translation_domain']);
$container->setParameter('validator.mapping.loader.xml_files_loader.mapping_files', $this->getValidatorXmlMappingFiles($container));
$container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $this->getValidatorYamlMappingFiles($container)); $xmlMappings = $this->getValidatorXmlMappingFiles($container);
$yamlMappings = $this->getValidatorYamlMappingFiles($container);
if (count($xmlMappings) > 0) {
$validatorBuilder->addMethodCall('addXmlMappings', array($xmlMappings));
}
if (count($yamlMappings) > 0) {
$validatorBuilder->addMethodCall('addYamlMappings', array($yamlMappings));
}
$definition = $container->findDefinition('validator.email'); $definition = $container->findDefinition('validator.email');
$definition->replaceArgument(0, $config['strict_email']); $definition->replaceArgument(0, $config['strict_email']);
if (array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { if (array_key_exists('enable_annotations', $config) && $config['enable_annotations']) {
$loaderChain = $container->getDefinition('validator.mapping.loader.loader_chain'); $validatorBuilder->addMethodCall('enableAnnotations', array(new Reference('annotation_reader')));
$arguments = $loaderChain->getArguments(); }
array_unshift($arguments[0], new Reference('validator.mapping.loader.annotation_loader'));
$loaderChain->setArguments($arguments); if (array_key_exists('static_method', $config) && $config['static_method']) {
foreach ($config['static_method'] as $methodName) {
$validatorBuilder->addMethodCall('addMethodMapping', array($methodName));
}
} }
if (isset($config['cache'])) { if (isset($config['cache'])) {
$container->getDefinition('validator.mapping.class_metadata_factory')
->replaceArgument(1, new Reference('validator.mapping.cache.'.$config['cache']));
$container->setParameter( $container->setParameter(
'validator.mapping.cache.prefix', 'validator.mapping.cache.prefix',
'validator_'.hash('sha256', $container->getParameter('kernel.root_dir')) 'validator_'.hash('sha256', $container->getParameter('kernel.root_dir'))
); );
$validatorBuilder->addMethodCall('setCache', array(new Reference('validator.mapping.cache.'.$config['cache'])));
}
if ('auto' !== $config['api']) {
switch ($config['api']) {
case '2.4':
$api = Validation::API_VERSION_2_4;
break;
case '2.5':
$api = Validation::API_VERSION_2_5;
break;
default:
$api = Validation::API_VERSION_2_5_BC;
break;
}
$validatorBuilder->addMethodCall('setApiVersion', array($api));
} }
} }

View File

@ -7,6 +7,14 @@
<xsd:element name="config" type="config" /> <xsd:element name="config" type="config" />
<xsd:simpleType name="validator_api_version">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="2.4" />
<xsd:enumeration value="2.5" />
<xsd:enumeration value="2.5-api" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="config"> <xsd:complexType name="config">
<xsd:all> <xsd:all>
<xsd:element name="form" type="form" minOccurs="0" maxOccurs="1" /> <xsd:element name="form" type="form" minOccurs="0" maxOccurs="1" />
@ -151,9 +159,15 @@
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="validation"> <xsd:complexType name="validation">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="static-method" type="xsd:string" />
</xsd:choice>
<xsd:attribute name="enabled" type="xsd:boolean" /> <xsd:attribute name="enabled" type="xsd:boolean" />
<xsd:attribute name="cache" type="xsd:string" /> <xsd:attribute name="cache" type="xsd:string" />
<xsd:attribute name="enable-annotations" type="xsd:boolean" /> <xsd:attribute name="enable-annotations" type="xsd:boolean" />
<xsd:attribute name="static-method" type="xsd:boolean" />
<xsd:attribute name="api" type="validator_api_version" />
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="annotations"> <xsd:complexType name="annotations">

View File

@ -5,35 +5,33 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters> <parameters>
<parameter key="validator.class">Symfony\Component\Validator\Validator</parameter> <parameter key="validator.class">Symfony\Component\Validator\ValidatorInterface</parameter>
<parameter key="validator.builder.class">Symfony\Component\Validator\ValidatorBuilderInterface</parameter>
<parameter key="validator.builder.factory.class">Symfony\Component\Validator\Validation</parameter>
<parameter key="validator.mapping.class_metadata_factory.class">Symfony\Component\Validator\Mapping\ClassMetadataFactory</parameter> <parameter key="validator.mapping.class_metadata_factory.class">Symfony\Component\Validator\Mapping\ClassMetadataFactory</parameter>
<parameter key="validator.mapping.cache.apc.class">Symfony\Component\Validator\Mapping\Cache\ApcCache</parameter> <parameter key="validator.mapping.cache.apc.class">Symfony\Component\Validator\Mapping\Cache\ApcCache</parameter>
<parameter key="validator.mapping.cache.prefix" /> <parameter key="validator.mapping.cache.prefix" />
<parameter key="validator.mapping.loader.loader_chain.class">Symfony\Component\Validator\Mapping\Loader\LoaderChain</parameter>
<parameter key="validator.mapping.loader.static_method_loader.class">Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader</parameter>
<parameter key="validator.mapping.loader.annotation_loader.class">Symfony\Component\Validator\Mapping\Loader\AnnotationLoader</parameter>
<parameter key="validator.mapping.loader.xml_files_loader.class">Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader</parameter>
<parameter key="validator.mapping.loader.yaml_files_loader.class">Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader</parameter>
<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.yaml_files_loader.mapping_files" type="collection" />
<parameter key="validator.expression.class">Symfony\Component\Validator\Constraints\ExpressionValidator</parameter> <parameter key="validator.expression.class">Symfony\Component\Validator\Constraints\ExpressionValidator</parameter>
<parameter key="validator.email.class">Symfony\Component\Validator\Constraints\EmailValidator</parameter> <parameter key="validator.email.class">Symfony\Component\Validator\Constraints\EmailValidator</parameter>
</parameters> </parameters>
<services> <services>
<service id="validator" class="%validator.class%"> <service id="validator" class="%validator.class%" factory-service="validator.builder" factory-method="getValidator" />
<argument type="service" id="validator.mapping.class_metadata_factory" />
<argument type="service" id="validator.validator_factory" /> <service id="validator.builder" class="%validator.builder.class%" factory-class="%validator.builder.factory.class%" factory-method="createValidatorBuilder" public="false">
<argument type="service" id="translator" /> <call method="setValidatorFactory">
<argument>%validator.translation_domain%</argument> <argument type="service" id="validator.validator_factory" />
<argument type="collection" /> </call>
<call method="setTranslator">
<argument type="service" id="translator" />
</call>
<call method="setTranslationDomain">
<argument>%validator.translation_domain%</argument>
</call>
</service> </service>
<service id="validator.mapping.class_metadata_factory" class="%validator.mapping.class_metadata_factory.class%" public="false"> <service id="validator.mapping.class_metadata_factory" alias="validator" public="false" />
<argument type="service" id="validator.mapping.loader.loader_chain" />
<argument>null</argument>
</service>
<service id="validator.mapping.cache.apc" class="%validator.mapping.cache.apc.class%" public="false"> <service id="validator.mapping.cache.apc" class="%validator.mapping.cache.apc.class%" public="false">
<argument>%validator.mapping.cache.prefix%</argument> <argument>%validator.mapping.cache.prefix%</argument>
@ -44,28 +42,6 @@
<argument type="collection" /> <argument type="collection" />
</service> </service>
<service id="validator.mapping.loader.loader_chain" class="%validator.mapping.loader.loader_chain.class%" public="false">
<argument type="collection">
<argument type="service" id="validator.mapping.loader.static_method_loader" />
<argument type="service" id="validator.mapping.loader.xml_files_loader" />
<argument type="service" id="validator.mapping.loader.yaml_files_loader" />
</argument>
</service>
<service id="validator.mapping.loader.static_method_loader" class="%validator.mapping.loader.static_method_loader.class%" public="false" />
<service id="validator.mapping.loader.annotation_loader" class="%validator.mapping.loader.annotation_loader.class%" public="false">
<argument type="service" id="annotation_reader" />
</service>
<service id="validator.mapping.loader.xml_files_loader" class="%validator.mapping.loader.xml_files_loader.class%" public="false">
<argument>%validator.mapping.loader.xml_files_loader.mapping_files%</argument>
</service>
<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>
</service>
<service id="validator.expression" class="%validator.expression.class%"> <service id="validator.expression" class="%validator.expression.class%">
<argument type="service" id="property_accessor" /> <argument type="service" id="property_accessor" />
<tag name="validator.constraint_validator" alias="validator.expression" /> <tag name="validator.constraint_validator" alias="validator.expression" />

View File

@ -126,8 +126,10 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
'validation' => array( 'validation' => array(
'enabled' => false, 'enabled' => false,
'enable_annotations' => false, 'enable_annotations' => false,
'static_method' => array('loadClassMetadata'),
'translation_domain' => 'validators', 'translation_domain' => 'validators',
'strict_email' => false, 'strict_email' => false,
'api' => 'auto',
), ),
'annotations' => array( 'annotations' => array(
'cache' => 'file', 'cache' => 'file',

View File

@ -0,0 +1,9 @@
<?php
$container->loadFromExtension('framework', array(
'secret' => 's3cr3t',
'validation' => array(
'enabled' => true,
'api' => '2.4',
),
));

View File

@ -0,0 +1,9 @@
<?php
$container->loadFromExtension('framework', array(
'secret' => 's3cr3t',
'validation' => array(
'enabled' => true,
'static_method' => array('loadFoo', 'loadBar'),
),
));

View File

@ -0,0 +1,9 @@
<?php
$container->loadFromExtension('framework', array(
'secret' => 's3cr3t',
'validation' => array(
'enabled' => true,
'static_method' => false,
),
));

View File

@ -0,0 +1,12 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config secret="s3cr3t">
<framework:validation enabled="true" api="2.4" />
</framework:config>
</container>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config secret="s3cr3t">
<framework:validation enabled="true">
<framework:static-method>loadFoo</framework:static-method>
<framework:static-method>loadBar</framework:static-method>
</framework:validation>
</framework:config>
</container>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config secret="s3cr3t">
<framework:validation enabled="true" static-method="false" />
</framework:config>
</container>

View File

@ -0,0 +1,5 @@
framework:
secret: s3cr3t
validation:
enabled: true
api: 2.4

View File

@ -0,0 +1,5 @@
framework:
secret: s3cr3t
validation:
enabled: true
static_method: [loadFoo, loadBar]

View File

@ -0,0 +1,5 @@
framework:
secret: s3cr3t
validation:
enabled: true
static_method: false

View File

@ -15,6 +15,8 @@ use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Validator\Validation;
abstract class FrameworkExtensionTest extends TestCase abstract class FrameworkExtensionTest extends TestCase
{ {
@ -257,17 +259,24 @@ abstract class FrameworkExtensionTest extends TestCase
{ {
$container = $this->createContainerFromFile('full'); $container = $this->createContainerFromFile('full');
$this->assertTrue($container->hasDefinition('validator'), '->registerValidationConfiguration() loads validator.xml');
$this->assertTrue($container->hasDefinition('validator.mapping.loader.xml_files_loader'), '->registerValidationConfiguration() defines the XML loader');
$this->assertTrue($container->hasDefinition('validator.mapping.loader.yaml_files_loader'), '->registerValidationConfiguration() defines the YAML loader');
$xmlFiles = $container->getParameter('validator.mapping.loader.xml_files_loader.mapping_files');
$ref = new \ReflectionClass('Symfony\Component\Form\Form'); $ref = new \ReflectionClass('Symfony\Component\Form\Form');
$this->assertContains( $xmlMappings = array(realpath(dirname($ref->getFileName()).'/Resources/config/validation.xml'));
realpath(dirname($ref->getFileName()).'/Resources/config/validation.xml'),
array_map('realpath', $xmlFiles), $calls = $container->getDefinition('validator.builder')->getMethodCalls();
'->registerValidationConfiguration() adds Form validation.xml to XML loader'
); $this->assertCount(6, $calls);
$this->assertSame('setValidatorFactory', $calls[0][0]);
$this->assertEquals(array(new Reference('validator.validator_factory')), $calls[0][1]);
$this->assertSame('setTranslator', $calls[1][0]);
$this->assertEquals(array(new Reference('translator')), $calls[1][1]);
$this->assertSame('setTranslationDomain', $calls[2][0]);
$this->assertSame(array('%validator.translation_domain%'), $calls[2][1]);
$this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertSame(array($xmlMappings), $calls[3][1]);
$this->assertSame('addMethodMapping', $calls[4][0]);
$this->assertSame(array('loadClassMetadata'), $calls[4][1]);
$this->assertSame('setCache', $calls[5][0]);
$this->assertEquals(array(new Reference('validator.mapping.cache.apc')), $calls[5][1]);
} }
public function testAnnotations() public function testAnnotations()
@ -289,15 +298,14 @@ abstract class FrameworkExtensionTest extends TestCase
{ {
$container = $this->createContainerFromFile('validation_annotations'); $container = $this->createContainerFromFile('validation_annotations');
$this->assertTrue($container->hasDefinition('validator.mapping.loader.annotation_loader'), '->registerValidationConfiguration() defines the annotation loader'); $calls = $container->getDefinition('validator.builder')->getMethodCalls();
$loaders = $container->getDefinition('validator.mapping.loader.loader_chain')->getArgument(0);
$found = false; $this->assertCount(6, $calls);
foreach ($loaders as $loader) { $this->assertSame('enableAnnotations', $calls[4][0]);
if ('validator.mapping.loader.annotation_loader' === (string) $loader) { $this->assertEquals(array(new Reference('annotation_reader')), $calls[4][1]);
$found = true; $this->assertSame('addMethodMapping', $calls[5][0]);
} $this->assertSame(array('loadClassMetadata'), $calls[5][1]);
} // no cache this time
$this->assertTrue($found, 'validator.mapping.loader.annotation_loader is added to the loader chain.');
} }
public function testValidationPaths() public function testValidationPaths()
@ -308,14 +316,49 @@ abstract class FrameworkExtensionTest extends TestCase
'kernel.bundles' => array('TestBundle' => 'Symfony\Bundle\FrameworkBundle\Tests\TestBundle'), 'kernel.bundles' => array('TestBundle' => 'Symfony\Bundle\FrameworkBundle\Tests\TestBundle'),
)); ));
$yamlArgs = $container->getParameter('validator.mapping.loader.yaml_files_loader.mapping_files'); $calls = $container->getDefinition('validator.builder')->getMethodCalls();
$this->assertCount(1, $yamlArgs);
$this->assertStringEndsWith('TestBundle'.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'validation.yml', $yamlArgs[0]);
$xmlArgs = $container->getParameter('validator.mapping.loader.xml_files_loader.mapping_files'); $this->assertCount(7, $calls);
$this->assertCount(2, $xmlArgs); $this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertStringEndsWith('Component'.DIRECTORY_SEPARATOR.'Form/Resources/config/validation.xml', $xmlArgs[0]); $this->assertSame('addYamlMappings', $calls[4][0]);
$this->assertStringEndsWith('TestBundle'.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'validation.xml', $xmlArgs[1]); $this->assertSame('enableAnnotations', $calls[5][0]);
$this->assertSame('addMethodMapping', $calls[6][0]);
$this->assertSame(array('loadClassMetadata'), $calls[6][1]);
$xmlMappings = $calls[3][1][0];
$this->assertCount(2, $xmlMappings);
$this->assertStringEndsWith('Component'.DIRECTORY_SEPARATOR.'Form/Resources/config/validation.xml', $xmlMappings[0]);
$this->assertStringEndsWith('TestBundle'.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'validation.xml', $xmlMappings[1]);
$yamlMappings = $calls[4][1][0];
$this->assertCount(1, $yamlMappings);
$this->assertStringEndsWith('TestBundle'.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'validation.yml', $yamlMappings[0]);
}
public function testValidationNoStaticMethod()
{
$container = $this->createContainerFromFile('validation_no_static_method');
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
$this->assertCount(4, $calls);
$this->assertSame('addXmlMappings', $calls[3][0]);
// no cache, no annotations, no static methods
}
public function testValidationApiVersion()
{
$container = $this->createContainerFromFile('validation_2_4_api');
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
$this->assertCount(6, $calls);
$this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertSame('addMethodMapping', $calls[4][0]);
$this->assertSame(array('loadClassMetadata'), $calls[4][1]);
$this->assertSame('setApiVersion', $calls[5][0]);
$this->assertSame(array(Validation::API_VERSION_2_4), $calls[5][1]);
// no cache, no annotations
} }
public function testFormsCanBeEnabledWithoutCsrfProtection() public function testFormsCanBeEnabledWithoutCsrfProtection()

View File

@ -139,7 +139,7 @@ class ValidatorBuilderTest extends \PHPUnit_Framework_TestCase
$this->markTestSkipped('Not supported prior to PHP 5.3.9'); $this->markTestSkipped('Not supported prior to PHP 5.3.9');
} }
$this->assertSame($this->builder, $this->builder->setApiVersion(Validation::API_VERSION_2_4 | Validation::API_VERSION_2_5)); $this->assertSame($this->builder, $this->builder->setApiVersion(Validation::API_VERSION_2_5_BC));
$this->assertInstanceOf('Symfony\Component\Validator\Validator\LegacyValidator', $this->builder->getValidator()); $this->assertInstanceOf('Symfony\Component\Validator\Validator\LegacyValidator', $this->builder->getValidator());
} }
} }

View File

@ -28,6 +28,12 @@ final class Validation
*/ */
const API_VERSION_2_5 = 2; const API_VERSION_2_5 = 2;
/**
* The Validator API provided by Symfony 2.5 and newer with a backwards
* compatibility layer for 2.4 and older.
*/
const API_VERSION_2_5_BC = 3;
/** /**
* Creates a new validator. * Creates a new validator.
* *

View File

@ -22,9 +22,9 @@ use Symfony\Component\Validator\Exception\ValidatorException;
* @author Bernhard Schussek <bschussek@gmail.com> * @author Bernhard Schussek <bschussek@gmail.com>
* *
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
* Use {@link Validator\TraversingValidator} instead. * Use {@link Validator\RecursiveValidator} instead.
*/ */
class Validator implements ValidatorInterface class Validator implements ValidatorInterface, Mapping\Factory\MetadataFactoryInterface
{ {
/** /**
* @var MetadataFactoryInterface * @var MetadataFactoryInterface
@ -82,6 +82,14 @@ class Validator implements ValidatorInterface
return $this->metadataFactory->getMetadataFor($value); return $this->metadataFactory->getMetadataFor($value);
} }
/**
* {@inheritDoc}
*/
public function hasMetadataFor($value)
{
return $this->metadataFactory->hasMetadataFor($value);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
/** /**
* Validates PHP values against constraints. * Validates PHP values against constraints.
@ -21,7 +22,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
* @since 2.5 * @since 2.5
* @author Bernhard Schussek <bschussek@gmail.com> * @author Bernhard Schussek <bschussek@gmail.com>
*/ */
interface ValidatorInterface interface ValidatorInterface extends MetadataFactoryInterface
{ {
/** /**
* Validates a value against a constraint or a list of constraints. * Validates a value against a constraint or a list of constraints.
@ -96,24 +97,4 @@ interface ValidatorInterface
* @return ContextualValidatorInterface The validator for that context * @return ContextualValidatorInterface The validator for that context
*/ */
public function inContext(ExecutionContextInterface $context); public function inContext(ExecutionContextInterface $context);
/**
* Returns the metadata for an object.
*
* @param object $object The object
*
* @return \Symfony\Component\Validator\Mapping\MetadataInterface The metadata
*
* @throws \Symfony\Component\Validator\Exception\NoSuchMetadataException If no metadata exists
*/
public function getMetadataFor($object);
/**
* Returns whether the validator has metadata for an object.
*
* @param object $object The object
*
* @return Boolean Whether metadata exists for that object
*/
public function hasMetadataFor($object);
} }

View File

@ -319,14 +319,14 @@ class ValidatorBuilder implements ValidatorBuilderInterface
*/ */
public function setApiVersion($apiVersion) public function setApiVersion($apiVersion)
{ {
if (!($apiVersion & (Validation::API_VERSION_2_4 | Validation::API_VERSION_2_5))) { if (!in_array($apiVersion, array(Validation::API_VERSION_2_4, Validation::API_VERSION_2_5, Validation::API_VERSION_2_5_BC))) {
throw new InvalidArgumentException(sprintf( throw new InvalidArgumentException(sprintf(
'The requested API version is invalid: "%s"', 'The requested API version is invalid: "%s"',
$apiVersion $apiVersion
)); ));
} }
if (version_compare(PHP_VERSION, '5.3.9', '<') && $apiVersion === (Validation::API_VERSION_2_4 | Validation::API_VERSION_2_5)) { if (version_compare(PHP_VERSION, '5.3.9', '<') && $apiVersion === Validation::API_VERSION_2_5_BC) {
throw new InvalidArgumentException(sprintf( throw new InvalidArgumentException(sprintf(
'The Validator API that is compatible with both Symfony 2.4 '. 'The Validator API that is compatible with both Symfony 2.4 '.
'and Symfony 2.5 can only be used on PHP 5.3.9 and higher. '. 'and Symfony 2.5 can only be used on PHP 5.3.9 and higher. '.
@ -403,7 +403,7 @@ class ValidatorBuilder implements ValidatorBuilderInterface
if (null === $apiVersion) { if (null === $apiVersion) {
$apiVersion = version_compare(PHP_VERSION, '5.3.9', '<') $apiVersion = version_compare(PHP_VERSION, '5.3.9', '<')
? Validation::API_VERSION_2_4 ? Validation::API_VERSION_2_4
: (Validation::API_VERSION_2_4 | Validation::API_VERSION_2_5); : Validation::API_VERSION_2_5_BC;
} }
if (Validation::API_VERSION_2_4 === $apiVersion) { if (Validation::API_VERSION_2_4 === $apiVersion) {