Completed
Push — master ( 36a006...f90c70 )
by CodexShaper
04:12
created

Kernel::has_middleware()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * The file handle the request.
4
 *
5
 * @link       https://github.com/maab16
6
 * @since      1.0.0
7
 *
8
 * @package    WPB
9
 * @subpackage WPB/src/Http
10
 */
11
12
namespace WPB\Http;
13
14
use WPB\Http\Events\RequestHandled;
15
use Illuminate\Contracts\Container\Container;
16
use Illuminate\Contracts\Debug\ExceptionHandler;
17
use WPB\Contracts\Http\Kernel as KernelContract;
18
use Illuminate\Routing\Pipeline;
19
use Illuminate\Routing\Router;
20
use Illuminate\Support\Facades\Facade;
21
use InvalidArgumentException;
22
use Throwable;
23
24
/**
25
 * The request handler.
26
 *
27
 * @since      1.0.0
28
 * @package    WPB
29
 * @subpackage WPB/src/Http
30
 * @author     Md Abu Ahsan basir <[email protected]>
31
 */
32
class Kernel implements KernelContract {
33
34
	/**
35
	 * The application implementation.
36
	 *
37
	 * @var \Illuminate\Contracts\Foundation\Application
38
	 */
39
	protected $app;
40
41
	/**
42
	 * The router instance.
43
	 *
44
	 * @var \Illuminate\Routing\Router
45
	 */
46
	protected $router;
47
48
	/**
49
	 * The bootstrap classes for the application.
50
	 *
51
	 * @var array
52
	 */
53
	protected $bootstrappers = array();
54
55
	/**
56
	 * The application's middleware stack.
57
	 *
58
	 * @var array
59
	 */
60
	protected $middleware = array();
61
62
	/**
63
	 * The application's route middleware groups.
64
	 *
65
	 * @var array
66
	 */
67
	protected $middleware_groups = array();
68
69
	/**
70
	 * The application's route middleware.
71
	 *
72
	 * @var array
73
	 */
74
	protected $route_middleware = array();
75
76
	/**
77
	 * The priority-sorted list of middleware.
78
	 *
79
	 * Forces non-global middleware to always be in the given order.
80
	 *
81
	 * @var array
82
	 */
83
	protected $middleware_priority = array();
84
85
	/**
86
	 * Create a new HTTP kernel instance.
87
	 *
88
	 * @param \Illuminate\Contracts\Container\Container $app The app.
89
	 * @param \Illuminate\Routing\Router                $router The app router.
90
	 *
91
	 * @return void
92
	 */
93
	public function __construct( Container $app, Router $router ) {
94
		$this->app    = $app;
0 ignored issues
show
Documentation Bug introduced by
$app is of type Illuminate\Contracts\Container\Container, but the property $app was declared to be of type Illuminate\Contracts\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...
95
		$this->router = $router;
96
97
		$this->sync_middleware_to_router();
98
	}
99
100
	/**
101
	 * Handle an incoming HTTP request.
102
	 *
103
	 * @param \Illuminate\Http\Request $request The app http request.
104
	 *
105
	 * @throws \Exception The throwable exception.
106
	 *
107
	 * @return \Illuminate\Http\Response
108
	 */
109
	public function handle( $request ) {
110
		try {
111
			$request->enableHttpMethodParameterOverride();
112
			$response = $this->send_request_through_router( $request );
113
		} catch ( Throwable $e ) {
114
			$this->report_exception( $e );
115
			$response = $this->render_exception( $request, $e );
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
116
			throw new \Exception( $e, 1 );
117
		}
118
119
		$this->app['events']->dispatch(
120
			new RequestHandled( $request, $response )
121
		);
122
123
		return $response;
124
	}
125
126
	/**
127
	 * Send the given request through the middleware / router.
128
	 *
129
	 * @param \Illuminate\Http\Request $request The app http request.
130
	 *
131
	 * @return \Illuminate\Http\Response
132
	 */
133
	protected function send_request_through_router( $request ) {
134
		$this->app->instance( 'request', $request );
135
136
		Facade::clearResolvedInstance( 'request' );
137
138
		$this->bootstrap();
139
140
		return ( new Pipeline( $this->app ) )
141
					->send( $request )
142
					->through( $this->middleware )
143
					->then( $this->dispatch_to_router() );
144
	}
145
146
	/**
147
	 * Bootstrap the application for HTTP requests.
148
	 *
149
	 * @return void
150
	 */
151
	public function bootstrap() {}
152
153
	/**
154
	 * Get the route dispatcher callback.
155
	 *
156
	 * @return \Closure
157
	 */
158
	protected function dispatch_to_router() {
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 The app http request.
170
	 * @param \Illuminate\Http\Response $response The app http response.
171
	 *
172
	 * @return void
173
	 */
174
	public function terminate( $request, $response ) {
175
		$this->terminate_middleware( $request, $response );
176
177
		$this->app->terminate();
178
	}
179
180
	/**
181
	 * Call the terminate method on any terminable middleware.
182
	 *
183
	 * @param \Illuminate\Http\Request  $request The app http request.
184
	 * @param \Illuminate\Http\Response $response The app http response.
185
	 *
186
	 * @return void
187
	 */
188
	protected function terminate_middleware( $request, $response ) {
189
		$middlewares = $this->app->shouldSkipMiddleware() ? array() : array_merge(
190
			$this->gather_route_middleware( $request ),
191
			$this->middleware
192
		);
193
194
		foreach ( $middlewares as $middleware ) {
195
			if ( ! is_string( $middleware ) ) {
196
				continue;
197
			}
198
199
			list( $name ) = $this->parse_middleware( $middleware );
200
201
			$instance = $this->app->make( $name );
202
203
			if ( method_exists( $instance, 'terminate' ) ) {
204
				$instance->terminate( $request, $response );
205
			}
206
		}
207
	}
208
209
	/**
210
	 * Gather the route middleware for the given request.
211
	 *
212
	 * @param \Illuminate\Http\Request $request The app http request.
213
	 *
214
	 * @return array
215
	 */
216
	protected function gather_route_middleware( $request ) {
217
		$route = $request->route();
218
		if ( $route ) {
219
			return $this->router->gatherRouteMiddleware( $route );
0 ignored issues
show
Bug introduced by
It seems like $route can also be of type string; however, parameter $route of Illuminate\Routing\Router::gatherRouteMiddleware() does only seem to accept Illuminate\Routing\Route, maybe add an additional type check? ( Ignorable by Annotation )

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

219
			return $this->router->gatherRouteMiddleware( /** @scrutinizer ignore-type */ $route );
Loading history...
220
		}
221
222
		return array();
223
	}
224
225
	/**
226
	 * Parse a middleware string to get the name and parameters.
227
	 *
228
	 * @param string $middleware The app middleware.
229
	 *
230
	 * @return array
231
	 */
232
	protected function parse_middleware( $middleware ) {
233
234
		list( $name, $parameters ) = array_pad( explode( ':', $middleware, 2 ), 2, array() );
235
236
		if ( is_string( $parameters ) ) {
237
			$parameters = explode( ',', $parameters );
238
		}
239
240
		return array( $name, $parameters );
241
	}
242
243
	/**
244
	 * Determine if the kernel has a given middleware.
245
	 *
246
	 * @param string $middleware The app middleware.
247
	 *
248
	 * @return bool
249
	 */
250
	public function has_middleware( $middleware ) {
251
		return in_array( $middleware, $this->middleware );
252
	}
253
254
	/**
255
	 * Add a new middleware to beginning of the stack if it does not already exist.
256
	 *
257
	 * @param string $middleware The app middleware.
258
	 *
259
	 * @return $this
260
	 */
261
	public function prepend_middleware( $middleware ) {
262
		if ( array_search( $middleware, $this->middleware ) === false ) {
263
			array_unshift( $this->middleware, $middleware );
264
		}
265
266
		return $this;
267
	}
268
269
	/**
270
	 * Add a new middleware to end of the stack if it does not already exist.
271
	 *
272
	 * @param string $middleware The app middleware.
273
	 *
274
	 * @return $this
275
	 */
276
	public function push_middleware( $middleware ) {
277
		if ( array_search( $middleware, $this->middleware ) === false ) {
278
			$this->middleware[] = $middleware;
279
		}
280
281
		return $this;
282
	}
283
284
	/**
285
	 * Prepend the given middleware to the given middleware group.
286
	 *
287
	 * @param string $group The app group.
288
	 * @param string $middleware The app middleware.
289
	 *
290
	 * @throws \InvalidArgumentException The invalid argument exception.
291
	 *
292
	 * @return $this
293
	 */
294
	public function prepend_middleware_to_group( $group, $middleware ) {
295
		if ( ! isset( $this->middleware_groups[ $group ] ) ) {
296
			throw new InvalidArgumentException( "The [{$group}] middleware group has not been defined." );
297
		}
298
299
		if ( array_search( $middleware, $this->middleware_groups[ $group ] ) === false ) {
300
			array_unshift( $this->middleware_groups[ $group ], $middleware );
301
		}
302
303
		$this->sync_middleware_to_router();
304
305
		return $this;
306
	}
307
308
	/**
309
	 * Append the given middleware to the given middleware group.
310
	 *
311
	 * @param string $group The app group.
312
	 * @param string $middleware The app middleware.
313
	 *
314
	 * @throws \InvalidArgumentException The invalid argument exception.
315
	 *
316
	 * @return $this
317
	 */
318
	public function append_middleware_to_group( $group, $middleware ) {
319
		if ( ! isset( $this->middleware_groups[ $group ] ) ) {
320
			throw new InvalidArgumentException( "The [{$group}] middleware group has not been defined." );
321
		}
322
323
		if ( array_search( $middleware, $this->middleware_groups[ $group ] ) === false ) {
324
			$this->middleware_groups[ $group ][] = $middleware;
325
		}
326
327
		$this->sync_middleware_to_router();
328
329
		return $this;
330
	}
331
332
	/**
333
	 * Prepend the given middleware to the middleware priority list.
334
	 *
335
	 * @param string $middleware The app middleware.
336
	 *
337
	 * @return $this
338
	 */
339
	public function prepend_to_middleware_priority( $middleware ) {
340
		if ( ! in_array( $middleware, $this->middleware_priority ) ) {
341
			array_unshift( $this->middleware_priority, $middleware );
342
		}
343
344
		$this->sync_middleware_to_router();
345
346
		return $this;
347
	}
348
349
	/**
350
	 * Append the given middleware to the middleware priority list.
351
	 *
352
	 * @param string $middleware The app middleware.
353
	 *
354
	 * @return $this
355
	 */
356
	public function append_to_middleware_priority( $middleware ) {
357
		if ( ! in_array( $middleware, $this->middleware_priority ) ) {
358
			$this->middleware_priority[] = $middleware;
359
		}
360
361
		$this->sync_middleware_to_router();
362
363
		return $this;
364
	}
365
366
	/**
367
	 * Sync the current state of the middleware to the router.
368
	 *
369
	 * @return void
370
	 */
371
	protected function sync_middleware_to_router() {
372
		$this->router->middlewarePriority = $this->middleware_priority;
373
374
		foreach ( $this->middleware_groups as $key => $middleware ) {
375
			$this->router->middlewareGroup( $key, $middleware );
376
		}
377
378
		foreach ( $this->route_middleware as $key => $middleware ) {
379
			$this->router->aliasMiddleware( $key, $middleware );
380
		}
381
	}
382
383
	/**
384
	 * Get the bootstrap classes for the application.
385
	 *
386
	 * @return array
387
	 */
388
	protected function bootstrappers() {
389
		return $this->bootstrappers;
390
	}
391
392
	/**
393
	 * Report the exception to the exception handler.
394
	 *
395
	 * @param \Throwable $e The throwable exception.
396
	 *
397
	 * @return void
398
	 */
399
	protected function report_exception( Throwable $e ) {
400
		$this->app[ ExceptionHandler::class ]->report( $e );
401
	}
402
403
	/**
404
	 * Render the exception to a response.
405
	 *
406
	 * @param \Illuminate\Http\Request $request The app http request.
407
	 * @param \Throwable               $e The throwable exception.
408
	 *
409
	 * @return \Symfony\Component\HttpFoundation\Response
410
	 */
411
	protected function render_exception( $request, Throwable $e ) {
412
		return $this->app[ ExceptionHandler::class ]->render( $request, $e );
413
	}
414
415
	/**
416
	 * Get the application's route middleware groups.
417
	 *
418
	 * @return array
419
	 */
420
	public function get_middleware_groups() {
421
		return $this->middleware_groups;
422
	}
423
424
	/**
425
	 * Get the application's route middleware.
426
	 *
427
	 * @return array
428
	 */
429
	public function get_route_middleware() {
430
		return $this->route_middleware;
431
	}
432
433
	/**
434
	 * Get the Laravel application instance.
435
	 *
436
	 * @return \Illuminate\Contracts\Foundation\Application
437
	 */
438
	public function get_application() {
439
		return $this->app;
440
	}
441
}
442