Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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: 09.10.2024, 12:56 - Dateigröße: 9.96 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\Definition;
015  use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
016  use Symfony\Component\DependencyInjection\Reference;
017  use Symfony\Component\DependencyInjection\Parameter;
018  use Symfony\Component\DependencyInjection\ContainerInterface;
019  use Symfony\Component\DependencyInjection\ContainerBuilder;
020  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
021  use Symfony\Component\DependencyInjection\Scope;
022   
023  /**
024   * GraphvizDumper dumps a service container as a graphviz file.
025   *
026   * You can convert the generated dot file with the dot utility (http://www.graphviz.org/):
027   *
028   *   dot -Tpng container.dot > foo.png
029   *
030   * @author Fabien Potencier <fabien@symfony.com>
031   */
032  class GraphvizDumper extends Dumper
033  {
034      private $nodes;
035      private $edges;
036      private $options = array(
037              'graph' => array('ratio' => 'compress'),
038              'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'),
039              'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5),
040              'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'),
041              'node.definition' => array('fillcolor' => '#eeeeee'),
042              'node.missing' => array('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       * @param array $options An array of options
058       *
059       * @return string The dot representation of the service container
060       */
061      public function dump(array $options = array())
062      {
063          foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) {
064              if (isset($options[$key])) {
065                  $this->options[$key] = array_merge($this->options[$key], $options[$key]);
066              }
067          }
068   
069          $this->nodes = $this->findNodes();
070   
071          $this->edges = array();
072          foreach ($this->container->getDefinitions() as $id => $definition) {
073              $this->edges[$id] = array_merge(
074                  $this->findEdges($id, $definition->getArguments(), true, ''),
075                  $this->findEdges($id, $definition->getProperties(), false, '')
076              );
077   
078              foreach ($definition->getMethodCalls() as $call) {
079                  $this->edges[$id] = array_merge(
080                      $this->edges[$id],
081                      $this->findEdges($id, $call[1], false, $call[0].'()')
082                  );
083              }
084          }
085   
086          return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot();
087      }
088   
089      /**
090       * Returns all nodes.
091       *
092       * @return string A string representation of all nodes
093       */
094      private function addNodes()
095      {
096          $code = '';
097          foreach ($this->nodes as $id => $node) {
098              $aliases = $this->getAliases($id);
099   
100              $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']));
101          }
102   
103          return $code;
104      }
105   
106      /**
107       * Returns all edges.
108       *
109       * @return string A string representation of all edges
110       */
111      private function addEdges()
112      {
113          $code = '';
114          foreach ($this->edges as $id => $edges) {
115              foreach ($edges as $edge) {
116                  $code .= sprintf("  node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed');
117              }
118          }
119   
120          return $code;
121      }
122   
123      /**
124       * Finds all edges belonging to a specific service id.
125       *
126       * @param string $id        The service id used to find edges
127       * @param array  $arguments An array of arguments
128       * @param bool   $required
129       * @param string $name
130       *
131       * @return array An array of edges
132       */
133      private function findEdges($id, array $arguments, $required, $name)
134      {
135          $edges = array();
136          foreach ($arguments as $argument) {
137              if ($argument instanceof Parameter) {
138                  $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null;
139              } elseif (is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) {
140                  $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null;
141              }
142   
143              if ($argument instanceof Reference) {
144                  if (!$this->container->has((string) $argument)) {
145                      $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']);
146                  }
147   
148                  $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument);
149              } elseif (is_array($argument)) {
150                  $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name));
151              }
152          }
153   
154          return $edges;
155      }
156   
157      /**
158       * Finds all nodes.
159       *
160       * @return array An array of all nodes
161       */
162      private function findNodes()
163      {
164          $nodes = array();
165   
166          $container = $this->cloneContainer();
167   
168          foreach ($container->getDefinitions() as $id => $definition) {
169              $class = $definition->getClass();
170   
171              if ('\\' === substr($class, 0, 1)) {
172                  $class = substr($class, 1);
173              }
174   
175              try {
176                  $class = $this->container->getParameterBag()->resolveValue($class);
177              } catch (ParameterNotFoundException $e) {
178              }
179   
180              $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')));
181              $container->setDefinition($id, new Definition('stdClass'));
182          }
183   
184          foreach ($container->getServiceIds() as $id) {
185              $service = $container->get($id);
186   
187              if (array_key_exists($id, $container->getAliases())) {
188                  continue;
189              }
190   
191              if (!$container->hasDefinition($id)) {
192                  $class = ('service_container' === $id) ? get_class($this->container) : get_class($service);
193                  $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']);
194              }
195          }
196   
197          return $nodes;
198      }
199   
200      private function cloneContainer()
201      {
202          $parameterBag = new ParameterBag($this->container->getParameterBag()->all());
203   
204          $container = new ContainerBuilder($parameterBag);
205          $container->setDefinitions($this->container->getDefinitions());
206          $container->setAliases($this->container->getAliases());
207          $container->setResources($this->container->getResources());
208          foreach ($this->container->getScopes(false) as $scope => $parentScope) {
209              $container->addScope(new Scope($scope, $parentScope));
210          }
211          foreach ($this->container->getExtensions() as $extension) {
212              $container->registerExtension($extension);
213          }
214   
215          return $container;
216      }
217   
218      /**
219       * Returns the start dot.
220       *
221       * @return string The string representation of a start dot
222       */
223      private function startDot()
224      {
225          return sprintf("digraph sc {\n  %s\n  node [%s];\n  edge [%s];\n\n",
226              $this->addOptions($this->options['graph']),
227              $this->addOptions($this->options['node']),
228              $this->addOptions($this->options['edge'])
229          );
230      }
231   
232      /**
233       * Returns the end dot.
234       *
235       * @return string
236       */
237      private function endDot()
238      {
239          return "}\n";
240      }
241   
242      /**
243       * Adds attributes.
244       *
245       * @param array $attributes An array of attributes
246       *
247       * @return string A comma separated list of attributes
248       */
249      private function addAttributes(array $attributes)
250      {
251          $code = array();
252          foreach ($attributes as $k => $v) {
253              $code[] = sprintf('%s="%s"', $k, $v);
254          }
255   
256          return $code ? ', '.implode(', ', $code) : '';
257      }
258   
259      /**
260       * Adds options.
261       *
262       * @param array $options An array of options
263       *
264       * @return string A space separated list of options
265       */
266      private function addOptions(array $options)
267      {
268          $code = array();
269          foreach ($options as $k => $v) {
270              $code[] = sprintf('%s="%s"', $k, $v);
271          }
272   
273          return implode(' ', $code);
274      }
275   
276      /**
277       * Dotizes an identifier.
278       *
279       * @param string $id The identifier to dotize
280       *
281       * @return string A dotized string
282       */
283      private function dotize($id)
284      {
285          return strtolower(preg_replace('/\W/i', '_', $id));
286      }
287   
288      /**
289       * Compiles an array of aliases for a specified service id.
290       *
291       * @param string $id A service id
292       *
293       * @return array An array of aliases
294       */
295      private function getAliases($id)
296      {
297          $aliases = array();
298          foreach ($this->container->getAliases() as $alias => $origin) {
299              if ($id == $origin) {
300                  $aliases[] = $alias;
301              }
302          }
303   
304          return $aliases;
305      }
306  }
307