From e1643b7a647ce7a5cdfc42be80c4898c2a73dc4f Mon Sep 17 00:00:00 2001 From: Martijn Date: Fri, 8 May 2026 10:15:55 +0200 Subject: [PATCH] Add possibility to bypass 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 329c0d463f0..eaf04d62163 100644 --- a/config/graphql.php +++ b/config/graphql.php @@ -98,6 +98,7 @@ 'cache' => [ 'expiry' => 60, + 'exclude' => [], ], /* diff --git a/src/GraphQL/ResponseCache/DefaultCache.php b/src/GraphQL/ResponseCache/DefaultCache.php index 14a99190933..f0bc888aa48 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\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Carbon; @@ -13,6 +15,10 @@ class DefaultCache implements ResponseCache { public function get(Request $request) { + if ($this->shouldBypassCache($request->input('query'))) { + return null; + } + $cached = Cache::get($this->getCacheKey($request)); if (! is_array($cached)) { @@ -77,4 +83,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; + } }