From ca3342008097aa218c7333e405a2fb12c7ea3102 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Fri, 30 Oct 2020 18:58:26 -0400 Subject: [PATCH] Support navigation and globals in the static caching invalidation Clean up tests by using regular mocks, not spies, and do a little tidying. Closes #2639 Closes #2393 Co-authored-by: Duncan McClean --- src/StaticCaching/DefaultInvalidator.php | 37 ++++-- src/StaticCaching/Invalidate.php | 18 +++ .../StaticCaching/DefaultInvalidatorTest.php | 118 +++++++++++------- 3 files changed, 118 insertions(+), 55 deletions(-) diff --git a/src/StaticCaching/DefaultInvalidator.php b/src/StaticCaching/DefaultInvalidator.php index e4d7ae42e2..ac354a1c1e 100644 --- a/src/StaticCaching/DefaultInvalidator.php +++ b/src/StaticCaching/DefaultInvalidator.php @@ -3,6 +3,8 @@ namespace Statamic\StaticCaching; use Statamic\Contracts\Entries\Entry; +use Statamic\Contracts\Globals\GlobalSet; +use Statamic\Contracts\Structures\Nav; use Statamic\Contracts\Taxonomies\Term; use Statamic\Support\Arr; @@ -23,33 +25,50 @@ public function invalidate($item) return $this->cacher->flush(); } - // Invalidate the item's own URL. - if ($url = $item->url()) { - $this->cacher->invalidateUrl($url); - } - if ($item instanceof Entry) { $this->invalidateEntryUrls($item); } elseif ($item instanceof Term) { $this->invalidateTermUrls($item); + } elseif ($item instanceof Nav) { + $this->invalidateNavUrls($item); + } elseif ($item instanceof GlobalSet) { + $this->invalidateGlobalUrls($item); } } protected function invalidateEntryUrls($entry) { - $collection = $entry->collectionHandle(); + if ($url = $entry->url()) { + $this->cacher->invalidateUrl($url); + } $this->cacher->invalidateUrls( - Arr::get($this->rules, "collections.$collection.urls") + Arr::get($this->rules, "collections.{$entry->collectionHandle()}.urls") ); } protected function invalidateTermUrls($term) { - $taxonomy = $term->taxonomyHandle(); + if ($url = $term->url()) { + $this->cacher->invalidateUrl($url); + } $this->cacher->invalidateUrls( - Arr::get($this->rules, "taxonomies.$taxonomy.urls") + Arr::get($this->rules, "taxonomies.{$term->taxonomyHandle()}.urls") + ); + } + + protected function invalidateNavUrls($nav) + { + $this->cacher->invalidateUrls( + Arr::get($this->rules, "navigation.{$nav->handle()}.urls") + ); + } + + protected function invalidateGlobalUrls($set) + { + $this->cacher->invalidateUrls( + Arr::get($this->rules, "globals.{$set->handle()}.urls") ); } } diff --git a/src/StaticCaching/Invalidate.php b/src/StaticCaching/Invalidate.php index 3962ed7a81..faa379bde3 100644 --- a/src/StaticCaching/Invalidate.php +++ b/src/StaticCaching/Invalidate.php @@ -5,6 +5,10 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Statamic\Events\EntryDeleted; use Statamic\Events\EntrySaved; +use Statamic\Events\GlobalSetDeleted; +use Statamic\Events\GlobalSetSaved; +use Statamic\Events\NavDeleted; +use Statamic\Events\NavSaved; use Statamic\Events\TermDeleted; use Statamic\Events\TermSaved; @@ -17,6 +21,10 @@ class Invalidate implements ShouldQueue EntryDeleted::class => 'invalidateEntry', TermSaved::class => 'invalidateTerm', TermDeleted::class => 'invalidateTerm', + GlobalSetSaved::class => 'invalidateGlobalSet', + GlobalSetDeleted::class => 'invalidateGlobalSet', + NavSaved::class => 'invalidateNav', + NavDeleted::class => 'invalidateNav', ]; public function __construct(Invalidator $invalidator) @@ -40,4 +48,14 @@ public function invalidateTerm($event) { $this->invalidator->invalidate($event->term); } + + public function invalidateGlobalSet($event) + { + $this->invalidator->invalidate($event->globals); + } + + public function invalidateNav($event) + { + $this->invalidator->invalidate($event->nav); + } } diff --git a/tests/StaticCaching/DefaultInvalidatorTest.php b/tests/StaticCaching/DefaultInvalidatorTest.php index 0e575fd0f1..4904c7f240 100644 --- a/tests/StaticCaching/DefaultInvalidatorTest.php +++ b/tests/StaticCaching/DefaultInvalidatorTest.php @@ -2,8 +2,10 @@ namespace Tests\StaticCaching; -use Statamic\Contracts\Data\Content\Content; +use Mockery; use Statamic\Contracts\Entries\Entry; +use Statamic\Contracts\Globals\GlobalSet; +use Statamic\Contracts\Structures\Nav; use Statamic\Contracts\Taxonomies\Term; use Statamic\StaticCaching\Cacher; use Statamic\StaticCaching\DefaultInvalidator as Invalidator; @@ -12,46 +14,33 @@ class DefaultInvalidatorTest extends \PHPUnit\Framework\TestCase { public function tearDown(): void { - if ($container = \Mockery::getContainer()) { - $this->addToAssertionCount($container->mockery_getExpectationCount()); - } - - parent::tearDown(); + Mockery::close(); } /** @test */ public function specifying_all_as_invalidation_rule_will_just_flush_the_cache() { - $cacher = \Mockery::spy(Cacher::class); - $invalidator = new Invalidator($cacher, 'all'); - $content = \Mockery::mock(Content::class); + $cacher = Mockery::mock(Cacher::class)->shouldReceive('flush')->once()->getMock(); + $item = Mockery::mock(Entry::class); - $invalidator->invalidate($content); + $invalidator = new Invalidator($cacher, 'all'); - $cacher->shouldHaveReceived('flush'); + $this->assertNull($invalidator->invalidate($item)); } /** @test */ - public function the_entrys_url_gets_invalidated() + public function collection_urls_can_be_invalidated() { - $cacher = \Mockery::spy(Cacher::class); - $invalidator = new Invalidator($cacher); + $cacher = tap(Mockery::mock(Cacher::class), function ($cacher) { + $cacher->shouldReceive('invalidateUrl')->with('/my/test/entry')->once(); + $cacher->shouldReceive('invalidateUrls')->once()->with(['/blog/one', '/blog/two']); + }); - $entry = tap(\Mockery::mock(Entry::class), function ($m) { + $entry = tap(Mockery::mock(Entry::class), function ($m) { $m->shouldReceive('url')->andReturn('/my/test/entry'); $m->shouldReceive('collectionHandle')->andReturn('blog'); }); - $invalidator->invalidate($entry); - - $cacher->shouldNotHaveReceived('flush'); - $cacher->shouldHaveReceived('invalidateUrl')->with('/my/test/entry'); - } - - /** @test */ - public function collection_urls_can_be_invalidated() - { - $cacher = \Mockery::spy(Cacher::class); $invalidator = new Invalidator($cacher, [ 'collections' => [ 'blog' => [ @@ -63,24 +52,22 @@ public function collection_urls_can_be_invalidated() ], ]); - $entry = tap(\Mockery::mock(Entry::class), function ($m) { - $m->shouldReceive('url')->andReturn('/my/test/entry'); - $m->shouldReceive('collectionHandle')->andReturn('blog'); - }); - - $invalidator->invalidate($entry); - - $cacher->shouldNotHaveReceived('flush'); - $cacher->shouldHaveReceived('invalidateUrls')->once()->with([ - '/blog/one', - '/blog/two', - ]); + $this->assertNull($invalidator->invalidate($entry)); } /** @test */ public function taxonomy_urls_can_be_invalidated() { - $cacher = \Mockery::spy(Cacher::class); + $cacher = tap(Mockery::mock(Cacher::class), function ($cacher) { + $cacher->shouldReceive('invalidateUrl')->with('/my/test/term')->once(); + $cacher->shouldReceive('invalidateUrls')->once()->with(['/tags/one', '/tags/two']); + }); + + $term = tap(Mockery::mock(Term::class), function ($m) { + $m->shouldReceive('url')->andReturn('/my/test/term'); + $m->shouldReceive('taxonomyHandle')->andReturn('tags'); + }); + $invalidator = new Invalidator($cacher, [ 'taxonomies' => [ 'tags' => [ @@ -92,17 +79,56 @@ public function taxonomy_urls_can_be_invalidated() ], ]); - $entry = tap(\Mockery::mock(Term::class), function ($m) { - $m->shouldReceive('url')->andReturn('/my/test/term'); - $m->shouldReceive('taxonomyHandle')->andReturn('tags'); + $this->assertNull($invalidator->invalidate($term)); + } + + /** @test */ + public function navigation_urls_can_be_invalidated() + { + $cacher = tap(Mockery::mock(Cacher::class), function ($cacher) { + $cacher->shouldReceive('invalidateUrls')->once()->with(['/one', '/two']); }); - $invalidator->invalidate($entry); + $nav = tap(Mockery::mock(Nav::class), function ($m) { + $m->shouldReceive('handle')->andReturn('links'); + }); - $cacher->shouldNotHaveReceived('flush'); - $cacher->shouldHaveReceived('invalidateUrls')->once()->with([ - '/tags/one', - '/tags/two', + $invalidator = new Invalidator($cacher, [ + 'navigation' => [ + 'links' => [ + 'urls' => [ + '/one', + '/two', + ], + ], + ], ]); + + $this->assertNull($invalidator->invalidate($nav)); + } + + /** @test */ + public function globals_urls_can_be_invalidated() + { + $cacher = tap(Mockery::mock(Cacher::class), function ($cacher) { + $cacher->shouldReceive('invalidateUrls')->once()->with(['/one', '/two']); + }); + + $set = tap(Mockery::mock(GlobalSet::class), function ($m) { + $m->shouldReceive('handle')->andReturn('social'); + }); + + $invalidator = new Invalidator($cacher, [ + 'globals' => [ + 'social' => [ + 'urls' => [ + '/one', + '/two', + ], + ], + ], + ]); + + $this->assertNull($invalidator->invalidate($set)); } }