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

Passed
Pull Request — master (#264)
by Jérémiah
16:33
created

ErrorHandler::createErrorFormatter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Overblog\GraphQLBundle\Error;
4
5
use GraphQL\Error\ClientAware;
6
use GraphQL\Error\Debug;
7
use GraphQL\Error\Error as GraphQLError;
8
use GraphQL\Error\FormattedError;
9
use GraphQL\Error\UserError as GraphQLUserError;
10
use GraphQL\Executor\ExecutionResult;
11
use Overblog\GraphQLBundle\Event\ErrorFormattingEvent;
12
use Overblog\GraphQLBundle\Event\Events;
13
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
14
15
class ErrorHandler
16
{
17
    const DEFAULT_ERROR_MESSAGE = 'Internal server Error';
18
    const DEFAULT_USER_WARNING_CLASS = UserWarning::class;
19
    const DEFAULT_USER_ERROR_CLASS = UserError::class;
20
21
    /** @var EventDispatcherInterface */
22
    private $dispatcher;
23
24
    /** @var string */
25
    private $internalErrorMessage;
26
27
    /** @var array */
28
    private $exceptionMap;
29
30
    /** @var string */
31
    private $userWarningClass = self::DEFAULT_USER_WARNING_CLASS;
32
33
    /** @var string */
34
    private $userErrorClass = self::DEFAULT_USER_ERROR_CLASS;
35
36
    /** @var bool */
37
    private $mapExceptionsToParent;
38
39 74
    public function __construct(
40
        EventDispatcherInterface $dispatcher,
41
        $internalErrorMessage = null,
42
        array $exceptionMap = [],
43
        $mapExceptionsToParent = false
44
    ) {
45 74
        $this->dispatcher = $dispatcher;
46 74
        if (empty($internalErrorMessage)) {
47 15
            $internalErrorMessage = self::DEFAULT_ERROR_MESSAGE;
48
        }
49 74
        $this->internalErrorMessage = $internalErrorMessage;
50 74
        $this->exceptionMap = $exceptionMap;
51 74
        $this->mapExceptionsToParent = $mapExceptionsToParent;
52 74
    }
53
54 59
    public function setUserWarningClass($userWarningClass)
55
    {
56 59
        $this->userWarningClass = $userWarningClass;
57
58 59
        return $this;
59
    }
60
61 59
    public function setUserErrorClass($userErrorClass)
62
    {
63 59
        $this->userErrorClass = $userErrorClass;
64
65 59
        return $this;
66
    }
67
68 73
    public function handleErrors(ExecutionResult $executionResult, $throwRawException = false, $debug = false)
69
    {
70 73
        $errorFormatter = $this->createErrorFormatter($debug);
71 73
        $executionResult->setErrorFormatter($errorFormatter);
72 73
        $exceptions = $this->treatExceptions($executionResult->errors, $throwRawException);
73 70
        $executionResult->errors = $exceptions['errors'];
74 70
        if (!empty($exceptions['extensions']['warnings'])) {
75 7
            $executionResult->extensions['warnings'] = array_map($errorFormatter, $exceptions['extensions']['warnings']);
76
        }
77 70
    }
78
79 73
    private function createErrorFormatter($debug = false)
80
    {
81 73
        $debugMode = false;
82 73
        if ($debug) {
83 1
            $debugMode = Debug::INCLUDE_TRACE | Debug::INCLUDE_DEBUG_MESSAGE;
84
        }
85
86 73
        return function (GraphQLError $error) use ($debugMode) {
87 23
            $event = new ErrorFormattingEvent($error, FormattedError::createFromException($error, $debugMode, $this->internalErrorMessage));
0 ignored issues
show
Documentation introduced by
$error is of type object<GraphQL\Error\Error>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
88 23
            $this->dispatcher->dispatch(Events::ERROR_FORMATTING, $event);
89
90 23
            return $event->getFormattedError()->getArrayCopy();
91 73
        };
92
    }
93
94
    /**
95
     * @param GraphQLError[] $errors
96
     * @param bool           $throwRawException
97
     *
98
     * @return array
99
     *
100
     * @throws \Error|\Exception
101
     */
102 73
    private function treatExceptions(array $errors, $throwRawException)
103
    {
104
        $treatedExceptions = [
105 73
            'errors' => [],
106
            'extensions' => [
107
                'warnings' => [],
108
            ],
109
        ];
110
111
        /** @var GraphQLError $error */
112 73
        foreach ($this->flattenErrors($errors) as $error) {
113 26
            $rawException = $this->convertException($error->getPrevious());
114
115
            // raw GraphQL Error or InvariantViolation exception
116 26
            if (null === $rawException || $rawException instanceof GraphQLUserError) {
117 9
                $treatedExceptions['errors'][] = $error;
118 9
                continue;
119
            }
120
121
            // recreate a error with converted exception
122 18
            $errorWithConvertedException = new GraphQLError(
123 18
                $error->getMessage(),
124 18
                $error->nodes,
125 18
                $error->getSource(),
126 18
                $error->getPositions(),
127 18
                $error->path,
128 18
                $rawException
129
            );
130
131
            // user error
132 18
            if ($rawException instanceof $this->userErrorClass) {
133 8
                $treatedExceptions['errors'][] = $errorWithConvertedException;
134 8
                continue;
135
            }
136
137
            // user warning
138 11
            if ($rawException instanceof $this->userWarningClass) {
139 7
                $treatedExceptions['extensions']['warnings'][] = $errorWithConvertedException;
140 7
                continue;
141
            }
142
143
            // if is a catch exception wrapped in Error
144 5
            if ($throwRawException) {
145 3
                throw $rawException;
146
            }
147
148 2
            $treatedExceptions['errors'][] = $errorWithConvertedException;
149
        }
150
151 70
        return $treatedExceptions;
152
    }
153
154
    /**
155
     * @param GraphQLError[] $errors
156
     *
157
     * @return GraphQLError[]
158
     */
159 73
    private function flattenErrors(array $errors)
160
    {
161 73
        $flattenErrors = [];
162
163 73
        foreach ($errors as $error) {
164 26
            $rawException = $error->getPrevious();
165
            // multiple errors
166 26
            if ($rawException instanceof UserErrors) {
167 1
                $rawExceptions = $rawException;
168 1
                foreach ($rawExceptions->getErrors() as $rawException) {
169 1
                    $flattenErrors[] = GraphQLError::createLocatedError($rawException, $error->nodes, $error->path);
170
                }
171
            } else {
172 26
                $flattenErrors[] = $error;
173
            }
174
        }
175
176 73
        return $flattenErrors;
177
    }
178
179
    /**
180
     * Tries to convert a raw exception into a user warning or error
181
     * that is displayed to the user.
182
     *
183
     * @param \Exception|\Error $rawException
184
     *
185
     * @return \Exception|\Error
186
     */
187 26
    private function convertException($rawException = null)
188
    {
189 26
        if (null === $rawException || $rawException instanceof ClientAware) {
190 14
            return $rawException;
191
        }
192
193 13
        $errorClass = $this->findErrorClass($rawException);
194 13
        if (null !== $errorClass) {
195 8
            return new $errorClass($rawException->getMessage(), $rawException->getCode(), $rawException);
196
        }
197
198 5
        return $rawException;
199
    }
200
201
    /**
202
     * @param \Exception|\Error $rawException
203
     *
204
     * @return string|null
205
     */
206 13
    private function findErrorClass($rawException)
207
    {
208 13
        $rawExceptionClass = get_class($rawException);
209 13
        if (isset($this->exceptionMap[$rawExceptionClass])) {
210 7
            return $this->exceptionMap[$rawExceptionClass];
211
        }
212
213 6
        if ($this->mapExceptionsToParent) {
214 2
            return $this->findErrorClassUsingParentException($rawException);
215
        }
216
217 4
        return null;
218
    }
219
220
    /**
221
     * @param \Exception|\Error $rawException
222
     *
223
     * @return string|null
224
     */
225 2
    private function findErrorClassUsingParentException($rawException)
226
    {
227 2
        foreach ($this->exceptionMap as $rawExceptionClass => $errorClass) {
228 1
            if ($rawException instanceof $rawExceptionClass) {
229 1
                return $errorClass;
230
            }
231
        }
232
233 1
        return null;
234
    }
235
}
236