From bc5299abfcd3f08467f0a2da3ec9ba548fcc3e8c Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 29 Jul 2011 22:48:14 -0500 Subject: [PATCH] tweaked router architecture to be non-static. --- system/router.php | 136 +++++++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 56 deletions(-) diff --git a/system/router.php b/system/router.php index 24fb078c..7c130d7a 100644 --- a/system/router.php +++ b/system/router.php @@ -3,27 +3,90 @@ class Router { /** - * Search a set of routes for the route matching a method and URI. + * The request method and URI. + * + * @var string + */ + public $request; + + /** + * All of the loaded routes. + * + * @var array + */ + public $routes; + + /** + * Create a new router for a request method and URI. * * @param string $method * @param string $uri - * @return Route + * @param array $routes + * @return void */ - public static function route($method, $uri) + public function __construct($method, $uri, $routes = null) { - $routes = static::load($uri); - // Put the request method and URI in route form. // Routes begin with the request method and a forward slash. - $uri = $method.' /'.trim($uri, '/'); + $this->request = $method.' /'.trim($uri, '/'); - // Is there an exact match for the request? - if (isset($routes[$uri])) + $this->routes = (is_array($routes)) ? $routes : $this->load($uri); + } + + /** + * Create a new router for a request method and URI. + * + * @param string $method + * @param string $uri + * @param array $routes + * @return Router + */ + public static function make($method, $uri, $routes = null) + { + return new static($method, $uri, $routes); + } + + /** + * Load the appropriate routes for the request URI. + * + * @param string $uri + * @return array + */ + public function load($uri) + { + $base = require APP_PATH.'routes'.EXT; + + if ( ! is_dir(APP_PATH.'routes') or $uri == '') { - return Request::$route = new Route($uri, $routes[$uri]); + return $base; } - foreach ($routes as $keys => $callback) + list($routes, $segments) = array(array(), explode('/', $uri)); + + foreach (array_reverse($segments, true) as $key => $value) + { + if (file_exists($path = ROUTE_PATH.implode('/', array_slice($segments, 0, $key + 1)).EXT)) + { + $routes = require $path; + } + } + + return array_merge($routes, $base); + } + + /** + * Search a set of routes for the route matching a method and URI. + * + * @return Route + */ + public function route() + { + if (isset($this->routes[$this->request])) + { + return Request::$route = new Route($this->request, $this->routes[$this->request]); + } + + foreach ($this->routes as $keys => $callback) { // Only check routes that have multiple URIs or wildcards. // Other routes would have been caught by the check for literal matches. @@ -31,69 +94,30 @@ public static function route($method, $uri) { foreach (explode(', ', $keys) as $key) { - if (preg_match('#^'.static::translate_wildcards($key).'$#', $uri)) + if (preg_match('#^'.$this->translate_wildcards($key).'$#', $this->request)) { - return Request::$route = new Route($keys, $callback, static::parameters($uri, $key)); + return Request::$route = new Route($keys, $callback, $this->parameters($this->request, $key)); } } } } } - /** - * Load the appropriate route file for the request URI. - * - * @param string $uri - * @return array - */ - public static function load($uri) - { - $base = require APP_PATH.'routes'.EXT; - - return (is_dir(APP_PATH.'routes') and $uri !== '') ? array_merge(static::load_from_directory($uri), $base) : $base; - } - - /** - * Load the appropriate route file from the routes directory. - * - * @param string $uri - * @return array - */ - private static function load_from_directory($uri) - { - $segments = explode('/', $uri); - - // Route files can be nested deep within sub-directories. - // Iterate backwards through the URI looking for the deepest matching file. - foreach (array_reverse($segments, true) as $key => $value) - { - if (file_exists($path = ROUTE_PATH.implode('/', array_slice($segments, 0, $key + 1)).EXT)) - { - return require $path; - } - } - - return array(); - } - /** * Translate route URI wildcards into actual regular expressions. * * @param string $key * @return string */ - private static function translate_wildcards($key) + private function translate_wildcards($key) { $replacements = 0; // For optional parameters, first translate the wildcards to their regex equivalent, sans the ")?" ending. + // We will add the endings back on after we know how many replacements we made. $key = str_replace(array('/(:num?)', '/(:any?)'), array('(?:/([0-9]+)', '(?:/([a-zA-Z0-9\-_]+)'), $key, $replacements); - - // Now, to properly close the regular expression, we need to append a ")?" for each optional segment in the route. - if ($replacements > 0) - { - $key .= str_repeat(')?', $replacements); - } + + $key .= ($replacements > 0) ? str_repeat(')?', $replacements) : ''; return str_replace(array(':num', ':any'), array('[0-9]+', '[a-zA-Z0-9\-_]+'), $key); } @@ -107,7 +131,7 @@ private static function translate_wildcards($key) * @param string $route * @return array */ - private static function parameters($uri, $route) + private function parameters($uri, $route) { return array_values(array_intersect_key(explode('/', $uri), preg_grep('/\(.+\)/', explode('/', $route)))); }