[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |