root/trunk/system/libraries/Router.php

Revision 2936, 7.3 kB (checked in by Shadowhand, 1 week ago)

How did that happen? Thanks zextra!

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