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