Passed
Push — master ( 685651...ff2960 )
by Atanas
02:52
created

HasMiddlewareTrait::middleware()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 2
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2018 Atanas Angelov
6
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0
7
 * @link      https://wpemerge.com/
8
 */
9
10
namespace WPEmerge\Middleware;
11
12
use Closure;
13
use WPEmerge\Exceptions\Exception;
14
use WPEmerge\Facades\Framework;
15
use WPEmerge\Facades\Router;
16
use WPEmerge\Helpers\MixedType;
17
use WPEmerge\Requests\RequestInterface;
18
19
/**
20
 * Allow objects to have middleware
21
 */
22
trait HasMiddlewareTrait {
23
	/**
24
	 * Array of all registered middleware.
25
	 *
26
	 * @var array
27
	 */
28
	protected $middleware = [];
29
30
	/**
31
	 * Check if the passed entity is a valid middleware.
32
	 *
33
	 * @param  mixed   $middleware
34
	 * @return boolean
35
	 */
36 6
	protected function isMiddleware( $middleware ) {
37
		return (
38
			$middleware instanceof Closure
39 6
			||
40 5
			is_a( $middleware, MiddlewareInterface::class, true )
41 6
		);
42
	}
43
44
	/**
45
	 * Get registered middleware.
46
	 *
47
	 * @return array
48
	 */
49 1
	public function getMiddleware() {
50 1
		return $this->middleware;
51
	}
52
53
	/**
54
	 * Set registered middleware.
55
	 * Accepts: a class name, an instance of a class, a Closure or an array of any of the previous.
56
	 *
57
	 * @throws Exception
58
	 * @param  string|\Closure|\WPEmerge\Middleware\MiddlewareInterface|array $middleware
59
	 * @return void
60
	 */
61 3
	public function setMiddleware( $middleware ) {
62 3
		$middleware = MixedType::toArray( $middleware );
63
64 3
		foreach ( $middleware as $item ) {
65 2
			if ( ! $this->isMiddleware( $item ) ) {
66 1
				throw new Exception(
67
					'Passed middleware must be a closure or the name or instance of a class which ' .
68 1
					'implements the ' . MiddlewareInterface::class . ' interface.'
69 1
				);
70
			}
71 2
		}
72
73
		// TODO this router dependency should be avoided.
74 2
		$this->middleware = Router::sortMiddleware( $middleware );
75 2
	}
76
77
	/**
78
	 * Add middleware.
79
	 * Accepts: a class name, an instance of a class, a Closure or an array of any of the previous.
80
	 *
81
	 * @throws Exception
82
	 * @param  string|\Closure|\WPEmerge\Middleware\MiddlewareInterface|array $middleware
83
	 * @return static                                                         $this
84
	 */
85 1
	public function addMiddleware( $middleware ) {
86 1
		$middleware = MixedType::toArray( $middleware );
87
88 1
		$this->setMiddleware( array_merge( $this->getMiddleware(), $middleware ) );
89
90 1
		return $this;
91
	}
92
93
	/**
94
	 * Alias for addMiddleware.
95
	 *
96
	 * @codeCoverageIgnore
97
	 * @param  string|\Closure|\WPEmerge\Middleware\MiddlewareInterface|array $middleware
98
	 * @return static                                                         $this
99
	 */
100
	public function middleware( $middleware ) {
101
		return call_user_func_array( [$this, 'addMiddleware'], func_get_args() );
102
	}
103
104
	/**
105
	 * Execute an array of middleware recursively (last in, first out).
106
	 *
107
	 * @param  array                               $middleware
108
	 * @param  RequestInterface                    $request
109
	 * @param  Closure                             $next
110
	 * @return \Psr\Http\Message\ResponseInterface
111
	 */
112 5
	public function executeMiddleware( $middleware, RequestInterface $request, Closure $next ) {
113 5
		$top_middleware = array_shift( $middleware );
114
115 5
		if ( $top_middleware === null ) {
116 5
			return $next( $request );
117
		}
118
119 4
		$top_middleware_next = function ( $request ) use ( $middleware, $next ) {
120 4
			return $this->executeMiddleware( $middleware, $request, $next );
121 4
		};
122
123 4
		return MixedType::value( $top_middleware, [$request, $top_middleware_next], 'handle', [Framework::class, 'instantiate'] );
124
	}
125
}
126