From 5b40e2da456f6777340f663d8daef6abb0b325b2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 13 Jul 2014 11:12:14 -0400 Subject: [PATCH] Add the actions and only options to resources(). These options let you limit which routes are connected for a resource set, and re-map the controller methods used. Refs #3962 --- src/Routing/RouteBuilder.php | 37 ++++++++----- tests/TestCase/Routing/RouteBuilderTest.php | 57 ++++++++++++++++++++- 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/Routing/RouteBuilder.php b/src/Routing/RouteBuilder.php index 90258b66d40..dbd7419e39a 100644 --- a/src/Routing/RouteBuilder.php +++ b/src/Routing/RouteBuilder.php @@ -47,14 +47,13 @@ class RouteBuilder { * * @var array */ - protected static $_resourceMap = array( - array('action' => 'index', 'method' => 'GET', 'id' => false), - array('action' => 'view', 'method' => 'GET', 'id' => true), - array('action' => 'add', 'method' => 'POST', 'id' => false), - array('action' => 'edit', 'method' => 'PUT', 'id' => true), - array('action' => 'delete', 'method' => 'DELETE', 'id' => true), - array('action' => 'edit', 'method' => 'POST', 'id' => true) - ); + protected static $_resourceMap = [ + 'index' => ['action' => 'index', 'method' => 'GET', 'id' => false], + 'create' => ['action' => 'add', 'method' => 'POST', 'id' => false], + 'view' => ['action' => 'view', 'method' => 'GET', 'id' => true], + 'update' => ['action' => 'edit', 'method' => ['PUT', 'PATCH'], 'id' => true], + 'delete' => ['action' => 'delete', 'method' => 'DELETE', 'id' => true], + ]; /** * The extensions that should be set into the routes connected. @@ -187,6 +186,8 @@ public function params() { * * - 'id' - The regular expression fragment to use when matching IDs. By default, matches * integer values and UUIDs. + * - 'only' - Only connect the specific list of actions. + * - 'actions' - Override the method names used for connecting actions. * * @param string|array $name A controller name or array of controller names (i.e. "Posts" or "ListItems") * @param array $options Options to use when generating REST routes @@ -201,10 +202,13 @@ public function resources($name, $options = [], $callback = null) { } $options += array( 'connectOptions' => [], - 'id' => static::ID . '|' . static::UUID + 'id' => static::ID . '|' . static::UUID, + 'only' => ['index', 'update', 'create', 'view', 'delete'], + 'actions' => [], ); + $options['only'] = (array)$options['only']; + $connectOptions = $options['connectOptions']; - unset($options['connectOptions']); $urlName = Inflector::underscore($name); @@ -213,12 +217,21 @@ public function resources($name, $options = [], $callback = null) { $ext = $options['_ext']; } - foreach (static::$_resourceMap as $params) { + foreach (static::$_resourceMap as $method => $params) { + if (!in_array($method, $options['only'], true)) { + continue; + } + + $action = $params['action']; + if (isset($options['actions'][$method])) { + $action = $options['actions'][$method]; + } + $id = $params['id'] ? ':id' : ''; $url = '/' . implode('/', array_filter(array($urlName, $id))); $params = array( 'controller' => $name, - 'action' => $params['action'], + 'action' => $action, '[method]' => $params['method'], '_ext' => $ext ); diff --git a/tests/TestCase/Routing/RouteBuilderTest.php b/tests/TestCase/Routing/RouteBuilderTest.php index e6afe8eb9a5..81082a987f2 100644 --- a/tests/TestCase/Routing/RouteBuilderTest.php +++ b/tests/TestCase/Routing/RouteBuilderTest.php @@ -250,13 +250,68 @@ public function testResources() { $routes->resources('Articles', ['_ext' => 'json']); $all = $this->collection->routes(); - $this->assertCount(6, $all); + $this->assertCount(5, $all); $this->assertEquals('/api/articles', $all[0]->template); $this->assertEquals('json', $all[0]->defaults['_ext']); $this->assertEquals('Articles', $all[0]->defaults['controller']); } +/** + * Test the only option of RouteBuilder. + * + * @return void + */ + public function testResourcesOnlyString() { + $routes = new RouteBuilder($this->collection, '/'); + $routes->resources('Articles', ['only' => 'index']); + + $result = $this->collection->routes(); + $this->assertCount(1, $result); + $this->assertEquals('/articles', $result[0]->template); + } + +/** + * Test the only option of RouteBuilder. + * + * @return void + */ + public function testResourcesOnlyArray() { + $routes = new RouteBuilder($this->collection, '/'); + $routes->resources('Articles', ['only' => ['index', 'delete']]); + + $result = $this->collection->routes(); + $this->assertCount(2, $result); + $this->assertEquals('/articles', $result[0]->template); + $this->assertEquals('index', $result[0]->defaults['action']); + $this->assertEquals('GET', $result[0]->defaults['[method]']); + + $this->assertEquals('/articles/:id', $result[1]->template); + $this->assertEquals('delete', $result[1]->defaults['action']); + $this->assertEquals('DELETE', $result[1]->defaults['[method]']); + } + +/** + * Test the actions option of RouteBuilder. + * + * @return void + */ + public function testResourcesActions() { + $routes = new RouteBuilder($this->collection, '/'); + $routes->resources('Articles', [ + 'only' => ['index', 'delete'], + 'actions' => ['index' => 'showList'] + ]); + + $result = $this->collection->routes(); + $this->assertCount(2, $result); + $this->assertEquals('/articles', $result[0]->template); + $this->assertEquals('showList', $result[0]->defaults['action']); + + $this->assertEquals('/articles/:id', $result[1]->template); + $this->assertEquals('delete', $result[1]->defaults['action']); + } + /** * Test nesting resources *