Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
Refactor error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
crisu83 committed Nov 9, 2018
1 parent 9ee27bd commit 13adcc8
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 66 deletions.
27 changes: 27 additions & 0 deletions src/Error/Handler/AbstractErrorMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Digia\GraphQL\Error\Handler;

use Digia\GraphQL\Execution\ExecutionContext;
use Digia\GraphQL\Execution\ExecutionException;

abstract class AbstractErrorMiddleware implements ErrorMiddlewareInterface
{
/**
* @param \Throwable $exception
* @param callable $next
* @return mixed
*/
public function handleError(\Throwable $exception, callable $next)
{
}

/**
* @param ExecutionException $exception
* @param ExecutionContext $context
* @return mixed
*/
public function handleExecutionError(ExecutionException $exception, ExecutionContext $context, callable $next)
{
}
}
19 changes: 0 additions & 19 deletions src/Error/Handler/AddErrorMiddleware.php

This file was deleted.

31 changes: 31 additions & 0 deletions src/Error/Handler/CallableMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Digia\GraphQL\Error\Handler;

use Digia\GraphQL\Execution\ExecutionContext;
use Digia\GraphQL\Execution\ExecutionException;

class CallableMiddleware extends AbstractErrorMiddleware
{
/**
* @var callable
*/
protected $handleCallback;

/**
* CallableMiddleware constructor.
* @param callable $handleCallback
*/
public function __construct(callable $handleCallback)
{
$this->handleCallback = $handleCallback;
}

/**
* @inheritdoc
*/
public function handleExecutionError(ExecutionException $exception, ExecutionContext $context, callable $next)
{
return \call_user_func($this->handleCallback, $exception, $context, $next);
}
}
31 changes: 24 additions & 7 deletions src/Error/Handler/ErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ErrorHandler implements ErrorHandlerInterface
/**
* @var ErrorMiddlewareInterface[]
*/
protected $middleware;
protected $middleware = [];

/**
* ErrorHandler constructor.
Expand All @@ -23,19 +23,36 @@ public function __construct(array $middleware)
}
}

/**
* @param \Throwable $exception
*/
public function handleError(\Throwable $exception)
{
$next = function () {
// NO-OP
};

foreach ($this->middleware as $middleware) {
$next = function (\Throwable $exception) use ($middleware, $next) {
return $middleware->handleError($exception, $next);
};
}

\call_user_func($next, $exception);
}

/**
* @inheritdoc
*/
public function handle(ExecutionException $exception, ExecutionContext $context)
public function handleExecutionError(ExecutionException $exception, ExecutionContext $context)
{
$next = function () {
// NO-OP
};

foreach (\array_reverse($this->middleware) as $mw) {
/** @var ErrorMiddlewareInterface $mw */
$next = function (ExecutionException $exception, ExecutionContext $context) use ($mw, $next) {
return $mw->handle($exception, $context, $next);
foreach ($this->middleware as $middleware) {
$next = function (ExecutionException $exception, ?ExecutionContext $context) use ($middleware, $next) {
return $middleware->handleExecutionError($exception, $context, $next);
};
}

Expand All @@ -47,6 +64,6 @@ public function handle(ExecutionException $exception, ExecutionContext $context)
*/
protected function addMiddleware(ErrorMiddlewareInterface $middleware)
{
$this->middleware[] = $middleware;
\array_unshift($this->middleware, $middleware);
}
}
11 changes: 8 additions & 3 deletions src/Error/Handler/ErrorHandlerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
interface ErrorHandlerInterface
{
/**
* @param ExecutionException $exception
* @param ExecutionContext $context
* @param \Throwable $exception
*/
public function handle(ExecutionException $exception, ExecutionContext $context);
public function handleError(\Throwable $exception);

/**
* @param ExecutionException $exception
* @param ExecutionContext $context
*/
public function handleExecutionError(ExecutionException $exception, ExecutionContext $context);
}
9 changes: 8 additions & 1 deletion src/Error/Handler/ErrorMiddlewareInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@

interface ErrorMiddlewareInterface
{
/**
* @param \Throwable $exception
* @param callable $next
* @return mixed
*/
public function handleError(\Throwable $exception, callable $next);

/**
* @param ExecutionException $exception
* @param ExecutionContext $context
* @return mixed
*/
public function handle(ExecutionException $exception, ExecutionContext $context, callable $next);
public function handleExecutionError(ExecutionException $exception, ExecutionContext $context, callable $next);
}
8 changes: 3 additions & 5 deletions src/Execution/Execution.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ public function execute(
});
}

if (null !== $errorHandler) {
if ($errorHandler instanceof ErrorHandlerInterface) {
foreach ($context->getErrors() as $error) {
$errorHandler->handleError($error);
$errorHandler->handleExecutionError($error, $context);
}
}

Expand All @@ -72,15 +72,13 @@ public function execute(
* @param ExecutionContext $context
* @param FieldCollector $fieldCollector
* @param ValuesResolver $valuesResolver
* @param ErrorHandlerInterface|null $errorHandler
* @return array|mixed|null|PromiseInterface
*/
protected function executeOperation(
?string $operationName,
ExecutionContext $context,
FieldCollector $fieldCollector,
ValuesResolver $valuesResolver,
?ErrorHandlerInterface $errorHandler = null
ValuesResolver $valuesResolver
) {
$strategy = $operationName === 'mutation'
? new SerialExecutionStrategy($context, $fieldCollector, $valuesResolver)
Expand Down
78 changes: 77 additions & 1 deletion src/GraphQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

namespace Digia\GraphQL;

use Digia\GraphQL\Error\Handler\CallableMiddleware;
use Digia\GraphQL\Error\Handler\ErrorHandler;
use Digia\GraphQL\Error\Handler\ErrorHandlerInterface;
use Digia\GraphQL\Error\InvariantException;
use Digia\GraphQL\Execution\ExecutionInterface;
use Digia\GraphQL\Execution\ExecutionProvider;
use Digia\GraphQL\Execution\ExecutionResult;
Expand All @@ -14,6 +17,7 @@
use Digia\GraphQL\Language\NodePrinterInterface;
use Digia\GraphQL\Language\ParserInterface;
use Digia\GraphQL\Language\Source;
use Digia\GraphQL\Language\SyntaxErrorException;
use Digia\GraphQL\Schema\Building\SchemaBuilderInterface;
use Digia\GraphQL\Schema\Building\SchemaBuildingProvider;
use Digia\GraphQL\Schema\Extension\SchemaExtenderInterface;
Expand Down Expand Up @@ -248,7 +252,7 @@ public static function execute(
array $variableValues = [],
$operationName = null,
callable $fieldResolver = null,
$errorHandler = null
?ErrorHandlerInterface $errorHandler = null
): ExecutionResult {
/** @var ExecutionInterface $execution */
$execution = static::make(ExecutionInterface::class);
Expand All @@ -265,6 +269,78 @@ public static function execute(
);
}

/**
* @param Schema $schema
* @param string $source
* @param null $rootValue
* @param null $contextValue
* @param array $variableValues
* @param null|string $operationName
* @param callable|null $fieldResolver
* @param ErrorHandlerInterface|null $errorHandler
* @return ExecutionResult
* @throws InvariantException
* @throws SyntaxErrorException
*/
public static function process(
Schema $schema,
string $source,
$rootValue = null,
$contextValue = null,
array $variableValues = [],
?string $operationName = null,
?callable $fieldResolver = null,
?ErrorHandlerInterface $errorHandler = null
): ExecutionResult
{
$schemaValidationErrors = validateSchema($schema);

if (!empty($schemaValidationErrors)) {
if (null !== $errorHandler) {
foreach ($schemaValidationErrors as $schemaValidationError) {
$errorHandler->handleError($schemaValidationError);
}
}

return (new ExecutionResult(null, $schemaValidationErrors));
}

try {
$document = parse($source);
} catch (SyntaxErrorException $error) {
if (null !== $errorHandler) {
$errorHandler->handleError($error);
}

return (new ExecutionResult(null, [$error]));
}

$validationErrors = validate($schema, $document);

if (!empty($validationErrors)) {
if (null !== $errorHandler) {
foreach ($validationErrors as $validationError) {
$errorHandler->handleError($validationError);
}
}

return (new ExecutionResult(null, $validationErrors));
}

$result = execute(
$schema,
$document,
$rootValue,
$contextValue,
$variableValues,
$operationName,
$fieldResolver,
$errorHandler
);

return $result;
}

/**
* @param NodeInterface $node
* @return string
Expand Down
29 changes: 10 additions & 19 deletions src/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Digia\GraphQL;

use Digia\GraphQL\Error\Handler\CallableMiddleware;
use Digia\GraphQL\Error\Handler\ErrorHandler;
use Digia\GraphQL\Error\Handler\ErrorHandlerInterface;
use Digia\GraphQL\Error\InvariantException;
use Digia\GraphQL\Execution\ExecutionResult;
Expand Down Expand Up @@ -165,41 +167,30 @@ function printNode(NodeInterface $node): string
* @param mixed|null $rootValue
* @param mixed|null $contextValue
* @param array $variableValues
* @param mixed|null $operationName
* @param string|null $operationName
* @param callable|null $fieldResolver
* @param ErrorHandlerInterface|callable|null $errorHandler
* @return array
* @throws InvariantException
* @throws SyntaxErrorException
*/
function graphql(
Schema $schema,
string $source,
$rootValue = null,
$contextValue = null,
array $variableValues = [],
$operationName = null,
callable $fieldResolver = null,
?string $operationName = null,
?callable $fieldResolver = null,
$errorHandler = null
): array {
$schemaValidationErrors = validateSchema($schema);
if (!empty($schemaValidationErrors)) {
return (new ExecutionResult([], $schemaValidationErrors))->toArray();
if (\is_callable($errorHandler)) {
$errorHandler = new ErrorHandler([new CallableMiddleware($errorHandler)]);
}

try {
$document = parse($source);
} catch (SyntaxErrorException $error) {
return (new ExecutionResult([], [$error]))->toArray();
}

$validationErrors = validate($schema, $document);
if (!empty($validationErrors)) {
return (new ExecutionResult([], $validationErrors))->toArray();
}

$result = execute(
$result = GraphQL::process(
$schema,
$document,
$source,
$rootValue,
$contextValue,
$variableValues,
Expand Down
Loading

0 comments on commit 13adcc8

Please sign in to comment.