10000 [3.0][FrameworkBundle] Asset helpers should not be in the request scope · Issue #11653 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[3.0][FrameworkBundle] Asset helpers should not be in the request scope #11653

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

Closed
csarrazi opened this issue Aug 12, 2014 · 10 comments
Closed

[3.0][FrameworkBundle] Asset helpers should not be in the request scope #11653

csarrazi opened this issue Aug 12, 2014 · 10 comments

Comments

@csarrazi
Copy link
Contributor

Right now, using the asset twig function results in the following error:

[Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException]

Scope Widening Injection detected: The definition "templating.asset.default_package" references the service "request" which belongs to a narrower scope. Generally, it is safer to either move "templating.asset.default_package" to scope "request" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "request" each time it is needed. In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.

As one may want to rely on the asset helper to generate URIs outside from a request (i.e., in a command-line, for sending e-mails), it should not depend on the request service, but rather on request_stack, in order to be available in a wider scope.

This would also allow the simplification of Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension, by removing calls to the setScope() methods, once support for scopes is dropped for 3.0.

@stof
Copy link
Member
stof commented Aug 12, 2014

The issue is that we cannot change the PathPackage to avoid using the Request itself without breaking BC. This is why it is still in the request scope.

Note that when you specify a base url for assets instead of getting the base path from the request, the generated UrlPackage is in the container scope.

@fabpot
Copy link
Member
fabpot commented Aug 12, 2014

... and we already have a couple of PRs dealing with this issue.

@csarrazi
Copy link
Contributor Author

The PathPackage i'm talking about is actually the one in the FrameworkBundle (not the one from the Templating component, which has no dependency whatsoever).

PathPackage is the only remaining public service which actually still depends on the request scope (apart from the request service itself, which is deprecated).

Edit: mistook FrameworkBundle and FrameworkExtraBundle. Removed comment about BC.

@csarrazi
Copy link
Contributor Author

@fabpot Didn't see any PR adressing this particular issue, or anything related to asset packages (apart from #10973) or scopes.

In a console app, the workaround for now is not pretty at all:

$request = new Request();
$locale = $this->getContainer()->getParameter('locale');
$request->setLocale($locale);
$this->getContainer()->set('request', $request);
$this->getContainer()->get('translator')->setLocale($locale);

$this->getContainer()->enterScope('request');
$template = $this->getContainer()->get('twig')->render('AcmeDemoBundle:Email:email.html.twig');
$this->getContainer()->leaveScope('request');

@stof
Copy link
Member
stof commented Aug 12, 2014

@csarrazi but changing the way we depend on the request in the extended PathPackage requires changing the base class of the component too (if you get the request from the request stack in the constructor, you have the same issue than currently).

and breaking compatibility is something we can do in 3.0, but not in 2.6. This is why we are still using the request scope currently (we are working on the 2.6 development, not on the 3.0 one). There was an attempt to stop using the request scope here when we introduced the RequestStack in Symfony, but we did not manage to do the refactoring in a BC way.

@csarrazi
Copy link
Contributor Author

@stof Sorry about BC. I was thinking about FrameworkExtraBundle, which is obviously very different from FrameworkBundle ;)

In any case, PathPackage is not part of the api, and the change I intended to do was to inject RequestStack.

In any case, the CLI needs some love. Too many hacks are needed in order to be able to generate Uris, generate asset Uris, etc.

@csarrazi csarrazi changed the title [FrameworkBundle] Asset helpers should not be in the request scope [3.0][FrameworkBundle] Asset helpers should not be in the request scope Aug 12, 2014
@stof
Copy link
Member
stof commented Aug 12, 2014

@csarrazi Not being flagged as @api does not mean we can break BC on the class in the way we want. It only means that we give us a bit more freedom with BC (saying that it is safe to use the class, but it may not be safe to extend it in your own code for instance).

Generating Uris in the console does not require any hack. It only requires a small configuration, which is necessary because we cannot guess on which domain the application is running, and whether it is in a subfolder of the document root, given that the app is not accessed through HTTP: http://symfony.com/doc/current/cookbook/console/sending_emails.html#configuring-the-request-context-globally (the default value if not configured would generate a link http://localhost/).

Generating asset uris in the CLI is indeed more complex when your asset base urls are guessed based on the request (when you configure a base url when using a CDN for instance, there is strictly nothing to change to generate asset urls in the CLI)

@lyrixx
Copy link
Member
lyrixx commented Aug 13, 2014

It's funny (or not), But we (me and @tucksaun) stubble upon the same issue. we solve this issue by a custom compiler pass in our bundle:

<?php

namespace SensioLabs\Bundle\ToolkitBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * As we hook-up into the assets helper config, Symfony does not handle
 * correctly the scope of templating.helper.assets.
 * So we try to set-up the higher scope for this service.
 *
 * @see https://github.com/symfony/symfony/issues/11653
 */
class AssetsHelperPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('templating.helper.assets')) {
            return;
        }

        $assetsHelper =  $container->getDefinition('templating.helper.assets');

        $defaultScope = $this->getPackageScope($container, $assetsHelper->getArgument(0));

        $assetsHelper->setScope($defaultScope);

        foreach ($assetsHelper->getArgument(1) as $arg) {
            if ('request' === $this->getPackageScope($container, $arg)) {
                $assetsHelper->setScope('request');

                break;
            }
        }
    }

    private function getPackageScope(ContainerBuilder $container,  Reference $package)
    {
        $definition = $container->getDefinition((string) $package);

        return $definition->getScope();
    }
}

I think we could safely move some code from the FrameworkExtension to a Compiler pass.
WDYT?

@stof
Copy link
Member
stof commented Sep 4, 2014

@lyrixx this looks good for 2.6. Can you send a PR ?

@lyrixx
Copy link
Member
lyrixx commented Sep 19, 2014

yep ;)

fabpot added a commit that referenced this issue Sep 22, 2014
…e 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
@fabpot fabpot closed this as completed Sep 22, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
0