[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
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\ContainerBuilder; 15 use Symfony\Component\DependencyInjection\ContainerInterface; 16 use Symfony\Component\DependencyInjection\Definition; 17 use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; 18 use Symfony\Component\DependencyInjection\Parameter; 19 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; 20 use Symfony\Component\DependencyInjection\Reference; 21 use Symfony\Component\DependencyInjection\Scope; 22 23 /** 24 * GraphvizDumper dumps a service container as a graphviz file. 25 * 26 * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): 27 * 28 * dot -Tpng container.dot > foo.png 29 * 30 * @author Fabien Potencier <fabien@symfony.com> 31 */ 32 class GraphvizDumper extends Dumper 33 { 34 private $nodes; 35 private $edges; 36 private $options = array( 37 'graph' => array('ratio' => 'compress'), 38 'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'), 39 'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5), 40 'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'), 41 'node.definition' => array('fillcolor' => '#eeeeee'), 42 'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'), 43 ); 44 45 /** 46 * Dumps the service container as a graphviz graph. 47 * 48 * Available options: 49 * 50 * * graph: The default options for the whole graph 51 * * node: The default options for nodes 52 * * edge: The default options for edges 53 * * node.instance: The default options for services that are defined directly by object instances 54 * * node.definition: The default options for services that are defined via service definition instances 55 * * node.missing: The default options for missing services 56 * 57 * @return string The dot representation of the service container 58 */ 59 public function dump(array $options = array()) 60 { 61 foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) { 62 if (isset($options[$key])) { 63 $this->options[$key] = array_merge($this->options[$key], $options[$key]); 64 } 65 } 66 67 $this->nodes = $this->findNodes(); 68 69 $this->edges = array(); 70 foreach ($this->container->getDefinitions() as $id => $definition) { 71 $this->edges[$id] = array_merge( 72 $this->findEdges($id, $definition->getArguments(), true, ''), 73 $this->findEdges($id, $definition->getProperties(), false, '') 74 ); 75 76 foreach ($definition->getMethodCalls() as $call) { 77 $this->edges[$id] = array_merge( 78 $this->edges[$id], 79 $this->findEdges($id, $call[1], false, $call[0].'()') 80 ); 81 } 82 } 83 84 return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot(); 85 } 86 87 /** 88 * Returns all nodes. 89 * 90 * @return string A string representation of all nodes 91 */ 92 private function addNodes() 93 { 94 $code = ''; 95 foreach ($this->nodes as $id => $node) { 96 $aliases = $this->getAliases($id); 97 98 $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); 99 } 100 101 return $code; 102 } 103 104 /** 105 * Returns all edges. 106 * 107 * @return string A string representation of all edges 108 */ 109 private function addEdges() 110 { 111 $code = ''; 112 foreach ($this->edges as $id => $edges) { 113 foreach ($edges as $edge) { 114 $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed'); 115 } 116 } 117 118 return $code; 119 } 120 121 /** 122 * Finds all edges belonging to a specific service id. 123 * 124 * @param string $id The service id used to find edges 125 * @param array $arguments An array of arguments 126 * @param bool $required 127 * @param string $name 128 * 129 * @return array An array of edges 130 */ 131 private function findEdges($id, array $arguments, $required, $name) 132 { 133 $edges = array(); 134 foreach ($arguments as $argument) { 135 if ($argument instanceof Parameter) { 136 $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; 137 } elseif (\is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { 138 $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; 139 } 140 141 if ($argument instanceof Reference) { 142 if (!$this->container->has((string) $argument)) { 143 $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']); 144 } 145 146 $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument); 147 } elseif (\is_array($argument)) { 148 $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name)); 149 } 150 } 151 152 return $edges; 153 } 154 155 /** 156 * Finds all nodes. 157 * 158 * @return array An array of all nodes 159 */ 160 private function findNodes() 161 { 162 $nodes = array(); 163 164 $container = $this->cloneContainer(); 165 166 foreach ($container->getDefinitions() as $id => $definition) { 167 $class = $definition->getClass(); 168 169 if ('\\' === substr($class, 0, 1)) { 170 $class = substr($class, 1); 171 } 172 173 try { 174 $class = $this->container->getParameterBag()->resolveValue($class); 175 } catch (ParameterNotFoundException $e) { 176 } 177 178 $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], array('style' => $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope(false) ? 'filled' : 'dotted'))); 179 $container->setDefinition($id, new Definition('stdClass')); 180 } 181 182 foreach ($container->getServiceIds() as $id) { 183 $service = $container->get($id); 184 185 if (array_key_exists($id, $container->getAliases())) { 186 continue; 187 } 188 189 if (!$container->hasDefinition($id)) { 190 $class = ('service_container' === $id) ? \get_class($this->container) : \get_class($service); 191 $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']); 192 } 193 } 194 195 return $nodes; 196 } 197 198 private function cloneContainer() 199 { 200 $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); 201 202 $container = new ContainerBuilder($parameterBag); 203 $container->setDefinitions($this->container->getDefinitions()); 204 $container->setAliases($this->container->getAliases()); 205 $container->setResources($this->container->getResources()); 206 foreach ($this->container->getScopes(false) as $scope => $parentScope) { 207 $container->addScope(new Scope($scope, $parentScope)); 208 } 209 foreach ($this->container->getExtensions() as $extension) { 210 $container->registerExtension($extension); 211 } 212 213 return $container; 214 } 215 216 /** 217 * Returns the start dot. 218 * 219 * @return string The string representation of a start dot 220 */ 221 private function startDot() 222 { 223 return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", 224 $this->addOptions($this->options['graph']), 225 $this->addOptions($this->options['node']), 226 $this->addOptions($this->options['edge']) 227 ); 228 } 229 230 /** 231 * Returns the end dot. 232 * 233 * @return string 234 */ 235 private function endDot() 236 { 237 return "}\n"; 238 } 239 240 /** 241 * Adds attributes. 242 * 243 * @param array $attributes An array of attributes 244 * 245 * @return string A comma separated list of attributes 246 */ 247 private function addAttributes(array $attributes) 248 { 249 $code = array(); 250 foreach ($attributes as $k => $v) { 251 $code[] = sprintf('%s="%s"', $k, $v); 252 } 253 254 return $code ? ', '.implode(', ', $code) : ''; 255 } 256 257 /** 258 * Adds options. 259 * 260 * @param array $options An array of options 261 * 262 * @return string A space separated list of options 263 */ 264 private function addOptions(array $options) 265 { 266 $code = array(); 267 foreach ($options as $k => $v) { 268 $code[] = sprintf('%s="%s"', $k, $v); 269 } 270 271 return implode(' ', $code); 272 } 273 274 /** 275 * Dotizes an identifier. 276 * 277 * @param string $id The identifier to dotize 278 * 279 * @return string A dotized string 280 */ 281 private function dotize($id) 282 { 283 return strtolower(preg_replace('/\W/i', '_', $id)); 284 } 285 286 /** 287 * Compiles an array of aliases for a specified service id. 288 * 289 * @param string $id A service id 290 * 291 * @return array An array of aliases 292 */ 293 private function getAliases($id) 294 { 295 $aliases = array(); 296 foreach ($this->container->getAliases() as $alias => $origin) { 297 if ($id == $origin) { 298 $aliases[] = $alias; 299 } 300 } 301 302 return $aliases; 303 } 304 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |