Route and Results buttons updated.
[speedfreak] / Server / system / libraries / Router.php
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3  * Router
4  *
5  * $Id: Router.php 4391 2009-06-04 03:10:12Z zombor $
6  *
7  * @package    Core
8  * @author     Kohana Team
9  * @copyright  (c) 2007-2008 Kohana Team
10  * @license    http://kohanaphp.com/license.html
11  */
12 class Router_Core {
13
14         protected static $routes;
15
16         public static $current_uri  = '';
17         public static $query_string = '';
18         public static $complete_uri = '';
19         public static $routed_uri   = '';
20         public static $url_suffix   = '';
21
22         public static $segments;
23         public static $rsegments;
24
25         public static $controller;
26         public static $controller_path;
27
28         public static $method    = 'index';
29         public static $arguments = array();
30
31         /**
32          * Router setup routine. Automatically called during Kohana setup process.
33          *
34          * @return  void
35          */
36         public static function setup()
37         {
38                 if ( ! empty($_SERVER['QUERY_STRING']))
39                 {
40                         // Set the query string to the current query string
41                         Router::$query_string = '?'.trim($_SERVER['QUERY_STRING'], '&/');
42                 }
43
44                 if (Router::$routes === NULL)
45                 {
46                         // Load routes
47                         Router::$routes = Kohana::config('routes');
48                 }
49
50                 // Default route status
51                 $default_route = FALSE;
52
53                 if (Router::$current_uri === '')
54                 {
55                         // Make sure the default route is set
56                         if ( ! isset(Router::$routes['_default']))
57                                 throw new Kohana_Exception('core.no_default_route');
58
59                         // Use the default route when no segments exist
60                         Router::$current_uri = Router::$routes['_default'];
61
62                         // Default route is in use
63                         $default_route = TRUE;
64                 }
65
66                 // Make sure the URL is not tainted with HTML characters
67                 Router::$current_uri = html::specialchars(Router::$current_uri, FALSE);
68
69                 // Remove all dot-paths from the URI, they are not valid
70                 Router::$current_uri = preg_replace('#\.[\s./]*/#', '', Router::$current_uri);
71
72                 // At this point segments, rsegments, and current URI are all the same
73                 Router::$segments = Router::$rsegments = Router::$current_uri = trim(Router::$current_uri, '/');
74
75                 // Set the complete URI
76                 Router::$complete_uri = Router::$current_uri.Router::$query_string;
77
78                 // Explode the segments by slashes
79                 Router::$segments = ($default_route === TRUE OR Router::$segments === '') ? array() : explode('/', Router::$segments);
80
81                 if ($default_route === FALSE AND count(Router::$routes) > 1)
82                 {
83                         // Custom routing
84                         Router::$rsegments = Router::routed_uri(Router::$current_uri);
85                 }
86
87                 // The routed URI is now complete
88                 Router::$routed_uri = Router::$rsegments;
89
90                 // Routed segments will never be empty
91                 Router::$rsegments = explode('/', Router::$rsegments);
92
93                 // Prepare to find the controller
94                 $controller_path = '';
95                 $method_segment  = NULL;
96
97                 // Paths to search
98                 $paths = Kohana::include_paths();
99
100                 foreach (Router::$rsegments as $key => $segment)
101                 {
102                         // Add the segment to the search path
103                         $controller_path .= $segment;
104
105                         $found = FALSE;
106                         foreach ($paths as $dir)
107                         {
108                                 // Search within controllers only
109                                 $dir .= 'controllers/';
110
111                                 if (is_dir($dir.$controller_path) OR is_file($dir.$controller_path.EXT))
112                                 {
113                                         // Valid path
114                                         $found = TRUE;
115
116                                         // The controller must be a file that exists with the search path
117                                         if ($c = str_replace('\\', '/', realpath($dir.$controller_path.EXT))
118                                             AND is_file($c) AND strpos($c, $dir) === 0)
119                                         {
120                                                 // Set controller name
121                                                 Router::$controller = $segment;
122
123                                                 // Change controller path
124                                                 Router::$controller_path = $c;
125
126                                                 // Set the method segment
127                                                 $method_segment = $key + 1;
128
129                                                 // Stop searching
130                                                 break;
131                                         }
132                                 }
133                         }
134
135                         if ($found === FALSE)
136                         {
137                                 // Maximum depth has been reached, stop searching
138                                 break;
139                         }
140
141                         // Add another slash
142                         $controller_path .= '/';
143                 }
144
145                 if ($method_segment !== NULL AND isset(Router::$rsegments[$method_segment]))
146                 {
147                         // Set method
148                         Router::$method = Router::$rsegments[$method_segment];
149
150                         if (isset(Router::$rsegments[$method_segment + 1]))
151                         {
152                                 // Set arguments
153                                 Router::$arguments = array_slice(Router::$rsegments, $method_segment + 1);
154                         }
155                 }
156
157                 // Last chance to set routing before a 404 is triggered
158                 Event::run('system.post_routing');
159
160                 if (Router::$controller === NULL)
161                 {
162                         // No controller was found, so no page can be rendered
163                         Event::run('system.404');
164                 }
165         }
166
167         /**
168          * Attempts to determine the current URI using CLI, GET, PATH_INFO, ORIG_PATH_INFO, or PHP_SELF.
169          *
170          * @return  void
171          */
172         public static function find_uri()
173         {
174                 if (PHP_SAPI === 'cli')
175                 {
176                         // Command line requires a bit of hacking
177                         if (isset($_SERVER['argv'][1]))
178                         {
179                                 Router::$current_uri = $_SERVER['argv'][1];
180
181                                 // Remove GET string from segments
182                                 if (($query = strpos(Router::$current_uri, '?')) !== FALSE)
183                                 {
184                                         list (Router::$current_uri, $query) = explode('?', Router::$current_uri, 2);
185
186                                         // Parse the query string into $_GET
187                                         parse_str($query, $_GET);
188
189                                         // Convert $_GET to UTF-8
190                                         $_GET = utf8::clean($_GET);
191                                 }
192                         }
193                 }
194                 elseif (isset($_GET['kohana_uri']))
195                 {
196                         // Use the URI defined in the query string
197                         Router::$current_uri = $_GET['kohana_uri'];
198
199                         // Remove the URI from $_GET
200                         unset($_GET['kohana_uri']);
201
202                         // Remove the URI from $_SERVER['QUERY_STRING']
203                         $_SERVER['QUERY_STRING'] = preg_replace('~\bkohana_uri\b[^&]*+&?~', '', $_SERVER['QUERY_STRING']);
204                 }
205                 elseif (isset($_SERVER['PATH_INFO']) AND $_SERVER['PATH_INFO'])
206                 {
207                         Router::$current_uri = $_SERVER['PATH_INFO'];
208                 }
209                 elseif (isset($_SERVER['ORIG_PATH_INFO']) AND $_SERVER['ORIG_PATH_INFO'])
210                 {
211                         Router::$current_uri = $_SERVER['ORIG_PATH_INFO'];
212                 }
213                 elseif (isset($_SERVER['PHP_SELF']) AND $_SERVER['PHP_SELF'])
214                 {
215                         Router::$current_uri = $_SERVER['PHP_SELF'];
216                 }
217                 
218                 if (($strpos_fc = strpos(Router::$current_uri, KOHANA)) !== FALSE)
219                 {
220                         // Remove the front controller from the current uri
221                         Router::$current_uri = (string) substr(Router::$current_uri, $strpos_fc + strlen(KOHANA));
222                 }
223                 
224                 // Remove slashes from the start and end of the URI
225                 Router::$current_uri = trim(Router::$current_uri, '/');
226                 
227                 if (Router::$current_uri !== '')
228                 {
229                         if ($suffix = Kohana::config('core.url_suffix') AND strpos(Router::$current_uri, $suffix) !== FALSE)
230                         {
231                                 // Remove the URL suffix
232                                 Router::$current_uri = preg_replace('#'.preg_quote($suffix).'$#u', '', Router::$current_uri);
233
234                                 // Set the URL suffix
235                                 Router::$url_suffix = $suffix;
236                         }
237
238                         // Reduce multiple slashes into single slashes
239                         Router::$current_uri = preg_replace('#//+#', '/', Router::$current_uri);
240                 }
241         }
242
243         /**
244          * Generates routed URI from given URI.
245          *
246          * @param  string  URI to convert
247          * @return string  Routed uri
248          */
249         public static function routed_uri($uri)
250         {
251                 if (Router::$routes === NULL)
252                 {
253                         // Load routes
254                         Router::$routes = Kohana::config('routes');
255                 }
256
257                 // Prepare variables
258                 $routed_uri = $uri = trim($uri, '/');
259
260                 if (isset(Router::$routes[$uri]))
261                 {
262                         // Literal match, no need for regex
263                         $routed_uri = Router::$routes[$uri];
264                 }
265                 else
266                 {
267                         // Loop through the routes and see if anything matches
268                         foreach (Router::$routes as $key => $val)
269                         {
270                                 if ($key === '_default') continue;
271
272                                 // Trim slashes
273                                 $key = trim($key, '/');
274                                 $val = trim($val, '/');
275
276                                 if (preg_match('#^'.$key.'$#u', $uri))
277                                 {
278                                         if (strpos($val, '$') !== FALSE)
279                                         {
280                                                 // Use regex routing
281                                                 $routed_uri = preg_replace('#^'.$key.'$#u', $val, $uri);
282                                         }
283                                         else
284                                         {
285                                                 // Standard routing
286                                                 $routed_uri = $val;
287                                         }
288
289                                         // A valid route has been found
290                                         break;
291                                 }
292                         }
293                 }
294
295                 if (isset(Router::$routes[$routed_uri]))
296                 {
297                         // Check for double routing (without regex)
298                         $routed_uri = Router::$routes[$routed_uri];
299                 }
300
301                 return trim($routed_uri, '/');
302         }
303
304 } // End Router