PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/system/core/Router.php

https://gitlab.com/bipsahu/ptcs
PHP | 522 lines | 233 code | 74 blank | 215 comment | 36 complexity | db7d57b81f8c2d6687fc6a3a1148238b 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 5.1.6 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author ExpressionEngine Dev Team
  9. * @copyright Copyright (c) 2008 - 2014, 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. /**
  29. * Config class
  30. *
  31. * @var object
  32. * @access public
  33. */
  34. var $config;
  35. /**
  36. * List of routes
  37. *
  38. * @var array
  39. * @access public
  40. */
  41. var $routes = array();
  42. /**
  43. * List of error routes
  44. *
  45. * @var array
  46. * @access public
  47. */
  48. var $error_routes = array();
  49. /**
  50. * Current class name
  51. *
  52. * @var string
  53. * @access public
  54. */
  55. var $class = '';
  56. /**
  57. * Current method name
  58. *
  59. * @var string
  60. * @access public
  61. */
  62. var $method = 'index';
  63. /**
  64. * Sub-directory that contains the requested controller class
  65. *
  66. * @var string
  67. * @access public
  68. */
  69. var $directory = '';
  70. /**
  71. * Default controller (and method if specific)
  72. *
  73. * @var string
  74. * @access public
  75. */
  76. var $default_controller;
  77. /**
  78. * Constructor
  79. *
  80. * Runs the route mapping function.
  81. */
  82. function __construct()
  83. {
  84. $this->config =& load_class('Config', 'core');
  85. $this->uri =& load_class('URI', 'core');
  86. log_message('debug', "Router Class Initialized");
  87. }
  88. // --------------------------------------------------------------------
  89. /**
  90. * Set the route mapping
  91. *
  92. * This function determines what should be served based on the URI request,
  93. * as well as any "routes" that have been set in the routing config file.
  94. *
  95. * @access private
  96. * @return void
  97. */
  98. function _set_routing()
  99. {
  100. // Are query strings enabled in the config file? Normally CI doesn't utilize query strings
  101. // since URI segments are more search-engine friendly, but they can optionally be used.
  102. // If this feature is enabled, we will gather the directory/class/method a little differently
  103. $segments = array();
  104. if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
  105. {
  106. if (isset($_GET[$this->config->item('directory_trigger')]))
  107. {
  108. $this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')])));
  109. $segments[] = $this->fetch_directory();
  110. }
  111. if (isset($_GET[$this->config->item('controller_trigger')]))
  112. {
  113. $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
  114. $segments[] = $this->fetch_class();
  115. }
  116. if (isset($_GET[$this->config->item('function_trigger')]))
  117. {
  118. $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
  119. $segments[] = $this->fetch_method();
  120. }
  121. }
  122. // Load the routes.php file.
  123. if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
  124. {
  125. include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
  126. }
  127. elseif (is_file(APPPATH.'config/routes.php'))
  128. {
  129. include(APPPATH.'config/routes.php');
  130. }
  131. $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
  132. unset($route);
  133. // Set the default controller so we can display it in the event
  134. // the URI doesn't correlated to a valid controller.
  135. $this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);
  136. // Were there any query string segments? If so, we'll validate them and bail out since we're done.
  137. if (count($segments) > 0)
  138. {
  139. return $this->_validate_request($segments);
  140. }
  141. // Fetch the complete URI string
  142. $this->uri->_fetch_uri_string();
  143. // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
  144. if ($this->uri->uri_string == '')
  145. {
  146. return $this->_set_default_controller();
  147. }
  148. // Do we need to remove the URL suffix?
  149. $this->uri->_remove_url_suffix();
  150. // Compile the segments into an array
  151. $this->uri->_explode_segments();
  152. // Parse any custom routing that may exist
  153. $this->_parse_routes();
  154. // Re-index the segment array so that it starts with 1 rather than 0
  155. $this->uri->_reindex_segments();
  156. }
  157. // --------------------------------------------------------------------
  158. /**
  159. * Set the default controller
  160. *
  161. * @access private
  162. * @return void
  163. */
  164. function _set_default_controller()
  165. {
  166. if ($this->default_controller === FALSE)
  167. {
  168. show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
  169. }
  170. // Is the method being specified?
  171. if (strpos($this->default_controller, '/') !== FALSE)
  172. {
  173. $x = explode('/', $this->default_controller);
  174. $this->set_class($x[0]);
  175. $this->set_method($x[1]);
  176. $this->_set_request($x);
  177. }
  178. else
  179. {
  180. $this->set_class($this->default_controller);
  181. $this->set_method('index');
  182. $this->_set_request(array($this->default_controller, 'index'));
  183. }
  184. // re-index the routed segments array so it starts with 1 rather than 0
  185. $this->uri->_reindex_segments();
  186. log_message('debug', "No URI present. Default controller set.");
  187. }
  188. // --------------------------------------------------------------------
  189. /**
  190. * Set the Route
  191. *
  192. * This function takes an array of URI segments as
  193. * input, and sets the current class/method
  194. *
  195. * @access private
  196. * @param array
  197. * @param bool
  198. * @return void
  199. */
  200. function _set_request($segments = array())
  201. {
  202. $segments = $this->_validate_request($segments);
  203. if (count($segments) == 0)
  204. {
  205. return $this->_set_default_controller();
  206. }
  207. $this->set_class($segments[0]);
  208. if (isset($segments[1]))
  209. {
  210. // A standard method request
  211. $this->set_method($segments[1]);
  212. }
  213. else
  214. {
  215. // This lets the "routed" segment array identify that the default
  216. // index method is being used.
  217. $segments[1] = 'index';
  218. }
  219. // Update our "routed" segment array to contain the segments.
  220. // Note: If there is no custom routing, this array will be
  221. // identical to $this->uri->segments
  222. $this->uri->rsegments = $segments;
  223. }
  224. // --------------------------------------------------------------------
  225. /**
  226. * Validates the supplied segments. Attempts to determine the path to
  227. * the controller.
  228. *
  229. * @access private
  230. * @param array
  231. * @return array
  232. */
  233. function _validate_request($segments)
  234. {
  235. if (count($segments) == 0)
  236. {
  237. return $segments;
  238. }
  239. // Does the requested controller exist in the root folder?
  240. if (file_exists(APPPATH.'controllers/'.$segments[0].'.php'))
  241. {
  242. return $segments;
  243. }
  244. // Is the controller in a sub-folder?
  245. if (is_dir(APPPATH.'controllers/'.$segments[0]))
  246. {
  247. // Set the directory and remove it from the segment array
  248. $this->set_directory($segments[0]);
  249. $segments = array_slice($segments, 1);
  250. if (count($segments) > 0)
  251. {
  252. // Does the requested controller exist in the sub-folder?
  253. if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))
  254. {
  255. if ( ! empty($this->routes['404_override']))
  256. {
  257. $x = explode('/', $this->routes['404_override']);
  258. $this->set_directory('');
  259. $this->set_class($x[0]);
  260. $this->set_method(isset($x[1]) ? $x[1] : 'index');
  261. return $x;
  262. }
  263. else
  264. {
  265. show_404($this->fetch_directory().$segments[0]);
  266. }
  267. }
  268. }
  269. else
  270. {
  271. // Is the method being specified in the route?
  272. if (strpos($this->default_controller, '/') !== FALSE)
  273. {
  274. $x = explode('/', $this->default_controller);
  275. $this->set_class($x[0]);
  276. $this->set_method($x[1]);
  277. }
  278. else
  279. {
  280. $this->set_class($this->default_controller);
  281. $this->set_method('index');
  282. }
  283. // Does the default controller exist in the sub-folder?
  284. if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php'))
  285. {
  286. $this->directory = '';
  287. return array();
  288. }
  289. }
  290. return $segments;
  291. }
  292. // If we've gotten this far it means that the URI does not correlate to a valid
  293. // controller class. We will now see if there is an override
  294. if ( ! empty($this->routes['404_override']))
  295. {
  296. $x = explode('/', $this->routes['404_override']);
  297. $this->set_class($x[0]);
  298. $this->set_method(isset($x[1]) ? $x[1] : 'index');
  299. return $x;
  300. }
  301. // Nothing else to do at this point but show a 404
  302. show_404($segments[0]);
  303. }
  304. // --------------------------------------------------------------------
  305. /**
  306. * Parse Routes
  307. *
  308. * This function matches any routes that may exist in
  309. * the config/routes.php file against the URI to
  310. * determine if the class/method need to be remapped.
  311. *
  312. * @access private
  313. * @return void
  314. */
  315. function _parse_routes()
  316. {
  317. // Turn the segment array into a URI string
  318. $uri = implode('/', $this->uri->segments);
  319. // Is there a literal match? If so we're done
  320. if (isset($this->routes[$uri]))
  321. {
  322. return $this->_set_request(explode('/', $this->routes[$uri]));
  323. }
  324. // Loop through the route array looking for wild-cards
  325. foreach ($this->routes as $key => $val)
  326. {
  327. // Convert wild-cards to RegEx
  328. $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
  329. // Does the RegEx match?
  330. if (preg_match('#^'.$key.'$#', $uri))
  331. {
  332. // Do we have a back-reference?
  333. if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
  334. {
  335. $val = preg_replace('#^'.$key.'$#', $val, $uri);
  336. }
  337. return $this->_set_request(explode('/', $val));
  338. }
  339. }
  340. // If we got this far it means we didn't encounter a
  341. // matching route so we'll set the site default route
  342. $this->_set_request($this->uri->segments);
  343. }
  344. // --------------------------------------------------------------------
  345. /**
  346. * Set the class name
  347. *
  348. * @access public
  349. * @param string
  350. * @return void
  351. */
  352. function set_class($class)
  353. {
  354. $this->class = str_replace(array('/', '.'), '', $class);
  355. }
  356. // --------------------------------------------------------------------
  357. /**
  358. * Fetch the current class
  359. *
  360. * @access public
  361. * @return string
  362. */
  363. function fetch_class()
  364. {
  365. return $this->class;
  366. }
  367. // --------------------------------------------------------------------
  368. /**
  369. * Set the method name
  370. *
  371. * @access public
  372. * @param string
  373. * @return void
  374. */
  375. function set_method($method)
  376. {
  377. $this->method = $method;
  378. }
  379. // --------------------------------------------------------------------
  380. /**
  381. * Fetch the current method
  382. *
  383. * @access public
  384. * @return string
  385. */
  386. function fetch_method()
  387. {
  388. if ($this->method == $this->fetch_class())
  389. {
  390. return 'index';
  391. }
  392. return $this->method;
  393. }
  394. // --------------------------------------------------------------------
  395. /**
  396. * Set the directory name
  397. *
  398. * @access public
  399. * @param string
  400. * @return void
  401. */
  402. function set_directory($dir)
  403. {
  404. $this->directory = str_replace(array('/', '.'), '', $dir).'/';
  405. }
  406. // --------------------------------------------------------------------
  407. /**
  408. * Fetch the sub-directory (if any) that contains the requested controller class
  409. *
  410. * @access public
  411. * @return string
  412. */
  413. function fetch_directory()
  414. {
  415. return $this->directory;
  416. }
  417. // --------------------------------------------------------------------
  418. /**
  419. * Set the controller overrides
  420. *
  421. * @access public
  422. * @param array
  423. * @return null
  424. */
  425. function _set_overrides($routing)
  426. {
  427. if ( ! is_array($routing))
  428. {
  429. return;
  430. }
  431. if (isset($routing['directory']))
  432. {
  433. $this->set_directory($routing['directory']);
  434. }
  435. if (isset($routing['controller']) AND $routing['controller'] != '')
  436. {
  437. $this->set_class($routing['controller']);
  438. }
  439. if (isset($routing['function']))
  440. {
  441. $routing['function'] = ($routing['function'] == '') ? 'index' : $routing['function'];
  442. $this->set_method($routing['function']);
  443. }
  444. }
  445. }
  446. // END Router Class
  447. /* End of file Router.php */
  448. /* Location: ./system/core/Router.php */