From 5a319144abeed3b69f7c7c352a4e2ba3f2ae2efd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jan 2015 14:15:09 +0100 Subject: [PATCH 1/2] added an absolute_url() Twig function --- CHANGELOG.md | 5 ++ Extension/HttpFoundationExtension.php | 72 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 Extension/HttpFoundationExtension.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 4be010ba..7fba4782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +2.7.0 +----- + + * added an HttpFoundation extension (provides the `absolute_url` function) + 2.5.0 ----- diff --git a/Extension/HttpFoundationExtension.php b/Extension/HttpFoundationExtension.php new file mode 100644 index 00000000..44e710f2 --- /dev/null +++ b/Extension/HttpFoundationExtension.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Extension; + +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Asset\Packages; + +/** + * Twig extension for the Symfony HttpFoundation component. + * + * @author Fabien Potencier + */ +class HttpFoundationExtension extends \Twig_Extension +{ + private $requestStack; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + } + + /** + * {@inheritdoc} + */ + public function getFunctions() + { + return array( + new \Twig_SimpleFunction('absolute_url', array($this, 'generateAbsoluteUrl')), + ); + } + + /** + * Returns the absolute URL for the given path. + * + * This method returns the path unchanged if no request is available. + * + * @param string $path The path + * + * @return string The absolute URL + */ + public function generateAbsoluteUrl($path) + { + if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { + return $path; + } + + if (!$request = $this->requestStack->getMasterRequest()) { + return $path; + } + + return $request->getUriForPath($path); + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'request'; + } +} From 8fa9050742fc564836900de4361d9a50dd976739 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jan 2015 14:25:19 +0100 Subject: [PATCH 2/2] added a relative_path Twig function --- CHANGELOG.md | 2 +- Extension/HttpFoundationExtension.php | 41 +++++++++- .../Extension/HttpFoundationExtensionTest.php | 74 +++++++++++++++++++ 3 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 Tests/Extension/HttpFoundationExtensionTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fba4782..c4df599b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 2.7.0 ----- - * added an HttpFoundation extension (provides the `absolute_url` function) + * added an HttpFoundation extension (provides the `absolute_url` and the `relative_path` functions) 2.5.0 ----- diff --git a/Extension/HttpFoundationExtension.php b/Extension/HttpFoundationExtension.php index 44e710f2..e21a8899 100644 --- a/Extension/HttpFoundationExtension.php +++ b/Extension/HttpFoundationExtension.php @@ -12,7 +12,7 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Asset\Packages; +use Symfony\Component\HttpFoundation\Request; /** * Twig extension for the Symfony HttpFoundation component. @@ -35,17 +35,20 @@ public function getFunctions() { return array( new \Twig_SimpleFunction('absolute_url', array($this, 'generateAbsoluteUrl')), + new \Twig_SimpleFunction('relative_path', array($this, 'generateRelativePath')), ); } /** - * Returns the absolute URL for the given path. + * Returns the absolute URL for the given absolute or relative path. * * This method returns the path unchanged if no request is available. * * @param string $path The path * * @return string The absolute URL + * + * @see Request::getUriForPath() */ public function generateAbsoluteUrl($path) { @@ -57,9 +60,43 @@ public function generateAbsoluteUrl($path) return $path; } + if (!$path || '/' !== $path[0]) { + $prefix = $request->getPathInfo(); + $last = strlen($prefix) - 1; + if ($last !== $pos = strrpos($prefix, '/')) { + $prefix = substr($prefix, 0, $pos).'/'; + } + + $path = $prefix.$path; + } + return $request->getUriForPath($path); } + /** + * Returns a relative path based on the current Request. + * + * This method returns the path unchanged if no request is available. + * + * @param string $path The path + * + * @return string The relative path + * + * @see Request::getRelativeUriForPath() + */ + public function generateRelativePath($path) + { + if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { + return $path; + } + + if (!$request = $this->requestStack->getMasterRequest()) { + return $path; + } + + return $request->getRelativeUriForPath($path); + } + /** * Returns the name of the extension. * diff --git a/Tests/Extension/HttpFoundationExtensionTest.php b/Tests/Extension/HttpFoundationExtensionTest.php new file mode 100644 index 00000000..228cc3fc --- /dev/null +++ b/Tests/Extension/HttpFoundationExtensionTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use Symfony\Bridge\Twig\Extension\HttpFoundationExtension; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Request; + +class HttpFoundationExtensionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getGenerateAbsoluteUrlData() + */ + public function testGenerateAbsoluteUrl($expected, $path, $pathinfo) + { + $stack = new RequestStack(); + $stack->push(Request::create($pathinfo)); + $extension = new HttpFoundationExtension($stack); + + $this->assertEquals($expected, $extension->generateAbsoluteUrl($path)); + } + + public function getGenerateAbsoluteUrlData() + { + return array( + array('http://localhost/foo.png', '/foo.png', '/foo/bar.html'), + array('http://localhost/foo/foo.png', 'foo.png', '/foo/bar.html'), + array('http://localhost/foo/foo.png', 'foo.png', '/foo/bar'), + array('http://localhost/foo/bar/foo.png', 'foo.png', '/foo/bar/'), + + array('http://example.com/baz', 'http://example.com/baz', '/'), + array('https://example.com/baz', 'https://example.com/baz', '/'), + array('//example.com/baz', '//example.com/baz', '/'), + ); + } + + /** + * @dataProvider getGenerateRelativePathData() + */ + public function testGenerateRelativePath($expected, $path, $pathinfo) + { + if (!method_exists('Symfony\Component\HttpFoundation\Request', 'getRelativeUriForPath')) { + $this->markTestSkipped('Your version of Symfony HttpFoundation is too old.'); + } + + $stack = new RequestStack(); + $stack->push(Request::create($pathinfo)); + $extension = new HttpFoundationExtension($stack); + + $this->assertEquals($expected, $extension->generateRelativePath($path)); + } + + public function getGenerateRelativePathData() + { + return array( + array('../foo.png', '/foo.png', '/foo/bar.html'), + array('../baz/foo.png', '/baz/foo.png', '/foo/bar.html'), + array('baz/foo.png', 'baz/foo.png', '/foo/bar.html'), + + array('http://example.com/baz', 'http://example.com/baz', '/'), + array('https://example.com/baz', 'https://example.com/baz', '/'), + array('//example.com/baz', '//example.com/baz', '/'), + ); + } +}