From 11265eecca34dbe1ec2b84e904ddf01778e0a8d2 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Mon, 26 Aug 2024 16:56:55 +0100 Subject: [PATCH 01/21] Add config options for sorting, allowing, disallowing query parameters --- config/static_caching.php | 10 ++++++ src/StaticCaching/Cachers/AbstractCacher.php | 10 ++---- src/StaticCaching/ServiceProvider.php | 3 +- src/StaticCaching/StaticCacheManager.php | 34 ++++++++++++++++++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/config/static_caching.php b/config/static_caching.php index 72ba4761b09..3d6bed526df 100644 --- a/config/static_caching.php +++ b/config/static_caching.php @@ -102,6 +102,16 @@ 'ignore_query_strings' => false, + 'sort_query_strings' => false, + + 'allowed_query_parameters' => [ + // + ], + + 'disallowed_query_strings' => [ + // + ], + /* |-------------------------------------------------------------------------- | Nocache diff --git a/src/StaticCaching/Cachers/AbstractCacher.php b/src/StaticCaching/Cachers/AbstractCacher.php index 3f93d71d1a0..2e6aec27591 100644 --- a/src/StaticCaching/Cachers/AbstractCacher.php +++ b/src/StaticCaching/Cachers/AbstractCacher.php @@ -7,8 +7,10 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; use Statamic\Facades\Site; +use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cacher; use Statamic\StaticCaching\UrlExcluder; +use Statamic\Support\Arr; use Statamic\Support\Str; abstract class AbstractCacher implements Cacher @@ -137,13 +139,7 @@ public function cacheDomain($domain = null) */ public function getUrl(Request $request) { - $url = $request->getUri(); - - if ($this->config('ignore_query_strings')) { - $url = explode('?', $url)[0]; - } - - return $url; + return StaticCache::currentUrl($request); } /** diff --git a/src/StaticCaching/ServiceProvider.php b/src/StaticCaching/ServiceProvider.php index b4550dd0af4..e3ddbe73f7b 100644 --- a/src/StaticCaching/ServiceProvider.php +++ b/src/StaticCaching/ServiceProvider.php @@ -7,6 +7,7 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider as LaravelServiceProvider; use Statamic\Facades\Cascade; +use Statamic\Facades\StaticCache; use Statamic\StaticCaching\NoCache\DatabaseSession; use Statamic\StaticCaching\NoCache\Session; @@ -36,7 +37,7 @@ public function register() }); $this->app->singleton(Session::class, function ($app) { - $uri = $app['request']->getUri(); + $uri = StaticCache::currentUrl(request()); if (config('statamic.static_caching.ignore_query_strings', false)) { $uri = explode('?', $uri)[0]; diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index dd273e3691a..447c70c33a0 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -3,6 +3,7 @@ namespace Statamic\StaticCaching; use Illuminate\Cache\Repository; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Statamic\Events\StaticCacheCleared; use Statamic\Facades\Site; @@ -11,6 +12,7 @@ use Statamic\StaticCaching\Cachers\NullCacher; use Statamic\StaticCaching\Cachers\Writer; use Statamic\StaticCaching\NoCache\DatabaseRegion; +use Statamic\Support\Arr; use Statamic\Support\Manager; class StaticCacheManager extends Manager @@ -40,6 +42,38 @@ public function createApplicationDriver(array $config) return new ApplicationCacher($this->app[Repository::class], $config); } + public function currentUrl(Request $request): string + { + $url = $request->getUri(); + + if (config('statamic.static_caching.ignore_query_strings')) { + $url = explode('?', $url)[0]; + } + + $parts = parse_url($url); + + if (isset($parts['query'])) { + parse_str($parts['query'], $query); + + if (config('statamic.static_caching.sort_query_strings', false)) { + $query = Arr::sort($query); + } + + if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { + $query = array_intersect_key($query, array_flip($allowedQueryStrings)); + } + + if ($disallowedQueryStrings = config('statamic.static_caching.disallowed_query_strings')) { + $disallowedQueryStrings = array_flip($disallowedQueryStrings); + $query = array_diff_key($query, $disallowedQueryStrings); + } + + $url = $parts['scheme'].'://'.$parts['host'].$parts['path'].'?'.http_build_query($query); + } + + return $url; + } + public function cacheStore() { return Cache::store($this->hasCustomStore() ? 'static_cache' : null); From 67880ce998758ba06bc693f353028982385f295d Mon Sep 17 00:00:00 2001 From: duncanmcclean Date: Mon, 26 Aug 2024 15:58:58 +0000 Subject: [PATCH 02/21] Fix styling --- src/StaticCaching/Cachers/AbstractCacher.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/StaticCaching/Cachers/AbstractCacher.php b/src/StaticCaching/Cachers/AbstractCacher.php index 2e6aec27591..872fd9f1e01 100644 --- a/src/StaticCaching/Cachers/AbstractCacher.php +++ b/src/StaticCaching/Cachers/AbstractCacher.php @@ -10,7 +10,6 @@ use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cacher; use Statamic\StaticCaching\UrlExcluder; -use Statamic\Support\Arr; use Statamic\Support\Str; abstract class AbstractCacher implements Cacher From 67be0e37460597d0de671ab65a272895badcea7a Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Mon, 26 Aug 2024 17:42:34 +0100 Subject: [PATCH 03/21] Tests. --- src/StaticCaching/StaticCacheManager.php | 2 +- tests/StaticCaching/CacherTest.php | 20 ++----- tests/StaticCaching/ManagerTest.php | 71 ++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 447c70c33a0..809544b589b 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -46,7 +46,7 @@ public function currentUrl(Request $request): string { $url = $request->getUri(); - if (config('statamic.static_caching.ignore_query_strings')) { + if (config('statamic.static_caching.ignore_query_strings', false)) { $url = explode('?', $url)[0]; } diff --git a/tests/StaticCaching/CacherTest.php b/tests/StaticCaching/CacherTest.php index 586f9d4f45e..13061561306 100644 --- a/tests/StaticCaching/CacherTest.php +++ b/tests/StaticCaching/CacherTest.php @@ -7,6 +7,7 @@ use Illuminate\Support\Collection; use Mockery; use PHPUnit\Framework\Attributes\Test; +use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cachers\AbstractCacher; use Tests\TestCase; @@ -38,21 +39,12 @@ public function gets_a_url() { $cacher = $this->cacher(); - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - ]); + $request = Request::create('http://example.com/test', 'GET'); - $this->assertEquals('http://example.com/test?foo=bar', $cacher->getUrl($request)); - } - - #[Test] - public function gets_a_url_with_query_strings_disabled() - { - $cacher = $this->cacher(['ignore_query_strings' => true]); - - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - ]); + StaticCache::shouldReceive('currentUrl') + ->with($request) + ->andReturn('http://example.com/test') + ->once(); $this->assertEquals('http://example.com/test', $cacher->getUrl($request)); } diff --git a/tests/StaticCaching/ManagerTest.php b/tests/StaticCaching/ManagerTest.php index 86d5f8fdbe1..99c4e59e2fa 100644 --- a/tests/StaticCaching/ManagerTest.php +++ b/tests/StaticCaching/ManagerTest.php @@ -2,6 +2,7 @@ namespace Tests\StaticCaching; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Mockery; use PHPUnit\Framework\Attributes\Test; @@ -57,4 +58,74 @@ public function it_flushes_without_static_cache_store() StaticCache::flush(); } + + #[Test] + public function it_gets_the_current_url() + { + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + ]); + + $this->assertEquals('http://example.com/test?foo=bar', StaticCache::currentUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_query_strings_disabled() + { + config()->set('statamic.static_caching.ignore_query_strings', true); + + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + ]); + + $this->assertEquals('http://example.com/test', StaticCache::currentUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_query_string_sorting() + { + $this->markTestIncomplete("We might not actually need this config option. It looks like Symfony's Request::normalizeQueryString() method already sorts query strings using ksort()."); + + config()->set('statamic.static_caching.sort_query_strings', true); + + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + 'baz' => 'qux', + 'quux' => 'corge', + ]); + + $this->assertEquals('http://example.com/test?baz=qux&foo=bar&quux=corge', StaticCache::currentUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_allowed_query_parameters() + { + config()->set('statamic.static_caching.allowed_query_strings', [ + 'foo', 'quux', + ]); + + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + 'baz' => 'qux', + 'quux' => 'corge', + ]); + + $this->assertEquals('http://example.com/test?foo=bar&quux=corge', StaticCache::currentUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_disallowed_query_parameters() + { + config()->set('statamic.static_caching.disallowed_query_strings', [ + 'quux', + ]); + + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + 'baz' => 'qux', + 'quux' => 'corge', + ]); + + $this->assertEquals('http://example.com/test?baz=qux&foo=bar', StaticCache::currentUrl($request)); + } } From 75e7a6cc259b1c66e5e50d899aff3340f91732a4 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Mon, 26 Aug 2024 18:37:10 +0100 Subject: [PATCH 04/21] Sort by key. --- src/StaticCaching/StaticCacheManager.php | 2 +- tests/StaticCaching/ManagerTest.php | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 809544b589b..439632d04ee 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -56,7 +56,7 @@ public function currentUrl(Request $request): string parse_str($parts['query'], $query); if (config('statamic.static_caching.sort_query_strings', false)) { - $query = Arr::sort($query); + $query = Arr::sort($query, fn ($value, $key) => $key) } if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { diff --git a/tests/StaticCaching/ManagerTest.php b/tests/StaticCaching/ManagerTest.php index 99c4e59e2fa..39d4ff4bf0d 100644 --- a/tests/StaticCaching/ManagerTest.php +++ b/tests/StaticCaching/ManagerTest.php @@ -84,8 +84,6 @@ public function it_gets_the_current_url_with_query_strings_disabled() #[Test] public function it_gets_the_current_url_with_query_string_sorting() { - $this->markTestIncomplete("We might not actually need this config option. It looks like Symfony's Request::normalizeQueryString() method already sorts query strings using ksort()."); - config()->set('statamic.static_caching.sort_query_strings', true); $request = Request::create('http://example.com/test', 'GET', [ From 8d27f160b85c1808eb72fab65da945b1b020066b Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Mon, 26 Aug 2024 19:06:54 +0100 Subject: [PATCH 05/21] wip --- src/StaticCaching/StaticCacheManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 439632d04ee..9c82bd194eb 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -56,7 +56,7 @@ public function currentUrl(Request $request): string parse_str($parts['query'], $query); if (config('statamic.static_caching.sort_query_strings', false)) { - $query = Arr::sort($query, fn ($value, $key) => $key) + $query = Arr::sort($query, fn ($value, $key) => $key); } if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { From b77eaa6d0d7ca697e7a0fbc7fa3966dfebf177b5 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Tue, 27 Aug 2024 09:46:38 +0100 Subject: [PATCH 06/21] Remove sorting config option --- src/StaticCaching/StaticCacheManager.php | 4 ---- tests/StaticCaching/ManagerTest.php | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 9c82bd194eb..917473b31be 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -55,10 +55,6 @@ public function currentUrl(Request $request): string if (isset($parts['query'])) { parse_str($parts['query'], $query); - if (config('statamic.static_caching.sort_query_strings', false)) { - $query = Arr::sort($query, fn ($value, $key) => $key); - } - if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { $query = array_intersect_key($query, array_flip($allowedQueryStrings)); } diff --git a/tests/StaticCaching/ManagerTest.php b/tests/StaticCaching/ManagerTest.php index 39d4ff4bf0d..5d3e6f0ff88 100644 --- a/tests/StaticCaching/ManagerTest.php +++ b/tests/StaticCaching/ManagerTest.php @@ -81,20 +81,6 @@ public function it_gets_the_current_url_with_query_strings_disabled() $this->assertEquals('http://example.com/test', StaticCache::currentUrl($request)); } - #[Test] - public function it_gets_the_current_url_with_query_string_sorting() - { - config()->set('statamic.static_caching.sort_query_strings', true); - - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - 'baz' => 'qux', - 'quux' => 'corge', - ]); - - $this->assertEquals('http://example.com/test?baz=qux&foo=bar&quux=corge', StaticCache::currentUrl($request)); - } - #[Test] public function it_gets_the_current_url_with_allowed_query_parameters() { From 67f4a0c8513159cdb2b8e9fce750961e120bb950 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Tue, 27 Aug 2024 10:01:49 +0100 Subject: [PATCH 07/21] Add failing test --- tests/StaticCaching/ManagerTest.php | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/StaticCaching/ManagerTest.php b/tests/StaticCaching/ManagerTest.php index 5d3e6f0ff88..170cf9477d6 100644 --- a/tests/StaticCaching/ManagerTest.php +++ b/tests/StaticCaching/ManagerTest.php @@ -5,6 +5,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Mockery; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cacher; @@ -98,18 +99,22 @@ public function it_gets_the_current_url_with_allowed_query_parameters() } #[Test] - public function it_gets_the_current_url_with_disallowed_query_parameters() + #[DataProvider('disallowedQueryParametersProvider')] + public function it_gets_the_current_url_with_disallowed_query_parameters(array $disallowed, string $url, array $query, string $expected) { - config()->set('statamic.static_caching.disallowed_query_strings', [ - 'quux', - ]); + config()->set('statamic.static_caching.disallowed_query_strings', $disallowed); - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - 'baz' => 'qux', - 'quux' => 'corge', - ]); + $request = Request::create($url, 'GET', $query); + + $this->assertEquals($expected, StaticCache::currentUrl($request)); + } - $this->assertEquals('http://example.com/test?baz=qux&foo=bar', StaticCache::currentUrl($request)); + public static function disallowedQueryParametersProvider() + { + return [ + [[], 'http://example.com/test', ['foo' => 'bar'], 'http://example.com/test?foo=bar'], + [['quux'], 'http://example.com/test', ['quux' => 'corge'], 'http://example.com/test'], + [['quux'], 'http://example.com/test', ['foo' => 'bar', 'baz' => 'qux', 'quux' => 'corge'], 'http://example.com/test?baz=qux&foo=bar'], + ]; } } From 0b6bbdcfc5d33ffc56b4d6dd090c8b5fbb3e5039 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Tue, 27 Aug 2024 10:03:46 +0100 Subject: [PATCH 08/21] Ensure there's no trailing `?` when URL ends up with no query parameters --- src/StaticCaching/StaticCacheManager.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 917473b31be..6c0529cab32 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -64,7 +64,11 @@ public function currentUrl(Request $request): string $query = array_diff_key($query, $disallowedQueryStrings); } - $url = $parts['scheme'].'://'.$parts['host'].$parts['path'].'?'.http_build_query($query); + $url = $parts['scheme'].'://'.$parts['host'].$parts['path']; + + if ($query) { + $url .= '?'.http_build_query($query); + } } return $url; From 5c0a5be4978fe2bce593fd7783c9f26f3cff02e4 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Tue, 27 Aug 2024 10:04:17 +0100 Subject: [PATCH 09/21] Ensure currentUrl works when no query parameters are provided --- tests/StaticCaching/ManagerTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/StaticCaching/ManagerTest.php b/tests/StaticCaching/ManagerTest.php index 170cf9477d6..a7668c29a3b 100644 --- a/tests/StaticCaching/ManagerTest.php +++ b/tests/StaticCaching/ManagerTest.php @@ -62,6 +62,14 @@ public function it_flushes_without_static_cache_store() #[Test] public function it_gets_the_current_url() + { + $request = Request::create('http://example.com/test', 'GET'); + + $this->assertEquals('http://example.com/test', StaticCache::currentUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_query_parameters() { $request = Request::create('http://example.com/test', 'GET', [ 'foo' => 'bar', From 274274cc977f896ba0c944d0aeefc9a821a9b68c Mon Sep 17 00:00:00 2001 From: duncanmcclean Date: Tue, 27 Aug 2024 09:05:55 +0000 Subject: [PATCH 10/21] Fix styling --- src/StaticCaching/StaticCacheManager.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 6c0529cab32..3e0f5a398a9 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -12,7 +12,6 @@ use Statamic\StaticCaching\Cachers\NullCacher; use Statamic\StaticCaching\Cachers\Writer; use Statamic\StaticCaching\NoCache\DatabaseRegion; -use Statamic\Support\Arr; use Statamic\Support\Manager; class StaticCacheManager extends Manager From 400fcac4bc87b3b96785464ec55077aa52722758 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Tue, 27 Aug 2024 10:07:32 +0100 Subject: [PATCH 11/21] Remove `sort_query_strings` from config file --- config/static_caching.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/static_caching.php b/config/static_caching.php index 3d6bed526df..daf030dc751 100644 --- a/config/static_caching.php +++ b/config/static_caching.php @@ -102,8 +102,6 @@ 'ignore_query_strings' => false, - 'sort_query_strings' => false, - 'allowed_query_parameters' => [ // ], From c4c6caaf9c3d3767118304ec3d2288d6d371ec5e Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Tue, 3 Sep 2024 16:43:27 -0400 Subject: [PATCH 12/21] call getUrl on the cacher rather than a new manager method --- src/StaticCaching/Cachers/AbstractCacher.php | 13 +--- src/StaticCaching/Cachers/GetsRequestUrl.php | 40 +++++++++++ src/StaticCaching/Cachers/NullCacher.php | 2 + src/StaticCaching/ServiceProvider.php | 3 +- src/StaticCaching/StaticCacheManager.php | 33 --------- tests/StaticCaching/ApplicationCacherTest.php | 66 ++++++++++++++++++ tests/StaticCaching/CacherTest.php | 17 ----- tests/StaticCaching/ManagerTest.php | 68 ------------------- 8 files changed, 111 insertions(+), 131 deletions(-) create mode 100644 src/StaticCaching/Cachers/GetsRequestUrl.php diff --git a/src/StaticCaching/Cachers/AbstractCacher.php b/src/StaticCaching/Cachers/AbstractCacher.php index 872fd9f1e01..7082f2bd5d4 100644 --- a/src/StaticCaching/Cachers/AbstractCacher.php +++ b/src/StaticCaching/Cachers/AbstractCacher.php @@ -7,13 +7,14 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; use Statamic\Facades\Site; -use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cacher; use Statamic\StaticCaching\UrlExcluder; use Statamic\Support\Str; abstract class AbstractCacher implements Cacher { + use GetsRequestUrl; + /** * @var Repository */ @@ -131,16 +132,6 @@ public function cacheDomain($domain = null) $this->cache->forever($this->normalizeKey('domains'), $domains->all()); } - /** - * Get the URL from a request. - * - * @return string - */ - public function getUrl(Request $request) - { - return StaticCache::currentUrl($request); - } - /** * Get all the URLs that have been cached. * diff --git a/src/StaticCaching/Cachers/GetsRequestUrl.php b/src/StaticCaching/Cachers/GetsRequestUrl.php new file mode 100644 index 00000000000..5389be19295 --- /dev/null +++ b/src/StaticCaching/Cachers/GetsRequestUrl.php @@ -0,0 +1,40 @@ +getUri(); + + if (config('statamic.static_caching.ignore_query_strings', false)) { + $url = explode('?', $url)[0]; + } + + $parts = parse_url($url); + + if (isset($parts['query'])) { + parse_str($parts['query'], $query); + + if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { + $query = array_intersect_key($query, array_flip($allowedQueryStrings)); + } + + if ($disallowedQueryStrings = config('statamic.static_caching.disallowed_query_strings')) { + $disallowedQueryStrings = array_flip($disallowedQueryStrings); + $query = array_diff_key($query, $disallowedQueryStrings); + } + + $url = $parts['scheme'].'://'.$parts['host'].$parts['path']; + + if ($query) { + $url .= '?'.http_build_query($query); + } + } + + return $url; + } +} diff --git a/src/StaticCaching/Cachers/NullCacher.php b/src/StaticCaching/Cachers/NullCacher.php index e92da3fa423..ac27d044dc8 100644 --- a/src/StaticCaching/Cachers/NullCacher.php +++ b/src/StaticCaching/Cachers/NullCacher.php @@ -7,6 +7,8 @@ class NullCacher implements Cacher { + use GetsRequestUrl; + public function cachePage(Request $request, $content) { // diff --git a/src/StaticCaching/ServiceProvider.php b/src/StaticCaching/ServiceProvider.php index e3ddbe73f7b..e277702e7c2 100644 --- a/src/StaticCaching/ServiceProvider.php +++ b/src/StaticCaching/ServiceProvider.php @@ -7,7 +7,6 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider as LaravelServiceProvider; use Statamic\Facades\Cascade; -use Statamic\Facades\StaticCache; use Statamic\StaticCaching\NoCache\DatabaseSession; use Statamic\StaticCaching\NoCache\Session; @@ -37,7 +36,7 @@ public function register() }); $this->app->singleton(Session::class, function ($app) { - $uri = StaticCache::currentUrl(request()); + $uri = $app[Cacher::class]->getUrl($app['request']); if (config('statamic.static_caching.ignore_query_strings', false)) { $uri = explode('?', $uri)[0]; diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 3e0f5a398a9..dd273e3691a 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -3,7 +3,6 @@ namespace Statamic\StaticCaching; use Illuminate\Cache\Repository; -use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Statamic\Events\StaticCacheCleared; use Statamic\Facades\Site; @@ -41,38 +40,6 @@ public function createApplicationDriver(array $config) return new ApplicationCacher($this->app[Repository::class], $config); } - public function currentUrl(Request $request): string - { - $url = $request->getUri(); - - if (config('statamic.static_caching.ignore_query_strings', false)) { - $url = explode('?', $url)[0]; - } - - $parts = parse_url($url); - - if (isset($parts['query'])) { - parse_str($parts['query'], $query); - - if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { - $query = array_intersect_key($query, array_flip($allowedQueryStrings)); - } - - if ($disallowedQueryStrings = config('statamic.static_caching.disallowed_query_strings')) { - $disallowedQueryStrings = array_flip($disallowedQueryStrings); - $query = array_diff_key($query, $disallowedQueryStrings); - } - - $url = $parts['scheme'].'://'.$parts['host'].$parts['path']; - - if ($query) { - $url .= '?'.http_build_query($query); - } - } - - return $url; - } - public function cacheStore() { return Cache::store($this->hasCustomStore() ? 'static_cache' : null); diff --git a/tests/StaticCaching/ApplicationCacherTest.php b/tests/StaticCaching/ApplicationCacherTest.php index 4dc40445943..051d66565ec 100644 --- a/tests/StaticCaching/ApplicationCacherTest.php +++ b/tests/StaticCaching/ApplicationCacherTest.php @@ -177,4 +177,70 @@ public function it_flushes() $this->assertEquals([], $cacher->getUrls('http://example.com')->all()); $this->assertEquals([], $cacher->getUrls('http://another.com')->all()); } + + #[Test] + public function it_gets_the_current_url() + { + $request = Request::create('http://example.com/test', 'GET'); + + $this->assertEquals('http://example.com/test', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_query_parameters() + { + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + ]); + + $this->assertEquals('http://example.com/test?foo=bar', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_query_strings_disabled() + { + config()->set('statamic.static_caching.ignore_query_strings', true); + + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + ]); + + $this->assertEquals('http://example.com/test', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + } + + #[Test] + public function it_gets_the_current_url_with_allowed_query_parameters() + { + config()->set('statamic.static_caching.allowed_query_strings', [ + 'foo', 'quux', + ]); + + $request = Request::create('http://example.com/test', 'GET', [ + 'foo' => 'bar', + 'baz' => 'qux', + 'quux' => 'corge', + ]); + + $this->assertEquals('http://example.com/test?foo=bar&quux=corge', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + } + + #[Test] + #[DataProvider('disallowedQueryParametersProvider')] + public function it_gets_the_current_url_with_disallowed_query_parameters(array $disallowed, string $url, array $query, string $expected) + { + config()->set('statamic.static_caching.disallowed_query_strings', $disallowed); + + $request = Request::create($url, 'GET', $query); + + $this->assertEquals($expected, (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + } + + public static function disallowedQueryParametersProvider() + { + return [ + [[], 'http://example.com/test', ['foo' => 'bar'], 'http://example.com/test?foo=bar'], + [['quux'], 'http://example.com/test', ['quux' => 'corge'], 'http://example.com/test'], + [['quux'], 'http://example.com/test', ['foo' => 'bar', 'baz' => 'qux', 'quux' => 'corge'], 'http://example.com/test?baz=qux&foo=bar'], + ]; + } } diff --git a/tests/StaticCaching/CacherTest.php b/tests/StaticCaching/CacherTest.php index 13061561306..2c544275030 100644 --- a/tests/StaticCaching/CacherTest.php +++ b/tests/StaticCaching/CacherTest.php @@ -3,11 +3,9 @@ namespace Tests\StaticCaching; use Illuminate\Cache\Repository; -use Illuminate\Http\Request; use Illuminate\Support\Collection; use Mockery; use PHPUnit\Framework\Attributes\Test; -use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cachers\AbstractCacher; use Tests\TestCase; @@ -34,21 +32,6 @@ public function gets_default_expiration() $this->assertEquals(10, $cacher->getDefaultExpiration()); } - #[Test] - public function gets_a_url() - { - $cacher = $this->cacher(); - - $request = Request::create('http://example.com/test', 'GET'); - - StaticCache::shouldReceive('currentUrl') - ->with($request) - ->andReturn('http://example.com/test') - ->once(); - - $this->assertEquals('http://example.com/test', $cacher->getUrl($request)); - } - #[Test] public function gets_the_base_url_using_the_deprecated_config_value() { diff --git a/tests/StaticCaching/ManagerTest.php b/tests/StaticCaching/ManagerTest.php index a7668c29a3b..86d5f8fdbe1 100644 --- a/tests/StaticCaching/ManagerTest.php +++ b/tests/StaticCaching/ManagerTest.php @@ -2,10 +2,8 @@ namespace Tests\StaticCaching; -use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Mockery; -use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\StaticCache; use Statamic\StaticCaching\Cacher; @@ -59,70 +57,4 @@ public function it_flushes_without_static_cache_store() StaticCache::flush(); } - - #[Test] - public function it_gets_the_current_url() - { - $request = Request::create('http://example.com/test', 'GET'); - - $this->assertEquals('http://example.com/test', StaticCache::currentUrl($request)); - } - - #[Test] - public function it_gets_the_current_url_with_query_parameters() - { - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - ]); - - $this->assertEquals('http://example.com/test?foo=bar', StaticCache::currentUrl($request)); - } - - #[Test] - public function it_gets_the_current_url_with_query_strings_disabled() - { - config()->set('statamic.static_caching.ignore_query_strings', true); - - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - ]); - - $this->assertEquals('http://example.com/test', StaticCache::currentUrl($request)); - } - - #[Test] - public function it_gets_the_current_url_with_allowed_query_parameters() - { - config()->set('statamic.static_caching.allowed_query_strings', [ - 'foo', 'quux', - ]); - - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - 'baz' => 'qux', - 'quux' => 'corge', - ]); - - $this->assertEquals('http://example.com/test?foo=bar&quux=corge', StaticCache::currentUrl($request)); - } - - #[Test] - #[DataProvider('disallowedQueryParametersProvider')] - public function it_gets_the_current_url_with_disallowed_query_parameters(array $disallowed, string $url, array $query, string $expected) - { - config()->set('statamic.static_caching.disallowed_query_strings', $disallowed); - - $request = Request::create($url, 'GET', $query); - - $this->assertEquals($expected, StaticCache::currentUrl($request)); - } - - public static function disallowedQueryParametersProvider() - { - return [ - [[], 'http://example.com/test', ['foo' => 'bar'], 'http://example.com/test?foo=bar'], - [['quux'], 'http://example.com/test', ['quux' => 'corge'], 'http://example.com/test'], - [['quux'], 'http://example.com/test', ['foo' => 'bar', 'baz' => 'qux', 'quux' => 'corge'], 'http://example.com/test?baz=qux&foo=bar'], - ]; - } } From b239be5b6db4816efef623495f6c10bb8846af48 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Tue, 3 Sep 2024 16:52:35 -0400 Subject: [PATCH 13/21] use the config --- src/StaticCaching/Cachers/GetsRequestUrl.php | 6 ++-- src/StaticCaching/StaticCacheManager.php | 2 ++ tests/StaticCaching/ApplicationCacherTest.php | 34 ++++++++++++------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/StaticCaching/Cachers/GetsRequestUrl.php b/src/StaticCaching/Cachers/GetsRequestUrl.php index 5389be19295..66300f722fb 100644 --- a/src/StaticCaching/Cachers/GetsRequestUrl.php +++ b/src/StaticCaching/Cachers/GetsRequestUrl.php @@ -10,7 +10,7 @@ public function getUrl(Request $request) { $url = $request->getUri(); - if (config('statamic.static_caching.ignore_query_strings', false)) { + if ($this->config('ignore_query_strings', false)) { $url = explode('?', $url)[0]; } @@ -19,11 +19,11 @@ public function getUrl(Request $request) if (isset($parts['query'])) { parse_str($parts['query'], $query); - if ($allowedQueryStrings = config('statamic.static_caching.allowed_query_strings')) { + if ($allowedQueryStrings = $this->config('allowed_query_strings')) { $query = array_intersect_key($query, array_flip($allowedQueryStrings)); } - if ($disallowedQueryStrings = config('statamic.static_caching.disallowed_query_strings')) { + if ($disallowedQueryStrings = $this->config('disallowed_query_strings')) { $disallowedQueryStrings = array_flip($disallowedQueryStrings); $query = array_diff_key($query, $disallowedQueryStrings); } diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index dd273e3691a..9af77ab541d 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -59,6 +59,8 @@ protected function getConfig($name) return array_merge($config, [ 'exclude' => $this->app['config']['statamic.static_caching.exclude'] ?? [], 'ignore_query_strings' => $this->app['config']['statamic.static_caching.ignore_query_strings'] ?? false, + 'allowed_query_strings' => $this->app['config']['statamic.static_caching.allowed_query_strings'] ?? [], + 'disallowed_query_strings' => $this->app['config']['statamic.static_caching.disallowed_query_strings'] ?? [], 'locale' => Site::current()->handle(), ]); } diff --git a/tests/StaticCaching/ApplicationCacherTest.php b/tests/StaticCaching/ApplicationCacherTest.php index 051d66565ec..b5b6e19fbd1 100644 --- a/tests/StaticCaching/ApplicationCacherTest.php +++ b/tests/StaticCaching/ApplicationCacherTest.php @@ -183,7 +183,9 @@ public function it_gets_the_current_url() { $request = Request::create('http://example.com/test', 'GET'); - $this->assertEquals('http://example.com/test', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + $cacher = new ApplicationCacher(app(Repository::class), []); + + $this->assertEquals('http://example.com/test', $cacher->getUrl($request)); } #[Test] @@ -193,46 +195,52 @@ public function it_gets_the_current_url_with_query_parameters() 'foo' => 'bar', ]); - $this->assertEquals('http://example.com/test?foo=bar', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + $cacher = new ApplicationCacher(app(Repository::class), []); + + $this->assertEquals('http://example.com/test?foo=bar', $cacher->getUrl($request)); } #[Test] public function it_gets_the_current_url_with_query_strings_disabled() { - config()->set('statamic.static_caching.ignore_query_strings', true); - $request = Request::create('http://example.com/test', 'GET', [ 'foo' => 'bar', ]); - $this->assertEquals('http://example.com/test', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + $cacher = new ApplicationCacher(app(Repository::class), [ + 'ignore_query_strings' => true, + ]); + + $this->assertEquals('http://example.com/test', $cacher->getUrl($request)); } #[Test] public function it_gets_the_current_url_with_allowed_query_parameters() { - config()->set('statamic.static_caching.allowed_query_strings', [ - 'foo', 'quux', - ]); - $request = Request::create('http://example.com/test', 'GET', [ 'foo' => 'bar', 'baz' => 'qux', 'quux' => 'corge', ]); - $this->assertEquals('http://example.com/test?foo=bar&quux=corge', (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + $cacher = new ApplicationCacher(app(Repository::class), [ + 'allowed_query_strings' => ['foo', 'quux'], + ]); + + $this->assertEquals('http://example.com/test?foo=bar&quux=corge', $cacher->getUrl($request)); } #[Test] #[DataProvider('disallowedQueryParametersProvider')] public function it_gets_the_current_url_with_disallowed_query_parameters(array $disallowed, string $url, array $query, string $expected) { - config()->set('statamic.static_caching.disallowed_query_strings', $disallowed); - $request = Request::create($url, 'GET', $query); - $this->assertEquals($expected, (new ApplicationCacher(app(Repository::class), []))->getUrl($request)); + $cacher = new ApplicationCacher(app(Repository::class), [ + 'disallowed_query_strings' => $disallowed, + ]); + + $this->assertEquals($expected, $cacher->getUrl($request)); } public static function disallowedQueryParametersProvider() From 0a92f8204759df1eb9585630ad9bbe69c182c711 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 4 Sep 2024 10:47:58 -0400 Subject: [PATCH 14/21] move from trait into abstract cacher --- src/StaticCaching/Cachers/AbstractCacher.php | 34 ++++++++++++++++- src/StaticCaching/Cachers/GetsRequestUrl.php | 40 -------------------- src/StaticCaching/Cachers/NullCacher.php | 6 ++- 3 files changed, 37 insertions(+), 43 deletions(-) delete mode 100644 src/StaticCaching/Cachers/GetsRequestUrl.php diff --git a/src/StaticCaching/Cachers/AbstractCacher.php b/src/StaticCaching/Cachers/AbstractCacher.php index 7082f2bd5d4..c2d9c1674fb 100644 --- a/src/StaticCaching/Cachers/AbstractCacher.php +++ b/src/StaticCaching/Cachers/AbstractCacher.php @@ -13,8 +13,6 @@ abstract class AbstractCacher implements Cacher { - use GetsRequestUrl; - /** * @var Repository */ @@ -281,4 +279,36 @@ protected function getPathAndDomain($url) $parsed['scheme'].'://'.$parsed['host'], ]; } + + public function getUrl(Request $request) + { + $url = $request->getUri(); + + if ($this->config('ignore_query_strings', false)) { + $url = explode('?', $url)[0]; + } + + $parts = parse_url($url); + + if (isset($parts['query'])) { + parse_str($parts['query'], $query); + + if ($allowedQueryStrings = $this->config('allowed_query_strings')) { + $query = array_intersect_key($query, array_flip($allowedQueryStrings)); + } + + if ($disallowedQueryStrings = $this->config('disallowed_query_strings')) { + $disallowedQueryStrings = array_flip($disallowedQueryStrings); + $query = array_diff_key($query, $disallowedQueryStrings); + } + + $url = $parts['scheme'].'://'.$parts['host'].$parts['path']; + + if ($query) { + $url .= '?'.http_build_query($query); + } + } + + return $url; + } } diff --git a/src/StaticCaching/Cachers/GetsRequestUrl.php b/src/StaticCaching/Cachers/GetsRequestUrl.php deleted file mode 100644 index 66300f722fb..00000000000 --- a/src/StaticCaching/Cachers/GetsRequestUrl.php +++ /dev/null @@ -1,40 +0,0 @@ -getUri(); - - if ($this->config('ignore_query_strings', false)) { - $url = explode('?', $url)[0]; - } - - $parts = parse_url($url); - - if (isset($parts['query'])) { - parse_str($parts['query'], $query); - - if ($allowedQueryStrings = $this->config('allowed_query_strings')) { - $query = array_intersect_key($query, array_flip($allowedQueryStrings)); - } - - if ($disallowedQueryStrings = $this->config('disallowed_query_strings')) { - $disallowedQueryStrings = array_flip($disallowedQueryStrings); - $query = array_diff_key($query, $disallowedQueryStrings); - } - - $url = $parts['scheme'].'://'.$parts['host'].$parts['path']; - - if ($query) { - $url .= '?'.http_build_query($query); - } - } - - return $url; - } -} diff --git a/src/StaticCaching/Cachers/NullCacher.php b/src/StaticCaching/Cachers/NullCacher.php index ac27d044dc8..567530e7c60 100644 --- a/src/StaticCaching/Cachers/NullCacher.php +++ b/src/StaticCaching/Cachers/NullCacher.php @@ -7,7 +7,6 @@ class NullCacher implements Cacher { - use GetsRequestUrl; public function cachePage(Request $request, $content) { @@ -48,4 +47,9 @@ public function getBaseUrl() { // } + + public function getUrl(Request $request) + { + return $request->getUri(); + } } From 7dbdece8ccdfb3267bb96195d44e440fb937b4d4 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 4 Sep 2024 10:48:24 -0400 Subject: [PATCH 15/21] change to single data provided test --- tests/StaticCaching/ApplicationCacherTest.php | 107 +++++++----------- 1 file changed, 43 insertions(+), 64 deletions(-) diff --git a/tests/StaticCaching/ApplicationCacherTest.php b/tests/StaticCaching/ApplicationCacherTest.php index b5b6e19fbd1..3ff3ae5e983 100644 --- a/tests/StaticCaching/ApplicationCacherTest.php +++ b/tests/StaticCaching/ApplicationCacherTest.php @@ -179,76 +179,55 @@ public function it_flushes() } #[Test] - public function it_gets_the_current_url() - { - $request = Request::create('http://example.com/test', 'GET'); - - $cacher = new ApplicationCacher(app(Repository::class), []); - - $this->assertEquals('http://example.com/test', $cacher->getUrl($request)); - } - - #[Test] - public function it_gets_the_current_url_with_query_parameters() - { - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - ]); + #[DataProvider('currentUrlProvider')] + public function it_gets_the_current_url( + array $query, + array $config, + string $expectedUrl + ) { + $request = Request::create('http://example.com/test', 'GET', $query); - $cacher = new ApplicationCacher(app(Repository::class), []); - - $this->assertEquals('http://example.com/test?foo=bar', $cacher->getUrl($request)); - } - - #[Test] - public function it_gets_the_current_url_with_query_strings_disabled() - { - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - ]); - - $cacher = new ApplicationCacher(app(Repository::class), [ - 'ignore_query_strings' => true, - ]); - - $this->assertEquals('http://example.com/test', $cacher->getUrl($request)); - } - - #[Test] - public function it_gets_the_current_url_with_allowed_query_parameters() - { - $request = Request::create('http://example.com/test', 'GET', [ - 'foo' => 'bar', - 'baz' => 'qux', - 'quux' => 'corge', - ]); - - $cacher = new ApplicationCacher(app(Repository::class), [ - 'allowed_query_strings' => ['foo', 'quux'], - ]); - - $this->assertEquals('http://example.com/test?foo=bar&quux=corge', $cacher->getUrl($request)); - } - - #[Test] - #[DataProvider('disallowedQueryParametersProvider')] - public function it_gets_the_current_url_with_disallowed_query_parameters(array $disallowed, string $url, array $query, string $expected) - { - $request = Request::create($url, 'GET', $query); - - $cacher = new ApplicationCacher(app(Repository::class), [ - 'disallowed_query_strings' => $disallowed, - ]); + $cacher = new ApplicationCacher(app(Repository::class), $config); - $this->assertEquals($expected, $cacher->getUrl($request)); + $this->assertEquals($expectedUrl, $cacher->getUrl($request)); } - public static function disallowedQueryParametersProvider() + public static function currentUrlProvider() { return [ - [[], 'http://example.com/test', ['foo' => 'bar'], 'http://example.com/test?foo=bar'], - [['quux'], 'http://example.com/test', ['quux' => 'corge'], 'http://example.com/test'], - [['quux'], 'http://example.com/test', ['foo' => 'bar', 'baz' => 'qux', 'quux' => 'corge'], 'http://example.com/test?baz=qux&foo=bar'], + 'no query' => [ + [], + [], + 'http://example.com/test', + ], + 'with query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + [], + 'http://example.com/test?alfa=a&bravo=b&charlie=c', + ], + 'with query, ignoring query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + ['ignore_query_strings' => true], + 'http://example.com/test', + ], + 'with query, allowed query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + ['allowed_query_strings' => ['alfa', 'bravo']], + 'http://example.com/test?alfa=a&bravo=b', + ], + 'with query, disallowed query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + ['disallowed_query_strings' => ['charlie']], + 'http://example.com/test?alfa=a&bravo=b', + ], + 'with query, allowed and disallowed' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + [ + 'allowed_query_strings' => ['alfa', 'bravo'], + 'disallowed_query_strings' => ['bravo'], + ], + 'http://example.com/test?alfa=a', + ], ]; } } From a6a84e0c1efe2bdc0ac7c2cb62306faa1fe7c299 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 4 Sep 2024 10:49:21 -0400 Subject: [PATCH 16/21] file cacher getUrl ignores the new settings, and keeps the query string order --- src/StaticCaching/Cachers/FileCacher.php | 26 ++++++++++- tests/StaticCaching/FileCacherTest.php | 55 ++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/StaticCaching/Cachers/FileCacher.php b/src/StaticCaching/Cachers/FileCacher.php index c0e372b5475..dd8c78c2d9a 100644 --- a/src/StaticCaching/Cachers/FileCacher.php +++ b/src/StaticCaching/Cachers/FileCacher.php @@ -12,6 +12,7 @@ use Statamic\StaticCaching\Replacers\CsrfTokenReplacer; use Statamic\Support\Arr; use Statamic\Support\Str; +use Symfony\Component\HttpFoundation\HeaderUtils; class FileCacher extends AbstractCacher { @@ -61,7 +62,7 @@ public function cachePage(Request $request, $content) $content = $this->normalizeContent($content); - $path = $this->getFilePath($request->getUri()); + $path = $this->getFilePath($url); if (! $this->writer->write($path, $content, $this->config('lock_hold_length'))) { return; @@ -265,4 +266,27 @@ public function getNocachePlaceholder() { return $this->nocachePlaceholder ?? ''; } + + public function getUrl(Request $request) + { + $url = $request->getUri(); + + $url = explode('?', $url)[0]; + + if ($this->config('ignore_query_strings', false)) { + return $url; + } + + // Symfony will normalize the query string which includes alphabetizing it. However, we + // want to maintain the real order so that when nginx looks for the file, it can find + // it. The following is the same normalizing code from Symfony without the ordering. + + if (! $qs = $request->server->get('QUERY_STRING')) { + return $url; + } + + $qs = HeaderUtils::parseQuery($qs); + + return $url.'?'.http_build_query($qs, '', '&', \PHP_QUERY_RFC3986); + } } diff --git a/tests/StaticCaching/FileCacherTest.php b/tests/StaticCaching/FileCacherTest.php index 131622d6c1b..bc522b5d5ae 100644 --- a/tests/StaticCaching/FileCacherTest.php +++ b/tests/StaticCaching/FileCacherTest.php @@ -3,6 +3,7 @@ namespace Tests\StaticCaching; use Illuminate\Contracts\Cache\Repository; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Event; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; @@ -325,6 +326,60 @@ public static function invalidateEventProvider() ]; } + #[Test] + #[DataProvider('currentUrlProvider')] + public function it_gets_the_current_url( + array $query, + array $config, + string $expectedUrl + ) { + $request = Request::create('http://example.com/test', 'GET', $query); + + $cacher = $this->fileCacher($config); + + $this->assertEquals($expectedUrl, $cacher->getUrl($request)); + } + + public static function currentUrlProvider() + { + return [ + 'no query' => [ + [], + [], + 'http://example.com/test', + ], + 'with query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + [], + 'http://example.com/test?bravo=b&charlie=c&alfa=a', + ], + 'with query, ignoring query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + ['ignore_query_strings' => true], + 'http://example.com/test', + ], + 'with query, allowed query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + ['allowed_query_strings' => ['alfa', 'bravo']], + 'http://example.com/test?bravo=b&charlie=c&alfa=a', // allowed_query_strings has no effect + ], + 'with query, disallowed query' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + ['disallowed_query_strings' => ['charlie']], + 'http://example.com/test?bravo=b&charlie=c&alfa=a', // disallowed_query_strings has no effect + + ], + 'with query, allowed and disallowed' => [ + ['bravo' => 'b', 'charlie' => 'c', 'alfa' => 'a'], + [ + 'allowed_query_strings' => ['alfa', 'bravo'], + 'disallowed_query_strings' => ['bravo'], + ], + 'http://example.com/test?bravo=b&charlie=c&alfa=a', // allowed_query_strings and disallowed_query_strings have no effect + ], + ]; + } + private function cacheKey($domain) { return 'static-cache:'.md5($domain).'.urls'; From 1e94ec9250fe82b4943a501fd39efb6fcb489dbd Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 4 Sep 2024 10:49:58 -0400 Subject: [PATCH 17/21] add noop config method --- src/StaticCaching/Cachers/NullCacher.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/StaticCaching/Cachers/NullCacher.php b/src/StaticCaching/Cachers/NullCacher.php index 567530e7c60..de27a40bbde 100644 --- a/src/StaticCaching/Cachers/NullCacher.php +++ b/src/StaticCaching/Cachers/NullCacher.php @@ -7,6 +7,10 @@ class NullCacher implements Cacher { + public function config($key, $default = null) + { + return $default; + } public function cachePage(Request $request, $content) { From e38462bf3b7cfb005cd2a5d306cfc7b6f9946869 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 4 Sep 2024 11:09:47 -0400 Subject: [PATCH 18/21] sync config name --- config/static_caching.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/static_caching.php b/config/static_caching.php index daf030dc751..2cb9f69f8f4 100644 --- a/config/static_caching.php +++ b/config/static_caching.php @@ -102,7 +102,7 @@ 'ignore_query_strings' => false, - 'allowed_query_parameters' => [ + 'allowed_query_strings' => [ // ], From 2b6c4f33ad10f3ffb6a31751bd8038b2f6d521fa Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Fri, 6 Sep 2024 16:04:37 -0400 Subject: [PATCH 19/21] dont filter query strings on excluded urls --- src/StaticCaching/Cachers/AbstractCacher.php | 4 ++++ src/StaticCaching/Cachers/FileCacher.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/StaticCaching/Cachers/AbstractCacher.php b/src/StaticCaching/Cachers/AbstractCacher.php index c2d9c1674fb..eb125047d2a 100644 --- a/src/StaticCaching/Cachers/AbstractCacher.php +++ b/src/StaticCaching/Cachers/AbstractCacher.php @@ -284,6 +284,10 @@ public function getUrl(Request $request) { $url = $request->getUri(); + if ($this->isExcluded($url)) { + return $url; + } + if ($this->config('ignore_query_strings', false)) { $url = explode('?', $url)[0]; } diff --git a/src/StaticCaching/Cachers/FileCacher.php b/src/StaticCaching/Cachers/FileCacher.php index dd8c78c2d9a..7be32839a52 100644 --- a/src/StaticCaching/Cachers/FileCacher.php +++ b/src/StaticCaching/Cachers/FileCacher.php @@ -271,6 +271,10 @@ public function getUrl(Request $request) { $url = $request->getUri(); + if ($this->isExcluded($url)) { + return $url; + } + $url = explode('?', $url)[0]; if ($this->config('ignore_query_strings', false)) { From 47e9046825137246b936b9bec4beed6449d677bd Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Fri, 6 Sep 2024 16:04:50 -0400 Subject: [PATCH 20/21] add a request macro --- src/StaticCaching/ServiceProvider.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/StaticCaching/ServiceProvider.php b/src/StaticCaching/ServiceProvider.php index e277702e7c2..5a025affe42 100644 --- a/src/StaticCaching/ServiceProvider.php +++ b/src/StaticCaching/ServiceProvider.php @@ -87,6 +87,10 @@ public function boot() return 'handle('.$exp.', \Illuminate\Support\Arr::except(get_defined_vars(), [\'__data\', \'__path\'])); ?>'; }); + Request::macro('normalizedFullUrl', function () { + return app(Cacher::class)->getUrl($this); + }); + Request::macro('fakeStaticCacheStatus', function (int $status) { $url = '/__shared-errors/'.$status; $this->pathInfo = $url; From 1fc804fbf977022bb7ef3fa448c7fb53deb36ef0 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 9 Sep 2024 10:32:59 -0400 Subject: [PATCH 21/21] needs a string, even if its not really used --- src/StaticCaching/Cachers/NullCacher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StaticCaching/Cachers/NullCacher.php b/src/StaticCaching/Cachers/NullCacher.php index de27a40bbde..014d3abceb9 100644 --- a/src/StaticCaching/Cachers/NullCacher.php +++ b/src/StaticCaching/Cachers/NullCacher.php @@ -49,7 +49,7 @@ public function getUrls($domain = null) public function getBaseUrl() { - // + return '/'; } public function getUrl(Request $request)