Passed
Pull Request — master (#178)
by
unknown
02:51
created

Route::cacheable()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 14
c 0
b 0
f 0
nc 7
nop 2
dl 0
loc 27
rs 9.4888
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.0
13
 */
14
15
namespace Quantum\Router;
16
17
use Quantum\Libraries\ResourceCache\ViewCache;
18
use Quantum\Exceptions\DatabaseException;
19
use Quantum\Exceptions\SessionException;
20
use Quantum\Exceptions\ConfigException;
21
use Quantum\Exceptions\RouteException;
22
use Quantum\Exceptions\LangException;
23
use Quantum\Exceptions\DiException;
24
use ReflectionException;
25
use Closure;
26
27
/**
28
 * Route Class
29
 * @package Quantum\Router
30
 */
31
class Route
32
{
33
34
	/**
35
	 * Current module name
36
	 * @var string
37
	 */
38
	private $moduleName;
39
40
	/**
41
	 * Module options
42
	 * @var array
43
	 */
44
	private $moduleOptions = [];
45
46
	/**
47
	 * Identifies the group middleware
48
	 * @var bool
49
	 */
50
	private $isGroupMiddlewares;
51
52
	/**
53
	 * Identifies the group
54
	 * @var boolean
55
	 */
56
	private $isGroup = false;
57
58
	/**
59
	 * Current group name
60
	 * @var string
61
	 */
62
	private $currentGroupName = null;
63
64
	/**
65
	 * Current route
66
	 * @var array
67
	 */
68
	private $currentRoute = [];
69
70
	/**
71
	 * Virtual routes
72
	 * @var array
73
	 */
74
	private $virtualRoutes = [];
75
76
	/**
77
	 * @var ViewCache
78
	 */
79
	private $viewCacheInstance;
80
81
	/**
82
	 * @param array $module
83
	 * @param ViewCache $viewCache
84
	 */
85
	public function __construct(array $module, ViewCache $viewCache)
86
	{
87
		$this->virtualRoutes['*'] = [];
88
		$this->moduleName = key($module);
89
		$this->moduleOptions = $module[key($module)];
90
		$this->viewCacheInstance = $viewCache;
91
	}
92
93
	/**
94
	 * @param string $route
95
	 * @param string $method
96
	 * @param ...$params
97
	 * @return $this
98
	 */
99
	public function add(string $route, string $method, ...$params): Route
100
	{
101
		$this->currentRoute = [
102
			'route' => !empty($this->moduleOptions['prefix']) ? $this->moduleOptions['prefix'] . '/' . $route : $route,
103
			'prefix' => $this->moduleOptions['prefix'],
104
			'method' => $method,
105
			'module' => $this->moduleName
106
		];
107
108
		if (key_exists('cacheable', $this->moduleOptions)){
109
			$enabled = true;
110
			if (!$this->moduleOptions['cacheable']){
111
				$enabled = false;
112
			}
113
114
			$this->currentRoute['shouldCache'] = $enabled;
115
		}
116
117
		if (is_callable($params[0])) {
118
			$this->currentRoute['callback'] = $params[0];
119
		} else {
120
			$this->currentRoute['controller'] = $params[0];
121
			$this->currentRoute['action'] = $params[1];
122
		}
123
124
		if ($this->currentGroupName) {
125
			$this->currentRoute['group'] = $this->currentGroupName;
126
			$this->virtualRoutes[$this->currentGroupName][] = $this->currentRoute;
127
		} else {
128
			$this->isGroup = false;
129
			$this->isGroupMiddlewares = false;
130
			$this->virtualRoutes['*'][] = $this->currentRoute;
131
		}
132
133
		return $this;
134
	}
135
136
	/**
137
	 * @param string $route
138
	 * @param ...$params
139
	 * @return $this
140
	 */
141
	public function get(string $route, ...$params): Route
142
	{
143
		return $this->add($route, 'GET', ...$params);
144
	}
145
146
	/**
147
	 * @param string $route
148
	 * @param ...$params
149
	 * @return $this
150
	 */
151
	public function post(string $route, ...$params): Route
152
	{
153
		return $this->add($route, 'POST', ...$params);
154
	}
155
156
	/**
157
	 * Starts a named group of routes
158
	 * @param string $groupName
159
	 * @param Closure $callback
160
	 * @return Route
161
	 */
162
	public function group(string $groupName, Closure $callback): Route
163
	{
164
		$this->currentGroupName = $groupName;
165
166
		$this->isGroup = true;
167
		$this->isGroupMiddlewares = false;
168
		$callback($this);
169
		$this->isGroupMiddlewares = true;
170
		$this->currentGroupName = null;
171
172
		return $this;
173
	}
174
175
	/**
176
	 * Adds middlewares to routes and route groups
177
	 * @param array $middlewares
178
	 * @return Route
179
	 */
180
	public function middlewares(array $middlewares = []): Route
181
	{
182
		if (!$this->isGroup) {
183
			end($this->virtualRoutes['*']);
184
			$lastKey = key($this->virtualRoutes['*']);
185
			$this->assignMiddlewaresToRoute($this->virtualRoutes['*'][$lastKey], $middlewares);
186
			return $this;
187
		}
188
189
		end($this->virtualRoutes);
190
		$lastKeyOfFirstRound = key($this->virtualRoutes);
191
192
		if (!$this->isGroupMiddlewares) {
193
			end($this->virtualRoutes[$lastKeyOfFirstRound]);
194
			$lastKeyOfSecondRound = key($this->virtualRoutes[$lastKeyOfFirstRound]);
195
			$this->assignMiddlewaresToRoute($this->virtualRoutes[$lastKeyOfFirstRound][$lastKeyOfSecondRound], $middlewares);
196
			return $this;
197
		}
198
199
		foreach ($this->virtualRoutes[$lastKeyOfFirstRound] as &$route) {
200
			$this->assignMiddlewaresToRoute($route, $middlewares);
201
		}
202
203
		return $this;
204
	}
205
206
	/**
207
	 * @param bool $shouldCache
208
	 * @param int|null $ttl
209
	 * @return $this
210
	 * @throws ConfigException
211
	 * @throws DatabaseException
212
	 * @throws DiException
213
	 * @throws LangException
214
	 * @throws ReflectionException
215
	 * @throws SessionException
216
	 */
217
	public function cacheable(bool $shouldCache, int $ttl = null): Route
218
	{
219
		if (empty(session()->getId())){
220
			return $this;
221
		}
222
223
		if ($ttl) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ttl of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
224
			$this->viewCacheInstance->setTtl($ttl);
225
		}
226
227
		if (!$this->isGroup){
228
			end($this->virtualRoutes['*']);
229
			$lastKey = key($this->virtualRoutes['*']);
230
231
			$this->virtualRoutes['*'][$lastKey]['shouldCache'] = $shouldCache;
232
233
			return $this;
234
		}
235
236
		end($this->virtualRoutes);
237
		$lastKeyOfFirstRound = key($this->virtualRoutes);
238
239
		foreach ($this->virtualRoutes[$lastKeyOfFirstRound] as &$route) {
240
			$route['shouldCache'] = $shouldCache;
241
		}
242
243
		return $this;
244
	}
245
246
	/**
247
	 * Sets a unique name for a route
248
	 * @param string $name
249
	 * @return Route
250
	 * @throws RouteException
251
	 */
252
	public function name(string $name): Route
253
	{
254
		if (empty($this->currentRoute)) {
255
			throw RouteException::nameBeforeDefinition();
256
		}
257
258
		if ($this->isGroupMiddlewares) {
259
			throw RouteException::nameOnGroup();
260
		}
261
262
		foreach ($this->virtualRoutes as &$virtualRoute) {
263
			foreach ($virtualRoute as &$route) {
264
				if (isset($route['name']) && $route['name'] == $name) {
265
					throw RouteException::nonUniqueName();
266
				}
267
268
				if ($route['route'] == $this->currentRoute['route']) {
269
					$route['name'] = $name;
270
				}
271
			}
272
		}
273
274
		return $this;
275
	}
276
277
	/**
278
	 * Gets the run-time routes
279
	 * @return array
280
	 */
281
	public function getRuntimeRoutes(): array
282
	{
283
		$runtimeRoutes = [];
284
		foreach ($this->virtualRoutes as $virtualRoute) {
285
			foreach ($virtualRoute as $route) {
286
				$runtimeRoutes[] = $route;
287
			}
288
		}
289
		return $runtimeRoutes;
290
	}
291
292
	/**
293
	 * Gets the virtual routes
294
	 * @return array
295
	 */
296
	public function getVirtualRoutes(): array
297
	{
298
		return $this->virtualRoutes;
299
	}
300
301
	/**
302
	 * Assigns middlewares to the route
303
	 * @param array $route
304
	 * @param array $middlewares
305
	 */
306
	private function assignMiddlewaresToRoute(array &$route, array $middlewares)
307
	{
308
		if (!key_exists('middlewares', $route)) {
309
			$route['middlewares'] = $middlewares;
310
		} else {
311
			$middlewares = array_reverse($middlewares);
312
313
			foreach ($middlewares as $middleware) {
314
				array_unshift($route['middlewares'], $middleware);
315
			}
316
		}
317
	}
318
}
319