diff options
Diffstat (limited to 'system/core/Router.php')
-rw-r--r-- | system/core/Router.php | 209 |
1 files changed, 109 insertions, 100 deletions
diff --git a/system/core/Router.php b/system/core/Router.php index 5bc053045..30bf39657 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Router Class @@ -39,56 +40,49 @@ class CI_Router { /** - * Config class + * CI_Config class object * - * @var object + * @var object */ public $config; /** * List of routes * - * @var array + * @var array */ public $routes = array(); /** - * List of error routes - * - * @var array - */ - public $error_routes = array(); - - /** * Current class name * - * @var string + * @var string */ public $class = ''; /** * Current method name * - * @var string + * @var string */ public $method = 'index'; /** * Sub-directory that contains the requested controller class * - * @var string + * @var string */ public $directory = ''; /** * Default controller (and method if specific) * - * @var string + * @var string */ public $default_controller; /** - * Constructor + * Class constructor * * Runs the route mapping function. * @@ -104,9 +98,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the route mapping + * Set route mapping * - * This function determines what should be served based on the URI request, + * Determines what should be served based on the URI request, * as well as any "routes" that have been set in the routing config file. * * @return void @@ -148,12 +142,12 @@ class CI_Router { include(APPPATH.'config/routes.php'); } - $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route; + $this->routes = (isset($route) && is_array($route)) ? $route : array(); unset($route); // Set the default controller so we can display it in the event // the URI doesn't correlated to a valid controller. - $this->default_controller = empty($this->routes['default_controller']) ? FALSE : strtolower($this->routes['default_controller']); + $this->default_controller = empty($this->routes['default_controller']) ? FALSE : $this->routes['default_controller']; // Were there any query string segments? If so, we'll validate them and bail out since we're done. if (count($segments) > 0) @@ -179,31 +173,27 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the default controller + * Set default controller * * @return void */ protected function _set_default_controller() { - if ($this->default_controller === FALSE) + if (empty($this->default_controller)) { show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.'); } + // Is the method being specified? - if (strpos($this->default_controller, '/') !== FALSE) + if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2) { - $x = explode('/', $this->default_controller); - $this->set_class($x[0]); - $this->set_method($x[1]); - $this->_set_request($x); - } - else - { - $this->set_class($this->default_controller); - $this->set_method('index'); - $this->_set_request(array($this->default_controller, 'index')); + $method = 'index'; } + $this->set_class($class); + $this->set_method($method); + $this->_set_request(array($class, $method)); + // re-index the routed segments array so it starts with 1 rather than 0 $this->uri->_reindex_segments(); @@ -213,12 +203,12 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the Route + * Set request route * - * This function takes an array of URI segments as - * input, and sets the current class/method + * Takes an array of URI segments as input and sets the class/method + * to be called. * - * @param array + * @param array $segments URI segments * @return void */ protected function _set_request($segments = array()) @@ -232,17 +222,8 @@ class CI_Router { $this->set_class($segments[0]); - if (isset($segments[1])) - { - // A standard method request - $this->set_method($segments[1]); - } - else - { - // This lets the "routed" segment array identify that the default - // index method is being used. - $segments[1] = 'index'; - } + isset($segments[1]) OR $segments[1] = 'index'; + $this->set_method($segments[1]); // Update our "routed" segment array to contain the segments. // Note: If there is no custom routing, this array will be @@ -253,11 +234,12 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Validates the supplied segments. - * Attempts to determine the path to the controller. + * Validate request + * + * Attempts validate the URI request and determine the controller path. * - * @param array - * @return array + * @param array $segments URI segments + * @return array URI segments */ protected function _validate_request($segments) { @@ -266,9 +248,13 @@ class CI_Router { return $segments; } + $temp = str_replace('-', '_', $segments[0]); + // Does the requested controller exist in the root folder? - if (file_exists(APPPATH.'controllers/'.$segments[0].'.php')) + if (file_exists(APPPATH.'controllers/'.$temp.'.php')) { + $segments[0] = $temp; + empty($segments[1]) OR $segments[1] = str_replace('-', '_', $segments[1]); return $segments; } @@ -276,22 +262,19 @@ class CI_Router { if (is_dir(APPPATH.'controllers/'.$segments[0])) { // Set the directory and remove it from the segment array - $this->set_directory($segments[0]); - $segments = array_slice($segments, 1); - + $this->set_directory(array_shift($segments)); if (count($segments) > 0) { + $segments[0] = str_replace('-', '_', $segments[0]); + empty($segments[1]) OR $segments[1] = str_replace('-', '_', $segments[1]); + // Does the requested controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) { if ( ! empty($this->routes['404_override'])) { - $x = explode('/', $this->routes['404_override']); - $this->set_directory(''); - $this->set_class($x[0]); - $this->set_method(isset($x[1]) ? $x[1] : 'index'); - - return $x; + $this->directory = ''; + return explode('/', $this->routes['404_override'], 2); } else { @@ -302,40 +285,26 @@ class CI_Router { else { // Is the method being specified in the route? - if (strpos($this->default_controller, '/') !== FALSE) - { - $x = explode('/', $this->default_controller); - $this->set_class($x[0]); - $this->set_method($x[1]); - } - else - { - $this->set_class($this->default_controller); - $this->set_method('index'); - } - - // Does the default controller exist in the sub-folder? - if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) + $segments = explode('/', $this->default_controller); + if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) { $this->directory = ''; - return array(); } - } return $segments; } - // If we've gotten this far it means that the URI does not correlate to a valid // controller class. We will now see if there is an override if ( ! empty($this->routes['404_override'])) { - $x = explode('/', $this->routes['404_override']); - $this->set_class($x[0]); - $this->set_method(isset($x[1]) ? $x[1] : 'index'); + if (sscanf($this->routes['404_override'], '%[^/]/%s', $class, $method) !== 2) + { + $method = 'index'; + } - return $x; + return array($class, $method); } // Nothing else to do at this point but show a 404 @@ -347,9 +316,8 @@ class CI_Router { /** * Parse Routes * - * This function matches any routes that may exist in - * the config/routes.php file against the URI to - * determine if the class/method need to be remapped. + * Matches any routes that may exist in the config/routes.php file + * against the URI to determine if the class/method need to be remapped. * * @return void */ @@ -368,13 +336,51 @@ class CI_Router { foreach ($this->routes as $key => $val) { // Convert wild-cards to RegEx - $key = str_replace(array(':any', ':num'), array('.+', '[0-9]+'), $key); + $key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key); // Does the RegEx match? - if (preg_match('#^'.$key.'$#', $uri)) + if (preg_match('#^'.$key.'$#', $uri, $matches)) { - // Do we have a back-reference? - if (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE) + // Are we using callbacks to process back-references? + if ( ! is_string($val) && is_callable($val)) + { + // Remove the original string from the matches array. + array_shift($matches); + + // Get the match count. + $match_count = count($matches); + + // Determine how many parameters the callback has. + $reflection = new ReflectionFunction($val); + $param_count = $reflection->getNumberOfParameters(); + + // Are there more parameters than matches? + if ($param_count > $match_count) + { + // Any params without matches will be set to an empty string. + $matches = array_merge($matches, array_fill($match_count, $param_count - $match_count, '')); + + $match_count = $param_count; + } + + // Get the parameters so we can use their default values. + $params = $reflection->getParameters(); + + for ($m = 0; $m < $match_count; $m++) + { + // Is the match empty and does a default value exist? + if (empty($matches[$m]) && $params[$m]->isDefaultValueAvailable()) + { + // Substitute the empty match for the default value. + $matches[$m] = $params[$m]->getDefaultValue(); + } + } + + // Execute the callback using the values in matches as its parameters. + $val = call_user_func_array($val, $matches); + } + // Are we using the default routing method for back-references? + elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE) { $val = preg_replace('#^'.$key.'$#', $val, $uri); } @@ -391,9 +397,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the class name + * Set class name * - * @param string + * @param string $class Class name * @return void */ public function set_class($class) @@ -416,9 +422,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the method name + * Set method name * - * @param string + * @param string $method Method name * @return void */ public function set_method($method) @@ -441,9 +447,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the directory name + * Set directory name * - * @param string + * @param string $dir Directory name * @return void */ public function set_directory($dir) @@ -454,7 +460,10 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Fetch the sub-directory (if any) that contains the requested controller class + * Fetch directory + * + * Feches the sub-directory (if any) that contains the requested + * controller class. * * @return string */ @@ -466,9 +475,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the controller overrides + * Set controller overrides * - * @param array + * @param array $routing Route overrides * @return void */ public function _set_overrides($routing) @@ -490,7 +499,7 @@ class CI_Router { if (isset($routing['function'])) { - $routing['function'] = ($routing['function'] == '') ? 'index' : $routing['function']; + $routing['function'] = empty($routing['function']) ? 'index' : $routing['function']; $this->set_method($routing['function']); } } |