diff --git a/src/Schema/Resolver/AbstractResolver.php b/src/Schema/Resolver/AbstractResolver.php index 0beb1513..545460f4 100644 --- a/src/Schema/Resolver/AbstractResolver.php +++ b/src/Schema/Resolver/AbstractResolver.php @@ -54,4 +54,12 @@ public function resolveType($rootValue, $context = null, ?ResolveInfo $info = nu // Override this method when your resolver returns an interface or an union type. return null; } + + /** + * @inheritdoc + */ + public function getMiddleware(): ?array + { + return null; + } } diff --git a/src/Schema/Resolver/ResolverCollection.php b/src/Schema/Resolver/ResolverCollection.php index c1b58c38..838e5507 100644 --- a/src/Schema/Resolver/ResolverCollection.php +++ b/src/Schema/Resolver/ResolverCollection.php @@ -29,6 +29,15 @@ public function addResolver(string $fieldName, callable $resolver) $this->resolvers[$fieldName] = $resolver; } + /** + * @param string $fieldName + * @return callable|null + */ + public function getResolver(string $fieldName): ?callable + { + return $this->resolvers[$fieldName] ?? null; + } + /** * @inheritdoc */ @@ -51,6 +60,14 @@ public function getTypeResolver(): ?callable return $this->resolvers[static::TYPE_RESOLVER_KEY] ?? null; } + /** + * @inheritdoc + */ + public function getMiddleware(): ?array + { + return null; + } + /** * @param array $resolvers */ @@ -64,13 +81,4 @@ protected function registerResolvers(array $resolvers): void $this->addResolver($typeName, $resolver); } } - - /** - * @param string $fieldName - * @return callable|null - */ - protected function getResolver(string $fieldName): ?callable - { - return $this->resolvers[$fieldName] ?? null; - } } diff --git a/src/Schema/Resolver/ResolverInterface.php b/src/Schema/Resolver/ResolverInterface.php index e35cd31f..a23b8cf8 100644 --- a/src/Schema/Resolver/ResolverInterface.php +++ b/src/Schema/Resolver/ResolverInterface.php @@ -13,4 +13,9 @@ public function getResolveCallback(): ?callable; * @return callable|null */ public function getTypeResolver(): ?callable; + + /** + * @return array|null + */ + public function getMiddleware(): ?array; } diff --git a/src/Schema/Resolver/ResolverRegistry.php b/src/Schema/Resolver/ResolverRegistry.php index 280fd4d1..5994b6f8 100644 --- a/src/Schema/Resolver/ResolverRegistry.php +++ b/src/Schema/Resolver/ResolverRegistry.php @@ -44,7 +44,7 @@ public function getFieldResolver(string $typeName, string $fieldName): ?callable $resolver = $this->getResolver($typeName); $resolver = $resolver instanceof ResolverCollection - ? $resolver->getResolveCallback()($fieldName) + ? $resolver->getResolver($fieldName) : $resolver; $resolveCallback = $resolver instanceof ResolverInterface @@ -56,7 +56,11 @@ public function getFieldResolver(string $typeName, string $fieldName): ?callable } if (null !== $this->middleware) { - return $this->applyMiddleware($resolveCallback, \array_reverse($this->middleware)); + $middleware = $resolver instanceof ResolverInterface + ? $this->getMiddlewareToApply($resolver, $this->middleware) + : $this->middleware; + + return $this->applyMiddleware($resolveCallback, \array_reverse($middleware)); } return $resolveCallback; @@ -98,6 +102,24 @@ protected function registerResolvers(array $resolvers): void } } + /** + * @param ResolverInterface $resolver + * @param ResolverMiddlewareInterface[] $middleware + * @return array + */ + protected function getMiddlewareToApply(ResolverInterface $resolver, array $middleware): array + { + $resolverMiddleware = $resolver->getMiddleware(); + + if (null === $resolverMiddleware) { + return $middleware; + } + + return \array_filter($middleware, function (ResolverMiddlewareInterface $mw) use ($resolverMiddleware) { + return \in_array(\get_class($mw), $resolverMiddleware, true); + }); + } + /** * @param callable $resolveCallback * @param array $middleware diff --git a/tests/Unit/Schema/Resolver/ResolverRegistryTest.php b/tests/Unit/Schema/Resolver/ResolverRegistryTest.php index 696e42af..c06a921b 100644 --- a/tests/Unit/Schema/Resolver/ResolverRegistryTest.php +++ b/tests/Unit/Schema/Resolver/ResolverRegistryTest.php @@ -3,8 +3,8 @@ namespace Digia\GraphQL\Test\Unit\Schema\Resolver; use Digia\GraphQL\Execution\ResolveInfo; -use Digia\GraphQL\Schema\Resolver\AbstractResolver; use Digia\GraphQL\Schema\Resolver\AbstractObjectResolver; +use Digia\GraphQL\Schema\Resolver\AbstractResolver; use Digia\GraphQL\Schema\Resolver\AbstractResolverMiddleware; use Digia\GraphQL\Schema\Resolver\ResolverCollection; use Digia\GraphQL\Schema\Resolver\ResolverMiddlewareInterface; @@ -119,8 +119,9 @@ public function testMiddleware() new LogResultMiddleware($logCallback) ]); - $registry->getFieldResolver('Query', 'hello')(null, ['name' => 'Bob']); + $result = $registry->getFieldResolver('Query', 'hello')(null, ['name' => 'Bob']); + $this->assertEquals('Hello Bob!', $result); $this->assertEquals([ '1. logInput {"name":"Bob"}', '2. logResult', @@ -129,6 +130,32 @@ public function testMiddleware() '5. logInput', ], $messages); } + + public function testResolverWithSpecificMiddleware() + { + $messages = []; + + $logCallback = function (string $message) use (&$messages) { + $messages[] = $message; + }; + + $registry = new ResolverRegistry([ + 'Query' => [ + 'hello' => new HelloResolverWithSpecificMiddleware($logCallback), + ], + ], [ + new LogInputMiddleware($logCallback), + new LogResultMiddleware($logCallback) + ]); + + $registry->getFieldResolver('Query', 'hello')(null, ['name' => 'Bob']); + + $this->assertEquals([ + '1. logInput {"name":"Bob"}', + '3. resolver: hello', + '5. logInput', + ], $messages); + } } abstract class LogMiddleware implements ResolverMiddlewareInterface @@ -205,3 +232,13 @@ public function resolve($rootValue, array $arguments, $context = null, ?ResolveI return \sprintf('Hello %s!', $arguments['name'] ?? 'world'); } } + +class HelloResolverWithSpecificMiddleware extends HelloResolver +{ + public function getMiddleware(): ?array + { + return [ + LogInputMiddleware::class, + ]; + } +}