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