feature #11961 [FrameworkBundle] Determine templating.engine.php scope as late as possible (lyrixx)

This PR was merged into the 2.6-dev branch.

Discussion
----------

[FrameworkBundle] Determine templating.engine.php scope as late as possible

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

Commits
-------

169dadd [FrameworkBundle] Determine templating.engine.php scope as late as possible
This commit is contained in:
Fabien Potencier 2014-09-22 14:32:47 +02:00
commit aeef2bc5da
5 changed files with 189 additions and 15 deletions

View File

@ -0,0 +1,66 @@
<?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\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
class TemplatingAssetHelperPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('templating.helper.assets')) {
return;
}
$assetsHelperDefinition = $container->getDefinition('templating.helper.assets');
$args = $assetsHelperDefinition->getArguments();
if ('request' === $this->getPackageScope($container, $args[0])) {
$assetsHelperDefinition->setScope('request');
return;
}
if (!array_key_exists(1, $args)) {
return;
}
if (!is_array($args[1])) {
return;
}
foreach ($args[1] as $arg) {
if ('request' === $this->getPackageScope($container, $arg)) {
$assetsHelperDefinition->setScope('request');
break;
}
}
}
private function getPackageScope(ContainerBuilder $container, $package)
{
if ($package instanceof Reference) {
return $container->findDefinition((string) $package)->getScope();
}
if ($package instanceof Definition) {
return $package->getScope();
}
// Someone did some voodoo with a compiler pass. So we ignore this
// 'package'. Can we be sure, it's a package anyway?
}
}

View File

@ -484,19 +484,6 @@ class FrameworkExtension extends Extension
$namedPackages,
));
// Apply request scope to assets helper if one or more packages are request-scoped
$requireRequestScope = array_reduce(
$namedPackages,
function ($v, Reference $ref) use ($container) {
return $v || 'request' === $container->getDefinition($ref)->getScope();
},
'request' === $defaultPackage->getScope()
);
if ($requireRequestScope) {
$container->getDefinition('templating.helper.assets')->setScope('request');
}
if (!empty($config['loaders'])) {
$loaders = array_map(function ($loader) { return new Reference($loader); }, $config['loaders']);

View File

@ -16,6 +16,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInit
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingAssetHelperPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RoutingResolverPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
@ -70,6 +71,7 @@ class FrameworkBundle extends Bundle
// but as late as possible to get resolved parameters
$container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new TemplatingPass());
$container->addCompilerPass(new TemplatingAssetHelperPass());
$container->addCompilerPass(new AddConstraintValidatorsPass());
$container->addCompilerPass(new AddValidatorInitializersPass());
$container->addCompilerPass(new AddConsoleCommandPass());

View File

@ -0,0 +1,121 @@
<?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\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingAssetHelperPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
class TemplatingAssetHelperPassTest extends \PHPUnit_Framework_TestCase
{
public function getScopesTests()
{
return array(
array('container'),
array('request'),
);
}
/** @dataProvider getScopesTests */
public function testFindLowestScopeInDefaultPackageWithReference($scope)
{
$container = new ContainerBuilder();
$defaultPackage = new Definition('stdClass');
$defaultPackage->setScope($scope);
$container->setDefinition('default_package', $defaultPackage);
$definition = new Definition('stdClass', array(new Reference('default_package')));
$container->setDefinition('templating.helper.assets', $definition);
$profilerPass = new TemplatingAssetHelperPass();
$profilerPass->process($container);
$this->assertSame($scope, $definition->getScope());
}
/** @dataProvider getScopesTests */
public function testFindLowestScopeInDefaultPackageWithDefinition($scope)
{
$container = new ContainerBuilder();
$defaultPackage = new Definition('stdClass');
$defaultPackage->setScope($scope);
$definition = new Definition('stdClass', array($defaultPackage));
$container->setDefinition('templating.helper.assets', $definition);
$profilerPass = new TemplatingAssetHelperPass();
$profilerPass->process($container);
$this->assertSame($scope, $definition->getScope());
}
/** @dataProvider getScopesTests */
public function testFindLowestScopeInNamedPackageWithReference($scope)
{
$container = new ContainerBuilder();
$defaultPackage = new Definition('stdClass');
$container->setDefinition('default_package', $defaultPackage);
$aPackage = new Definition('stdClass');
$container->setDefinition('a_package', $aPackage);
$bPackage = new Definition('stdClass');
$bPackage->setScope($scope);
$container->setDefinition('b_package', $bPackage);
$cPackage = new Definition('stdClass');
$container->setDefinition('c_package', $cPackage);
$definition = new Definition('stdClass', array(new Reference('default_package'), array(
new Reference('a_package'),
new Reference('b_package'),
new Reference('c_package'),
)));
$container->setDefinition('templating.helper.assets', $definition);
$profilerPass = new TemplatingAssetHelperPass();
$profilerPass->process($container);
$this->assertSame($scope, $definition->getScope());
}
/** @dataProvider getScopesTests */
public function testFindLowestScopeInNamedPackageWithDefinition($scope)
{
$container = new ContainerBuilder();
$defaultPackage = new Definition('stdClass');
$aPackage = new Definition('stdClass');
$bPackage = new Definition('stdClass');
$bPackage->setScope($scope);
$cPackage = new Definition('stdClass');
$definition = new Definition('stdClass', array($defaultPackage, array(
$aPackage,
$bPackage,
$cPackage,
)));
$container->setDefinition('templating.helper.assets', $definition);
$profilerPass = new TemplatingAssetHelperPass();
$profilerPass->process($container);
$this->assertSame($scope, $definition->getScope());
}
}

View File

@ -186,8 +186,6 @@ abstract class FrameworkExtensionTest extends TestCase
$this->assertTrue($container->hasDefinition('templating.name_parser'), '->registerTemplatingConfiguration() loads templating.xml');
$this->assertEquals('request', $container->getDefinition('templating.helper.assets')->getScope(), '->registerTemplatingConfiguration() sets request scope on assets helper if one or more packages are request-scoped');
// default package should have one HTTP base URL and path package SSL URL
$this->assertTrue($container->hasDefinition('templating.asset.default_package.http'));
$package = $container->getDefinition('templating.asset.default_package.http');