Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

GraphvizDumper.php

Zuletzt modifiziert: 01.05.2026, 11:27 - Dateigröße: 10.44 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Symfony\Component\DependencyInjection\Dumper;
 013   
 014  use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
 015  use Symfony\Component\DependencyInjection\ContainerBuilder;
 016  use Symfony\Component\DependencyInjection\Definition;
 017  use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
 018  use Symfony\Component\DependencyInjection\Parameter;
 019  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 020  use Symfony\Component\DependencyInjection\Reference;
 021   
 022  /**
 023   * GraphvizDumper dumps a service container as a graphviz file.
 024   *
 025   * You can convert the generated dot file with the dot utility (http://www.graphviz.org/):
 026   *
 027   *   dot -Tpng container.dot > foo.png
 028   *
 029   * @author Fabien Potencier <fabien@symfony.com>
 030   */
 031  class GraphvizDumper extends Dumper
 032  {
 033      private $nodes;
 034      private $edges;
 035      // All values should be strings
 036      private $options = [
 037              'graph' => ['ratio' => 'compress'],
 038              'node' => ['fontsize' => '11', 'fontname' => 'Arial', 'shape' => 'record'],
 039              'edge' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => '0.5'],
 040              'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'],
 041              'node.definition' => ['fillcolor' => '#eeeeee'],
 042              'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled'],
 043          ];
 044   
 045      /**
 046       * Dumps the service container as a graphviz graph.
 047       *
 048       * Available options:
 049       *
 050       *  * graph: The default options for the whole graph
 051       *  * node: The default options for nodes
 052       *  * edge: The default options for edges
 053       *  * node.instance: The default options for services that are defined directly by object instances
 054       *  * node.definition: The default options for services that are defined via service definition instances
 055       *  * node.missing: The default options for missing services
 056       *
 057       * @return string The dot representation of the service container
 058       */
 059      public function dump(array $options = [])
 060      {
 061          foreach (['graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing'] as $key) {
 062              if (isset($options[$key])) {
 063                  $this->options[$key] = array_merge($this->options[$key], $options[$key]);
 064              }
 065          }
 066   
 067          $this->nodes = $this->findNodes();
 068   
 069          $this->edges = [];
 070          foreach ($this->container->getDefinitions() as $id => $definition) {
 071              $this->edges[$id] = array_merge(
 072                  $this->findEdges($id, $definition->getArguments(), true, ''),
 073                  $this->findEdges($id, $definition->getProperties(), false, '')
 074              );
 075   
 076              foreach ($definition->getMethodCalls() as $call) {
 077                  $this->edges[$id] = array_merge(
 078                      $this->edges[$id],
 079                      $this->findEdges($id, $call[1], false, $call[0].'()')
 080                  );
 081              }
 082          }
 083   
 084          return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__');
 085      }
 086   
 087      /**
 088       * Returns all nodes.
 089       *
 090       * @return string A string representation of all nodes
 091       */
 092      private function addNodes()
 093      {
 094          $code = '';
 095          foreach ($this->nodes as $id => $node) {
 096              $aliases = $this->getAliases($id);
 097   
 098              $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']));
 099          }
 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\"%s];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed', $edge['lazy'] ? ' color="#9999ff"' : '');
 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, $lazy = false)
 132      {
 133          $edges = [];
 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                  $lazyEdge = $lazy;
 143   
 144                  if (!$this->container->has((string) $argument)) {
 145                      $this->nodes[(string) $argument] = ['name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']];
 146                  } elseif ('service_container' !== (string) $argument) {
 147                      $lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy();
 148                  }
 149   
 150                  $edges[] = ['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge];
 151              } elseif ($argument instanceof ArgumentInterface) {
 152                  $edges = array_merge($edges, $this->findEdges($id, $argument->getValues(), $required, $name, true));
 153              } elseif ($argument instanceof Definition) {
 154                  $edges = array_merge($edges,
 155                      $this->findEdges($id, $argument->getArguments(), $required, ''),
 156                      $this->findEdges($id, $argument->getProperties(), false, '')
 157                  );
 158                  foreach ($argument->getMethodCalls() as $call) {
 159                      $edges = array_merge($edges, $this->findEdges($id, $call[1], false, $call[0].'()'));
 160                  }
 161              } elseif (\is_array($argument)) {
 162                  $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name, $lazy));
 163              }
 164          }
 165   
 166          return $edges;
 167      }
 168   
 169      /**
 170       * Finds all nodes.
 171       *
 172       * @return array An array of all nodes
 173       */
 174      private function findNodes()
 175      {
 176          $nodes = [];
 177   
 178          $container = $this->cloneContainer();
 179   
 180          foreach ($container->getDefinitions() as $id => $definition) {
 181              $class = $definition->getClass();
 182   
 183              if ('\\' === substr($class, 0, 1)) {
 184                  $class = substr($class, 1);
 185              }
 186   
 187              try {
 188                  $class = $this->container->getParameterBag()->resolveValue($class);
 189              } catch (ParameterNotFoundException $e) {
 190              }
 191   
 192              $nodes[$id] = ['class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], ['style' => $definition->isShared() ? 'filled' : 'dotted'])];
 193              $container->setDefinition($id, new Definition('stdClass'));
 194          }
 195   
 196          foreach ($container->getServiceIds() as $id) {
 197              if (\array_key_exists($id, $container->getAliases())) {
 198                  continue;
 199              }
 200   
 201              if (!$container->hasDefinition($id)) {
 202                  $nodes[$id] = ['class' => str_replace('\\', '\\\\', \get_class($container->get($id))), 'attributes' => $this->options['node.instance']];
 203              }
 204          }
 205   
 206          return $nodes;
 207      }
 208   
 209      private function cloneContainer()
 210      {
 211          $parameterBag = new ParameterBag($this->container->getParameterBag()->all());
 212   
 213          $container = new ContainerBuilder($parameterBag);
 214          $container->setDefinitions($this->container->getDefinitions());
 215          $container->setAliases($this->container->getAliases());
 216          $container->setResources($this->container->getResources());
 217          foreach ($this->container->getExtensions() as $extension) {
 218              $container->registerExtension($extension);
 219          }
 220   
 221          return $container;
 222      }
 223   
 224      /**
 225       * Returns the start dot.
 226       *
 227       * @return string The string representation of a start dot
 228       */
 229      private function startDot()
 230      {
 231          return sprintf("digraph sc {\n  %s\n  node [%s];\n  edge [%s];\n\n",
 232              $this->addOptions($this->options['graph']),
 233              $this->addOptions($this->options['node']),
 234              $this->addOptions($this->options['edge'])
 235          );
 236      }
 237   
 238      /**
 239       * Returns the end dot.
 240       *
 241       * @return string
 242       */
 243      private function endDot()
 244      {
 245          return "}\n";
 246      }
 247   
 248      /**
 249       * Adds attributes.
 250       *
 251       * @param array $attributes An array of attributes
 252       *
 253       * @return string A comma separated list of attributes
 254       */
 255      private function addAttributes(array $attributes)
 256      {
 257          $code = [];
 258          foreach ($attributes as $k => $v) {
 259              $code[] = sprintf('%s="%s"', $k, $v);
 260          }
 261   
 262          return $code ? ', '.implode(', ', $code) : '';
 263      }
 264   
 265      /**
 266       * Adds options.
 267       *
 268       * @param array $options An array of options
 269       *
 270       * @return string A space separated list of options
 271       */
 272      private function addOptions(array $options)
 273      {
 274          $code = [];
 275          foreach ($options as $k => $v) {
 276              $code[] = sprintf('%s="%s"', $k, $v);
 277          }
 278   
 279          return implode(' ', $code);
 280      }
 281   
 282      /**
 283       * Dotizes an identifier.
 284       *
 285       * @param string $id The identifier to dotize
 286       *
 287       * @return string A dotized string
 288       */
 289      private function dotize($id)
 290      {
 291          return strtolower(preg_replace('/\W/i', '_', $id));
 292      }
 293   
 294      /**
 295       * Compiles an array of aliases for a specified service id.
 296       *
 297       * @param string $id A service id
 298       *
 299       * @return array An array of aliases
 300       */
 301      private function getAliases($id)
 302      {
 303          $aliases = [];
 304          foreach ($this->container->getAliases() as $alias => $origin) {
 305              if ($id == $origin) {
 306                  $aliases[] = $alias;
 307              }
 308          }
 309   
 310          return $aliases;
 311      }
 312  }
 313