Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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: 02.04.2025, 15:03 - 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