Permalink
Browse files

Merge pull request #12 from elazar/route-filters

Added support for route filters to the application and dispatcher classes
  • Loading branch information...
whatthejeff committed Jun 29, 2011
2 parents 6922779 + ca883a8 commit 4caae2b3c53d121bd3461e8903be86e15fdcd037
View
@@ -159,6 +159,28 @@ put('/process_my_form', function(){
});
```
### Route Filters
In some cases, routes patterns require a global modification, such as prepending a base path when the application is running in a subdirectory of the document root and web server-level URL rewrites are not an available or desirable option. Route filters are callbacks that are executed on each route pattern before it's evaluated against the current request.
**bootstrap.php:**
``` php
config('base_dir', '/subdir');
route(function($pattern) {
return config('base_dir') . $pattern;
});
```
**Controller.php:**
``` php
// This route will actually resolve to /subdir/foo
$app->get('/foo', function() {
// ...
});
```
Pass
----
View
@@ -115,6 +115,32 @@ function before()
);
}
/**
* Defines a new route filter.
*
* Closure `$filter` will be invoked on each route pattern before it's
* evaluated against the current request.
*
* NOTE: If you call `route()` multiple times, each callback will be invoked
* in the order it was defined.
*
* @code
* route(function($pattern){
* return '/subdir' . $pattern;
* });
* @endcode
*
* @param Closure $filter The filter to add.
*
* @return void
*/
function route()
{
return call_user_func_array(
array(Application::getInstance('breeze'), 'route'), func_get_args()
);
}
/**
* Defines or dispatches a condition.
*
View
@@ -1497,16 +1497,21 @@ public function dispatch($requestMethod = null, $requestUri = null)
$this->setRequestMethod($requestMethod);
if (isset($this->_routes[$this->_requestMethod])) {
$filters = $this->_application->getRouteFilters();
foreach ($this->_routes[$this->_requestMethod] as $route) {
$pattern = $route['pattern'];
foreach ($filters as $filter) {
$pattern = $filter($pattern);
}
try {
if ($route['pattern']{0} != '/') {
if ($pattern{0} != '/') {
$this->_processRegexpRoute(
$route['pattern'],
$pattern,
$route['handler']
);
} else {
$this->_processRoute(
$route['pattern'], $route['handler']
$pattern, $route['handler']
);
}
} catch (PassException $exception) {
@@ -1991,6 +1996,12 @@ class Application
* @var Breeze\ClosuresCollection
*/
protected $_filters = array();
/**
* User-defined route filters.
*
* @var Breeze\ClosuresCollection
*/
protected $_routeFilters;
/**
* Initializes defined plugins and allows for overriding of default
@@ -2034,6 +2045,9 @@ public function __construct(Configurations $configurations = null)
'after_filters_object', 'Breeze\\ClosuresCollection'
)
);
$this->_routeFilters = $this->_getDependency(
'route_filters_object', 'Breeze\\ClosuresCollection'
);
foreach (self::$_plugins as $plugin) {
$plugin($this);
@@ -2094,6 +2108,7 @@ public function __clone()
$this->_conditions = clone $this->_conditions;
$this->_status = clone $this->_status;
$this->_userHelpers = clone $this->_userHelpers;
$this->_routeFilters = clone $this->_routeFilters;
$this->_filters[self::BEFORE] = clone $this->_filters[self::BEFORE];
$this->_filters[self::AFTER] = clone $this->_filters[self::AFTER];
@@ -2504,6 +2519,16 @@ public function getUserHelpers()
return array_keys($this->_userHelpers->all());
}
/**
* Gets a list of all user-defined route filters.
*
* @return array All user-defined route filters.
*/
public function getRouteFilters()
{
return $this->_routeFilters->all();
}
/**
* Adds a filter to be executed before the request is routed.
*
@@ -2516,6 +2541,19 @@ public function before($filter)
$this->_filters[self::BEFORE]->add($filter);
}
/**
* Adds a filter to be executed on each route before evaluating it
* against the current request.
*
* @param Closure $filter The filter to add.
*
* @return void
*/
public function route($filter)
{
$this->_routeFilters->add($filter);
}
/**
* Adds a filter to be executed after the request is routed.
*
@@ -2578,4 +2616,4 @@ public function run($requestMethod = null, $requestUri = null)
// to the end of a Breeze request
}
}
}
}
@@ -783,6 +783,18 @@ public function testAddAfterFilter()
$this->_application->after($closure);
}
/**
* Tests {@link Breeze\Application::route()} to add a route filter.
*/
public function testAddRouteFilter()
{
$closure = function(){};
$this->_mocks['route_filters_object']->expects($this->once())
->method('add')
->with($this->equalTo($closure));
$this->_application->route($closure);
}
/**
* Tests {@link Breeze\Application::filter()} with a bad filter type throws
* an InvalidArgumentException.
@@ -1006,8 +1018,12 @@ public function testCloneIsDeep()
->method('add');
$clone->after(function(){});
$this->_mocks['route_filters_object']->expects($this->never())
->method('add');
$clone->route(function(){});
$this->_configurations->expects($this->never())
->method('set');
$clone->config('jeff', 'is cool');
}
}
}
@@ -90,6 +90,9 @@ protected function _setupMockedDependencies()
$this->_mocks['after_filters_object'] = $this->getMock(
'Breeze\\ClosuresCollection', array(), array(), '', FALSE
);
$this->_mocks['route_filters_object'] = $this->getMock(
'Breeze\\ClosuresCollection', array(), array(), '', FALSE
);
$this->_configurations = $this->getMock(
'Breeze\\Configurations', array(), array(), '', FALSE
@@ -129,11 +129,25 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase
* @return void
*/
public function setUp()
{
$this->_mockApplication();
$this->_dispatcher = new Dispatcher($this->_application);
}
/**
* Configures a mock application instance.
*
* @param array $routeFilterCallbacks Optional list of router filter
* callbacks to add
*/
protected function _mockApplication(array $routeFilterCallbacks = array())
{
$this->_application = $this->getMock(
'Breeze\\Application', array(), array(), '', FALSE
'Breeze\\Application', array('getRouteFilters'), array(), '', FALSE
);
$this->_dispatcher = new Dispatcher($this->_application);
$this->_application->expects($this->any())
->method('getRouteFilters')
->will($this->returnValue($routeFilterCallbacks));
}
/**
@@ -235,6 +249,24 @@ public function testSetRequestUriWithParameter()
});
}
/**
* Tests {@link Breeze\Dispatcher\Dispatcher::dispatch()} with route
* filters added.
*/
public function testDispatchWithRouteFilters()
{
$bar = function($pattern) { return $pattern . '/bar'; };
$baz = function($pattern) { return $pattern . '/baz'; };
$this->_mockApplication(array($bar, $baz));
$this->_dispatcher = new Dispatcher($this->_application);
$success = false;
$this->_dispatcher->get('/foo', function() use (&$success) {
$success = true;
});
$this->_dispatcher->dispatch('GET', '/foo/bar/baz');
$this->assertTrue($success);
}
/**
* Tests {@link Breeze\Dispatcher\Dispatcher::setRequestUri()} to
* set the requested URI from the $_SERVER['REQUEST_URI'] superglobal.

0 comments on commit 4caae2b

Please sign in to comment.