/src/Symfony/Component/Validator/ValidatorBuilder.php

https://github.com/liuggio/symfony · PHP · 407 lines · 224 code · 80 blank · 103 comment · 28 complexity · f87f8cdec12fec3b49056d3376c2bd6b MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator;
  11. use Doctrine\Common\Annotations\AnnotationReader;
  12. use Doctrine\Common\Annotations\CachedReader;
  13. use Doctrine\Common\Annotations\Reader;
  14. use Doctrine\Common\Cache\ArrayCache;
  15. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  16. use Symfony\Component\Translation\TranslatorInterface;
  17. use Symfony\Component\Validator\Context\ExecutionContextFactory;
  18. use Symfony\Component\Validator\Context\LegacyExecutionContextFactory;
  19. use Symfony\Component\Validator\Exception\InvalidArgumentException;
  20. use Symfony\Component\Validator\Exception\ValidatorException;
  21. use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
  22. use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
  23. use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
  24. use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
  25. use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
  26. use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
  27. use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader;
  28. use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
  29. use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader;
  30. use Symfony\Component\Validator\Validator\LegacyValidator;
  31. use Symfony\Component\Validator\Validator\RecursiveValidator;
  32. use Symfony\Component\Validator\Validator as ValidatorV24;
  33. /**
  34. * The default implementation of {@link ValidatorBuilderInterface}.
  35. *
  36. * @author Bernhard Schussek <bschussek@gmail.com>
  37. */
  38. class ValidatorBuilder implements ValidatorBuilderInterface
  39. {
  40. /**
  41. * @var array
  42. */
  43. private $initializers = array();
  44. /**
  45. * @var array
  46. */
  47. private $xmlMappings = array();
  48. /**
  49. * @var array
  50. */
  51. private $yamlMappings = array();
  52. /**
  53. * @var array
  54. */
  55. private $methodMappings = array();
  56. /**
  57. * @var Reader|null
  58. */
  59. private $annotationReader;
  60. /**
  61. * @var MetadataFactoryInterface|null
  62. */
  63. private $metadataFactory;
  64. /**
  65. * @var ConstraintValidatorFactoryInterface|null
  66. */
  67. private $validatorFactory;
  68. /**
  69. * @var CacheInterface|null
  70. */
  71. private $metadataCache;
  72. /**
  73. * @var TranslatorInterface|null
  74. */
  75. private $translator;
  76. /**
  77. * @var null|string
  78. */
  79. private $translationDomain;
  80. /**
  81. * @var PropertyAccessorInterface|null
  82. */
  83. private $propertyAccessor;
  84. /**
  85. * @var int|null
  86. */
  87. private $apiVersion;
  88. /**
  89. * {@inheritdoc}
  90. */
  91. public function addObjectInitializer(ObjectInitializerInterface $initializer)
  92. {
  93. $this->initializers[] = $initializer;
  94. return $this;
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. public function addObjectInitializers(array $initializers)
  100. {
  101. $this->initializers = array_merge($this->initializers, $initializers);
  102. return $this;
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. public function addXmlMapping($path)
  108. {
  109. if (null !== $this->metadataFactory) {
  110. throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
  111. }
  112. $this->xmlMappings[] = $path;
  113. return $this;
  114. }
  115. /**
  116. * {@inheritdoc}
  117. */
  118. public function addXmlMappings(array $paths)
  119. {
  120. if (null !== $this->metadataFactory) {
  121. throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
  122. }
  123. $this->xmlMappings = array_merge($this->xmlMappings, $paths);
  124. return $this;
  125. }
  126. /**
  127. * {@inheritdoc}
  128. */
  129. public function addYamlMapping($path)
  130. {
  131. if (null !== $this->metadataFactory) {
  132. throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
  133. }
  134. $this->yamlMappings[] = $path;
  135. return $this;
  136. }
  137. /**
  138. * {@inheritdoc}
  139. */
  140. public function addYamlMappings(array $paths)
  141. {
  142. if (null !== $this->metadataFactory) {
  143. throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
  144. }
  145. $this->yamlMappings = array_merge($this->yamlMappings, $paths);
  146. return $this;
  147. }
  148. /**
  149. * {@inheritdoc}
  150. */
  151. public function addMethodMapping($methodName)
  152. {
  153. if (null !== $this->metadataFactory) {
  154. throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
  155. }
  156. $this->methodMappings[] = $methodName;
  157. return $this;
  158. }
  159. /**
  160. * {@inheritdoc}
  161. */
  162. public function addMethodMappings(array $methodNames)
  163. {
  164. if (null !== $this->metadataFactory) {
  165. throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
  166. }
  167. $this->methodMappings = array_merge($this->methodMappings, $methodNames);
  168. return $this;
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function enableAnnotationMapping(Reader $annotationReader = null)
  174. {
  175. if (null !== $this->metadataFactory) {
  176. throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.');
  177. }
  178. if (null === $annotationReader) {
  179. if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) {
  180. throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.');
  181. }
  182. $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache());
  183. }
  184. $this->annotationReader = $annotationReader;
  185. return $this;
  186. }
  187. /**
  188. * {@inheritdoc}
  189. */
  190. public function disableAnnotationMapping()
  191. {
  192. $this->annotationReader = null;
  193. return $this;
  194. }
  195. /**
  196. * {@inheritdoc}
  197. */
  198. public function setMetadataFactory(MetadataFactoryInterface $metadataFactory)
  199. {
  200. if (count($this->xmlMappings) > 0 || count($this->yamlMappings) > 0 || count($this->methodMappings) > 0 || null !== $this->annotationReader) {
  201. throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.');
  202. }
  203. $this->metadataFactory = $metadataFactory;
  204. return $this;
  205. }
  206. /**
  207. * {@inheritdoc}
  208. */
  209. public function setMetadataCache(CacheInterface $cache)
  210. {
  211. if (null !== $this->metadataFactory) {
  212. throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.');
  213. }
  214. $this->metadataCache = $cache;
  215. return $this;
  216. }
  217. /**
  218. * {@inheritdoc}
  219. */
  220. public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory)
  221. {
  222. if (null !== $this->propertyAccessor) {
  223. 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().');
  224. }
  225. $this->validatorFactory = $validatorFactory;
  226. return $this;
  227. }
  228. /**
  229. * {@inheritdoc}
  230. */
  231. public function setTranslator(TranslatorInterface $translator)
  232. {
  233. $this->translator = $translator;
  234. return $this;
  235. }
  236. /**
  237. * {@inheritdoc}
  238. */
  239. public function setTranslationDomain($translationDomain)
  240. {
  241. $this->translationDomain = $translationDomain;
  242. return $this;
  243. }
  244. /**
  245. * {@inheritdoc}
  246. */
  247. public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor)
  248. {
  249. if (null !== $this->validatorFactory) {
  250. throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.');
  251. }
  252. $this->propertyAccessor = $propertyAccessor;
  253. return $this;
  254. }
  255. /**
  256. * {@inheritdoc}
  257. */
  258. public function setApiVersion($apiVersion)
  259. {
  260. if (!in_array($apiVersion, array(Validation::API_VERSION_2_4, Validation::API_VERSION_2_5, Validation::API_VERSION_2_5_BC))) {
  261. throw new InvalidArgumentException(sprintf(
  262. 'The requested API version is invalid: "%s"',
  263. $apiVersion
  264. ));
  265. }
  266. if (version_compare(PHP_VERSION, '5.3.9', '<') && $apiVersion === Validation::API_VERSION_2_5_BC) {
  267. throw new InvalidArgumentException(sprintf(
  268. 'The Validator API that is compatible with both Symfony 2.4 '.
  269. 'and Symfony 2.5 can only be used on PHP 5.3.9 and higher. '.
  270. 'Your current PHP version is %s.',
  271. PHP_VERSION
  272. ));
  273. }
  274. $this->apiVersion = $apiVersion;
  275. return $this;
  276. }
  277. /**
  278. * {@inheritdoc}
  279. */
  280. public function getValidator()
  281. {
  282. $metadataFactory = $this->metadataFactory;
  283. if (!$metadataFactory) {
  284. $loaders = array();
  285. if (count($this->xmlMappings) > 1) {
  286. $loaders[] = new XmlFilesLoader($this->xmlMappings);
  287. } elseif (1 === count($this->xmlMappings)) {
  288. $loaders[] = new XmlFileLoader($this->xmlMappings[0]);
  289. }
  290. if (count($this->yamlMappings) > 1) {
  291. $loaders[] = new YamlFilesLoader($this->yamlMappings);
  292. } elseif (1 === count($this->yamlMappings)) {
  293. $loaders[] = new YamlFileLoader($this->yamlMappings[0]);
  294. }
  295. foreach ($this->methodMappings as $methodName) {
  296. $loaders[] = new StaticMethodLoader($methodName);
  297. }
  298. if ($this->annotationReader) {
  299. $loaders[] = new AnnotationLoader($this->annotationReader);
  300. }
  301. $loader = null;
  302. if (count($loaders) > 1) {
  303. $loader = new LoaderChain($loaders);
  304. } elseif (1 === count($loaders)) {
  305. $loader = $loaders[0];
  306. }
  307. $metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache);
  308. }
  309. $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($this->propertyAccessor);
  310. $translator = $this->translator ?: new DefaultTranslator();
  311. $apiVersion = $this->apiVersion;
  312. if (null === $apiVersion) {
  313. $apiVersion = version_compare(PHP_VERSION, '5.3.9', '<')
  314. ? Validation::API_VERSION_2_4
  315. : Validation::API_VERSION_2_5_BC;
  316. }
  317. if (Validation::API_VERSION_2_4 === $apiVersion) {
  318. return new ValidatorV24($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers);
  319. }
  320. if (Validation::API_VERSION_2_5 === $apiVersion) {
  321. $contextFactory = new ExecutionContextFactory($translator, $this->translationDomain);
  322. return new RecursiveValidator($contextFactory, $metadataFactory, $validatorFactory, $this->initializers);
  323. }
  324. $contextFactory = new LegacyExecutionContextFactory($metadataFactory, $translator, $this->translationDomain);
  325. return new LegacyValidator($contextFactory, $metadataFactory, $validatorFactory, $this->initializers);
  326. }
  327. }