blob: d9dd6dd3f87204e12b645c955b2b6cd3e1e24f07 [file] [log] [blame]
Derek Allarda72b60d2007-01-31 23:56:11 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
Derek Allardd2df9bc2007-04-15 17:41:17 +00003 * CodeIgniter
Derek Allarda72b60d2007-01-31 23:56:11 +00004 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
Derek Allard3d879d52008-01-18 19:41:32 +00008 * @author ExpressionEngine Dev Team
Derek Allardd2df9bc2007-04-15 17:41:17 +00009 * @copyright Copyright (c) 2006, EllisLab, Inc.
Derek Jones7a9193a2008-01-21 18:39:20 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
Derek Allarda72b60d2007-01-31 23:56:11 +000012 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Router Class
20 *
21 * Parses URIs and determines routing
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
Derek Allard3d879d52008-01-18 19:41:32 +000025 * @author ExpressionEngine Dev Team
Derek Allarda72b60d2007-01-31 23:56:11 +000026 * @category Libraries
Derek Jones7a9193a2008-01-21 18:39:20 +000027 * @link http://codeigniter.com/user_guide/general/routing.html
Derek Allarda72b60d2007-01-31 23:56:11 +000028 */
29class CI_Router {
30
Rick Ellis30b40152007-07-20 00:01:13 +000031 var $config;
Derek Allarda72b60d2007-01-31 23:56:11 +000032 var $routes = array();
33 var $error_routes = array();
34 var $class = '';
35 var $method = 'index';
36 var $directory = '';
37 var $uri_protocol = 'auto';
38 var $default_controller;
39 var $scaffolding_request = FALSE; // Must be set to FALSE
40
41 /**
42 * Constructor
43 *
44 * Runs the route mapping function.
45 */
46 function CI_Router()
47 {
48 $this->config =& load_class('Config');
Rick Ellis30b40152007-07-20 00:01:13 +000049 $this->uri =& load_class('URI');
50 $this->_set_routing();
Derek Allarda72b60d2007-01-31 23:56:11 +000051 log_message('debug', "Router Class Initialized");
52 }
53
54 // --------------------------------------------------------------------
55
56 /**
57 * Set the route mapping
58 *
59 * This function determines what should be served based on the URI request,
60 * as well as any "routes" that have been set in the routing config file.
61 *
62 * @access private
63 * @return void
64 */
Rick Ellis30b40152007-07-20 00:01:13 +000065 function _set_routing()
Derek Allarda72b60d2007-01-31 23:56:11 +000066 {
67 // Are query strings enabled in the config file?
68 // If so, we're done since segment based URIs are not used with query strings.
69 if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
70 {
Rick Ellis30b40152007-07-20 00:01:13 +000071 $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
Derek Allarda72b60d2007-01-31 23:56:11 +000072
73 if (isset($_GET[$this->config->item('function_trigger')]))
74 {
Rick Ellis30b40152007-07-20 00:01:13 +000075 $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
Derek Allarda72b60d2007-01-31 23:56:11 +000076 }
77
78 return;
79 }
80
81 // Load the routes.php file.
82 @include(APPPATH.'config/routes'.EXT);
83 $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
84 unset($route);
85
86 // Set the default controller so we can display it in the event
87 // the URI doesn't correlated to a valid controller.
88 $this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);
89
90 // Fetch the complete URI string
Rick Ellis30b40152007-07-20 00:01:13 +000091 $this->uri->_fetch_uri_string();
Derek Allarda72b60d2007-01-31 23:56:11 +000092
93 // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
Rick Ellis30b40152007-07-20 00:01:13 +000094 if ($this->uri->uri_string == '')
Derek Allarda72b60d2007-01-31 23:56:11 +000095 {
96 if ($this->default_controller === FALSE)
97 {
98 show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
99 }
100
101 $this->set_class($this->default_controller);
102 $this->set_method('index');
Derek Jonesd45379e2008-01-30 03:47:03 +0000103 $this->_set_request(array($this->default_controller, 'index'));
104
Derek Jones881a79e2008-02-13 03:28:18 +0000105 // re-index the routed segments array so it starts with 1 rather than 0
106 $this->uri->_reindex_segments();
107
Derek Allarda72b60d2007-01-31 23:56:11 +0000108 log_message('debug', "No URI present. Default controller set.");
109 return;
110 }
111 unset($this->routes['default_controller']);
112
Rick Ellis30b40152007-07-20 00:01:13 +0000113 // Do we need to remove the URL suffix?
114 $this->uri->_remove_url_suffix();
Derek Allarda72b60d2007-01-31 23:56:11 +0000115
Rick Ellis30b40152007-07-20 00:01:13 +0000116 // Compile the segments into an array
117 $this->uri->_explode_segments();
Derek Allarda72b60d2007-01-31 23:56:11 +0000118
119 // Parse any custom routing that may exist
120 $this->_parse_routes();
121
122 // Re-index the segment array so that it starts with 1 rather than 0
Rick Ellis30b40152007-07-20 00:01:13 +0000123 $this->uri->_reindex_segments();
Derek Allarda72b60d2007-01-31 23:56:11 +0000124 }
125
126 // --------------------------------------------------------------------
127
128 /**
Rick Ellis30b40152007-07-20 00:01:13 +0000129 * Set the Route
Derek Allarda72b60d2007-01-31 23:56:11 +0000130 *
131 * This function takes an array of URI segments as
Rick Ellis30b40152007-07-20 00:01:13 +0000132 * input, and sets the current class/method
Derek Allarda72b60d2007-01-31 23:56:11 +0000133 *
134 * @access private
135 * @param array
136 * @param bool
137 * @return void
138 */
Rick Ellis30b40152007-07-20 00:01:13 +0000139 function _set_request($segments = array())
Derek Allarda72b60d2007-01-31 23:56:11 +0000140 {
Rick Ellis30b40152007-07-20 00:01:13 +0000141 $segments = $this->_validate_request($segments);
Derek Allarda72b60d2007-01-31 23:56:11 +0000142
143 if (count($segments) == 0)
144 {
145 return;
146 }
147
148 $this->set_class($segments[0]);
149
150 if (isset($segments[1]))
151 {
152 // A scaffolding request. No funny business with the URL
153 if ($this->routes['scaffolding_trigger'] == $segments[1] AND $segments[1] != '_ci_scaffolding')
154 {
155 $this->scaffolding_request = TRUE;
156 unset($this->routes['scaffolding_trigger']);
157 }
158 else
159 {
160 // A standard method request
161 $this->set_method($segments[1]);
162 }
163 }
Derek Jonesc38c7032008-01-30 15:38:56 +0000164 else
165 {
166 // This lets the "routed" segment array identify that the default
167 // index method is being used.
168 $segments[1] = 'index';
169 }
Derek Allarda72b60d2007-01-31 23:56:11 +0000170
171 // Update our "routed" segment array to contain the segments.
172 // Note: If there is no custom routing, this array will be
Rick Ellis30b40152007-07-20 00:01:13 +0000173 // identical to $this->uri->segments
174 $this->uri->rsegments = $segments;
Derek Allarda72b60d2007-01-31 23:56:11 +0000175 }
176
177 // --------------------------------------------------------------------
178
179 /**
180 * Validates the supplied segments. Attempts to determine the path to
181 * the controller.
182 *
183 * @access private
184 * @param array
185 * @return array
186 */
Rick Ellis30b40152007-07-20 00:01:13 +0000187 function _validate_request($segments)
Derek Allarda72b60d2007-01-31 23:56:11 +0000188 {
189 // Does the requested controller exist in the root folder?
190 if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
191 {
192 return $segments;
193 }
194
195 // Is the controller in a sub-folder?
196 if (is_dir(APPPATH.'controllers/'.$segments[0]))
197 {
198 // Set the directory and remove it from the segment array
199 $this->set_directory($segments[0]);
200 $segments = array_slice($segments, 1);
201
202 if (count($segments) > 0)
203 {
204 // Does the requested controller exist in the sub-folder?
205 if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
206 {
Derek Jones8a160772008-02-27 05:19:50 +0000207 show_404($this->fetch_directory().$segments[0]);
Derek Allarda72b60d2007-01-31 23:56:11 +0000208 }
209 }
210 else
211 {
212 $this->set_class($this->default_controller);
213 $this->set_method('index');
214
215 // Does the default controller exist in the sub-folder?
216 if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
217 {
218 $this->directory = '';
219 return array();
220 }
221
222 }
223
224 return $segments;
225 }
226
227 // Can't find the requested controller...
Derek Jones8a160772008-02-27 05:19:50 +0000228 show_404($segments[0]);
Derek Allarda72b60d2007-01-31 23:56:11 +0000229 }
Derek Allarda72b60d2007-01-31 23:56:11 +0000230
Derek Allarda72b60d2007-01-31 23:56:11 +0000231 // --------------------------------------------------------------------
232
233 /**
234 * Parse Routes
235 *
236 * This function matches any routes that may exist in
237 * the config/routes.php file against the URI to
238 * determine if the class/method need to be remapped.
239 *
240 * @access private
241 * @return void
242 */
243 function _parse_routes()
244 {
245 // Do we even have any custom routing to deal with?
Derek Allard445b24d2007-04-24 12:48:19 +0000246 // There is a default scaffolding trigger, so we'll look just for 1
247 if (count($this->routes) == 1)
Derek Allarda72b60d2007-01-31 23:56:11 +0000248 {
Rick Ellis30b40152007-07-20 00:01:13 +0000249 $this->_set_request($this->uri->segments);
Derek Allarda72b60d2007-01-31 23:56:11 +0000250 return;
251 }
Derek Allard445b24d2007-04-24 12:48:19 +0000252
Derek Allarda72b60d2007-01-31 23:56:11 +0000253 // Turn the segment array into a URI string
Rick Ellis30b40152007-07-20 00:01:13 +0000254 $uri = implode('/', $this->uri->segments);
255 $num = count($this->uri->segments);
Derek Allarda72b60d2007-01-31 23:56:11 +0000256
257 // Is there a literal match? If so we're done
258 if (isset($this->routes[$uri]))
259 {
Rick Ellis30b40152007-07-20 00:01:13 +0000260 $this->_set_request(explode('/', $this->routes[$uri]));
Derek Allarda72b60d2007-01-31 23:56:11 +0000261 return;
262 }
263
264 // Loop through the route array looking for wild-cards
Rick Ellis183fe842007-07-22 02:09:13 +0000265 foreach ($this->routes as $key => $val)
Derek Allarda72b60d2007-01-31 23:56:11 +0000266 {
267 // Convert wild-cards to RegEx
268 $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
269
270 // Does the RegEx match?
271 if (preg_match('#^'.$key.'$#', $uri))
272 {
273 // Do we have a back-reference?
274 if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
275 {
276 $val = preg_replace('#^'.$key.'$#', $val, $uri);
277 }
278
Rick Ellis30b40152007-07-20 00:01:13 +0000279 $this->_set_request(explode('/', $val));
Derek Allarda72b60d2007-01-31 23:56:11 +0000280 return;
281 }
282 }
Derek Jonesc38c7032008-01-30 15:38:56 +0000283
Derek Allarda72b60d2007-01-31 23:56:11 +0000284 // If we got this far it means we didn't encounter a
285 // matching route so we'll set the site default route
Rick Ellis30b40152007-07-20 00:01:13 +0000286 $this->_set_request($this->uri->segments);
Derek Allarda72b60d2007-01-31 23:56:11 +0000287 }
288
289 // --------------------------------------------------------------------
290
291 /**
292 * Set the class name
293 *
294 * @access public
295 * @param string
296 * @return void
297 */
298 function set_class($class)
299 {
paulburdick691010e2007-06-28 00:02:30 +0000300 $this->class = $class;
Derek Allarda72b60d2007-01-31 23:56:11 +0000301 }
302
303 // --------------------------------------------------------------------
304
305 /**
306 * Fetch the current class
307 *
308 * @access public
309 * @return string
310 */
311 function fetch_class()
312 {
313 return $this->class;
314 }
315
316 // --------------------------------------------------------------------
317
318 /**
319 * Set the method name
320 *
321 * @access public
322 * @param string
323 * @return void
324 */
325 function set_method($method)
326 {
paulburdick691010e2007-06-28 00:02:30 +0000327 $this->method = $method;
Derek Allarda72b60d2007-01-31 23:56:11 +0000328 }
329
330 // --------------------------------------------------------------------
331
332 /**
333 * Fetch the current method
334 *
335 * @access public
336 * @return string
337 */
338 function fetch_method()
339 {
340 if ($this->method == $this->fetch_class())
341 {
342 return 'index';
343 }
344
345 return $this->method;
346 }
347
348 // --------------------------------------------------------------------
349
350 /**
351 * Set the directory name
352 *
353 * @access public
354 * @param string
355 * @return void
356 */
357 function set_directory($dir)
358 {
paulburdick691010e2007-06-28 00:02:30 +0000359 $this->directory = $dir.'/';
Derek Allarda72b60d2007-01-31 23:56:11 +0000360 }
361
362 // --------------------------------------------------------------------
363
364 /**
365 * Fetch the sub-directory (if any) that contains the requested controller class
366 *
367 * @access public
368 * @return string
369 */
370 function fetch_directory()
371 {
372 return $this->directory;
373 }
374
375}
376// END Router Class
adminb0dd10f2006-08-25 17:25:49 +0000377?>