-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[WIP][2.3][FrameworkBundle][Templating] Generate assets with absolute url #7722
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
Changes from all commits
c488d5c
da3513a
89c47e9
f76a244
47f0f81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?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\Templating\Asset; | ||
|
||
use Symfony\Component\Routing\RequestContext; | ||
use Symfony\Component\Templating\Asset\Package; | ||
|
||
/** | ||
* This package attempts to return absolute URL for assets | ||
* | ||
* @author Roman Marintšenko <roman.marintsenko@knplabs.com> | ||
*/ | ||
class AbsoluteUrlPackage extends Package | ||
{ | ||
private $context; | ||
|
||
/** | ||
* @param RequestContext $context Request context | ||
* @param string $version The version | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
* @param string $format The version format | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above? |
||
*/ | ||
public function __construct(RequestContext $context, $version = null, $format = null) | ||
{ | ||
$this->context = $context; | ||
|
||
parent::__construct($version, $format); | ||
} | ||
|
||
public function getUrl($path) | ||
{ | ||
if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { | ||
return $path; | ||
} | ||
|
||
$url = ltrim($path, '/'); | ||
if ($baseUrl = $this->context->getBaseUrl()) { | ||
$url = trim($baseUrl, '/').'/'.$url; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so we are not leaving spaces between the contactenating .'s, thought i just saw @bschussek using them for his PR There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good question! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cordoval I was pushing a few old PRs recently that I probably forgot to scan for this convention change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bschussek sorry, i'm still confused. Is it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
// get scheme, host and port from RequestContext | ||
// based on \Symfony\Component\Routing\Generator\UrlGenerator::doGenerate() | ||
$schemeAuthority = ''; | ||
if ($host = $this->context->getHost()) { | ||
$scheme = $this->context->getScheme(); | ||
|
||
$port = ''; | ||
if ('http' === $scheme && 80 != $this->context->getHttpPort()) { | ||
$port = ':'.$this->context->getHttpPort(); | ||
} elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { | ||
$port = ':'.$this->context->getHttpsPort(); | ||
} | ||
|
||
$schemeAuthority .= $scheme.'://'.$host.$port; | ||
} | ||
|
||
$url = $schemeAuthority.'/'.$url; | ||
|
||
$url = $this->applyVersion($url); | ||
|
||
return $url; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?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\Templating\Asset; | ||
|
||
use Symfony\Component\Routing\RequestContext; | ||
use Symfony\Bundle\FrameworkBundle\Templating\Asset\AbsoluteUrlPackage; | ||
|
||
/** | ||
* This package attempts to return absolute URL for assets | ||
* | ||
* @author Roman Marintšenko <roman.marintsenko@knplabs.com> | ||
*/ | ||
class AbsoluteUrlPackageTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
public function testGetUrl() | ||
{ | ||
$package = new AbsoluteUrlPackage(new RequestContext()); | ||
$this->assertEquals('http://example.com/foo.js', $package->getUrl('http://example.com/foo.js'), '->getUrl() does nothing if an absolute URL is already given'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('', 'GET', 'symfony.com')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have you tried a dataprovider for this test? just wondering |
||
$this->assertEquals('http://symfony.com/foo.js', $package->getUrl('foo.js'), '->getUrl() prepends host and scheme to a given path'); | ||
$this->assertEquals('http://symfony.com/foo.js', $package->getUrl('/foo.js'), '->getUrl() prepends host and scheme to a given absolute path'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('foo', 'GET', 'symfony.com')); | ||
$this->assertEquals('http://symfony.com/foo/foo.js', $package->getUrl('foo.js'), '->getUrl() prepends base url to relative path'); | ||
$this->assertEquals('http://symfony.com/foo/foo.js', $package->getUrl('/foo.js'), '->getUrl() prepends base url to absolute path'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('/foo', 'GET', 'symfony.com')); | ||
$this->assertEquals('http://symfony.com/foo/foo.js', $package->getUrl('foo.js'), '->getUrl() prepends base url with backslash at beginning to relative path'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('foo/', 'GET', 'symfony.com')); | ||
$this->assertEquals('http://symfony.com/foo/foo.js', $package->getUrl('foo.js'), '->getUrl() prepends base url with backslash at end to relative path'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('', 'GET', 'symfony.com', 'http', 8080)); | ||
$this->assertEquals('http://symfony.com:8080/foo.js', $package->getUrl('foo.js'), '->getUrl() prepends port if it is different than 80'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('', 'GET', 'symfony.com', 'https', 80, 443)); | ||
$this->assertEquals('https://symfony.com/foo.js', $package->getUrl('foo.js'), '->getUrl() does not prepend 443 port if scheme is https'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('', 'GET', 'symfony.com', 'https', 80, 444)); | ||
$this->assertEquals('https://symfony.com:444/foo.js', $package->getUrl('foo.js'), '->getUrl() prepends port if scheme is https and it is different than 443'); | ||
|
||
$package = new AbsoluteUrlPackage(new RequestContext('', 'GET', 'symfony.com'), 'abcd'); | ||
$this->assertEquals('http://symfony.com/foo.js?abcd', $package->getUrl('foo.js'), '->getUrl() appends the version if defined'); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ public function getFunctions() | |
{ | ||
return array( | ||
'asset' => new \Twig_Function_Method($this, 'getAssetUrl'), | ||
'asset_url' => new \Twig_Function_Method($this, 'getAssetAbsoluteUrl'), | ||
'assets_version' => new \Twig_Function_Method($this, 'getAssetsVersion'), | ||
); | ||
} | ||
|
@@ -55,6 +56,24 @@ public function getAssetUrl($path, $packageName = null) | |
return $this->container->get('templating.helper.assets')->getUrl($path, $packageName); | ||
} | ||
|
||
/** | ||
* Returns absolute URL for a given asset path | ||
* Does not rely on assets_base_urls parameter, instead tries to match request scheme/host/port | ||
* | ||
* If called from CLI, then relies on router.request_context.* parameters: | ||
* router.request_context.host | ||
* router.request_context.scheme | ||
* router.request_context.base_url | ||
* | ||
* @param string $path A public path | ||
* | ||
* @return string A public path which takes into account the base path and URL path | ||
*/ | ||
public function getAssetAbsoluteUrl($path) | ||
{ | ||
return $this->getAssetUrl($path, 'absolute_url'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be broken as soon as you use asset packages (you cannot get an absolute url based on the package) and your code does not play well with packages urls which are already absolute because of the base url. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This, nothing ensure that you have an asset package named There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @stof I get that I can't rely on Or you mean that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Inori you cannot get the absolute url by using a different asset package. An asset package defines a set of base urls and a version. If we want to support absolute urls, I see 2 solutions:
|
||
} | ||
|
||
/** | ||
* Returns the version of the assets in a package. | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A service named
absolute_url
is a bad idea IMO. It does not descibe at all what the service is about.thus, making the alias target the abstract service looks weird to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea was to add a simple name that developers can reference when calling
asset()
.Do you think I should get rid of the alias completely or change to something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you pass as argument when calling
asset()
is not a service idThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, misunderstood the setup. Thanks!