/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php

https://github.com/jdewit/symfony · PHP · 343 lines · 209 code · 52 blank · 82 comment · 18 complexity · 04c977b72957e24195e87548eab36feb MD5 · raw file

  1. <?php
  2. namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
  3. use Symfony\Component\DependencyInjection\Alias;
  4. use Symfony\Component\DependencyInjection\ContainerBuilder;
  5. use Symfony\Component\DependencyInjection\Definition;
  6. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  7. use Symfony\Component\Routing\Route;
  8. use Symfony\Component\Routing\RouteCollection;
  9. /**
  10. * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
  11. */
  12. class XmlDescriptor extends Descriptor
  13. {
  14. /**
  15. * {@inheritdoc}
  16. */
  17. protected function describeRouteCollection(RouteCollection $routes, array $options = array())
  18. {
  19. $this->writeDocument($this->getRouteCollectionDocument($routes));
  20. }
  21. /**
  22. * {@inheritdoc}
  23. */
  24. protected function describeRoute(Route $route, array $options = array())
  25. {
  26. $this->writeDocument($this->getRouteDocument($route, isset($options['name']) ? $options['name'] : null));
  27. }
  28. /**
  29. * {@inheritdoc}
  30. */
  31. protected function describeContainerParameters(ParameterBag $parameters, array $options = array())
  32. {
  33. $this->writeDocument($this->getContainerParametersDocument($parameters));
  34. }
  35. /**
  36. * {@inheritdoc}
  37. */
  38. protected function describeContainerTags(ContainerBuilder $builder, array $options = array())
  39. {
  40. $this->writeDocument($this->getContainerTagsDocument($builder, isset($options['show_private']) && $options['show_private']));
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. protected function describeContainerService($service, array $options = array())
  46. {
  47. if (!isset($options['id'])) {
  48. throw new \InvalidArgumentException('An "id" option must be provided.');
  49. }
  50. $this->writeDocument($this->getContainerServiceDocument($service, $options['id']));
  51. }
  52. /**
  53. * {@inheritdoc}
  54. */
  55. protected function describeContainerServices(ContainerBuilder $builder, array $options = array())
  56. {
  57. $this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_private']) && $options['show_private']));
  58. }
  59. /**
  60. * {@inheritdoc}
  61. */
  62. protected function describeContainerDefinition(Definition $definition, array $options = array())
  63. {
  64. $this->writeDocument($this->getContainerDefinitionDocument($definition, isset($options['id']) ? $options['id'] : null, isset($options['omit_tags']) && $options['omit_tags']));
  65. }
  66. /**
  67. * {@inheritdoc}
  68. */
  69. protected function describeContainerAlias(Alias $alias, array $options = array())
  70. {
  71. $this->writeDocument($this->getContainerAliasDocument($alias, isset($options['id']) ? $options['id'] : null));
  72. }
  73. /**
  74. * Writes DOM document.
  75. *
  76. * @param \DOMDocument $dom
  77. *
  78. * @return \DOMDocument|string
  79. */
  80. private function writeDocument(\DOMDocument $dom)
  81. {
  82. $dom->formatOutput = true;
  83. $this->write($dom->saveXML());
  84. }
  85. /**
  86. * @param RouteCollection $routes
  87. *
  88. * @return \DOMDocument
  89. */
  90. private function getRouteCollectionDocument(RouteCollection $routes)
  91. {
  92. $dom = new \DOMDocument('1.0', 'UTF-8');
  93. $dom->appendChild($routesXML = $dom->createElement('routes'));
  94. foreach ($routes->all() as $name => $route) {
  95. $routeXML = $this->getRouteDocument($route, $name);
  96. $routesXML->appendChild($routesXML->ownerDocument->importNode($routeXML->childNodes->item(0), true));
  97. }
  98. return $dom;
  99. }
  100. /**
  101. * @param Route $route
  102. * @param string|null $name
  103. *
  104. * @return \DOMDocument
  105. */
  106. private function getRouteDocument(Route $route, $name = null)
  107. {
  108. $dom = new \DOMDocument('1.0', 'UTF-8');
  109. $dom->appendChild($routeXML = $dom->createElement('route'));
  110. if ($name) {
  111. $routeXML->setAttribute('name', $name);
  112. }
  113. $routeXML->setAttribute('class', get_class($route));
  114. $routeXML->appendChild($pathXML = $dom->createElement('path'));
  115. $pathXML->setAttribute('regex', $route->compile()->getRegex());
  116. $pathXML->appendChild(new \DOMText($route->getPath()));
  117. if ('' !== $route->getHost()) {
  118. $routeXML->appendChild($hostXML = $dom->createElement('host'));
  119. $hostXML->setAttribute('regex', $route->compile()->getHostRegex());
  120. $hostXML->appendChild(new \DOMText($route->getHost()));
  121. }
  122. foreach ($route->getSchemes() as $scheme) {
  123. $routeXML->appendChild($schemeXML = $dom->createElement('scheme'));
  124. $schemeXML->appendChild(new \DOMText($scheme));
  125. }
  126. foreach ($route->getMethods() as $method) {
  127. $routeXML->appendChild($methodXML = $dom->createElement('method'));
  128. $methodXML->appendChild(new \DOMText($method));
  129. }
  130. if (count($route->getDefaults())) {
  131. $routeXML->appendChild($defaultsXML = $dom->createElement('defaults'));
  132. foreach ($route->getDefaults() as $attribute => $value) {
  133. $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
  134. $defaultXML->setAttribute('key', $attribute);
  135. $defaultXML->appendChild(new \DOMText($this->formatValue($value)));
  136. }
  137. }
  138. $requirements = $route->getRequirements();
  139. unset($requirements['_scheme'], $requirements['_method']);
  140. if (count($requirements)) {
  141. $routeXML->appendChild($requirementsXML = $dom->createElement('requirements'));
  142. foreach ($requirements as $attribute => $pattern) {
  143. $requirementsXML->appendChild($requirementXML = $dom->createElement('requirement'));
  144. $requirementXML->setAttribute('key', $attribute);
  145. $requirementXML->appendChild(new \DOMText($pattern));
  146. }
  147. }
  148. if (count($route->getOptions())) {
  149. $routeXML->appendChild($optionsXML = $dom->createElement('options'));
  150. foreach ($route->getOptions() as $name => $value) {
  151. $optionsXML->appendChild($optionXML = $dom->createElement('option'));
  152. $optionXML->setAttribute('key', $name);
  153. $optionXML->appendChild(new \DOMText($this->formatValue($value)));
  154. }
  155. }
  156. return $dom;
  157. }
  158. /**
  159. * @param ParameterBag $parameters
  160. *
  161. * @return \DOMDocument
  162. */
  163. private function getContainerParametersDocument(ParameterBag $parameters)
  164. {
  165. $dom = new \DOMDocument('1.0', 'UTF-8');
  166. $dom->appendChild($parametersXML = $dom->createElement('parameters'));
  167. foreach ($this->sortParameters($parameters) as $key => $value) {
  168. $parametersXML->appendChild($parameterXML = $dom->createElement('parameter'));
  169. $parameterXML->setAttribute('key', $key);
  170. $parameterXML->appendChild(new \DOMText($this->formatParameter($value)));
  171. }
  172. return $dom;
  173. }
  174. /**
  175. * @param ContainerBuilder $builder
  176. * @param boolean $showPrivate
  177. *
  178. * @return \DOMDocument
  179. */
  180. private function getContainerTagsDocument(ContainerBuilder $builder, $showPrivate = false)
  181. {
  182. $dom = new \DOMDocument('1.0', 'UTF-8');
  183. $dom->appendChild($containerXML = $dom->createElement('container'));
  184. foreach ($this->findDefinitionsByTag($builder, $showPrivate) as $tag => $definitions) {
  185. $containerXML->appendChild($tagXML = $dom->createElement('tag'));
  186. $tagXML->setAttribute('name', $tag);
  187. foreach ($definitions as $serviceId => $definition) {
  188. $definitionXML = $this->getContainerDefinitionDocument($definition, $serviceId, true);
  189. $tagXML->appendChild($dom->importNode($definitionXML->childNodes->item(0), true));
  190. }
  191. }
  192. return $dom;
  193. }
  194. /**
  195. * @param mixed $service
  196. * @param string $id
  197. *
  198. * @return \DOMDocument
  199. */
  200. private function getContainerServiceDocument($service, $id)
  201. {
  202. $dom = new \DOMDocument('1.0', 'UTF-8');
  203. if ($service instanceof Alias) {
  204. $dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), true));
  205. } elseif ($service instanceof Definition) {
  206. $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id)->childNodes->item(0), true));
  207. } else {
  208. $dom->appendChild($serviceXML = $dom->createElement('service'));
  209. $serviceXML->setAttribute('id', $id);
  210. $serviceXML->setAttribute('class', get_class($service));
  211. }
  212. return $dom;
  213. }
  214. /**
  215. * @param ContainerBuilder $builder
  216. * @param string|null $tag
  217. * @param boolean $showPrivate
  218. *
  219. * @return \DOMDocument
  220. */
  221. private function getContainerServicesDocument(ContainerBuilder $builder, $tag = null, $showPrivate = false)
  222. {
  223. $dom = new \DOMDocument('1.0', 'UTF-8');
  224. $dom->appendChild($containerXML = $dom->createElement('container'));
  225. $serviceIds = $tag ? array_keys($builder->findTaggedServiceIds($tag)) : $builder->getServiceIds();
  226. foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
  227. $service = $this->resolveServiceDefinition($builder, $serviceId);
  228. if ($service instanceof Definition && !($showPrivate || $service->isPublic())) {
  229. continue;
  230. }
  231. $serviceXML = $this->getContainerServiceDocument($service, $serviceId);
  232. $containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), true));
  233. }
  234. return $dom;
  235. }
  236. /**
  237. * @param Definition $definition
  238. * @param string|null $id
  239. * @param boolean $omitTags
  240. *
  241. * @return \DOMDocument
  242. */
  243. private function getContainerDefinitionDocument(Definition $definition, $id = null, $omitTags = false)
  244. {
  245. $dom = new \DOMDocument('1.0', 'UTF-8');
  246. $dom->appendChild($serviceXML = $dom->createElement('definition'));
  247. if ($id) {
  248. $serviceXML->setAttribute('id', $id);
  249. }
  250. $serviceXML->setAttribute('class', $definition->getClass());
  251. $serviceXML->setAttribute('scope', $definition->getScope());
  252. $serviceXML->setAttribute('public', $definition->isPublic() ? 'true' : 'false');
  253. $serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false');
  254. $serviceXML->setAttribute('file', $definition->getFile());
  255. if (!$omitTags) {
  256. $tags = $definition->getTags();
  257. if (count($tags) > 0) {
  258. $serviceXML->appendChild($tagsXML = $dom->createElement('tags'));
  259. foreach ($tags as $tagName => $tagData) {
  260. foreach ($tagData as $parameters) {
  261. $tagsXML->appendChild($tagXML = $dom->createElement('tag'));
  262. $tagXML->setAttribute('name', $tagName);
  263. foreach ($parameters as $name => $value) {
  264. $tagXML->appendChild($parameterXML = $dom->createElement('parameter'));
  265. $parameterXML->setAttribute('name', $name);
  266. $parameterXML->textContent = $value;
  267. }
  268. }
  269. }
  270. }
  271. }
  272. return $dom;
  273. }
  274. /**
  275. * @param Alias $alias
  276. * @param string|null $id
  277. *
  278. * @return \DOMDocument
  279. */
  280. private function getContainerAliasDocument(Alias $alias, $id = null)
  281. {
  282. $dom = new \DOMDocument('1.0', 'UTF-8');
  283. $dom->appendChild($aliasXML = $dom->createElement('alias'));
  284. if ($id) {
  285. $aliasXML->setAttribute('id', $id);
  286. }
  287. $aliasXML->setAttribute('service', (string) $alias);
  288. $aliasXML->setAttribute('public', $alias->isPublic() ? 'true' : 'false');
  289. return $dom;
  290. }
  291. }