Version 1
[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             if (null === $this->yamlParser) {
46                 $this->yamlParser = new YamlParser();
47             }
48
49             $this->classes = $this->parseFile($this->file);
50
51             if (isset($this->classes['namespaces'])) {
52                 foreach ($this->classes['namespaces'] as $alias => $namespace) {
53                     $this->addNamespaceAlias($alias, $namespace);
54                 }
55
56                 unset($this->classes['namespaces']);
57             }
58         }
59
60         if (isset($this->classes[$metadata->getClassName()])) {
61             $classDescription = $this->classes[$metadata->getClassName()];
62
63             $this->loadClassMetadataFromYaml($metadata, $classDescription);
64
65             return true;
66         }
67
68         return false;
69     }
70
71     /**
72      * Parses a collection of YAML nodes.
73      *
74      * @param array $nodes The YAML nodes
75      *
76      * @return array An array of values or Constraint instances
77      */
78     protected function parseNodes(array $nodes)
79     {
80         $values = array();
81
82         foreach ($nodes as $name => $childNodes) {
83             if (is_numeric($name) && is_array($childNodes) && 1 === count($childNodes)) {
84                 $options = current($childNodes);
85
86                 if (is_array($options)) {
87                     $options = $this->parseNodes($options);
88                 }
89
90                 $values[] = $this->newConstraint(key($childNodes), $options);
91             } else {
92                 if (is_array($childNodes)) {
93                     $childNodes = $this->parseNodes($childNodes);
94                 }
95
96                 $values[$name] = $childNodes;
97             }
98         }
99
100         return $values;
101     }
102
103     /**
104      * Loads the YAML class descriptions from the given file.
105      *
106      * @param string $path The path of the YAML file
107      *
108      * @return array The class descriptions
109      *
110      * @throws \InvalidArgumentException If the file could not be loaded or did
111      *                                   not contain a YAML array
112      */
113     private function parseFile($path)
114     {
115         try {
116             $classes = $this->yamlParser->parse(file_get_contents($path));
117         } catch (ParseException $e) {
118             throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
119         }
120
121         // empty file
122         if (null === $classes) {
123             return array();
124         }
125
126         // not an array
127         if (!is_array($classes)) {
128             throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file));
129         }
130
131         return $classes;
132     }
133
134     /**
135      * Loads the validation metadata from the given YAML class description.
136      *
137      * @param ClassMetadata $metadata         The metadata to load
138      * @param array         $classDescription The YAML class description
139      */
140     private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $classDescription)
141     {
142         if (isset($classDescription['group_sequence_provider'])) {
143             $metadata->setGroupSequenceProvider(
144                 (bool) $classDescription['group_sequence_provider']
145             );
146         }
147
148         if (isset($classDescription['group_sequence'])) {
149             $metadata->setGroupSequence($classDescription['group_sequence']);
150         }
151
152         if (isset($classDescription['constraints']) && is_array($classDescription['constraints'])) {
153             foreach ($this->parseNodes($classDescription['constraints']) as $constraint) {
154                 $metadata->addConstraint($constraint);
155             }
156         }
157
158         if (isset($classDescription['properties']) && is_array($classDescription['properties'])) {
159             foreach ($classDescription['properties'] as $property => $constraints) {
160                 if (null !== $constraints) {
161                     foreach ($this->parseNodes($constraints) as $constraint) {
162                         $metadata->addPropertyConstraint($property, $constraint);
163                     }
164                 }
165             }
166         }
167
168         if (isset($classDescription['getters']) && is_array($classDescription['getters'])) {
169             foreach ($classDescription['getters'] as $getter => $constraints) {
170                 if (null !== $constraints) {
171                     foreach ($this->parseNodes($constraints) as $constraint) {
172                         $metadata->addGetterConstraint($getter, $constraint);
173                     }
174                 }
175             }
176         }
177     }
178 }