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

LintCommand.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 8.83 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\Exception\InvalidArgumentException;
016  use Symfony\Component\Console\Exception\RuntimeException;
017  use Symfony\Component\Console\Input\InputArgument;
018  use Symfony\Component\Console\Input\InputInterface;
019  use Symfony\Component\Console\Input\InputOption;
020  use Symfony\Component\Console\Output\OutputInterface;
021  use Symfony\Component\Console\Style\SymfonyStyle;
022  use Symfony\Component\Finder\Finder;
023  use Twig\Environment;
024  use Twig\Error\Error;
025  use Twig\Loader\ArrayLoader;
026  use Twig\Source;
027   
028  /**
029   * Command that will validate your template syntax and output encountered errors.
030   *
031   * @author Marc Weistroff <marc.weistroff@sensiolabs.com>
032   * @author Jérôme Tamarelle <jerome@tamarelle.net>
033   */
034  class LintCommand extends Command
035  {
036      protected static $defaultName = 'lint:twig';
037   
038      private $twig;
039   
040      /**
041       * @param Environment $twig
042       */
043      public function __construct($twig = null)
044      {
045          if (!$twig instanceof Environment) {
046              @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);
047   
048              parent::__construct($twig);
049   
050              return;
051          }
052   
053          parent::__construct();
054   
055          $this->twig = $twig;
056      }
057   
058      public function setTwigEnvironment(Environment $twig)
059      {
060          @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
061   
062          $this->twig = $twig;
063      }
064   
065      /**
066       * @return Environment $twig
067       */
068      protected function getTwigEnvironment()
069      {
070          @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
071   
072          return $this->twig;
073      }
074   
075      protected function configure()
076      {
077          $this
078              ->setDescription('Lints a template and outputs encountered errors')
079              ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
080              ->addArgument('filename', InputArgument::IS_ARRAY)
081              ->setHelp(<<<'EOF'
082  The <info>%command.name%</info> command lints a template and outputs to STDOUT
083  the first encountered syntax error.
084   
085  You can validate the syntax of contents passed from STDIN:
086   
087    <info>cat filename | php %command.full_name%</info>
088   
089  Or the syntax of a file:
090   
091    <info>php %command.full_name% filename</info>
092   
093  Or of a whole directory:
094   
095    <info>php %command.full_name% dirname</info>
096    <info>php %command.full_name% dirname --format=json</info>
097   
098  EOF
099              )
100          ;
101      }
102   
103      protected function execute(InputInterface $input, OutputInterface $output)
104      {
105          $io = new SymfonyStyle($input, $output);
106   
107          // BC to be removed in 4.0
108          if (__CLASS__ !== static::class) {
109              $r = new \ReflectionMethod($this, 'getTwigEnvironment');
110              if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
111                  @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);
112   
113                  $this->twig = $this->getTwigEnvironment();
114              }
115          }
116          if (null === $this->twig) {
117              throw new \RuntimeException('The Twig environment needs to be set.');
118          }
119   
120          $filenames = $input->getArgument('filename');
121   
122          if (0 === \count($filenames)) {
123              if (0 !== ftell(\STDIN)) {
124                  throw new RuntimeException('Please provide a filename or pipe template content to STDIN.');
125              }
126   
127              $template = '';
128              while (!feof(\STDIN)) {
129                  $template .= fread(\STDIN, 1024);
130              }
131   
132              return $this->display($input, $output, $io, [$this->validate($template, uniqid('sf_', true))]);
133          }
134   
135          $filesInfo = $this->getFilesInfo($filenames);
136   
137          return $this->display($input, $output, $io, $filesInfo);
138      }
139   
140      private function getFilesInfo(array $filenames)
141      {
142          $filesInfo = [];
143          foreach ($filenames as $filename) {
144              foreach ($this->findFiles($filename) as $file) {
145                  $filesInfo[] = $this->validate(file_get_contents($file), $file);
146              }
147          }
148   
149          return $filesInfo;
150      }
151   
152      protected function findFiles($filename)
153      {
154          if (is_file($filename)) {
155              return [$filename];
156          } elseif (is_dir($filename)) {
157              return Finder::create()->files()->in($filename)->name('*.twig');
158          }
159   
160          throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
161      }
162   
163      private function validate($template, $file)
164      {
165          $realLoader = $this->twig->getLoader();
166          try {
167              $temporaryLoader = new ArrayLoader([(string) $file => $template]);
168              $this->twig->setLoader($temporaryLoader);
169              $nodeTree = $this->twig->parse($this->twig->tokenize(new Source($template, (string) $file)));
170              $this->twig->compile($nodeTree);
171              $this->twig->setLoader($realLoader);
172          } catch (Error $e) {
173              $this->twig->setLoader($realLoader);
174   
175              return ['template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e];
176          }
177   
178          return ['template' => $template, 'file' => $file, 'valid' => true];
179      }
180   
181      private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, $files)
182      {
183          switch ($input->getOption('format')) {
184              case 'txt':
185                  return $this->displayTxt($output, $io, $files);
186              case 'json':
187                  return $this->displayJson($output, $files);
188              default:
189                  throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
190          }
191      }
192   
193      private function displayTxt(OutputInterface $output, SymfonyStyle $io, $filesInfo)
194      {
195          $errors = 0;
196   
197          foreach ($filesInfo as $info) {
198              if ($info['valid'] && $output->isVerbose()) {
199                  $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
200              } elseif (!$info['valid']) {
201                  ++$errors;
202                  $this->renderException($io, $info['template'], $info['exception'], $info['file']);
203              }
204          }
205   
206          if (0 === $errors) {
207              $io->success(sprintf('All %d Twig files contain valid syntax.', \count($filesInfo)));
208          } else {
209              $io->warning(sprintf('%d Twig files have valid syntax and %d contain errors.', \count($filesInfo) - $errors, $errors));
210          }
211   
212          return min($errors, 1);
213      }
214   
215      private function displayJson(OutputInterface $output, $filesInfo)
216      {
217          $errors = 0;
218   
219          array_walk($filesInfo, function (&$v) use (&$errors) {
220              $v['file'] = (string) $v['file'];
221              unset($v['template']);
222              if (!$v['valid']) {
223                  $v['message'] = $v['exception']->getMessage();
224                  unset($v['exception']);
225                  ++$errors;
226              }
227          });
228   
229          $output->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
230   
231          return min($errors, 1);
232      }
233   
234      private function renderException(OutputInterface $output, $template, Error $exception, $file = null)
235      {
236          $line = $exception->getTemplateLine();
237   
238          if ($file) {
239              $output->text(sprintf('<error> ERROR </error> in %s (line %s)', $file, $line));
240          } else {
241              $output->text(sprintf('<error> ERROR </error> (line %s)', $line));
242          }
243   
244          foreach ($this->getContext($template, $line) as $lineNumber => $code) {
245              $output->text(sprintf(
246                  '%s %-6s %s',
247                  $lineNumber === $line ? '<error> >> </error>' : '    ',
248                  $lineNumber,
249                  $code
250              ));
251              if ($lineNumber === $line) {
252                  $output->text(sprintf('<error> >> %s</error> ', $exception->getRawMessage()));
253              }
254          }
255      }
256   
257      private function getContext($template, $line, $context = 3)
258      {
259          $lines = explode("\n", $template);
260   
261          $position = max(0, $line - $context);
262          $max = min(\count($lines), $line - 1 + $context);
263   
264          $result = [];
265          while ($position < $max) {
266              $result[$position + 1] = $lines[$position];
267              ++$position;
268          }
269   
270          return $result;
271      }
272  }
273