Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for route filters to the application and dispatcher classes #12

Merged
merged 2 commits into from
Jun 29, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
----

Expand Down
26 changes: 26 additions & 0 deletions lib/Breeze.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
46 changes: 42 additions & 4 deletions lib/Breeze/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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.
*
Expand All @@ -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.
*
Expand Down Expand Up @@ -2578,4 +2616,4 @@ public function run($requestMethod = null, $requestUri = null)
// to the end of a Breeze request
}
}
}
}
18 changes: 17 additions & 1 deletion test/Breeze/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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');
}
}
}
3 changes: 3 additions & 0 deletions test/Breeze/ApplicationTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 35 additions & 3 deletions test/Breeze/Dispatcher/DispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/**
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -482,4 +514,4 @@ function() use ($uri) {
}
}
}
}
}