Skip to content

Commit cc286d5

Browse files
duncanmccleanclaudejasonvarga
authored
[6.x] Fix static cache invalidation stripping trailing slashes (#14713)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent 8b02ee0 commit cc286d5

2 files changed

Lines changed: 61 additions & 9 deletions

File tree

src/StaticCaching/DefaultInvalidator.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ protected function getFormUrls($form)
9797
$prefixedRelativeUrls = Site::all()->map(function ($site) use ($rules) {
9898
return $rules
9999
->reject(fn (string $rule) => URL::isAbsolute($rule))
100-
->map(fn (string $rule) => URL::tidy($site->url().'/'.$rule, withTrailingSlash: false));
100+
->map(fn (string $rule) => URL::tidy($site->url().'/'.$rule));
101101
})->flatten()->all();
102102

103103
return [
@@ -115,7 +115,7 @@ protected function getAssetUrls($asset)
115115
$prefixedRelativeUrls = Site::all()->map(function ($site) use ($rules) {
116116
return $rules
117117
->reject(fn (string $rule) => URL::isAbsolute($rule))
118-
->map(fn (string $rule) => URL::tidy($site->url().'/'.$rule, withTrailingSlash: false));
118+
->map(fn (string $rule) => URL::tidy($site->url().'/'.$rule));
119119
})->flatten()->all();
120120

121121
return [
@@ -141,7 +141,7 @@ protected function getEntryUrls($entry)
141141

142142
$prefixedRelativeUrls = $rules
143143
->reject(fn (string $rule) => URL::isAbsolute($rule))
144-
->map(fn (string $rule) => URL::tidy($entry->site()->url().'/'.$rule, withTrailingSlash: false))
144+
->map(fn (string $rule) => URL::tidy($entry->site()->url().'/'.$rule))
145145
->all();
146146

147147
return [
@@ -170,7 +170,7 @@ protected function getTermUrls($term)
170170

171171
$prefixedRelativeUrls = $rules
172172
->reject(fn (string $rule) => URL::isAbsolute($rule))
173-
->map(fn (string $rule) => URL::tidy($term->site()->url().'/'.$rule, withTrailingSlash: false))
173+
->map(fn (string $rule) => URL::tidy($term->site()->url().'/'.$rule))
174174
->all();
175175

176176
return [
@@ -192,7 +192,7 @@ protected function getNavUrls($nav)
192192
$prefixedRelativeUrls = $nav->sites()->map(function ($site) use ($rules) {
193193
return $rules
194194
->reject(fn (string $rule) => URL::isAbsolute($rule))
195-
->map(fn (string $rule) => URL::tidy(Site::get($site)->url().'/'.$rule, withTrailingSlash: false));
195+
->map(fn (string $rule) => URL::tidy(Site::get($site)->url().'/'.$rule));
196196
})->flatten()->all();
197197

198198
return [
@@ -212,7 +212,7 @@ protected function getNavTreeUrls($tree)
212212

213213
$prefixedRelativeUrls = $rules
214214
->reject(fn (string $rule) => URL::isAbsolute($rule))
215-
->map(fn (string $rule) => URL::tidy($tree->site()->url().'/'.$rule, withTrailingSlash: false))
215+
->map(fn (string $rule) => URL::tidy($tree->site()->url().'/'.$rule))
216216
->all();
217217

218218
return [
@@ -232,7 +232,7 @@ protected function getGlobalUrls($variables)
232232

233233
$prefixedRelativeUrls = $rules
234234
->reject(fn (string $rule) => URL::isAbsolute($rule))
235-
->map(fn (string $rule) => URL::tidy($variables->site()->url().'/'.$rule, withTrailingSlash: false))
235+
->map(fn (string $rule) => URL::tidy($variables->site()->url().'/'.$rule))
236236
->all();
237237

238238
return [
@@ -252,7 +252,7 @@ protected function getCollectionUrls($collection)
252252
$prefixedRelativeUrls = $collection->sites()->map(function ($site) use ($rules) {
253253
return $rules
254254
->reject(fn (string $rule) => URL::isAbsolute($rule))
255-
->map(fn (string $rule) => URL::tidy(Site::get($site)->url().'/'.$rule, withTrailingSlash: false));
255+
->map(fn (string $rule) => URL::tidy(Site::get($site)->url().'/'.$rule));
256256
})->flatten()->all();
257257

258258
return [
@@ -270,7 +270,7 @@ protected function getCollectionTreeUrls($tree)
270270

271271
$prefixedRelativeUrls = $rules
272272
->reject(fn (string $rule) => URL::isAbsolute($rule))
273-
->map(fn (string $rule) => URL::tidy($tree->site()->url().'/'.$rule, withTrailingSlash: false))
273+
->map(fn (string $rule) => URL::tidy($tree->site()->url().'/'.$rule))
274274
->all();
275275

276276
return [

tests/StaticCaching/DefaultInvalidatorTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Statamic\Contracts\Taxonomies\Taxonomy;
1515
use Statamic\Contracts\Taxonomies\Term;
1616
use Statamic\Facades\Site;
17+
use Statamic\Facades\URL;
1718
use Statamic\Globals\Variables;
1819
use Statamic\StaticCaching\Cacher;
1920
use Statamic\StaticCaching\DefaultInvalidator as Invalidator;
@@ -25,6 +26,13 @@
2526

2627
class DefaultInvalidatorTest extends TestCase
2728
{
29+
public function tearDown(): void
30+
{
31+
URL::enforceTrailingSlashes(false);
32+
URL::clearUrlCache();
33+
parent::tearDown();
34+
}
35+
2836
#[Test]
2937
public function specifying_all_as_invalidation_rule_will_just_flush_the_cache()
3038
{
@@ -388,6 +396,50 @@ public function collection_urls_can_be_invalidated_by_an_entry_in_a_multisite()
388396
$this->assertNull($invalidator->invalidate($entry));
389397
}
390398

399+
#[Test]
400+
public function invalidation_urls_respect_trailing_slash_enforcement()
401+
{
402+
URL::enforceTrailingSlashes();
403+
404+
$cacher = tap(Mockery::mock(Cacher::class), function ($cacher) {
405+
$cacher->shouldReceive('invalidateUrls')->with([
406+
'http://test.com/my/test/entry/',
407+
'http://localhost/blog/three/',
408+
'http://localhost/blog/one/',
409+
'http://localhost/blog/two/',
410+
])->once();
411+
});
412+
413+
$entry = tap(Mockery::mock(Entry::class), function ($m) {
414+
$m->shouldReceive('isRedirect')->andReturn(false);
415+
$m->shouldReceive('absoluteUrl')->andReturn('http://test.com/my/test/entry/');
416+
$m->shouldReceive('collectionHandle')->andReturn('blog');
417+
$m->shouldReceive('descendants')->andReturn(collect());
418+
$m->shouldReceive('site')->andReturn(Site::default());
419+
$m->shouldReceive('parent')->andReturnNull();
420+
$m->shouldReceive('toAugmentedCollection')
421+
->andReturnSelf()
422+
->shouldReceive('merge')
423+
->andReturn(collect([
424+
'parent_uri' => '/my/test/',
425+
]));
426+
});
427+
428+
$invalidator = new Invalidator($cacher, [
429+
'collections' => [
430+
'blog' => [
431+
'urls' => [
432+
'/blog/one',
433+
'/blog/two',
434+
'http://localhost/blog/three/',
435+
],
436+
],
437+
],
438+
]);
439+
440+
$this->assertNull($invalidator->invalidate($entry));
441+
}
442+
391443
#[Test]
392444
public function entry_urls_are_not_invalidated_by_an_entry_with_a_redirect()
393445
{

0 commit comments

Comments
 (0)