comparison vendor/symfony/dependency-injection/Dumper/XmlDumper.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 7a779792577d
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
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\DependencyInjection\Dumper;
13
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15 use Symfony\Component\DependencyInjection\Parameter;
16 use Symfony\Component\DependencyInjection\Reference;
17 use Symfony\Component\DependencyInjection\Definition;
18 use Symfony\Component\DependencyInjection\Alias;
19 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
20 use Symfony\Component\ExpressionLanguage\Expression;
21
22 /**
23 * XmlDumper dumps a service container as an XML string.
24 *
25 * @author Fabien Potencier <fabien@symfony.com>
26 * @author Martin HasoĊˆ <martin.hason@gmail.com>
27 */
28 class XmlDumper extends Dumper
29 {
30 /**
31 * @var \DOMDocument
32 */
33 private $document;
34
35 /**
36 * Dumps the service container as an XML string.
37 *
38 * @param array $options An array of options
39 *
40 * @return string An xml string representing of the service container
41 */
42 public function dump(array $options = array())
43 {
44 $this->document = new \DOMDocument('1.0', 'utf-8');
45 $this->document->formatOutput = true;
46
47 $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container');
48 $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
49 $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd');
50
51 $this->addParameters($container);
52 $this->addServices($container);
53
54 $this->document->appendChild($container);
55 $xml = $this->document->saveXML();
56 $this->document = null;
57
58 return $this->container->resolveEnvPlaceholders($xml);
59 }
60
61 /**
62 * Adds parameters.
63 *
64 * @param \DOMElement $parent
65 */
66 private function addParameters(\DOMElement $parent)
67 {
68 $data = $this->container->getParameterBag()->all();
69 if (!$data) {
70 return;
71 }
72
73 if ($this->container->isFrozen()) {
74 $data = $this->escape($data);
75 }
76
77 $parameters = $this->document->createElement('parameters');
78 $parent->appendChild($parameters);
79 $this->convertParameters($data, 'parameter', $parameters);
80 }
81
82 /**
83 * Adds method calls.
84 *
85 * @param array $methodcalls
86 * @param \DOMElement $parent
87 */
88 private function addMethodCalls(array $methodcalls, \DOMElement $parent)
89 {
90 foreach ($methodcalls as $methodcall) {
91 $call = $this->document->createElement('call');
92 $call->setAttribute('method', $methodcall[0]);
93 if (count($methodcall[1])) {
94 $this->convertParameters($methodcall[1], 'argument', $call);
95 }
96 $parent->appendChild($call);
97 }
98 }
99
100 /**
101 * Adds a service.
102 *
103 * @param Definition $definition
104 * @param string $id
105 * @param \DOMElement $parent
106 */
107 private function addService($definition, $id, \DOMElement $parent)
108 {
109 $service = $this->document->createElement('service');
110 if (null !== $id) {
111 $service->setAttribute('id', $id);
112 }
113 if ($class = $definition->getClass()) {
114 if ('\\' === substr($class, 0, 1)) {
115 $class = substr($class, 1);
116 }
117
118 $service->setAttribute('class', $class);
119 }
120 if (!$definition->isShared()) {
121 $service->setAttribute('shared', 'false');
122 }
123 if (!$definition->isPublic()) {
124 $service->setAttribute('public', 'false');
125 }
126 if ($definition->isSynthetic()) {
127 $service->setAttribute('synthetic', 'true');
128 }
129 if ($definition->isLazy()) {
130 $service->setAttribute('lazy', 'true');
131 }
132 if (null !== $decorated = $definition->getDecoratedService()) {
133 list($decorated, $renamedId, $priority) = $decorated;
134 $service->setAttribute('decorates', $decorated);
135 if (null !== $renamedId) {
136 $service->setAttribute('decoration-inner-name', $renamedId);
137 }
138 if (0 !== $priority) {
139 $service->setAttribute('decoration-priority', $priority);
140 }
141 }
142
143 foreach ($definition->getTags() as $name => $tags) {
144 foreach ($tags as $attributes) {
145 $tag = $this->document->createElement('tag');
146 $tag->setAttribute('name', $name);
147 foreach ($attributes as $key => $value) {
148 $tag->setAttribute($key, $value);
149 }
150 $service->appendChild($tag);
151 }
152 }
153
154 if ($definition->getFile()) {
155 $file = $this->document->createElement('file');
156 $file->appendChild($this->document->createTextNode($definition->getFile()));
157 $service->appendChild($file);
158 }
159
160 if ($parameters = $definition->getArguments()) {
161 $this->convertParameters($parameters, 'argument', $service);
162 }
163
164 if ($parameters = $definition->getProperties()) {
165 $this->convertParameters($parameters, 'property', $service, 'name');
166 }
167
168 $this->addMethodCalls($definition->getMethodCalls(), $service);
169
170 if ($callable = $definition->getFactory()) {
171 $factory = $this->document->createElement('factory');
172
173 if (is_array($callable) && $callable[0] instanceof Definition) {
174 $this->addService($callable[0], null, $factory);
175 $factory->setAttribute('method', $callable[1]);
176 } elseif (is_array($callable)) {
177 $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
178 $factory->setAttribute('method', $callable[1]);
179 } else {
180 $factory->setAttribute('function', $callable);
181 }
182 $service->appendChild($factory);
183 }
184
185 if ($definition->isDeprecated()) {
186 $deprecated = $this->document->createElement('deprecated');
187 $deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%')));
188
189 $service->appendChild($deprecated);
190 }
191
192 if ($definition->isAutowired()) {
193 $service->setAttribute('autowire', 'true');
194 }
195
196 foreach ($definition->getAutowiringTypes() as $autowiringTypeValue) {
197 $autowiringType = $this->document->createElement('autowiring-type');
198 $autowiringType->appendChild($this->document->createTextNode($autowiringTypeValue));
199
200 $service->appendChild($autowiringType);
201 }
202
203 if ($callable = $definition->getConfigurator()) {
204 $configurator = $this->document->createElement('configurator');
205
206 if (is_array($callable) && $callable[0] instanceof Definition) {
207 $this->addService($callable[0], null, $configurator);
208 $configurator->setAttribute('method', $callable[1]);
209 } elseif (is_array($callable)) {
210 $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
211 $configurator->setAttribute('method', $callable[1]);
212 } else {
213 $configurator->setAttribute('function', $callable);
214 }
215 $service->appendChild($configurator);
216 }
217
218 $parent->appendChild($service);
219 }
220
221 /**
222 * Adds a service alias.
223 *
224 * @param string $alias
225 * @param Alias $id
226 * @param \DOMElement $parent
227 */
228 private function addServiceAlias($alias, Alias $id, \DOMElement $parent)
229 {
230 $service = $this->document->createElement('service');
231 $service->setAttribute('id', $alias);
232 $service->setAttribute('alias', $id);
233 if (!$id->isPublic()) {
234 $service->setAttribute('public', 'false');
235 }
236 $parent->appendChild($service);
237 }
238
239 /**
240 * Adds services.
241 *
242 * @param \DOMElement $parent
243 */
244 private function addServices(\DOMElement $parent)
245 {
246 $definitions = $this->container->getDefinitions();
247 if (!$definitions) {
248 return;
249 }
250
251 $services = $this->document->createElement('services');
252 foreach ($definitions as $id => $definition) {
253 $this->addService($definition, $id, $services);
254 }
255
256 $aliases = $this->container->getAliases();
257 foreach ($aliases as $alias => $id) {
258 while (isset($aliases[(string) $id])) {
259 $id = $aliases[(string) $id];
260 }
261 $this->addServiceAlias($alias, $id, $services);
262 }
263 $parent->appendChild($services);
264 }
265
266 /**
267 * Converts parameters.
268 *
269 * @param array $parameters
270 * @param string $type
271 * @param \DOMElement $parent
272 * @param string $keyAttribute
273 */
274 private function convertParameters(array $parameters, $type, \DOMElement $parent, $keyAttribute = 'key')
275 {
276 $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1);
277 foreach ($parameters as $key => $value) {
278 $element = $this->document->createElement($type);
279 if ($withKeys) {
280 $element->setAttribute($keyAttribute, $key);
281 }
282
283 if (is_array($value)) {
284 $element->setAttribute('type', 'collection');
285 $this->convertParameters($value, $type, $element, 'key');
286 } elseif ($value instanceof Reference) {
287 $element->setAttribute('type', 'service');
288 $element->setAttribute('id', (string) $value);
289 $behaviour = $value->getInvalidBehavior();
290 if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) {
291 $element->setAttribute('on-invalid', 'null');
292 } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
293 $element->setAttribute('on-invalid', 'ignore');
294 }
295 } elseif ($value instanceof Definition) {
296 $element->setAttribute('type', 'service');
297 $this->addService($value, null, $element);
298 } elseif ($value instanceof Expression) {
299 $element->setAttribute('type', 'expression');
300 $text = $this->document->createTextNode(self::phpToXml((string) $value));
301 $element->appendChild($text);
302 } else {
303 if (in_array($value, array('null', 'true', 'false'), true)) {
304 $element->setAttribute('type', 'string');
305 }
306 $text = $this->document->createTextNode(self::phpToXml($value));
307 $element->appendChild($text);
308 }
309 $parent->appendChild($element);
310 }
311 }
312
313 /**
314 * Escapes arguments.
315 *
316 * @param array $arguments
317 *
318 * @return array
319 */
320 private function escape(array $arguments)
321 {
322 $args = array();
323 foreach ($arguments as $k => $v) {
324 if (is_array($v)) {
325 $args[$k] = $this->escape($v);
326 } elseif (is_string($v)) {
327 $args[$k] = str_replace('%', '%%', $v);
328 } else {
329 $args[$k] = $v;
330 }
331 }
332
333 return $args;
334 }
335
336 /**
337 * Converts php types to xml types.
338 *
339 * @param mixed $value Value to convert
340 *
341 * @return string
342 *
343 * @throws RuntimeException When trying to dump object or resource
344 */
345 public static function phpToXml($value)
346 {
347 switch (true) {
348 case null === $value:
349 return 'null';
350 case true === $value:
351 return 'true';
352 case false === $value:
353 return 'false';
354 case $value instanceof Parameter:
355 return '%'.$value.'%';
356 case is_object($value) || is_resource($value):
357 throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
358 default:
359 return (string) $value;
360 }
361 }
362 }