Kernel::gatherRouteMiddleware()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 8
ccs 0
cts 4
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace CodexShaper\WP\Http;
4
5
use CodexShaper\WP\Http\Events\RequestHandled;
6
use Illuminate\Contracts\Container\Container;
7
use Illuminate\Contracts\Debug\ExceptionHandler;
8
use Illuminate\Contracts\Http\Kernel as KernelContract;
9
use Illuminate\Routing\Pipeline;
10
use Illuminate\Routing\Router;
11
use Illuminate\Support\Facades\Facade;
12
use InvalidArgumentException;
13
use Throwable;
14
15
class Kernel implements KernelContract
16
{
17
    /**
18
     * The application implementation.
19
     *
20
     * @var \Illuminate\Contracts\Foundation\Application
21
     */
22
    protected $app;
23
24
    /**
25
     * The router instance.
26
     *
27
     * @var \Illuminate\Routing\Router
28
     */
29
    protected $router;
30
31
    /**
32
     * The bootstrap classes for the application.
33
     *
34
     * @var array
35
     */
36
    protected $bootstrappers = [];
37
38
    /**
39
     * The application's middleware stack.
40
     *
41
     * @var array
42
     */
43
    protected $middleware = [];
44
45
    /**
46
     * The application's route middleware groups.
47
     *
48
     * @var array
49
     */
50
    protected $middlewareGroups = [];
51
52
    /**
53
     * The application's route middleware.
54
     *
55
     * @var array
56
     */
57
    protected $routeMiddleware = [];
58
59
    /**
60
     * The priority-sorted list of middleware.
61
     *
62
     * Forces non-global middleware to always be in the given order.
63
     *
64
     * @var array
65
     */
66
    protected $middlewarePriority = [
67
        \Illuminate\Session\Middleware\StartSession::class,
68
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
69
        \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
70
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
71
        \Illuminate\Session\Middleware\AuthenticateSession::class,
72
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
73
        \Illuminate\Auth\Middleware\Authorize::class,
74
    ];
75
76
    /**
77
     * Create a new HTTP kernel instance.
78
     *
79
     * @param \Illuminate\Contracts\Foundation\Application $app
80
     * @param \Illuminate\Routing\Router                   $router
81
     *
82
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
83
     */
84
    public function __construct(Container $app, Router $router)
85
    {
86
        $this->app = $app;
0 ignored issues
show
Documentation Bug introduced by
$app is of type object<Illuminate\Contracts\Container\Container>, but the property $app was declared to be of type object<Illuminate\Contra...Foundation\Application>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
87
        $this->router = $router;
88
89
        $this->syncMiddlewareToRouter();
90
    }
91
92
    /**
93
     * Handle an incoming HTTP request.
94
     *
95
     * @param \Illuminate\Http\Request $request
96
     *
97
     * @return \Illuminate\Http\Response
98
     */
99
    public function handle($request)
100
    {
101
        try {
102
            $request->enableHttpMethodParameterOverride();
103
            $response = $this->sendRequestThroughRouter($request);
104
        } catch (Throwable $e) {
105
            throw new \Exception($e, 1);
106
            $this->reportException($e);
0 ignored issues
show
Unused Code introduced by
$this->reportException($e); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
107
108
            $response = $this->renderException($request, $e);
109
        }
110
111
        $this->app['events']->dispatch(
112
            new RequestHandled($request, $response)
113
        );
114
115
        return $response;
116
    }
117
118
    /**
119
     * Send the given request through the middleware / router.
120
     *
121
     * @param \Illuminate\Http\Request $request
122
     *
123
     * @return \Illuminate\Http\Response
124
     */
125
    protected function sendRequestThroughRouter($request)
126
    {
127
        $this->app->instance('request', $request);
128
129
        Facade::clearResolvedInstance('request');
130
131
        $this->bootstrap();
132
133
        return (new Pipeline($this->app))
134
                    ->send($request)
135
                    // ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
136
                    ->through($this->middleware)
137
                    ->then($this->dispatchToRouter());
138
    }
139
140
    /**
141
     * Bootstrap the application for HTTP requests.
142
     *
143
     * @return void
144
     */
145
    public function bootstrap()
146
    {
147
        // if (! $this->app->hasBeenBootstrapped()) {
148
        //     $this->app->bootstrapWith($this->bootstrappers());
149
        // }
150
    }
151
152
    /**
153
     * Get the route dispatcher callback.
154
     *
155
     * @return \Closure
156
     */
157
    protected function dispatchToRouter()
158
    {
159
        return function ($request) {
160
            $this->app->instance('request', $request);
161
162
            return $this->router->dispatch($request);
163
        };
164
    }
165
166
    /**
167
     * Call the terminate method on any terminable middleware.
168
     *
169
     * @param \Illuminate\Http\Request  $request
170
     * @param \Illuminate\Http\Response $response
171
     *
172
     * @return void
173
     */
174
    public function terminate($request, $response)
175
    {
176
        $this->terminateMiddleware($request, $response);
177
178
        $this->app->terminate();
179
    }
180
181
    /**
182
     * Call the terminate method on any terminable middleware.
183
     *
184
     * @param \Illuminate\Http\Request  $request
185
     * @param \Illuminate\Http\Response $response
186
     *
187
     * @return void
188
     */
189
    protected function terminateMiddleware($request, $response)
190
    {
191
        $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
192
            $this->gatherRouteMiddleware($request),
193
            $this->middleware
194
        );
195
196
        foreach ($middlewares as $middleware) {
197
            if (!is_string($middleware)) {
198
                continue;
199
            }
200
201
            [$name] = $this->parseMiddleware($middleware);
0 ignored issues
show
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
202
203
            $instance = $this->app->make($name);
204
205
            if (method_exists($instance, 'terminate')) {
206
                $instance->terminate($request, $response);
207
            }
208
        }
209
    }
210
211
    /**
212
     * Gather the route middleware for the given request.
213
     *
214
     * @param \Illuminate\Http\Request $request
215
     *
216
     * @return array
217
     */
218
    protected function gatherRouteMiddleware($request)
219
    {
220
        if ($route = $request->route()) {
221
            return $this->router->gatherRouteMiddleware($route);
0 ignored issues
show
Documentation introduced by
$route is of type object|string, but the function expects a object<Illuminate\Routing\Route>.

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...
222
        }
223
224
        return [];
225
    }
226
227
    /**
228
     * Parse a middleware string to get the name and parameters.
229
     *
230
     * @param string $middleware
231
     *
232
     * @return array
233
     */
234
    protected function parseMiddleware($middleware)
235
    {
236
        [$name, $parameters] = array_pad(explode(':', $middleware, 2), 2, []);
0 ignored issues
show
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $parameters seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
237
238
        if (is_string($parameters)) {
0 ignored issues
show
Bug introduced by
The variable $parameters seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
239
            $parameters = explode(',', $parameters);
0 ignored issues
show
Bug introduced by
The variable $parameters seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
240
        }
241
242
        return [$name, $parameters];
0 ignored issues
show
Bug introduced by
The variable $parameters does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
243
    }
244
245
    /**
246
     * Determine if the kernel has a given middleware.
247
     *
248
     * @param string $middleware
249
     *
250
     * @return bool
251
     */
252
    public function hasMiddleware($middleware)
253
    {
254
        return in_array($middleware, $this->middleware);
255
    }
256
257
    /**
258
     * Add a new middleware to beginning of the stack if it does not already exist.
259
     *
260
     * @param string $middleware
261
     *
262
     * @return $this
263
     */
264
    public function prependMiddleware($middleware)
265
    {
266
        if (array_search($middleware, $this->middleware) === false) {
267
            array_unshift($this->middleware, $middleware);
268
        }
269
270
        return $this;
271
    }
272
273
    /**
274
     * Add a new middleware to end of the stack if it does not already exist.
275
     *
276
     * @param string $middleware
277
     *
278
     * @return $this
279
     */
280
    public function pushMiddleware($middleware)
281
    {
282
        if (array_search($middleware, $this->middleware) === false) {
283
            $this->middleware[] = $middleware;
284
        }
285
286
        return $this;
287
    }
288
289
    /**
290
     * Prepend the given middleware to the given middleware group.
291
     *
292
     * @param string $group
293
     * @param string $middleware
294
     *
295
     * @throws \InvalidArgumentException
296
     *
297
     * @return $this
298
     */
299
    public function prependMiddlewareToGroup($group, $middleware)
300
    {
301
        if (!isset($this->middlewareGroups[$group])) {
302
            throw new InvalidArgumentException("The [{$group}] middleware group has not been defined.");
303
        }
304
305
        if (array_search($middleware, $this->middlewareGroups[$group]) === false) {
306
            array_unshift($this->middlewareGroups[$group], $middleware);
307
        }
308
309
        $this->syncMiddlewareToRouter();
310
311
        return $this;
312
    }
313
314
    /**
315
     * Append the given middleware to the given middleware group.
316
     *
317
     * @param string $group
318
     * @param string $middleware
319
     *
320
     * @throws \InvalidArgumentException
321
     *
322
     * @return $this
323
     */
324
    public function appendMiddlewareToGroup($group, $middleware)
325
    {
326
        if (!isset($this->middlewareGroups[$group])) {
327
            throw new InvalidArgumentException("The [{$group}] middleware group has not been defined.");
328
        }
329
330
        if (array_search($middleware, $this->middlewareGroups[$group]) === false) {
331
            $this->middlewareGroups[$group][] = $middleware;
332
        }
333
334
        $this->syncMiddlewareToRouter();
335
336
        return $this;
337
    }
338
339
    /**
340
     * Prepend the given middleware to the middleware priority list.
341
     *
342
     * @param string $middleware
343
     *
344
     * @return $this
345
     */
346
    public function prependToMiddlewarePriority($middleware)
347
    {
348
        if (!in_array($middleware, $this->middlewarePriority)) {
349
            array_unshift($this->middlewarePriority, $middleware);
350
        }
351
352
        $this->syncMiddlewareToRouter();
353
354
        return $this;
355
    }
356
357
    /**
358
     * Append the given middleware to the middleware priority list.
359
     *
360
     * @param string $middleware
361
     *
362
     * @return $this
363
     */
364
    public function appendToMiddlewarePriority($middleware)
365
    {
366
        if (!in_array($middleware, $this->middlewarePriority)) {
367
            $this->middlewarePriority[] = $middleware;
368
        }
369
370
        $this->syncMiddlewareToRouter();
371
372
        return $this;
373
    }
374
375
    /**
376
     * Sync the current state of the middleware to the router.
377
     *
378
     * @return void
379
     */
380
    protected function syncMiddlewareToRouter()
381
    {
382
        $this->router->middlewarePriority = $this->middlewarePriority;
383
384
        foreach ($this->middlewareGroups as $key => $middleware) {
385
            $this->router->middlewareGroup($key, $middleware);
386
        }
387
388
        foreach ($this->routeMiddleware as $key => $middleware) {
389
            $this->router->aliasMiddleware($key, $middleware);
390
        }
391
    }
392
393
    /**
394
     * Get the bootstrap classes for the application.
395
     *
396
     * @return array
397
     */
398
    protected function bootstrappers()
399
    {
400
        return $this->bootstrappers;
401
    }
402
403
    /**
404
     * Report the exception to the exception handler.
405
     *
406
     * @param \Throwable $e
407
     *
408
     * @return void
409
     */
410
    protected function reportException(Throwable $e)
411
    {
412
        $this->app[ExceptionHandler::class]->report($e);
413
    }
414
415
    /**
416
     * Render the exception to a response.
417
     *
418
     * @param \Illuminate\Http\Request $request
419
     * @param \Throwable               $e
420
     *
421
     * @return \Symfony\Component\HttpFoundation\Response
422
     */
423
    protected function renderException($request, Throwable $e)
424
    {
425
        return $this->app[ExceptionHandler::class]->render($request, $e);
426
    }
427
428
    /**
429
     * Get the application's route middleware groups.
430
     *
431
     * @return array
432
     */
433
    public function getMiddlewareGroups()
434
    {
435
        return $this->middlewareGroups;
436
    }
437
438
    /**
439
     * Get the application's route middleware.
440
     *
441
     * @return array
442
     */
443
    public function getRouteMiddleware()
444
    {
445
        return $this->routeMiddleware;
446
    }
447
448
    /**
449
     * Get the Laravel application instance.
450
     *
451
     * @return \Illuminate\Contracts\Foundation\Application
452
     */
453
    public function getApplication()
454
    {
455
        return $this->app;
456
    }
457
}
458