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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
LintCommand.php
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\Component\Yaml\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\InputInterface;
018 use Symfony\Component\Console\Input\InputOption;
019 use Symfony\Component\Console\Output\OutputInterface;
020 use Symfony\Component\Console\Style\SymfonyStyle;
021 use Symfony\Component\Yaml\Exception\ParseException;
022 use Symfony\Component\Yaml\Parser;
023 use Symfony\Component\Yaml\Yaml;
024
025 /**
026 * Validates YAML files syntax and outputs encountered errors.
027 *
028 * @author Grégoire Pineau <lyrixx@lyrixx.info>
029 * @author Robin Chalas <robin.chalas@gmail.com>
030 */
031 class LintCommand extends Command
032 {
033 protected static $defaultName = 'lint:yaml';
034
035 private $parser;
036 private $format;
037 private $displayCorrectFiles;
038 private $directoryIteratorProvider;
039 private $isReadableProvider;
040
041 public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null)
042 {
043 parent::__construct($name);
044
045 $this->directoryIteratorProvider = $directoryIteratorProvider;
046 $this->isReadableProvider = $isReadableProvider;
047 }
048
049 /**
050 * {@inheritdoc}
051 */
052 protected function configure()
053 {
054 $this
055 ->setDescription('Lints a file and outputs encountered errors')
056 ->addArgument('filename', null, 'A file or a directory or STDIN')
057 ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
058 ->addOption('parse-tags', null, InputOption::VALUE_NONE, 'Parse custom tags')
059 ->setHelp(<<<EOF
060 The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
061 the first encountered syntax error.
062
063 You can validates YAML contents passed from STDIN:
064
065 <info>cat filename | php %command.full_name%</info>
066
067 You can also validate the syntax of a file:
068
069 <info>php %command.full_name% filename</info>
070
071 Or of a whole directory:
072
073 <info>php %command.full_name% dirname</info>
074 <info>php %command.full_name% dirname --format=json</info>
075
076 EOF
077 )
078 ;
079 }
080
081 protected function execute(InputInterface $input, OutputInterface $output)
082 {
083 $io = new SymfonyStyle($input, $output);
084 $filename = $input->getArgument('filename');
085 $this->format = $input->getOption('format');
086 $this->displayCorrectFiles = $output->isVerbose();
087 $flags = $input->getOption('parse-tags') ? Yaml::PARSE_CUSTOM_TAGS : 0;
088
089 if (!$filename) {
090 if (!$stdin = $this->getStdin()) {
091 throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
092 }
093
094 return $this->display($io, [$this->validate($stdin, $flags)]);
095 }
096
097 if (!$this->isReadable($filename)) {
098 throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
099 }
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 }
254