From 98982086c2484953083f2f7029b5c4bc7489ec64 Mon Sep 17 00:00:00 2001 From: Andreas Schempp Date: Tue, 27 Aug 2024 10:14:30 +0200 Subject: [PATCH] Add setting to prioritize root page for countries --- config/services.yml | 4 ++ contao/dca/tl_page.php | 26 +++++++ contao/languages/en/tl_page.xlf | 13 ++++ .../Compiler/RouteFilterPass.php | 5 +- src/Routing/CountryPriorityFilter.php | 68 +++++++++++++++++++ 5 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 contao/dca/tl_page.php create mode 100644 contao/languages/en/tl_page.xlf create mode 100644 src/Routing/CountryPriorityFilter.php diff --git a/config/services.yml b/config/services.yml index 995d15c..708d9e8 100644 --- a/config/services.yml +++ b/config/services.yml @@ -72,3 +72,7 @@ services: Terminal42\Geoip2CountryBundle\Routing\CountryRestrictionFilter: arguments: - '@Terminal42\Geoip2CountryBundle\CountryProvider' + - + Terminal42\Geoip2CountryBundle\Routing\CountryPriorityFilter: + arguments: + - '@Terminal42\Geoip2CountryBundle\CountryProvider' diff --git a/contao/dca/tl_page.php b/contao/dca/tl_page.php new file mode 100644 index 0000000..d388706 --- /dev/null +++ b/contao/dca/tl_page.php @@ -0,0 +1,26 @@ +addField('geoip_priority', 'language_legend', PaletteManipulator::POSITION_APPEND) + ->applyToPalette('root', 'tl_page') + ->applyToPalette('rootfallback', 'tl_page') +; + +$GLOBALS['TL_DCA']['tl_page']['fields'] += [ + 'geoip_priority' => [ + 'exclude' => true, + 'inputType' => 'select', + 'options_callback' => static fn () => System::getContainer()->get('contao.intl.countries')->getCountries(), + 'eval' => [ + 'includeBlankOption' => true, + 'multiple' => true, + 'chosen' => true, + 'csv' => ',', + 'tl_class' => 'clr w50', + ], + 'sql' => ['type' => 'string', 'length' => 255, 'default' => ''], + ], +]; diff --git a/contao/languages/en/tl_page.xlf b/contao/languages/en/tl_page.xlf new file mode 100644 index 0000000..9d6f632 --- /dev/null +++ b/contao/languages/en/tl_page.xlf @@ -0,0 +1,13 @@ + + + + + + GeoIP Priority + + + Select countries where this root page should have priority regardless of browser language detection. + + + + diff --git a/src/DependencyInjection/Compiler/RouteFilterPass.php b/src/DependencyInjection/Compiler/RouteFilterPass.php index cbeeb86..e3d43f4 100644 --- a/src/DependencyInjection/Compiler/RouteFilterPass.php +++ b/src/DependencyInjection/Compiler/RouteFilterPass.php @@ -7,6 +7,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Terminal42\Geoip2CountryBundle\Routing\CountryPriorityFilter; use Terminal42\Geoip2CountryBundle\Routing\CountryRestrictionFilter; class RouteFilterPass implements CompilerPassInterface @@ -21,6 +22,8 @@ public function process(ContainerBuilder $container): void return; } - $container->getDefinition($this->serviceId)->addMethodCall('addRouteFilter', [new Reference(CountryRestrictionFilter::class)]); + $service = $container->getDefinition($this->serviceId); + $service->addMethodCall('addRouteFilter', [new Reference(CountryRestrictionFilter::class)]); + $service->addMethodCall('addRouteFilter', [new Reference(CountryPriorityFilter::class), 1]); } } diff --git a/src/Routing/CountryPriorityFilter.php b/src/Routing/CountryPriorityFilter.php new file mode 100644 index 0000000..555c1df --- /dev/null +++ b/src/Routing/CountryPriorityFilter.php @@ -0,0 +1,68 @@ +countryProvider->getCountryCode($request); + $map = []; + + foreach ($collection as $name => $route) { + $pageModel = $route->getDefault('pageModel'); + + if ( + !$pageModel instanceof PageModel + && !str_ends_with($name, '.root') + && !str_ends_with($name, '.fallback') + ) { + continue; + } + + $map[$name] = $this->hasPriority($this->getRootPage($pageModel), $country); + $hasPriority = $hasPriority ?: $map[$name]; + } + + if ($hasPriority) { + foreach ($map as $name => $priority) { + if (!$priority) { + $collection->remove($name); + continue; + } + + // Fake page to be fallback to fix Contao\CoreBundle\Routing\Matcher\LanguageFilter + $collection->get($name)->getDefault('pageModel')->rootIsFallback = true; + } + } + + return $collection; + } + + private function getRootPage(PageModel $pageModel): PageModel + { + if ('root' === $pageModel->type) { + return $pageModel; + } + + return PageModel::findById($pageModel->loadDetails()->rootId); + } + + private function hasPriority(PageModel $pageModel, string $country): bool + { + return \in_array($country, explode(',', (string) $pageModel->geoip_priority), true); + } +}