[TwigBundle] Add possibility to generate absolute assets urls
This commit is contained in:
parent
b7c158a831
commit
76b88511a6
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Bundle\TwigBundle\Extension;
|
namespace Symfony\Bundle\TwigBundle\Extension;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
use Symfony\Component\Routing\RequestContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Twig extension for Symfony assets helper
|
* Twig extension for Symfony assets helper
|
||||||
@ -21,10 +22,12 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||||||
class AssetsExtension extends \Twig_Extension
|
class AssetsExtension extends \Twig_Extension
|
||||||
{
|
{
|
||||||
private $container;
|
private $container;
|
||||||
|
private $context;
|
||||||
|
|
||||||
public function __construct(ContainerInterface $container)
|
public function __construct(ContainerInterface $container, RequestContext $requestContext)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
|
$this->context = $requestContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,14 +48,21 @@ class AssetsExtension extends \Twig_Extension
|
|||||||
*
|
*
|
||||||
* Absolute paths (i.e. http://...) are returned unmodified.
|
* Absolute paths (i.e. http://...) are returned unmodified.
|
||||||
*
|
*
|
||||||
* @param string $path A public path
|
* @param string $path A public path
|
||||||
* @param string $packageName The name of the asset package to use
|
* @param string $packageName The name of the asset package to use
|
||||||
|
* @param Boolean $absolute Whether to return an absolute URL or a relative one
|
||||||
*
|
*
|
||||||
* @return string A public path which takes into account the base path and URL path
|
* @return string A public path which takes into account the base path and URL path
|
||||||
*/
|
*/
|
||||||
public function getAssetUrl($path, $packageName = null)
|
public function getAssetUrl($path, $packageName = null, $absolute = false)
|
||||||
{
|
{
|
||||||
return $this->container->get('templating.helper.assets')->getUrl($path, $packageName);
|
$url = $this->container->get('templating.helper.assets')->getUrl($path, $packageName);
|
||||||
|
|
||||||
|
if (!$absolute) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->ensureUrlIsAbsolute($url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,4 +86,33 @@ class AssetsExtension extends \Twig_Extension
|
|||||||
{
|
{
|
||||||
return 'assets';
|
return 'assets';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures an URL is absolute, if possible.
|
||||||
|
*
|
||||||
|
* @param string $url The URL that has to be absolute
|
||||||
|
*
|
||||||
|
* @return string The absolute URL
|
||||||
|
*/
|
||||||
|
private function ensureUrlIsAbsolute($url)
|
||||||
|
{
|
||||||
|
if (false !== strpos($url, '://') || 0 === strpos($url, '//')) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('' === $host = $this->context->getHost()) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $scheme.'://'.$host.$port.$url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
<service id="twig.extension.assets" class="%twig.extension.assets.class%" public="false">
|
<service id="twig.extension.assets" class="%twig.extension.assets.class%" public="false">
|
||||||
<tag name="twig.extension" />
|
<tag name="twig.extension" />
|
||||||
<argument type="service" id="service_container" />
|
<argument type="service" id="service_container" />
|
||||||
|
<argument type="service" id="router.request_context" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="twig.extension.actions" class="%twig.extension.actions.class%" public="false">
|
<service id="twig.extension.actions" class="%twig.extension.actions.class%" public="false">
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
<?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\TwigBundle\Tests\Extension;
|
||||||
|
|
||||||
|
use Symfony\Bundle\TwigBundle\Extension\AssetsExtension;
|
||||||
|
use Symfony\Bundle\TwigBundle\Tests\TestCase;
|
||||||
|
use Symfony\Component\Routing\RequestContext;
|
||||||
|
|
||||||
|
class AssetsExtensionTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider provideGetGetAssetUrlArguments
|
||||||
|
*/
|
||||||
|
public function testGetAssetUrl($path, $packageName, $absolute, $relativeUrl, $expectedUrl, $scheme, $host, $httpPort, $httpsPort)
|
||||||
|
{
|
||||||
|
$helper = $this->createHelperMock($path, $packageName, $relativeUrl);
|
||||||
|
$container = $this->createContainerMock($helper);
|
||||||
|
|
||||||
|
$context = $this->createRequestContextMock($scheme, $host, $httpPort, $httpsPort);
|
||||||
|
|
||||||
|
$extension = new AssetsExtension($container, $context);
|
||||||
|
$this->assertEquals($expectedUrl, $extension->getAssetUrl($path, $packageName, $absolute));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAssetWithtoutHost()
|
||||||
|
{
|
||||||
|
$path = '/path/to/asset';
|
||||||
|
$packageName = null;
|
||||||
|
$relativeUrl = '/bundle-name/path/to/asset';
|
||||||
|
|
||||||
|
$helper = $this->createHelperMock($path, $packageName, $relativeUrl);
|
||||||
|
$container = $this->createContainerMock($helper);
|
||||||
|
|
||||||
|
$context = $this->createRequestContextMock('http', '', 80, 443);
|
||||||
|
|
||||||
|
$extension = new AssetsExtension($container, $context);
|
||||||
|
$this->assertEquals($relativeUrl, $extension->getAssetUrl($path, $packageName, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideGetGetAssetUrlArguments()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('/path/to/asset', 'package-name', false, '/bundle-name/path/to/asset', '/bundle-name/path/to/asset', 'http', 'symfony.com', 80, null),
|
||||||
|
array('/path/to/asset', 'package-name', false, 'http://subdomain.symfony.com/bundle-name/path/to/asset', 'http://subdomain.symfony.com/bundle-name/path/to/asset', 'http', 'symfony.com', 80, null),
|
||||||
|
array('/path/to/asset', null, false, '/bundle-name/path/to/asset', '/bundle-name/path/to/asset', 'http', 'symfony.com', 80, null),
|
||||||
|
array('/path/to/asset', 'package-name', true, '/bundle-name/path/to/asset', 'http://symfony.com/bundle-name/path/to/asset', 'http', 'symfony.com', 80, null),
|
||||||
|
array('/path/to/asset', 'package-name', true, 'http://subdomain.symfony.com/bundle-name/path/to/asset', 'http://subdomain.symfony.com/bundle-name/path/to/asset', 'http', 'symfony.com', 80, null),
|
||||||
|
array('/path/to/asset', null, true, '/bundle-name/path/to/asset', 'https://symfony.com:92/bundle-name/path/to/asset', 'https', 'symfony.com', null, 92),
|
||||||
|
array('/path/to/asset', null, true, '/bundle-name/path/to/asset', 'http://symfony.com:660/bundle-name/path/to/asset', 'http', 'symfony.com', 660, null),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createRequestContextMock($scheme, $host, $httpPort, $httpsPort)
|
||||||
|
{
|
||||||
|
$context = $this->getMockBuilder('Symfony\Component\Routing\RequestContext')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$context->expects($this->any())
|
||||||
|
->method('getScheme')
|
||||||
|
->will($this->returnValue($scheme));
|
||||||
|
$context->expects($this->any())
|
||||||
|
->method('getHost')
|
||||||
|
->will($this->returnValue($host));
|
||||||
|
$context->expects($this->any())
|
||||||
|
->method('getHttpPort')
|
||||||
|
->will($this->returnValue($httpPort));
|
||||||
|
$context->expects($this->any())
|
||||||
|
->method('getHttpsPort')
|
||||||
|
->will($this->returnValue($httpsPort));
|
||||||
|
|
||||||
|
return $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createContainerMock($helper)
|
||||||
|
{
|
||||||
|
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||||
|
$container->expects($this->any())
|
||||||
|
->method('get')
|
||||||
|
->with('templating.helper.assets')
|
||||||
|
->will($this->returnValue($helper));
|
||||||
|
|
||||||
|
return $container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createHelperMock($path, $packageName, $returnValue)
|
||||||
|
{
|
||||||
|
$helper = $this->getMockBuilder('Symfony\Component\Templating\Helper\CoreAssetsHelper')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$helper->expects($this->any())
|
||||||
|
->method('getUrl')
|
||||||
|
->with($path, $packageName)
|
||||||
|
->will($this->returnValue($returnValue));
|
||||||
|
|
||||||
|
return $helper;
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,9 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/stopwatch": "~2.2",
|
"symfony/stopwatch": "~2.2",
|
||||||
"symfony/dependency-injection": "~2.0",
|
"symfony/dependency-injection": "~2.0",
|
||||||
"symfony/config": "~2.2"
|
"symfony/config": "~2.2",
|
||||||
|
"symfony/routing": "~2.1",
|
||||||
|
"symfony/templating": "~2.1"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": { "Symfony\\Bundle\\TwigBundle\\": "" }
|
"psr-0": { "Symfony\\Bundle\\TwigBundle\\": "" }
|
||||||
|
Reference in New Issue
Block a user