2012-07-30 09:57:16 +01:00
< ? 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 ;
2014-02-22 10:43:44 +00:00
use Doctrine\Common\Annotations\AnnotationRegistry ;
2013-09-10 16:14:04 +01:00
use Symfony\Component\PropertyAccess\PropertyAccess ;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface ;
2014-02-21 17:48:33 +00:00
use Symfony\Component\Validator\Context\ExecutionContextFactory ;
use Symfony\Component\Validator\Context\LegacyExecutionContextFactory ;
use Symfony\Component\Validator\Exception\InvalidArgumentException ;
2012-07-30 09:57:16 +01:00
use Symfony\Component\Validator\Mapping\ClassMetadataFactory ;
use Symfony\Component\Validator\Exception\ValidatorException ;
use Symfony\Component\Validator\Mapping\Loader\LoaderChain ;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface ;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader ;
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader ;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader ;
use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader ;
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader ;
use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader ;
2012-11-27 21:42:05 +00:00
use Symfony\Component\Translation\TranslatorInterface ;
2012-07-30 11:49:07 +01:00
use Doctrine\Common\Annotations\Reader ;
2012-07-30 09:57:16 +01:00
use Doctrine\Common\Annotations\AnnotationReader ;
2012-07-30 11:49:07 +01:00
use Doctrine\Common\Annotations\CachedReader ;
use Doctrine\Common\Cache\ArrayCache ;
2014-02-21 17:48:33 +00:00
use Symfony\Component\Validator\NodeTraverser\NonRecursiveNodeTraverser ;
use Symfony\Component\Validator\NodeVisitor\ContextUpdateVisitor ;
use Symfony\Component\Validator\NodeVisitor\DefaultGroupReplacingVisitor ;
use Symfony\Component\Validator\NodeVisitor\NodeValidationVisitor ;
use Symfony\Component\Validator\NodeVisitor\ObjectInitializationVisitor ;
use Symfony\Component\Validator\Validator as ValidatorV24 ;
2014-02-22 10:43:44 +00:00
use Symfony\Component\Validator\Validator\TraversingValidator ;
2014-02-21 17:48:33 +00:00
use Symfony\Component\Validator\Validator\LegacyValidator ;
2012-07-30 09:57:16 +01:00
/**
* The default implementation of { @ link ValidatorBuilderInterface } .
*
* @ author Bernhard Schussek < bschussek @ gmail . com >
*/
class ValidatorBuilder implements ValidatorBuilderInterface
{
/**
* @ var array
*/
private $initializers = array ();
/**
* @ var array
*/
private $xmlMappings = array ();
/**
* @ var array
*/
private $yamlMappings = array ();
/**
* @ var array
*/
private $methodMappings = array ();
/**
2012-07-30 11:49:07 +01:00
* @ var Reader
2012-07-30 09:57:16 +01:00
*/
2012-07-30 11:49:07 +01:00
private $annotationReader = null ;
2012-07-30 09:57:16 +01:00
/**
2012-11-22 14:58:46 +00:00
* @ var MetadataFactoryInterface
2012-07-30 09:57:16 +01:00
*/
private $metadataFactory ;
/**
* @ var ConstraintValidatorFactoryInterface
*/
private $validatorFactory ;
/**
* @ var CacheInterface
*/
private $metadataCache ;
2012-11-27 21:42:05 +00:00
/**
* @ var TranslatorInterface
*/
private $translator ;
/**
* @ var null | string
*/
private $translationDomain ;
2013-09-10 16:14:04 +01:00
/**
* @ var PropertyAccessorInterface
*/
private $propertyAccessor ;
2014-02-21 17:48:33 +00:00
/**
* @ var integer
*/
private $apiVersion ;
2012-07-30 09:57:16 +01:00
/**
* { @ inheritdoc }
*/
public function addObjectInitializer ( ObjectInitializerInterface $initializer )
{
$this -> initializers [] = $initializer ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addObjectInitializers ( array $initializers )
{
$this -> initializers = array_merge ( $this -> initializers , $initializers );
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addXmlMapping ( $path )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.' );
}
$this -> xmlMappings [] = $path ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addXmlMappings ( array $paths )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.' );
}
$this -> xmlMappings = array_merge ( $this -> xmlMappings , $paths );
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addYamlMapping ( $path )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.' );
}
$this -> yamlMappings [] = $path ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addYamlMappings ( array $paths )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.' );
}
$this -> yamlMappings = array_merge ( $this -> yamlMappings , $paths );
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addMethodMapping ( $methodName )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.' );
}
$this -> methodMappings [] = $methodName ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function addMethodMappings ( array $methodNames )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.' );
}
$this -> methodMappings = array_merge ( $this -> methodMappings , $methodNames );
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
2012-07-30 11:49:07 +01:00
public function enableAnnotationMapping ( Reader $annotationReader = null )
2012-07-30 09:57:16 +01:00
{
2012-07-30 11:49:07 +01:00
if ( null !== $this -> metadataFactory ) {
2012-07-30 09:57:16 +01:00
throw new ValidatorException ( 'You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.' );
}
2012-07-30 11:49:07 +01:00
if ( null === $annotationReader ) {
2013-10-31 18:07:47 +00:00
if ( ! class_exists ( 'Doctrine\Common\Annotations\AnnotationReader' ) || ! class_exists ( 'Doctrine\Common\Cache\ArrayCache' )) {
throw new \RuntimeException ( 'Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.' );
2012-07-30 11:49:07 +01:00
}
$annotationReader = new CachedReader ( new AnnotationReader (), new ArrayCache ());
}
$this -> annotationReader = $annotationReader ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 11:49:07 +01:00
}
/**
* { @ inheritdoc }
*/
public function disableAnnotationMapping ()
{
$this -> annotationReader = null ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
2013-03-01 08:39:10 +00:00
public function setMetadataFactory ( MetadataFactoryInterface $metadataFactory )
2012-07-30 09:57:16 +01:00
{
2012-07-30 11:49:07 +01:00
if ( count ( $this -> xmlMappings ) > 0 || count ( $this -> yamlMappings ) > 0 || count ( $this -> methodMappings ) > 0 || null !== $this -> annotationReader ) {
2012-07-30 09:57:16 +01:00
throw new ValidatorException ( 'You cannot set a custom metadata factory after adding custom mappings. You should do either of both.' );
}
$this -> metadataFactory = $metadataFactory ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function setMetadataCache ( CacheInterface $cache )
{
if ( null !== $this -> metadataFactory ) {
throw new ValidatorException ( 'You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.' );
}
2012-10-22 15:37:12 +01:00
2012-07-30 09:57:16 +01:00
$this -> metadataCache = $cache ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
/**
* { @ inheritdoc }
*/
public function setConstraintValidatorFactory ( ConstraintValidatorFactoryInterface $validatorFactory )
{
2013-09-10 16:14:04 +01:00
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().' );
}
2012-07-30 09:57:16 +01:00
$this -> validatorFactory = $validatorFactory ;
2012-08-23 10:11:16 +01:00
return $this ;
2012-07-30 09:57:16 +01:00
}
2012-11-27 21:42:05 +00:00
/**
* { @ inheritdoc }
*/
public function setTranslator ( TranslatorInterface $translator )
{
$this -> translator = $translator ;
return $this ;
}
/**
* { @ inheritdoc }
*/
public function setTranslationDomain ( $translationDomain )
{
$this -> translationDomain = $translationDomain ;
return $this ;
}
2013-09-10 16:14:04 +01:00
/**
* { @ 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 ;
}
2014-02-21 17:48:33 +00:00
/**
* { @ inheritdoc }
*/
public function setApiVersion ( $apiVersion )
{
if ( ! ( $apiVersion & ( Validation :: API_VERSION_2_4 | Validation :: API_VERSION_2_5 ))) {
throw new InvalidArgumentException ( sprintf (
'The requested API version is invalid: "%s"' ,
$apiVersion
));
}
if ( version_compare ( PHP_VERSION , '5.3.9' , '<' ) && $apiVersion === ( Validation :: API_VERSION_2_4 | Validation :: API_VERSION_2_5 )) {
throw new InvalidArgumentException ( sprintf (
'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. ' .
'Your current PHP version is %s.' ,
PHP_VERSION
));
}
$this -> apiVersion = $apiVersion ;
return $this ;
}
2012-07-30 09:57:16 +01:00
/**
* { @ inheritdoc }
*/
public function getValidator ()
{
$metadataFactory = $this -> metadataFactory ;
if ( ! $metadataFactory ) {
$loaders = array ();
if ( count ( $this -> xmlMappings ) > 1 ) {
$loaders [] = new XmlFilesLoader ( $this -> xmlMappings );
} elseif ( 1 === count ( $this -> xmlMappings )) {
$loaders [] = new XmlFileLoader ( $this -> xmlMappings [ 0 ]);
}
if ( count ( $this -> yamlMappings ) > 1 ) {
$loaders [] = new YamlFilesLoader ( $this -> yamlMappings );
} elseif ( 1 === count ( $this -> yamlMappings )) {
$loaders [] = new YamlFileLoader ( $this -> yamlMappings [ 0 ]);
}
2012-07-30 11:49:07 +01:00
foreach ( $this -> methodMappings as $methodName ) {
$loaders [] = new StaticMethodLoader ( $methodName );
2012-07-30 09:57:16 +01:00
}
2012-07-30 11:49:07 +01:00
if ( $this -> annotationReader ) {
$loaders [] = new AnnotationLoader ( $this -> annotationReader );
2014-02-22 10:43:44 +00:00
AnnotationRegistry :: registerLoader ( function ( $class ) {
if ( 0 === strpos ( $class , __NAMESPACE__ . '\\Constraints\\' )) {
$file = str_replace ( __NAMESPACE__ . '\\Constraints\\' , __DIR__ . '/Constraints/' , $class ) . '.php' ;
if ( is_file ( $file )) {
require_once $file ;
return true ;
}
}
return false ;
});
2012-07-30 09:57:16 +01:00
}
$loader = null ;
if ( count ( $loaders ) > 1 ) {
$loader = new LoaderChain ( $loaders );
} elseif ( 1 === count ( $loaders )) {
$loader = $loaders [ 0 ];
}
$metadataFactory = new ClassMetadataFactory ( $loader , $this -> metadataCache );
}
2013-09-10 16:14:04 +01:00
$propertyAccessor = $this -> propertyAccessor ? : PropertyAccess :: createPropertyAccessor ();
$validatorFactory = $this -> validatorFactory ? : new ConstraintValidatorFactory ( $propertyAccessor );
2012-11-27 21:42:05 +00:00
$translator = $this -> translator ? : new DefaultTranslator ();
2014-02-21 17:48:33 +00:00
$apiVersion = $this -> apiVersion ;
if ( null === $apiVersion ) {
$apiVersion = version_compare ( PHP_VERSION , '5.3.9' , '<' )
? Validation :: API_VERSION_2_4
: ( Validation :: API_VERSION_2_4 | Validation :: API_VERSION_2_5 );
}
if ( Validation :: API_VERSION_2_4 === $apiVersion ) {
return new ValidatorV24 ( $metadataFactory , $validatorFactory , $translator , $this -> translationDomain , $this -> initializers );
}
if ( Validation :: API_VERSION_2_5 === $apiVersion ) {
2014-02-22 10:43:44 +00:00
$contextFactory = new ExecutionContextFactory ( $translator , $this -> translationDomain );
2014-02-21 17:48:33 +00:00
} else {
2014-02-22 10:43:44 +00:00
$contextFactory = new LegacyExecutionContextFactory ( $translator , $this -> translationDomain );
2014-02-21 17:48:33 +00:00
}
if ( Validation :: API_VERSION_2_5 === $apiVersion ) {
2014-02-22 10:43:44 +00:00
$nodeTraverser = new NonRecursiveNodeTraverser ( $metadataFactory );
if ( count ( $this -> initializers ) > 0 ) {
$nodeTraverser -> addVisitor ( new ObjectInitializationVisitor ( $this -> initializers ));
}
$nodeTraverser -> addVisitor ( new ContextUpdateVisitor ());
$nodeTraverser -> addVisitor ( new DefaultGroupReplacingVisitor ());
$nodeTraverser -> addVisitor ( new NodeValidationVisitor ( $nodeTraverser , $validatorFactory ));
return new TraversingValidator ( $contextFactory , $nodeTraverser , $metadataFactory );
2014-02-21 17:48:33 +00:00
}
2012-07-30 09:57:16 +01:00
2014-02-22 10:43:44 +00:00
return new LegacyValidator ( $contextFactory , $metadataFactory , $validatorFactory );
2012-07-30 09:57:16 +01:00
}
}