Posted: Sat Jun 23, 2007 4:44 am
I'm breaking rules by successive posting here but I guess half the forum members are in bed now :P
Now it's copying values into a passed array. The last two tests should interest you :)
EDIT |
Ok, and some more: Wildcards, multiple routes setting values:
TODO
Arrays in URL
Rewriting URLs
Tidying up remaining ?foo=bar&x=y&a=12 strings intelligently
Now it's copying values into a passed array. The last two tests should interest you :)
Code: Select all
<?php
Mock::Generate("Request_Route", "MockRoute");
Mock::GeneratePartial("Request_Route", "PartialRoute", array("hydrateRequest"));
class TestOfRouter extends UnitTestCase
{
public function testEachRouteIsChecked()
{
$router = new Request_Router();
$route1 = new MockRoute();
$route1->__construct("/foo/bar", array());
$route1->expectAtLeastOnce("getUri");
$router->addRoute($route1);
$route2 = new MockRoute();
$route2->__construct("/zip/button", array());
$route2->expectAtLeastOnce("getUri");
$router->addRoute($route2);
$router->execute();
}
public function testRoutesAreExecutedOnUriMatch()
{
$router = new Request_Router();
$route1 = new PartialRoute();
$route1->__construct("/foo/bar", array());
$route1->expectOnce("hydrateRequest");
$router->addRoute($route1);
$route2 = new PartialRoute();
$route2->__construct("/zip/button", array());
$route2->expectNever("hydrateRequest");
$router->addRoute($route2);
$router->setUri("/foo/bar");
$router->execute();
}
public function testMatchCanContainVariables()
{
$router = new Request_Router();
$route1 = new PartialRoute();
$route1->__construct("/foobar/:bar", array());
$route1->expectNever("hydrateRequest");
$router->addRoute($route1);
$route2 = new PartialRoute();
$route2->__construct("/foo/:bar", array());
$route2->expectOnce("hydrateRequest");
$router->addRoute($route2);
$router->setUri("/foo/1234");
$router->execute();
}
public function testMultipleRoutesCanApply()
{
$router = new Request_Router();
$route1 = new PartialRoute();
$route1->__construct("/:foo/:bar", array());
$route1->expectOnce("hydrateRequest");
$router->addRoute($route1);
$route2 = new PartialRoute();
$route2->__construct("/foo/:bar", array());
$route2->expectOnce("hydrateRequest");
$router->addRoute($route2);
$router->setUri("/foo/1234");
$router->execute();
}
public function testListedValuesAreUsed()
{
$router = new Request_Router();
$route = new Request_Route("/foo/bar", array("order" => "1234", "date" => "2007-06-22"));
$router->addRoute($route);
$router->setUri("/foo/bar");
$array = array();
$router->execute($array);
$this->assertEqual($array["order"], "1234");
$this->assertEqual($array["date"], "2007-06-22");
$router = new Request_Router();
$route = new Request_Route("/foo/:bar", array("rodent" => "mouse", "where" => "clock"));
$router->addRoute($route);
$router->setUri("/foo/testing123");
$array = array();
$router->execute($array);
$this->assertEqual($array["rodent"], "mouse");
$this->assertEqual($array["where"], "clock");
}
public function testDynamicValuesAreUsed()
{
$router = new Request_Router();
$route = new Request_Route("/foo/:bar", array("rodent" => "mouse", "where" => "clock"));
$router->addRoute($route);
$router->setUri("/foo/testing123");
$array = array();
$router->execute($array);
$this->assertEqual($array["bar"], "testing123");
$router = new Request_Router();
$route = new Request_Route("/:module/:action/:id", array());
$router->addRoute($route);
$router->setUri("/incidents/update/123");
$array = array();
$router->execute($array);
$this->assertEqual($array["module"], "incidents");
$this->assertEqual($array["action"], "update");
$this->assertEqual($array["id"], "123");
}
}Code: Select all
<?php
/**
* Web Request Router class.
* @author Chris Corbyn
*/
class Request_Router
{
protected $routes = array();
protected $uri;
public function addRoute(Request_Route $route)
{
$this->routes[] = $route;
}
public function getRoutes()
{
return $this->routes;
}
public function setUri($uri)
{
$this->uri = $uri;
}
public function getUri()
{
return $this->uri;
}
public function execute(&$request = null)
{
if ($request === null) $request =& $_GET;
foreach ($this->getRoutes() as $route)
{
$uri = $route->getUri();
if (empty($uri)) continue;
$uri = preg_quote($uri, "~");
//Create a regexp for the URI
$uri = preg_replace("~\\\\:([a-zA-Z0-9_]+)~", "(?P<\$1>[^/:\\?&]+)", $uri);
$uri = "~^" . $uri . "\$~D";
if (preg_match($uri, $this->getUri(), $matches))
{
$route->hydrateRequest($request, $matches);
}
}
}
}Code: Select all
<?php
/**
* An individual routing rule.
* @author Chris Corbyn
*/
class Request_Route
{
protected $uri;
protected $defaults = array();
public function __construct($uri, Array $defaults)
{
$this->setUri($uri);
$this->setDefaults($defaults);
}
public function setUri($uri)
{
$this->uri = $uri;
}
public function getUri()
{
return $this->uri;
}
public function setDefaults(Array $defaults)
{
$this->defaults = $defaults;
}
public function getDefaults()
{
return $this->defaults;
}
public function hydrateRequest(Array &$request, Array $matches)
{
$uri_matches = array();
foreach ($matches as $k => $v)
{
if (!is_int($k)) $uri_matches[$k] = $v;
}
$request = array_merge($request, $uri_matches);
$request = array_merge($request, $this->getDefaults());
}
}Ok, and some more: Wildcards, multiple routes setting values:
Code: Select all
public function testWildcardsCanBeUsed()
{
$router = new Request_Router();
$route1 = new PartialRoute();
$route1->__construct("/*/:bar", array());
$route1->expectOnce("hydrateRequest");
$router->addRoute($route1);
$route2 = new PartialRoute();
$route2->__construct("/foo/*", array());
$route2->expectOnce("hydrateRequest");
$router->addRoute($route2);
$router->setUri("/foo/1234");
$router->execute();
}
public function testTrailingSlashIsIrrelevant()
{
$router = new Request_Router();
$route = new PartialRoute();
$route->__construct("/:foo/:bar");
$route->expectCallCount("hydrateRequest", 2);
$router->addRoute($route);
$router->setUri("/x/y");
$router->execute();
$router->setUri("/x/y/");
$router->execute();
}
public function testMultipleRoutesCanHydrateRequest()
{
$router = new Request_Router();
$router->addRoute(new Request_Route("/:module/:action/*"));
$router->addRoute(new Request_Route("/docs/:chapter/:pageNumber", array("action" => "view")));
$router->addRoute(new Request_Route("/docs/introduction/:page", array("action" => "view", "isIntro" => 1)));
$router->setUri("/docs/introduction/3");
$array = array();
$router->execute($array);
$this->assertEqual($array["module"], "docs");
$this->assertEqual($array["action"], "view");
$this->assertEqual($array["chapter"], "introduction");
$this->assertEqual($array["pageNumber"], 3);
$this->assertEqual($array["page"], 3);
}Code: Select all
<?php
/**
* Web Request Router class.
* @author Chris Corbyn
*/
class Request_Router
{
protected $routes = array();
protected $uri;
public function addRoute(Request_Route $route)
{
$this->routes[] = $route;
}
public function getRoutes()
{
return $this->routes;
}
public function setUri($uri)
{
$this->uri = rtrim($uri, "/");
}
public function getUri()
{
return $this->uri;
}
public function execute(&$request = null)
{
if ($request === null) $request =& $_GET;
foreach ($this->getRoutes() as $route)
{
$uri = $route->getUri();
if (empty($uri)) continue;
//Create a regexp for the URI
$uri = preg_quote($uri, "~");
$uri = str_replace("\\*", ".*?", $uri);
$uri = preg_replace("~\\\\:([a-zA-Z0-9_]+)~", "(?P<\$1>[^/:\\?&]+)", $uri);
$uri = "~^" . $uri . "\$~D";
if (preg_match($uri, $this->getUri(), $matches))
{
$route->hydrateRequest($request, $matches);
}
}
}
}Code: Select all
<?php
/**
* An individual routing rule.
* @author Chris Corbyn
*/
class Request_Route
{
protected $uri;
protected $defaults = array();
public function __construct($uri, Array $defaults = null)
{
if ($defaults === null) $defaults = array();
$this->setUri($uri);
$this->setDefaults($defaults);
}
public function setUri($uri)
{
$this->uri = rtrim($uri, "/");
}
public function getUri()
{
return $this->uri;
}
public function setDefaults(Array $defaults)
{
$this->defaults = $defaults;
}
public function getDefaults()
{
return $this->defaults;
}
public function hydrateRequest(Array &$request, Array $matches)
{
$uri_matches = array();
foreach ($matches as $k => $v)
{
if (!is_int($k)) $uri_matches[$k] = $v;
}
$request = array_merge($request, $uri_matches);
$request = array_merge($request, $this->getDefaults());
}
}Arrays in URL
Rewriting URLs
Tidying up remaining ?foo=bar&x=y&a=12 strings intelligently