Skip to content

Commit

Permalink
Rewrite the language filter to use the page properties
Browse files Browse the repository at this point in the history
  • Loading branch information
aschempp committed Apr 8, 2020
1 parent 78dfc42 commit b8616b0
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 33 deletions.
2 changes: 0 additions & 2 deletions core-bundle/src/Resources/config/services.yml
Expand Up @@ -491,8 +491,6 @@ services:

contao.routing.language_filter:
class: Contao\CoreBundle\Routing\Matcher\LanguageFilter
arguments:
- '%contao.prepend_locale%'

contao.routing.legacy_matcher:
class: Contao\CoreBundle\Routing\Matcher\LegacyMatcher
Expand Down
21 changes: 9 additions & 12 deletions core-bundle/src/Routing/Matcher/LanguageFilter.php
Expand Up @@ -22,34 +22,31 @@
*/
class LanguageFilter implements RouteFilterInterface
{
/**
* @var bool
*/
private $prependLocale;

/**
* @internal Do not inherit from this class; decorate the "contao.routing.language_filter" service instead
*/
public function __construct(bool $prependLocale)
public function __construct()
{
$this->prependLocale = $prependLocale;
}

public function filter(RouteCollection $collection, Request $request): RouteCollection
{
$languages = $request->getLanguages();

foreach ($collection->all() as $name => $route) {
if ('.fallback' !== substr($name, -9) && ($this->prependLocale || '.root' !== substr($name, -5))) {
/** @var PageModel $pageModel */
$pageModel = $route->getDefault('pageModel');

if (!$pageModel instanceof PageModel) {
continue;
}

/** @var PageModel $pageModel */
$pageModel = $route->getDefault('pageModel');
if ('.fallback' !== substr($name, -9) && ('' !== $pageModel->languagePrefix || '.root' !== substr($name, -5))) {
continue;
}

if (
!$pageModel instanceof PageModel
|| $pageModel->rootIsFallback
$pageModel->rootIsFallback
|| \in_array(str_replace('-', '_', $pageModel->rootLanguage), $languages, true)
|| preg_grep('/'.preg_quote($pageModel->rootLanguage, '/').'_[A-Z]{2}/', $languages)
) {
Expand Down
29 changes: 10 additions & 19 deletions core-bundle/tests/Routing/Matcher/LanguageFilterTest.php
Expand Up @@ -27,11 +27,11 @@ class LanguageFilterTest extends TestCase
*
* @dataProvider getRoutesAndLanguages
*/
public function testRemovesARouteIfTheAcceptedLanguagesDoNotMatch(string $name, ?PageModel $page, string $acceptLanguage, bool $expectPageModel, bool $expectRemoval, bool $prependLocale = false): void
public function testRemovesARouteIfTheAcceptedLanguagesDoNotMatch(string $name, ?PageModel $page, string $acceptLanguage, bool $expectRemoval): void
{
$route = $this->createMock(Route::class);
$route
->expects($expectPageModel ? $this->once() : $this->never())
->expects($this->once())
->method('getDefault')
->with('pageModel')
->willReturn($page)
Expand All @@ -52,74 +52,65 @@ public function testRemovesARouteIfTheAcceptedLanguagesDoNotMatch(string $name,
$request = Request::create('/');
$request->headers->set('Accept-Language', $acceptLanguage);

$filter = new LanguageFilter($prependLocale);
$filter = new LanguageFilter();
$filter->filter($collection, $request);
}

public function getRoutesAndLanguages(): \Generator
{
yield 'Removes a fallback page route if the accepted language does not match' => [
'tl_page.2.fallback',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'en']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'en', 'languagePrefix' => '']),
'de',
true,
true,
];

yield 'Removes a root page route if the accepted language does not match' => [
'tl_page.2.root',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'en']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'en', 'languagePrefix' => '']),
'de',
true,
true,
];

yield 'Does not remove a root page route if contao.prepend_locale is enabled' => [
'tl_page.2.root',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'en']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'en', 'languagePrefix' => 'en']),
'de',
false,
false,
true,
];

yield 'Does not remove a route if there is no Contao page object' => [
'tl_page.2.fallback',
null,
'de',
true,
false,
];

yield 'Does not remove a route if the root page is the language fallback' => [
'tl_page.2.root',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => true, 'rootLanguage' => 'en']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => true, 'rootLanguage' => 'en', 'languagePrefix' => '']),
'de',
true,
false,
];

yield 'Does not remove a route if the root page language is accepted' => [
'tl_page.2.root',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'de']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'de', 'languagePrefix' => '']),
'de',
true,
false,
];

yield 'Does not remove a route if the root page language with region code is accepted' => [
'tl_page.2.root',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'de']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'de', 'languagePrefix' => '']),
'de-CH',
true,
false,
];

yield 'Does not remove a route if the root page language with region code equals the accepted language' => [
'tl_page.2.root',
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'de-CH']),
$this->mockClassWithProperties(PageModel::class, ['rootIsFallback' => false, 'rootLanguage' => 'de-CH', 'languagePrefix' => '']),
'de-CH',
true,
false,
];
}
Expand Down

0 comments on commit b8616b0

Please sign in to comment.