Passed
Push — master ( 3c464a...c957c0 )
by Atanas
03:48
created

Router::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 4
dl 0
loc 6
ccs 0
cts 0
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace WPEmerge\Routing;
4
5
use Exception;
6
use Psr\Http\Message\ResponseInterface;
7
use WPEmerge\Facades\Framework;
8
use WPEmerge\Requests\Request;
9
use WPEmerge\Facades\Response;
10
11
/**
12
 * Provide routing for site requests (i.e. all non-api requests)
13
 */
14
class Router implements HasRoutesInterface {
15
	use HasRoutesTrait {
16
		addRoute as traitAddRoute;
17
	}
18
19
	/**
20
	 * Current request.
21
	 *
22
	 * @var Request
23
	 */
24
	protected $request = null;
25
26
	/**
27
	 * Global middleware.
28
	 *
29
	 * @var array
30
	 */
31
	protected $middleware = [];
32
33
	/**
34
	 * Global middleware priority.
35
	 *
36
	 * @var array
37
	 */
38
	protected $middleware_priority = [];
39
40
	/**
41
	 * Default global middleware priority.
42
	 *
43
	 * @var integer
44
	 */
45
	protected $default_middleware_priority = 0;
46
47
	/**
48
	 * Current active route.
49
	 *
50
	 * @var RouteInterface
51
	 */
52
	protected $current_route = null;
53
54
	/**
55
	 * Constructor.
56
	 *
57
	 * @codeCoverageIgnore
58
	 * @param Request $request
59
	 * @param array   $middleware
60
	 * @param array   $middleware_priority
61
	 * @param integer $default_middleware_priority
62
	 */
63
	public function __construct( Request $request, $middleware, $middleware_priority, $default_middleware_priority ) {
64
		$this->request = $request;
65
		$this->middleware_priority = $middleware_priority;
66
		$this->default_middleware_priority = $default_middleware_priority;
67
		$this->middleware = $this->sortMiddleware( $middleware );
68
	}
69
70
	/**
71
	 * Hook into WordPress actions.
72
	 *
73
	 * @codeCoverageIgnore
74
	 * @return void
75
	 */
76
	public function boot() {
77
		add_action( 'init', [$this, 'registerRewriteRules'], 1000 );
78
		add_action( 'template_include', [$this, 'execute'], 1000 );
79
	}
80
81
	/**
82
	 * Register route rewrite rules with WordPress.
83
	 *
84
	 * @codeCoverageIgnore
85
	 * @return void
86
	 */
87
	public function registerRewriteRules() {
88
		$rules = apply_filters( 'wpemerge.routing.rewrite_rules', [] );
89
		foreach ( $rules as $rule => $rewrite_to ) {
90
			add_rewrite_rule( $rule, $rewrite_to, 'top' );
91
		}
92
	}
93
94
	/**
95
	 * Get middleware priority.
96
	 *
97
	 * @param  mixed   $middleware
98
	 * @return integer
99
	 */
100
	protected function getMiddlewarePriority( $middleware ) {
101
		if ( is_string( $middleware ) && isset( $this->middleware_priority[ $middleware ] ) ) {
102
			return $this->middleware_priority[ $middleware ];
103
		}
104
105
		return $this->default_middleware_priority;
106
	}
107
108
	/**
109
	 * Sort middleware by priority in ascending order.
110
	 *
111
	 * @param  array $middleware
112
	 * @return array
113
	 */
114
	protected function sortMiddleware( $middleware ) {
115
		usort( $middleware, function( $a, $b ) {
116
			return $this->getMiddlewarePriority( $a ) - $this->getMiddlewarePriority( $b );
117
		} );
118
119
		return $middleware;
120
	}
121
122
	/**
123
	 * {@inheritDoc}
124
	 */
125
	public function addRoute( $route ) {
126
		$route->addMiddleware( $this->middleware );
127
		return $this->traitAddRoute( $route );
128
	}
129
130
	/**
131
	 * Execute the first satisfied route, if any.
132
	 *
133
	 * @param  string $view
134
	 * @return string
135
	 */
136 7
	public function execute( $view ) {
137 7
		$routes = $this->getRoutes();
138
139 7
		foreach ( $routes as $route ) {
140 7
			if ( $route->isSatisfied( $this->request ) ) {
141 5
				$this->setCurrentRoute( $route );
142 5
				return $this->handle( $this->request, $route, $view );
143
			}
144 2
		}
145
146 2
		return $view;
147
	}
148
149
	/**
150
	 * Execute a route.
151
	 *
152
	 * @throws Exception
153
	 * @param  Request        $request
154
	 * @param  RouteInterface $route
155
	 * @param  string         $view
156
	 * @return string
157
	 */
158 4
	protected function handle( Request $request, RouteInterface $route, $view ) {
159 4
		$response = $route->handle( $request, $view );
160
161 4
		if ( ! $response instanceof ResponseInterface ) {
162 2
			if ( Framework::debugging() ) {
163 1
				throw new Exception( 'Response returned by controller is not valid (expectected ' . ResponseInterface::class . '; received ' . gettype( $response ) . ').' );
164
			}
165 1
			$response = Response::error( 500 );
166 1
		}
167
168 3
		add_filter( 'wpemerge.response', function() use ( $response ) {
169 2
			return $response;
170 3
		} );
171
172 3
		return WPEMERGE_DIR . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'view.php';
173
	}
174
175
	/**
176
	 * Get the current route.
177
	 *
178
	 * @return RouteInterface
179
	 */
180 1
	public function getCurrentRoute() {
181 1
		return $this->current_route;
182
	}
183
184
	/**
185
	 * Set the current route.
186
	 *
187
	 * @param  RouteInterface
188
	 * @return void
189
	 */
190 1
	public function setCurrentRoute( RouteInterface $current_route ) {
191 1
		$this->current_route = $current_route;
192 1
	}
193
194
	/**
195
	 * Handle ALL requests.
196
	 *
197
	 * @param  string|Closure|null $handler
198
	 * @return RouteInterface
199
	 */
200 1
	public function handleAll( $handler = null ) {
201
		// match ANY request method
202
		// match ANY url
203
		// by default, use built-in WordPress controller
204 1
		return $this->any( '*', $handler );
205
	}
206
}
207