From 04ea06928066ab3af82a74b90a1e39042b3c483d Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 12 Jun 2018 10:48:13 +0300 Subject: [PATCH] Fixed routing issues with multisite and multilanguage (Grav 1.5 edition) (#2046) * Fixed routing issues with multisite and multilanguage (#1501) --- system/src/Grav/Common/Grav.php | 8 +-- system/src/Grav/Common/Page/Page.php | 45 +++++------- system/src/Grav/Common/Page/Pages.php | 70 ++++++++++++------- .../Common/Processors/InitializeProcessor.php | 29 +++++--- .../Common/Service/PageServiceProvider.php | 37 +++++----- system/src/Grav/Common/Twig/TwigExtension.php | 4 +- system/src/Grav/Common/Uri.php | 31 +++----- 7 files changed, 113 insertions(+), 111 deletions(-) diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index e6a49a1656..3e413c1446 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -9,7 +9,6 @@ namespace Grav\Common; use Grav\Common\Config\Config; -use Grav\Common\Language\Language; use Grav\Common\Page\Medium\ImageMedium; use Grav\Common\Page\Medium\Medium; use Grav\Common\Page\Page; @@ -205,11 +204,8 @@ public function redirect($route, $code = null) */ public function redirectLangSafe($route, $code = null) { - /** @var Language $language */ - $language = $this['language']; - - if (!$this['uri']->isExternal($route) && $language->enabled() && $language->isIncludeDefaultLanguage()) { - $this->redirect($language->getLanguage() . $route, $code); + if (!$this['uri']->isExternal($route)) { + $this->redirect($this['pages']->route($route), $code); } else { $this->redirect($route, $code); } diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index cfdffe3e68..1b1fc85c33 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1647,14 +1647,19 @@ public function canonical($include_lang = true) * Gets the url for the Page. * * @param bool $include_host Defaults false, but true would include http://yourhost.com - * @param bool $canonical true to return the canonical URL - * @param bool $include_lang + * @param bool $canonical True to return the canonical URL + * @param bool $include_base Include base url on multisite as well as language code * @param bool $raw_route * * @return string The url. */ - public function url($include_host = false, $canonical = false, $include_lang = true, $raw_route = false) + public function url($include_host = false, $canonical = false, $include_base = true, $raw_route = false) { + // Override any URL when external_url is set + if (isset($this->external_url)) { + return $this->external_url; + } + $grav = Grav::instance(); /** @var Pages $pages */ @@ -1663,41 +1668,25 @@ public function url($include_host = false, $canonical = false, $include_lang = t /** @var Config $config */ $config = $grav['config']; - /** @var Language $language */ - $language = $grav['language']; - - /** @var Uri $uri */ - $uri = $grav['uri']; - - // Override any URL when external_url is set - if (isset($this->external_url)) { - return $this->external_url; - } - - // get pre-route - if ($include_lang && $language->enabled()) { - $pre_route = $language->getLanguageURLPrefix(); - } else { - $pre_route = ''; - } + // get base route (multisite base and language) + $route = $include_base ? $pages->baseRoute() : ''; // add full route if configured to do so - if ($config->get('system.absolute_urls', false)) { + if (!$include_host && $config->get('system.absolute_urls', false)) { $include_host = true; } - // get canonical route if requested if ($canonical) { - $route = $pre_route . $this->routeCanonical(); + $route .= $this->routeCanonical(); } elseif ($raw_route) { - $route = $pre_route . $this->rawRoute(); + $route .= $this->rawRoute(); } else { - $route = $pre_route . $this->route(); + $route .= $this->route(); } - $rootUrl = $uri->rootUrl($include_host) . $pages->base(); - - $url = $rootUrl . '/' . trim($route, '/') . $this->urlExtension(); + /** @var Uri $uri */ + $uri = $grav['uri']; + $url = $uri->rootUrl($include_host) . '/' . trim($route, '/') . $this->urlExtension(); // trim trailing / if not root if ($url !== '/') { diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 2ff049d9e6..cffd89292c 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -49,7 +49,7 @@ class Pages /** * @var array|string[] */ - protected $baseUrl = []; + protected $baseRoute = []; /** * @var array|string[] @@ -120,7 +120,7 @@ public function base($path = null) if ($path !== null) { $path = trim($path, '/'); $this->base = $path ? '/' . $path : null; - $this->baseUrl = []; + $this->baseRoute = []; } return $this->base; @@ -128,39 +128,61 @@ public function base($path = null) /** * - * Get base URL for Grav pages. + * Get base route for Grav pages. * - * @param string $lang Optional language code for multilingual links. - * @param bool $absolute If true, return absolute url, if false, return relative url. Otherwise return default. + * @param string $lang Optional language code for multilingual routes. * * @return string */ - public function baseUrl($lang = null, $absolute = null) + public function baseRoute($lang = null) { - $lang = (string) $lang; - $type = $absolute === null ? 'base_url' : ($absolute ? 'base_url_absolute' : 'base_url_relative'); - $key = "{$lang} {$type}"; - - if (!isset($this->baseUrl[$key])) { - /** @var Config $config */ - $config = $this->grav['config']; + $key = $lang ?: 'default'; + if (!isset($this->baseRoute[$key])) { /** @var Language $language */ $language = $this->grav['language']; - if (!$lang) { - $lang = $language->getActive(); - } + $path_base = rtrim($this->base(), '/'); + $path_lang = $language->enabled() ? $language->getLanguageURLPrefix($lang) : ''; - $path_append = rtrim($this->grav['pages']->base(), '/'); - if ($language->getDefault() !== $lang || $config->get('system.languages.include_default_lang') === true) { - $path_append .= $lang ? '/' . $lang : ''; - } + $this->baseRoute[$key] = $path_base . $path_lang; + } + + return $this->baseRoute[$key]; + } - $this->baseUrl[$key] = $this->grav[$type] . $path_append; + /** + * + * Get route for Grav site. + * + * @param string $route Optional route to the page. + * @param string $lang Optional language code for multilingual links. + * + * @return string + */ + public function route($route = '/', $lang = null) + { + if (!$route || $route === '/') { + return $this->baseRoute($lang) ?: '/'; } - return $this->baseUrl[$key]; + return $this->baseRoute($lang) . $route; + } + + /** + * + * Get base URL for Grav pages. + * + * @param string $lang Optional language code for multilingual links. + * @param bool|null $absolute If true, return absolute url, if false, return relative url. Otherwise return default. + * + * @return string + */ + public function baseUrl($lang = null, $absolute = null) + { + $type = $absolute === null ? 'base_url' : ($absolute ? 'base_url_absolute' : 'base_url_relative'); + + return $this->grav[$type] . $this->baseRoute($lang); } /** @@ -179,7 +201,7 @@ public function homeUrl($lang = null, $absolute = null) /** * - * Get home URL for Grav site. + * Get URL for Grav site. * * @param string $route Optional route to the page. * @param string $lang Optional language code for multilingual links. @@ -189,7 +211,7 @@ public function homeUrl($lang = null, $absolute = null) */ public function url($route = '/', $lang = null, $absolute = null) { - if ($route === '/') { + if (!$route || $route === '/') { return $this->homeUrl($lang, $absolute); } diff --git a/system/src/Grav/Common/Processors/InitializeProcessor.php b/system/src/Grav/Common/Processors/InitializeProcessor.php index e3f25691c9..96e6a7e805 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -8,6 +8,10 @@ namespace Grav\Common\Processors; +use Grav\Common\Config\Config; +use Grav\Common\Uri; +use Grav\Common\Utils; + class InitializeProcessor extends ProcessorBase implements ProcessorInterface { public $id = 'init'; @@ -15,29 +19,36 @@ class InitializeProcessor extends ProcessorBase implements ProcessorInterface public function process() { - $this->container['config']->debug(); + /** @var Config $config */ + $config = $this->container['config']; + $config->debug(); // Use output buffering to prevent headers from being sent too early. ob_start(); - if ($this->container['config']->get('system.cache.gzip')) { + if ($config->get('system.cache.gzip') && !@ob_start('ob_gzhandler')) { // Enable zip/deflate with a fallback in case of if browser does not support compressing. - if (!@ob_start("ob_gzhandler")) { - ob_start(); - } + ob_start(); } // Initialize the timezone. - if ($this->container['config']->get('system.timezone')) { + if ($config->get('system.timezone')) { date_default_timezone_set($this->container['config']->get('system.timezone')); } // FIXME: Initialize session should happen later after plugins have been loaded. This is a workaround to fix session issues in AWS. - if ($this->container['config']->get('system.session.initialize', 1) && isset($this->container['session'])) { + if (isset($this->container['session']) && $config->get('system.session.initialize', true)) { $this->container['session']->init(); } - // Initialize uri. - $this->container['uri']->init(); + /** @var Uri $uri */ + $uri = $this->container['uri']; + $uri->init(); + + // Redirect pages with trailing slash if configured to do so. + $path = $uri->path() ?: '/'; + if ($path !== '/' && $config->get('system.pages.redirect_trailing_slash', false) && Utils::endsWith($path, '/')) { + $this->container->redirect(rtrim($path, '/'), 302); + } $this->container->setLocale(); } diff --git a/system/src/Grav/Common/Service/PageServiceProvider.php b/system/src/Grav/Common/Service/PageServiceProvider.php index bf55f791b4..ccfa58089a 100644 --- a/system/src/Grav/Common/Service/PageServiceProvider.php +++ b/system/src/Grav/Common/Service/PageServiceProvider.php @@ -8,6 +8,7 @@ namespace Grav\Common\Service; +use Grav\Common\Config\Config; use Grav\Common\Grav; use Grav\Common\Language\Language; use Grav\Common\Page\Page; @@ -26,35 +27,33 @@ public function register(Container $container) /** @var Pages $pages */ $pages = $c['pages']; + /** @var Config $config */ + $config = $c['config']; + /** @var Uri $uri */ $uri = $c['uri']; - $path = $uri->path(); // Don't trim to support trailing slash default routes - $path = $path ?: '/'; - + $path = $uri->path() ?: '/'; // Don't trim to support trailing slash default routes $page = $pages->dispatch($path); // Redirection tests if ($page) { - /** @var Language $language */ - $language = $c['language']; - // some debugger override logic if ($page->debugger() === false) { $c['debugger']->enabled(false); } - if ($c['config']->get('system.force_ssl')) { - if (!isset($_SERVER['HTTPS']) || $_SERVER["HTTPS"] != "on") { - $url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; + if ($config->get('system.force_ssl')) { + if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') { + $url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $c->redirect($url); } } - $url = $page->route(); + $url = $pages->route($page->route()); if ($uri->params()) { - if ($url == '/') { //Avoid double slash + if ($url === '/') { //Avoid double slash $url = $uri->params(); } else { $url .= $uri->params(); @@ -67,18 +66,16 @@ public function register(Container $container) $url .= '#' . $uri->fragment(); } + /** @var Language $language */ + $language = $c['language']; + // Language-specific redirection scenarios - if ($language->enabled()) { - if ($language->isLanguageInUrl() && !$language->isIncludeDefaultLanguage()) { - $c->redirect($url); - } - if (!$language->isLanguageInUrl() && $language->isIncludeDefaultLanguage()) { - $c->redirectLangSafe($url); - } + if ($language->enabled() && ($language->isLanguageInUrl() xor $language->isIncludeDefaultLanguage())) { + $c->redirect($url); } // Default route test and redirect - if ($c['config']->get('system.pages.redirect_default_route') && $page->route() != $path) { - $c->redirectLangSafe($url); + if ($config->get('system.pages.redirect_default_route') && $page->route() !== $path) { + $c->redirect($url); } } diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php index f9446e993b..37e8751d97 100644 --- a/system/src/Grav/Common/Twig/TwigExtension.php +++ b/system/src/Grav/Common/Twig/TwigExtension.php @@ -748,7 +748,7 @@ public function dump(\Twig_Environment $env, $context) * Output a Gist * * @param string $id - * @param string $file + * @param string|bool $file * * @return string */ @@ -976,7 +976,7 @@ public function regexFilter($array, $regex, $flags = 0) { public function redirectFunc($url, $statusCode = 303) { header('Location: ' . $url, true, $statusCode); - die(); + exit(); } /** diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index 2995374d88..affbf7a33a 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -11,6 +11,7 @@ use Grav\Common\Config\Config; use Grav\Common\Language\Language; use Grav\Common\Page\Page; +use Grav\Common\Page\Pages; use Grav\Framework\Route\RouteFactory; use Grav\Framework\Uri\UriFactory; use Grav\Framework\Uri\UriPartsFilter; @@ -157,12 +158,6 @@ public function init() $uri = str_replace($setup_base, '', $uri); } - // If configured to, redirect trailing slash URI's with a 302 redirect - $redirect = str_replace($this->root, '', rtrim($uri, '/')); - if ($redirect && $uri !== '/' && $redirect !== $this->base() && $config->get('system.pages.redirect_trailing_slash', false) && Utils::endsWith($uri, '/')) { - $grav->redirect($redirect, 302); - } - // process params $uri = $this->processParams($uri, $config->get('system.param_sep')); @@ -207,9 +202,9 @@ public function init() } // Set some Grav stuff - $grav['base_url_absolute'] = $grav['config']->get('system.custom_base_url') ?: $this->rootUrl(true); + $grav['base_url_absolute'] = $config->get('system.custom_base_url') ?: $this->rootUrl(true); $grav['base_url_relative'] = $this->rootUrl(false); - $grav['base_url'] = $grav['config']->get('system.absolute_urls') ? $grav['base_url_absolute'] : $grav['base_url_relative']; + $grav['base_url'] = $config->get('system.absolute_urls') ? $grav['base_url_absolute'] : $grav['base_url_relative']; RouteFactory::setRoot($this->root_path); RouteFactory::setLanguage($language->getLanguageURLPrefix()); @@ -482,11 +477,9 @@ public function uri($include_root = true) { if ($include_root) { return $this->uri; - } else { - $uri = str_replace($this->root_path, '', $this->uri); - return $uri; } + return str_replace($this->root_path, '', $this->uri); } /** @@ -509,16 +502,10 @@ public function baseIncludingLanguage() { $grav = Grav::instance(); - // Link processing should prepend language - $language = $grav['language']; - $language_append = ''; - if ($language->enabled()) { - $language_append = $language->getLanguageURLPrefix(); - } - - $base = $grav['base_url_relative']; + /** @var Pages $pages */ + $pages = $grav['pages']; - return rtrim($base . $grav['pages']->base(), '/') . $language_append; + return $pages->baseUrl(null, false); } /** @@ -1263,7 +1250,7 @@ public function post($element = null, $filter_type = null) { if (!$this->post) { $content_type = $this->getContentType(); - if ($content_type == 'application/json') { + if ($content_type === 'application/json') { $json = file_get_contents('php://input'); $this->post = json_decode($json, true); } elseif (!empty($_POST)) { @@ -1271,7 +1258,7 @@ public function post($element = null, $filter_type = null) } } - if ($this->post && !is_null($element)) { + if ($this->post && null !== $element) { $item = Utils::getDotNotation($this->post, $element); if ($filter_type) { $item = filter_var($item, $filter_type);