From 9fcfb802e6636bf31dc64126052379b57db1907f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 2 Jun 2017 22:24:49 +0300 Subject: [PATCH 1/4] 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 | 66 ++++++++++++------- .../Common/Processors/InitializeProcessor.php | 22 ++++++- .../Common/Service/PageServiceProvider.php | 31 ++++----- system/src/Grav/Common/Twig/TwigExtension.php | 11 ++-- system/src/Grav/Common/Uri.php | 10 --- 7 files changed, 104 insertions(+), 89 deletions(-) diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index a260ec95f7..1c71ee2fdc 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 c177a6a843..51174551aa 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1580,13 +1580,18 @@ 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 */ @@ -1595,41 +1600,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 d3b5f86b26..d5220cf729 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -48,7 +48,7 @@ class Pages /** * @var array|string[] */ - protected $baseUrl = []; + protected $baseRoute = []; /** * @var array|string[] @@ -127,39 +127,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 $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); } /** @@ -188,7 +210,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 734eb8211b..4adc297e5c 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -8,6 +8,9 @@ namespace Grav\Common\Processors; +use Grav\Common\Uri; +use Grav\Common\Utils; + class InitializeProcessor extends ProcessorBase implements ProcessorInterface { public $id = 'init'; @@ -15,7 +18,8 @@ class InitializeProcessor extends ProcessorBase implements ProcessorInterface public function process() { - $this->container['config']->debug(); + $config = $this->container['config']; + $config->debug(); // Use output buffering to prevent headers from being sent too early. ob_start(); @@ -33,7 +37,21 @@ public function process() // Initialize uri, session. $this->container['session']->init(); - $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 ($config->get('system.pages.redirect_trailing_slash', false) && $path !== '/' && Utils::endsWith($path, '/')) { + $this->container->redirect(rtrim($path, '/')); + } + + // Set some Grav stuff + $this->container['base_url_absolute'] = $config->get('system.custom_base_url') ?: $uri->rootUrl(true); + $this->container['base_url_relative'] = $uri->rootUrl(false); + $this->container['base_url'] = $config->get('system.absolute_urls') ? $this->container['base_url_absolute'] : $this->container['base_url_relative']; $this->container->setLocale(); } diff --git a/system/src/Grav/Common/Service/PageServiceProvider.php b/system/src/Grav/Common/Service/PageServiceProvider.php index 13a0b8fe29..ac7c5992c2 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,32 +27,30 @@ 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) { Grav::instance()['debugger']->enabled(false); } - if ($c['config']->get('system.force_ssl')) { + 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 @@ -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 bde56608b8..553bff9000 100644 --- a/system/src/Grav/Common/Twig/TwigExtension.php +++ b/system/src/Grav/Common/Twig/TwigExtension.php @@ -337,7 +337,7 @@ public function base64DecodeFilter($str) * @param string $filter * @param array|int $direction * - * @return string + * @return array */ public function sortByKeyFilter(array $input, $filter, $direction = SORT_ASC) { @@ -744,7 +744,7 @@ public function dump(\Twig_Environment $env, $context) * Output a Gist * * @param string $id - * @param string $file + * @param string|bool $file * * @return string */ @@ -803,7 +803,7 @@ public function arrayFunc($value) * * @param string $key key of item * @param string $val value of item - * @param string $current_array optional array to add to + * @param array $current_array optional array to add to * * @return array */ @@ -941,7 +941,7 @@ public function regexReplace($subject, $pattern, $replace, $limit = -1) public function redirectFunc($url, $statusCode = 303) { header('Location: ' . $url, true, $statusCode); - die(); + exit(); } /** @@ -1004,6 +1004,8 @@ public function exifFunc($image, $raw = false) } } } + + return null; } /** @@ -1025,6 +1027,7 @@ public function mediaFunc($media_dir) return new Media($media_dir); } + return null; } /** diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index bb95c77ec8..878adfa929 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -295,11 +295,6 @@ public function init() $uri = str_replace($setup_base, '', $uri); } - // If configured to, redirect trailing slash URI's with a 301 redirect - if ($config->get('system.pages.redirect_trailing_slash', false) && $uri != '/' && Utils::endsWith($uri, '/')) { - $grav->redirect(str_replace($this->root, '', rtrim($uri, '/')), 301); - } - // process params $uri = $this->processParams($uri, $config->get('system.param_sep')); @@ -349,11 +344,6 @@ public function init() if ($this->content_path != '') { $this->paths = explode('/', $this->content_path); } - - // Set some Grav stuff - $grav['base_url_absolute'] = $grav['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']; } /** From ad498b5de8b1826745f71080cf853c7d1fce5b82 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 5 Jun 2017 09:37:05 +0300 Subject: [PATCH 2/4] Fix unit tests (#1501) --- system/src/Grav/Common/Processors/InitializeProcessor.php | 5 ----- system/src/Grav/Common/Uri.php | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/system/src/Grav/Common/Processors/InitializeProcessor.php b/system/src/Grav/Common/Processors/InitializeProcessor.php index 4adc297e5c..33f188de4b 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -48,11 +48,6 @@ public function process() $this->container->redirect(rtrim($path, '/')); } - // Set some Grav stuff - $this->container['base_url_absolute'] = $config->get('system.custom_base_url') ?: $uri->rootUrl(true); - $this->container['base_url_relative'] = $uri->rootUrl(false); - $this->container['base_url'] = $config->get('system.absolute_urls') ? $this->container['base_url_absolute'] : $this->container['base_url_relative']; - $this->container->setLocale(); } } diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index 878adfa929..73513ebaa0 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -344,6 +344,11 @@ public function init() if ($this->content_path != '') { $this->paths = explode('/', $this->content_path); } + + // Set some Grav stuff + $grav['base_url_absolute'] = $config->get('system.custom_base_url') ?: $this->rootUrl(true); + $grav['base_url_relative'] = $this->rootUrl(false); + $grav['base_url'] = $config->get('system.absolute_urls') ? $grav['base_url_absolute'] : $grav['base_url_relative']; } /** From 5d000f1dd6d9fbf3f53e399ff51724587131fef3 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 1 Jun 2018 11:12:39 +0300 Subject: [PATCH 3/4] Code cleanup --- system/src/Grav/Common/Page/Pages.php | 6 +++--- .../Grav/Common/Processors/InitializeProcessor.php | 12 +++++------- .../src/Grav/Common/Service/PageServiceProvider.php | 8 ++++---- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index c34c371bb6..dbf91431ce 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -173,8 +173,8 @@ public function route($route = '/', $lang = null) * * Get base URL 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 links. + * @param bool|null $absolute If true, return absolute url, if false, return relative url. Otherwise return default. * * @return string */ @@ -201,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. diff --git a/system/src/Grav/Common/Processors/InitializeProcessor.php b/system/src/Grav/Common/Processors/InitializeProcessor.php index d5efce2a20..96e6a7e805 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -25,20 +25,18 @@ public function process() // 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(); } @@ -48,7 +46,7 @@ public function process() // Redirect pages with trailing slash if configured to do so. $path = $uri->path() ?: '/'; - if ($config->get('system.pages.redirect_trailing_slash', false) && $path !== '/' && Utils::endsWith($path, '/')) { + if ($path !== '/' && $config->get('system.pages.redirect_trailing_slash', false) && Utils::endsWith($path, '/')) { $this->container->redirect(rtrim($path, '/'), 302); } diff --git a/system/src/Grav/Common/Service/PageServiceProvider.php b/system/src/Grav/Common/Service/PageServiceProvider.php index 0b292a2525..ccfa58089a 100644 --- a/system/src/Grav/Common/Service/PageServiceProvider.php +++ b/system/src/Grav/Common/Service/PageServiceProvider.php @@ -44,8 +44,8 @@ public function register(Container $container) } if ($config->get('system.force_ssl')) { - if (!isset($_SERVER['HTTPS']) || $_SERVER["HTTPS"] != "on") { - $url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; + if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') { + $url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $c->redirect($url); } } @@ -53,7 +53,7 @@ public function register(Container $container) $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(); @@ -74,7 +74,7 @@ public function register(Container $container) $c->redirect($url); } // Default route test and redirect - if ($config->get('system.pages.redirect_default_route') && $page->route() != $path) { + if ($config->get('system.pages.redirect_default_route') && $page->route() !== $path) { $c->redirect($url); } } From 2eac670efbbc685a2db02e498f3b8cd764d10196 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 1 Jun 2018 11:53:00 +0300 Subject: [PATCH 4/4] Remove some duplicated code --- system/src/Grav/Common/Page/Pages.php | 2 +- system/src/Grav/Common/Uri.php | 21 +++++++-------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index dbf91431ce..cffd89292c 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -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; diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index b26dac1263..ccc2fbd2db 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; @@ -476,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); } /** @@ -503,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); } /** @@ -1243,7 +1236,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)) { @@ -1251,7 +1244,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);