Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#586)
by Stefano
20:55
created

ErrorHandler::convertException()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 4
nc 3
nop 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\Error;
6
7
use GraphQL\Error\Debug;
8
use GraphQL\Error\Error as GraphQLError;
9
use GraphQL\Error\FormattedError;
10
use GraphQL\Error\UserError as GraphQLUserError;
11
use GraphQL\Executor\ExecutionResult;
12
use Overblog\GraphQLBundle\Event\ErrorFormattingEvent;
13
use Overblog\GraphQLBundle\Event\Events;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
16
class ErrorHandler
17
{
18
    public const DEFAULT_ERROR_MESSAGE = 'Internal server Error';
19
20
    /** @var EventDispatcherInterface */
21
    private $dispatcher;
22
23
    /** @var ExceptionConverterInterface */
24
    private $exceptionConverter;
25
26
    /** @var string */
27
    private $internalErrorMessage;
28
29 112
    public function __construct(
30
        EventDispatcherInterface $dispatcher,
31
        ExceptionConverterInterface $exceptionConverter,
32
        string $internalErrorMessage = self::DEFAULT_ERROR_MESSAGE
33
    ) {
34 112
        $this->dispatcher = $dispatcher;
35 112
        $this->exceptionConverter = $exceptionConverter;
36 112
        $this->internalErrorMessage = $internalErrorMessage;
37 112
    }
38
39 111
    public function handleErrors(ExecutionResult $executionResult, bool $throwRawException = false, bool $debug = false): void
40
    {
41 111
        $errorFormatter = $this->createErrorFormatter($debug);
42
43 111
        $executionResult->setErrorFormatter($errorFormatter);
44
45 111
        $exceptions = $this->treatExceptions($executionResult->errors, $throwRawException);
46 107
        $executionResult->errors = $exceptions['errors'];
47
48 107
        if (!empty($exceptions['extensions']['warnings'])) {
49 11
            $executionResult->extensions['warnings'] = \array_map($errorFormatter, $exceptions['extensions']['warnings']);
50
        }
51 107
    }
52
53 111
    private function createErrorFormatter(bool $debug): \Closure
54
    {
55 111
        $debugMode = false;
56
57 111
        if ($debug) {
58 2
            $debugMode = Debug::INCLUDE_TRACE | Debug::INCLUDE_DEBUG_MESSAGE;
59
        }
60
61
        return function (GraphQLError $error) use ($debugMode): array {
62 37
            $event = new ErrorFormattingEvent($error, FormattedError::createFromException($error, $debugMode, $this->internalErrorMessage));
63
64 37
            $this->dispatcher->dispatch($event, Events::ERROR_FORMATTING);
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with Overblog\GraphQLBundle\E...vents::ERROR_FORMATTING. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

64
            $this->dispatcher->/** @scrutinizer ignore-call */ 
65
                               dispatch($event, Events::ERROR_FORMATTING);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
65
66 37
            return $event->getFormattedError()->getArrayCopy();
67 111
        };
68
    }
69
70
    /**
71
     * @param GraphQLError[] $errors
72
     * @param bool           $throwRawException
73
     *
74
     * @return array
75
     *
76
     * @throws \Error|\Exception
77
     */
78 111
    private function treatExceptions(array $errors, bool $throwRawException): array
79
    {
80
        $treatedExceptions = [
81 111
            'errors' => [],
82
            'extensions' => [
83
                'warnings' => [],
84
            ],
85
        ];
86
87
        /** @var GraphQLError $error */
88 111
        foreach ($this->flattenErrors($errors) as $error) {
89 41
            $rawException = $error->getPrevious();
90
91 41
            if (null !== $rawException) {
92 31
                $rawException = $this->exceptionConverter->convertException($error->getPrevious());
93
            }
94
95
            // raw GraphQL Error or InvariantViolation exception
96 41
            if (null === $rawException) {
97 11
                $treatedExceptions['errors'][] = $error;
98
99 11
                continue;
100
            }
101
102
            // recreate a error with converted exception
103 31
            $errorWithConvertedException = new GraphQLError(
104 31
                $error->getMessage(),
105 31
                $error->nodes,
106 31
                $error->getSource(),
107 31
                $error->getPositions(),
108 31
                $error->path,
109 31
                $rawException
110
            );
111
112
            // user error
113 31
            if ($rawException instanceof GraphQLUserError) {
114 8
                $treatedExceptions['errors'][] = $errorWithConvertedException;
115
116 8
                continue;
117
            }
118
119
            // user warning
120 24
            if ($rawException instanceof UserWarning) {
121 11
                $treatedExceptions['extensions']['warnings'][] = $errorWithConvertedException;
122
123 11
                continue;
124
            }
125
126
            // if is a catch exception wrapped in Error
127 14
            if ($throwRawException) {
128 4
                throw $rawException;
129
            }
130
131 10
            $treatedExceptions['errors'][] = $errorWithConvertedException;
132
        }
133
134 107
        return $treatedExceptions;
135
    }
136
137
    /**
138
     * @param GraphQLError[] $errors
139
     *
140
     * @return GraphQLError[]
141
     */
142 111
    private function flattenErrors(array $errors): array
143
    {
144 111
        $flattenErrors = [];
145
146 111
        foreach ($errors as $error) {
147 41
            $rawException = $error->getPrevious();
148
149
            // multiple errors
150 41
            if ($rawException instanceof UserErrors) {
151 1
                $rawExceptions = $rawException;
152
153 1
                foreach ($rawExceptions->getErrors() as $rawException) {
154 1
                    $flattenErrors[] = GraphQLError::createLocatedError($rawException, $error->nodes, $error->path);
155
                }
156
            } else {
157 41
                $flattenErrors[] = $error;
158
            }
159
        }
160
161 111
        return $flattenErrors;
162
    }
163
}
164