8bcdf9f97ef94d6c2af58469a9da99421f217f21
[yaffs-website] / vendor / symfony / validator / Mapping / Loader / XmlFileLoader.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\Config\Util\XmlUtils;
15 use Symfony\Component\Validator\Exception\MappingException;
16 use Symfony\Component\Validator\Mapping\ClassMetadata;
17
18 /**
19  * Loads validation metadata from an XML file.
20  *
21  * @author Bernhard Schussek <bschussek@gmail.com>
22  */
23 class XmlFileLoader extends FileLoader
24 {
25     /**
26      * The XML nodes of the mapping file.
27      *
28      * @var \SimpleXMLElement[]|null
29      */
30     protected $classes;
31
32     /**
33      * {@inheritdoc}
34      */
35     public function loadClassMetadata(ClassMetadata $metadata)
36     {
37         if (null === $this->classes) {
38             // This method may throw an exception. Do not modify the class'
39             // state before it completes
40             $xml = $this->parseFile($this->file);
41
42             $this->classes = array();
43
44             foreach ($xml->namespace as $namespace) {
45                 $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
46             }
47
48             foreach ($xml->class as $class) {
49                 $this->classes[(string) $class['name']] = $class;
50             }
51         }
52
53         if (isset($this->classes[$metadata->getClassName()])) {
54             $classDescription = $this->classes[$metadata->getClassName()];
55
56             $this->loadClassMetadataFromXml($metadata, $classDescription);
57
58             return true;
59         }
60
61         return false;
62     }
63
64     /**
65      * Parses a collection of "constraint" XML nodes.
66      *
67      * @param \SimpleXMLElement $nodes The XML nodes
68      *
69      * @return array The Constraint instances
70      */
71     protected function parseConstraints(\SimpleXMLElement $nodes)
72     {
73         $constraints = array();
74
75         foreach ($nodes as $node) {
76             if (count($node) > 0) {
77                 if (count($node->value) > 0) {
78                     $options = $this->parseValues($node->value);
79                 } elseif (count($node->constraint) > 0) {
80                     $options = $this->parseConstraints($node->constraint);
81                 } elseif (count($node->option) > 0) {
82                     $options = $this->parseOptions($node->option);
83                 } else {
84                     $options = array();
85                 }
86             } elseif (strlen((string) $node) > 0) {
87                 $options = XmlUtils::phpize(trim($node));
88             } else {
89                 $options = null;
90             }
91
92             $constraints[] = $this->newConstraint((string) $node['name'], $options);
93         }
94
95         return $constraints;
96     }
97
98     /**
99      * Parses a collection of "value" XML nodes.
100      *
101      * @param \SimpleXMLElement $nodes The XML nodes
102      *
103      * @return array The values
104      */
105     protected function parseValues(\SimpleXMLElement $nodes)
106     {
107         $values = array();
108
109         foreach ($nodes as $node) {
110             if (count($node) > 0) {
111                 if (count($node->value) > 0) {
112                     $value = $this->parseValues($node->value);
113                 } elseif (count($node->constraint) > 0) {
114                     $value = $this->parseConstraints($node->constraint);
115                 } else {
116                     $value = array();
117                 }
118             } else {
119                 $value = trim($node);
120             }
121
122             if (isset($node['key'])) {
123                 $values[(string) $node['key']] = $value;
124             } else {
125                 $values[] = $value;
126             }
127         }
128
129         return $values;
130     }
131
132     /**
133      * Parses a collection of "option" XML nodes.
134      *
135      * @param \SimpleXMLElement $nodes The XML nodes
136      *
137      * @return array The options
138      */
139     protected function parseOptions(\SimpleXMLElement $nodes)
140     {
141         $options = array();
142
143         foreach ($nodes as $node) {
144             if (count($node) > 0) {
145                 if (count($node->value) > 0) {
146                     $value = $this->parseValues($node->value);
147                 } elseif (count($node->constraint) > 0) {
148                     $value = $this->parseConstraints($node->constraint);
149                 } else {
150                     $value = array();
151                 }
152             } else {
153                 $value = XmlUtils::phpize($node);
154                 if (is_string($value)) {
155                     $value = trim($value);
156                 }
157             }
158
159             $options[(string) $node['name']] = $value;
160         }
161
162         return $options;
163     }
164
165     /**
166      * Loads the XML class descriptions from the given file.
167      *
168      * @param string $path The path of the XML file
169      *
170      * @return \SimpleXMLElement The class descriptions
171      *
172      * @throws MappingException If the file could not be loaded
173      */
174     protected function parseFile($path)
175     {
176         try {
177             $dom = XmlUtils::loadFile($path, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd');
178         } catch (\Exception $e) {
179             throw new MappingException($e->getMessage(), $e->getCode(), $e);
180         }
181
182         return simplexml_import_dom($dom);
183     }
184
185     private function loadClassMetadataFromXml(ClassMetadata $metadata, \SimpleXMLElement $classDescription)
186     {
187         if (count($classDescription->{'group-sequence-provider'}) > 0) {
188             $metadata->setGroupSequenceProvider(true);
189         }
190
191         foreach ($classDescription->{'group-sequence'} as $groupSequence) {
192             if (count($groupSequence->value) > 0) {
193                 $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value));
194             }
195         }
196
197         foreach ($this->parseConstraints($classDescription->constraint) as $constraint) {
198             $metadata->addConstraint($constraint);
199         }
200
201         foreach ($classDescription->property as $property) {
202             foreach ($this->parseConstraints($property->constraint) as $constraint) {
203                 $metadata->addPropertyConstraint((string) $property['name'], $constraint);
204             }
205         }
206
207         foreach ($classDescription->getter as $getter) {
208             foreach ($this->parseConstraints($getter->constraint) as $constraint) {
209                 $metadata->addGetterConstraint((string) $getter['property'], $constraint);
210             }
211         }
212     }
213 }