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