[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/symfony/twig-bridge/Command/ -> DebugCommand.php (source)

   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\Bridge\Twig\Command;
  13  
  14  use Symfony\Component\Console\Command\Command;
  15  use Symfony\Component\Console\Formatter\OutputFormatter;
  16  use Symfony\Component\Console\Input\InputArgument;
  17  use Symfony\Component\Console\Input\InputInterface;
  18  use Symfony\Component\Console\Input\InputOption;
  19  use Symfony\Component\Console\Output\OutputInterface;
  20  use Symfony\Component\Console\Style\SymfonyStyle;
  21  use Twig\Environment;
  22  use Twig\Loader\FilesystemLoader;
  23  
  24  /**
  25   * Lists twig functions, filters, globals and tests present in the current project.
  26   *
  27   * @author Jordi Boggiano <j.boggiano@seld.be>
  28   */
  29  class DebugCommand extends Command
  30  {
  31      protected static $defaultName = 'debug:twig';
  32  
  33      private $twig;
  34      private $projectDir;
  35  
  36      /**
  37       * @param Environment $twig
  38       * @param string|null $projectDir
  39       */
  40      public function __construct($twig = null, $projectDir = null)
  41      {
  42          if (!$twig instanceof Environment) {
  43              @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);
  44  
  45              parent::__construct($twig);
  46  
  47              return;
  48          }
  49  
  50          parent::__construct();
  51  
  52          $this->twig = $twig;
  53          $this->projectDir = $projectDir;
  54      }
  55  
  56      public function setTwigEnvironment(Environment $twig)
  57      {
  58          @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
  59  
  60          $this->twig = $twig;
  61      }
  62  
  63      /**
  64       * @return Environment $twig
  65       */
  66      protected function getTwigEnvironment()
  67      {
  68          @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
  69  
  70          return $this->twig;
  71      }
  72  
  73      protected function configure()
  74      {
  75          $this
  76              ->setDefinition([
  77                  new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'),
  78                  new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'),
  79              ])
  80              ->setDescription('Shows a list of twig functions, filters, globals and tests')
  81              ->setHelp(<<<'EOF'
  82  The <info>%command.name%</info> command outputs a list of twig functions,
  83  filters, globals and tests. Output can be filtered with an optional argument.
  84  
  85    <info>php %command.full_name%</info>
  86  
  87  The command lists all functions, filters, etc.
  88  
  89    <info>php %command.full_name% date</info>
  90  
  91  The command lists everything that contains the word date.
  92  
  93    <info>php %command.full_name% --format=json</info>
  94  
  95  The command lists everything in a machine readable json format.
  96  EOF
  97              )
  98          ;
  99      }
 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  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1