Passed
Push — master ( 9b5f74...fb0215 )
by Atanas
03:00
created

Route::rewrite()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 14
ccs 0
cts 9
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WPEmerge\Routing;
4
5
use WPEmerge\Exceptions\Exception;
6
use WPEmerge\Facades\Framework;
7
use WPEmerge\Facades\RouteCondition;
8
use WPEmerge\Middleware\HasMiddlewareTrait;
9
use WPEmerge\Requests\Request;
10
use WPEmerge\Routing\Conditions\ConditionInterface;
11
use WPEmerge\Routing\Conditions\InvalidRouteConditionException;
12
use WPEmerge\Routing\Conditions\UrlCondition;
13
14
/**
15
 * Represent a route
16
 */
17
class Route implements RouteInterface {
18
	use HasMiddlewareTrait;
19
20
	/**
21
	 * Allowed methods.
22
	 *
23
	 * @var string[]
24
	 */
25
	protected $methods = [];
26
27
	/**
28
	 * Route condition.
29
	 *
30
	 * @var ConditionInterface
31
	 */
32
	protected $condition = null;
33
34
	/**
35
	 * Route handler.
36
	 *
37
	 * @var RouteHandler
38
	 */
39
	protected $handler = null;
40
41
	/**
42
	 * Query filter.
43
	 *
44
	 * @var callable
45
	 */
46
	protected $query_filter = null;
47
48
	/**
49
	 * Query filter action priority.
50
	 *
51
	 * @var integer
52
	 */
53
	protected $query_filter_priority = 1000;
54
55
	/**
56
	 * Constructor.
57
	 *
58
	 * @throws Exception
59
	 * @param  string[]        $methods
60
	 * @param  mixed           $condition
61
	 * @param  string|\Closure $handler
62
	 */
63 3
	public function __construct( $methods, $condition, $handler ) {
64 3
		if ( ! $condition instanceof ConditionInterface ) {
65
			try {
66 2
				$condition = RouteCondition::make( $condition );
67 1
			} catch ( InvalidRouteConditionException $e ) {
68 1
				throw new Exception( 'Route condition is not a valid route string or condition.' );
69
			}
70
		}
71
72 2
		$this->methods = $methods;
73 2
		$this->condition = $condition;
74 2
		$this->handler = new RouteHandler( $handler );
75 2
	}
76
77
	/**
78
	 * Get allowed methods.
79
	 *
80
	 * @return string[]
81
	 */
82 1
	public function getMethods() {
83 1
		return $this->methods;
84
	}
85
86
	/**
87
	 * Get condition.
88
	 *
89
	 * @return ConditionInterface
90
	 */
91 1
	public function getCondition() {
92 1
		return $this->condition;
93
	}
94
95
	/**
96
	 * Get handler.
97
	 *
98
	 * @return RouteHandler
99
	 */
100 1
	public function getHandler() {
101 1
		return $this->handler;
102
	}
103
104
	/**
105
	 * Get the main WordPress query vars filter, if any.
106
	 *
107
	 * @return callable|null
108
	 */
109
	public function getQueryFilter() {
110
		return $this->query_filter;
111
	}
112
113
	/**
114
	 * Set the main WordPress query vars filter and add it to the appropriate WordPress action.
115
	 *
116
	 * @param  callable|null $query_filter
117
	 * @return self          $this
118
	 */
119
	public function setQueryFilter( $query_filter ) {
120
		$this->query_filter = $query_filter;
121
		$this->addQueryFilter();
122
		return $this;
123
	}
124
125
	/**
126
	 * Add the query filter to the appropriate WordPress action.
127
	 *
128
	 * @return self $this
129
	 */
130
	public function addQueryFilter() {
131
		$filter = [$this, 'applyQueryFilter'];
132
133
		if ( ! has_action( 'request', $filter ) ) {
134
			add_action( 'request', $filter, $this->query_filter_priority );
135
		}
136
137
		return $this;
138
	}
139
140
	/**
141
	 * Remove the query filter from the appropriate WordPress action.
142
	 *
143
	 * @return self $this
144
	 */
145
	public function removeQueryFilter() {
146
		$filter = [$this, 'applyQueryFilter'];
147
148
		if ( has_action( 'request', $filter ) ) {
149
			remove_action( 'request', $filter, $this->query_filter_priority );
150
		}
151
152
		return $this;
153
	}
154
155
	/**
156
	 * Apply the query filter, if any.
157
	 *
158
	 * @throws Exception
159
	 * @param  array<string, mixed> $query_vars
160
	 * @return array<string, mixed>
161
	 */
162
	public function applyQueryFilter( $query_vars ) {
163
		$request = Framework::resolve( WPEMERGE_REQUEST_KEY );
164
		$condition = $this->getCondition();
165
166
		if ( ! is_callable( $this->getQueryFilter() ) ) {
167
			return $query_vars;
168
		}
169
170
		if ( ! $condition instanceof UrlCondition ) {
171
			throw new Exception( 'Routes with queries can only use URL condition. Is the route in a non-URL route group?' );
172
		}
173
174
		if ( $this->getCondition()->isSatisfied( $request ) ) {
175
			$arguments = $this->getCondition()->getArguments( $request );
176
			$query_vars = call_user_func_array( $this->getQueryFilter(), array_merge( [$query_vars], $arguments ) );
177
		}
178
179
		return $query_vars;
180
	}
181
182
	/**
183
	 * Set the main WordPress query vars filter.
184
	 * Alias of ::setQueryFilter()
185
	 *
186
	 * @codeCoverageIgnore
187
	 * @param  callable $query_filter
188
	 * @return self     $this
189
	 */
190
	public function query( $query_filter ) {
191
		return $this->setQueryFilter( $query_filter );
192
	}
193
194
	/**
195
	 * {@inheritDoc}
196
	 */
197 2
	public function isSatisfied( Request $request ) {
198 2
		if ( ! in_array( $request->getMethod(), $this->methods) ) {
199 1
			return false;
200
		}
201 2
		return $this->condition->isSatisfied( $request );
202
	}
203
204
	/**
205
	 * {@inheritDoc}
206
	 */
207
	public function getArguments( Request $request ) {
208
		return $this->getCondition()->getArguments( $request );
209
	}
210
211
	/**
212
	 * {@inheritDoc}
213
	 */
214
	public function handle( Request $request, $view ) {
215
		$arguments = array_merge( [$request, $view], $this->condition->getArguments( $request ) );
216
		return $this->executeMiddleware( $this->getMiddleware(), $request, function() use ( $arguments ) {
217
			return call_user_func_array( [$this->handler, 'execute'], $arguments );
218
		} );
219
	}
220
}
221