1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Anax\Route; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* A container for routes. |
7
|
|
|
* |
8
|
|
|
*/ |
9
|
|
|
class RouterInjectable |
10
|
|
|
{ |
11
|
|
|
/** |
12
|
|
|
* Properties |
13
|
|
|
* |
14
|
|
|
*/ |
15
|
|
|
private $routes = []; // All the routes |
16
|
|
|
private $internalRoutes = []; // All internal routes |
17
|
|
|
private $lastRoute = null; // Last route that was callbacked |
18
|
|
|
|
19
|
|
|
|
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Get all routes. |
23
|
|
|
* |
24
|
|
|
* @return array with all routes. |
25
|
|
|
*/ |
26
|
|
|
public function getAll() |
27
|
|
|
{ |
28
|
|
|
return $this->routes; |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
|
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Get all internal routes. |
35
|
|
|
* |
36
|
|
|
* @return array with internal routes. |
37
|
|
|
*/ |
38
|
|
|
public function getInternal() |
39
|
|
|
{ |
40
|
|
|
return $this->internalRoutes; |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
|
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Add a route to the router. |
47
|
|
|
* |
48
|
|
|
* @param string $rule for this route |
49
|
|
|
* @param mixed $action null, string or callable to implement a |
50
|
|
|
* controller for the route |
51
|
|
|
* |
52
|
|
|
* @return class as new route |
53
|
|
|
*/ |
54
|
8 |
View Code Duplication |
public function add($rule, $action = null) |
|
|
|
|
55
|
|
|
{ |
56
|
8 |
|
$route = new Route(); |
57
|
8 |
|
$route->set($rule, $action, []); |
|
|
|
|
58
|
8 |
|
$this->routes[] = $route; |
59
|
|
|
|
60
|
8 |
|
return $route; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
|
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Add aroute to the router with specific request method. |
67
|
|
|
* |
68
|
|
|
* @param array $method as array of strings of request methods |
69
|
|
|
* @param string $rule for this route |
70
|
|
|
* @param mixed $action null, string or callable to implement a |
71
|
|
|
* controller for the route |
72
|
|
|
* |
73
|
|
|
* @return class as new route |
74
|
|
|
*/ |
75
|
3 |
View Code Duplication |
public function any($method, $rule, $action = null) |
|
|
|
|
76
|
|
|
{ |
77
|
3 |
|
$route = new Route(); |
78
|
3 |
|
$route->set($rule, $action, $method); |
|
|
|
|
79
|
3 |
|
$this->routes[] = $route; |
80
|
|
|
|
81
|
3 |
|
return $route; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
|
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Add a GET route to the router. |
88
|
|
|
* |
89
|
|
|
* @param string $rule for this route |
90
|
|
|
* @param mixed $action null, string or callable to implement a |
91
|
|
|
* controller for the route |
92
|
|
|
* |
93
|
|
|
* @return class as new route |
94
|
|
|
*/ |
95
|
1 |
|
public function get($rule, $action = null) |
96
|
|
|
{ |
97
|
1 |
|
return $this->any(["GET"], $rule, $action); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
|
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Add a POST route to the router. |
104
|
|
|
* |
105
|
|
|
* @param string $rule for this route |
106
|
|
|
* @param mixed $action null, string or callable to implement a |
107
|
|
|
* controller for the route |
108
|
|
|
* |
109
|
|
|
* @return class as new route |
110
|
|
|
*/ |
111
|
1 |
|
public function post($rule, $action = null) |
112
|
|
|
{ |
113
|
1 |
|
return $this->any(["POST"], $rule, $action); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
|
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Add a PUT route to the router. |
120
|
|
|
* |
121
|
|
|
* @param string $rule for this route |
122
|
|
|
* @param mixed $action null, string or callable to implement a |
123
|
|
|
* controller for the route |
124
|
|
|
* |
125
|
|
|
* @return class as new route |
126
|
|
|
*/ |
127
|
1 |
|
public function put($rule, $action = null) |
128
|
|
|
{ |
129
|
1 |
|
return $this->any(["PUT"], $rule, $action); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
|
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Add a DELETE route to the router. |
136
|
|
|
* |
137
|
|
|
* @param string $rule for this route |
138
|
|
|
* @param mixed $action null, string or callable to implement a |
139
|
|
|
* controller for the route |
140
|
|
|
* |
141
|
|
|
* @return class as new route |
142
|
|
|
*/ |
143
|
1 |
|
public function delete($rule, $action = null) |
144
|
|
|
{ |
145
|
1 |
|
return $this->any(["DELETE"], $rule, $action); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
|
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Add an internal (not exposed to url-matching) route to the router. |
152
|
|
|
* |
153
|
|
|
* @param string $rule for this route |
154
|
|
|
* @param mixed $action null, string or callable to implement a controller for the route |
155
|
|
|
* |
156
|
|
|
* @return class as new route |
157
|
|
|
*/ |
158
|
3 |
|
public function addInternal($rule, $action = null) |
159
|
|
|
{ |
160
|
3 |
|
$route = new Route(); |
161
|
3 |
|
$route->set($rule, $action); |
|
|
|
|
162
|
3 |
|
$this->internalRoutes[$rule] = $route; |
163
|
3 |
|
return $route; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
|
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Add an internal (not exposed to url-matching) route to the router. |
170
|
|
|
* |
171
|
|
|
* @param string $rule for this route |
172
|
|
|
* @param mixed $action null, string or callable to implement a |
|
|
|
|
173
|
|
|
* controller for the route |
174
|
|
|
* |
175
|
|
|
* @return void |
176
|
|
|
*/ |
177
|
4 |
|
public function handleInternal($rule) |
178
|
|
|
{ |
179
|
4 |
|
if (!isset($this->internalRoutes[$rule])) { |
180
|
1 |
|
throw new NotFoundException("No internal route to handle: " . $rule); |
181
|
|
|
} |
182
|
3 |
|
$route = $this->internalRoutes[$rule]; |
183
|
3 |
|
$this->lastRoute = $rule; |
184
|
3 |
|
$route->handle(); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
|
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Get the route for the last route that was handled. |
191
|
|
|
* |
192
|
|
|
* @return mixed |
193
|
|
|
*/ |
194
|
|
|
public function getLastRoute() |
195
|
|
|
{ |
196
|
|
|
return $this->lastRoute; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
|
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Handle the routes and match them towards the request, dispatch them |
203
|
|
|
* when a match is made. Each route handler may throw exceptions that |
204
|
|
|
* may redirect to an internal route for error handling. |
205
|
|
|
* |
206
|
|
|
* @param string $query the query/route to match a handler for. |
207
|
|
|
* @param string $method the request method to match. |
208
|
|
|
* |
209
|
|
|
* @return mixed content returned from route. |
210
|
|
|
*/ |
211
|
9 |
|
public function handle($query, $method = null) |
212
|
|
|
{ |
213
|
|
|
try { |
214
|
|
|
// Match predefined routes |
215
|
9 |
|
foreach ($this->routes as $route) { |
216
|
8 |
|
if ($route->match($query, $method)) { |
217
|
8 |
|
$this->lastRoute = $route->getRule(); |
218
|
8 |
|
return $route->handle(); |
219
|
|
|
} |
220
|
4 |
|
} |
221
|
|
|
|
222
|
|
|
// No route was matched |
223
|
1 |
|
$this->handleInternal("404"); |
224
|
4 |
|
} catch (ForbiddenException $e) { |
225
|
1 |
|
$this->handleInternal("403"); |
226
|
3 |
|
} catch (NotFoundException $e) { |
227
|
2 |
|
$this->handleInternal("404"); |
228
|
1 |
|
} catch (InternalErrorException $e) { |
229
|
1 |
|
$this->handleInternal("500"); |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.