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