This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
Go to file
Fabien Potencier 0b505ffee0 merged branch Exercise/assets-helper-scope-2 (PR #2223)
Commits
-------

6555e28 Remove unnecessary use statement
369f181 [FrameworkBundle] Add request scope to assets helper only if needed
d6b915a [FrameworkBundle] Assets templating helper does not need request scope

Discussion
----------

[FrameworkBundle] Assign request scope to assets helper only if needed

**Note**: This PR replaces #2218

I traced this request scope addition back to [an old commit](d9f5c99fab (commitcomment-597654)) from @kriswallsmith.

No other helpers have request scope and the assets helper's parameters don't appear to depend on the request in any way, so this appears to be unnecessary. As-is, request scope here prevents use of the assets helper from a console command that may need to internally render a template.

---------------------------------------------------------------------------

by fabpot at 2011/09/20 08:10:48 -0700

There is probably a reason why it was set to the request scope (just run the unit tests ;)).

---------------------------------------------------------------------------

by jmikola at 2011/09/20 08:22:46 -0700

Doh! Didn't even think to do that for such a small change.

I will investigate further. Do you have any idea how one can generate templates (which call the `asset()` function) during a console script?

---------------------------------------------------------------------------

by fabpot at 2011/09/20 08:33:22 -0700

Apparently, something depends on the Request somewhere. We need to find what needs the Request and determine if this is legitimate or not.

---------------------------------------------------------------------------

by henrikbjorn at 2011/09/20 09:25:05 -0700

https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php#L33

---------------------------------------------------------------------------

by jmikola at 2011/09/20 10:40:23 -0700

Thanks @henrikbjorn. So, it appears the default behavior of the asset helper is to use the request path as the base URL for assets. In my particular case, I didn't get this scope-widening exception at runtime because I use `assets_base_urls`, which results in the request-independent UrlPackage being injected instead of PathPackage.

This is tricky. I think there's definitely a use case for folks rendering templates outside of a request. Sending HTML emails via some console command is perhaps the most common example. Also, if those developers are not using a CDN, they likely won't think of using `assets_base_urls` at all. Unfortunately, that appears to be the only configuration option where the site's domain is specified (outside of, say, a session domain).

---------------------------------------------------------------------------

by lsmith77 at 2011/09/20 10:45:42 -0700

So do we need 2 services?

---------------------------------------------------------------------------

by jmikola at 2011/09/20 10:52:02 -0700

Well, we actually already have two services. I think that's why PathPackages and UrlPackages are distinct. The issue is that the asset helper has been assigned the request scope to accommodate to satisfy the most restrictive possibility.

I don't think two separate asset helpers would help the developer, even if it'd let us get passing tests.

Also, there is a very real use case here that I wasn't struggling with. You want to render templates with asset paths outside of a request (from a console command). In that case, you need a base URL, but where do you get that from?

Has anyone else encountered that requirement? I know we definitely did at OpenSky, and now at Exercise.com.

---------------------------------------------------------------------------

by jmikola at 2011/09/22 20:14:37 -0700

Had a chat with @kriswallsmith today. We brainstormed and came up with the idea of simply adding `strict="false"` to the request arguments of these templating services. That would disable the premature scope exception, but lead to different kind of error if the user attempted to call `asset()` when using a PathPackage (no `asset_base_urls` and no UrlPackage in play).

The PathPackage class in the templating component obviously has no request dependency -- just the FrameworkBundle version. I started modifying FrameworkBundle's PathPackage to make the Request usage optional (if it's not available, an empty base path is provided to the parent constructor, which actually works fine).

In the course of implementing that, I made the request argument `strict="false" on-invalid="null"` and encountered some strange behavior (possibly a bug) where the PathPackage service generated in FrameworkExtension via the DefinitionDecorator was not inheriting the strict/invalid properties. If I removed `on-invalid="null", strictness was inherited just fine. I'm going to continue looking into this, but at this point it seems like that may be a separate PR if it is, indeed, a bug.

Just going to paste my chat transcript with Kris here for some extra context:

```
<jmikola> if you have a moment later, could you chime in on https://github.com/symfony/symfony/pull/2223 ?
<jmikola> it's about using the asset() helper from a console command
<jmikola> i could have sworn we were sending emails like this in opensky, from console commands
<jmikola> doing the same thing for exercise, but the request scope on the asset helper is a cog in the gear
<kris>    you don't have base urls configured?
<jmikola> we do
<jmikola> but the service is request-scoped because it doesn't know until runtime if it will be using UrlPackage or PathPackage
<jmikola> and PathPackage depends on the request object
<kris>    yeah, it's tricky
<jmikola> so i think the scope was added to handle the most restrictive case
<jmikola> no way around that except to remove the scoping at runtime i suppose
<kris>    we can tweak the scope in a compilation pass
<kris>    but that could create some wtfs
<jmikola> why?
<jmikola> because some asset() calls might specify a package name?
<jmikola> without base_url's?
<kris>    what about setting strict to false?
<jmikola> i haven't played with package names but i think that's how it works
<jmikola> ah, what's the problem with that again? i know it disables the exception
<jmikola> but if strict is false, what's the benefit of having request scope at all?
<kris>    there are a lot of instances of strict="false" in the core
<jmikola> if strict is false, the scope becomes just documentation?
<jmikola> i'm drawing a blank on how that works - i just know strictness turns on the exceptions for widening violations
<kris>    right
<kris>    it means that helper would no longer be in the request scope, even though it uses a service from the request scope
<kris>    i think that would be fine
<jmikola> ah, strict=false goes on the service argument
<jmikola> does that mean we'd apply that to the definition of templating.asset.path_package ?
<kris>    yes
<jmikola> or just when PathPackage becomes an argument to the helper?
<jmikola> ok
<kris>    whatever uses the request
<jmikola> and this would still cause havoc if I didn't define base_urls and tried to call asset() :)
<jmikola> i suppose in the form of null passed when Request instance expected?
<jmikola> or worse, undefined service request
<kris>    right...
<jmikola> ok
<kris>    so maybe we need a way to manually define the base path
<jmikola> for PathPackage
<kris>    right, i think that's what's in the component
<jmikola> UrlPackage only comes into play if there's 1 or more assets_base_urls defined, right?
<kris>    right
<jmikola> i'm looking at it, and am curious what happens if it was constructed with no base urls :)
<jmikola> since there's no checks that the array is full
<jmikola> *non-empty
<jmikola> ah, if it's empty it uses '' as the base Url
<jmikola> Perhaps PathPackage in FrameworkBundle could make the request optional
<jmikola> the core PathPackage does support an empty baseUrl
<jmikola> $basePath rather
<jmikola> it uses "/" by default
<kris>    how about a configurator that calls setBasePath() if the container includes a request?
<jmikola> then the service would still need to be request scoped, no?
<jmikola> what it the same service was used on multiple requests
<jmikola> thinking of those trendy php app servers :)
<kris>    the service wouldn't use the request
<kris>    the configurator would
<kris>    but via dic injection
<jmikola> do configurators exist?
<jmikola> i don't think i've seen one, a class with that name is in the DistributionBundle though - probably different
<kris>    you can define a configurator on a service
<jmikola> example? is this done via tags?
<kris>    it's a callable that will be passed the service before it leaves the container for the first time
<jmikola> so the PathPackage base class in the Templating component has a private basePath, it'd need a setBasePath method added of course
<kris>    yeah, that's fine
<jmikola> ah <configurator
<jmikola> can't believe i've never seen this before
<kris>    it's an old feature
<kris>    and you can only set one for some reason
<jmikola> woah, it's only in test fixtures
<jmikola> nothing actually uses it
<jmikola> yet :)
<jmikola> configurators receive the container as their only argument?
<jmikola> oh, no arguments at all
<kris>    they receive the service
<kris>    but a configurator can be a service itself
<kris>    i would add a base path node to the config
<kris>    and disallow using both base path and base urls
<kris>    and only use the configurator if the base path isn't explicitly set
<jmikola> now, in this case i'd have the configurator for the PathPackage service be another service that depends on request
<kris>    no
<kris>    the configurator should depend on the container
<kris>    check if there is a request service and use it to set the base path if so
<jmikola> ok, and it's responsible for $pathPackage->setBaseUrl($request->getBasePath()) if the request exists
<jmikola> right
<kris>    setBasePath
<jmikola> correct, sorry
<jmikola> i think a base_path and base_url can co-exist
<jmikola> base_url will entail use of the UrlPackage
<jmikola> and base_path is simply the default value for PathPackages
<jmikola> in the absence of the request
<kris>    i don't follow
<jmikola> a base_url option in the config would simply be for the case where PathPackage is utilized outside of a request scope (i.e. console command)
<jmikola> sorry, base_path***
<jmikola> assets_base_url is for UrlPackages
<kris>    right
<jmikola> ok, so you're saying at the top level, or in the packages prototypes, we'd allow only one or the other
<jmikola> at present, there's only asset_base_url's, so that implies configurations creating only UrlPackages
<kris>    add a validation to the Configuration class so you have to choose one or the other
<kris>    i don't understand why you would need base_path from the cli
<jmikola> so in this case, absence of either will result in a PathPackage configured based on the current request
<kris>    don't you need absolute urls in your emails?
<kris>    i'm rethinking
<jmikola> yes, we're using UrlPackages of course
<jmikola> but the request scope ruined this for me
<kris>    don't bother with base_path in the config
<kris>    just do the configurator
<jmikola> there's still a possibility that someone would generate HTML for on-site use from a console command
<jmikola> perhaps pre-building twig templates or something
<jmikola> your idea made sense i think
<jmikola> even if it's an edge case
<jmikola> granted, most people are perfectly fine with "/" as a default base_path in the absence of a request
<kris>    that would be another pr
<jmikola> right
<jmikola> then for now, what about just making the request argument on-invalid null?
<jmikola> and changing PathPackage in the bundle
<jmikola> PathPackage in the component already handles an empty base path itself just fine
<kris>    yeah, that's better
<jmikola> on-invalid="null" and strict="false"
<kris>    nice
<jmikola> i'm satisifed with the simplicity of that
<jmikola> and will comment about your base_path option idea in my PR for a future task when i get around to it - as that sounded great as well
<jmikola> thanks for talking through this w/ me :)
<kris>    np
<jmikola> PackageFactory is the new roadblock, heh
<jmikola> getPackage() { return $this->container->get($request->isSecure() ? $sslId : $httpId); }
<jmikola> :D
<kris>    oh yeah
<jmikola> should i utilize the same logic? default to non-ssl?
<jmikola> i'm actually curious how gmail handles references to http:// assets embedded in its emails
<jmikola> i suppose it renders message bodies in iframes
<kris>    then it would be impossible to render https asset urls without a request
<jmikola> wouldn't it default to the http url?
<kris>    right
<kris>    but what if you only have https base urls configured?
<jmikola> if you break them into http and https blocks, it'd be a problem
<kris>    i think it always uses https if you only have https urls configured
<jmikola> otherwise, the shorthand notation sorts them for you
<jmikola> and all https urls are available to http
<jmikola> ah, you're correct
<jmikola> FrameworkExtension::createPackageDefinition
```

---------------------------------------------------------------------------

by jmikola at 2011/09/26 10:39:00 -0700

@fabpot: I believe I reached an agreeable solution, so please review when you get a chance.

I removed any `strict` and `on-invalid` trickery (ideas I was discussing with Kris) and decided to only apply request scoping to the assets helper if one or more of its injected packages (default or named) is request scoped.

This satisfies my requirements, as I had absolute base URL's defined for both HTTP and SSL protocols. It also leaves the current scope exceptions in place if, for instance, someone only defined an HTTP base URL and FrameworkBundle ended up creating a PathPackage for their SSL assets. I go into detail about this more in my second commit, and I think the added tests help explain this as well.

---------------------------------------------------------------------------

by jmikola at 2011/09/26 16:56:30 -0700

Something screwed up earlier and this PR's branch included all commits in `symfony/master`. I just cleaned things up.
2011-09-27 09:52:20 +02:00
src/Symfony Remove unnecessary use statement 2011-09-26 19:54:19 -04:00
tests [ClassLoader] Fixed state when trait_exists doesn't exists 2011-09-25 19:25:50 +02:00
.gitignore Added vendor directory to .gitignore 2010-06-24 10:44:28 +02:00
autoload.php.dist fixed autoloader when tests are run on a machine without intl installed 2011-07-20 14:27:10 +02:00
CHANGELOG-2.0.md updated CHANGELOG for 2.0.3 2011-09-25 11:50:40 +02:00
check_cs fixed root search path to include only './src' and './tests' 2011-06-08 18:11:05 +02:00
CONTRIBUTORS.md update CONTRIBUTORS for 2.0.2 2011-09-25 10:26:33 +02:00
LICENSE added the LICENSE file for the YAML component 2011-02-18 11:52:11 +01:00
phpunit.xml.dist [Security] cleaned up opt-in to benchmark test 2011-03-06 20:06:13 +01:00
README.md [README] Adding a small section with information about contributing. 2011-09-23 11:21:11 -05:00
UPDATE.ja.md updated translation of UPDATE file (Japanese RC5 added) 2011-07-30 02:08:25 +09:00
UPDATE.md updated UPDATE file 2011-07-22 17:45:02 +02:00
vendors.php updated vendors for 2.0.2 2011-09-25 09:55:09 +02:00

README

What is Symfony2?

Symfony2 is a PHP 5.3 full-stack web framework. It is written with speed and flexibility in mind. It allows developers to build better and easy to maintain websites with PHP.

Symfony can be used to develop all kind of websites, from your personal blog to high traffic ones like Dailymotion or Yahoo! Answers.

Requirements

Symfony2 is only supported on PHP 5.3.2 and up.

Installation

The best way to install Symfony2 is to download the Symfony Standard Edition available at http://symfony.com/download.

Documentation

The "Quick Tour" tutorial gives you a first feeling of the framework. If, like us, you think that Symfony2 can help speed up your development and take the quality of your work to the next level, read the official Symfony2 documentation.

Contributing

Symfony2 is an open source, community-driven project. If you'd like to contribute, please read the Contributing Code part of the documentation. If you're submitting a pull request, please follow the guidelines in the Submitting a Patch section.