Skip to content

Commit

Permalink
Merge pull request #4525 from cakephp/3.0-router-extensions
Browse files Browse the repository at this point in the history
3.0 router extensions
  • Loading branch information
ADmad committed Sep 7, 2014
2 parents d07e363 + f52bf79 commit 1fa7a93
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 94 deletions.
6 changes: 3 additions & 3 deletions src/Controller/Component/RequestHandlerComponent.php
Expand Up @@ -63,7 +63,7 @@ class RequestHandlerComponent extends Component {
* Contains the file extension parsed out by the Router
*
* @var string
* @see Router::parseExtensions()
* @see Router::extensions()
*/
public $ext = null;

Expand Down Expand Up @@ -149,7 +149,7 @@ public function implementedEvents() {
*
* @param Event $event The initialize event that was fired.
* @return void
* @see Router::parseExtensions()
* @see Router::extensions()
*/
public function initialize(Event $event) {
if (isset($this->request->params['_ext'])) {
Expand Down Expand Up @@ -207,7 +207,7 @@ protected function _setExtension() {
* The startup method of the RequestHandler enables several automatic behaviors
* related to the detection of certain properties of the HTTP request, including:
*
* - If Router::parseExtensions() is enabled, the layout and template type are
* - If Router::extensions() is enabled, the layout and template type are
* switched based on the parsed extension or Accept-Type header. For example, if `controller/action.xml`
* is requested, the view path becomes `app/View/Controller/xml/action.ctp`. Also if
* `controller/action` is requested with `Accept-Type: application/xml` in the headers
Expand Down
8 changes: 4 additions & 4 deletions src/Routing/RouteBuilder.php
Expand Up @@ -219,7 +219,7 @@ public function params() {
* - 'actions' - Override the method names used for connecting actions.
*
* @param string $name A controller name to connect resource routes for.
* @param array $options Options to use when generating REST routes
* @param array|callable $options Options to use when generating REST routes, or a callback.
* @param callable $callback An optional callback to be executed in a nested scope. Nested
* scopes inherit the existing path and 'id' parameter.
* @return array Array of mapped resources
Expand Down Expand Up @@ -440,7 +440,7 @@ protected function _makeRoute($route, $defaults, $options) {
* shifted into the passed arguments. As well as supplying patterns for routing parameters.
* @return array Array of routes
*/
public function redirect($route, $url, $options = []) {
public function redirect($route, $url, array $options = []) {
$options['routeClass'] = 'Cake\Routing\Route\RedirectRoute';
if (is_string($url)) {
$url = array('redirect' => $url);
Expand Down Expand Up @@ -514,8 +514,8 @@ public function plugin($name, $options = [], $callback = null) {
* to the supplied parameters.
*
* @param string $path The path to create a scope for.
* @param array|callable $params Either the parameters to add to routes, or a callback
* @param callable $callback The callback to invoke that builds the plugin routes
* @param array|callable $params Either the parameters to add to routes, or a callback.
* @param callable $callback The callback to invoke that builds the plugin routes.
* Only required when $params is defined.
* @return void
* @throws \InvalidArgumentException when there is no callable parameter.
Expand Down
34 changes: 18 additions & 16 deletions src/Routing/RouteCollection.php
Expand Up @@ -74,7 +74,7 @@ class RouteCollection {
* `_name` option, which enables named routes.
* @return void
*/
public function add(Route $route, $options = []) {
public function add(Route $route, array $options = []) {
$this->_routes[] = $route;

// Explicit names
Expand All @@ -99,7 +99,7 @@ public function add(Route $route, $options = []) {

$extensions = $route->extensions();
if ($extensions) {
$this->addExtensions($extensions);
$this->extensions($extensions);
}
}

Expand Down Expand Up @@ -274,27 +274,29 @@ public function named() {
return $this->_named;
}

/**
* Add one or more extensions.
*
* @param array $extensions The extensions to add.
* @return void
*/
public function addExtensions(array $extensions) {
$this->_extensions = array_unique(array_merge($this->_extensions, $extensions));
}

/**
* Get/set the extensions that the route collection could handle.
*
* @param null|string|array $extensions Either the list of extensions to set, or null to get.
* @param null|string|array $extensions Either the list of extensions to set,
* or null to get.
* @param bool $merge Whether to merge with or override existing extensions.
* Defaults to `true`.
* @return array The valid extensions.
*/
public function extensions($extensions = null) {
public function extensions($extensions = null, $merge = true) {
if ($extensions === null) {
return array_unique($this->_extensions);
return $this->_extensions;
}

$extensions = (array)$extensions;
if ($merge) {
$extensions = array_unique(array_merge(
$this->_extensions,
$extensions
));
}
$this->_extensions = (array)$extensions;

return $this->_extensions = $extensions;
}

}
63 changes: 33 additions & 30 deletions src/Routing/Router.php
Expand Up @@ -709,47 +709,50 @@ public static function normalize($url = '/') {
}

/**
* Set/add valid extensions. Instructs the router to parse out file extensions
* Deprecated method for backwards compatibility.
*
* @param string|array $extensions List of extensions to be added.
* @param bool $merge Whether to merge with or override existing extensions.
* Defaults to `true`.
* @return array Extensions list.
* @deprecated 3.0.0 Use Router::extensions() instead.
*/
public static function parseExtensions($extensions = null, $merge = true) {
trigger_error(
'Router::parseExtensions() is deprecated should use Router::extensions() instead.',
E_USER_DEPRECATED
);
return static::extensions($extensions, $merge);
}

/**
* Get/Set valid extensions. Instructs the router to parse out file extensions
* from the URL. For example, http://example.com/posts.rss would yield a file
* extension of "rss". The file extension itself is made available in the
* controller as `$this->params['_ext']`, and is used by the RequestHandler
* controller as `$this->request->params['_ext']`, and is used by the RequestHandler
* component to automatically switch to alternate layouts and templates, and
* load helpers corresponding to the given content, i.e. RssHelper. Switching
* layouts and helpers requires that the chosen extension has a defined mime type
* in `Cake\Network\Response`.
*
* An array of valid extension can be passed to this method. If called without
* any parameters it will return current list of set extensions.
* A string or an array of valid extensions can be passed to this method.
* If called without any parameters it will return current list of set extensions.
*
* @param array|string $extensions List of extensions to be added as valid extension
* @param bool $merge Default true will merge extensions. Set to false to override
* current extensions
* @return array
* @param array|string $extensions List of extensions to be added.
* @param bool $merge Whether to merge with or override existing extensions.
* Defaults to `true`.
* @return array Array of extensions Router is configured to parse.
*/
public static function parseExtensions($extensions = null, $merge = true) {
public static function extensions($extensions = null, $merge = true) {
$collection = static::$_collection;
if ($extensions === null) {
if (!static::$initialized) {
static::_loadRoutes();
}
return $collection->extensions();
}
$extensions = (array)$extensions;
if ($merge) {
$extensions = array_merge($collection->extensions(), $extensions);
}
return $collection->extensions($extensions);
}

/**
* Get the list of extensions that can be parsed by Router.
*
* To add / update extensions use `Router::parseExtensions()`
*
* @return array Array of extensions Router is configured to parse.
*/
public static function extensions() {
if (!static::$initialized) {
static::_loadRoutes();
}
return static::$_collection->extensions();
return $collection->extensions($extensions, $merge);
}

/**
Expand All @@ -768,7 +771,7 @@ public static function extensions() {
* @param array $options The array of options.
* @return \Cake\Network\Request The modified request
*/
public static function parseNamedParams(Request $request, $options = []) {
public static function parseNamedParams(Request $request, array $options = []) {
$options += array('separator' => ':');
if (empty($request->params['pass'])) {
$request->params['named'] = [];
Expand Down Expand Up @@ -829,12 +832,12 @@ public static function parseNamedParams(Request $request, $options = []) {
* specific kinds of scopes.
*
* Routing scopes will inherit the globally set extensions configured with
* Router::parseExtensions(). You can also set valid extensions using
* Router::extensions(). You can also set valid extensions using
* `$routes->extensions()` in your closure.
*
* @param string $path The path prefix for the scope. This path will be prepended
* to all routes connected in the scoped collection.
* @param array $params An array of routing defaults to add to each connected route.
* @param array|callable $params An array of routing defaults to add to each connected route.
* If you have no parameters, this argument can be a callable.
* @param callable $callback The callback to invoke with the scoped collection.
* @throws \InvalidArgumentException When an invalid callable is provided.
Expand Down
32 changes: 16 additions & 16 deletions tests/TestCase/Controller/Component/RequestHandlerComponentTest.php
Expand Up @@ -125,7 +125,7 @@ public function testInitializeCallback() {
public function testInitializeContentTypeSettingExt() {
$event = new Event('Controller.initialize', $this->Controller);
$_SERVER['HTTP_ACCEPT'] = 'application/json';
Router::parseExtensions('json', false);
Router::extensions('json', false);

$this->assertNull($this->RequestHandler->ext);

Expand All @@ -143,7 +143,7 @@ public function testInitializeContentTypeWithjQueryAccept() {
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions('json', false);
Router::extensions('json', false);

$this->RequestHandler->initialize($event);
$this->assertEquals('json', $this->RequestHandler->ext);
Expand All @@ -158,7 +158,7 @@ public function testInitializeContentTypeWithjQueryTextPlainAccept() {
$_SERVER['HTTP_ACCEPT'] = 'text/plain, */*; q=0.01';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions('csv', false);
Router::extensions('csv', false);

$this->RequestHandler->initialize($event);
$this->assertNull($this->RequestHandler->ext);
Expand All @@ -174,7 +174,7 @@ public function testInitializeContentTypeWithjQueryAcceptAndMultiplesExtensions(
$_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, */*; q=0.01';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions(['rss', 'json'], false);
Router::extensions(['rss', 'json'], false);

$this->RequestHandler->initialize($event);
$this->assertEquals('json', $this->RequestHandler->ext);
Expand All @@ -189,7 +189,7 @@ public function testInitializeNoContentTypeWithSingleAccept() {
$_SERVER['HTTP_ACCEPT'] = 'application/json, text/html, */*; q=0.01';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions('json', false);
Router::extensions('json', false);

$this->RequestHandler->initialize($event);
$this->assertNull($this->RequestHandler->ext);
Expand All @@ -207,13 +207,13 @@ public function testInitializeNoContentTypeWithMultipleAcceptedTypes() {
$_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, application/xml, */*; q=0.01';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions(['xml', 'json'], false);
Router::extensions(['xml', 'json'], false);

$this->RequestHandler->initialize($event);
$this->assertEquals('xml', $this->RequestHandler->ext);

$this->RequestHandler->ext = null;
Router::parseExtensions(array('json', 'xml'), false);
Router::extensions(array('json', 'xml'), false);

$this->RequestHandler->initialize($event);
$this->assertEquals('json', $this->RequestHandler->ext);
Expand All @@ -228,7 +228,7 @@ public function testInitializeContentTypeWithMultipleAcceptedTypes() {
$_SERVER['HTTP_ACCEPT'] = 'text/csv;q=1.0, application/json;q=0.8, application/xml;q=0.7';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions(['xml', 'json'], false);
Router::extensions(['xml', 'json'], false);

$this->RequestHandler->initialize($event);
$this->assertEquals('json', $this->RequestHandler->ext);
Expand All @@ -243,7 +243,7 @@ public function testInitializeAmbiguousAndroidAccepts() {
$_SERVER['HTTP_ACCEPT'] = 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5';
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
Router::parseExtensions(['html', 'xml'], false);
Router::extensions(['html', 'xml'], false);

$this->RequestHandler->initialize($event);
$this->assertNull($this->RequestHandler->ext);
Expand All @@ -256,7 +256,7 @@ public function testInitializeAmbiguousAndroidAccepts() {
*/
public function testInititalizeFirefoxHeaderNotXml() {
$_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;image/png,image/jpeg,image/*;q=0.9,*/*;q=0.8';
Router::parseExtensions(['xml', 'json'], false);
Router::extensions(['xml', 'json'], false);

$event = new Event('Controller.initialize', $this->Controller);
$this->RequestHandler->initialize($event);
Expand All @@ -272,7 +272,7 @@ public function testInitializeContentTypeAndExtensionMismatch() {
$event = new Event('Controller.initialize', $this->Controller);
$this->assertNull($this->RequestHandler->ext);
$extensions = Router::extensions();
Router::parseExtensions('xml', false);
Router::extensions('xml', false);

$this->Controller->request = $this->getMock('Cake\Network\Request', ['accepts']);
$this->Controller->request->expects($this->any())
Expand All @@ -282,7 +282,7 @@ public function testInitializeContentTypeAndExtensionMismatch() {
$this->RequestHandler->initialize($event);
$this->assertNull($this->RequestHandler->ext);

call_user_func_array(array('Cake\Routing\Router', 'parseExtensions'), [$extensions, false]);
call_user_func_array(array('Cake\Routing\Router', 'extensions'), [$extensions, false]);
}

/**
Expand Down Expand Up @@ -359,7 +359,7 @@ public function testAutoAjaxLayout() {
* @return void
*/
public function testJsonViewLoaded() {
Router::parseExtensions(['json', 'xml', 'ajax'], false);
Router::extensions(['json', 'xml', 'ajax'], false);
$this->Controller->request->params['_ext'] = 'json';
$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->initialize($event);
Expand All @@ -376,7 +376,7 @@ public function testJsonViewLoaded() {
* @return void
*/
public function testXmlViewLoaded() {
Router::parseExtensions(['json', 'xml', 'ajax'], false);
Router::extensions(['json', 'xml', 'ajax'], false);
$this->Controller->request->params['_ext'] = 'xml';
$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->initialize($event);
Expand All @@ -393,7 +393,7 @@ public function testXmlViewLoaded() {
* @return void
*/
public function testAjaxViewLoaded() {
Router::parseExtensions(['json', 'xml', 'ajax'], false);
Router::extensions(['json', 'xml', 'ajax'], false);
$this->Controller->request->params['_ext'] = 'ajax';
$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->initialize($event);
Expand All @@ -409,7 +409,7 @@ public function testAjaxViewLoaded() {
* @return void
*/
public function testNoViewClassExtension() {
Router::parseExtensions(['json', 'xml', 'ajax', 'csv'], false);
Router::extensions(['json', 'xml', 'ajax', 'csv'], false);
$this->Controller->request->params['_ext'] = 'csv';
$event = new Event('Controller.startup', $this->Controller);
$this->RequestHandler->initialize($event);
Expand Down
6 changes: 3 additions & 3 deletions tests/TestCase/Routing/RouteCollectionTest.php
Expand Up @@ -305,10 +305,10 @@ public function testExtensions() {
$this->assertEquals(['json'], $this->collection->extensions());

$this->collection->extensions(['rss', 'xml']);
$this->assertEquals(['rss', 'xml'], $this->collection->extensions());
$this->assertEquals(['json', 'rss', 'xml'], $this->collection->extensions());

$this->collection->addExtensions(['json']);
$this->assertEquals(['rss', 'xml', 'json'], $this->collection->extensions());
$this->collection->extensions(['csv'], false);
$this->assertEquals(['csv'], $this->collection->extensions());
}

}

0 comments on commit 1fa7a93

Please sign in to comment.