[ Index ]

PHP Cross Reference of phpBB-3.3.2-deutsch

title

Body

[close]

/vendor/symfony/yaml/Command/ -> LintCommand.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\Component\Yaml\Command;
  13  
  14  use Symfony\Component\Console\Command\Command;
  15  use Symfony\Component\Console\Exception\InvalidArgumentException;
  16  use Symfony\Component\Console\Exception\RuntimeException;
  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 Symfony\Component\Yaml\Exception\ParseException;
  22  use Symfony\Component\Yaml\Parser;
  23  use Symfony\Component\Yaml\Yaml;
  24  
  25  /**
  26   * Validates YAML files syntax and outputs encountered errors.
  27   *
  28   * @author Grégoire Pineau <lyrixx@lyrixx.info>
  29   * @author Robin Chalas <robin.chalas@gmail.com>
  30   */
  31  class LintCommand extends Command
  32  {
  33      protected static $defaultName = 'lint:yaml';
  34  
  35      private $parser;
  36      private $format;
  37      private $displayCorrectFiles;
  38      private $directoryIteratorProvider;
  39      private $isReadableProvider;
  40  
  41      public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null)
  42      {
  43          parent::__construct($name);
  44  
  45          $this->directoryIteratorProvider = $directoryIteratorProvider;
  46          $this->isReadableProvider = $isReadableProvider;
  47      }
  48  
  49      /**
  50       * {@inheritdoc}
  51       */
  52      protected function configure()
  53      {
  54          $this
  55              ->setDescription('Lints a file and outputs encountered errors')
  56              ->addArgument('filename', null, 'A file or a directory or STDIN')
  57              ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
  58              ->addOption('parse-tags', null, InputOption::VALUE_NONE, 'Parse custom tags')
  59              ->setHelp(<<<EOF
  60  The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
  61  the first encountered syntax error.
  62  
  63  You can validates YAML contents passed from STDIN:
  64  
  65    <info>cat filename | php %command.full_name%</info>
  66  
  67  You can also validate the syntax of a file:
  68  
  69    <info>php %command.full_name% filename</info>
  70  
  71  Or of a whole directory:
  72  
  73    <info>php %command.full_name% dirname</info>
  74    <info>php %command.full_name% dirname --format=json</info>
  75  
  76  EOF
  77              )
  78          ;
  79      }
  80  
  81      protected function execute(InputInterface $input, OutputInterface $output)
  82      {
  83          $io = new SymfonyStyle($input, $output);
  84          $filename = $input->getArgument('filename');
  85          $this->format = $input->getOption('format');
  86          $this->displayCorrectFiles = $output->isVerbose();
  87          $flags = $input->getOption('parse-tags') ? Yaml::PARSE_CUSTOM_TAGS : 0;
  88  
  89          if (!$filename) {
  90              if (!$stdin = $this->getStdin()) {
  91                  throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
  92              }
  93  
  94              return $this->display($io, [$this->validate($stdin, $flags)]);
  95          }
  96  
  97          if (!$this->isReadable($filename)) {
  98              throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
  99          }
 100  
 101          $filesInfo = [];
 102          foreach ($this->getFiles($filename) as $file) {
 103              $filesInfo[] = $this->validate(file_get_contents($file), $flags, $file);
 104          }
 105  
 106          return $this->display($io, $filesInfo);
 107      }
 108  
 109      private function validate($content, $flags, $file = null)
 110      {
 111          $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) {
 112              if (\E_USER_DEPRECATED === $level) {
 113                  throw new ParseException($message, $this->getParser()->getRealCurrentLineNb() + 1);
 114              }
 115  
 116              return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false;
 117          });
 118  
 119          try {
 120              $this->getParser()->parse($content, Yaml::PARSE_CONSTANT | $flags);
 121          } catch (ParseException $e) {
 122              return ['file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage()];
 123          } finally {
 124              restore_error_handler();
 125          }
 126  
 127          return ['file' => $file, 'valid' => true];
 128      }
 129  
 130      private function display(SymfonyStyle $io, array $files)
 131      {
 132          switch ($this->format) {
 133              case 'txt':
 134                  return $this->displayTxt($io, $files);
 135              case 'json':
 136                  return $this->displayJson($io, $files);
 137              default:
 138                  throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
 139          }
 140      }
 141  
 142      private function displayTxt(SymfonyStyle $io, array $filesInfo)
 143      {
 144          $countFiles = \count($filesInfo);
 145          $erroredFiles = 0;
 146  
 147          foreach ($filesInfo as $info) {
 148              if ($info['valid'] && $this->displayCorrectFiles) {
 149                  $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
 150              } elseif (!$info['valid']) {
 151                  ++$erroredFiles;
 152                  $io->text('<error> ERROR </error>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
 153                  $io->text(sprintf('<error> >> %s</error>', $info['message']));
 154              }
 155          }
 156  
 157          if (0 === $erroredFiles) {
 158              $io->success(sprintf('All %d YAML files contain valid syntax.', $countFiles));
 159          } else {
 160              $io->warning(sprintf('%d YAML files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
 161          }
 162  
 163          return min($erroredFiles, 1);
 164      }
 165  
 166      private function displayJson(SymfonyStyle $io, array $filesInfo)
 167      {
 168          $errors = 0;
 169  
 170          array_walk($filesInfo, function (&$v) use (&$errors) {
 171              $v['file'] = (string) $v['file'];
 172              if (!$v['valid']) {
 173                  ++$errors;
 174              }
 175          });
 176  
 177          $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
 178  
 179          return min($errors, 1);
 180      }
 181  
 182      private function getFiles($fileOrDirectory)
 183      {
 184          if (is_file($fileOrDirectory)) {
 185              yield new \SplFileInfo($fileOrDirectory);
 186  
 187              return;
 188          }
 189  
 190          foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
 191              if (!\in_array($file->getExtension(), ['yml', 'yaml'])) {
 192                  continue;
 193              }
 194  
 195              yield $file;
 196          }
 197      }
 198  
 199      /**
 200       * @return string|null
 201       */
 202      private function getStdin()
 203      {
 204          if (0 !== ftell(\STDIN)) {
 205              return null;
 206          }
 207  
 208          $inputs = '';
 209          while (!feof(\STDIN)) {
 210              $inputs .= fread(\STDIN, 1024);
 211          }
 212  
 213          return $inputs;
 214      }
 215  
 216      private function getParser()
 217      {
 218          if (!$this->parser) {
 219              $this->parser = new Parser();
 220          }
 221  
 222          return $this->parser;
 223      }
 224  
 225      private function getDirectoryIterator($directory)
 226      {
 227          $default = function ($directory) {
 228              return new \RecursiveIteratorIterator(
 229                  new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
 230                  \RecursiveIteratorIterator::LEAVES_ONLY
 231              );
 232          };
 233  
 234          if (null !== $this->directoryIteratorProvider) {
 235              return \call_user_func($this->directoryIteratorProvider, $directory, $default);
 236          }
 237  
 238          return $default($directory);
 239      }
 240  
 241      private function isReadable($fileOrDirectory)
 242      {
 243          $default = function ($fileOrDirectory) {
 244              return is_readable($fileOrDirectory);
 245          };
 246  
 247          if (null !== $this->isReadableProvider) {
 248              return \call_user_func($this->isReadableProvider, $fileOrDirectory, $default);
 249          }
 250  
 251          return $default($fileOrDirectory);
 252      }
 253  }


Generated: Wed Nov 11 20:28:18 2020 Cross-referenced by PHPXref 0.7.1