126 lines
2.9 KiB
PHP
126 lines
2.9 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Kirby\Cms;
|
||
|
|
|
||
|
|
use Exception;
|
||
|
|
use Kirby\Exception\NotFoundException;
|
||
|
|
use Kirby\Http\Router;
|
||
|
|
use Kirby\Toolkit\A;
|
||
|
|
use Kirby\Toolkit\Str;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The language router is used internally
|
||
|
|
* to handle language-specific (scoped) routes
|
||
|
|
*
|
||
|
|
* @package Kirby Cms
|
||
|
|
* @author Bastian Allgeier <bastian@getkirby.com>
|
||
|
|
* @link https://getkirby.com
|
||
|
|
* @copyright Bastian Allgeier
|
||
|
|
* @license https://getkirby.com/license
|
||
|
|
*/
|
||
|
|
class LanguageRouter
|
||
|
|
{
|
||
|
|
protected Router $router;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates a new language router instance
|
||
|
|
* for the given language
|
||
|
|
*/
|
||
|
|
public function __construct(
|
||
|
|
protected Language $language
|
||
|
|
) {
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetches all scoped routes for the
|
||
|
|
* current language from the Kirby instance
|
||
|
|
*
|
||
|
|
* @throws \Kirby\Exception\NotFoundException
|
||
|
|
*/
|
||
|
|
public function routes(): array
|
||
|
|
{
|
||
|
|
$language = $this->language;
|
||
|
|
$kirby = $language->kirby();
|
||
|
|
$routes = $kirby->routes();
|
||
|
|
|
||
|
|
// only keep the scoped language routes
|
||
|
|
$routes = array_values(array_filter($routes, function ($route) use ($language) {
|
||
|
|
// no language scope
|
||
|
|
if (empty($route['language']) === true) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// wildcard
|
||
|
|
if ($route['language'] === '*') {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// get all applicable languages
|
||
|
|
$languages = Str::split(strtolower($route['language']), '|');
|
||
|
|
|
||
|
|
// validate the language
|
||
|
|
return in_array($language->code(), $languages) === true;
|
||
|
|
}));
|
||
|
|
|
||
|
|
// add the page-scope if necessary
|
||
|
|
foreach ($routes as $index => $route) {
|
||
|
|
if ($pageId = ($route['page'] ?? null)) {
|
||
|
|
if ($page = $kirby->page($pageId)) {
|
||
|
|
// convert string patterns to arrays
|
||
|
|
$patterns = A::wrap($route['pattern']);
|
||
|
|
|
||
|
|
// prefix all patterns with the page slug
|
||
|
|
$patterns = A::map(
|
||
|
|
$patterns,
|
||
|
|
fn ($pattern) => $page->uri($language) . '/' . $pattern
|
||
|
|
);
|
||
|
|
|
||
|
|
// re-inject the pattern and the full page object
|
||
|
|
$routes[$index]['pattern'] = $patterns;
|
||
|
|
$routes[$index]['page'] = $page;
|
||
|
|
} else {
|
||
|
|
throw new NotFoundException('The page "' . $pageId . '" does not exist');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $routes;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Wrapper around the Router::call method
|
||
|
|
* that injects the Language instance and
|
||
|
|
* if needed also the Page as arguments.
|
||
|
|
*/
|
||
|
|
public function call(string|null $path = null): mixed
|
||
|
|
{
|
||
|
|
$language = $this->language;
|
||
|
|
$kirby = $language->kirby();
|
||
|
|
$this->router ??= new Router($this->routes());
|
||
|
|
|
||
|
|
try {
|
||
|
|
return $this->router->call($path, $kirby->request()->method(), function ($route) use ($kirby, $language) {
|
||
|
|
$kirby->setCurrentTranslation($language);
|
||
|
|
$kirby->setCurrentLanguage($language);
|
||
|
|
|
||
|
|
if ($page = $route->page()) {
|
||
|
|
return $route->action()->call(
|
||
|
|
$route,
|
||
|
|
$language,
|
||
|
|
$page,
|
||
|
|
...$route->arguments()
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $route->action()->call(
|
||
|
|
$route,
|
||
|
|
$language,
|
||
|
|
...$route->arguments()
|
||
|
|
);
|
||
|
|
});
|
||
|
|
} catch (Exception) {
|
||
|
|
return $kirby->resolve($path, $language->code());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|