Skip to content

Commit

Permalink
Restore 'persist' option for routes.
Browse files Browse the repository at this point in the history
Refs #6038
  • Loading branch information
ADmad committed Mar 15, 2015
1 parent 30f9ec5 commit 7f62d57
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 4 deletions.
29 changes: 27 additions & 2 deletions src/Routing/Route/Route.php
Expand Up @@ -376,6 +376,28 @@ protected function _parseArgs($args, $context)
return $pass;
}

/**
* Apply persistent parameters to a URL array. Persistent parameters are a
* special key used during route creation to force route parameters to
* persist when omitted from a URL array.
*
* @param array $url The array to apply persistent parameters to.
* @param array $params An array of persistent values to replace persistent ones.
* @return array An array with persistent parameters applied.
*/
public function persistParams(array $url, array $params)
{
if (empty($this->options['persist']) || !is_array($this->options['persist'])) {
return $url;
}
foreach ($this->options['persist'] as $persistKey) {
if (array_key_exists($persistKey, $params) && !isset($url[$persistKey])) {
$url[$persistKey] = $params[$persistKey];
}
}
return $url;
}

/**
* Check if a URL array matches this route instance.
*
Expand All @@ -385,8 +407,8 @@ protected function _parseArgs($args, $context)
*
* @param array $url An array of parameters to check matching with.
* @param array $context An array of the current request context.
* Contains information such as the current host, scheme, port, and base
* directory.
* Contains information such as the current host, scheme, port, base
* directory and other url params.
* @return mixed Either a string url for the parameters if they match or false.
*/
public function match(array $url, array $context = [])
Expand All @@ -395,7 +417,10 @@ public function match(array $url, array $context = [])
$this->compile();
}
$defaults = $this->defaults;
$context += ['params' => []];

$url = $this->persistParams($url, $context['params']);
unset($context['params']);
$hostOptions = array_intersect_key($url, $context);

// Check for properties that will cause an
Expand Down
4 changes: 4 additions & 0 deletions src/Routing/RouteBuilder.php
Expand Up @@ -350,6 +350,10 @@ public function resources($name, $options = [], $callback = null)
* - `routeClass` is used to extend and change how individual routes parse requests
* and handle reverse routing, via a custom routing class.
* Ex. `'routeClass' => 'SlugRoute'`
* - `persist` is used to define which route parameters should be automatically
* included when generating new URLs. You can override persistent parameters
* by redefining them in a URL or remove them by setting the parameter to `false`.
* Ex. `'persist' => ['lang']`
* - `_name` is used to define a specific name for routes. This can be used to optimize
* reverse routing lookups. If undefined a name will be generated for each
* connected route.
Expand Down
2 changes: 1 addition & 1 deletion src/Routing/RouteCollection.php
Expand Up @@ -222,7 +222,7 @@ protected function _getNames($url)
*
* @param array $url The url to match.
* @param array $context The request context to use. Contains _base, _port,
* _host, and _scheme keys.
* _host, _scheme and params keys.
* @return string|false Either a string on match, or false on failure.
* @throws \Cake\Routing\Exception\MissingRouteException when a route cannot be matched.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Routing/Router.php
Expand Up @@ -612,7 +612,7 @@ public static function url($url = null, $full = false)
}

$url = static::_applyUrlFilters($url);
$output = static::$_collection->match($url, static::$_requestContext);
$output = static::$_collection->match($url, static::$_requestContext + ['params' => $params]);
} else {
$plainString = (
strpos($url, 'javascript:') === 0 ||
Expand Down
18 changes: 18 additions & 0 deletions tests/TestCase/Routing/Route/RouteTest.php
Expand Up @@ -348,6 +348,24 @@ public function testMatchBasic()
$this->assertEquals($expected, $result);
}

/**
* Test match() with persist option
*
* @return void
*/
public function testMatchWithPersistOption()
{
$context = [
'params' => ['lang' => 'en']
];
$route = new Route('/:lang/:controller/:action', [], ['persist' => ['lang']]);
$result = $route->match(
['controller' => 'tasks', 'action' => 'add'],
$context
);
$this->assertEquals('/en/tasks/add', $result);
}

/**
* Test match() with _host and other keys.
*/
Expand Down
23 changes: 23 additions & 0 deletions tests/TestCase/Routing/RouterTest.php
Expand Up @@ -1197,6 +1197,29 @@ public function testUrlGenerationWithUrlFilter()
$this->assertEquals(2, $calledCount);
}

/**
* Test url param persistence.
*
* @return void
*/
public function testUrlParamPersistence()
{
Router::connect('/:lang/:controller/:action/*', [], ['persist' => ['lang']]);
$request = new Request();
$request->addParams([
'lang' => 'en',
'controller' => 'posts',
'action' => 'index'
])->addPaths([
'base' => '',
'here' => '/'
]);
Router::pushRequest($request);

$result = Router::url(['controller' => 'tasks', 'action' => 'edit', '1234']);
$this->assertEquals('/en/tasks/edit/1234', $result);
}

/**
* Test that plain strings urls work
*
Expand Down

0 comments on commit 7f62d57

Please sign in to comment.