From 07e0017fea3ac0ec19c001b28ecca3a335149698 Mon Sep 17 00:00:00 2001 From: Martijn Date: Mon, 30 Mar 2026 16:20:13 +0200 Subject: [PATCH] Add ability to exclude queries from graphql cache --- config/graphql.php | 1 + src/GraphQL/ResponseCache/DefaultCache.php | 51 ++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/config/graphql.php b/config/graphql.php index 02f8258ce31..485040aee2d 100644 --- a/config/graphql.php +++ b/config/graphql.php @@ -86,6 +86,7 @@ 'cache' => [ 'expiry' => 60, + 'exclude' => [], ], ]; diff --git a/src/GraphQL/ResponseCache/DefaultCache.php b/src/GraphQL/ResponseCache/DefaultCache.php index d49014bce31..f160210ffb6 100644 --- a/src/GraphQL/ResponseCache/DefaultCache.php +++ b/src/GraphQL/ResponseCache/DefaultCache.php @@ -2,6 +2,8 @@ namespace Statamic\GraphQL\ResponseCache; +use GraphQL\Language\AST\FieldNode; +use GraphQL\Language\Parser; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; @@ -12,6 +14,10 @@ class DefaultCache implements ResponseCache { public function get(Request $request) { + if ($this->shouldBypassCache($request->input('query'))) { + return null; + } + return Cache::get($this->getCacheKey($request)); } @@ -66,4 +72,49 @@ public function handleInvalidationEvent(Event $event) Cache::forget($this->getTrackingKey()); } + + public function shouldBypassCache(string $query): bool + { + $excludedQueries = config('statamic.graphql.cache.exclude', []); + if (!$excludedQueries) { + return false; + } + + $ast = Parser::parse($query); + + foreach ($ast->definitions as $definition) { + if (!isset($definition->selectionSet)) { + continue; + } + + foreach (array_keys($excludedQueries) as $excludedQuery) { + foreach ($definition->selectionSet->selections as $selection) { + if ($this->containsFieldRecursive($selection, $excludedQuery)) { + return true; + } + } + } + } + + return false; + } + + private function containsFieldRecursive($node, string $fieldName): bool + { + if ($node instanceof FieldNode) { + if ($node->name->value === $fieldName) { + return true; + } + + if ($node->selectionSet) { + foreach ($node->selectionSet->selections as $selection) { + if ($this->containsFieldRecursive($selection, $fieldName)) { + return true; + } + } + } + } + + return false; + } }