Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
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\Bridge\Twig\Command;
013
014 use Symfony\Component\Console\Command\Command;
015 use Symfony\Component\Console\Input\InputArgument;
016 use Symfony\Component\Console\Input\InputInterface;
017 use Symfony\Component\Console\Input\InputOption;
018 use Symfony\Component\Console\Output\OutputInterface;
019 use Symfony\Component\Console\Style\SymfonyStyle;
020 use Symfony\Component\Finder\Finder;
021
022 /**
023 * Command that will validate your template syntax and output encountered errors.
024 *
025 * @author Marc Weistroff <marc.weistroff@sensiolabs.com>
026 * @author Jérôme Tamarelle <jerome@tamarelle.net>
027 */
028 class LintCommand extends Command
029 {
030 private $twig;
031
032 /**
033 * {@inheritdoc}
034 */
035 public function __construct($name = 'lint:twig')
036 {
037 parent::__construct($name);
038 }
039
040 /**
041 * Sets the twig environment.
042 *
043 * @param \Twig_Environment $twig
044 */
045 public function setTwigEnvironment(\Twig_Environment $twig)
046 {
047 $this->twig = $twig;
048 }
049
050 /**
051 * @return \Twig_Environment $twig
052 */
053 protected function getTwigEnvironment()
054 {
055 return $this->twig;
056 }
057
058 protected function configure()
059 {
060 $this
061 ->setAliases(array('twig:lint'))
062 ->setDescription('Lints a template and outputs encountered errors')
063 ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
064 ->addArgument('filename', InputArgument::IS_ARRAY)
065 ->setHelp(<<<EOF
066 The <info>%command.name%</info> command lints a template and outputs to STDOUT
067 the first encountered syntax error.
068
069 You can validate the syntax of contents passed from STDIN:
070
071 <info>cat filename | php %command.full_name%</info>
072
073 Or the syntax of a file:
074
075 <info>php %command.full_name% filename</info>
076
077 Or of a whole directory:
078
079 <info>php %command.full_name% dirname</info>
080 <info>php %command.full_name% dirname --format=json</info>
081
082 EOF
083 )
084 ;
085 }
086
087 protected function execute(InputInterface $input, OutputInterface $output)
088 {
089 $io = new SymfonyStyle($input, $output);
090
091 if (false !== strpos($input->getFirstArgument(), ':l')) {
092 $io->caution('The use of "twig:lint" command is deprecated since version 2.7 and will be removed in 3.0. Use the "lint:twig" instead.');
093 }
094
095 if (null === $twig = $this->getTwigEnvironment()) {
096 $io->error('The Twig environment needs to be set.');
097
098 return 1;
099 }
100
101 $filenames = $input->getArgument('filename');
102
103 if (0 === count($filenames)) {
104 if (0 !== ftell(STDIN)) {
105 throw new \RuntimeException('Please provide a filename or pipe template content to STDIN.');
106 }
107
108 $template = '';
109 while (!feof(STDIN)) {
110 $template .= fread(STDIN, 1024);
111 }
112
113 return $this->display($input, $output, $io, array($this->validate($twig, $template, uniqid('sf_'))));
114 }
115
116 $filesInfo = $this->getFilesInfo($twig, $filenames);
117
118 return $this->display($input, $output, $io, $filesInfo);
119 }
120
121 private function getFilesInfo(\Twig_Environment $twig, array $filenames)
122 {
123 $filesInfo = array();
124 foreach ($filenames as $filename) {
125 foreach ($this->findFiles($filename) as $file) {
126 $filesInfo[] = $this->validate($twig, file_get_contents($file), $file);
127 }
128 }
129
130 return $filesInfo;
131 }
132
133 protected function findFiles($filename)
134 {
135 if (is_file($filename)) {
136 return array($filename);
137 } elseif (is_dir($filename)) {
138 return Finder::create()->files()->in($filename)->name('*.twig');
139 }
140
141 throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename));
142 }
143
144 private function validate(\Twig_Environment $twig, $template, $file)
145 {
146 $realLoader = $twig->getLoader();
147 try {
148 $temporaryLoader = new \Twig_Loader_Array(array((string) $file => $template));
149 $twig->setLoader($temporaryLoader);
150 $nodeTree = $twig->parse($twig->tokenize($template, (string) $file));
151 $twig->compile($nodeTree);
152 $twig->setLoader($realLoader);
153 } catch (\Twig_Error $e) {
154 $twig->setLoader($realLoader);
155
156 return array('template' => $template, 'file' => $file, 'valid' => false, 'exception' => $e);
157 }
158
159 return array('template' => $template, 'file' => $file, 'valid' => true);
160 }
161
162 private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, $files)
163 {
164 switch ($input->getOption('format')) {
165 case 'txt':
166 return $this->displayTxt($output, $io, $files);
167 case 'json':
168 return $this->displayJson($output, $files);
169 default:
170 throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
171 }
172 }
173
174 private function displayTxt(OutputInterface $output, SymfonyStyle $io, $filesInfo)
175 {
176 $errors = 0;
177
178 foreach ($filesInfo as $info) {
179 if ($info['valid'] && $output->isVerbose()) {
180 $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
181 } elseif (!$info['valid']) {
182 ++$errors;
183 $this->renderException($io, $info['template'], $info['exception'], $info['file']);
184 }
185 }
186
187 if ($errors === 0) {
188 $io->success(sprintf('All %d Twig files contain valid syntax.', count($filesInfo)));
189 } else {
190 $io->warning(sprintf('%d Twig files have valid syntax and %d contain errors.', count($filesInfo) - $errors, $errors));
191 }
192
193 return min($errors, 1);
194 }
195
196 private function displayJson(OutputInterface $output, $filesInfo)
197 {
198 $errors = 0;
199
200 array_walk($filesInfo, function (&$v) use (&$errors) {
201 $v['file'] = (string) $v['file'];
202 unset($v['template']);
203 if (!$v['valid']) {
204 $v['message'] = $v['exception']->getMessage();
205 unset($v['exception']);
206 ++$errors;
207 }
208 });
209
210 $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0));
211
212 return min($errors, 1);
213 }
214
215 private function renderException(OutputInterface $output, $template, \Twig_Error $exception, $file = null)
216 {
217 $line = $exception->getTemplateLine();
218
219 if ($file) {
220 $output->text(sprintf('<error> ERROR </error> in %s (line %s)', $file, $line));
221 } else {
222 $output->text(sprintf('<error> ERROR </error> (line %s)', $line));
223 }
224
225 foreach ($this->getContext($template, $line) as $lineNumber => $code) {
226 $output->text(sprintf(
227 '%s %-6s %s',
228 $lineNumber === $line ? '<error> >> </error>' : ' ',
229 $lineNumber,
230 $code
231 ));
232 if ($lineNumber === $line) {
233 $output->text(sprintf('<error> >> %s</error> ', $exception->getRawMessage()));
234 }
235 }
236 }
237
238 private function getContext($template, $line, $context = 3)
239 {
240 $lines = explode("\n", $template);
241
242 $position = max(0, $line - $context);
243 $max = min(count($lines), $line - 1 + $context);
244
245 $result = array();
246 while ($position < $max) {
247 $result[$position + 1] = $lines[$position];
248 ++$position;
249 }
250
251 return $result;
252 }
253 }
254