1eabd1885fd1bb6be64b617d0f2746a09d975b73
[yaffs-website] / vendor / symfony / validator / Mapping / Loader / YamlFileLoader.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Validator\Mapping\Loader;
13
14 use Symfony\Component\Validator\Mapping\ClassMetadata;
15 use Symfony\Component\Yaml\Exception\ParseException;
16 use Symfony\Component\Yaml\Parser as YamlParser;
17
18 /**
19  * Loads validation metadata from a YAML file.
20  *
21  * @author Bernhard Schussek <bschussek@gmail.com>
22  */
23 class YamlFileLoader extends FileLoader
24 {
25     /**
26      * An array of YAML class descriptions.
27      *
28      * @var array
29      */
30     protected $classes = null;
31
32     /**
33      * Caches the used YAML parser.
34      *
35      * @var YamlParser
36      */
37     private $yamlParser;
38
39     /**
40      * {@inheritdoc}
41      */
42     public function loadClassMetadata(ClassMetadata $metadata)
43     {
44         if (null === $this->classes) {
45             $this->loadClassesFromYaml();
46         }
47
48         if (isset($this->classes[$metadata->getClassName()])) {
49             $classDescription = $this->classes[$metadata->getClassName()];
50
51             $this->loadClassMetadataFromYaml($metadata, $classDescription);
52
53             return true;
54         }
55
56         return false;
57     }
58
59     /**
60      * Return the names of the classes mapped in this file.
61      *
62      * @return string[] The classes names
63      */
64     public function getMappedClasses()
65     {
66         if (null === $this->classes) {
67             $this->loadClassesFromYaml();
68         }
69
70         return array_keys($this->classes);
71     }
72
73     /**
74      * Parses a collection of YAML nodes.
75      *
76      * @param array $nodes The YAML nodes
77      *
78      * @return array An array of values or Constraint instances
79      */
80     protected function parseNodes(array $nodes)
81     {
82         $values = array();
83
84         foreach ($nodes as $name => $childNodes) {
85             if (is_numeric($name) && is_array($childNodes) && 1 === count($childNodes)) {
86                 $options = current($childNodes);
87
88                 if (is_array($options)) {
89                     $options = $this->parseNodes($options);
90                 }
91
92                 $values[] = $this->newConstraint(key($childNodes), $options);
93             } else {
94                 if (is_array($childNodes)) {
95                     $childNodes = $this->parseNodes($childNodes);
96                 }
97
98                 $values[$name] = $childNodes;
99             }
100         }
101
102         return $values;
103     }
104
105     /**
106      * Loads the YAML class descriptions from the given file.
107      *
108      * @param string $path The path of the YAML file
109      *
110      * @return array The class descriptions
111      *
112      * @throws \InvalidArgumentException If the file could not be loaded or did
113      *                                   not contain a YAML array
114      */
115     private function parseFile($path)
116     {
117         try {
118             $classes = $this->yamlParser->parse(file_get_contents($path));
119         } catch (ParseException $e) {
120             throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
121         }
122
123         // empty file
124         if (null === $classes) {
125             return array();
126         }
127
128         // not an array
129         if (!is_array($classes)) {
130             throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file));
131         }
132
133         return $classes;
134     }
135
136     private function loadClassesFromYaml()
137     {
138         if (null === $this->yamlParser) {
139             $this->yamlParser = new YamlParser();
140         }
141
142         $this->classes = $this->parseFile($this->file);
143
144         if (isset($this->classes['namespaces'])) {
145             foreach ($this->classes['namespaces'] as $alias => $namespace) {
146                 $this->addNamespaceAlias($alias, $namespace);
147             }
148
149             unset($this->classes['namespaces']);
150         }
151     }
152
153     private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $classDescription)
154     {
155         if (isset($classDescription['group_sequence_provider'])) {
156             $metadata->setGroupSequenceProvider(
157                 (bool) $classDescription['group_sequence_provider']
158             );
159         }
160
161         if (isset($classDescription['group_sequence'])) {
162             $metadata->setGroupSequence($classDescription['group_sequence']);
163         }
164
165         if (isset($classDescription['constraints']) && is_array($classDescription['constraints'])) {
166             foreach ($this->parseNodes($classDescription['constraints']) as $constraint) {
167                 $metadata->addConstraint($constraint);
168             }
169         }
170
171         if (isset($classDescription['properties']) && is_array($classDescription['properties'])) {
172             foreach ($classDescription['properties'] as $property => $constraints) {
173                 if (null !== $constraints) {
174                     foreach ($this->parseNodes($constraints) as $constraint) {
175                         $metadata->addPropertyConstraint($property, $constraint);
176                     }
177                 }
178             }
179         }
180
181         if (isset($classDescription['getters']) && is_array($classDescription['getters'])) {
182             foreach ($classDescription['getters'] as $getter => $constraints) {
183                 if (null !== $constraints) {
184                     foreach ($this->parseNodes($constraints) as $constraint) {
185                         $metadata->addGetterConstraint($getter, $constraint);
186                     }
187                 }
188             }
189         }
190     }
191 }