30790084ed5176bbf8f3a06931e9685dfb162c77
[yaffs-website] / vendor / symfony / routing / Tests / Generator / UrlGeneratorTest.php
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\Generator;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Routing\RouteCollection;
16 use Symfony\Component\Routing\Route;
17 use Symfony\Component\Routing\Generator\UrlGenerator;
18 use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
19 use Symfony\Component\Routing\RequestContext;
20
21 class UrlGeneratorTest extends TestCase
22 {
23     public function testAbsoluteUrlWithPort80()
24     {
25         $routes = $this->getRoutes('test', new Route('/testing'));
26         $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL);
27
28         $this->assertEquals('http://localhost/app.php/testing', $url);
29     }
30
31     public function testAbsoluteSecureUrlWithPort443()
32     {
33         $routes = $this->getRoutes('test', new Route('/testing'));
34         $url = $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL);
35
36         $this->assertEquals('https://localhost/app.php/testing', $url);
37     }
38
39     public function testAbsoluteUrlWithNonStandardPort()
40     {
41         $routes = $this->getRoutes('test', new Route('/testing'));
42         $url = $this->getGenerator($routes, array('httpPort' => 8080))->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL);
43
44         $this->assertEquals('http://localhost:8080/app.php/testing', $url);
45     }
46
47     public function testAbsoluteSecureUrlWithNonStandardPort()
48     {
49         $routes = $this->getRoutes('test', new Route('/testing'));
50         $url = $this->getGenerator($routes, array('httpsPort' => 8080, 'scheme' => 'https'))->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL);
51
52         $this->assertEquals('https://localhost:8080/app.php/testing', $url);
53     }
54
55     public function testRelativeUrlWithoutParameters()
56     {
57         $routes = $this->getRoutes('test', new Route('/testing'));
58         $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH);
59
60         $this->assertEquals('/app.php/testing', $url);
61     }
62
63     public function testRelativeUrlWithParameter()
64     {
65         $routes = $this->getRoutes('test', new Route('/testing/{foo}'));
66         $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_PATH);
67
68         $this->assertEquals('/app.php/testing/bar', $url);
69     }
70
71     public function testRelativeUrlWithNullParameter()
72     {
73         $routes = $this->getRoutes('test', new Route('/testing.{format}', array('format' => null)));
74         $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH);
75
76         $this->assertEquals('/app.php/testing', $url);
77     }
78
79     /**
80      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
81      */
82     public function testRelativeUrlWithNullParameterButNotOptional()
83     {
84         $routes = $this->getRoutes('test', new Route('/testing/{foo}/bar', array('foo' => null)));
85         // This must raise an exception because the default requirement for "foo" is "[^/]+" which is not met with these params.
86         // Generating path "/testing//bar" would be wrong as matching this route would fail.
87         $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH);
88     }
89
90     public function testRelativeUrlWithOptionalZeroParameter()
91     {
92         $routes = $this->getRoutes('test', new Route('/testing/{page}'));
93         $url = $this->getGenerator($routes)->generate('test', array('page' => 0), UrlGeneratorInterface::ABSOLUTE_PATH);
94
95         $this->assertEquals('/app.php/testing/0', $url);
96     }
97
98     public function testNotPassedOptionalParameterInBetween()
99     {
100         $routes = $this->getRoutes('test', new Route('/{slug}/{page}', array('slug' => 'index', 'page' => 0)));
101         $this->assertSame('/app.php/index/1', $this->getGenerator($routes)->generate('test', array('page' => 1)));
102         $this->assertSame('/app.php/', $this->getGenerator($routes)->generate('test'));
103     }
104
105     public function testRelativeUrlWithExtraParameters()
106     {
107         $routes = $this->getRoutes('test', new Route('/testing'));
108         $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_PATH);
109
110         $this->assertEquals('/app.php/testing?foo=bar', $url);
111     }
112
113     public function testAbsoluteUrlWithExtraParameters()
114     {
115         $routes = $this->getRoutes('test', new Route('/testing'));
116         $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL);
117
118         $this->assertEquals('http://localhost/app.php/testing?foo=bar', $url);
119     }
120
121     public function testUrlWithNullExtraParameters()
122     {
123         $routes = $this->getRoutes('test', new Route('/testing'));
124         $url = $this->getGenerator($routes)->generate('test', array('foo' => null), UrlGeneratorInterface::ABSOLUTE_URL);
125
126         $this->assertEquals('http://localhost/app.php/testing', $url);
127     }
128
129     public function testUrlWithExtraParametersFromGlobals()
130     {
131         $routes = $this->getRoutes('test', new Route('/testing'));
132         $generator = $this->getGenerator($routes);
133         $context = new RequestContext('/app.php');
134         $context->setParameter('bar', 'bar');
135         $generator->setContext($context);
136         $url = $generator->generate('test', array('foo' => 'bar'));
137
138         $this->assertEquals('/app.php/testing?foo=bar', $url);
139     }
140
141     public function testUrlWithGlobalParameter()
142     {
143         $routes = $this->getRoutes('test', new Route('/testing/{foo}'));
144         $generator = $this->getGenerator($routes);
145         $context = new RequestContext('/app.php');
146         $context->setParameter('foo', 'bar');
147         $generator->setContext($context);
148         $url = $generator->generate('test', array());
149
150         $this->assertEquals('/app.php/testing/bar', $url);
151     }
152
153     public function testGlobalParameterHasHigherPriorityThanDefault()
154     {
155         $routes = $this->getRoutes('test', new Route('/{_locale}', array('_locale' => 'en')));
156         $generator = $this->getGenerator($routes);
157         $context = new RequestContext('/app.php');
158         $context->setParameter('_locale', 'de');
159         $generator->setContext($context);
160         $url = $generator->generate('test', array());
161
162         $this->assertSame('/app.php/de', $url);
163     }
164
165     /**
166      * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
167      */
168     public function testGenerateWithoutRoutes()
169     {
170         $routes = $this->getRoutes('foo', new Route('/testing/{foo}'));
171         $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL);
172     }
173
174     /**
175      * @expectedException \Symfony\Component\Routing\Exception\MissingMandatoryParametersException
176      */
177     public function testGenerateForRouteWithoutMandatoryParameter()
178     {
179         $routes = $this->getRoutes('test', new Route('/testing/{foo}'));
180         $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL);
181     }
182
183     /**
184      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
185      */
186     public function testGenerateForRouteWithInvalidOptionalParameter()
187     {
188         $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
189         $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL);
190     }
191
192     /**
193      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
194      */
195     public function testGenerateForRouteWithInvalidParameter()
196     {
197         $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => '1|2')));
198         $this->getGenerator($routes)->generate('test', array('foo' => '0'), UrlGeneratorInterface::ABSOLUTE_URL);
199     }
200
201     public function testGenerateForRouteWithInvalidOptionalParameterNonStrict()
202     {
203         $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
204         $generator = $this->getGenerator($routes);
205         $generator->setStrictRequirements(false);
206         $this->assertNull($generator->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL));
207     }
208
209     public function testGenerateForRouteWithInvalidOptionalParameterNonStrictWithLogger()
210     {
211         $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
212         $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
213         $logger->expects($this->once())
214             ->method('error');
215         $generator = $this->getGenerator($routes, array(), $logger);
216         $generator->setStrictRequirements(false);
217         $this->assertNull($generator->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL));
218     }
219
220     public function testGenerateForRouteWithInvalidParameterButDisabledRequirementsCheck()
221     {
222         $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+')));
223         $generator = $this->getGenerator($routes);
224         $generator->setStrictRequirements(null);
225         $this->assertSame('/app.php/testing/bar', $generator->generate('test', array('foo' => 'bar')));
226     }
227
228     /**
229      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
230      */
231     public function testGenerateForRouteWithInvalidMandatoryParameter()
232     {
233         $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+')));
234         $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL);
235     }
236
237     /**
238      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
239      */
240     public function testRequiredParamAndEmptyPassed()
241     {
242         $routes = $this->getRoutes('test', new Route('/{slug}', array(), array('slug' => '.+')));
243         $this->getGenerator($routes)->generate('test', array('slug' => ''));
244     }
245
246     public function testSchemeRequirementDoesNothingIfSameCurrentScheme()
247     {
248         $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('http')));
249         $this->assertEquals('/app.php/', $this->getGenerator($routes)->generate('test'));
250
251         $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('https')));
252         $this->assertEquals('/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test'));
253     }
254
255     public function testSchemeRequirementForcesAbsoluteUrl()
256     {
257         $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('https')));
258         $this->assertEquals('https://localhost/app.php/', $this->getGenerator($routes)->generate('test'));
259
260         $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('http')));
261         $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test'));
262     }
263
264     public function testSchemeRequirementCreatesUrlForFirstRequiredScheme()
265     {
266         $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('Ftp', 'https')));
267         $this->assertEquals('ftp://localhost/app.php/', $this->getGenerator($routes)->generate('test'));
268     }
269
270     public function testPathWithTwoStartingSlashes()
271     {
272         $routes = $this->getRoutes('test', new Route('//path-and-not-domain'));
273
274         // this must not generate '//path-and-not-domain' because that would be a network path
275         $this->assertSame('/path-and-not-domain', $this->getGenerator($routes, array('BaseUrl' => ''))->generate('test'));
276     }
277
278     public function testNoTrailingSlashForMultipleOptionalParameters()
279     {
280         $routes = $this->getRoutes('test', new Route('/category/{slug1}/{slug2}/{slug3}', array('slug2' => null, 'slug3' => null)));
281
282         $this->assertEquals('/app.php/category/foo', $this->getGenerator($routes)->generate('test', array('slug1' => 'foo')));
283     }
284
285     public function testWithAnIntegerAsADefaultValue()
286     {
287         $routes = $this->getRoutes('test', new Route('/{default}', array('default' => 0)));
288
289         $this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo')));
290     }
291
292     public function testNullForOptionalParameterIsIgnored()
293     {
294         $routes = $this->getRoutes('test', new Route('/test/{default}', array('default' => 0)));
295
296         $this->assertEquals('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => null)));
297     }
298
299     public function testQueryParamSameAsDefault()
300     {
301         $routes = $this->getRoutes('test', new Route('/test', array('page' => 1)));
302
303         $this->assertSame('/app.php/test?page=2', $this->getGenerator($routes)->generate('test', array('page' => 2)));
304         $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('page' => 1)));
305         $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('page' => '1')));
306         $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test'));
307     }
308
309     public function testArrayQueryParamSameAsDefault()
310     {
311         $routes = $this->getRoutes('test', new Route('/test', array('array' => array('foo', 'bar'))));
312
313         $this->assertSame('/app.php/test?array%5B0%5D=bar&array%5B1%5D=foo', $this->getGenerator($routes)->generate('test', array('array' => array('bar', 'foo'))));
314         $this->assertSame('/app.php/test?array%5Ba%5D=foo&array%5Bb%5D=bar', $this->getGenerator($routes)->generate('test', array('array' => array('a' => 'foo', 'b' => 'bar'))));
315         $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('array' => array('foo', 'bar'))));
316         $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('array' => array(1 => 'bar', 0 => 'foo'))));
317         $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test'));
318     }
319
320     public function testGenerateWithSpecialRouteName()
321     {
322         $routes = $this->getRoutes('$péß^a|', new Route('/bar'));
323
324         $this->assertSame('/app.php/bar', $this->getGenerator($routes)->generate('$péß^a|'));
325     }
326
327     public function testUrlEncoding()
328     {
329         // This tests the encoding of reserved characters that are used for delimiting of URI components (defined in RFC 3986)
330         // and other special ASCII chars. These chars are tested as static text path, variable path and query param.
331         $chars = '@:[]/()*\'" +,;-._~&$<>|{}%\\^`!?foo=bar#id';
332         $routes = $this->getRoutes('test', new Route("/$chars/{varpath}", array(), array('varpath' => '.+')));
333         $this->assertSame('/app.php/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id'
334            .'/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id'
335            .'?query=%40%3A%5B%5D/%28%29%2A%27%22+%2B%2C%3B-._%7E%26%24%3C%3E%7C%7B%7D%25%5C%5E%60%21%3Ffoo%3Dbar%23id',
336             $this->getGenerator($routes)->generate('test', array(
337                 'varpath' => $chars,
338                 'query' => $chars,
339             ))
340         );
341     }
342
343     public function testEncodingOfRelativePathSegments()
344     {
345         $routes = $this->getRoutes('test', new Route('/dir/../dir/..'));
346         $this->assertSame('/app.php/dir/%2E%2E/dir/%2E%2E', $this->getGenerator($routes)->generate('test'));
347         $routes = $this->getRoutes('test', new Route('/dir/./dir/.'));
348         $this->assertSame('/app.php/dir/%2E/dir/%2E', $this->getGenerator($routes)->generate('test'));
349         $routes = $this->getRoutes('test', new Route('/a./.a/a../..a/...'));
350         $this->assertSame('/app.php/a./.a/a../..a/...', $this->getGenerator($routes)->generate('test'));
351     }
352
353     public function testAdjacentVariables()
354     {
355         $routes = $this->getRoutes('test', new Route('/{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '\d+')));
356         $generator = $this->getGenerator($routes);
357         $this->assertSame('/app.php/foo123', $generator->generate('test', array('x' => 'foo', 'y' => '123')));
358         $this->assertSame('/app.php/foo123bar.xml', $generator->generate('test', array('x' => 'foo', 'y' => '123', 'z' => 'bar', '_format' => 'xml')));
359
360         // The default requirement for 'x' should not allow the separator '.' in this case because it would otherwise match everything
361         // and following optional variables like _format could never match.
362         $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Routing\Exception\InvalidParameterException');
363         $generator->generate('test', array('x' => 'do.t', 'y' => '123', 'z' => 'bar', '_format' => 'xml'));
364     }
365
366     public function testOptionalVariableWithNoRealSeparator()
367     {
368         $routes = $this->getRoutes('test', new Route('/get{what}', array('what' => 'All')));
369         $generator = $this->getGenerator($routes);
370
371         $this->assertSame('/app.php/get', $generator->generate('test'));
372         $this->assertSame('/app.php/getSites', $generator->generate('test', array('what' => 'Sites')));
373     }
374
375     public function testRequiredVariableWithNoRealSeparator()
376     {
377         $routes = $this->getRoutes('test', new Route('/get{what}Suffix'));
378         $generator = $this->getGenerator($routes);
379
380         $this->assertSame('/app.php/getSitesSuffix', $generator->generate('test', array('what' => 'Sites')));
381     }
382
383     public function testDefaultRequirementOfVariable()
384     {
385         $routes = $this->getRoutes('test', new Route('/{page}.{_format}'));
386         $generator = $this->getGenerator($routes);
387
388         $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', array('page' => 'index', '_format' => 'mobile.html')));
389     }
390
391     /**
392      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
393      */
394     public function testDefaultRequirementOfVariableDisallowsSlash()
395     {
396         $routes = $this->getRoutes('test', new Route('/{page}.{_format}'));
397         $this->getGenerator($routes)->generate('test', array('page' => 'index', '_format' => 'sl/ash'));
398     }
399
400     /**
401      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
402      */
403     public function testDefaultRequirementOfVariableDisallowsNextSeparator()
404     {
405         $routes = $this->getRoutes('test', new Route('/{page}.{_format}'));
406         $this->getGenerator($routes)->generate('test', array('page' => 'do.t', '_format' => 'html'));
407     }
408
409     public function testWithHostDifferentFromContext()
410     {
411         $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com'));
412
413         $this->assertEquals('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', array('name' => 'Fabien', 'locale' => 'fr')));
414     }
415
416     public function testWithHostSameAsContext()
417     {
418         $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com'));
419
420         $this->assertEquals('/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' => 'Fabien', 'locale' => 'fr')));
421     }
422
423     public function testWithHostSameAsContextAndAbsolute()
424     {
425         $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com'));
426
427         $this->assertEquals('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL));
428     }
429
430     /**
431      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
432      */
433     public function testUrlWithInvalidParameterInHost()
434     {
435         $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com'));
436         $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH);
437     }
438
439     /**
440      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
441      */
442     public function testUrlWithInvalidParameterInHostWhenParamHasADefaultValue()
443     {
444         $routes = $this->getRoutes('test', new Route('/', array('foo' => 'bar'), array('foo' => 'bar'), array(), '{foo}.example.com'));
445         $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH);
446     }
447
448     /**
449      * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException
450      */
451     public function testUrlWithInvalidParameterEqualsDefaultValueInHost()
452     {
453         $routes = $this->getRoutes('test', new Route('/', array('foo' => 'baz'), array('foo' => 'bar'), array(), '{foo}.example.com'));
454         $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH);
455     }
456
457     public function testUrlWithInvalidParameterInHostInNonStrictMode()
458     {
459         $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com'));
460         $generator = $this->getGenerator($routes);
461         $generator->setStrictRequirements(false);
462         $this->assertNull($generator->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH));
463     }
464
465     public function testHostIsCaseInsensitive()
466     {
467         $routes = $this->getRoutes('test', new Route('/', array(), array('locale' => 'en|de|fr'), array(), '{locale}.FooBar.com'));
468         $generator = $this->getGenerator($routes);
469         $this->assertSame('//EN.FooBar.com/app.php/', $generator->generate('test', array('locale' => 'EN'), UrlGeneratorInterface::NETWORK_PATH));
470     }
471
472     /**
473      * @group legacy
474      */
475     public function testLegacyGenerateNetworkPath()
476     {
477         $routes = $this->getRoutes('test', new Route('/{name}', array(), array('_scheme' => 'http'), array(), '{locale}.example.com'));
478
479         $this->assertSame('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
480             array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'network path with different host'
481         );
482         $this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test',
483             array('name' => 'Fabien', 'locale' => 'fr', 'query' => 'string'), UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context'
484         );
485         $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test',
486             array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context'
487         );
488         $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
489             array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested'
490         );
491     }
492
493     public function testGenerateNetworkPath()
494     {
495         $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com', array('http')));
496
497         $this->assertSame('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
498             array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'network path with different host'
499         );
500         $this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test',
501             array('name' => 'Fabien', 'locale' => 'fr', 'query' => 'string'), UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context'
502         );
503         $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test',
504             array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context'
505         );
506         $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
507             array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested'
508         );
509     }
510
511     public function testGenerateRelativePath()
512     {
513         $routes = new RouteCollection();
514         $routes->add('article', new Route('/{author}/{article}/'));
515         $routes->add('comments', new Route('/{author}/{article}/comments'));
516         $routes->add('host', new Route('/{article}', array(), array(), array(), '{author}.example.com'));
517         $routes->add('scheme', new Route('/{author}/blog', array(), array(), array(), '', array('https')));
518         $routes->add('unrelated', new Route('/about'));
519
520         $generator = $this->getGenerator($routes, array('host' => 'example.com', 'pathInfo' => '/fabien/symfony-is-great/'));
521
522         $this->assertSame('comments', $generator->generate('comments',
523             array('author' => 'fabien', 'article' => 'symfony-is-great'), UrlGeneratorInterface::RELATIVE_PATH)
524         );
525         $this->assertSame('comments?page=2', $generator->generate('comments',
526             array('author' => 'fabien', 'article' => 'symfony-is-great', 'page' => 2), UrlGeneratorInterface::RELATIVE_PATH)
527         );
528         $this->assertSame('../twig-is-great/', $generator->generate('article',
529             array('author' => 'fabien', 'article' => 'twig-is-great'), UrlGeneratorInterface::RELATIVE_PATH)
530         );
531         $this->assertSame('../../bernhard/forms-are-great/', $generator->generate('article',
532             array('author' => 'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH)
533         );
534         $this->assertSame('//bernhard.example.com/app.php/forms-are-great', $generator->generate('host',
535             array('author' => 'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH)
536         );
537         $this->assertSame('https://example.com/app.php/bernhard/blog', $generator->generate('scheme',
538                 array('author' => 'bernhard'), UrlGeneratorInterface::RELATIVE_PATH)
539         );
540         $this->assertSame('../../about', $generator->generate('unrelated',
541             array(), UrlGeneratorInterface::RELATIVE_PATH)
542         );
543     }
544
545     /**
546      * @dataProvider provideRelativePaths
547      */
548     public function testGetRelativePath($sourcePath, $targetPath, $expectedPath)
549     {
550         $this->assertSame($expectedPath, UrlGenerator::getRelativePath($sourcePath, $targetPath));
551     }
552
553     public function provideRelativePaths()
554     {
555         return array(
556             array(
557                 '/same/dir/',
558                 '/same/dir/',
559                 '',
560             ),
561             array(
562                 '/same/file',
563                 '/same/file',
564                 '',
565             ),
566             array(
567                 '/',
568                 '/file',
569                 'file',
570             ),
571             array(
572                 '/',
573                 '/dir/file',
574                 'dir/file',
575             ),
576             array(
577                 '/dir/file.html',
578                 '/dir/different-file.html',
579                 'different-file.html',
580             ),
581             array(
582                 '/same/dir/extra-file',
583                 '/same/dir/',
584                 './',
585             ),
586             array(
587                 '/parent/dir/',
588                 '/parent/',
589                 '../',
590             ),
591             array(
592                 '/parent/dir/extra-file',
593                 '/parent/',
594                 '../',
595             ),
596             array(
597                 '/a/b/',
598                 '/x/y/z/',
599                 '../../x/y/z/',
600             ),
601             array(
602                 '/a/b/c/d/e',
603                 '/a/c/d',
604                 '../../../c/d',
605             ),
606             array(
607                 '/a/b/c//',
608                 '/a/b/c/',
609                 '../',
610             ),
611             array(
612                 '/a/b/c/',
613                 '/a/b/c//',
614                 './/',
615             ),
616             array(
617                 '/root/a/b/c/',
618                 '/root/x/b/c/',
619                 '../../../x/b/c/',
620             ),
621             array(
622                 '/a/b/c/d/',
623                 '/a',
624                 '../../../../a',
625             ),
626             array(
627                 '/special-chars/sp%20ce/1€/mäh/e=mc²',
628                 '/special-chars/sp%20ce/1€/<µ>/e=mc²',
629                 '../<µ>/e=mc²',
630             ),
631             array(
632                 'not-rooted',
633                 'dir/file',
634                 'dir/file',
635             ),
636             array(
637                 '//dir/',
638                 '',
639                 '../../',
640             ),
641             array(
642                 '/dir/',
643                 '/dir/file:with-colon',
644                 './file:with-colon',
645             ),
646             array(
647                 '/dir/',
648                 '/dir/subdir/file:with-colon',
649                 'subdir/file:with-colon',
650             ),
651             array(
652                 '/dir/',
653                 '/dir/:subdir/',
654                 './:subdir/',
655             ),
656         );
657     }
658
659     protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null)
660     {
661         $context = new RequestContext('/app.php');
662         foreach ($parameters as $key => $value) {
663             $method = 'set'.$key;
664             $context->$method($value);
665         }
666
667         return new UrlGenerator($routes, $context, $logger);
668     }
669
670     protected function getRoutes($name, Route $route)
671     {
672         $routes = new RouteCollection();
673         $routes->add($name, $route);
674
675         return $routes;
676     }
677 }