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 $defaultRoute = null; // A default route to catch all |
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 controller for the route |
50
|
|
|
* |
51
|
|
|
* @return class as new route |
52
|
|
|
*/ |
53
|
5 |
View Code Duplication |
public function add($rule, $action = null) |
|
|
|
|
54
|
|
|
{ |
55
|
5 |
|
$route = new Route(); |
56
|
5 |
|
$route->set($rule, $action); |
|
|
|
|
57
|
5 |
|
$this->routes[] = $route; |
58
|
|
|
|
59
|
|
|
// Set as default route |
60
|
5 |
|
if ($rule == "*") { |
61
|
1 |
|
$this->defaultRoute = $route; |
62
|
1 |
|
} |
63
|
|
|
|
64
|
5 |
|
return $route; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
|
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Add a default route to the router, to use when all other routes fail. |
71
|
|
|
* |
72
|
|
|
* @param mixed $action null, string or callable to implement a controller for the route |
73
|
|
|
* |
74
|
|
|
* @return class as new route |
75
|
|
|
*/ |
76
|
1 |
View Code Duplication |
public function addDefault($action) |
|
|
|
|
77
|
|
|
{ |
78
|
1 |
|
$route = new Route(); |
79
|
1 |
|
$route->set("*", $action); |
|
|
|
|
80
|
1 |
|
$this->routes[] = $route; |
81
|
1 |
|
$this->defaultRoute = $route; |
82
|
|
|
|
83
|
1 |
|
return $route; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
|
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Add an internal (not exposed to url-matching) route to the router. |
90
|
|
|
* |
91
|
|
|
* @param string $rule for this route |
92
|
|
|
* @param mixed $action null, string or callable to implement a controller for the route |
93
|
|
|
* |
94
|
|
|
* @return class as new route |
95
|
|
|
*/ |
96
|
3 |
|
public function addInternal($rule, $action = null) |
97
|
|
|
{ |
98
|
3 |
|
$route = new Route(); |
99
|
3 |
|
$route->set($rule, $action); |
|
|
|
|
100
|
3 |
|
$this->internalRoutes[$rule] = $route; |
101
|
3 |
|
return $route; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
|
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Add an internal (not exposed to url-matching) route to the router. |
108
|
|
|
* |
109
|
|
|
* @param string $rule for this route |
110
|
|
|
* @param mixed $action null, string or callable to implement a |
|
|
|
|
111
|
|
|
* controller for the route |
112
|
|
|
* |
113
|
|
|
* @return void |
114
|
|
|
*/ |
115
|
4 |
|
public function handleInternal($rule) |
116
|
|
|
{ |
117
|
4 |
|
if (!isset($this->internalRoutes[$rule])) { |
118
|
1 |
|
throw new NotFoundException("No internal route to handle: " . $rule); |
119
|
|
|
} |
120
|
3 |
|
$route = $this->internalRoutes[$rule]; |
121
|
3 |
|
$route->handle(); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
|
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Handle the routes and match them towards the request, dispatch them |
128
|
|
|
* when a match is made. Each route handler may throw exceptions that |
129
|
|
|
* may redirect to an internal route for error handling. |
130
|
|
|
* |
131
|
|
|
* @param string $query the query/route to match a handler for. |
132
|
|
|
* |
133
|
|
|
* @return mixed content returned from route. |
134
|
|
|
*/ |
135
|
6 |
|
public function handle($query) |
136
|
|
|
{ |
137
|
|
|
try { |
138
|
|
|
// Match predefined routes |
139
|
6 |
|
foreach ($this->routes as $route) { |
140
|
5 |
|
if ($route->match($query)) { |
141
|
5 |
|
return $route->handle(); |
142
|
|
|
} |
143
|
2 |
|
} |
144
|
|
|
|
145
|
|
|
// Use the "catch-all" route |
146
|
1 |
|
if ($this->defaultRoute) { |
147
|
|
|
return $this->defaultRoute->handle(); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
// No route was matched |
151
|
1 |
|
$this->handleInternal("404"); |
152
|
4 |
|
} catch (ForbiddenException $e) { |
153
|
1 |
|
$this->handleInternal("403"); |
154
|
3 |
|
} catch (NotFoundException $e) { |
155
|
2 |
|
$this->handleInternal("404"); |
156
|
1 |
|
} catch (InternalErrorException $e) { |
157
|
1 |
|
$this->handleInternal("500"); |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
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.