diff options
Diffstat (limited to 'src/lib/Router.class.php')
-rw-r--r-- | src/lib/Router.class.php | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/lib/Router.class.php b/src/lib/Router.class.php new file mode 100644 index 0000000..459034d --- /dev/null +++ b/src/lib/Router.class.php @@ -0,0 +1,110 @@ +<?php + +require_once('Controller.class.php'); + +class Router { + /** + * Array mapping URIs to controllers. + * A controller may register itself either by using + * Router::register($URI, $controller[, $function]); + * or by adding itself to the $ROUTER global. + * + * The default here just gives us a 404 handler. + */ + private $routes = array('/*' => 'Http404'); + + /** + * Instantiate a router that looks for controllers in $controllerpath. + */ + public function Router($controllerpath) { + // create a $ROUTES global that can be used to set up our + // $this->routes. + global $ROUTES; + $ROUTES = $this->routes; + + // Split $controllerpath into directories, and load the + // controllers in each. + $dirs = explode(PATH_SEPARATOR, $controllerpath); + foreach ($dirs as $dir) { + // Find all files in $dir with the ext `.class.php' + $controllerfiles = glob($dir.'/*.class.php'); + foreach ($controllerfiles as $file) { + // and include them + require_once($file); + } + } + + $this->routes = $ROUTES; + unset($ROUTES); + } + + /** + * Route the page at the relative URL $page to the appropriate + * controller, and call the appropriate function. + */ + public function route($page) { + $parts = explode('/', $page); + $length = count($parts); // the # of segments in $controllerpart + + // if $page ends in "/", strip that off + if ($parts[$length-1]=='') { + array_pop($parts); + $length--; + } + + $controllerpart = implode('/', $parts); + + // Keep shortening $controllerpart until it matches something in + // $this->routes. The shortest it will ever become is '/*'. + // If no key exists for '/*', that's an infinite loop. + // Fortunately, the default value of $this->routes directs '/*' + // to the Http404 controller. + while(!isset($this->routes[$controllerpart])) { + $some_parts = array_slice($parts, 0, $length); + $controllerpart = implode('/', $some_parts).'/*'; + $length--; + } + $length++; + + // Figure what function to call on what controller + // Grammar Nazi Warning: `what' or `which'? + $controller = $this->routes[$controllerpart]; + if (strpos($controller, '->')===false) { + // imply function + $function = $parts[$length]; + } else { + preg_match('/(.*)->(.*)/', $controller, $matches); + $controller = $matches[1]; + $function = $matches[2]; + } + + // Default to the `index' function, provided by all controllers + if ($function=='') { + $function = 'index'; + } + + // We will pass these arrays to the function. + $routed = array_slice($parts, 0, $length); + $remainder = array_slice($parts, $length); + + // Finally, run the controller + $obj = new $controller(); + if (in_array($function, get_class_methods($obj))) { + call_user_func(array($obj, $function), + $routed, $remainder); + } else { + $obj->http404($routed, $remainder); + } + } + + /** + * This is to allow controllers to register themselves to the router. + * If $function=='', then the function will be determined by the segment + * to the right of the last segment in $path + */ + public static function register($path, $controller, $function='') { + $str = $controller.(($function=='')?'':'->'.$function); + global $ROUTES; + $ROUTES[$path] = $str; + } +}
\ No newline at end of file |