upgrade to codeigniter 1.7.2 for f12
[www-register-wizard.git] / libraries / Router.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3  * CodeIgniter
4  *
5  * An open source application development framework for PHP 4.3.2 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008 - 2009, EllisLab, Inc.
10  * @license             http://codeigniter.com/user_guide/license.html
11  * @link                http://codeigniter.com
12  * @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
25  * @author              ExpressionEngine Dev Team
26  * @category    Libraries
27  * @link                http://codeigniter.com/user_guide/general/routing.html
28  */
29 class CI_Router {
30
31         var $config;    
32         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');
49                 $this->uri =& load_class('URI');
50                 $this->_set_routing();
51                 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          */
65         function _set_routing()
66         {
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                 {
71                         $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
72
73                         if (isset($_GET[$this->config->item('function_trigger')]))
74                         {
75                                 $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
76                         }
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
91                 $this->uri->_fetch_uri_string();
92         
93                 // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
94                 if ($this->uri->uri_string == '')
95                 {
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                         if (strpos($this->default_controller, '/') !== FALSE)
102                         {
103                                 $x = explode('/', $this->default_controller);
104
105                                 $this->set_class(end($x));
106                                 $this->set_method('index');
107                                 $this->_set_request($x);
108                         }
109                         else
110                         {
111                                 $this->set_class($this->default_controller);
112                                 $this->set_method('index');
113                                 $this->_set_request(array($this->default_controller, 'index'));
114                         }
115
116                         // re-index the routed segments array so it starts with 1 rather than 0
117                         $this->uri->_reindex_segments();
118                         
119                         log_message('debug', "No URI present. Default controller set.");
120                         return;
121                 }
122                 unset($this->routes['default_controller']);
123                 
124                 // Do we need to remove the URL suffix?
125                 $this->uri->_remove_url_suffix();
126                 
127                 // Compile the segments into an array
128                 $this->uri->_explode_segments();
129                 
130                 // Parse any custom routing that may exist
131                 $this->_parse_routes();         
132                 
133                 // Re-index the segment array so that it starts with 1 rather than 0
134                 $this->uri->_reindex_segments();
135         }
136         
137         // --------------------------------------------------------------------
138         
139         /**
140          * Set the Route
141          *
142          * This function takes an array of URI segments as
143          * input, and sets the current class/method
144          *
145          * @access      private
146          * @param       array
147          * @param       bool
148          * @return      void
149          */
150         function _set_request($segments = array())
151         {
152                 $segments = $this->_validate_request($segments);
153                 
154                 if (count($segments) == 0)
155                 {
156                         return;
157                 }
158                                                 
159                 $this->set_class($segments[0]);
160                 
161                 if (isset($segments[1]))
162                 {
163                         // A scaffolding request. No funny business with the URL
164                         if ($this->routes['scaffolding_trigger'] == $segments[1] AND $segments[1] != '_ci_scaffolding')
165                         {
166                                 $this->scaffolding_request = TRUE;
167                                 unset($this->routes['scaffolding_trigger']);
168                         }
169                         else
170                         {
171                                 // A standard method request
172                                 $this->set_method($segments[1]);
173                         }
174                 }
175                 else
176                 {
177                         // This lets the "routed" segment array identify that the default
178                         // index method is being used.
179                         $segments[1] = 'index';
180                 }
181                 
182                 // Update our "routed" segment array to contain the segments.
183                 // Note: If there is no custom routing, this array will be
184                 // identical to $this->uri->segments
185                 $this->uri->rsegments = $segments;
186         }
187         
188         // --------------------------------------------------------------------
189         
190         /**
191          * Validates the supplied segments.  Attempts to determine the path to
192          * the controller.
193          *
194          * @access      private
195          * @param       array
196          * @return      array
197          */     
198         function _validate_request($segments)
199         {
200                 // Does the requested controller exist in the root folder?
201                 if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
202                 {
203                         return $segments;
204                 }
205
206                 // Is the controller in a sub-folder?
207                 if (is_dir(APPPATH.'controllers/'.$segments[0]))
208                 {               
209                         // Set the directory and remove it from the segment array
210                         $this->set_directory($segments[0]);
211                         $segments = array_slice($segments, 1);
212                         
213                         if (count($segments) > 0)
214                         {
215                                 // Does the requested controller exist in the sub-folder?
216                                 if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
217                                 {
218                                         show_404($this->fetch_directory().$segments[0]);
219                                 }
220                         }
221                         else
222                         {
223                                 $this->set_class($this->default_controller);
224                                 $this->set_method('index');
225                         
226                                 // Does the default controller exist in the sub-folder?
227                                 if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
228                                 {
229                                         $this->directory = '';
230                                         return array();
231                                 }
232                         
233                         }
234
235                         return $segments;
236                 }
237
238                 // Can't find the requested controller...
239                 show_404($segments[0]);
240         }
241
242         // --------------------------------------------------------------------
243
244         /**
245          *  Parse Routes
246          *
247          * This function matches any routes that may exist in
248          * the config/routes.php file against the URI to
249          * determine if the class/method need to be remapped.
250          *
251          * @access      private
252          * @return      void
253          */
254         function _parse_routes()
255         {
256                 // Do we even have any custom routing to deal with?
257                 // There is a default scaffolding trigger, so we'll look just for 1
258                 if (count($this->routes) == 1)
259                 {
260                         $this->_set_request($this->uri->segments);
261                         return;
262                 }
263
264                 // Turn the segment array into a URI string
265                 $uri = implode('/', $this->uri->segments);
266
267                 // Is there a literal match?  If so we're done
268                 if (isset($this->routes[$uri]))
269                 {
270                         $this->_set_request(explode('/', $this->routes[$uri]));         
271                         return;
272                 }
273                                 
274                 // Loop through the route array looking for wild-cards
275                 foreach ($this->routes as $key => $val)
276                 {                                               
277                         // Convert wild-cards to RegEx
278                         $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
279                         
280                         // Does the RegEx match?
281                         if (preg_match('#^'.$key.'$#', $uri))
282                         {                       
283                                 // Do we have a back-reference?
284                                 if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
285                                 {
286                                         $val = preg_replace('#^'.$key.'$#', $val, $uri);
287                                 }
288                         
289                                 $this->_set_request(explode('/', $val));                
290                                 return;
291                         }
292                 }
293
294                 // If we got this far it means we didn't encounter a
295                 // matching route so we'll set the site default route
296                 $this->_set_request($this->uri->segments);
297         }
298
299         // --------------------------------------------------------------------
300         
301         /**
302          * Set the class name
303          *
304          * @access      public
305          * @param       string
306          * @return      void
307          */     
308         function set_class($class)
309         {
310                 $this->class = $class;
311         }
312         
313         // --------------------------------------------------------------------
314         
315         /**
316          * Fetch the current class
317          *
318          * @access      public
319          * @return      string
320          */     
321         function fetch_class()
322         {
323                 return $this->class;
324         }
325         
326         // --------------------------------------------------------------------
327         
328         /**
329          *  Set the method name
330          *
331          * @access      public
332          * @param       string
333          * @return      void
334          */     
335         function set_method($method)
336         {
337                 $this->method = $method;
338         }
339
340         // --------------------------------------------------------------------
341         
342         /**
343          *  Fetch the current method
344          *
345          * @access      public
346          * @return      string
347          */     
348         function fetch_method()
349         {
350                 if ($this->method == $this->fetch_class())
351                 {
352                         return 'index';
353                 }
354
355                 return $this->method;
356         }
357
358         // --------------------------------------------------------------------
359         
360         /**
361          *  Set the directory name
362          *
363          * @access      public
364          * @param       string
365          * @return      void
366          */     
367         function set_directory($dir)
368         {
369                 $this->directory = $dir.'/';
370         }
371
372         // --------------------------------------------------------------------
373         
374         /**
375          *  Fetch the sub-directory (if any) that contains the requested controller class
376          *
377          * @access      public
378          * @return      string
379          */     
380         function fetch_directory()
381         {
382                 return $this->directory;
383         }
384
385 }
386 // END Router Class
387
388 /* End of file Router.php */
389 /* Location: ./system/libraries/Router.php */