Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes twig bundle project root dir discovery #22570

Closed
wants to merge 5 commits into from
Closed

Fixes twig bundle project root dir discovery #22570

wants to merge 5 commits into from

Conversation

pounard
Copy link
Contributor

@pounard pounard commented Apr 28, 2017

Q A
Branch? master
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #22149
License MIT
Doc PR none

TwigBundle ExtensionPass uses a directory lookup algorithm to find the composer.json file. When working under open_basedir restrictions, if the project root folder is not allowed PHP runtime to read, the composer.json will never be found, throwing PHP notices along the way and ending up using the filesystem root instead.

Since that 3.3 introduced the kernel getProjectRoot() method and kernel.project_dir variable, the TwigBundle can now leverage it, in order to get more consistent, and allow site builders to override the getProjectRoot() kernel method, hence bypass the open_basedir restrictions in reliable and safe way.

$twigLoader = $container->getDefinition('twig.loader.native_filesystem');
if ($container->has('templating')) {
$loader = $container->getDefinition('twig.loader.filesystem');
$loader->setMethodCalls(array_merge($twigLoader->getMethodCalls(), $loader->getMethodCalls()));
$loader->replaceArgument(2, $composerRootDir);
$loader->replaceArgument(2, $projectDir);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even better: use %kernel.project_dir% directly in the service definition, and remove the handling of this argument from the compiler pass

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, got it now, you're right it should work.

Copy link
Contributor Author

@pounard pounard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof did your changes.

$twigLoader = $container->getDefinition('twig.loader.native_filesystem');
if ($container->has('templating')) {
$loader = $container->getDefinition('twig.loader.filesystem');
$loader->setMethodCalls(array_merge($twigLoader->getMethodCalls(), $loader->getMethodCalls()));
$loader->replaceArgument(2, $composerRootDir);
$loader->replaceArgument(2, $projectDir);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, got it now, you're right it should work.

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

Hum. I do need to fix tests. I obviously ran the wrong tests the first time.

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

@stof how would you fix it for 3.2 and 3.0 since that the kernel.project_dir variable does not exist in there ? I was think in trying to read it anyway (ie. if ($container->hasParameter('kernel.project_dir')) {) is that a bad idea?

The question is not innocent, we do really experience this bug on production apps, and it needs fixing in current stable, I'm not fond in backporting a variable in stable, but it would help us fixing our env by just setting it.

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

Only PHP 7.1 fails, but for a very deep unknown reason.

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

[pounard@guinevere] /var/www/symfony
 >  uname -a
Linux guinevere 4.10.11-1-ARCH #1 SMP PREEMPT Tue Apr 18 08:39:42 CEST 2017 x86_64 GNU/Linux
[pounard@guinevere] /var/www/symfony
 >  php -v
PHP 7.1.4 (cli) (built: Apr 11 2017 18:45:29) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.1.4, Copyright (c) 1999-2017, by Zend Technologies
    with Xdebug v2.5.3, Copyright (c) 2002-2017, by Derick Rethans
[pounard@guinevere] /var/www/symfony
 >  phpunit -vvv --filter TwigBundle
PHPUnit 5.7.19 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.1.4 with Xdebug 2.5.3
Configuration: /var/www/symfony/phpunit.xml.dist

Testing Symfony Test Suite
........................................                          40 / 40 (100%)

Time: 7.5 seconds, Memory: 96.00MB

OK (40 tests, 143 assertions)

Legacy deprecation notices (1)

Test OK locally.

@ro0NL
Copy link
Contributor

ro0NL commented Apr 28, 2017

You need to bump the http-kernel dep in the twig bundle;
https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/TwigBundle/composer.json#L23

This parameter exists as of 3.3

how would you fix it for 3.2 and 3.0 since that the kernel.project_dir variable does not exist in there

Maybe keep the current implementation, and consider it "improved" as of 3.3

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

@ro0NL

Maybe keep the current implementation, and consider it "improved" as of 3.3

The current implementation in 3.0 -> 3.2 is subject to the original bug I experienced: when the project root dir is under open_basedir restriction, TwigBundle skips the folder because it can't read the composer.json file, then the loop goes until it reaches the filesystem root and uses that instead. It needs fixing.

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

@ro0NL in your opinion, should I get the getComposerDir() function back into the master and just conditionally use the kernel.project_root if exists ?

@ro0NL
Copy link
Contributor

ro0NL commented Apr 28, 2017

In master %kernel.project_dir% just exists.. so this PR is fine for master/3.3 i guess :)

The current implementation in 3.0 -> 3.2 is subject to the original bug I experienced

Thing is we cant backport a new feature (the project_dir param).. so we need a different approach on lower branches... ie. the current one.

@chalasr
Copy link
Member

chalasr commented Apr 28, 2017

The current implementation in 3.0 -> 3.2 is subject to the original bug I experienced: when the project root dir is under open_basedir restriction, TwigBundle skips the folder because it can't read the composer.json file, then the loop goes until it reaches the filesystem root and uses that instead. It needs fixing.

Doesn't the same situation occur with kernel.project_dir? The default implementation of Kenrel::getProjectRootDir() looks similar

@ro0NL
Copy link
Contributor

ro0NL commented Apr 28, 2017

True.. but you can override the param way more easily :) and if overriden, we need to use that variant as well :)

@chalasr
Copy link
Member

chalasr commented Apr 28, 2017

sure :)

@stof
Copy link
Member

stof commented Apr 28, 2017

Using the project dir is the right approach for 3.3+. So to fix the build for deps=low, you just need to bump the min required version in TwigBundle

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

Ok, I bumped the version, now the real tricky question arise: how do I fix it for 3.0 -> 3.2 versions knowing I have real sites in real productions buggy because of this ?

@ro0NL
Copy link
Contributor

ro0NL commented Apr 28, 2017

you need to bump to 3.3 ;-) the param does not exists in 3.2.2.

Maybe for lower branches we should start checking for open_basedir, and if we traversed to the filesystem root, but without a composer.json return the current dir as well 🤔

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

Oh sorry, just stupidly ran the test locally and pushed...

@pounard
Copy link
Contributor Author

pounard commented Apr 28, 2017

w00t, sorry for the noise, it should be OK now.

@nicolas-grekas nicolas-grekas added this to the 3.3 milestone Apr 28, 2017
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@fabpot
Copy link
Member

fabpot commented Apr 28, 2017

Thank you @pounard.

@fabpot fabpot closed this Apr 28, 2017
fabpot added a commit that referenced this pull request Apr 28, 2017
This PR was squashed before being merged into the 3.3-dev branch (closes #22570).

Discussion
----------

Fixes twig bundle project root dir discovery

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

<!--
- Bug fixes must be submitted against the lowest branch where they apply
  (lowest branches are regularly merged to upper ones so they get the fixes too).
- Features and deprecations must be submitted against the master branch.
- Please fill in this template according to the PR you're about to submit.
- Replace this comment by a description of what your PR is solving.
-->

TwigBundle ExtensionPass uses a directory lookup algorithm to find the composer.json file. When working under open_basedir restrictions, if the project root folder is not allowed PHP runtime to read, the composer.json will never be found, throwing PHP notices along the way and ending up using the filesystem root instead.

Since that 3.3 introduced the kernel getProjectRoot() method and kernel.project_dir variable, the TwigBundle can now leverage it, in order to get more consistent, and allow site builders to override the getProjectRoot() kernel method, hence bypass the open_basedir restrictions in reliable and safe way.

Commits
-------

3cb2e5b Fixes twig bundle project root dir discovery
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants