Created
June 8, 2012 13:27
-
-
Save chdemko/2895611 to your computer and use it in GitHub Desktop.
Replacement for parseRoute function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @package Joomla.Platform | |
* @subpackage Application | |
* | |
* @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. | |
* @license GNU General Public License version 2 or later; see LICENSE | |
*/ | |
defined('JPATH_PLATFORM') or die; | |
/** | |
* Basic Web application router class for the Joomla Platform. | |
* | |
* @package Joomla.Platform | |
* @subpackage Application | |
* @since 12.3 | |
*/ | |
class JApplicationWebRouterBase extends JApplicationWebRouter | |
{ | |
/** | |
* @var array An array of rules, each rule being an associative array('regex'=> $regex, 'vars' => $vars, 'controller' => $controller) | |
* for routing the request. | |
* @since 12.3 | |
*/ | |
protected $maps = array(); | |
/** | |
* Add a route map to the router. If the pattern already exists it will be overwritten. | |
* | |
* @param string $pattern The route pattern to use for matching. | |
* @param string $controller The controller name to map to the given pattern. | |
* | |
* @return JApplicationWebRouter This object for method chaining. | |
* | |
* @since 12.3 | |
*/ | |
public function addMap($pattern, $controller) | |
{ | |
// Sanitize and explode the pattern. | |
$pattern = explode('/', trim(parse_url((string) $pattern, PHP_URL_PATH), ' /')); | |
// Prepare the route variables | |
$vars = array(); | |
// Initialize regular expression | |
$regex = array(); | |
// Loop on each segment | |
foreach ($pattern as $segment) | |
{ | |
// Match any number of segments | |
if ($segment == '*') | |
{ | |
$regex[] = '.*'; | |
} | |
// Match segment '\*' | |
elseif ($segment == '\*') | |
{ | |
$regex[] = '/'; | |
$regex[] = '\*'; | |
} | |
// Match unnamed var | |
elseif ($segment == ':') | |
{ | |
$regex[] = '/'; | |
$regex[] = '[^/]*'; | |
} | |
// Match named var | |
elseif ($segment[0] == ':') | |
{ | |
$vars[] = substr($segment, 1); | |
$regex[] = '/'; | |
$regex[] = '([^/]*)'; | |
} | |
// Match segment starting with '\\:' | |
elseif ($segment[0] == '\\' && $segment[1] == ':') | |
{ | |
$regex[] = '/'; | |
$regex[] = preg_quote(substr($segment, 1)); | |
} | |
// Regular segment | |
else | |
{ | |
$regex[] = '/'; | |
$regex[] = preg_quote($segment); | |
} | |
} | |
// Sanitize regex | |
if ($regex[0] == '/') | |
{ | |
$regex = array_slice($regex, 1); | |
} | |
$this->maps[] = array( | |
'regex' => chr(1) . '^' . implode($regex) . '$' . chr(1), | |
'vars' => $vars, | |
'controller' => (string) $controller | |
); | |
return $this; | |
} | |
/** | |
* Add a route map to the router. If the pattern already exists it will be overwritten. | |
* | |
* @param array $maps A list of route maps to add to the router as $pattern => $controller. | |
* | |
* @return JApplicationWebRouter This object for method chaining. | |
* | |
* @since 12.3 | |
*/ | |
public function addMaps($maps) | |
{ | |
foreach ($maps as $pattern => $controller) | |
{ | |
$this->addMap($pattern, $controller); | |
} | |
return $this; | |
} | |
/** | |
* Parse the given route and return the name of a controller mapped to the given route. | |
* | |
* @param string $route The route string for which to find and execute a controller. | |
* | |
* @return string The controller name for the given route excluding prefix. | |
* | |
* @since 12.3 | |
* @throws InvalidArgumentException | |
*/ | |
protected function parseRoute($route) | |
{ | |
// Initialize variables. | |
$controller = false; | |
// Sanitize and explode the route. | |
$route = trim(parse_url($route, PHP_URL_PATH), ' /'); | |
// If the route is empty then simply return the default route. No parsing necessary. | |
if ($route == '') | |
{ | |
return $this->default; | |
} | |
// Iterate through all of the known route maps looking for a match. | |
foreach ($this->maps as $rule) | |
{ | |
if (preg_match($rule['regex'], $route, $matches)) | |
{ | |
// If we have gotten this far then we have a positive match. | |
$controller = $rule['controller']; | |
// Time to set the input variables. | |
// We are only going to set them if they don't already exist to avoid overwriting things. | |
foreach ($rule['vars'] as $i => $var) | |
{ | |
$this->input->def($var, $matches[$i + 1]); | |
// Don't forget to do an explicit set on the GET superglobal. | |
$this->input->get->def($var, $matches[$i + 1]); | |
} | |
break; | |
} | |
} | |
// We were unable to find a route match for the request. Panic. | |
if (!$controller) | |
{ | |
throw new InvalidArgumentException(sprintf('Unable to handle request for route `%s`.', $route), 404); | |
} | |
return $controller; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @package Joomla.UnitTest | |
* @subpackage Application | |
* | |
* @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. | |
* @license GNU General Public License version 2 or later; see LICENSE | |
*/ | |
/** | |
* Test class for JApplicationWebRouterBase. | |
* | |
* @package Joomla.UnitTest | |
* @subpackage Application | |
* @since 12.3 | |
*/ | |
class JApplicationWebRouterBaseTest extends TestCase | |
{ | |
/** | |
* @var JApplicationWebRouterBase The object to be tested. | |
* @since 12.3 | |
*/ | |
private $_instance; | |
/** | |
* @var JInput The JInput object to be inspected for route variables. | |
* @since 12.3 | |
*/ | |
private $_input; | |
/** | |
* Provides test data for route parsing. | |
* | |
* @return array | |
* | |
* @since 12.3 | |
*/ | |
public static function getParseRouteData() | |
{ | |
// Route, Exception, ControllerName, InputData, MapSet | |
return array( | |
array('', false, 'home', array(), 1), | |
array('articles/4', true, 'home', array(), 1), | |
array('', false, 'index', array(), 2), | |
array('login', false, 'login', array(), 2), | |
array('articles', false, 'articles', array(), 2), | |
array('articles/4', false, 'article', array('article_id' => 4), 2), | |
array('articles/4/crap', true, '', array(), 2), | |
array('test', true, '', array(), 2), | |
array('test/foo', true, '', array(), 2), | |
array('test/foo/path', true, '', array(), 2), | |
array('test/foo/path/bar', false, 'test', array('seg1' => 'foo', 'seg2' => 'bar'), 2), | |
array('content/article-1/*', false, 'content', array(), 2), | |
array('content/cat-1/article-1', false, 'article', array('category' => 'cat-1', 'article' => 'article-1'), 2), | |
array('content/cat-1/cat-2/article-1', false, 'article', array('category' => 'cat-2', 'article' => 'article-1'), 2), | |
array('content/cat-1/cat-2/cat-3/article-1', false, 'article', array('category' => 'cat-3', 'article' => 'article-1'), 2) | |
); | |
} | |
/** | |
* Tests the addMap method. | |
* | |
* @return void | |
* | |
* @covers JApplicationWebRouterBase::addMap | |
* @since 12.3 | |
*/ | |
public function testAddMap() | |
{ | |
$this->assertAttributeEmpty('maps', $this->_instance); | |
$this->_instance->addMap('foo', 'MyApplicationFoo'); | |
$this->assertAttributeEquals(array(array('regex' => chr(1) . '^foo$' . chr(1), 'vars' => array(), 'controller' => 'MyApplicationFoo')), 'maps', $this->_instance); | |
} | |
/** | |
* Tests the addMaps method. | |
* | |
* @return void | |
* | |
* @covers JApplicationWebRouterBase::addMaps | |
* @since 12.3 | |
*/ | |
public function testAddMaps() | |
{ | |
$maps = array( | |
'login' => 'login', | |
'logout' => 'logout', | |
'requests' => 'requests', | |
'requests/:request_id' => 'request' | |
); | |
$rules = array( | |
array( | |
'regex' => chr(1) . '^login$' . chr(1), | |
'vars' => array(), | |
'controller' => 'login' | |
), | |
array( | |
'regex' => chr(1) . '^logout$' . chr(1), | |
'vars' => array(), | |
'controller' => 'logout' | |
), | |
array( | |
'regex' => chr(1) . '^requests$' . chr(1), | |
'vars' => array(), | |
'controller' => 'requests' | |
), | |
array( | |
'regex' => chr(1) . '^requests/([^/]*)$' . chr(1), | |
'vars' => array('request_id'), | |
'controller' => 'request' | |
) | |
); | |
$this->assertAttributeEmpty('maps', $this->_instance); | |
$this->_instance->addMaps($maps); | |
$this->assertAttributeEquals($rules, 'maps', $this->_instance); | |
} | |
/** | |
* Tests the JApplicationWebRouterBase::parseRoute method. | |
* | |
* @param string $r The route to parse. | |
* @param boolean $e True if an exception is expected. | |
* @param string $c The expected controller name. | |
* @param array $i The expected input object data. | |
* @param integer $m The map set to use for setting up the router. | |
* | |
* @return void | |
* | |
* @covers JApplicationWebRouterBase::parseRoute | |
* @dataProvider getParseRouteData | |
* @since 12.3 | |
*/ | |
public function testParseRoute($r, $e, $c, $i, $m) | |
{ | |
// Setup the router maps. | |
$mapSetup = 'setMaps' . $m; | |
$this->$mapSetup(); | |
// If we should expect an exception set that up. | |
if ($e) | |
{ | |
$this->setExpectedException('InvalidArgumentException'); | |
} | |
// Execute the route parsing. | |
$actual = TestReflection::invoke($this->_instance, 'parseRoute', $r); | |
// Test the assertions. | |
$this->assertEquals($c, $actual, 'Incorrect controller name found.'); | |
$this->assertAttributeEquals($i, 'data', $this->_input, 'The input data is incorrect.'); | |
} | |
/** | |
* Setup the router maps to option 1. | |
* | |
* This has no routes but has a default controller for the home page. | |
* | |
* @return void | |
* | |
* @since 12.3 | |
*/ | |
protected function setMaps1() | |
{ | |
$this->_instance->addMaps(array()); | |
$this->_instance->setDefaultController('home'); | |
} | |
/** | |
* Setup the router maps to option 2. | |
* | |
* @return void | |
* | |
* @since 12.3 | |
*/ | |
protected function setMaps2() | |
{ | |
$this->_instance->addMaps( | |
array( | |
'login' => 'login', | |
'logout' => 'logout', | |
'articles' => 'articles', | |
'articles/:article_id' => 'article', | |
'test/:seg1/path/:seg2' => 'test', | |
'content/:/\*' => 'content', | |
'content/*/:category/:article' => 'article' | |
) | |
); | |
$this->_instance->setDefaultController('index'); | |
} | |
/** | |
* Prepares the environment before running a test. | |
* | |
* @return void | |
* | |
* @since 12.3 | |
*/ | |
protected function setUp() | |
{ | |
parent::setUp(); | |
// Construct the clean JInput object. | |
$this->_input = new JInput(array()); | |
$this->_instance = new JApplicationWebRouterBase($this->getMockWeb(), $this->_input); | |
} | |
/** | |
* Cleans up the environment after running a test. | |
* | |
* @return void | |
* | |
* @since 12.3 | |
*/ | |
protected function tearDown() | |
{ | |
$this->_instance = null; | |
parent::tearDown(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment