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 (#264)
by Jérémiah
22:49
created

ErrorHandler::setUserErrorClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 1
cts 1
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
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 85
    /** @var bool */
37
    private $mapExceptionsToParent;
38
39
    public function __construct(
40
        EventDispatcherInterface $dispatcher,
41
        $internalErrorMessage = null,
42 85
        array $exceptionMap = [],
43 85
        $mapExceptionsToParent = false
44 78
    ) {
45
        $this->dispatcher = $dispatcher;
46 85
        if (empty($internalErrorMessage)) {
47 85
            $internalErrorMessage = self::DEFAULT_ERROR_MESSAGE;
48 85
        }
49 85
        $this->internalErrorMessage = $internalErrorMessage;
50
        $this->exceptionMap = $exceptionMap;
51 71
        $this->mapExceptionsToParent = $mapExceptionsToParent;
52
    }
53 71
54
    public function setUserWarningClass($userWarningClass)
55 71
    {
56
        $this->userWarningClass = $userWarningClass;
57
58 71
        return $this;
59
    }
60 71
61
    public function setUserErrorClass($userErrorClass)
62 71
    {
63
        $this->userErrorClass = $userErrorClass;
64
65
        return $this;
66
    }
67
68
    public function handleErrors(ExecutionResult $executionResult, $throwRawException = false, $debug = false)
69
    {
70
        $errorFormatter = $this->createErrorFormatter($debug);
71
        $executionResult->setErrorFormatter($errorFormatter);
72
        $exceptions = $this->treatExceptions($executionResult->errors, $throwRawException);
73 70
        $executionResult->errors = $exceptions['errors'];
74
        if (!empty($exceptions['extensions']['warnings'])) {
75
            $executionResult->extensions['warnings'] = array_map($errorFormatter, $exceptions['extensions']['warnings']);
76 70
        }
77
    }
78
79
    private function createErrorFormatter($debug = false)
80
    {
81
        $debugMode = false;
82
        if ($debug) {
83 70
            $debugMode = Debug::INCLUDE_TRACE | Debug::INCLUDE_DEBUG_MESSAGE;
84 25
        }
85
86
        return function (GraphQLError $error) use ($debugMode) {
87 25
            $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 9
            $this->dispatcher->dispatch(Events::ERROR_FORMATTING, $event);
89 9
90
            return $event->getFormattedError()->getArrayCopy();
91
        };
92
    }
93 17
94 8
    /**
95 8
     * @param GraphQLError[] $errors
96 5
     * @param bool           $throwRawException
97
     *
98 8
     * @return array
99
     *
100
     * @throws \Error|\Exception
101
     */
102 10
    private function treatExceptions(array $errors, $throwRawException)
103 7
    {
104 7
        $treatedExceptions = [
105 3
            'errors' => [],
106
            'extensions' => [
107 7
                'warnings' => [],
108
            ],
109
        ];
110
111 4
        /** @var GraphQLError $error */
112 1
        foreach ($this->flattenErrors($errors) as $error) {
113 1
            $rawException = $this->convertException($error->getPrevious());
114 1
115
            // raw GraphQL Error or InvariantViolation exception
116 1
            if (null === $rawException || $rawException instanceof GraphQLUserError) {
117
                $treatedExceptions['errors'][] = $error;
118
                continue;
119
            }
120 4
121 3
            // recreate a error with converted exception
122
            $errorWithConvertedException = new GraphQLError(
123
                $error->getMessage(),
124 1
                $error->nodes,
125
                $error->getSource(),
126 1
                $error->getPositions(),
127 1
                $error->path,
128 1
                $rawException
129 1
            );
130 1
131 1
            // user error
132 1
            if ($rawException instanceof $this->userErrorClass) {
133
                $treatedExceptions['errors'][] = $errorWithConvertedException;
134
                continue;
135
            }
136 67
137
            // user warning
138
            if ($rawException instanceof $this->userWarningClass) {
139
                $treatedExceptions['extensions']['warnings'][] = $errorWithConvertedException;
140
                continue;
141
            }
142
143 9
            // if is a catch exception wrapped in Error
144
            if ($throwRawException) {
145 9
                throw $rawException;
146 9
            }
147 9
148 9
            $treatedExceptions['errors'][] = $errorWithConvertedException;
149 9
        }
150 9
151 9
        return $treatedExceptions;
152
    }
153
154 9
    /**
155 9
     * @param GraphQLError[] $errors
156
     *
157 70
     * @return GraphQLError[]
158
     */
159 70
    private function flattenErrors(array $errors)
160 70
    {
161 67
        $flattenErrors = [];
162 67
163 7
        foreach ($errors as $error) {
164
            $rawException = $error->getPrevious();
165 67
            // multiple errors
166
            if ($rawException instanceof UserErrors) {
167
                $rawExceptions = $rawException;
168
                foreach ($rawExceptions->getErrors() as $rawException) {
169
                    $flattenErrors[] = GraphQLError::createLocatedError($rawException, $error->nodes, $error->path);
170
                }
171
            } else {
172
                $flattenErrors[] = $error;
173
            }
174
        }
175 25
176
        return $flattenErrors;
177 25
    }
178 9
179
    /**
180
     * Tries to convert a raw exception into a user warning or error
181 17
     * that is displayed to the user.
182 17
     *
183 8
     * @param \Exception|\Error $rawException
184
     *
185
     * @return \Exception|\Error
186 9
     */
187
    private function convertException($rawException = null)
188
    {
189
        if (null === $rawException || $rawException instanceof ClientAware) {
190
            return $rawException;
191
        }
192
193
        $errorClass = $this->findErrorClass($rawException);
194 17
        if (null !== $errorClass) {
195
            return new $errorClass($rawException->getMessage(), $rawException->getCode(), $rawException);
196 17
        }
197 17
198 7
        return $rawException;
199
    }
200
201 10
    /**
202 2
     * @param \Exception|\Error $rawException
203
     *
204
     * @return string|null
205 8
     */
206
    private function findErrorClass($rawException)
207
    {
208
        $rawExceptionClass = get_class($rawException);
209
        if (isset($this->exceptionMap[$rawExceptionClass])) {
210
            return $this->exceptionMap[$rawExceptionClass];
211
        }
212
213 2
        if ($this->mapExceptionsToParent) {
214
            return $this->findErrorClassUsingParentException($rawException);
215 2
        }
216 1
217 1
        return null;
218
    }
219
220
    /**
221 1
     * @param \Exception|\Error $rawException
222
     *
223
     * @return string|null
224
     */
225
    private function findErrorClassUsingParentException($rawException)
226
    {
227
        foreach ($this->exceptionMap as $rawExceptionClass => $errorClass) {
228
            if ($rawException instanceof $rawExceptionClass) {
229
                return $errorClass;
230
            }
231
        }
232
233
        return null;
234
    }
235
}
236