diff --git a/src/StaticCache.php b/src/StaticCache.php index 527a82f..e113847 100644 --- a/src/StaticCache.php +++ b/src/StaticCache.php @@ -12,6 +12,7 @@ use craft\helpers\ElementHelper; use craft\helpers\StringHelper; use craft\services\Elements; +use craft\services\Gql; use craft\utilities\ClearCaches; use craft\web\UrlManager; use craft\web\View; @@ -62,6 +63,8 @@ class StaticCache extends \yii\base\Component private Collection $tagsToPurge; private Collection $fetchUrls; private bool $collectingCacheInfo = false; + /** @var bool[] */ + private array $graphqlCachingStack = []; public function init(): void { @@ -78,6 +81,18 @@ public function registerEventHandlers(): void fn(Event $event) => $this->handleInitWebApplication($event), ); + Event::on( + Gql::class, + Gql::EVENT_BEFORE_EXECUTE_GQL_QUERY, + fn(Event $event) => $this->handleBeforeExecuteGqlQuery($event), + ); + + Event::on( + Gql::class, + Gql::EVENT_AFTER_EXECUTE_GQL_QUERY, + fn(Event $event) => $this->handleAfterExecuteGqlQuery($event), + ); + Event::on( View::class, View::EVENT_BEFORE_RENDER_PAGE_TEMPLATE, @@ -164,6 +179,23 @@ private function handleAfterPrepareWebResponse(Event $event): void $this->addCacheHeadersToWebResponse(); } + private function handleBeforeExecuteGqlQuery(Event $event): void + { + if ($this->collectingCacheInfo) { + // TODO: Remove after https://github.com/craftcms/cms/pull/19508 reaches Cloud's minimum supported Craft version. + $generalConfig = Craft::$app->getConfig()->getGeneral(); + $this->graphqlCachingStack[] = $generalConfig->enableGraphqlCaching; + $generalConfig->enableGraphqlCaching = false; + } + } + + private function handleAfterExecuteGqlQuery(Event $event): void + { + if ($this->graphqlCachingStack !== []) { + Craft::$app->getConfig()->getGeneral()->enableGraphqlCaching = array_pop($this->graphqlCachingStack); + } + } + private function handleBeforeRenderPageTemplate(TemplateEvent $event): void { /** @var UrlManager $urlManager */ diff --git a/tests/unit/StaticCacheTest.php b/tests/unit/StaticCacheTest.php index 3ace6cd..3e38dac 100644 --- a/tests/unit/StaticCacheTest.php +++ b/tests/unit/StaticCacheTest.php @@ -125,6 +125,35 @@ public function testPostResponsesAreNotCacheable(): void $this->assertFalse($this->isCacheable($staticCache)); } + public function testGraphqlCachingIsOnlyDisabledWhileCollectingCacheInfo(): void + { + $staticCache = new StaticCache(); + $generalConfig = Craft::$app->getConfig()->getGeneral(); + $enableGraphqlCaching = $generalConfig->enableGraphqlCaching; + + try { + $generalConfig->enableGraphqlCaching = true; + $this->handleBeforeExecuteGqlQuery($staticCache); + $this->assertTrue($generalConfig->enableGraphqlCaching); + + $collectingCacheInfo = new ReflectionProperty($staticCache, 'collectingCacheInfo'); + $collectingCacheInfo->setValue($staticCache, true); + $this->handleBeforeExecuteGqlQuery($staticCache); + $this->assertFalse($generalConfig->enableGraphqlCaching); + + $this->handleBeforeExecuteGqlQuery($staticCache); + $this->assertFalse($generalConfig->enableGraphqlCaching); + + $this->handleAfterExecuteGqlQuery($staticCache); + $this->assertFalse($generalConfig->enableGraphqlCaching); + + $this->handleAfterExecuteGqlQuery($staticCache); + $this->assertTrue($generalConfig->enableGraphqlCaching); + } finally { + $generalConfig->enableGraphqlCaching = $enableGraphqlCaching; + } + } + public function testStaticCacheDirectivesPreferCdnCacheControl(): void { $staticCache = new StaticCache(); @@ -602,6 +631,18 @@ private function staticCacheDirectives(StaticCache $staticCache): Collection return $method->invoke($staticCache); } + private function handleBeforeExecuteGqlQuery(StaticCache $staticCache): void + { + $method = new ReflectionMethod($staticCache, 'handleBeforeExecuteGqlQuery'); + $method->invoke($staticCache, new \yii\base\Event()); + } + + private function handleAfterExecuteGqlQuery(StaticCache $staticCache): void + { + $method = new ReflectionMethod($staticCache, 'handleAfterExecuteGqlQuery'); + $method->invoke($staticCache, new \yii\base\Event()); + } + private function addCacheHeadersToWebResponse(StaticCache $staticCache): void { $method = new ReflectionMethod($staticCache, 'addCacheHeadersToWebResponse');