1
|
|
|
<?php |
2
|
|
|
namespace Suricate; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
// TODO : handle closure |
6
|
|
|
**/ |
7
|
|
|
class Router extends Service |
8
|
|
|
{ |
9
|
|
|
private $requestUri; |
10
|
|
|
private $baseUri; |
11
|
|
|
private $routes; |
12
|
|
|
private $response; |
13
|
|
|
private $appMiddlewares = array( |
14
|
|
|
'\Suricate\Middleware\CheckMaintenance', |
15
|
|
|
); |
16
|
|
|
|
17
|
|
|
|
18
|
|
|
|
19
|
1 |
|
public function __construct() |
20
|
|
|
{ |
21
|
1 |
|
$this->routes = array(); |
22
|
1 |
|
$this->response = Suricate::Response(); |
23
|
1 |
|
$this->parseRequest(); |
24
|
|
|
|
25
|
|
|
// Get app base URI, to transform real path before passing to route |
26
|
1 |
|
$this->baseUri = Suricate::App()->getParameter('base_uri'); |
27
|
1 |
|
} |
28
|
|
|
|
29
|
|
|
public function configure($parameters = array()) |
30
|
|
|
{ |
31
|
|
|
|
32
|
|
|
foreach ($parameters as $routeName => $routeData) { |
33
|
|
|
if (isset($routeData['isRest']) && $routeData['isRest']) { |
34
|
|
|
$this->buildRestRoutes($routeName, $routeData); |
35
|
|
|
} else { |
36
|
|
|
$this->buildRoute($routeName, $routeData); |
37
|
|
|
} |
38
|
|
|
} |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
private function buildRoute($routeName, $routeData) { |
42
|
|
|
if (isset($routeData['target'])) { |
43
|
|
|
$routeTarget = explode('::', $routeData['target']); |
44
|
|
|
} else { |
45
|
|
|
$routeTarget = null; |
46
|
|
|
} |
47
|
|
|
$routeMethod = isset($routeData['method']) ? $routeData['method'] : 'any'; |
48
|
|
|
$parameters = isset($routeData['parameters']) ? $routeData['parameters'] : array(); |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
if (isset($routeData['middleware'])) { |
52
|
|
|
$middleware = (array)$routeData['middleware']; |
53
|
|
|
} else { |
54
|
|
|
$middleware = array(); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
$this->addRoute( |
58
|
|
|
$routeName, |
59
|
|
|
$routeMethod, |
60
|
|
|
$routeData['path'], |
61
|
|
|
$routeTarget, |
62
|
|
|
$parameters, |
63
|
|
|
$middleware |
64
|
|
|
); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
private function buildRestRoutes($routeBaseName, $routeBaseData) |
68
|
|
|
{ |
69
|
|
|
// If route has a parameters array defined, take the first defined |
70
|
|
|
// argument as ":id" parameter, and use key as parameter name |
71
|
|
|
// otherwise, default to id => [0-9]* |
|
|
|
|
72
|
|
|
if (isset($routeBaseData['parameters']) |
73
|
|
|
&& is_array($routeBaseData['parameters']) |
74
|
|
|
&& count($routeBaseData['parameters']) > 1) { |
75
|
|
|
reset($routeBaseData['parameters']); |
76
|
|
|
$primaryParameterName = key($routeBaseData['parameters']); |
77
|
|
|
|
78
|
|
|
$routeParameters = dataGet($routeBaseData, 'parameters', []); |
79
|
|
|
} else { |
80
|
|
|
$primaryParameterName = 'id'; |
81
|
|
|
$primaryParameterPattern = '[0-9]*'; |
82
|
|
|
|
83
|
|
|
$routeParameters = array_merge( |
84
|
|
|
[$primaryParameterName => $primaryParameterPattern], |
85
|
|
|
dataGet($routeBaseData, 'parameters', []) |
86
|
|
|
); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
$resources = [ |
90
|
|
|
'index' => ['method' => 'GET', 'append' => ''], |
91
|
|
|
'create' => ['method' => 'GET', 'append' => '/create'], |
92
|
|
|
'store' => ['method' => 'POST', 'append' => ''], |
93
|
|
|
'show' => ['method' => 'GET', 'append' => '/:' . $primaryParameterName], |
94
|
|
|
'edit' => ['method' => 'GET', 'append' => '/:' . $primaryParameterName . '/edit'], |
95
|
|
|
'update' => ['method' => 'PUT', 'append' => '/:' . $primaryParameterName], |
96
|
|
|
'destroy' => ['method' => 'DELETE', 'append' => '/:' . $primaryParameterName], |
97
|
|
|
]; |
98
|
|
|
|
99
|
|
|
foreach ($resources as $name => $definition) { |
100
|
|
|
$routeName = $routeBaseName . '.' . $name; |
101
|
|
|
$routeData = $routeBaseData; |
102
|
|
|
$routeData['method'] = $definition['method']; |
103
|
|
|
$routeData['path'] .= $definition['append']; |
104
|
|
|
$routeData['target'] .= '::' . $name; |
105
|
|
|
$routeData['parameters'] = $routeParameters; |
106
|
|
|
|
107
|
|
|
$this->buildRoute($routeName, $routeData); |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
|
111
|
1 |
|
private function parseRequest() |
112
|
|
|
{ |
113
|
1 |
|
$this->requestUri = Suricate::Request()->getRequestUri(); |
114
|
1 |
|
$this->response->setRequestUri($this->requestUri); |
115
|
1 |
|
} |
116
|
|
|
|
117
|
|
|
public function addRoute($routeName, $routeMethod, $routePath, $routeTarget, $parametersDefinitions, $middleware = null) |
118
|
|
|
{ |
119
|
|
|
$computedRoutePath = ($this->baseUri != '/') ? $this->baseUri . $routePath : $routePath; |
120
|
|
|
$this->routes[$routeName] = new Route( |
121
|
|
|
$routeName, |
122
|
|
|
$routeMethod, |
123
|
|
|
$computedRoutePath, |
124
|
|
|
Suricate::Request(), |
125
|
|
|
$routeTarget, |
126
|
|
|
$parametersDefinitions, |
127
|
|
|
$middleware |
128
|
|
|
); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
public function addMiddleware($middleware) |
132
|
|
|
{ |
133
|
|
|
array_unshift($this->appMiddlewares, $middleware); |
134
|
|
|
|
135
|
|
|
return $this; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
public function getMiddlewares() |
139
|
|
|
{ |
140
|
|
|
return $this->appMiddlewares; |
141
|
|
|
} |
142
|
|
|
|
143
|
1 |
|
public function getResponse() |
144
|
|
|
{ |
145
|
1 |
|
return $this->response; |
146
|
|
|
} |
147
|
|
|
/** |
148
|
|
|
* Loop through each defined routes, to find good one |
149
|
|
|
* @return null |
150
|
|
|
*/ |
151
|
|
|
public function doRouting() |
152
|
|
|
{ |
153
|
|
|
$hasRoute = false; |
154
|
|
|
|
155
|
|
|
foreach ($this->routes as $route) { |
156
|
|
|
if ($route->isMatched) { |
157
|
|
|
$hasRoute = true; |
158
|
|
|
|
159
|
|
|
Suricate::Logger()->debug('Route "' . $route->getPath() . '" matched, target: ' . json_encode($route->target)); |
160
|
|
|
$result = $route->dispatch($this->response, $this->appMiddlewares); |
161
|
|
|
if ($result === false) { |
162
|
|
|
break; |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
// No route matched |
168
|
|
|
if (!$hasRoute) { |
169
|
|
|
Suricate::Logger()->debug('No route found'); |
170
|
|
|
app()->abort('404'); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
$this->response->write(); |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.