diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index 346d52a5ad41e..4be010ba20e56 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +2.5.0 +----- + + * moved command `twig:lint` from `TwigBundle` + 2.4.0 ----- diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php new file mode 100644 index 0000000000000..5ebd255450d4c --- /dev/null +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Finder\Finder; + +/** + * Command that will validate your template syntax and output encountered errors. + * + * @author Marc Weistroff + * @author Jérôme Tamarelle + */ +class LintCommand extends Command +{ + private $twig; + + /** + * {@inheritDoc} + */ + public function __construct($name = 'twig:lint') + { + parent::__construct($name); + } + + /** + * Sets the twig environment + * + * @param \Twig_Environment $twig + */ + public function setTwigEnvironment(\Twig_Environment $twig) + { + $this->twig = $twig; + } + + /** + * @return \Twig_Environment $twig + */ + protected function getTwigEnvironment() + { + return $this->twig; + } + + protected function configure() + { + $this + ->setDescription('Lints a template and outputs encountered errors') + ->addArgument('filename') + ->setHelp(<<%command.name% command lints a template and outputs to stdout +the first encountered syntax error. + +php %command.full_name% filename + +The command gets the contents of filename and validates its syntax. + +php %command.full_name% dirname + +The command finds all twig templates in dirname and validates the syntax +of each Twig template. + +cat filename | php %command.full_name% + +The command gets the template contents from stdin and validates its syntax. +EOF + ) + ; + } + + 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."); + } + + while (!feof(STDIN)) { + $template .= fread(STDIN, 1024); + } + + return $this->validateTemplate($twig, $output, $template); + } + + $files = $this->findFiles($filename); + + $errors = 0; + foreach ($files as $file) { + $errors += $this->validateTemplate($twig, $output, file_get_contents($file), $file); + } + + return $errors > 0 ? 1 : 0; + } + + protected function findFiles($filename) + { + if (is_file($filename)) { + return array($filename); + } elseif (is_dir($filename)) { + return Finder::create()->files()->in($filename)->name('*.twig'); + } + + throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); + } + + protected function validateTemplate(\Twig_Environment $twig, OutputInterface $output, $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 1; + } + + return 0; + } + + protected 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)); + } else { + $output->writeln(sprintf("KO (line %s)", $line)); + } + + foreach ($lines as $no => $code) { + $output->writeln(sprintf( + "%s %-6s %s", + $no == $line ? '>>' : ' ', + $no, + $code + )); + if ($no == $line) { + $output->writeln(sprintf('>> %s ', $exception->getRawMessage())); + } + } + } + + protected function getContext($template, $line, $context = 3) + { + $lines = explode("\n", $template); + + $position = max(0, $line - $context); + $max = min(count($lines), $line - 1 + $context); + + $result = array(); + while ($position < $max) { + $result[$position + 1] = $lines[$position]; + $position++; + } + + return $result; + } +} diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php new file mode 100644 index 0000000000000..da4460ccbe938 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Command; + +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Console\Application; +use Symfony\Bridge\Twig\Command\LintCommand; + +/** + * @covers \Symfony\Bridge\Twig\Command\LintCommand + */ +class LintCommandTest extends \PHPUnit_Framework_TestCase +{ + private $files; + + public function testLintCorrectFile() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile('{{ foo }}'); + + $ret = $tester->execute(array('filename' => $filename)); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertRegExp('/^OK in /', $tester->getDisplay()); + } + + public function testLintIncorrectFile() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile('{{ foo'); + + $ret = $tester->execute(array('filename' => $filename)); + + $this->assertEquals(1, $ret, 'Returns 1 in case of error'); + $this->assertRegExp('/^KO in /', $tester->getDisplay()); + } + + /** + * @expectedException \RuntimeException + */ + public function testLintFileNotReadable() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile(''); + unlink($filename); + + $ret = $tester->execute(array('filename' => $filename)); + } + + /** + * @return CommandTester + */ + private function createCommandTester() + { + $twig = new \Twig_Environment(new \Twig_Loader_Filesystem()); + + $command = new LintCommand(); + $command->setTwigEnvironment($twig); + + $application = new Application(); + $application->add($command); + $command = $application->find('twig:lint'); + + return new CommandTester($command); + } + + /** + * @return string Path to the new file + */ + private function createFile($content) + { + $filename = tempnam(sys_get_temp_dir(), 'sf-'); + file_put_contents($filename, $content); + + $this->files[] = $filename; + + return $filename; + } + + public function setUp() + { + $this->files = array(); + } + + public function tearDown() + { + foreach ($this->files as $file) { + if (file_exists($file)) { + unlink($file); + } + } + } +} diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index ea3fb7cde5b9f..02e98c3ccd5c7 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -28,7 +28,8 @@ "symfony/translation": "~2.2", "symfony/yaml": "~2.0", "symfony/security": "~2.4", - "symfony/stopwatch": "~2.2" + "symfony/stopwatch": "~2.2", + "symfony/console": "~2.2" }, "suggest": { "symfony/form": "For using the FormExtension", diff --git a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php index aa01ce6e7b0aa..79a765d768e5f 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php @@ -11,141 +11,69 @@ namespace Symfony\Bundle\TwigBundle\Command; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Bridge\Twig\Command\LintCommand as BaseLintCommand; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Finder\Finder; /** * Command that will validate your template syntax and output encountered errors. * * @author Marc Weistroff + * @author Jérôme Tamarelle */ -class LintCommand extends ContainerAwareCommand +class LintCommand extends BaseLintCommand implements ContainerAwareInterface { - protected function configure() + /** + * @var ContainerInterface|null + */ + private $container; + + /** + * {@inheritdoc} + */ + public function setContainer(ContainerInterface $container = null) { - $this - ->setName('twig:lint') - ->setDescription('Lints a template and outputs encountered errors') - ->addArgument('filename') - ->setHelp(<<%command.name% command lints a template and outputs to stdout -the first encountered syntax error. + $this->container = $container; + } -php %command.full_name% filename + /** + * {@inheritdoc} + */ + protected function getTwigEnvironment() + { + return $this->container->get('twig'); + } -The command gets the contents of filename and validates its syntax. + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); -php %command.full_name% dirname + $this + ->setHelp( + $this->getHelp().<<dirname and validates the syntax -of each Twig template. php %command.full_name% @AcmeMyBundle The command finds all twig templates in the AcmeMyBundle bundle and validates the syntax of each Twig template. - -cat filename | php %command.full_name% - -The command gets the template contents from stdin and validates its syntax. EOF ) ; } - protected function execute(InputInterface $input, OutputInterface $output) + protected function findFiles($filename) { - $twig = $this->getContainer()->get('twig'); - $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."); - } - - while (!feof(STDIN)) { - $template .= fread(STDIN, 1024); - } - - return $this->validateTemplate($twig, $output, $template); - } - - if (0 !== strpos($filename, '@') && !is_readable($filename)) { - throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); - } - - $files = array(); - if (is_file($filename)) { - $files = array($filename); - } elseif (is_dir($filename)) { - $files = Finder::create()->files()->in($filename)->name('*.twig'); - } else { + if (0 === strpos($filename, '@')) { $dir = $this->getApplication()->getKernel()->locateResource($filename); - $files = Finder::create()->files()->in($dir)->name('*.twig'); - } - - $errors = 0; - foreach ($files as $file) { - $errors += $this->validateTemplate($twig, $output, file_get_contents($file), $file); - } - - return $errors > 0 ? 1 : 0; - } - - protected function validateTemplate(\Twig_Environment $twig, OutputInterface $output, $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 1; - } - - return 0; - } - - protected 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)); - } else { - $output->writeln(sprintf("KO (line %s)", $line)); - } - - foreach ($lines as $no => $code) { - $output->writeln(sprintf( - "%s %-6s %s", - $no == $line ? '>>' : ' ', - $no, - $code - )); - if ($no == $line) { - $output->writeln(sprintf('>> %s ', $exception->getRawMessage())); - } - } - } - - protected function getContext($template, $line, $context = 3) - { - $lines = explode("\n", $template); - - $position = max(0, $line - $context); - $max = min(count($lines), $line - 1 + $context); - $result = array(); - while ($position < $max) { - $result[$position + 1] = $lines[$position]; - $position++; + return Finder::create()->files()->in($dir)->name('*.twig'); } - return $result; + return parent::findFiles($filename); } } diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 83b8285d5674c..88d866989ad20 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.3", - "symfony/twig-bridge": "~2.2", + "symfony/twig-bridge": "~2.5", "symfony/http-kernel": "~2.1" }, "require-dev": { 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