8000 Added UrlHelper · symfony/symfony@bb346b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit bb346b6

Browse files
committed
Added UrlHelper
1 parent 9793522 commit bb346b6

File tree

7 files changed

+286
-66
lines changed

7 files changed

+286
-66
lines changed

src/Symfony/Bridge/Twig/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ CHANGELOG
44
4.3.0
55
-----
66

7-
* added the `form_parent()` function that allows to reliably retrieve the parent form in Twig templates
7+
* added the `form_parent()` function that allows to reliably retrieve the parent form in Twig templates
8+
* deprecated `HttpFoundationExtension::generateAbsoluteUrl()` and
9+
`HttpFoundationExtension::generateRelativePath`
810

911
4.2.0
1012
-----

src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php

Lines changed: 30 additions & 63 deletions
A851
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\HttpFoundation\Request;
1515
use Symfony\Component\HttpFoundation\RequestStack;
1616
use Symfony\Component\Routing\RequestContext;
17+
use Symfony\Component\Routing\UrlHelper;
1718
use Twig\Extension\AbstractExtension;
1819
use Twig\TwigFunction;
1920

@@ -24,13 +25,27 @@
2425
*/
2526
class HttpFoundationExtension extends AbstractExtension
2627
{
27-
private $requestStack;
28-
private $requestContext;
28+
private $urlHelper;
2929

30-
public function __construct(RequestStack $requestStack, RequestContext $requestContext = null)
30+
public function __construct($urlHelper, RequestContext $requestContext = null)
3131
{
32-
$this->requestStack = $requestStack;
33-
$this->requestContext = $requestContext;
32+
if ($urlHelper instanceof UrlHelper) {
33+
$this->urlHelper = $urlHelper;
34+
35+
return;
36+
}
37+
38+
if (!$urlHelper instanceof RequestStack) {
39+
throw new \InvalidArgumentException(sprintf('The first argument must be an instance of "%s" or an instance of "%s".', UrlHelper::class, RequestStack::class));
40+
}
41+
42+
@trigger_error(sprintf('Passing an instance of "%s" as the first constructor argument is deprecated since Symfony 4.3, pass an instance of "%s" instead.', RequestStack::class, UrlHelper::class), E_USER_DEPRECATED);
43+
44+
if (2 === func_num_args()) {
45+
@trigger_error(sprintf('Passing the second argument to the constructor is deprecated since Symfony 4.3, pass an instance of "%s" as the first argument instead.', UrlHelper::class), E_USER_DEPRECATED);
46+
}
47+
48+
$this->urlHelper = new UrlHelper($urlHelper, $requestContext);
3449
}
3550

3651
/**
@@ -39,8 +54,8 @@ public function __construct(RequestStack $requestStack, RequestContext $requestC
3954
public function getFunctions()
4055
{
4156
return [
42-
new TwigFunction('absolute_url', [$this, 'generateAbsoluteUrl']),
43-
new TwigFunction('relative_path', [$this, 'generateRelativePath']),
57+
new TwigFunction('absolute_url', [$this->urlHelper, 'getAbsoluteUrl']),
58+
new TwigFunction('relative_path', [$this->urlHelper, 'getRelativePath']),
4459
];
4560
}
4661

@@ -54,58 +69,14 @@ public function getFunctions()
5469
* @return string The absolute URL
5570
*
5671
* @see Request::getUriForPath()
72+
*
73+
* @deprecated since Symfony 4.3, use Symfony\Component\Routing\UrlHelper::getAbsoluteUrl() instead
5774
*/
5875
public function generateAbsoluteUrl($path)
5976
{
60-
if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) {
61-
return $path;
62-
}
63-
64-
if (!$request = $this->requestStack->getMasterRequest()) {
65-
if (null !== $this->requestContext && '' !== $host = $this->requestContext->getHost()) {
66-
$scheme = $this->requestContext->getScheme();
67-
$port = '';
68-
69-
if ('http' === $scheme && 80 != $this->requestContext->getHttpPort()) {
70-
$port = ':'.$this->requestContext->getHttpPort();
71-
} elseif ('https' === $scheme && 443 != $this->requestContext->getHttpsPort()) {
72-
$port = ':'.$this->requestContext->getHttpsPort();
73-
}
74-
75-
if ('#' === $path[0]) {
76-
$queryString = $this->requestContext->getQueryString(); 10000
77-
$path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path;
78-
} elseif ('?' === $path[0]) {
79-
$path = $this->requestContext->getPathInfo().$path;
80-
}
77+
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.3, use "%s::getAbsoluteUrl()" instead.', __METHOD__, UrlHelper::class), E_USER_DEPRECATED);
8178

82-
if ('/' !== $path[0]) {
83-
$path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path;
84-
}
85-
86-
return $scheme.'://'.$host.$port.$path;
87-
}
88-
89-
return $path;
90-
}
91-
92-
if ('#' === $path[0]) {
93-
$path = $request->getRequestUri().$path;
94-
} elseif ('?' === $path[0]) {
95-
$path = $request->getPathInfo().$path;
96-
}
97-
98-
if (!$path || '/' !== $path[0]) {
99-
$prefix = $request->getPathInfo();
100-
$last = \strlen($prefix) - 1;
101-
if ($last !== $pos = strrpos($prefix, '/')) {
102-
$prefix = substr($prefix, 0, $pos).'/';
103-
}
104-
105-
return $request->getUriForPath($prefix.$path);
106-
}
107-
108-
return $request->getSchemeAndHttpHost().$path;
79+
return $this->urlHelper->getAbsoluteUrl($path);
10980
}
11081

11182
/**
@@ -118,18 +89,14 @@ public function generateAbsoluteUrl($path)
11889
* @return string The relative path
11990
*
12091
* @see Request::getRelativeUriForPath()
92+
*
93+
* @deprecated since Symfony 4.3, use Symfony\Component\Routing\UrlHelper::getRelativePath() instead
12194
*/
12295
public function generateRelativePath($path)
12396
{
124-
if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) {
125-
return $path;
126-
}
127-
128-
if (!$request = $this->requestStack->getMasterRequest()) {
129-
return $path;
130-
}
97+
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.3, use "%s::getRelativePath()" instead.', __METHOD__, UrlHelper::class), E_USER_DEPRECATED);
13198

132-
return $request->getRelativeUriForPath($path);
99+
return $this->urlHelper->getRelativePath($path);
133100
}
134101

135102
/**

src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@
8888
</service>
8989
<service id="Symfony\Component\Routing\RequestContext" alias="router.request_context" />
9090

91+
<service id="router.url_helper" class="Symfony\Component\Routing\UrlHelper">
92+
<argument type="service" id="request_stack" />
93+
<argument type="service" id="router.request_context" />
94+
</service>
95+
<service id="Symfony\Component\Routing\UrlHelper" alias="router.url_helper" />
96+
9197
<service id="router.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer">
9298
<tag name="container.service_subscriber" id="router" />
9399
<tag name="kernel.cache_warmer" />

src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,7 @@
108108
</service>
109109

110110
<service id="twig.extension.httpfoundation" class="Symfony\Bridge\Twig\Extension\HttpFoundationExtension">
111-
<argument type="service" id="request_stack" />
112-
<argument type="service" id="router.request_context" on-invalid="ignore" />
111+
<argument type="service" id="router.url_helper" />
113112
</service>
114113

115114
<service id="twig.extension.debug" class="Twig\Extension\DebugExtension" />

src/Symfony/Component/Routing/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ CHANGELOG
1111
* deprecated implementing `Serializable` for `Route` and `CompiledRoute`; if you serialize them, please
1212
ensure your unserialization logic can recover from a failure related to an updated serialization format
1313
* exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators
14+
* added `UrlHelper` that allows to get an absolute URL and a relative path for a given path
1415

1516
4.2.0
1617
-----
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\RequestStack;
17+
use Symfony\Component\Routing\RequestContext;
18+
use Symfony\Component\Routing\UrlHelper;
19+
20+
clas 10000 s UrlHelperTest extends TestCase
21+
{
22+
/**
23+
* @dataProvider getGenerateAbsoluteUrlData()
24+
*/
25+
public function testGenerateAbsoluteUrl($expected, $path, $pathinfo)
26+
{
27+
$stack = new RequestStack();
28+
$stack->push(Request::create($pathinfo));
29+
$helper = new UrlHelper($stack);
30+
31+
$this->assertEquals($expected, $helper->getAbsoluteUrl($path));
32+
}
33+
34+
public function getGenerateAbsoluteUrlData()
35+
{
36+
return [
37+
['http://localhost/foo.png', '/foo.png', '/foo/bar.html'],
38+
['http://localhost/foo/foo.png', 'foo.png', '/foo/bar.html'],
39+
['http://localhost/foo/foo.png', 'foo.png', '/foo/bar'],
40+
['http://localhost/foo/bar/foo.png', 'foo.png', '/foo/bar/'],
41+
42+
['http://example.com/baz', 'http://example.com/baz', '/'],
43+
['https://example.com/baz', 'https://example.com/baz', '/'],
44+
['//example.com/baz', '//example.com/baz', '/'],
45+
46+
['http://localhost/foo/bar?baz', '?baz', '/foo/bar'],
47+
['http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'],
48+
['http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'],
49+
50+
['http://localhost/foo/bar#baz', '#baz', '/foo/bar'],
51+
['http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'],
52+
['http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'],
53+
['http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'],
54+
];
55+
}
56+
57+
/**
58+
* @dataProvider getGenerateAbsoluteUrlRequestContextData
59+
*/
60+
public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected)
61+
{
62+
if (!class_exists('Symfony\Component\Routing\RequestContext')) {
63+
$this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.');
64+
}
65+
66+
$requestContext = new RequestContext($baseUrl, 'GET', $host, $scheme, $httpPort, $httpsPort, $path);
67+
$helper = new UrlHelper(new RequestStack(), $requestContext);
68+
69+
$this->assertEquals($expected, $helper->getAbsoluteUrl($path));
70+
}
71+
72+
/**
73+
* @dataProvider getGenerateAbsoluteUrlRequestContextData
74+
*/
75+
public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path)
76+
{
77+
if (!class_exists('Symfony\Component\Routing\RequestContext')) {
78+
$this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.');
79+
}
80+
81+
$helper = new UrlHelper(new RequestStack());
82+
83+
$this->assertEquals($path, $helper->getAbsoluteUrl($path));
84+
}
85+
86+
public function getGenerateAbsoluteUrlRequestContextData()
87+
{
88+
return [
89+
['/foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo.png'],
90+
['foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo/foo.png'],
91+
['foo.png', '/foo/bar/', 'localhost', 'http', 80, 443, 'http://localhost/foo/bar/foo.png'],
92+
['/foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo.png'],
93+
['foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo/foo.png'],
94+
['foo.png', '/foo/bar/', 'localhost', 'https', 80, 443, 'https://localhost/foo/bar/foo.png'],
95+
['/foo.png', '/foo', 'localhost', 'http', 443, 80, 'http://localhost:443/foo.png'],
96+
['/foo.png', '/foo', 'localhost', 'https', 443, 80, 'https://localhost:80/foo.png'],
97+
];
98+
}
99+
100+
public function testGenerateAbsoluteUrlWithScriptFileName()
101+
{
102+
$request = Request::create('http://localhost/app/web/app_dev.php');
103+
$request->server->set('SCRIPT_FILENAME', '/var/www/app/web/app_dev.php');
104+
105+
$stack = new RequestStack();
106+
$stack->push($request);
107+
$helper = new UrlHelper($stack);
108+
109+
$this->assertEquals(
110+
'http://localhost/app/web/bundles/framework/css/structure.css',
111+
$helper->getAbsoluteUrl('/app/web/bundles/framework/css/structure.css')
112+
);
113+
}
114+
115+
/**
116+
* @dataProvider getGenerateRelativePathData()
117+
*/
118+
public function testGenerateRelativePath($expected, $path, $pathinfo)
119+
{
120+
if (!method_exists('Symfony\Component\Ht B41A tpFoundation\Request', 'getRelativeUriForPath')) {
121+
$this->markTestSkipped('Your version of Symfony HttpFoundation is too old.');
122+
}
123+
124+
$stack = new RequestStack();
125+
$stack->push(Request::create($pathinfo));
126+
$urlHelper = new UrlHelper($stack);
127+
128+
$this->assertEquals($expected, $urlHelper->getRelativePath($path));
129+
}
130+
131+
public function getGenerateRelativePathData()
132+
{
133+
return [
134+
['../foo.png', '/foo.png', '/foo/bar.html'],
135+
['../baz/foo.png', '/baz/foo.png', '/foo/bar.html'],
136+
['baz/foo.png', 'baz/foo.png', '/foo/bar.html'],
137+
138+
['http://example.com/baz', 'http://example.com/baz', '/'],
139+
['https://example.com/baz', 'https://example.com/baz', '/'],
140+
['//example.com/baz', '//example.com/baz', '/'],
141+
];
142+
}
143+
}

0 commit comments

Comments
 (0)
0