diff --git a/src/Events/CollectionDefaultsSaved.php b/src/Events/CollectionDefaultsSaved.php new file mode 100644 index 00000000..289956cc --- /dev/null +++ b/src/Events/CollectionDefaultsSaved.php @@ -0,0 +1,11 @@ +cascade($cascade->all())->save(); + if ($item instanceof Collection) { + CollectionDefaultsSaved::dispatch($item); + } elseif ($item instanceof Taxonomy) { + TaxonomyDefaultsSaved::dispatch($item); + } + if ($disabled) { $this->removeChildSeo($item); } diff --git a/src/Listeners/InvalidateStaticCache.php b/src/Listeners/InvalidateStaticCache.php index 88356da7..c1fdb791 100644 --- a/src/Listeners/InvalidateStaticCache.php +++ b/src/Listeners/InvalidateStaticCache.php @@ -4,20 +4,25 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Statamic\Facades\URL; +use Statamic\SeoPro\Events\CollectionDefaultsSaved; use Statamic\SeoPro\Events\SiteDefaultsSaved; +use Statamic\SeoPro\Events\TaxonomyDefaultsSaved; use Statamic\StaticCaching\Cacher; +use Statamic\StaticCaching\Invalidator; use Statamic\Support\Arr; class InvalidateStaticCache implements ShouldQueue { private string|array $rules; - public function __construct(private Cacher $cacher) - { + public function __construct( + private Cacher $cacher, + private Invalidator $invalidator + ) { $this->rules = config('statamic.static_caching.invalidation.rules', []); } - public function handle(SiteDefaultsSaved $event): void + public function handleSiteDefaultsSaved(SiteDefaultsSaved $event): void { if (! config('statamic.static_caching.strategy')) { return; @@ -42,4 +47,36 @@ public function handle(SiteDefaultsSaved $event): void ...$prefixedRelativeUrls, ]); } + + public function handleCollectionDefaultsSaved(CollectionDefaultsSaved $event): void + { + if (! config('statamic.static_caching.strategy')) { + return; + } + + if ($this->rules === 'all') { + $this->cacher->flush(); + + return; + } + + $this->invalidator->invalidate($event->collection); + } + + public function handleTaxonomyDefaultsSaved(TaxonomyDefaultsSaved $event): void + { + if (! config('statamic.static_caching.strategy')) { + return; + } + + if ($this->rules === 'all') { + $this->cacher->flush(); + + return; + } + + $event->taxonomy->queryTerms()->get()->each(function ($term) { + $this->invalidator->invalidate($term); + }); + } } diff --git a/tests/StaticCachingInvalidationTest.php b/tests/StaticCachingInvalidationTest.php index 31f5421e..edd3d89d 100644 --- a/tests/StaticCachingInvalidationTest.php +++ b/tests/StaticCachingInvalidationTest.php @@ -4,9 +4,14 @@ use Mockery; use PHPUnit\Framework\Attributes\Test; +use Statamic\Facades\Collection; use Statamic\Facades\Site; +use Statamic\Facades\Taxonomy; +use Statamic\SeoPro\Events\CollectionDefaultsSaved; +use Statamic\SeoPro\Events\TaxonomyDefaultsSaved; use Statamic\SeoPro\SiteDefaults\SiteDefaults; use Statamic\StaticCaching\Cacher; +use Statamic\StaticCaching\Invalidator; class StaticCachingInvalidationTest extends TestCase { @@ -96,4 +101,91 @@ public function invalidates_urls_when_site_defaults_are_saved_in_a_multisite() SiteDefaults::in('fr')->save(); } + + #[Test] + public function does_nothing_for_collection_defaults_when_static_caching_is_disabled() + { + $invalidator = Mockery::mock(Invalidator::class); + $invalidator->shouldReceive('invalidate')->never(); + + $this->app->bind(Invalidator::class, fn () => $invalidator); + + config()->set('statamic.static_caching.strategy', null); + + $collection = Collection::find('pages'); + + CollectionDefaultsSaved::dispatch($collection); + } + + #[Test] + public function flushes_static_cache_when_collection_defaults_are_saved_with_all_rules() + { + $invalidator = Mockery::mock(Invalidator::class); + $invalidator->shouldReceive('invalidate')->never(); + + $this->app->bind(Invalidator::class, fn () => $invalidator); + + config()->set('statamic.static_caching.invalidation.rules', 'all'); + + $collection = Collection::find('pages'); + + CollectionDefaultsSaved::dispatch($collection); + } + + #[Test] + public function invalidates_collection_when_collection_defaults_are_saved() + { + $collection = Collection::find('pages'); + + $invalidator = Mockery::mock(Invalidator::class); + $invalidator->shouldReceive('invalidate')->withArgs(function ($item) use ($collection) { + return $item->handle() === $collection->handle(); + })->once(); + + $this->app->bind(Invalidator::class, fn () => $invalidator); + + CollectionDefaultsSaved::dispatch($collection); + } + + #[Test] + public function does_nothing_for_taxonomy_defaults_when_static_caching_is_disabled() + { + $invalidator = Mockery::mock(Invalidator::class); + $invalidator->shouldReceive('invalidate')->never(); + + $this->app->bind(Invalidator::class, fn () => $invalidator); + + config()->set('statamic.static_caching.strategy', null); + + $taxonomy = Taxonomy::find('topics'); + + TaxonomyDefaultsSaved::dispatch($taxonomy); + } + + #[Test] + public function flushes_static_cache_when_taxonomy_defaults_are_saved_with_all_rules() + { + $cacher = Mockery::mock(Cacher::class)->shouldReceive('flush')->once()->getMock(); + + $this->app->bind(Cacher::class, fn () => $cacher); + + config()->set('statamic.static_caching.invalidation.rules', 'all'); + + $taxonomy = Taxonomy::find('topics'); + + TaxonomyDefaultsSaved::dispatch($taxonomy); + } + + #[Test] + public function invalidates_terms_when_taxonomy_defaults_are_saved() + { + $taxonomy = Taxonomy::find('topics'); + + $invalidator = Mockery::mock(Invalidator::class); + $invalidator->shouldReceive('invalidate')->times($taxonomy->queryTerms()->count()); + + $this->app->bind(Invalidator::class, fn () => $invalidator); + + TaxonomyDefaultsSaved::dispatch($taxonomy); + } }