diff --git a/core-bundle/src/DataCollector/ContaoDataCollector.php b/core-bundle/src/DataCollector/ContaoDataCollector.php index 546f8a67ae8..fa58f5da005 100644 --- a/core-bundle/src/DataCollector/ContaoDataCollector.php +++ b/core-bundle/src/DataCollector/ContaoDataCollector.php @@ -120,7 +120,8 @@ public function getAdditionalData(): array $data['classes_set'], $data['classes_aliased'], $data['classes_composerized'], - $data['database_queries'] + $data['database_queries'], + $data['legacy_routing'] ); return $data; diff --git a/core-bundle/src/Routing/Candidates/LegacyCandidates.php b/core-bundle/src/Routing/Candidates/LegacyCandidates.php index 4ba72d93df6..614c181c780 100644 --- a/core-bundle/src/Routing/Candidates/LegacyCandidates.php +++ b/core-bundle/src/Routing/Candidates/LegacyCandidates.php @@ -32,6 +32,8 @@ class LegacyCandidates extends Candidates public function __construct(bool $prependLocale, string $urlSuffix) { + // Do not call the parent constructor + $this->prependLocale = $prependLocale; $this->urlSuffix = $urlSuffix; } @@ -55,6 +57,10 @@ public function getCandidates(Request $request) private function removeSuffixAndLanguage(string $pathInfo): ?string { + if ('' === $pathInfo) { + return ''; + } + $suffixLength = \strlen($this->urlSuffix); if (0 !== $suffixLength) { diff --git a/core-bundle/src/Routing/Enhancer/InputEnhancer.php b/core-bundle/src/Routing/Enhancer/InputEnhancer.php index 5143901f6e3..18fec7bf979 100644 --- a/core-bundle/src/Routing/Enhancer/InputEnhancer.php +++ b/core-bundle/src/Routing/Enhancer/InputEnhancer.php @@ -48,7 +48,7 @@ public function enhance(array $defaults, Request $request): array /** @var Input $input */ $input = $this->framework->getAdapter(Input::class); - if ('' !== $page->urlPrefix) { + if (!empty($page->urlPrefix)) { $input->setGet('language', $page->rootLanguage); } diff --git a/core-bundle/tests/Asset/ContaoContextTest.php b/core-bundle/tests/Asset/ContaoContextTest.php index 7af271b9a65..694918474e4 100644 --- a/core-bundle/tests/Asset/ContaoContextTest.php +++ b/core-bundle/tests/Asset/ContaoContextTest.php @@ -164,6 +164,7 @@ private function getPageWithDetails(): PageModel $container = $this->getContainerWithContaoConfiguration(); $container->set('contao.resource_finder', $finder); + $container->set('request_stack', new RequestStack()); System::setContainer($container); diff --git a/core-bundle/tests/DataCollector/ContaoDataCollectorTest.php b/core-bundle/tests/DataCollector/ContaoDataCollectorTest.php index 76fa4b0a4df..a99c5d9dd0a 100644 --- a/core-bundle/tests/DataCollector/ContaoDataCollectorTest.php +++ b/core-bundle/tests/DataCollector/ContaoDataCollectorTest.php @@ -15,12 +15,16 @@ use Contao\ContentImage; use Contao\ContentText; use Contao\CoreBundle\DataCollector\ContaoDataCollector; +use Contao\CoreBundle\Tests\Fixtures\DataCollector\BundleTestClass; +use Contao\CoreBundle\Tests\Fixtures\DataCollector\TestClass; use Contao\CoreBundle\Tests\TestCase; use Contao\CoreBundle\Util\PackageUtil; use Contao\LayoutModel; use Contao\PageModel; use Contao\System; use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -35,7 +39,7 @@ public function testCollectsDataInBackEnd(): void 'additional_data' => 'data', ]; - $collector = new ContaoDataCollector(); + $collector = new ContaoDataCollector($this->createParameterBag()); $collector->collect(new Request(), new Response()); $this->assertSame(['ContentText' => ContentText::class], $collector->getClassesAliased()); @@ -52,6 +56,7 @@ public function testCollectsDataInBackEnd(): void 'preview' => false, 'layout' => '', 'template' => '', + 'legacy_routing' => false, ], $collector->getSummary() ); @@ -81,7 +86,7 @@ public function testCollectsDataInFrontEnd(): void $GLOBALS['objPage'] = $page; - $collector = new ContaoDataCollector(); + $collector = new ContaoDataCollector($this->createParameterBag()); $collector->setFramework($framework); $collector->collect(new Request(), new Response()); @@ -94,6 +99,7 @@ public function testCollectsDataInFrontEnd(): void 'preview' => false, 'layout' => 'Default (ID 2)', 'template' => 'fe_page', + 'legacy_routing' => false, ], $collector->getSummary() ); @@ -105,13 +111,100 @@ public function testCollectsDataInFrontEnd(): void unset($GLOBALS['objPage']); } + public function testStoresTheLegacyRoutingData(bool $legacyRouting = false, bool $prependLocale = false, string $urlSuffix = '.html'): void + { + $collector = new ContaoDataCollector($this->createParameterBag($legacyRouting, $prependLocale, $urlSuffix)); + $collector->collect(new Request(), new Response()); + + $this->assertSame( + [ + 'enabled' => $legacyRouting, + 'prepend_locale' => $prependLocale, + 'url_suffix' => $urlSuffix, + 'hooks' => [], + ], + $collector->getLegacyRouting() + ); + } + + public function legacyRoutingProvider(): \Generator + { + yield [false, false, '.html']; + + yield [true, false, '.html']; + + yield [true, false, '.html']; + + yield [true, true, '.html']; + + yield [true, true, '.php']; + } + + public function testIncludesTheLegacyRoutingHooks() + { + $GLOBALS['TL_HOOKS'] = [ + 'getPageIdFromUrl' => [ + [TestClass::class, 'onGetPageIdFromUrl'], + ['foo.service', 'onGetPageIdFromUrl'], + ], + 'getRootPageFromUrl' => [ + [TestClass::class, 'onGetRootPageFromUrl'], + ['bar.service', 'onGetRootPageFromUrl'], + ], + ]; + + require_once(__DIR__.'/../Fixtures/DataCollector/TestClass.php'); + require_once(__DIR__.'/../Fixtures/DataCollector/vendor/foo/bar/BundleTestClass.php'); + + $systemAdapter = $this->mockAdapter(['importStatic']); + $systemAdapter + ->expects($this->exactly(4)) + ->method('importStatic') + ->withConsecutive([TestClass::class], ['foo.service'], [TestClass::class], ['bar.service']) + ->willReturnOnConsecutiveCalls(new TestClass(), new BundleTestClass(), new TestClass(), new BundleTestClass()) + ; + + $framework = $this->mockContaoFramework([ + System::class => $systemAdapter, + ]); + + $parameterBag = $this->createParameterBag(true); + $parameterBag->set('kernel.project_dir', \dirname(__DIR__).'/Fixtures/DataCollector'); + + $collector = new ContaoDataCollector($parameterBag); + $collector->setFramework($framework); + $collector->collect(new Request(), new Response()); + + $this->assertSame( + [ + ['name' => 'getPageIdFromUrl', 'class' => TestClass::class, 'method' => 'onGetPageIdFromUrl', 'package' => ''], + ['name' => 'getPageIdFromUrl', 'class' => BundleTestClass::class, 'method' => 'onGetPageIdFromUrl', 'package' => 'foo/bar'], + ['name' => 'getRootPageFromUrl', 'class' => TestClass::class, 'method' => 'onGetRootPageFromUrl', 'package' => ''], + ['name' => 'getRootPageFromUrl', 'class' => BundleTestClass::class, 'method' => 'onGetRootPageFromUrl', 'package' => 'foo/bar'], + ], + $collector->getLegacyRouting()['hooks'] + ); + } + public function testReturnsAnEmptyArrayIfTheKeyIsUnknown(): void { - $collector = new ContaoDataCollector(); + $collector = new ContaoDataCollector($this->createParameterBag()); $method = new \ReflectionMethod($collector, 'getData'); $method->setAccessible(true); $this->assertSame([], $method->invokeArgs($collector, ['foo'])); } + + /** + * @return ParameterBagInterface + */ + private function createParameterBag(bool $legacyRouting = false, bool $prependLocale = false, string $urlSuffix = '.html'): ParameterBagInterface + { + return new ParameterBag([ + 'contao.legacy_routing' => $legacyRouting, + 'contao.prepend_locale' => $prependLocale, + 'contao.url_suffix' => $urlSuffix, + ]); + } } diff --git a/core-bundle/tests/DependencyInjection/ContaoCoreExtensionTest.php b/core-bundle/tests/DependencyInjection/ContaoCoreExtensionTest.php index 58c8a135072..7e410f1880f 100644 --- a/core-bundle/tests/DependencyInjection/ContaoCoreExtensionTest.php +++ b/core-bundle/tests/DependencyInjection/ContaoCoreExtensionTest.php @@ -3631,4 +3631,29 @@ public function testRegistersTheImageTargetPath(): void $this->assertSame($this->getTempDir().'/my/custom/dir', $container->getParameter('contao.image.target_dir')); } + + private function getContainerBuilder(array $params = null): ContainerBuilder + { + $container = new ContainerBuilder( + new ParameterBag([ + 'kernel.debug' => false, + 'kernel.project_dir' => $this->getTempDir(), + 'kernel.default_locale' => 'en', + ]) + ); + + if (null === $params) { + $params = [ + 'contao' => [ + 'encryption_key' => 'foobar', + 'localconfig' => ['foo' => 'bar'], + ], + ]; + } + + $extension = new ContaoCoreExtension(); + $extension->load($params, $container); + + return $container; + } } diff --git a/core-bundle/tests/Fixtures/DataCollector/TestClass.php b/core-bundle/tests/Fixtures/DataCollector/TestClass.php new file mode 100644 index 00000000000..b144ec9f9ff --- /dev/null +++ b/core-bundle/tests/Fixtures/DataCollector/TestClass.php @@ -0,0 +1,16 @@ +mockConnectionWithLanguages($languages); $providers = $this->mockPageProvidersWithUrlSuffix($urlSuffixes); - $candidates = (new Candidates($connection, $providers, false, '.html', false))->getCandidates($request); + $candidates = (new Candidates($connection, $providers))->getCandidates($request); $this->assertSame($expected, $candidates); } @@ -68,7 +69,7 @@ public function testGetCandidatesInLegacyMode(string $pathInfo, array $urlSuffix ->method($this->anything()) ; - $candidates = (new Candidates($connection, $providers, true, $urlSuffixes[0] ?? '', 0 !== \count($languages)))->getCandidates($request); + $candidates = (new LegacyCandidates(0 !== \count($languages), $urlSuffixes[0] ?? ''))->getCandidates($request); $this->assertSame($expected, $candidates); } @@ -88,7 +89,7 @@ public function getCandidatesProvider() ['.html'], [], ['index'], - [], + ['index'], ]; yield [ @@ -96,7 +97,7 @@ public function getCandidatesProvider() [], ['en'], ['index'], - [], + ['index'], ]; yield [ diff --git a/core-bundle/tests/Routing/RouteProviderTest.php b/core-bundle/tests/Routing/RouteProviderTest.php index ad17b570209..51d90b8ae1c 100644 --- a/core-bundle/tests/Routing/RouteProviderTest.php +++ b/core-bundle/tests/Routing/RouteProviderTest.php @@ -440,6 +440,28 @@ public function getRootRoutes(): \Generator 0 => $this->createRootPage('de', 'german-root', false), ]; + $routeNames = [ + 'tl_page.'.$pages[0]->id.'.root', + 'tl_page.'.$pages[1]->id.'.root', + 'tl_page.'.$pages[2]->id.'.root', + ]; + + yield [ + $pages, + ['de', 'en'], + $routeNames, + ]; + + $pages = [ + 2 => $this->createRootPage('en', 'english-root', true), + 1 => $this->createPage('en', 'index', true), + 0 => $this->createRootPage('de', 'german-root', false), + ]; + + $pages[0]->urlPrefix = 'en'; + $pages[1]->urlPrefix = 'en'; + $pages[2]->urlPrefix = 'de'; + $routeNames = [ 'tl_page.'.$pages[0]->id.'.root', 'tl_page.'.$pages[1]->id.'.root', @@ -671,6 +693,8 @@ private function createRootPage(string $language, string $alias, bool $fallback $page->type = 'root'; $page->alias = $alias; $page->domain = $domain; + $page->urlPrefix = ''; + $page->urlSuffix = '.html'; $page->rootLanguage = $language; $page->rootIsFallback = $fallback; $page->rootUseSSL = 'https' === $scheme;