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

DebugCommand.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 9.85 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\Bridge\Twig\Command;
013   
014  use Symfony\Component\Console\Command\Command;
015  use Symfony\Component\Console\Formatter\OutputFormatter;
016  use Symfony\Component\Console\Input\InputArgument;
017  use Symfony\Component\Console\Input\InputInterface;
018  use Symfony\Component\Console\Input\InputOption;
019  use Symfony\Component\Console\Output\OutputInterface;
020  use Symfony\Component\Console\Style\SymfonyStyle;
021  use Twig\Environment;
022  use Twig\Loader\FilesystemLoader;
023   
024  /**
025   * Lists twig functions, filters, globals and tests present in the current project.
026   *
027   * @author Jordi Boggiano <j.boggiano@seld.be>
028   */
029  class DebugCommand extends Command
030  {
031      protected static $defaultName = 'debug:twig';
032   
033      private $twig;
034      private $projectDir;
035   
036      /**
037       * @param Environment $twig
038       * @param string|null $projectDir
039       */
040      public function __construct($twig = null, $projectDir = null)
041      {
042          if (!$twig instanceof Environment) {
043              @trigger_error(sprintf('Passing a command name as the first argument of "%s()" is deprecated since Symfony 3.4 and support for it will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), \E_USER_DEPRECATED);
044   
045              parent::__construct($twig);
046   
047              return;
048          }
049   
050          parent::__construct();
051   
052          $this->twig = $twig;
053          $this->projectDir = $projectDir;
054      }
055   
056      public function setTwigEnvironment(Environment $twig)
057      {
058          @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
059   
060          $this->twig = $twig;
061      }
062   
063      /**
064       * @return Environment $twig
065       */
066      protected function getTwigEnvironment()
067      {
068          @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
069   
070          return $this->twig;
071      }
072   
073      protected function configure()
074      {
075          $this
076              ->setDefinition([
077                  new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'),
078                  new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'),
079              ])
080              ->setDescription('Shows a list of twig functions, filters, globals and tests')
081              ->setHelp(<<<'EOF'
082  The <info>%command.name%</info> command outputs a list of twig functions,
083  filters, globals and tests. Output can be filtered with an optional argument.
084   
085    <info>php %command.full_name%</info>
086   
087  The command lists all functions, filters, etc.
088   
089    <info>php %command.full_name% date</info>
090   
091  The command lists everything that contains the word date.
092   
093    <info>php %command.full_name% --format=json</info>
094   
095  The command lists everything in a machine readable json format.
096  EOF
097              )
098          ;
099      }
100   
101      protected function execute(InputInterface $input, OutputInterface $output)
102      {
103          $io = new SymfonyStyle($input, $output);
104          $decorated = $io->isDecorated();
105   
106          // BC to be removed in 4.0
107          if (__CLASS__ !== static::class) {
108              $r = new \ReflectionMethod($this, 'getTwigEnvironment');
109              if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
110                  @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', static::class.'::getTwigEnvironment'), \E_USER_DEPRECATED);
111   
112                  $this->twig = $this->getTwigEnvironment();
113              }
114          }
115          if (null === $this->twig) {
116              throw new \RuntimeException('The Twig environment needs to be set.');
117          }
118   
119          $filter = $input->getArgument('filter');
120          $types = ['functions', 'filters', 'tests', 'globals'];
121   
122          if ('json' === $input->getOption('format')) {
123              $data = [];
124              foreach ($types as $type) {
125                  foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
126                      if (!$filter || false !== strpos($name, $filter)) {
127                          $data[$type][$name] = $this->getMetadata($type, $entity);
128                      }
129                  }
130              }
131   
132              if (isset($data['tests'])) {
133                  $data['tests'] = array_keys($data['tests']);
134              }
135   
136              $data['loader_paths'] = $this->getLoaderPaths();
137              $data = json_encode($data, \JSON_PRETTY_PRINT);
138              $io->writeln($decorated ? OutputFormatter::escape($data) : $data);
139   
140              return 0;
141          }
142   
143          foreach ($types as $index => $type) {
144              $items = [];
145              foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
146                  if (!$filter || false !== strpos($name, $filter)) {
147                      $items[$name] = $name.$this->getPrettyMetadata($type, $entity, $decorated);
148                  }
149              }
150   
151              if (!$items) {
152                  continue;
153              }
154   
155              $io->section(ucfirst($type));
156   
157              ksort($items);
158              $io->listing($items);
159          }
160   
161          $rows = [];
162          $firstNamespace = true;
163          $prevHasSeparator = false;
164          foreach ($this->getLoaderPaths() as $namespace => $paths) {
165              if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) {
166                  $rows[] = ['', ''];
167              }
168              $firstNamespace = false;
169              foreach ($paths as $path) {
170                  $rows[] = [$namespace, $path.\DIRECTORY_SEPARATOR];
171                  $namespace = '';
172              }
173              if (\count($paths) > 1) {
174                  $rows[] = ['', ''];
175                  $prevHasSeparator = true;
176              } else {
177                  $prevHasSeparator = false;
178              }
179          }
180          if ($prevHasSeparator) {
181              array_pop($rows);
182          }
183          $io->section('Loader Paths');
184          $io->table(['Namespace', 'Paths'], $rows);
185   
186          return 0;
187      }
188   
189      private function getLoaderPaths()
190      {
191          if (!($loader = $this->twig->getLoader()) instanceof FilesystemLoader) {
192              return [];
193          }
194   
195          $loaderPaths = [];
196          foreach ($loader->getNamespaces() as $namespace) {
197              $paths = array_map(function ($path) {
198                  if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) {
199                      $path = ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
200                  }
201   
202                  return $path;
203              }, $loader->getPaths($namespace));
204   
205              if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
206                  $namespace = '(None)';
207              } else {
208                  $namespace = '@'.$namespace;
209              }
210   
211              $loaderPaths[$namespace] = $paths;
212          }
213   
214          return $loaderPaths;
215      }
216   
217      private function getMetadata($type, $entity)
218      {
219          if ('globals' === $type) {
220              return $entity;
221          }
222          if ('tests' === $type) {
223              return null;
224          }
225          if ('functions' === $type || 'filters' === $type) {
226              $cb = $entity->getCallable();
227              if (null === $cb) {
228                  return null;
229              }
230              if (\is_array($cb)) {
231                  if (!method_exists($cb[0], $cb[1])) {
232                      return null;
233                  }
234                  $refl = new \ReflectionMethod($cb[0], $cb[1]);
235              } elseif (\is_object($cb) && method_exists($cb, '__invoke')) {
236                  $refl = new \ReflectionMethod($cb, '__invoke');
237              } elseif (\function_exists($cb)) {
238                  $refl = new \ReflectionFunction($cb);
239              } elseif (\is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) {
240                  $refl = new \ReflectionMethod($m[1], $m[2]);
241              } else {
242                  throw new \UnexpectedValueException('Unsupported callback type.');
243              }
244   
245              $args = $refl->getParameters();
246   
247              // filter out context/environment args
248              if ($entity->needsEnvironment()) {
249                  array_shift($args);
250              }
251              if ($entity->needsContext()) {
252                  array_shift($args);
253              }
254   
255              if ('filters' === $type) {
256                  // remove the value the filter is applied on
257                  array_shift($args);
258              }
259   
260              // format args
261              $args = array_map(function ($param) {
262                  if ($param->isDefaultValueAvailable()) {
263                      return $param->getName().' = '.json_encode($param->getDefaultValue());
264                  }
265   
266                  return $param->getName();
267              }, $args);
268   
269              return $args;
270          }
271   
272          return null;
273      }
274   
275      private function getPrettyMetadata($type, $entity, $decorated)
276      {
277          if ('tests' === $type) {
278              return '';
279          }
280   
281          try {
282              $meta = $this->getMetadata($type, $entity);
283              if (null === $meta) {
284                  return '(unknown?)';
285              }
286          } catch (\UnexpectedValueException $e) {
287              return sprintf(' <error>%s</error>', $decorated ? OutputFormatter::escape($e->getMessage()) : $e->getMessage());
288          }
289   
290          if ('globals' === $type) {
291              if (\is_object($meta)) {
292                  return ' = object('.\get_class($meta).')';
293              }
294   
295              $description = substr(@json_encode($meta), 0, 50);
296   
297              return sprintf(' = %s', $decorated ? OutputFormatter::escape($description) : $description);
298          }
299   
300          if ('functions' === $type) {
301              return '('.implode(', ', $meta).')';
302          }
303   
304          if ('filters' === $type) {
305              return $meta ? '('.implode(', ', $meta).')' : '';
306          }
307   
308          return null;
309      }
310  }
311