1 <?php
2 3 4 5 6 7
8
9 namespace Cross\Core;
10
11 use Cross\I\RouterInterface;
12 use Cross\Exception\FrontException;
13 use Cross\Exception\CoreException;
14 use Cross\Http\Request;
15
16 17 18 19 20
21 class Router implements RouterInterface
22 {
23 24 25 26 27
28 private $action;
29
30 31 32 33 34
35 private $controller;
36
37 38 39 40 41
42 private $params = array();
43
44 45 46
47 private $uriRequest;
48
49 50 51
52 private $originUriRequest;
53
54 55 56
57 private $config;
58
59 60 61
62 private $delegate;
63
64 65 66
67 private $defaultRouter = array();
68
69 70 71
72 const DEFAULT_ACTION = 'index';
73
74 75 76 77
78 function __construct(Delegate &$delegate)
79 {
80 $this->delegate = $delegate;
81 $this->config = $delegate->getConfig();
82 }
83
84 85 86 87 88 89 90
91 public function getRouter()
92 {
93 $rs = $this->getUriRequest('', $url_config);
94 if (!empty($rs)) {
95 $request = $this->parseRequestString($rs, $url_config);
96 $closure = $this->delegate->getClosureContainer();
97 if ($closure->has('router')) {
98 $closure->run('router', array($request, $this));
99 }
100
101 if (empty($this->controller) || empty($this->action)) {
102 $this->parseRouter($request, $url_config);
103 }
104 } else {
105 $router = $this->parseDefaultRouter($url_config['*']);
106 $this->setController($router[0]);
107 $this->setAction($router[1]);
108
109 $params = $this->parseParams(array(), $url_config);
110 $this->setParams($params);
111 }
112
113 return $this;
114 }
115
116 117 118 119 120
121 function useDefaulterRouter()
122 {
123 $router = $this->getDefaultRouter();
124 $this->setController($router[0]);
125 $this->setAction($router[1]);
126 }
127
128 129 130 131 132 133
134 function getDefaultRouter()
135 {
136 if (empty($this->defaultRouter)) {
137 $url_config = $this->config->get('url');
138 $this->parseDefaultRouter($url_config['*']);
139 }
140
141 return $this->defaultRouter;
142 }
143
144 145 146 147 148
149 public function getController()
150 {
151 return $this->controller;
152 }
153
154 155 156 157 158
159 public function getAction()
160 {
161 return $this->action;
162 }
163
164 165 166 167 168
169 public function getParams()
170 {
171 return $this->params;
172 }
173
174 175 176 177 178 179 180 181 182 183
184 public function getUriRequest($prefix = '/', &$url_config = array(), $clear_ampersand = true, $convert_html_entities = true)
185 {
186 $url_config = $this->config->get('url');
187 if (!empty($this->uriRequest)) {
188 return $this->uriRequest;
189 }
190
191 switch ($url_config['type']) {
192 case 1:
193 case 3:
194 $request = Request::getInstance()->getQueryString();
195 $this->originUriRequest = $request;
196
197 if ($clear_ampersand) {
198
199 $request_uri = Request::getInstance()->getRequestURI();
200 if ($url_config['rewrite'] && $request_uri && false !== strpos($request_uri, '?')) {
201 $query_string = parse_url($request_uri, PHP_URL_QUERY);
202 parse_str($query_string, $addition_params);
203 $_GET += $addition_params;
204
205 if ($query_string == $request) {
206 $request = '';
207 }
208 }
209
210 if (false !== ($l = strpos($request, '&'))) {
211 $request = substr($request, 0, $l);
212 }
213
214 if (false !== strpos($request, '=')) {
215 $request = '';
216 }
217
218 if (isset($request[0]) && $request[0] != '&') {
219 array_shift($_GET);
220 }
221 }
222 break;
223
224 case 2:
225 case 4:
226 case 5:
227 $request = Request::getInstance()->getPathInfo();
228 $this->originUriRequest = $request;
229 break;
230
231 default:
232 throw new CoreException('Not support URL type!');
233 }
234
235 if ($request) {
236 $request = urldecode(ltrim($request, '/'));
237 if ($convert_html_entities) {
238 $request = htmlspecialchars($request, ENT_QUOTES);
239 }
240 }
241
242 return $prefix . $request;
243 }
244
245 246 247 248 249 250 251
252 function parseRouter(array $request, array $url_config)
253 {
254 $combine_alias_key = '';
255 $ori_controller = $controller = array_shift($request);
256 if (isset($request[0])) {
257 $combine_alias_key = $controller . ':' . $request[0];
258 }
259
260 $controller_alias = '';
261 $router_config = $this->config->get('router');
262 if (isset($router_config [$combine_alias_key])) {
263 array_shift($request);
264 $controller_alias = $router_config [$combine_alias_key];
265 } elseif (isset($router_config [$controller])) {
266 $controller_alias = $router_config [$controller];
267 }
268
269 if (!empty($controller_alias)) {
270 if (false !== strpos($controller_alias, ':')) {
271 list($controller, $action) = explode(':', $controller_alias);
272 } else {
273 $controller = $controller_alias;
274 }
275 }
276
277 $ori_action = '';
278 if (!isset($action)) {
279 if (isset($request[0]) && !empty($request[0])) {
280 $ori_action = $action = array_shift($request);
281 } else {
282 $action = self::DEFAULT_ACTION;
283 }
284 }
285
286 $addition_params = array();
287 $params = $this->parseParams($request, $url_config, $addition_params);
288 $this->config->set('ori_router', array(
289 'request' => $this->originUriRequest,
290 'addition_params' => $addition_params,
291 'controller' => $ori_controller,
292 'action' => $ori_action,
293 'params' => $request,
294 ));
295
296 $this->setController($controller);
297 $this->setAction($action);
298 $this->setParams($params);
299 }
300
301 302 303 304 305
306 function setController($controller)
307 {
308 $this->controller = $controller;
309 }
310
311 312 313 314 315
316 function setAction($action)
317 {
318 $this->action = $action;
319 }
320
321 322 323 324 325
326 function setParams($params)
327 {
328 $this->params = $params;
329 }
330
331 332 333 334 335 336 337 338
339 private static function parseRequestString($query_string, $url_config)
340 {
341 $url_suffix = &$url_config['ext'];
342 if (isset($url_suffix[0]) && ($url_suffix_length = strlen(trim($url_suffix))) > 0) {
343 if (0 === strcasecmp($url_suffix, substr($query_string, -$url_suffix_length))) {
344 $query_string = substr($query_string, 0, -$url_suffix_length);
345 } else {
346 throw new FrontException('Page not found !');
347 }
348 }
349
350 $url_dot = &$url_config['dot'];
351 if ($url_dot && false !== strpos($query_string, $url_dot)) {
352 $router_params = explode($url_dot, $query_string);
353 $end_params = array_pop($router_params);
354 } else {
355 $router_params = array();
356 $end_params = $query_string;
357 }
358
359 $params_dot = &$url_config['params_dot'];
360 if ($params_dot && $params_dot != $url_dot && false !== strpos($end_params, $params_dot)) {
361 $params_data = explode($params_dot, $end_params);
362 foreach ($params_data as $p) {
363 $router_params[] = $p;
364 }
365 } else {
366 $router_params[] = $end_params;
367 }
368
369 return $router_params;
370 }
371
372 373 374 375 376 377 378
379 private function parseDefaultRouter($default_router)
380 {
381 if (empty($default_router)) {
382 throw new CoreException('Undefined default router!');
383 }
384
385 if (empty($this->defaultRouter)) {
386 if (false !== strpos($default_router, ':')) {
387 list($controller, $action) = explode(':', $default_router);
388 } else {
389 $controller = $default_router;
390 $action = self::DEFAULT_ACTION;
391 }
392
393 $this->defaultRouter = array($controller, $action);
394 }
395
396 return $this->defaultRouter;
397 }
398
399 400 401 402 403 404 405 406
407 private function parseParams(array $params, array $url_config, array &$addition_params = array())
408 {
409 $addition_params = $_GET;
410 if (empty($params)) {
411 $params = $addition_params;
412 } elseif (is_array($params) && !empty($addition_params)) {
413 if ($url_config['type'] == 2) {
414 $params = array_merge($params, $addition_params);
415 } else {
416 $params += $addition_params;
417 }
418 }
419
420 return $params;
421 }
422 }
423
424