Skip to content

Commit

Permalink
Track middleware by name.
Browse files Browse the repository at this point in the history
Track middleware by name in the builder, which will allow us to attach
the names of middleware to routes. This will allow us to resolve the
middleware by name in the middleware.
  • Loading branch information
markstory committed Jul 16, 2017
1 parent 48b882a commit 05fd40e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 7 deletions.
24 changes: 22 additions & 2 deletions src/Routing/RouteBuilder.php
Expand Up @@ -21,6 +21,7 @@
use Cake\Routing\Route\Route;
use Cake\Utility\Inflector;
use InvalidArgumentException;
use RuntimeException;

/**
* Provides features for building routes inside scopes.
Expand Down Expand Up @@ -100,6 +101,14 @@ class RouteBuilder
*/
protected $_collection;

/**
* The list of middleware that routes in this builder get
* added during construction.
*
* @var array
*/
protected $middleware = [];

/**
* Constructor
*
Expand Down Expand Up @@ -508,9 +517,10 @@ protected function _methodRoute($method, $template, $target, $name)
$name = $this->_namePrefix . $name;
}
$options = [
'_name' => $name,
'_ext' => $this->_extensions,
'_middleware' => $this->middleware,
'routeClass' => $this->_routeClass,
'_name' => $name,
];

$target['_method'] = $method;
Expand Down Expand Up @@ -646,6 +656,9 @@ public function connect($route, array $defaults = [], array $options = [])
if (isset($options['_name']) && $this->_namePrefix) {
$options['_name'] = $this->_namePrefix . $options['_name'];
}
if (empty($options['_middleware'])) {
$options['_middleware'] = $this->middleware;
}

$route = $this->_makeRoute($route, $defaults, $options);
$this->_collection->add($route, $options);
Expand Down Expand Up @@ -921,7 +934,14 @@ public function registerMiddleware($name, $middleware)
*/
public function applyMiddleware(...$names)
{
$this->_collection->applyMiddleware($this->_path, $names);
foreach ($names as $name) {
if (!$this->_collection->middlewareExists($name)) {
$message = "Cannot apply '$name' middleware or middleware group. " .
'Use registerMiddleware() to register middleware.';
throw new RuntimeException($message);
}
}
$this->middleware = array_merge($this->middleware, $names);

return $this;
}
Expand Down
44 changes: 39 additions & 5 deletions tests/TestCase/Routing/RouteBuilderTest.php
Expand Up @@ -827,6 +827,7 @@ public function testRegisterMiddleware()

$this->assertSame($result, $routes);
$this->assertTrue($this->collection->hasMiddleware('test'));
$this->assertTrue($this->collection->middlewareExists('test'));
}

/**
Expand Down Expand Up @@ -858,6 +859,7 @@ public function testMiddlewareGroup()

$this->assertSame($result, $routes);
$this->assertTrue($this->collection->hasMiddlewareGroup('group'));
$this->assertTrue($this->collection->middlewareExists('group'));
}

/**
Expand All @@ -880,7 +882,7 @@ public function testMiddlewareGroupOverlap()
* Test applying middleware to a scope when it doesn't exist
*
* @expectedException \RuntimeException
* @expectedExceptionMessage Cannot apply 'bad' middleware or middleware group to path '/api'. It has not been registered.
* @expectedExceptionMessage Cannot apply 'bad' middleware or middleware group. Use registerMiddleware() to register middleware
* @return void
*/
public function testApplyMiddlewareInvalidName()
Expand All @@ -904,10 +906,42 @@ public function testApplyMiddleware()
$result = $routes->applyMiddleware('test', 'test2');

$this->assertSame($result, $routes);
$this->assertEquals(
[$func, $func],
$this->collection->getMatchingMiddleware('/api/v1/ping')
);
}

/**
* Test that applyMiddleware() merges with previous data.
*
* @return void
*/
public function testApplyMiddlewareMerges()
{
$func = function () {
};
$routes = new RouteBuilder($this->collection, '/api');
$routes->registerMiddleware('test', $func)
->registerMiddleware('test2', $func);
$routes->applyMiddleware('test');
$routes->applyMiddleware('test2');

$this->assertAttributeEquals(['test', 'test2'], 'middleware', $routes);
}

/**
* Test applying middleware results in middleware attached to the route.
*
* @return void
*/
public function testApplyMiddlewareAttachToRoutes()
{
$func = function () {
};
$routes = new RouteBuilder($this->collection, '/api');
$routes->registerMiddleware('test', $func)
->registerMiddleware('test2', $func);
$routes->applyMiddleware('test', 'test2');
$route = $routes->get('/docs', ['controller' => 'Docs']);

$this->assertSame(['test', 'test2'], $route->getMiddleware());
}

/**
Expand Down

0 comments on commit 05fd40e

Please sign in to comment.