Skip to content

Commit

Permalink
Rename [method] to _method.
Browse files Browse the repository at this point in the history
This makes the more commonly used `_method` option congruent with other
'special keys' like _ssl and _host.

Include some backwards compatibility for creating routes, and generating
URLs.
  • Loading branch information
markstory committed Jul 15, 2014
1 parent c9df9b8 commit 80066a2
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 44 deletions.
24 changes: 19 additions & 5 deletions src/Routing/Route/Route.php
Expand Up @@ -85,7 +85,6 @@ class Route {
*/
protected $_headerMap = [
'type' => 'content_type',
'method' => 'request_method',
'server' => 'server_name'
];

Expand Down Expand Up @@ -117,6 +116,10 @@ public function __construct($template, $defaults = [], array $options = []) {
if (isset($this->options['_name'])) {
$this->_name = $this->options['_name'];
}
if (isset($this->defaults['[method]'])) {
$this->defaults['_method'] = $this->defaults['[method]'];
unset($this->defaults['[method]']);
}
if (isset($this->options['_ext'])) {
$this->_extensions = $this->options['_ext'];
}
Expand Down Expand Up @@ -272,6 +275,14 @@ public function parse($url) {
if (!preg_match($this->_compiledRoute, urldecode($url), $route)) {
return false;
}

if (isset($this->defaults['_method'])) {
$method = $request->env('REQUEST_METHOD');
if (!in_array($method, (array)$this->defaults['_method'], true)) {
return false;
}
}

foreach ($this->defaults as $key => $val) {
$key = (string)$key;
if ($key[0] === '[' && preg_match('/^\[(\w+)\]$/', $key, $header)) {
Expand Down Expand Up @@ -442,7 +453,7 @@ public function match(array $url, array $context = []) {
if (!$this->_matchMethod($url)) {
return false;
}
unset($url['[method]'], $defaults['[method]']);
unset($url['_method'], $url['[method]'], $defaults['_method']);

// Missing defaults is a fail.
if (array_diff_key($defaults, $url) !== []) {
Expand Down Expand Up @@ -513,13 +524,16 @@ public function match(array $url, array $context = []) {
* @return bool
*/
protected function _matchMethod($url) {
if (empty($this->defaults['[method]'])) {
if (empty($this->defaults['_method'])) {
return true;
}
if (empty($url['[method]'])) {
if (isset($url['[method]'])) {
$url['_method'] = $url['[method]'];
}
if (empty($url['_method'])) {
return false;
}
if (!in_array(strtoupper($url['[method]']), (array)$this->defaults['[method]'])) {
if (!in_array(strtoupper($url['_method']), (array)$this->defaults['_method'])) {
return false;
}
return true;
Expand Down
8 changes: 4 additions & 4 deletions src/Routing/RouteBuilder.php
Expand Up @@ -230,7 +230,7 @@ public function resources($name, $options = [], $callback = null) {
$params = array(
'controller' => $name,
'action' => $action,
'[method]' => $params['method'],
'_method' => $params['method'],
'_ext' => $ext
);
$routeOptions = $connectOptions + [
Expand Down Expand Up @@ -294,17 +294,17 @@ public function resources($name, $options = [], $callback = null) {
* connected route.
* - `_ext` is an array of filename extensions that will be parsed out of the url if present.
* See {@link ScopedRouteCollection::extensions()}.
* - `_method` Only match requests with specific HTTP verbs.
*
* You can also add additional conditions for matching routes to the $defaults array.
* The following conditions can be used:
*
* - `[type]` Only match requests for specific content types.
* - `[method]` Only match requests with specific HTTP verbs.
* - `[server]` Only match when $_SERVER['SERVER_NAME'] matches the given value.
*
* Example of using the `[method]` condition:
* Example of using the `_method` condition:
*
* `$routes->connect('/tasks', array('controller' => 'Tasks', 'action' => 'index', '[method]' => 'GET'));`
* `$routes->connect('/tasks', array('controller' => 'Tasks', 'action' => 'index', '_method' => 'GET'));`
*
* The above route will only be matched for GET requests. POST requests will fail to match this route.
*
Expand Down
47 changes: 37 additions & 10 deletions tests/TestCase/Routing/Route/RouteTest.php
Expand Up @@ -643,15 +643,15 @@ public function testParseWithPassDefaults() {
*/
public function testParseWithHttpHeaderConditions() {
$_SERVER['REQUEST_METHOD'] = 'GET';
$route = new Route('/sample', ['controller' => 'posts', 'action' => 'index', '[method]' => 'POST']);
$route = new Route('/sample', ['controller' => 'posts', 'action' => 'index', '_method' => 'POST']);
$this->assertFalse($route->parse('/sample'));

$_SERVER['REQUEST_METHOD'] = 'POST';
$expected = [
'controller' => 'posts',
'action' => 'index',
'pass' => [],
'[method]' => 'POST',
'_method' => 'POST',
];
$this->assertEquals($expected, $route->parse('/sample'));
}
Expand All @@ -666,7 +666,7 @@ public function testParseWithMultipleHttpMethodConditions() {
$route = new Route('/sample', [
'controller' => 'posts',
'action' => 'index',
'[method]' => ['PUT', 'POST']
'_method' => ['PUT', 'POST']
]);
$this->assertFalse($route->parse('/sample'));

Expand All @@ -675,7 +675,7 @@ public function testParseWithMultipleHttpMethodConditions() {
'controller' => 'posts',
'action' => 'index',
'pass' => [],
'[method]' => ['PUT', 'POST'],
'_method' => ['PUT', 'POST'],
];
$this->assertEquals($expected, $route->parse('/sample'));
}
Expand All @@ -689,7 +689,7 @@ public function testMatchWithMultipleHttpMethodConditions() {
$route = new Route('/sample', [
'controller' => 'posts',
'action' => 'index',
'[method]' => ['PUT', 'POST']
'_method' => ['PUT', 'POST']
]);
$url = [
'controller' => 'posts',
Expand All @@ -700,21 +700,21 @@ public function testMatchWithMultipleHttpMethodConditions() {
$url = [
'controller' => 'posts',
'action' => 'index',
'[method]' => 'GET',
'_method' => 'GET',
];
$this->assertFalse($route->match($url));

$url = [
'controller' => 'posts',
'action' => 'index',
'[method]' => 'PUT',
'_method' => 'PUT',
];
$this->assertEquals('/sample', $route->match($url));

$url = [
'controller' => 'posts',
'action' => 'index',
'[method]' => 'POST',
'_method' => 'POST',
];
$this->assertEquals('/sample', $route->match($url));
}
Expand All @@ -730,7 +730,7 @@ public function testParseWithContentTypeCondition() {
$route = new Route('/sample', [
'controller' => 'posts',
'action' => 'index',
'[method]' => 'POST',
'_method' => 'POST',
'[type]' => 'application/xml'
]);
$this->assertFalse($route->parse('/sample'), 'No content type set.');
Expand All @@ -745,12 +745,39 @@ public function testParseWithContentTypeCondition() {
'controller' => 'posts',
'action' => 'index',
'pass' => [],
'[method]' => 'POST',
'_method' => 'POST',
'[type]' => 'application/xml',
];
$this->assertEquals($expected, $route->parse('/sample'));
}

/**
* Check [method] compatibility.
*
* @return void
*/
public function testMethodCompatibility() {
$_SERVER['REQUEST_METHOD'] = 'POST';
$route = new Route('/sample', [
'controller' => 'Articles',
'action' => 'index',
'[method]' => 'POST',
]);
$url = [
'controller' => 'Articles',
'action' => 'index',
'_method' => 'POST',
];
$this->assertEquals('/sample', $route->match($url));

$url = [
'controller' => 'Articles',
'action' => 'index',
'[method]' => 'POST',
];
$this->assertEquals('/sample', $route->match($url));
}

/**
* test that patterns work for :action
*
Expand Down
4 changes: 2 additions & 2 deletions tests/TestCase/Routing/RouteBuilderTest.php
Expand Up @@ -323,11 +323,11 @@ public function testResourcesOnlyArray() {
$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('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]']);
$this->assertEquals('DELETE', $result[1]->defaults['_method']);
}

/**
Expand Down

0 comments on commit 80066a2

Please sign in to comment.