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 12namespace Symfony\Component\Routing\Tests\Generator\Dumper; 13 14use PHPUnit\Framework\TestCase; 15use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; 16use Symfony\Component\Routing\Generator\UrlGeneratorInterface; 17use Symfony\Component\Routing\RequestContext; 18use Symfony\Component\Routing\Route; 19use Symfony\Component\Routing\RouteCollection; 20 21/** 22 * @group legacy 23 */ 24class PhpGeneratorDumperTest extends TestCase 25{ 26 /** 27 * @var RouteCollection 28 */ 29 private $routeCollection; 30 31 /** 32 * @var PhpGeneratorDumper 33 */ 34 private $generatorDumper; 35 36 /** 37 * @var string 38 */ 39 private $testTmpFilepath; 40 41 /** 42 * @var string 43 */ 44 private $largeTestTmpFilepath; 45 46 protected function setUp(): void 47 { 48 parent::setUp(); 49 50 $this->routeCollection = new RouteCollection(); 51 $this->generatorDumper = new PhpGeneratorDumper($this->routeCollection); 52 $this->testTmpFilepath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_generator.'.$this->getName().'.php'; 53 $this->largeTestTmpFilepath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_generator.'.$this->getName().'.large.php'; 54 @unlink($this->testTmpFilepath); 55 @unlink($this->largeTestTmpFilepath); 56 } 57 58 protected function tearDown(): void 59 { 60 parent::tearDown(); 61 62 @unlink($this->testTmpFilepath); 63 64 $this->routeCollection = null; 65 $this->generatorDumper = null; 66 $this->testTmpFilepath = null; 67 } 68 69 public function testDumpWithRoutes() 70 { 71 $this->routeCollection->add('Test', new Route('/testing/{foo}')); 72 $this->routeCollection->add('Test2', new Route('/testing2')); 73 74 file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); 75 include $this->testTmpFilepath; 76 77 $projectUrlGenerator = new \ProjectUrlGenerator(new RequestContext('/app.php')); 78 79 $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); 80 $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); 81 $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); 82 $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); 83 84 $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); 85 $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); 86 $this->assertEquals('/app.php/testing/bar', $relativeUrlWithParameter); 87 $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); 88 } 89 90 public function testDumpWithSimpleLocalizedRoutes() 91 { 92 $this->routeCollection->add('test', (new Route('/foo'))); 93 $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'en')); 94 $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'nl')); 95 96 $code = $this->generatorDumper->dump([ 97 'class' => 'SimpleLocalizedProjectUrlGenerator', 98 ]); 99 file_put_contents($this->testTmpFilepath, $code); 100 include $this->testTmpFilepath; 101 102 $context = new RequestContext('/app.php'); 103 $projectUrlGenerator = new \SimpleLocalizedProjectUrlGenerator($context, null, 'en'); 104 105 $urlWithDefaultLocale = $projectUrlGenerator->generate('test'); 106 $urlWithSpecifiedLocale = $projectUrlGenerator->generate('test', ['_locale' => 'nl']); 107 $context->setParameter('_locale', 'en'); 108 $urlWithEnglishContext = $projectUrlGenerator->generate('test'); 109 $context->setParameter('_locale', 'nl'); 110 $urlWithDutchContext = $projectUrlGenerator->generate('test'); 111 112 $this->assertEquals('/app.php/testing/is/fun', $urlWithDefaultLocale); 113 $this->assertEquals('/app.php/testen/is/leuk', $urlWithSpecifiedLocale); 114 $this->assertEquals('/app.php/testing/is/fun', $urlWithEnglishContext); 115 $this->assertEquals('/app.php/testen/is/leuk', $urlWithDutchContext); 116 117 // test with full route name 118 $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test.en')); 119 120 $context->setParameter('_locale', 'de_DE'); 121 // test that it fall backs to another route when there is no matching localized route 122 $this->assertEquals('/app.php/foo', $projectUrlGenerator->generate('test')); 123 } 124 125 public function testDumpWithRouteNotFoundLocalizedRoutes() 126 { 127 $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); 128 $this->expectExceptionMessage('Unable to generate a URL for the named route "test" as such route does not exist.'); 129 $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'en')); 130 131 $code = $this->generatorDumper->dump([ 132 'class' => 'RouteNotFoundLocalizedProjectUrlGenerator', 133 ]); 134 file_put_contents($this->testTmpFilepath, $code); 135 include $this->testTmpFilepath; 136 137 $projectUrlGenerator = new \RouteNotFoundLocalizedProjectUrlGenerator(new RequestContext('/app.php'), null, 'pl_PL'); 138 $projectUrlGenerator->generate('test'); 139 } 140 141 public function testDumpWithFallbackLocaleLocalizedRoutes() 142 { 143 $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'en')); 144 $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'nl')); 145 $this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'fr')); 146 147 $code = $this->generatorDumper->dump([ 148 'class' => 'FallbackLocaleLocalizedProjectUrlGenerator', 149 ]); 150 file_put_contents($this->testTmpFilepath, $code); 151 include $this->testTmpFilepath; 152 153 $context = new RequestContext('/app.php'); 154 $context->setParameter('_locale', 'en_GB'); 155 $projectUrlGenerator = new \FallbackLocaleLocalizedProjectUrlGenerator($context, null, null); 156 157 // test with context _locale 158 $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test')); 159 // test with parameters _locale 160 $this->assertEquals('/app.php/testen/is/leuk', $projectUrlGenerator->generate('test', ['_locale' => 'nl_BE'])); 161 162 $projectUrlGenerator = new \FallbackLocaleLocalizedProjectUrlGenerator(new RequestContext('/app.php'), null, 'fr_CA'); 163 // test with default locale 164 $this->assertEquals('/app.php/tester/est/amusant', $projectUrlGenerator->generate('test')); 165 } 166 167 public function testDumpWithTooManyRoutes() 168 { 169 $this->routeCollection->add('Test', new Route('/testing/{foo}')); 170 for ($i = 0; $i < 32769; ++$i) { 171 $this->routeCollection->add('route_'.$i, new Route('/route_'.$i)); 172 } 173 $this->routeCollection->add('Test2', new Route('/testing2')); 174 175 file_put_contents($this->largeTestTmpFilepath, $this->generatorDumper->dump([ 176 'class' => 'ProjectLargeUrlGenerator', 177 ])); 178 $this->routeCollection = $this->generatorDumper = null; 179 include $this->largeTestTmpFilepath; 180 181 $projectUrlGenerator = new \ProjectLargeUrlGenerator(new RequestContext('/app.php')); 182 183 $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); 184 $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); 185 $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); 186 $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); 187 188 $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); 189 $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); 190 $this->assertEquals('/app.php/testing/bar', $relativeUrlWithParameter); 191 $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); 192 } 193 194 public function testDumpWithoutRoutes() 195 { 196 $this->expectException('InvalidArgumentException'); 197 file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'WithoutRoutesUrlGenerator'])); 198 include $this->testTmpFilepath; 199 200 $projectUrlGenerator = new \WithoutRoutesUrlGenerator(new RequestContext('/app.php')); 201 202 $projectUrlGenerator->generate('Test', []); 203 } 204 205 public function testGenerateNonExistingRoute() 206 { 207 $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); 208 $this->routeCollection->add('Test', new Route('/test')); 209 210 file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'NonExistingRoutesUrlGenerator'])); 211 include $this->testTmpFilepath; 212 213 $projectUrlGenerator = new \NonExistingRoutesUrlGenerator(new RequestContext()); 214 $projectUrlGenerator->generate('NonExisting', []); 215 } 216 217 public function testDumpForRouteWithDefaults() 218 { 219 $this->routeCollection->add('Test', new Route('/testing/{foo}', ['foo' => 'bar'])); 220 221 file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'DefaultRoutesUrlGenerator'])); 222 include $this->testTmpFilepath; 223 224 $projectUrlGenerator = new \DefaultRoutesUrlGenerator(new RequestContext()); 225 $url = $projectUrlGenerator->generate('Test', []); 226 227 $this->assertEquals('/testing', $url); 228 } 229 230 public function testDumpWithSchemeRequirement() 231 { 232 $this->routeCollection->add('Test1', new Route('/testing', [], [], [], '', ['ftp', 'https'])); 233 234 file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'SchemeUrlGenerator'])); 235 include $this->testTmpFilepath; 236 237 $projectUrlGenerator = new \SchemeUrlGenerator(new RequestContext('/app.php')); 238 239 $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); 240 $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); 241 242 $this->assertEquals('ftp://localhost/app.php/testing', $absoluteUrl); 243 $this->assertEquals('ftp://localhost/app.php/testing', $relativeUrl); 244 245 $projectUrlGenerator = new \SchemeUrlGenerator(new RequestContext('/app.php', 'GET', 'localhost', 'https')); 246 247 $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); 248 $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); 249 250 $this->assertEquals('https://localhost/app.php/testing', $absoluteUrl); 251 $this->assertEquals('/app.php/testing', $relativeUrl); 252 } 253 254 public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl() 255 { 256 $this->routeCollection->add('foo.en', (new Route('/{_locale}/fork'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo')->setRequirement('_locale', 'en')); 257 $this->routeCollection->add('foo.fr', (new Route('/{_locale}/fourchette'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo')->setRequirement('_locale', 'fr')); 258 $this->routeCollection->add('fun.en', (new Route('/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'fun')->setRequirement('_locale', 'en')); 259 $this->routeCollection->add('fun.fr', (new Route('/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'fun')->setRequirement('_locale', 'fr')); 260 261 file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump([ 262 'class' => 'PreserveTheGoodLocaleInTheUrlGenerator', 263 ])); 264 include $this->testTmpFilepath; 265 266 $requestContext = new RequestContext(); 267 $requestContext->setParameter('_locale', 'fr'); 268 269 $phpGenerator = new \PreserveTheGoodLocaleInTheUrlGenerator($requestContext); 270 271 $this->assertSame('/fr/fourchette', $phpGenerator->generate('foo')); 272 $this->assertSame('/en/fork', $phpGenerator->generate('foo.en')); 273 $this->assertSame('/en/fork', $phpGenerator->generate('foo', ['_locale' => 'en'])); 274 $this->assertSame('/fr/fourchette', $phpGenerator->generate('foo.fr', ['_locale' => 'en'])); 275 276 $this->assertSame('/amusant', $phpGenerator->generate('fun')); 277 $this->assertSame('/fun', $phpGenerator->generate('fun.en')); 278 $this->assertSame('/fun', $phpGenerator->generate('fun', ['_locale' => 'en'])); 279 $this->assertSame('/amusant', $phpGenerator->generate('fun.fr', ['_locale' => 'en'])); 280 } 281} 282