Failed Conditions
Branch refactor/kernels (4c6e24)
by Atanas
01:47
created

Router::handleAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 5
ccs 2
cts 2
cp 1
crap 1
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\Routing;
11
12
use WPEmerge\Requests\RequestInterface;
13
use WPEmerge\Routing\Conditions\ConditionFactory;
14
use WPEmerge\Routing\Conditions\ConditionInterface;
15
use WPEmerge\Routing\Conditions\HasUrlWhereInterface;
16
use WPEmerge\Routing\Conditions\InvalidRouteConditionException;
17
use WPEmerge\Support\Arr;
18
19
/**
20
 * Provide routing for site requests (i.e. all non-api requests).
21
 */
22
class Router implements HasRoutesInterface {
23
	use HasRoutesTrait {
24
		addRoute as traitAddRoute;
25
	}
26
27
	/**
28
	 * Condition factory.
29
	 *
30
	 * @var ConditionFactory
31
	 */
32
	protected $condition_factory = null;
33
34
	/**
35
	 * Current active route.
36
	 *
37
	 * @var RouteInterface
38
	 */
39
	protected $current_route = null;
40
41
	/**
42
	 * Group stack.
43
	 *
44
	 * @var array<array<string, mixed>>
45
	 */
46
	protected $group_stack = [];
47
48
	/**
49
	 * Constructor.
50
	 *
51
	 * @codeCoverageIgnore
52
	 * @param ConditionFactory      $condition_factory
53
	 */
54
	public function __construct( ConditionFactory $condition_factory ) {
55
		$this->condition_factory = $condition_factory;
56
	}
57
58
	/**
59
	 * Get the current route.
60
	 *
61
	 * @return RouteInterface
62
	 */
63 1
	public function getCurrentRoute() {
64 1
		return $this->current_route;
65
	}
66
67
	/**
68
	 * Set the current route.
69
	 *
70
	 * @param  RouteInterface
71
	 * @return void
72
	 */
73 1
	public function setCurrentRoute( RouteInterface $current_route ) {
74 1
		$this->current_route = $current_route;
75 1
	}
76
77
	/**
78
	 * Add a group to the group stack, merging all previous attributes.
79
	 *
80
	 * @param array<string, mixed> $attributes
81
	 * @return void
82
	 */
83
	protected function addGroupToStack( $attributes ) {
84
		$previous = Arr::last( $this->group_stack, null, [] );
85
86
		$condition = $this->condition_factory->merge(
87
			Arr::get( $previous, 'condition', '' ),
88
			Arr::get( $attributes, 'condition', '' )
89
		);
90
91
		$attributes = [
92
			'condition' => $condition !== null ? $condition : '',
93
			'where' => array_merge(
94
				Arr::get( $previous, 'where', [] ),
95
				Arr::get( $attributes, 'where', [] )
96
			),
97
			'middleware' => array_merge(
98
				(array) Arr::get( $previous, 'middleware', [] ),
99
				(array) Arr::get( $attributes, 'middleware', [] )
100
			),
101
		];
102
103
		$this->group_stack[] = $attributes;
104
	}
105
106
	/**
107
	 * Remove last group from the group stack.
108
	 *
109
	 * @return void
110
	 */
111
	protected function removeLastGroupFromStack() {
112
		array_pop( $this->group_stack );
113
	}
114
115
	/**
116
	 * Create a new route group.
117
	 *
118
	 * @param array<string, mixed> $attributes
119
	 * @param \Closure|string      $routes Closure or path to file.
120
	 * @return void
121
	 */
122 1
	public function group( $attributes, $routes ) {
123 1
		$this->addGroupToStack( $attributes );
124
125 1
		if ( is_string( $routes ) ) {
126
			require_once $routes;
127
		} else {
128 1
			$routes();
129
		}
130
131 1
		$this->removeLastGroupFromStack();
132 1
	}
133
134
	/**
135
	 * {@inheritDoc}
136
	 */
137 3
	public function makeRoute( $methods, $condition, $handler ) {
138 3
		if ( ! $condition instanceof ConditionInterface ) {
139
			try {
140 2
				$condition = $this->condition_factory->make( $condition );
141 1
			} catch ( InvalidRouteConditionException $e ) {
142 1
				throw new InvalidRouteConditionException( 'Route condition is not a valid route string or condition.' );
143
			}
144
		}
145
146 2
		return new Route( $methods, $condition, $handler );
147
	}
148
149
	/**
150
	 * {@inheritDoc}
151
	 */
152 2
	public function addRoute( $route ) {
153 2
		$group = Arr::last( $this->group_stack, null, [] );
154 2
		$condition = $route->getCondition();
155
156 2
		if ( $condition instanceof HasUrlWhereInterface ) {
157 1
			$condition->setUrlWhere( array_merge(
158 1
				Arr::get( $group, 'where', [] ),
159 1
				$condition->getUrlWhere()
160
			) );
161
		}
162
163 2
		$condition = $this->condition_factory->merge(
164 2
			Arr::get( $group, 'condition', '' ),
165 2
			$condition
166
		);
167
168 2
		$route->setCondition( $condition );
169
170 2
		$route->setMiddleware( array_merge(
171 2
			Arr::get( $group, 'middleware', [] ),
172 2
			$route->getMiddleware()
173
		) );
174
175 2
		return $this->traitAddRoute( $route );
176
	}
177
178
	/**
179
	 * Handle ALL requests.
180
	 *
181
	 * @param  string|\Closure|null $handler
182
	 * @return RouteInterface
183
	 */
184 1
	public function all( $handler = null ) {
185
		// Match ANY request method.
186
		// Match ANY url.
187
		// By default, use built-in WordPress controller.
188 1
		return $this->any( '*', $handler );
189
	}
190
191
	/**
192
	 * Assign and return the first satisfied route (if any) as the current one for the given request.
193
	 *
194
	 * @param  RequestInterface $request
195
	 * @param  array            $arguments
196
	 * @return RouteInterface
197
	 */
198 2
	public function execute( $request, $arguments = [] ) {
199 2
		$routes = $this->getRoutes();
200
201 2
		foreach ( $routes as $route ) {
202 2
			if ( $route->isSatisfied( $request ) ) {
203 1
				$this->setCurrentRoute( $route );
204 2
				return $route;
205
			}
206
		}
207
208 1
		return null;
209
	}
210
}
211