From 25e7f6c5e8c943df66a350f71d92ec5fe8e95e75 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 12 Mar 2021 11:45:00 +0200 Subject: [PATCH 1/4] Method `$pages->find()` should never redirect --- system/src/Grav/Common/Page/Pages.php | 185 ++++++++++++++++---------- system/src/Grav/Common/Uri.php | 2 +- 2 files changed, 115 insertions(+), 72 deletions(-) diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 4f645025c..3b3ce8ef3 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -880,103 +880,146 @@ public function inherited($route, $field = null) } /** - * alias method to return find a page. + * Find a page based on route. * - * @param string $route The relative URL of the page - * @param bool $all + * @param string $route The route of the page + * @param bool $all If true, return also non-routable pages, otherwise return null if page isn't routable * @return PageInterface|null */ public function find($route, $all = false) { - return $this->dispatch($route, $all, false); + $route = urldecode((string)$route); + + // Fetch page if there's a defined route to it. + $path = $this->routes[$route] ?? null; + $page = null !== $path ? $this->get($path) : null; + + // Try without trailing slash + if (null === $page && Utils::endsWith($route, '/')) { + $path = $this->routes[rtrim($route, '/')] ?? null; + $page = null !== $path ? $this->get($path) : null; + } + + if (!$all && !isset($this->grav['admin'])) { + if (null === $page || !$page->routable()) { + // If the page cannot be accessed, look for the site wide routes and wildcards. + $page = $this->findSiteBasedRoute($route) ?? $page; + } + } + + return $page; + } + + /** + * Check site based routes. + * + * @param string $route + * @return PageInterface|null + */ + protected function findSiteBasedRoute($route) + { + /** @var Config $config */ + $config = $this->grav['config']; + + $site_routes = $config->get('site.routes'); + if (!is_array($site_routes)) { + return null; + } + + $page = null; + + // See if route matches one in the site configuration + $site_route = $site_routes[$route] ?? null; + if ($site_route) { + $page = $this->find($site_route); + } else { + // Use reverse order because of B/C (previously matched multiple and returned the last match). + foreach (array_reverse($site_routes, true) as $pattern => $replace) { + $pattern = '#^' . str_replace('/', '\/', ltrim($pattern, '^')) . '#'; + try { + $found = preg_replace($pattern, $replace, $route); + if ($found && $found !== $route) { + $page = $this->find($found); + if ($page) { + return $page; + } + } + } catch (ErrorException $e) { + $this->grav['log']->error('site.routes: ' . $pattern . '-> ' . $e->getMessage()); + } + } + } + + return $page; } /** * Dispatch URI to a page. * * @param string $route The relative URL of the page - * @param bool $all - * @param bool $redirect + * @param bool $all If true, return also non-routable pages, otherwise return null if page isn't routable + * @param bool $redirect If true, allow redirects * @return PageInterface|null * @throws Exception */ public function dispatch($route, $all = false, $redirect = true) { - $route = urldecode($route); + $page = $this->find($route, true); - // Fetch page if there's a defined route to it. - $path = $this->routes[$route] ?? null; - $page = null !== $path ? $this->get($path) : null; - // Try without trailing slash - if (!$page && Utils::endsWith($route, '/')) { - $path = $this->routes[rtrim($route, '/')] ?? null; - $page = null !== $path ? $this->get($path) : null; + // If we want all pages or are in admin, return what we already have. + if ($all || isset($this->grav['admin'])) { + return $page; } - // Are we in the admin? this is important! - $not_admin = !isset($this->grav['admin']); + if ($page) { + $routable = $page->routable(); + if ($redirect) { + if ($page->redirect()) { + // Follow a redirect page. + $this->grav->redirectLangSafe($page->redirect()); + } + + if (!$routable && ($child = $page->children()->visible()->routable()->published()->first()) !== null) { + // Redirect to the first visible child as current page isn't routable. + $this->grav->redirectLangSafe($child->route()); + } + } - // If the page cannot be reached, look into site wide redirects, routes + wildcards - if (!$all && $not_admin) { - // If the page is a simple redirect, just do it. - if ($redirect && $page && $page->redirect()) { - $this->grav->redirectLangSafe($page->redirect()); + if ($routable) { + return $page; } + } - // fall back and check site based redirects - if (!$page || !$page->routable()) { - // Redirect to the first child (placeholder page) - if ($redirect && $page && count($children = $page->children()->visible()->routable()->published()) > 0) { - $this->grav->redirectLangSafe($children->first()->route()); - } + $route = urldecode((string)$route); - /** @var Config $config */ - $config = $this->grav['config']; + // The page cannot be reached, look into site wide redirects, routes and wildcards. + $redirectedPage = $this->findSiteBasedRoute($route); + if ($redirectedPage) { + $page = $this->dispatch($redirectedPage->route(), false, $redirect); + } - // See if route matches one in the site configuration - $site_route = $config->get("site.routes.{$route}"); - if ($site_route) { - $page = $this->dispatch($site_route, $all, $redirect); - } else { - /** @var Uri $uri */ - $uri = $this->grav['uri']; - /** @var \Grav\Framework\Uri\Uri $source_url */ - $source_url = $uri->uri(false); - - // Try Regex style redirects - $site_redirects = $config->get('site.redirects'); - if (is_array($site_redirects)) { - foreach ((array)$site_redirects as $pattern => $replace) { - $pattern = ltrim($pattern, '^'); - $pattern = '#^' . str_replace('/', '\/', $pattern) . '#'; - try { - /** @var string $found */ - $found = preg_replace($pattern, $replace, $source_url); - if ($found && $found !== $source_url) { - $this->grav->redirectLangSafe($found); - } - } catch (ErrorException $e) { - $this->grav['log']->error('site.redirects: ' . $pattern . '-> ' . $e->getMessage()); - } - } - } + /** @var Config $config */ + $config = $this->grav['config']; - // Try Regex style routes - $site_routes = $config->get('site.routes'); - if (is_array($site_routes)) { - foreach ((array)$site_routes as $pattern => $replace) { - $pattern = '#^' . str_replace('/', '\/', ltrim($pattern, '^')) . '#'; - try { - /** @var string $found */ - $found = preg_replace($pattern, $replace, $source_url); - if ($found && $found !== $source_url) { - $page = $this->dispatch($found, $all, $redirect); - } - } catch (ErrorException $e) { - $this->grav['log']->error('site.routes: ' . $pattern . '-> ' . $e->getMessage()); - } - } + /** @var Uri $uri */ + $uri = $this->grav['uri']; + /** @var \Grav\Framework\Uri\Uri $source_url */ + $source_url = $uri->uri(false); + + // Try Regex style redirects + $site_redirects = $config->get('site.redirects'); + if (is_array($site_redirects)) { + foreach ((array)$site_redirects as $pattern => $replace) { + $pattern = ltrim($pattern, '^'); + $pattern = '#^' . str_replace('/', '\/', $pattern) . '#'; + try { + /** @var string $found */ + $found = preg_replace($pattern, $replace, $source_url); + if ($found && $found !== $source_url) { + $this->grav->redirectLangSafe($found); } + } catch (ErrorException $e) { + $this->grav['log']->error('site.redirects: ' . $pattern . '-> ' . $e->getMessage()); } } } diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index 22f6b861b..f7046083d 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -519,7 +519,7 @@ public function basename() * Return the full uri * * @param bool $include_root - * @return mixed + * @return string */ public function uri($include_root = true) { From 2681a8196b128ecde37205e83778e039efcb9038 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 12 Mar 2021 12:45:41 +0200 Subject: [PATCH 2/4] Fixed `Uncaught ValueError: Path cannot be empty` when failing to upload a file [#3265] --- CHANGELOG.md | 1 + composer.json | 2 +- composer.lock | 126 ++++++++++--------- system/src/Grav/Console/Cli/CleanCommand.php | 5 +- 4 files changed, 72 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5b8a473..0023af0b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Fixed `Uri::isValidExtension()` returning false positives * Fixed `page.html` returning duplicated content with `system.pages.redirect_default_route` turned on [#3130](https://github.com/getgrav/grav/issues/3130) * Fixed site redirect with redirect code failing when redirecting to sub-pages [#3035](https://github.com/getgrav/grav/pull/3035/files) + * Fixed `Uncaught ValueError: Path cannot be empty` when failing to upload a file [#3265](https://github.com/getgrav/grav/issues/3265) # v1.7.7 ## 02/23/2021 diff --git a/composer.json b/composer.json index 76ffffb5a..34d1e7e09 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "psr/http-message": "^1.0", "psr/http-server-middleware": "^1.0", "psr/container": "~1.0.0", - "kodus/psr7-server": "*", + "nyholm/psr7-server": "^1.0", "nyholm/psr7": "^1.3", "twig/twig": "~1.44", "erusev/parsedown": "^1.7", diff --git a/composer.lock b/composer.lock index 2e9801b52..cd3939a2d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0db8500b7a3f92a2b194df17ee416022", + "content-hash": "4ae6fc7274c018b1bb34bb1b80bd62c5", "packages": [ { "name": "antoligy/dom-string-iterators", @@ -954,64 +954,6 @@ ], "time": "2020-12-27T00:18:25+00:00" }, - { - "name": "kodus/psr7-server", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/kodus/psr7-server.git", - "reference": "dcfd0116451b0f0e7c6b23b831757ed288347278" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kodus/psr7-server/zipball/dcfd0116451b0f0e7c6b23b831757ed288347278", - "reference": "dcfd0116451b0f0e7c6b23b831757ed288347278", - "shasum": "" - }, - "require": { - "php": "^7.1", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0" - }, - "replace": { - "nyholm/psr7-server": "^0.3" - }, - "require-dev": { - "nyholm/nsa": "^1.1", - "nyholm/psr7": "^1.0", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Nyholm\\Psr7Server\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com" - }, - { - "name": "Martijn van der Ven", - "email": "martijn@vanderven.se" - } - ], - "description": "Helper classes to handle PSR-7 server requests", - "homepage": "http://tnyholm.se", - "keywords": [ - "psr-17", - "psr-7" - ], - "support": { - "source": "https://github.com/kodus/psr7-server/tree/master" - }, - "time": "2019-06-17T10:48:13+00:00" - }, { "name": "league/climate", "version": "3.7.0", @@ -1496,6 +1438,72 @@ ], "time": "2021-02-18T15:41:32+00:00" }, + { + "name": "nyholm/psr7-server", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7-server.git", + "reference": "5c134aeb5dd6521c7978798663470dabf0528c96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/5c134aeb5dd6521c7978798663470dabf0528c96", + "reference": "5c134aeb5dd6521c7978798663470dabf0528c96", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "nyholm/nsa": "^1.1", + "nyholm/psr7": "^1.3", + "phpunit/phpunit": "^7.0 || ^8.5 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nyholm\\Psr7Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "Helper classes to handle PSR-7 server requests", + "homepage": "http://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7-server/issues", + "source": "https://github.com/Nyholm/psr7-server/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2020-11-15T15:26:20+00:00" + }, { "name": "phive/twig-extensions-deferred", "version": "v1.0.2", diff --git a/system/src/Grav/Console/Cli/CleanCommand.php b/system/src/Grav/Console/Cli/CleanCommand.php index 8aa019ccb..b0c949900 100644 --- a/system/src/Grav/Console/Cli/CleanCommand.php +++ b/system/src/Grav/Console/Cli/CleanCommand.php @@ -154,8 +154,6 @@ class CleanCommand extends Command 'vendor/itsgoingd/clockwork/.gitattributes', 'vendor/itsgoingd/clockwork/CHANGELOG.md', 'vendor/itsgoingd/clockwork/composer.json', - 'vendor/kodus/psr7-server/composer.json', - 'vendor/kodus/psr7-server/CHANGELOG.md', 'vendor/league/climate/composer.json', 'vendor/league/climate/CHANGELOG.md', 'vendor/league/climate/CONTRIBUTING.md', @@ -197,6 +195,9 @@ class CleanCommand extends Command 'vendor/nyholm/psr7/phpstan.neon.dist', 'vendor/nyholm/psr7/CHANGELOG.md', 'vendor/nyholm/psr7/psalm.xml', + 'vendor/nyholm/psr7-server/.github', + 'vendor/nyholm/psr7-server/composer.json', + 'vendor/nyholm/psr7-server/CHANGELOG.md', 'vendor/phive/twig-extensions-deferred/.gitignore', 'vendor/phive/twig-extensions-deferred/.travis.yml', 'vendor/phive/twig-extensions-deferred/composer.json', From 4f1af3709e15e27550e765386555d3075dbf5c4f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 15 Mar 2021 18:50:28 +0200 Subject: [PATCH 3/4] Fixed `Path cannot be empty` when viewing non-existent log file [#3270] --- CHANGELOG.md | 3 ++- system/src/Grav/Common/Helpers/LogViewer.php | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0023af0b4..9176ad7a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,12 +17,13 @@ * Fixed Grav using blueprints and form fields from disabled plugins * Fixed `FlexIndex::sortBy(['key' => 'ASC'])` having no effect * Fixed default Flex Pages collection ordering to order by filesystem path - * Fixed disappearing pages on save if `pages://` stream resolves to multiple folders where the preferred folder doesn't exist + * Fixed disappearing pages on save if `pages://` stream resolves to multiple folders where the preferred folder doesn't exist * Fixed Markdown image attribute `loading` [#3251](https://github.com/getgrav/grav/pull/3251) * Fixed `Uri::isValidExtension()` returning false positives * Fixed `page.html` returning duplicated content with `system.pages.redirect_default_route` turned on [#3130](https://github.com/getgrav/grav/issues/3130) * Fixed site redirect with redirect code failing when redirecting to sub-pages [#3035](https://github.com/getgrav/grav/pull/3035/files) * Fixed `Uncaught ValueError: Path cannot be empty` when failing to upload a file [#3265](https://github.com/getgrav/grav/issues/3265) + * Fixed `Path cannot be empty` when viewing non-existent log file [#3270](https://github.com/getgrav/grav/issues/3270) # v1.7.7 ## 02/23/2021 diff --git a/system/src/Grav/Common/Helpers/LogViewer.php b/system/src/Grav/Common/Helpers/LogViewer.php index 1e3e8d2f7..a03fde810 100644 --- a/system/src/Grav/Common/Helpers/LogViewer.php +++ b/system/src/Grav/Common/Helpers/LogViewer.php @@ -34,7 +34,7 @@ class LogViewer public function objectTail($filepath, $lines = 1, $desc = true) { $data = $this->tail($filepath, $lines); - $tailed_log = explode(PHP_EOL, $data); + $tailed_log = $data ? explode(PHP_EOL, $data) : []; $line_objects = []; foreach ($tailed_log as $line) { @@ -54,13 +54,13 @@ public function objectTail($filepath, $lines = 1, $desc = true) public function tail($filepath, $lines = 1) { - $f = @fopen($filepath, "rb"); + $f = $filepath ? @fopen($filepath, 'rb') : false; if ($f === false) { return false; - } else { - $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096)); } + $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096)); + fseek($f, -1, SEEK_END); if (fread($f, 1) != "\n") { $lines -= 1; From fad681430e769fff3edc2b5007260c45756567f1 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 15 Mar 2021 19:05:33 +0200 Subject: [PATCH 4/4] Composer update --- composer.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index cd3939a2d..6ea862f92 100644 --- a/composer.lock +++ b/composer.lock @@ -763,18 +763,18 @@ "source": { "type": "git", "url": "https://github.com/getgrav/Image.git", - "reference": "70afaa75ea19856813124142c51f5fb2e9f1a285" + "reference": "ea23859700f32447a85e79d96f331e3d6c8897a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getgrav/Image/zipball/70afaa75ea19856813124142c51f5fb2e9f1a285", - "reference": "70afaa75ea19856813124142c51f5fb2e9f1a285", + "url": "https://api.github.com/repos/getgrav/Image/zipball/ea23859700f32447a85e79d96f331e3d6c8897a8", + "reference": "ea23859700f32447a85e79d96f331e3d6c8897a8", "shasum": "" }, "require": { "ext-gd": "*", "gregwar/cache": "dev-php8", - "php": "^5.3 || ^7.0 || ^8.0" + "php": "^5.6 || ^7.0 || ^8.0" }, "require-dev": { "sllh/php-cs-fixer-styleci-bridge": "~1.0", @@ -808,7 +808,7 @@ "support": { "source": "https://github.com/getgrav/Image/tree/php8" }, - "time": "2020-12-02T14:04:28+00:00" + "time": "2021-03-15T17:03:52+00:00" }, { "name": "guzzlehttp/psr7", @@ -887,16 +887,16 @@ }, { "name": "itsgoingd/clockwork", - "version": "v5.0.6", + "version": "v5.0.7", "source": { "type": "git", "url": "https://github.com/itsgoingd/clockwork.git", - "reference": "1de3f9f9fc22217aa024f79ecbdf0fde418fc0a1" + "reference": "e41ee368ff4dcc30d3f4563fe8bd80ed72b293b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/1de3f9f9fc22217aa024f79ecbdf0fde418fc0a1", - "reference": "1de3f9f9fc22217aa024f79ecbdf0fde418fc0a1", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/e41ee368ff4dcc30d3f4563fe8bd80ed72b293b4", + "reference": "e41ee368ff4dcc30d3f4563fe8bd80ed72b293b4", "shasum": "" }, "require": { @@ -944,7 +944,7 @@ ], "support": { "issues": "https://github.com/itsgoingd/clockwork/issues", - "source": "https://github.com/itsgoingd/clockwork/tree/v5.0.6" + "source": "https://github.com/itsgoingd/clockwork/tree/v5.0.7" }, "funding": [ { @@ -952,7 +952,7 @@ "type": "github" } ], - "time": "2020-12-27T00:18:25+00:00" + "time": "2021-03-14T16:29:40+00:00" }, { "name": "league/climate",