PluginProbe
WindPress – Tailwind CSS integration for WordPress / 3.2.86
WindPress – Tailwind CSS integration for WordPress v3.2.86
3.2.90 3.2.89 3.2.88 3.2.87 3.2.86 3.2.85 3.2.84 3.2.83 3.2.82 3.2.81 trunk 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.2 3.0.3 3.0.4 3.0.5 All 144 releases
windpress / vendor / symfony / yaml / Command / LintCommand.php

LintCommand.php in WindPress – Tailwind CSS integration for WordPress 3.2.86, at vendor/symfony/yaml/Command/LintCommand.php

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