From 95169161e0f7813391bf99f495a301e39eb26c7b Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Mon, 9 Mar 2026 11:44:23 +0100 Subject: [PATCH 1/3] Update tooling --- benchmarks/ASTUnserializationBench.php | 2 ++ src/Auth/BaseCanDirective.php | 2 +- src/Execution/Arguments/Argument.php | 4 +--- src/Execution/ContextSerializer.php | 2 ++ src/Scout/ScoutEnhancer.php | 4 +--- src/Subscriptions/Storage/RedisStorageManager.php | 2 ++ src/Subscriptions/Subscriber.php | 2 ++ tests/Integration/Async/AsyncDirectiveTest.php | 2 ++ tests/Unit/Schema/AST/DocumentASTTest.php | 2 ++ tests/Unit/Subscriptions/SubscriberTest.php | 2 ++ 10 files changed, 17 insertions(+), 7 deletions(-) diff --git a/benchmarks/ASTUnserializationBench.php b/benchmarks/ASTUnserializationBench.php index a2fbb11d93..8b8723a62e 100644 --- a/benchmarks/ASTUnserializationBench.php +++ b/benchmarks/ASTUnserializationBench.php @@ -5,6 +5,8 @@ use GraphQL\Language\Parser; use Nuwave\Lighthouse\Schema\AST\DocumentAST; +use function Safe\unserialize; + /** * @BeforeMethods({"prepareSchema"}) */ diff --git a/src/Auth/BaseCanDirective.php b/src/Auth/BaseCanDirective.php index f1d463c786..61f49cbfdd 100644 --- a/src/Auth/BaseCanDirective.php +++ b/src/Auth/BaseCanDirective.php @@ -108,7 +108,7 @@ public function handleField(FieldValue $fieldValue): void } catch (\Throwable $throwable) { $action = $this->directiveArgValue('action'); if ($action === 'EXCEPTION_NOT_AUTHORIZED') { - throw new AuthorizationException(); + throw new AuthorizationException($throwable->getMessage(), $throwable->getCode(), $throwable); } if ($action === 'RETURN_VALUE') { diff --git a/src/Execution/Arguments/Argument.php b/src/Execution/Arguments/Argument.php index 6fa6f36511..850cd62603 100644 --- a/src/Execution/Arguments/Argument.php +++ b/src/Execution/Arguments/Argument.php @@ -14,9 +14,7 @@ class Argument */ public mixed $value; - /** - * The type of the argument. - */ + /** The type of the argument. */ public ListType|NamedType|null $type = null; /** diff --git a/src/Execution/ContextSerializer.php b/src/Execution/ContextSerializer.php index 854b2518a8..c65a102298 100644 --- a/src/Execution/ContextSerializer.php +++ b/src/Execution/ContextSerializer.php @@ -9,6 +9,8 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; use Nuwave\Lighthouse\Support\Contracts\SerializesContext; +use function Safe\unserialize; + class ContextSerializer implements SerializesContext { use SerializesAndRestoresModelIdentifiers; diff --git a/src/Scout/ScoutEnhancer.php b/src/Scout/ScoutEnhancer.php index 24b99c8c84..f7920a0892 100644 --- a/src/Scout/ScoutEnhancer.php +++ b/src/Scout/ScoutEnhancer.php @@ -40,9 +40,7 @@ class ScoutEnhancer public function __construct( protected ArgumentSet $argumentSet, - /** - * @var \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation|\Laravel\Scout\Builder $builder - */ + /** @var \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation|\Laravel\Scout\Builder $builder */ protected QueryBuilder|EloquentBuilder|Relation|ScoutBuilder $builder, ) { $this->gather($this->argumentSet); diff --git a/src/Subscriptions/Storage/RedisStorageManager.php b/src/Subscriptions/Storage/RedisStorageManager.php index 53709ddb5f..00cfcfa27f 100644 --- a/src/Subscriptions/Storage/RedisStorageManager.php +++ b/src/Subscriptions/Storage/RedisStorageManager.php @@ -10,6 +10,8 @@ use Nuwave\Lighthouse\Subscriptions\Contracts\StoresSubscriptions; use Nuwave\Lighthouse\Subscriptions\Subscriber; +use function Safe\unserialize; + /** * Stores subscribers and topics in redis. * diff --git a/src/Subscriptions/Subscriber.php b/src/Subscriptions/Subscriber.php index 691f5d14cc..9387a48174 100644 --- a/src/Subscriptions/Subscriber.php +++ b/src/Subscriptions/Subscriber.php @@ -11,6 +11,8 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; use Nuwave\Lighthouse\Support\Contracts\SerializesContext; +use function Safe\unserialize; + class Subscriber { /** diff --git a/tests/Integration/Async/AsyncDirectiveTest.php b/tests/Integration/Async/AsyncDirectiveTest.php index ec914bc603..48efb497f0 100644 --- a/tests/Integration/Async/AsyncDirectiveTest.php +++ b/tests/Integration/Async/AsyncDirectiveTest.php @@ -10,6 +10,8 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; use Tests\DBTestCase; +use function Safe\unserialize; + final class AsyncDirectiveTest extends DBTestCase { public function testDispatchesMutation(): void diff --git a/tests/Unit/Schema/AST/DocumentASTTest.php b/tests/Unit/Schema/AST/DocumentASTTest.php index fd6ad27008..484a806e63 100644 --- a/tests/Unit/Schema/AST/DocumentASTTest.php +++ b/tests/Unit/Schema/AST/DocumentASTTest.php @@ -11,6 +11,8 @@ use Tests\TestCase; use Tests\Utils\Models\User; +use function Safe\unserialize; + final class DocumentASTTest extends TestCase { public function testParsesSimpleSchema(): void diff --git a/tests/Unit/Subscriptions/SubscriberTest.php b/tests/Unit/Subscriptions/SubscriberTest.php index 6aa76bd287..d1ba229df7 100644 --- a/tests/Unit/Subscriptions/SubscriberTest.php +++ b/tests/Unit/Subscriptions/SubscriberTest.php @@ -12,6 +12,8 @@ use Tests\TestCase; use Tests\TestsSerialization; +use function Safe\unserialize; + final class SubscriberTest extends TestCase { use TestsSerialization; From 4df3d5ab040543205ac6fa5a8b4b8eaa6c106603 Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Mon, 9 Mar 2026 13:46:58 +0100 Subject: [PATCH 2/3] fix auth exception --- src/Auth/BaseCanDirective.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/BaseCanDirective.php b/src/Auth/BaseCanDirective.php index 61f49cbfdd..0d158b4f67 100644 --- a/src/Auth/BaseCanDirective.php +++ b/src/Auth/BaseCanDirective.php @@ -108,7 +108,7 @@ public function handleField(FieldValue $fieldValue): void } catch (\Throwable $throwable) { $action = $this->directiveArgValue('action'); if ($action === 'EXCEPTION_NOT_AUTHORIZED') { - throw new AuthorizationException($throwable->getMessage(), $throwable->getCode(), $throwable); + throw new AuthorizationException(AuthorizationException::MESSAGE, $throwable->getCode(), $throwable); } if ($action === 'RETURN_VALUE') { From 4bdbdee5af513de831fc82bbf4660a5079822dfa Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Mon, 9 Mar 2026 15:39:19 +0100 Subject: [PATCH 3/3] ignore Safe\unserialize - only in newer safe-php, breaking change to use it now --- benchmarks/ASTUnserializationBench.php | 4 ++-- src/Execution/ContextSerializer.php | 3 +-- src/Subscriptions/Storage/RedisStorageManager.php | 4 ++-- src/Subscriptions/Subscriber.php | 3 +-- tests/Integration/Async/AsyncDirectiveTest.php | 4 ++-- tests/Unit/Schema/AST/DocumentASTTest.php | 3 +-- tests/Unit/Subscriptions/SubscriberTest.php | 3 +-- 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/benchmarks/ASTUnserializationBench.php b/benchmarks/ASTUnserializationBench.php index 8b8723a62e..83d1061f8b 100644 --- a/benchmarks/ASTUnserializationBench.php +++ b/benchmarks/ASTUnserializationBench.php @@ -5,8 +5,6 @@ use GraphQL\Language\Parser; use Nuwave\Lighthouse\Schema\AST\DocumentAST; -use function Safe\unserialize; - /** * @BeforeMethods({"prepareSchema"}) */ @@ -54,6 +52,7 @@ public function prepareSchema(): void */ public function benchUnserializeDocumentNode(): void { + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) unserialize($this->documentNode); } @@ -64,6 +63,7 @@ public function benchUnserializeDocumentNode(): void */ public function benchUnserializeDocumentAST(): void { + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) unserialize($this->documentAST); } } diff --git a/src/Execution/ContextSerializer.php b/src/Execution/ContextSerializer.php index c65a102298..6d1c699cf1 100644 --- a/src/Execution/ContextSerializer.php +++ b/src/Execution/ContextSerializer.php @@ -9,8 +9,6 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; use Nuwave\Lighthouse\Support\Contracts\SerializesContext; -use function Safe\unserialize; - class ContextSerializer implements SerializesContext { use SerializesAndRestoresModelIdentifiers; @@ -44,6 +42,7 @@ public function unserialize(string $context): GraphQLContext [ 'request' => $rawRequest, 'user' => $rawUser + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) ] = unserialize($context); if ($rawRequest) { diff --git a/src/Subscriptions/Storage/RedisStorageManager.php b/src/Subscriptions/Storage/RedisStorageManager.php index 00cfcfa27f..4bf2848580 100644 --- a/src/Subscriptions/Storage/RedisStorageManager.php +++ b/src/Subscriptions/Storage/RedisStorageManager.php @@ -10,8 +10,6 @@ use Nuwave\Lighthouse\Subscriptions\Contracts\StoresSubscriptions; use Nuwave\Lighthouse\Subscriptions\Subscriber; -use function Safe\unserialize; - /** * Stores subscribers and topics in redis. * @@ -89,6 +87,7 @@ public function subscribersByTopic(string $topic): Collection // Other entries may contain invalid values. try { + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) $subscriber = unserialize($subscriber); // This key exists so remove it from the list of missing keys. @@ -166,6 +165,7 @@ protected function getSubscriber(string $channelKey): ?Subscriber $subscriber = $this->connection->command('get', [$channelKey]); return is_string($subscriber) + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) ? unserialize($subscriber) : null; } diff --git a/src/Subscriptions/Subscriber.php b/src/Subscriptions/Subscriber.php index 9387a48174..a79fb8b731 100644 --- a/src/Subscriptions/Subscriber.php +++ b/src/Subscriptions/Subscriber.php @@ -11,8 +11,6 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; use Nuwave\Lighthouse\Support\Contracts\SerializesContext; -use function Safe\unserialize; - class Subscriber { /** @@ -105,6 +103,7 @@ public function __unserialize(array $data): void $this->topic = $data['topic']; $documentNode = AST::fromArray( + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) unserialize($data['query']), ); assert($documentNode instanceof DocumentNode, 'We know the type since it is set during construction and serialized.'); diff --git a/tests/Integration/Async/AsyncDirectiveTest.php b/tests/Integration/Async/AsyncDirectiveTest.php index 48efb497f0..bbd68474d5 100644 --- a/tests/Integration/Async/AsyncDirectiveTest.php +++ b/tests/Integration/Async/AsyncDirectiveTest.php @@ -10,8 +10,6 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; use Tests\DBTestCase; -use function Safe\unserialize; - final class AsyncDirectiveTest extends DBTestCase { public function testDispatchesMutation(): void @@ -40,6 +38,7 @@ public function testDispatchesMutation(): void foreach ($jobs as $job) { $this->assertInstanceOf(AsyncMutation::class, $job); + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) $jobCycledThroughSerialization = unserialize(serialize($job)); $this->assertInstanceOf(AsyncMutation::class, $jobCycledThroughSerialization); Container::getInstance()->call([$jobCycledThroughSerialization, 'handle']); @@ -73,6 +72,7 @@ public function testDispatchesMutationOnCustomQueue(): void $this->assertInstanceOf(AsyncMutation::class, $job); $this->assertSame('custom', $job->queue); + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) $jobCycledThroughSerialization = unserialize(serialize($job)); $this->assertInstanceOf(AsyncMutation::class, $jobCycledThroughSerialization); Container::getInstance()->call([$jobCycledThroughSerialization, 'handle']); diff --git a/tests/Unit/Schema/AST/DocumentASTTest.php b/tests/Unit/Schema/AST/DocumentASTTest.php index 484a806e63..b5f00c8c5c 100644 --- a/tests/Unit/Schema/AST/DocumentASTTest.php +++ b/tests/Unit/Schema/AST/DocumentASTTest.php @@ -11,8 +11,6 @@ use Tests\TestCase; use Tests\Utils\Models\User; -use function Safe\unserialize; - final class DocumentASTTest extends TestCase { public function testParsesSimpleSchema(): void @@ -100,6 +98,7 @@ public function testBeSerialized(): void directive @foo on FIELD GRAPHQL); + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) $reserialized = unserialize( serialize($documentAST), ); diff --git a/tests/Unit/Subscriptions/SubscriberTest.php b/tests/Unit/Subscriptions/SubscriberTest.php index d1ba229df7..ed477a33a8 100644 --- a/tests/Unit/Subscriptions/SubscriberTest.php +++ b/tests/Unit/Subscriptions/SubscriberTest.php @@ -12,8 +12,6 @@ use Tests\TestCase; use Tests\TestsSerialization; -use function Safe\unserialize; - final class SubscriberTest extends TestCase { use TestsSerialization; @@ -47,6 +45,7 @@ public function testSerializable(): void $channel = $subscriber->channel; + // @phpstan-ignore theCodingMachineSafe.function (Safe\unserialize is not available in thecodingmachine/safe ^1 and ^2) $serialized = unserialize(serialize($subscriber)); $this->assertInstanceOf(Subscriber::class, $serialized);