diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 5ebd255450d4c..6636f6cce0e82 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -11,8 +11,13 @@ namespace Symfony\Bridge\Twig\Command; +if (!defined('JSON_PRETTY_PRINT')) { + define('JSON_PRETTY_PRINT', 128); +} + use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; @@ -56,23 +61,24 @@ protected function configure() { $this ->setDescription('Lints a template and outputs encountered errors') + ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') ->addArgument('filename') ->setHelp(<<%command.name% command lints a template and outputs to stdout +The %command.name% command lints a template and outputs to STDOUT the first encountered syntax error. +You can validate the syntax of a file: + php %command.full_name% filename -The command gets the contents of filename and validates its syntax. +Or of a whole directory: php %command.full_name% dirname +php %command.full_name% dirname --format=json -The command finds all twig templates in dirname and validates the syntax -of each Twig template. +You can also pass the template contents from STDIN: cat filename | php %command.full_name% - -The command gets the template contents from stdin and validates its syntax. EOF ) ; @@ -81,29 +87,27 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $twig = $this->getTwigEnvironment(); - $template = null; $filename = $input->getArgument('filename'); if (!$filename) { if (0 !== ftell(STDIN)) { - throw new \RuntimeException("Please provide a filename or pipe template content to stdin."); + throw new \RuntimeException("Please provide a filename or pipe template content to STDIN."); } + $template = ''; while (!feof(STDIN)) { $template .= fread(STDIN, 1024); } - return $this->validateTemplate($twig, $output, $template); + return $this->display($input, $output, array($this->validate($twig, $template))); } - $files = $this->findFiles($filename); - - $errors = 0; - foreach ($files as $file) { - $errors += $this->validateTemplate($twig, $output, file_get_contents($file), $file); + $filesInfo = array(); + foreach ($this->findFiles($filename) as $file) { + $filesInfo[] = $this->validate($twig, file_get_contents($file), $file); } - return $errors > 0 ? 1 : 0; + return $this->display($input, $output, $filesInfo); } protected function findFiles($filename) @@ -117,24 +121,69 @@ protected function findFiles($filename) throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); } - protected function validateTemplate(\Twig_Environment $twig, OutputInterface $output, $template, $file = null) + private function validate(\Twig_Environment $twig, $template, $file = null) { try { $twig->parse($twig->tokenize($template, $file ? (string) $file : null)); - $output->writeln('OK'.($file ? sprintf(' in %s', $file) : '')); } catch (\Twig_Error $e) { - $this->renderException($output, $template, $e, $file); + return array('template' => $template, 'file' => $file, 'valid' => false, 'exception' => $e); + } + + return array('template' => $template, 'file' => $file, 'valid' => true); + } + + private function display(InputInterface $input, OutputInterface $output, $files) + { + switch ($input->getOption('format')) { + case 'txt': + return $this->displayTxt($output, $files); + case 'json': + return $this->displayJson($output, $files); + default: + throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))); + } + } - return 1; + private function displayTxt(OutputInterface $output, $filesInfo) + { + $errors = 0; + + foreach ($filesInfo as $info) { + if ($info['valid'] && $output->isVerbose()) { + $output->writeln('OK'.($info['file'] ? sprintf(' in %s', $info['file']) : '')); + } elseif (!$info['valid']) { + $errors++; + $this->renderException($output, $info['template'], $info['exception'], $info['file']); + } } - return 0; + $output->writeln(sprintf('%d/%d valid files', count($filesInfo) - $errors, count($filesInfo))); + + return min($errors, 1); + } + + private function displayJson(OutputInterface $output, $filesInfo) + { + $errors = 0; + + array_walk($filesInfo, function (&$v) use (&$errors) { + $v['file'] = (string) $v['file']; + unset($v['template']); + if (!$v['valid']) { + $v['message'] = $v['exception']->getMessage(); + unset($v['exception']); + $errors++; + } + }); + + $output->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT)); + + return min($errors, 1); } - protected function renderException(OutputInterface $output, $template, \Twig_Error $exception, $file = null) + private function renderException(OutputInterface $output, $template, \Twig_Error $exception, $file = null) { $line = $exception->getTemplateLine(); - $lines = $this->getContext($template, $line); if ($file) { $output->writeln(sprintf("KO in %s (line %s)", $file, $line)); @@ -142,7 +191,7 @@ protected function renderException(OutputInterface $output, $template, \Twig_Err $output->writeln(sprintf("KO (line %s)", $line)); } - foreach ($lines as $no => $code) { + foreach ($this->getContext($template, $line) as $no => $code) { $output->writeln(sprintf( "%s %-6s %s", $no == $line ? '>>' : ' ', @@ -155,7 +204,7 @@ protected function renderException(OutputInterface $output, $template, \Twig_Err } } - protected function getContext($template, $line, $context = 3) + private function getContext($template, $line, $context = 3) { $lines = explode("\n", $template); diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php index da4460ccbe938..3fe54cbabf547 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -11,9 +11,10 @@ namespace Symfony\Bridge\Twig\Tests\Command; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Console\Application; use Symfony\Bridge\Twig\Command\LintCommand; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Tester\CommandTester; /** * @covers \Symfony\Bridge\Twig\Command\LintCommand @@ -27,7 +28,7 @@ public function testLintCorrectFile() $tester = $this->createCommandTester(); $filename = $this->createFile('{{ foo }}'); - $ret = $tester->execute(array('filename' => $filename)); + $ret = $tester->execute(array('filename' => $filename), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE)); $this->assertEquals(0, $ret, 'Returns 0 in case of success'); $this->assertRegExp('/^OK in /', $tester->getDisplay()); diff --git a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php index 79a765d768e5f..95c892cb0433b 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php @@ -57,10 +57,9 @@ protected function configure() $this->getHelp().<<php %command.full_name% @AcmeMyBundle +Or all template files in a bundle: -The command finds all twig templates in the AcmeMyBundle bundle and validates -the syntax of each Twig template. +php %command.full_name% @AcmeDemoBundle EOF ) ; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy