PageRenderTime 78ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/system/libraries/Router.php

http://php-personal-budget.googlecode.com/
PHP | 374 lines | 168 code | 54 blank | 152 comment | 25 complexity | b13018aa0779e8b9ecefcffdb6334a50 MD5 | raw file
  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) 2006, 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. * Router Class
  18. *
  19. * Parses URIs and determines routing
  20. *
  21. * @package CodeIgniter
  22. * @subpackage Libraries
  23. * @author ExpressionEngine Dev Team
  24. * @category Libraries
  25. * @link http://codeigniter.com/user_guide/general/routing.html
  26. */
  27. class CI_Router {
  28. var $config;
  29. var $routes = array();
  30. var $error_routes = array();
  31. var $class = '';
  32. var $method = 'index';
  33. var $directory = '';
  34. var $uri_protocol = 'auto';
  35. var $default_controller;
  36. var $scaffolding_request = FALSE; // Must be set to FALSE
  37. /**
  38. * Constructor
  39. *
  40. * Runs the route mapping function.
  41. */
  42. function CI_Router()
  43. {
  44. $this->config =& load_class('Config');
  45. $this->uri =& load_class('URI');
  46. $this->_set_routing();
  47. log_message('debug', "Router Class Initialized");
  48. }
  49. // --------------------------------------------------------------------
  50. /**
  51. * Set the route mapping
  52. *
  53. * This function determines what should be served based on the URI request,
  54. * as well as any "routes" that have been set in the routing config file.
  55. *
  56. * @access private
  57. * @return void
  58. */
  59. function _set_routing()
  60. {
  61. // Are query strings enabled in the config file?
  62. // If so, we're done since segment based URIs are not used with query strings.
  63. if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
  64. {
  65. $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
  66. if (isset($_GET[$this->config->item('function_trigger')]))
  67. {
  68. $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
  69. }
  70. return;
  71. }
  72. // Load the routes.php file.
  73. @include(APPPATH.'config/routes'.EXT);
  74. $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
  75. unset($route);
  76. // Set the default controller so we can display it in the event
  77. // the URI doesn't correlated to a valid controller.
  78. $this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);
  79. // Fetch the complete URI string
  80. $this->uri->_fetch_uri_string();
  81. // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
  82. if ($this->uri->uri_string == '')
  83. {
  84. if ($this->default_controller === FALSE)
  85. {
  86. show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
  87. }
  88. $this->set_class($this->default_controller);
  89. $this->set_method('index');
  90. $this->_set_request(array($this->default_controller, 'index'));
  91. log_message('debug', "No URI present. Default controller set.");
  92. return;
  93. }
  94. unset($this->routes['default_controller']);
  95. // Do we need to remove the URL suffix?
  96. $this->uri->_remove_url_suffix();
  97. // Compile the segments into an array
  98. $this->uri->_explode_segments();
  99. // Parse any custom routing that may exist
  100. $this->_parse_routes();
  101. // Re-index the segment array so that it starts with 1 rather than 0
  102. $this->uri->_reindex_segments();
  103. }
  104. // --------------------------------------------------------------------
  105. /**
  106. * Set the Route
  107. *
  108. * This function takes an array of URI segments as
  109. * input, and sets the current class/method
  110. *
  111. * @access private
  112. * @param array
  113. * @param bool
  114. * @return void
  115. */
  116. function _set_request($segments = array())
  117. {
  118. $segments = $this->_validate_request($segments);
  119. if (count($segments) == 0)
  120. {
  121. return;
  122. }
  123. $this->set_class($segments[0]);
  124. if (isset($segments[1]))
  125. {
  126. // A scaffolding request. No funny business with the URL
  127. if ($this->routes['scaffolding_trigger'] == $segments[1] AND $segments[1] != '_ci_scaffolding')
  128. {
  129. $this->scaffolding_request = TRUE;
  130. unset($this->routes['scaffolding_trigger']);
  131. }
  132. else
  133. {
  134. // A standard method request
  135. $this->set_method($segments[1]);
  136. }
  137. }
  138. else
  139. {
  140. // This lets the "routed" segment array identify that the default
  141. // index method is being used.
  142. $segments[1] = 'index';
  143. }
  144. // Update our "routed" segment array to contain the segments.
  145. // Note: If there is no custom routing, this array will be
  146. // identical to $this->uri->segments
  147. $this->uri->rsegments = $segments;
  148. }
  149. // --------------------------------------------------------------------
  150. /**
  151. * Validates the supplied segments. Attempts to determine the path to
  152. * the controller.
  153. *
  154. * @access private
  155. * @param array
  156. * @return array
  157. */
  158. function _validate_request($segments)
  159. {
  160. // Does the requested controller exist in the root folder?
  161. if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
  162. {
  163. return $segments;
  164. }
  165. // Is the controller in a sub-folder?
  166. if (is_dir(APPPATH.'controllers/'.$segments[0]))
  167. {
  168. // Set the directory and remove it from the segment array
  169. $this->set_directory($segments[0]);
  170. $segments = array_slice($segments, 1);
  171. if (count($segments) > 0)
  172. {
  173. // Does the requested controller exist in the sub-folder?
  174. if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
  175. {
  176. show_404();
  177. }
  178. }
  179. else
  180. {
  181. $this->set_class($this->default_controller);
  182. $this->set_method('index');
  183. // Does the default controller exist in the sub-folder?
  184. if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
  185. {
  186. $this->directory = '';
  187. return array();
  188. }
  189. }
  190. return $segments;
  191. }
  192. // Can't find the requested controller...
  193. show_404();
  194. }
  195. // --------------------------------------------------------------------
  196. /**
  197. * Parse Routes
  198. *
  199. * This function matches any routes that may exist in
  200. * the config/routes.php file against the URI to
  201. * determine if the class/method need to be remapped.
  202. *
  203. * @access private
  204. * @return void
  205. */
  206. function _parse_routes()
  207. {
  208. // Do we even have any custom routing to deal with?
  209. // There is a default scaffolding trigger, so we'll look just for 1
  210. if (count($this->routes) == 1)
  211. {
  212. $this->_set_request($this->uri->segments);
  213. return;
  214. }
  215. // Turn the segment array into a URI string
  216. $uri = implode('/', $this->uri->segments);
  217. $num = count($this->uri->segments);
  218. // Is there a literal match? If so we're done
  219. if (isset($this->routes[$uri]))
  220. {
  221. $this->_set_request(explode('/', $this->routes[$uri]));
  222. return;
  223. }
  224. // Loop through the route array looking for wild-cards
  225. foreach ($this->routes as $key => $val)
  226. {
  227. // Convert wild-cards to RegEx
  228. $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
  229. // Does the RegEx match?
  230. if (preg_match('#^'.$key.'$#', $uri))
  231. {
  232. // Do we have a back-reference?
  233. if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
  234. {
  235. $val = preg_replace('#^'.$key.'$#', $val, $uri);
  236. }
  237. $this->_set_request(explode('/', $val));
  238. return;
  239. }
  240. }
  241. // If we got this far it means we didn't encounter a
  242. // matching route so we'll set the site default route
  243. $this->_set_request($this->uri->segments);
  244. }
  245. // --------------------------------------------------------------------
  246. /**
  247. * Set the class name
  248. *
  249. * @access public
  250. * @param string
  251. * @return void
  252. */
  253. function set_class($class)
  254. {
  255. $this->class = $class;
  256. }
  257. // --------------------------------------------------------------------
  258. /**
  259. * Fetch the current class
  260. *
  261. * @access public
  262. * @return string
  263. */
  264. function fetch_class()
  265. {
  266. return $this->class;
  267. }
  268. // --------------------------------------------------------------------
  269. /**
  270. * Set the method name
  271. *
  272. * @access public
  273. * @param string
  274. * @return void
  275. */
  276. function set_method($method)
  277. {
  278. $this->method = $method;
  279. }
  280. // --------------------------------------------------------------------
  281. /**
  282. * Fetch the current method
  283. *
  284. * @access public
  285. * @return string
  286. */
  287. function fetch_method()
  288. {
  289. if ($this->method == $this->fetch_class())
  290. {
  291. return 'index';
  292. }
  293. return $this->method;
  294. }
  295. // --------------------------------------------------------------------
  296. /**
  297. * Set the directory name
  298. *
  299. * @access public
  300. * @param string
  301. * @return void
  302. */
  303. function set_directory($dir)
  304. {
  305. $this->directory = $dir.'/';
  306. }
  307. // --------------------------------------------------------------------
  308. /**
  309. * Fetch the sub-directory (if any) that contains the requested controller class
  310. *
  311. * @access public
  312. * @return string
  313. */
  314. function fetch_directory()
  315. {
  316. return $this->directory;
  317. }
  318. }
  319. // END Router Class
  320. ?>