Security update for Core, with self-updated composer
[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->loadClassesFromXml();
39         }
40
41         if (isset($this->classes[$metadata->getClassName()])) {
42             $classDescription = $this->classes[$metadata->getClassName()];
43
44             $this->loadClassMetadataFromXml($metadata, $classDescription);
45
46             return true;
47         }
48
49         return false;
50     }
51
52     /**
53      * Return the names of the classes mapped in this file.
54      *
55      * @return string[] The classes names
56      */
57     public function getMappedClasses()
58     {
59         if (null === $this->classes) {
60             $this->loadClassesFromXml();
61         }
62
63         return array_keys($this->classes);
64     }
65
66     /**
67      * Parses a collection of "constraint" XML nodes.
68      *
69      * @param \SimpleXMLElement $nodes The XML nodes
70      *
71      * @return array The Constraint instances
72      */
73     protected function parseConstraints(\SimpleXMLElement $nodes)
74     {
75         $constraints = array();
76
77         foreach ($nodes as $node) {
78             if (count($node) > 0) {
79                 if (count($node->value) > 0) {
80                     $options = $this->parseValues($node->value);
81                 } elseif (count($node->constraint) > 0) {
82                     $options = $this->parseConstraints($node->constraint);
83                 } elseif (count($node->option) > 0) {
84                     $options = $this->parseOptions($node->option);
85                 } else {
86                     $options = array();
87                 }
88             } elseif (strlen((string) $node) > 0) {
89                 $options = XmlUtils::phpize(trim($node));
90             } else {
91                 $options = null;
92             }
93
94             $constraints[] = $this->newConstraint((string) $node['name'], $options);
95         }
96
97         return $constraints;
98     }
99
100     /**
101      * Parses a collection of "value" XML nodes.
102      *
103      * @param \SimpleXMLElement $nodes The XML nodes
104      *
105      * @return array The values
106      */
107     protected function parseValues(\SimpleXMLElement $nodes)
108     {
109         $values = array();
110
111         foreach ($nodes as $node) {
112             if (count($node) > 0) {
113                 if (count($node->value) > 0) {
114                     $value = $this->parseValues($node->value);
115                 } elseif (count($node->constraint) > 0) {
116                     $value = $this->parseConstraints($node->constraint);
117                 } else {
118                     $value = array();
119                 }
120             } else {
121                 $value = trim($node);
122             }
123
124             if (isset($node['key'])) {
125                 $values[(string) $node['key']] = $value;
126             } else {
127                 $values[] = $value;
128             }
129         }
130
131         return $values;
132     }
133
134     /**
135      * Parses a collection of "option" XML nodes.
136      *
137      * @param \SimpleXMLElement $nodes The XML nodes
138      *
139      * @return array The options
140      */
141     protected function parseOptions(\SimpleXMLElement $nodes)
142     {
143         $options = array();
144
145         foreach ($nodes as $node) {
146             if (count($node) > 0) {
147                 if (count($node->value) > 0) {
148                     $value = $this->parseValues($node->value);
149                 } elseif (count($node->constraint) > 0) {
150                     $value = $this->parseConstraints($node->constraint);
151                 } else {
152                     $value = array();
153                 }
154             } else {
155                 $value = XmlUtils::phpize($node);
156                 if (is_string($value)) {
157                     $value = trim($value);
158                 }
159             }
160
161             $options[(string) $node['name']] = $value;
162         }
163
164         return $options;
165     }
166
167     /**
168      * Loads the XML class descriptions from the given file.
169      *
170      * @param string $path The path of the XML file
171      *
172      * @return \SimpleXMLElement The class descriptions
173      *
174      * @throws MappingException If the file could not be loaded
175      */
176     protected function parseFile($path)
177     {
178         try {
179             $dom = XmlUtils::loadFile($path, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd');
180         } catch (\Exception $e) {
181             throw new MappingException($e->getMessage(), $e->getCode(), $e);
182         }
183
184         return simplexml_import_dom($dom);
185     }
186
187     private function loadClassesFromXml()
188     {
189         // This method may throw an exception. Do not modify the class'
190         // state before it completes
191         $xml = $this->parseFile($this->file);
192
193         $this->classes = array();
194
195         foreach ($xml->namespace as $namespace) {
196             $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
197         }
198
199         foreach ($xml->class as $class) {
200             $this->classes[(string) $class['name']] = $class;
201         }
202     }
203
204     private function loadClassMetadataFromXml(ClassMetadata $metadata, \SimpleXMLElement $classDescription)
205     {
206         if (count($classDescription->{'group-sequence-provider'}) > 0) {
207             $metadata->setGroupSequenceProvider(true);
208         }
209
210         foreach ($classDescription->{'group-sequence'} as $groupSequence) {
211             if (count($groupSequence->value) > 0) {
212                 $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value));
213             }
214         }
215
216         foreach ($this->parseConstraints($classDescription->constraint) as $constraint) {
217             $metadata->addConstraint($constraint);
218         }
219
220         foreach ($classDescription->property as $property) {
221             foreach ($this->parseConstraints($property->constraint) as $constraint) {
222                 $metadata->addPropertyConstraint((string) $property['name'], $constraint);
223             }
224         }
225
226         foreach ($classDescription->getter as $getter) {
227             foreach ($this->parseConstraints($getter->constraint) as $constraint) {
228                 $metadata->addGetterConstraint((string) $getter['property'], $constraint);
229             }
230         }
231     }
232 }