GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ExceptionListener::onKernelException()   C
last analyzed

Complexity

Conditions 10
Paths 17

Size

Total Lines 49
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 10.0629

Importance

Changes 0
Metric Value
dl 0
loc 49
rs 5.5471
c 0
b 0
f 0
ccs 32
cts 35
cp 0.9143
cc 10
eloc 26
nc 17
nop 1
crap 10.0629

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace M6Web\Bundle\ApiExceptionBundle\EventListener;
4
5
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
6
use Symfony\Component\HttpFoundation\JsonResponse;
7
use Symfony\Component\HttpKernel\Kernel;
8
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface as SymfonyHttpExceptionInterface;
9
use M6Web\Bundle\ApiExceptionBundle\Manager\ExceptionManager;
10
use M6Web\Bundle\ApiExceptionBundle\Exception\Interfaces\ExceptionInterface;
11
use M6Web\Bundle\ApiExceptionBundle\Exception\Interfaces\HttpExceptionInterface;
12
use M6Web\Bundle\ApiExceptionBundle\Exception\Interfaces\FlattenErrorExceptionInterface;
13
14
/**
15
 * Class ExceptionListener
16
 */
17
class ExceptionListener
18
{
19
    /**
20
     * @var boolean
21
     */
22
    protected $stackTrace;
23
24
    /**
25
     * @var array
26
     */
27
    protected $default;
28
29
    /**
30
     * @var Kernel
31
     */
32
    protected $kernel;
33
34
    /**
35
     * @var ExceptionManager
36
     */
37
    protected $exceptionManager;
38
39
    /**
40
     * @var boolean
41
     */
42
    protected $matchAll;
43
44
    /**
45
     * Constructor
46
     *
47
     * @param Kernel           $kernel
48
     * @param ExceptionManager $exceptionManager
49
     * @param boolean          $matchAll
50
     * @param array            $default
51
     * @param boolean          $stackTrace
52
     */
53
    public function __construct(
54
        Kernel $kernel,
55
        ExceptionManager $exceptionManager,
56
        $matchAll,
57
        array $default,
58
        $stackTrace = false
59
    ) {
60 1
        $this->kernel           = $kernel;
61 1
        $this->exceptionManager = $exceptionManager;
62 1
        $this->matchAll         = $matchAll;
63 1
        $this->default          = $default;
64 1
        $this->stackTrace       = $stackTrace;
65 1
    }
66
67
    /**
68
     * Format response exception
69
     *
70
     * @param GetResponseForExceptionEvent $event
71
     */
72
    public function onKernelException(GetResponseForExceptionEvent $event)
73
    {
74 1
        $exception = $event->getException();
75
76 1
        if (!($event->getRequest())
77 1
            || ($this->matchAll === false && !$this->isApiException($exception))
78 1
        ) {
79 1
            return;
80
        }
81 1
82 1
        $data = [];
83
84 1
        if ($this->isApiException($exception)) {
85 1
            $exception = $this->exceptionManager->configure($exception);
0 ignored issues
show
Documentation introduced by
$exception is of type object<Exception>, but the function expects a object<M6Web\Bundle\ApiE...ces\ExceptionInterface>.

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...
86 1
        }
87
88 1
        $statusCode = $this->getStatusCode($exception);
0 ignored issues
show
Bug introduced by
It seems like $exception defined by $this->exceptionManager->configure($exception) on line 85 can also be of type object<M6Web\Bundle\ApiE...ces\ExceptionInterface>; however, M6Web\Bundle\ApiExceptio...stener::getStatusCode() does only seem to accept object<Exception>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
89
90 1
        $data['error']['status']  = $statusCode;
91
92 1
        if ($code = $exception->getCode()) {
93 1
            $data['error']['code'] = $code;
94 1
        }
95
96 1
        $data['error']['message'] = $this->getMessage($exception);
0 ignored issues
show
Bug introduced by
It seems like $exception defined by $this->exceptionManager->configure($exception) on line 85 can also be of type object<M6Web\Bundle\ApiE...ces\ExceptionInterface>; however, M6Web\Bundle\ApiExceptio...nListener::getMessage() does only seem to accept object<Exception>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
97
98 1
        if ($this->isFlattenErrorException($exception)) {
0 ignored issues
show
Bug introduced by
It seems like $exception defined by $this->exceptionManager->configure($exception) on line 85 can also be of type object<M6Web\Bundle\ApiE...ces\ExceptionInterface>; however, M6Web\Bundle\ApiExceptio...FlattenErrorException() does only seem to accept object<Exception>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
99 1
            $data['error']['errors'] = $exception->getFlattenErrors();
100 1
        }
101
102 1
        if ($this->stackTrace) {
103 1
            $data['error']['stack_trace'] = $exception->getTrace();
0 ignored issues
show
Bug introduced by
The method getTrace does only exist in Exception, but not in M6Web\Bundle\ApiExceptio...aces\ExceptionInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
104
105
            // Clean stacktrace to avoid circular reference or invalid type
106 1
            array_walk_recursive(
107 1
                $data['error']['stack_trace'],
108 1
                function(&$item) {
109 1
                    if (is_object($item)) {
110
                        $item = get_class($item);
111 1
                    } elseif (is_resource($item)) {
112
                        $item = get_resource_type($item);
113
                    }
114 1
                }
115 1
            );
116 1
        }
117
118 1
        $response = new JsonResponse($data, $statusCode, $this->getHeaders($exception));
0 ignored issues
show
Bug introduced by
It seems like $exception defined by $this->exceptionManager->configure($exception) on line 85 can also be of type object<M6Web\Bundle\ApiE...ces\ExceptionInterface>; however, M6Web\Bundle\ApiExceptio...nListener::getHeaders() does only seem to accept object<Exception>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
119 1
        $event->setResponse($response);
120 1
    }
121
122
    /**
123
     * Get exception status code
124
     *
125
     * @param \Exception $exception
126
     *
127
     * @return integer
128
     */
129
    private function getStatusCode(\Exception $exception)
130
    {
131 1
        $statusCode = $this->default['status'];
132
133
        if ($exception instanceof SymfonyHttpExceptionInterface
134 1
            || $exception instanceof HttpExceptionInterface
135 1
        ) {
136 1
            $statusCode = $exception->getStatusCode();
137 1
        }
138
139 1
        return $statusCode;
140
    }
141
142
    /**
143
     * Get exception message
144
     *
145
     * @param \Exception $exception
146
     *
147
     * @return integer
148
     */
149
    private function getMessage(\Exception $exception)
150
    {
151 1
        $message = $exception->getMessage();
152
153 1
        if ($this->isApiException($exception)) {
154 1
            $message = $exception->getMessageWithVariables();
0 ignored issues
show
Bug introduced by
The method getMessageWithVariables() does not exist on Exception. Did you maybe mean getMessage()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
155 1
        }
156
157 1
        return $message;
158
    }
159
160
    /**
161
     * Get exception headers
162
     *
163
     * @param \Exception $exception
164
     *
165
     * @return array
166
     */
167 1
    private function getHeaders(\Exception $exception)
168
    {
169 1
        $headers = $this->default['headers'];
170
171
        if ($exception instanceof SymfonyHttpExceptionInterface
172 1
            || $exception instanceof HttpExceptionInterface
173 1
        ) {
174 1
            $headers = $exception->getHeaders();
175 1
        }
176
177 1
        return $headers;
178
    }
179
180
    /**
181
     * Is api exception
182
     *
183
     * @param \Exception $exception
184
     *
185
     * @return boolean
186
     */
187
    private function isApiException(\Exception $exception)
188
    {
189 1
        if ($exception instanceof ExceptionInterface) {
190 1
            return true;
191
        }
192
193 1
        return false;
194
    }
195
196
    /**
197
     * Is flatten error exception
198
     *
199
     * @param \Exception $exception
200
     *
201
     * @return boolean
202
     */
203
    private function isFlattenErrorException(\Exception $exception)
204
    {
205 1
        if ($exception instanceof FlattenErrorExceptionInterface) {
206 1
            return true;
207
        }
208
209 1
        return false;
210
    }
211
}
212