Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[Twig] Decouple Twig commands from the Famework #9855

Closed
wants to merge 12 commits into from

9 participants

Jérôme Tamarelle Luis Cordova Guillermo González de Agüero Fabien Potencier Rouven Weßling Wouter J Joseph Bielawski Grégoire Pineau Christophe Coevoet
Jérôme Tamarelle

I want to use the command twig:lint in a Silex project.

In this PR, I've moved the class Symfony\Bundle\TwigBundle\Command\LintCommand to Symfony\Bridge\Twig\Command\LintCommand and removed dependency to the ContainerAwareCommand.

Q A
Bug fix? no
New feature? yes
BC breaks? yes (renamed class)
Deprecations? no
Tests pass? yes
Fixed tickets #9818 (comment)
License MIT
Doc PR n/a
  • Move command twig:debug once merged.
  • Lazy load twig service
src/Symfony/Bridge/Twig/Command/LintCommand.php
((21 lines not shown))
{
+ private $twig;
+
+ /**
+ * Constructor for dependency injection.
+ *
+ * @param \Twig_Environment $twig

why not just Twig_Environment or is the \ also needed here?

Christophe Coevoet Collaborator
stof added a note

If you remove the \, it becomes a relative class name, and you need to add a use statement for it. and Symfony does not add use statements for classes of the global namespace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Luis Cordova

nice, great move decoupling ftw! :+1:

src/Symfony/Bridge/Twig/Command/LintCommand.php
@@ -148,4 +163,12 @@ protected function getContext($template, $line, $context = 3)
return $result;
}
+
+ /**
+ * @return \Twig_Environment
+ */
+ protected function getTwig()
Christophe Coevoet Collaborator
stof added a note

You don't need this getter IMO

Jérôme Tamarelle
GromNaN added a note

My idea is that someone can extend the command class to customize how the twig instance is located.

Wouter J
WouterJ added a note

then you should make $this->twig protected and remove this getter, following the Symfony standards

Christophe Coevoet Collaborator
stof added a note

And I don't even think it make sense. Someone extending the command will still need to call the parent constructor, and so would still need to inject twig through the constructor

Jérôme Tamarelle
GromNaN added a note

Method removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bridge/Twig/Command/LintCommand.php
@@ -57,7 +72,7 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
- $twig = $this->getContainer()->get('twig');
+ $twig = $this->getTwig();
Joseph Bielawski
stloyd added a note

This is not needed anymore as you have class variable $this->twig.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bundle/TwigBundle/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+2.5.0
+-----
+
+ * moved `LintCommand` to the Twig bridge and register it as a service
Wouter J
WouterJ added a note

and registered it as a service

Jérôme Tamarelle
GromNaN added a note

Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Wouter J WouterJ commented on the diff
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",
Wouter J
WouterJ added a note

isn't this a BC break, as we can't use the bundle with symfony 2.2 anymore? (which could before this PR)

Christophe Coevoet Collaborator
stof added a note

This is not a BC break IMO. If you have the fullstack 2.2, you cannot use TwigBundle 2.5 anyway (as TwigBundle is part of the fullstack).
And if you use them standalone, composer will forbid you to upgrade to TwigBundle 2.5 without upgrading Twig-bridge as well, but this is part of the dependency resolution. If you try to do the job of composer manually, you are asking for pain anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jérôme Tamarelle

In addition, I've just added tests for the command.

Guillermo González de Agüero

I think you should add a note on the changelog about the BC break.

src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
@@ -131,5 +132,10 @@
<argument type="service" id="twig" />
<argument>%kernel.debug%</argument>
</service>
+
+ <service id="twig.command.lint" class="%twig.command.lint.class%">
+ <tag name="console.command" />
Grégoire Pineau
lyrixx added a note

Happy to see this feature used.
But two little questions: did you try this in a symfony2 project ? And does this make the application slower ?
Because in SF2 project, twig depends of lot of things (like security...).

Christophe Coevoet Collaborator
stof added a note

This is actually an issue with the commands defined as service (introduced in 2.4): commands are not loaded lazily, so all their dependency graph is instantiated for any unrelated console call

Grégoire Pineau
lyrixx added a note

It would be better if the getDefinition method was static.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bridge/Twig/Command/LintCommand.php
((21 lines not shown))
{
+ private $twig;
+
+ /**
+ * Constructor for dependency injection.
Fabien Potencier Owner
fabpot added a note

should be changed to just Constructor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Fabien Potencier
Owner

This one cannot be merged before we find a solution for lazy-loading console command as services.

Rouven Weßling

Couldn't this be done by moving it to the bridge as an abstract class with an abstract method getTwigEnvironment? This would mean no change for Symfony2 but make it easier reusable outside of it.

Fabien Potencier
Owner

Whatever we decide to do here should be done also in #9855

src/Symfony/Bridge/Twig/Command/LintCommand.php
((21 lines not shown))
{
+ private $twig;
+
+ /**
+ * Constructor for dependency injection.
+ *
+ * @param \Twig_Environment $twig
+ */
+ public function __construct(\Twig_Environment $twig)

Please allow passing the name trough, sometime one wants to rename a command for consistency.

Jérôme Tamarelle
GromNaN added a note

Actually, it's not possible to set a name in the constructor as it will be overwritten by the method configure(). The only solution is to set the command name explicitly with setName().

Wouter J
WouterJ added a note

It's very easy to implement: just add a $name parameter here with the standard name as default and pass it to parent::__construct(). After that, remove it from configure

Wouter J
WouterJ added a note

could you please also add this feature?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Wouter J

@fabbot I think something did go wrong, you linked to the same PR...

And I think this can be solved by overriding this command in the TwigBundle:

namespace Symfony\Bundle\TwigBundle\Command;

use Symfony\Bridge\Twig\Command\LintCommand as BaseLintCommand;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class LintCommand extends BaseLintCommand implements ContainerAwareInterface
{
    protected $container;

    public function __construct()
    {
        // override constructor to not set the twig environment yet
        parent::__construct(new \Twig_Environment());
    }

    public function setContainer(ContainerInterface $container)
    {
        $this->container = $container;
        $this->twig = $container->get('twig');
    }
}

This requires the twig property to be protected though. Or we can use the getTwig method to retrieve the environment and override that.

Then we can investigate more time into lazy loading service commands and after that, we can remove this "hack".

Jérôme Tamarelle

Seeing that using "commands as services" requires initializing a deep dependency tree each time the application is run, I can't find a solution to lazy-inject the twig service into the command.

So, I think that's better not using the "commands as a service" feature; even if this is a very brilliant approach. In my last commit, I've followed the suggestions from @realityking and @WouterJ and I've created a class in the bundle that extends the class in the bridge and retrieve the service from the container.

src/Symfony/Bridge/Twig/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+2.5.0
+-----
+
+ * added command `twig:lint` from `TwigBundle`
Fabien Potencier Owner
fabpot added a note

I would say moved instead of added

Jérôme Tamarelle
GromNaN added a note

Changed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bundle/TwigBundle/Command/LintCommand.php
((86 lines not shown))
- $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)
+ /**
+ * @var ContainerInterface|null
+ */
+ private $container;
+
+ /**
+ * @return ContainerInterface
+ */
+ protected function getContainer()
Fabien Potencier Owner
fabpot added a note

I would inline this method in the getTwigEnvironment one.

Jérôme Tamarelle
GromNaN added a note

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Fabien Potencier
Owner

... and tests are broken.

src/Symfony/Bundle/TwigBundle/Command/LintCommand.php
((141 lines not shown))
- }
- }
-
- 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++;
+ if (null === $this->container) {
+ $this->container = $this->getApplication()->getKernel()->getContainer();
Wouter J
WouterJ added a note

Afaik, container can't be null,as it's set by setContainer during initialization?

Jérôme Tamarelle
GromNaN added a note

Exact, I took that portion of code from ContainerAwareCommand; but it looks like a legacy fallback.
I've removed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jérôme Tamarelle

@fabpot everything as been fixed.

Rouven Weßling realityking commented on the diff
src/Symfony/Bridge/Twig/Command/LintCommand.php
((35 lines not shown))
+ }
+
+ /**
+ * Sets the twig environment
+ *
+ * @param \Twig_Environment $twig
+ */
+ public function setTwigEnvironment(\Twig_Environment $twig)
+ {
+ $this->twig = $twig;
+ }
+
+ /**
+ * @return \Twig_Environment $twig
+ */
+ protected function getTwigEnvironment()

I'd make this abstract and remove the setter. This would prevent making the setter non-functioning in the Bundle Command.

Jérôme Tamarelle
GromNaN added a note

As a developer, I don't want to be forced to create a class to use this command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bridge/Twig/Command/LintCommand.php
((101 lines not shown))
+ 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');
+ } elseif ($this->getApplication() instanceof FrameworkBundleApplication) {
+ $dir = $this->getApplication()->getKernel()->locateResource($filename);
+ $files = Finder::create()->files()->in($dir)->name('*.twig');
+ }

IMO this block should be moved to a method too, the last only needs to be done in Bundle command, the rest in the Bridge command.

Wouter J
WouterJ added a note

yes, indeed. The Bridge command should throw an exception and the bundle should then try to find the resource using the application

Doesn't even need to be an exception. The extended command can just check wether the result is empty and if that's the case do the final check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bridge/Twig/Command/LintCommand.php
((60 lines not shown))
+ ->setHelp(<<<EOF
+The <info>%command.name%</info> command lints a template and outputs to stdout
+the first encountered syntax error.
+
+<info>php %command.full_name% filename</info>
+
+The command gets the contents of <comment>filename</comment> and validates its syntax.
+
+<info>php %command.full_name% dirname</info>
+
+The command finds all twig templates in <comment>dirname</comment> and validates the syntax
+of each Twig template.
+
+<info>php %command.full_name% @AcmeMyBundle</info>
+
+The command finds all twig templates in the <comment>AcmeMyBundle</comment> bundle and validates

This also won't apply to the command in the Bridge.

Wouter J
WouterJ added a note

+1, the bundle command should do something like:

public function configure()
{
    parent::configure();
    $extraFeature = <<<EOF

<info>php %command.full_name% @AcmeMyBundle</info>

The command finds all twig templates in the <comment>AcmeMyBundle</comment> bundle and validates
the syntax of each Twig template.
EOF
    ;
    $this->setHelp($this->getHelp.$extraFeature);
}
Jérôme Tamarelle
GromNaN added a note

Done. GromNaN@c244b14
Thanks for the review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/Symfony/Bundle/TwigBundle/Command/LintCommand.php
((40 lines not shown))
-<info>php %command.full_name% filename</info>
+ /**
+ * {@inheritdoc}
+ */
+ public function getTwigEnvironment()
Fabien Potencier Owner
fabpot added a note

This should be protected like the one in the Bridge.

Jérôme Tamarelle
GromNaN added a note

Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Luis Cordova cordoval commented on the diff
src/Symfony/Bridge/Twig/Command/LintCommand.php
((7 lines not shown))
+ *
+ * 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 <marc.weistroff@sensiolabs.com>

are you sure this is you @GromNaN ?

Jérôme Tamarelle
GromNaN added a note

The original command has been written by @marcw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Fabien Potencier fabpot referenced this pull request from a commit
Fabien Potencier fabpot feature #9855 [Twig] Decouple Twig commands from the Famework (GromNaN)
This PR was squashed before being merged into the 2.5-dev branch (closes #9855).

Discussion
----------

[Twig] Decouple Twig commands from the Famework

I want to use the command `twig:lint` in a Silex project.

In this PR, I've moved the class `Symfony\Bundle\TwigBundle\Command\LintCommand` to `Symfony\Bridge\Twig\Command\LintCommand` and removed dependency to the `ContainerAwareCommand`.

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | yes (renamed class)
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9818 (comment)
| License       | MIT
| Doc PR        | n/a

 - [ ] Move command `twig:debug` once merged.
 - [x] Lazy load twig service

Commits
-------

907748d [Twig] Decouple Twig commands from the Famework
702e2a4
Fabien Potencier fabpot closed this pull request from a commit
Fabien Potencier fabpot feature #9855 [Twig] Decouple Twig commands from the Famework (GromNaN)
This PR was squashed before being merged into the 2.5-dev branch (closes #9855).

Discussion
----------

[Twig] Decouple Twig commands from the Famework

I want to use the command `twig:lint` in a Silex project.

In this PR, I've moved the class `Symfony\Bundle\TwigBundle\Command\LintCommand` to `Symfony\Bridge\Twig\Command\LintCommand` and removed dependency to the `ContainerAwareCommand`.

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | yes (renamed class)
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9818 (comment)
| License       | MIT
| Doc PR        | n/a

 - [ ] Move command `twig:debug` once merged.
 - [x] Lazy load twig service

Commits
-------

907748d [Twig] Decouple Twig commands from the Famework
702e2a4
Fabien Potencier fabpot closed this in 702e2a4
Jérôme Tamarelle GromNaN deleted the branch
Jérôme Tamarelle GromNaN referenced this pull request
Closed

[WIP][Console] Add ContainerAwareCommand #10087

0 of 1 task complete
Fabien Potencier fabpot referenced this pull request from a commit
Fabien Potencier fabpot minor #10571 [Form] Fixed infinite tests when ICU is available (webmo…
…zart)

This PR was submitted for the master branch but it was merged into the 2.4 branch instead (closes #10571).

Discussion
----------

[Form] Fixed infinite tests when ICU is available

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Commits
-------

61773de [Form] Fixed infinite tests when ICU is available
3cd1c9c bug #10565 fixed typos (fabpot)
584b5c0 fixed typos
4a0382b fixed CS
9e78a06 Merge branch '2.4'
b78d174 minor #10554 framework_bundle -> framework (mvrhov)
85cf7a7 framework_bundle -> framework
e505ecd feature #10370 [FrameworkBundle][Console] Add parameter descriptors (inalgnu)
6aa1050 Add parameter descriptors
4a06daf feature #9818 [TwigBundle] Add command to list twig functions, filters, globals and tests (Seldaek)
7d61154 Add command to list twig functions, filters, globals and tests
caabd41 feature #10546 [Validator] Improved ISBN validator (sprain)
ec42844 Improved ISBN validator
711788b fixed CS
cb147ec feature #10457 [Serializer] Unify usage of normalizer cache (Berdir)
e7389aa Move normalizer cache to getNormalier()/getDenormalizer(), use those in normalizeObject()/denormalizeObject()
5a4885e feature #9140 [Validator][Email] - Strict validation and soft dependency (egulias)
3368630 #1581 - Strict in Email constraint and use of Egulias\EmailValidator
e0de958 Merge branch '2.4'
830ab24 minor #10527 [HttpKernel] [Exception] Add UnprocessableEntityHttpException to HttpKernel Exceptions (steveYeah)
304cbe9 Add UnprocessableEntityHttpException to HttpKernel Exceptions
3ab2dd7 feature #10291 [Validator] New validator for UUIDs (colinodell)
19931c9 Added new validator for UUIDs
790ba4c feature #10534 [SwiftMailer] [MonologBundle] send error log mails from CLI (arodiss)
9bb602f added explicit swiftmailer flush after ConsoleEvents::TERMINATE
9dc14a5 feature #10513 [Bridge][Propel1][Form] Model choice accept custom unique column (cedriclombardot)
81e94d0 Model choice accept custom unique column
3b95d09 bug #10535 [Form] Fixed tests after merging pattern deprecation (stefanosala)
e2d8944 Fixed tests after merging pattern deprecation
58bdf84 Merge branch '2.4'
3baa43b Merge branch '2.4'
9e13cc0 feature #9178 made HttpFoundationRequestHandler a service (kor3k)
43451e9 made HttpFoundationRequestHandler a service
feea36d feature #10001 [Form] Deprecated max_length and pattern options (stefanosala)
52c07c7 Deprecated max_length and pattern options
37d484c bug #10530 [Process] Do not show output in FailedException if it was disabled (Taluu)
849703a When a process fails, check if the output is enabled
d6fccdd feature #9690 Using Oracle Database as ACL storage (skolodyazhnyy)
5f3be0e Fix Exception messages for ObjectIdentity ObjectIdentityInterface doesn't require implementing __toString method, so we need to make sure that object can be converted to string.
f66bed7 feature #10506 [Debug] sync with deprecation in DebugClassLoader (nicolas-grekas)
ad88cdd feature #10509 [FrameworkBundle] add scheme option to router:match command (Tobion)
e3f17f9 add scheme option to router:match command
c70a468 [Debug] sync with deprecation in DebugClassLoader
6586eaa feature #10194 [Console] Added standalone PSR-3 compliant logger (dunglas)
e40b34d [Console] Added standalone PSR-3 compliant logger
53fec31 feature #9097 [Validator] Added hasser support for entity method validation (bicpi)
e8b6978 [Validator] Added hasser support for entity method validation
b14fa26 feature #10476 [Console] Fixed unsetting of setted attributes on OutputFormatterStyle (Badkill)
ce0c4b4 [Console] Fixed unsetting of setted attributes on OutputFormatterStyle
8170db8 feature #10473 [WebProfilerBundle] enhance logs display (nicolas-grekas)
6deb4cc minor #10474 [Console] Rename Command::setProcessName to Command::setProcessTitle (lyrixx)
3e6c940 [WebProfilerBundle] enhance logs display
6786f6d [Console] Rename Command::setProcessName to Command::setProcessTitle
71dc07c feature #10466 [Debug] add a screaming mode to ErrorHandler (nicolas-grekas)
c152ccb minor #10469 fix doc block and namespace by @insekticide (cordoval)
5cc817d [Debug] add a screaming mode to ErrorHandler
89bde6e fix class namespace by @insekticid and doc block fix
48c9985 feature #10451 [TwigBundle] Add possibility to generate absolute assets urls (romainneutron)
a635c4f bug #10456 [Process] Handle idle timeout and disabled output conflict (romainneutron)
ae84810 [Process] Increase tests speed
40c08c6 [Process] Handle idle timeout and disable output conflict
76b8851 [TwigBundle] Add possibility to generate absolute assets urls
1e973b2 feature #10404 [Security] Match request based on HTTP methods in firewall config (danez)
a8e9ed5 Make it possible to match the request based on HTTP methods in the firewall configuration
f0c0c2c tweaked sentence
120a7e9 bug #10443 [FrameworkBundle] Use DIC parameter as default host value if available (romainneutron)
85a2fbf [FrameworkBundle] Use DIC parameter as default host value if available
b7c158a feature #10439 [FrameworkBundle] Add posibility to specify method and host in router:match command (romainneutron)
acc66b9 [FrameworkBundle] Add posibility to specify method and host in router:match command
c14d67c [SecurityBundle] changed a hardcoded string to its constant equivalent
ea0598a minor #10390 [Security] Add constants for access decision strategies (c960657)
1e0fea6 minor #10432 clean up framework bundle commands (cordoval)
0984313 clean up commands from framework bundle
5e0bb71 feature #10425 [Process] Add Process::disableOutput and Process::enableOutput methods (romainneutron)
a891e14 [Process] Add Process::disableOutput and Process::enableOutput methods
c2d4be1 feature #10418 [Form] Removed "magic" from FormErrorIterator (webmozart)
daac66e [Form] Removed "magic" from FormErrorIterator
5b07e0a feature #10414 [Validator] Checked the constraint class in constraint validators (webmozart)
ce81199 feature #9918 [Form] Changed Form::getErrors() to return an iterator and added two optional parameters $deep and $flatten (webmozart)
df56c23 [Validator] Checked the constraint class in constraint validators
5d6ef00 Add class constants for access decision strategies.
f15ea50 minor #10376 [Component][Serializer] Add fluent interface to GetSetMethodNormalizer (alexsegura)
2d42533 [Component][Serializer] Add fluent interface to GetSetMethodNormalizer
bc38d76 minor #10366 [FrameworkBundle] set a default value for gc_probability (fabpot)
1948d36 Merge branch '2.4'
f6bc83f minor #10373 added the BC docs to the contributing file (fabpot)
2f9432a added the BC docs to the contributing file
69d2c8e Merge branch '2.4'
e778cf1 fixed previous merge
0aeb394 feature #9739 [FrameworkBundle] Extract KernelTestCase from WebTestCase (johnkary)
4d31d2f fixed CS
c4b8e03 feature #9852 [Translation] Added template for relative file paths in FileDumper (florianv)
786c956 feature #10368 [FrameworkBundle] Added a translation:debug command (fabpot)
f039bde [FrameworkBundle] fixed edge cases for translation:debug and tweaked the output
5ea6437 [FrameworkBundle] refactored the built-in web server
a04175e Changed placeholders
623d149 Added a ConcreteDumper
84f0902 [Translation] Added template for relative file paths
887e6ff feature #10017 [FrameworkBundle] Add HHVM support for built-in web server (RickySu)
66798ba [FrameworkBundle] Add HHVM support for built-in web server
597a310 Added a translation:debug command
2a15923 feature #10100 [ClassLoader] A PSR-4 compatible class loader (derrabus)
6837df3 [ClassLoader] A PSR-4 compatible class loader
725f7ab bug #10367 [HttpKernel] fixed serialization of the request data collector (fabpot)
4a1639a feature #10314 [Serializer] added support for is.* methods in GetSetMethodNormalizer (tiraeth)
480219f [Serializer] added support for is.* methods in GetSetMethodNormalizer
6102f99 [HttpKernel] fixed serialization of the request data collector
98c3fe7 feature #10365 [Console] deprecated TableHelper in favor of Table (fabpot)
7e1bdd7 [FrameworkBundle] set a default value for gc_probability
21784ce [Console] make it possible to pass a style directly to Table::setStyle()
14caaec [Console] added the possibility to insert a table separator anywhere in a table output
39c495f [Console] deprecated TableHelper in favor of Table
77bfac7 Merge branch '2.4'
aed7eab [Console] fixed some initializations in the ProgressBar class
554b28d feature #10356 [Console] A better progress bar (fabpot)
0d1a58c [Console] made formats even more flexible
8c0022b [Console] fixed progress bar when using ANSI colors and Emojis
38f7a6f [Console] fixed PHP comptability
244d3b8 [Console] added a way to globally add a progress bar format or modify a built-in one
a9d47eb [Console] added a way to add a custom message on a progress bar
7a30e50 [Console] added support for multiline formats in ProgressBar
1aa7b8c [Console] added more default placeholder formatters for the progress bar
2a78a09 [Console] refactored the progress bar to allow placeholder to be extensible
4e76aa3 [Console] added ProgressBar (to replace the stateful ProgressHelper class)
65c9aca feature #10352 [DataCollector] Improves the readability of the collected arrays in the profiler (fabpot)
dce66c9 removed double-stringification of values in the profiler
eede330 feature #10354 removed as many usage of the request service as possible without breaking BC (fabpot)
d638369 removed as many usage of the request service as possible without breaking BC
681f14b feature #10353 [Debug] ExceptionHandlerInterface to allow third party exception handlers to handle fatal errors caught by ErrorHandler (FineWolf)
15d063b Create ExceptionHandlerInterface to allow third party exception handlers' to handle fatal errors
1cda2d4 [HttpKernel] tweaked value exporter
3f297ea Improves the readability of the collected arrays in the profiler.
7baeaa2 Merge branch '2.4'
a820930 bug #10308 [Debug] enhance non-PSR-0 compatibility for case mismatch test (nicolas-grekas)
ca4736b [Console] fixed missing abstract keyword
537f1fa minor #10315 Fix typo in method name (fixe)
9c582d9 minor #10320 Fix typo in UPGRADE-3.0.md (hice3000)
53c8189 Fix typo in UPGRADE-3.0.md
120e197 [Debug] enhance non-PSR-0 compatibility for case mismatch test
01858d3 Fixed typo in method name
872647a [Security] simplified code
6d926c8 minor #10311 use core StringUtils to compare hashes (steelywing)
9fc01d2 use core StringUtils to compare hashes
79baf8d feature #10165 [FrameworkBundle] config:dump-reference command can now dump current configuration (lyrixx)
aca3271 feature #9862 [FrameworkBundle] Added configuration for additionnal request formats (gquemener)
f90ba11 [FrameworkBundle] Added configuration for additionnal request formats
6e9358a feature #10257 [FrameworkBundle][Console] Load command from DIC after command from bundles. (lyrixx)
3e8f33a feature #10201 [Debug] error stacking + fatal screaming + case testing (nicolas-grekas)
838dc7e Merge branch '2.4'
5a5eb50 Merge branch '2.4'
6de362b [Debug] error stacking+fatal screaming+case testing
19a368e [FramworkBundle] Added config:debug command
34f4ef5 [FrameworkBundle][Console] Load command from DIC after command from bundles.
f828aee Merge branch '2.4'
d0386e4 minor #10214 [3.0][Console] Added isVerbosity* to OutputInterface (lyrixx)
816b295 [3.0][Console] Added isVerbosity* to OutputInterface
fe86efd feature #10200 [EventDispatcher] simplified code for TraceableEventDispatcher (fabpot)
6dfdb97 feature #10198 [Stopwatch] Allow getting duration of events without calling stop() (jochenvdv)
42e4c7b [EventDispatcher] simplified code for TraceableEventDispatcher
bcb5239 bug #10199 fix ProcessPipes (nicolas-grekas)
076d417 fix ProcessPipes
22970e0 Merge branch '2.4'
2efe461 Allow retrieving unstopped stopwatch events
d3d097d Include running periods in duration
bea1537 minor #10186 Made some HHVM-related fixes (fabpot)
4c9e307 Merge branch '2.4'
1e89880 Revert "minor #10160 [Translation] [Loader] Add INI_SCANNER_RAW to parse ini files (TeLiXj)"
1240758 [Routing] fixed CS
e223395 [Debug] fixed case differences between PHP and HHVM (classes are case-insensitive anyway in PHP)
23acc24 [Debug] made order of suggestions predictable in error messages
10d4d56 removed unneded test groups
51d3d62 feature #8655 Adds PTY mode & convenience method mustRun() (schmittjoh)
7affb71 minor #10172 [WebProfilerBundle] Use inline images instead of asset() in form-panel (Danez)
12eabd8 remove unused icons
7c3a3e1 minor #10160 [Translation] [Loader] Add INI_SCANNER_RAW to parse ini files (TeLiXj)
f259157 Further compress icon
eb6d02c Use inline images instead of asset() function
5ef60f1 [Translation] [Loader] Add INI_SCANNER_RAW to parse ini files
d61f492 minor #10149 Fixed grammar in Hungarian translations (r1pp3rj4ck)
7f74049 Fixed grammar in Hungarian translations
6a0de7f Merge branch '2.4'
774674e feature #10112 [Routing] Add createRoute method for AnnotationClassLoader (henrikbjorn)
4e137cc feature #10064 [TwigBridge] Added support for json format in twig:lint command (lyrixx)
2e2a65c Merge branch '2.4'
78d49fb minor #10081 [FrameworkBundle] Pretty Ppint json ouput of yaml:lint command (lyrixx)
97404b3 Add createRoute method for AnnotationClassLoader
689e9bf [FrameworkBundle] Pretty Ppint json ouput of yaml:lint command
4d2f94a [TwigBridge] Added support for json format in twig:lint command
621f991 [TwigBridge] Cleaned documentation of twig:lint command
4ad343b feature #10005 [Security] Added named encoders to EncoderFactory (tamirvs)
c69e2ca [Security] Added named encoders to EncoderFactory
a207006 minor #9996 [Routing] Added an extension point for globals in AnnotationClassLoader (lyrixx)
e1b85db feature #9405 [FrameworkBundle] Added a helper method to create AccessDeniedException (klaussilveira)
183d0ec [FrameworkBundle] Added a helper method to create AccessDeniedException
7da803f minor #10021 [WebProfilerBundle] Simplified session storage implementation (bschussek)
cec05bf [WebProfilerBundle] Simplified session storage implementation
fff29a3 feature #9967 Form debugger storage (WouterJ)
744da7f Form debugger storage
916420f feature #9980 [Routing][FrameworkBundle] Deprecated the apache dumper (jakzal)
6258cfa [Routing][FrameworkBundle] Deprecated the apache dumper
6b3fbb5 [Form] Changed the default value of $flatten in Form::getErrors() to true
a9268c4 [Form] Changed Form::getErrors() to return an iterator and added two optional parameters $deep and $flatten
8ea3a43 feature #9993 [Form] Errors now reference the field they were added to and the violation/exception that caused them (bschussek)
8f7524e [Routing] Added an extension point for globals in AnnotationClassLoader
c8a0ee6 [Form] Errors now reference the field they were added to and the violation/exception that caused them
147c82b minor #9972 Upgrade File for 2.5 (Danez)
fefcf41 Added upgrade info for #9601
c833518 feature #9776 [Console] Added the possibility to set a different default command (danielcsgomes)
418de05 [Console] Added the possibility to set a different default command
79bea0a feature #9966 added feedback to the cache:clear command (fabpot)
f2261da [FrameworkBundle] simplified code
a1f6411 [FrameworkBundle] added feedback in cache:clear
0af3ca3 Merge branch '2.4'
ef12af9 feature #9963 [HttpFoundation] JsonResponse::setEncodingOptions accepts also integer (stloyd)
f8bc3b2 [HttpFoundation] JsonResponse::setEncodingOptions accepts also integer
74fb207 feature #9915 [HttpFoundation] Add ability to change JSON encoding options (stloyd)
89f4784 [HttpFoundation] Add ability to change JSON encoding options
a596ba3 feature #8375 [OptionsResolver] Allow giving a callback as an allowedValue to OptionsResolver (marekkalnik)
07d1d30 Allow giving a callback as an allowedValue to OptionsResolver
f3670b4 feature #9666 [FrameworkBundle] Added a yaml:lint command (lyrixx)
9c06b27 [FrameworkBundle] Added yaml:lint command
8cd8ec0 Remove usage of deprecated _scheme in Routing Component
6063b49 Merge branch '2.4'
d3b28dc minor #9944 [FrameworkBundle] Update composer.json to account for #9792 (realityking)
f1efd16 [FrameworkBundle] Update composer.json to account for #9792
f499094 minor #9880 test for class route annotation (ewgRa)
60c2140 minor #9931 Removed all codeCoverageIgnore annotations from the code (stof)
ac94ddb test for class route annotation
4248169 Removed all codeCoverageIgnore annotations from the code
2c059ee feature #9926 [Finder] Added GLOB_BRACE support in Finder::in() method (jakzal)
a12db9b Merge branch '2.4'
e2698fc [Finder] Included GLOB_BRACE support in the CHANGELOG.
30814d3 [Finder] Added a test case for the GLOB_BRACE in Finder:in().
da67f5d [Finder] Added GLOB_BRACE support in Finder::in() method
64c7095 removed unneeded use statements
18d69a8 Merge branch '2.4'
df6b0b8 bug #9917 [HttpFoundation] fixed PHP warnings (fabpot)
cf71e22 [HttpFoundation] fixed PHP warnings
410d399 fixed PSR0
0defad9 Merge branch '2.4'
8850456 Merge branch '2.4'
702e2a4 feature #9855 [Twig] Decouple Twig commands from the Famework (GromNaN)
907748d [Twig] Decouple Twig commands from the Famework
3203793 added a missing namespace use statement
28a8400 feature #9251 [WIP] [FrameworkBundle] removed some more dependencies on the request service (fabpot)
9eaed35 feature #9857 Form Debugger JavaScript improvements (WouterJ)
d9bb4ff Reverted Sfjs.toggle change
6aaefd8 Reverted new image
ec2496f Fixed asset function
624a09f Enlarged the clickable area of the toggle button in the form tree
0ff2632 Moved toggle icon behind the headlines in the form debugger
8ba8db2 Changed toggle color back to blue and made headlines in the form debugger clickable
b8358e3 Added "use strict" statements
0936694 Inverted toggler images and improved button coloring
64a3442 Improved JavaScript of the form debugger
0908155 Vertically centered the icons in the form tree
9dc2cde Fixed CS
6eb1e49 Added error badge
b02c227 Made sections collapsable
b223527 Improved form tree
c19ff6f Expand tree
96c4486 minor #9374 Change of scope (djoos)
335bee2 Change of scope
5079f34 feature #9892 [Validator] Added Doctrine cache (florianv)
3c4de45 [Validator] Added Doctrine cache
c15175a Merge branch '2.4'
9fbe148 feature #9590 WebTestCase: Assume relative KERNEL_DIR is relative to phpunit.xml[.dist]? (mpdude)
4f3d502 [FrameworkBundle] removed some more dependencies on the request service
fd5a2d0 Merge branch '2.4'
7d80045 Merge branch '2.4'
f063108 feature #9814 [EventDispatcher] Added TraceableEventDispatcher from HttpKernel (florianv)
9a90e06 [EventDispatcher] Added TraceableEventDispatcher from HttpKernel
0b0c431 feature #9833 [Bridge] [DoctrineExtension] Allow cache drivers that are not an EM's child (FabioBatSilva)
f0d9af0 feature #9876 [Serializer] error handling inconsistencies fixed in the serializer decoders (fabpot)
a1ab939 [Serializer] fixed CS
6d9f0be Json encoder classes now throws UnexpectedValueException as XML classes
f9dff06 Merge branch '2.4'
f132197 feature #9360 [Finder] Fix finder date constraints and tests (ruian)
c6b1c74 feature #9837 [Form] added getter to transformer chain (cordoval)
7a9ab2c feature #8305 Added MutableAclProvider::deleteSecurityIdentity (lavoiesl)
a4d423e minor #8423 Update LocaleTest.php (mikemeier)
572126b Update LocaleTest.php
694bd72 Merge branch '2.4'
6a51831 feature #9846 [Console] hide output of ProgressHelper when isDecorated is false (kbond)
006cb81 [Console] show no output in ProgressHelper when isDecorated is false (fixes #9511)
8d39213 feature #8650 [Security][Acl] Add MutableAclProvider::updateUserSecurityIdentity (lemoinem)
2b7af12 feature #9843 [PropertyAccess] Allowed non alphanumeric chars in object properties (florianv)
20d4eb6 [PropertyAccess] Allowed non alphanumeric chars in object properties
da53d92 [Security][Acl] Fix #5787 : Add MutableAclProvider::updateUserSecurityIdentity
3565d96 added getter to transformer chain
c4f14fb Extract new base test class KernelTestClass
7528e4c Allow cache drivers that are not an EM's child
c0e4c4a bug #9816 [DependencyInjection] fixes #9815 Syntax error in PHP dumper (realityking)
e00b0f3 [DependencyInjection] fixes #9815 Syntax error in PHP dumper
baaf9b6 feature #9792 [EventDispatcher][HttpKernel] Move RegisterListenersPass from HttpKernel to EventDispatcher. (realityking)
89b8e0a [EventDispatcher][HttpKernel] Move RegisterListenersPass from HttpKernel to EventDispatcher.
ad4d6f7 feature #9668 [DepdencyInjection] forgot to add definition of dumped container member variable parameters (cordoval)
5b02d3f [DepdencyInjection] forgot to add definition of dumped container member variable parameters
8b08888 bug #9812 [DependencyInjection] fix a regression introduced in #9807 (realityking)
0d78776 [DependencyInjection] fix a regression introduced in #9807
11434de minor #9802 [HttpKernel] Remove FrameworkBundle dependency in BundleTest (florianv)
0604220 feature #9780 [Console] Added a way to set the process title (lyrixx)
20a064f [HttpKernel] Remove FrameworkBundle dependency in BundleTest
375a2c7 minor #9807 [DependencyInjection] Avoid call_user_func in dumped containers. (realityking)
be1eaaa [DependencyInjection] Avoid call_user_func in dumped containers.
204a25e [Console] Added a way to set the process title
67ae8fa feature #8224 [Form][2.4] added an option for multiple files upload (closes #1400) (bamarni)
c8c6448 [Form][2.4] added an option for multiple files upload (closes #1400)
c1051d5 fixed CS
e660bc9 feature #9773 [Form] Added delete_empty option to allow proper emptyData handling of collections (peterrehm)
8bdb7a0 [Form] Added delete_empty option to allow proper emptyData handling of collections
21ecad1 minor #9723 [Security] [Acl] [MaskBuilder] Refactor common code and reduce nesting (djlambert)
c0a7e1b feature #9791 [DependencyInjection] added support for inlining Configurators (realityking)
4e9aa07 [DependencyInjection] added support for inlining Configurators
8e1f854 feature #9779 [Debug] Added UndefinedMethodFatalErrorHandler (lyrixx)
74d13e3 [Debug] Added UndefinedMethodFatalErrorHandler
6764f91 Merge branch '2.4'
de57903 Merge branch '2.4'
7d85809 Refactor common code and reduce nesting
5e37fc8 Revert "encourage the running of coverage"
bb73852 encourage the running of coverage
e5362c1 Merge branch '2.4'
db4f551 Merge branch '2.4'
ce64435 minor #9594 [Security] Fixed typos/CS/PHPDoc (pborreli)
1fcc7c5 Merge branch '2.4'
05dc0e1 Consider KERNEL_DIR setting as relative to the PhpUnit XML file if it does not point to a directory (relative to the current cwd)
4aab341 updated version to 2.5
e1110de Fixed typos/CS/PHPDoc
4ccafa6 Fix finder date constraints and tests
dbd264a adds cache for isPtySupported()
6c11207 attempts to fix tests on Travis
2ff1870 adds convenience method mustRun
53441aa adds support for PTY mode
bdbbe58 [Security][Acl] Issue #5787 : Added MutableAclProvider::deleteSecurityIdentity
7cc8e7a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
5 src/Symfony/Bridge/Twig/CHANGELOG.md
View
@@ -1,6 +1,11 @@
CHANGELOG
=========
+2.5.0
+-----
+
+ * moved command `twig:lint` from `TwigBundle`
+
2.4.0
-----
173 src/Symfony/Bridge/Twig/Command/LintCommand.php
View
@@ -0,0 +1,173 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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 <marc.weistroff@sensiolabs.com>

are you sure this is you @GromNaN ?

Jérôme Tamarelle
GromNaN added a note

The original command has been written by @marcw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ * @author Jérôme Tamarelle <jerome@tamarelle.net>
+ */
+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()

I'd make this abstract and remove the setter. This would prevent making the setter non-functioning in the Bundle Command.

Jérôme Tamarelle
GromNaN added a note

As a developer, I don't want to be forced to create a class to use this command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ {
+ return $this->twig;
+ }
+
+ protected function configure()
+ {
+ $this
+ ->setDescription('Lints a template and outputs encountered errors')
+ ->addArgument('filename')
+ ->setHelp(<<<EOF
+The <info>%command.name%</info> command lints a template and outputs to stdout
+the first encountered syntax error.
+
+<info>php %command.full_name% filename</info>
+
+The command gets the contents of <comment>filename</comment> and validates its syntax.
+
+<info>php %command.full_name% dirname</info>
+
+The command finds all twig templates in <comment>dirname</comment> and validates the syntax
+of each Twig template.
+
+<info>cat filename | php %command.full_name%</info>
+
+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('<info>OK</info>'.($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("<error>KO</error> in %s (line %s)", $file, $line));
+ } else {
+ $output->writeln(sprintf("<error>KO</error> (line %s)", $line));
+ }
+
+ foreach ($lines as $no => $code) {
+ $output->writeln(sprintf(
+ "%s %-6s %s",
+ $no == $line ? '<error>>></error>' : ' ',
+ $no,
+ $code
+ ));
+ if ($no == $line) {
+ $output->writeln(sprintf('<error>>> %s</error> ', $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;
+ }
+}
102 src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php
View
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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);
+ }
+ }
+ }
+}
3  src/Symfony/Bridge/Twig/composer.json
View
@@ -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",
144 src/Symfony/Bundle/TwigBundle/Command/LintCommand.php
View
@@ -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 <marc.weistroff@sensiolabs.com>
+ * @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
-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(<<<EOF
-The <info>%command.name%</info> command lints a template and outputs to stdout
-the first encountered syntax error.
+ $this->container = $container;
+ }
-<info>php %command.full_name% filename</info>
+ /**
+ * {@inheritdoc}
+ */
+ protected function getTwigEnvironment()
+ {
+ return $this->container->get('twig');
+ }
-The command gets the contents of <comment>filename</comment> and validates its syntax.
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ parent::configure();
-<info>php %command.full_name% dirname</info>
+ $this
+ ->setHelp(
+ $this->getHelp().<<<EOF
-The command finds all twig templates in <comment>dirname</comment> and validates the syntax
-of each Twig template.
<info>php %command.full_name% @AcmeMyBundle</info>
The command finds all twig templates in the <comment>AcmeMyBundle</comment> bundle and validates
the syntax of each Twig template.
-
-<info>cat filename | php %command.full_name%</info>
-
-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('<info>OK</info>'.($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("<error>KO</error> in %s (line %s)", $file, $line));
- } else {
- $output->writeln(sprintf("<error>KO</error> (line %s)", $line));
- }
-
- foreach ($lines as $no => $code) {
- $output->writeln(sprintf(
- "%s %-6s %s",
- $no == $line ? '<error>>></error>' : ' ',
- $no,
- $code
- ));
- if ($no == $line) {
- $output->writeln(sprintf('<error>>> %s</error> ', $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);
}
}
2  src/Symfony/Bundle/TwigBundle/composer.json
View
@@ -17,7 +17,7 @@
],
"require": {
"php": ">=5.3.3",
- "symfony/twig-bridge": "~2.2",
+ "symfony/twig-bridge": "~2.5",
Wouter J
WouterJ added a note

isn't this a BC break, as we can't use the bundle with symfony 2.2 anymore? (which could before this PR)

Christophe Coevoet Collaborator
stof added a note

This is not a BC break IMO. If you have the fullstack 2.2, you cannot use TwigBundle 2.5 anyway (as TwigBundle is part of the fullstack).
And if you use them standalone, composer will forbid you to upgrade to TwigBundle 2.5 without upgrading Twig-bridge as well, but this is part of the dependency resolution. If you try to do the job of composer manually, you are asking for pain anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
"symfony/http-kernel": "~2.1"
},
"require-dev": {
Something went wrong with that request. Please try again.