Commit 6c8b446f authored by Taddeus Kroes's avatar Taddeus Kroes

Added Router class.

parent 1dee302c
<?php
/**
* Functions for URL routing: given an URL, call the corresponding handler
* function (the 'route' to the corresponding output).
*
* @author Taddeus Kroes
* @version 1.0
* @date 14-07-2012
*/
namespace BasicWeb;
require_once 'base.php';
/**
*
*
* <code>
*
* </code>
*
* @package BasicWeb
*/
class Router extends Base {
/**
* The regex delimiter that is added to the begin and end of patterns.
*
* @var string
*/
const DELIMITER = '%';
/**
* An associative array of regex patterns pointing to handler functions.
*
* @var array
*/
private $routes = array();
/**
* Create a new Router instance.
*
* @param array $routes An initial list of routes to set.
*/
function __construct(array $routes=array()) {
foreach( $routes as $pattern => $handler )
$this->add_route($pattern, $handler);
}
/**
* Add a route as a (pattern, handler) pair.
*
* The pattern is regular expression pattern without delimiters. The
* function adds '%^' at the begin and '$%' at the end of the pattern as
* delimiters.
*
* The handler function must receive no arguments if the regex pattern
* does not contain groups (which are contained in parentheses). If there
* are groups, the matches for these are passed to the handler fucntion in
* an array.
*
* @param string $pattern A regex pattern to mach URL's against.
* @param mixed $handler The handler function to call when $pattern is matched.
* @throws \InvalidArgumentException If $handler is not callable.
*/
function add_route($pattern, $handler) {
if( !is_callable($handler) )
throw new \InvalidArgumentException(sprintf('Handler for patterns "%s" is not callable.', $pattern));
$this->routes[self::DELIMITER.'^'.$pattern.'$'.self::DELIMITER] = $handler;
}
/**
* Call the handler function corresponding to the specified url.
*
* If any groups are in the matched regex pattern, a list of matches is
* passed to the handler function.
*
* @param string $url An url to match the saved patterns against.
* @return mixed FALSE if no pattern was matched, the return value of the
* corresponding handler function otherwise.
*/
function call_handler($url) {
foreach( $this->routes as $pattern => $handler ) {
if( preg_match($pattern, $url, $matches) ) {
array_shift($matches);
return call_user_func_array($handler, $matches);
}
}
return false;
}
}
?>
\ No newline at end of file
<?php
require_once 'router.php';
use BasicWeb\Router;
function test_handler_no_args() {
return true;
}
function test_handler_arg($arg) {
return $arg;
}
function test_handler_args($arg0, $arg1) {
return $arg1.$arg0;
}
class RouterTest extends PHPUnit_Framework_TestCase {
function setUp() {
$this->router = new Router(array(
'foo' => 'test_handler_no_args',
'(ba[rz])' => 'test_handler_arg',
'(ba[rz])(ba[rz])' => 'test_handler_args',
));
}
function test_call_handler_success() {
$this->assertEquals($this->router->call_handler('foo'), true);
$this->assertEquals($this->router->call_handler('bar'), 'bar');
$this->assertEquals($this->router->call_handler('baz'), 'baz');
$this->assertEquals($this->router->call_handler('bazbar'), 'barbaz');
}
function test_call_handler_failure() {
$this->assertFalse($this->router->call_handler('barfoo'));
}
function test_add_route() {
$this->router->add_route('(foobar)', 'test_handler_arg');
$this->assertEquals($this->router->call_handler('foobar'), 'foobar');
}
}
?>
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment