diff --git a/src/Routing/RouteBuilder.php b/src/Routing/RouteBuilder.php index 47a96367d57..74e720d2be4 100644 --- a/src/Routing/RouteBuilder.php +++ b/src/Routing/RouteBuilder.php @@ -23,6 +23,7 @@ use Cake\Routing\Route\RedirectRoute; use Cake\Routing\Route\Route; use Cake\Utility\Inflector; +use Closure; use InvalidArgumentException; use RuntimeException; @@ -344,14 +345,14 @@ public function namePrefix(?string $value = null): string * is available at `/posts` * * @param string $name A controller name to connect resource routes for. - * @param array|callable $options Options to use when generating REST routes, or a callback. - * @param callable|null $callback An optional callback to be executed in a nested scope. Nested + * @param array|\Closure $options Options to use when generating REST routes, or a callback. + * @param \Closure|null $callback An optional callback to be executed in a nested scope. Nested * scopes inherit the existing path and 'id' parameter. * @return $this */ - public function resources(string $name, $options = [], $callback = null) + public function resources(string $name, $options = [], ?Closure $callback = null) { - if (is_callable($options)) { + if ($options instanceof Closure) { $callback = $options; $options = []; } @@ -422,7 +423,7 @@ public function resources(string $name, $options = [], $callback = null) $this->connect($url, $params, $routeOptions); } - if (is_callable($callback)) { + if ($callback !== null) { $idName = Inflector::singularize(Inflector::underscore($name)) . '_id'; $path = '/' . $options['path'] . '/:' . $idName; $this->scope($path, [], $callback); @@ -849,18 +850,18 @@ public function redirect(string $route, $url, array $options = []): Route * ``` * * @param string $name The prefix name to use. - * @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|null $callback The callback to invoke that builds the prefixed routes. + * @param array|\Closure $params An array of routing defaults to add to each connected route. + * If you have no parameters, this argument can be a Closure. + * @param \Closure|null $callback The callback to invoke that builds the prefixed routes. * @return $this * @throws \InvalidArgumentException If a valid callback is not passed * @psalm-suppress PossiblyInvalidArrayAccess */ - public function prefix(string $name, $params = [], ?callable $callback = null) + public function prefix(string $name, $params = [], ?Closure $callback = null) { if ($callback === null) { - if (!is_callable($params)) { - throw new InvalidArgumentException('A valid callback is expected'); + if (!$params instanceof Closure) { + throw new InvalidArgumentException('A valid Closure is expected'); } $callback = $params; $params = []; @@ -894,16 +895,16 @@ public function prefix(string $name, $params = [], ?callable $callback = null) * prepended, and have a matching plugin routing key set. * * @param string $name The plugin name to build routes for - * @param array|callable $options Either the options to use, or a callback - * @param callable|null $callback The callback to invoke that builds the plugin routes + * @param array|\Closure $options Either the options to use, or a callback + * @param \Closure|null $callback The callback to invoke that builds the plugin routes * Only required when $options is defined. * @return $this */ - public function plugin(string $name, $options = [], ?callable $callback = null) + public function plugin(string $name, $options = [], ?Closure $callback = null) { if ($callback === null) { - if (!is_callable($options)) { - throw new InvalidArgumentException('A valid callback is expected'); + if (!$options instanceof Closure) { + throw new InvalidArgumentException('A valid Closure is expected'); } $callback = $options; $options = []; @@ -924,21 +925,20 @@ public function plugin(string $name, $options = [], ?callable $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|null $callback The callback to invoke that builds the plugin routes. + * @param array|\Closure $params Either the parameters to add to routes, or a callback. + * @param \Closure|null $callback The callback to invoke that builds the plugin routes. * Only required when $params is defined. * @return $this - * @throws \InvalidArgumentException when there is no callable parameter. + * @throws \InvalidArgumentException when there is no callback parameter. */ - public function scope(string $path, $params, $callback = null) + public function scope(string $path, $params, ?Closure $callback = null) { - if (is_callable($params)) { + if (!is_array($params)) { $callback = $params; $params = []; } - if (!is_callable($callback)) { - $msg = 'Need a callable function/object to connect routes.'; - throw new InvalidArgumentException($msg); + if (!$callback instanceof Closure) { + throw new InvalidArgumentException('Need a Closure to connect routes.'); } if ($this->_path !== '/') { @@ -987,7 +987,7 @@ public function fallbacks(?string $routeClass = null) * scope or any child scopes that share the same RouteCollection. * * @param string $name The name of the middleware. Used when applying middleware to a scope. - * @param callable|string $middleware The middleware callable or class name to register. + * @param \Closure|string $middleware The middleware Closure or class name to register. * @return $this * @see \Cake\Routing\RouteCollection */ diff --git a/src/Routing/RouteCollection.php b/src/Routing/RouteCollection.php index 3a471f3ef6a..db3858ea4cb 100644 --- a/src/Routing/RouteCollection.php +++ b/src/Routing/RouteCollection.php @@ -406,7 +406,7 @@ public function setExtensions(array $extensions, bool $merge = true) * scope or any child scopes that share the same RouteCollection. * * @param string $name The name of the middleware. Used when applying middleware to a scope. - * @param callable|string $middleware The middleware callable or class name to register. + * @param \Closure|string $middleware The middleware Closure or class name to register. * @return $this * @throws \RuntimeException */ diff --git a/src/Routing/Router.php b/src/Routing/Router.php index 12c58ad3992..2a444d8333c 100644 --- a/src/Routing/Router.php +++ b/src/Routing/Router.php @@ -20,6 +20,7 @@ use Cake\Http\ServerRequest; use Cake\Routing\Exception\MissingRouteException; use Cake\Utility\Inflector; +use Closure; use Exception; use ReflectionFunction; use ReflectionMethod; @@ -145,7 +146,7 @@ class Router * The stack of URL filters to apply against routing URLs before passing the * parameters to the route collection. * - * @var callable[] + * @var \Closure[] */ protected static $_urlFilters = []; @@ -322,10 +323,10 @@ public static function resetRoutes(): void * }); * ``` * - * @param callable $function The function to add + * @param \Closure $function The function to add * @return void */ - public static function addUrlFilter(callable $function): void + public static function addUrlFilter(Closure $function): void { static::$_urlFilters[] = $function; } @@ -781,13 +782,13 @@ public static function createRouteBuilder(string $path, array $options = []): Ro * * @param string $path The path prefix for the scope. This path will be prepended * to all routes connected in the scoped collection. - * @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|null $callback The callback to invoke with the scoped collection. - * @throws \InvalidArgumentException When an invalid callable is provided. + * @param array|\Closure $params An array of routing defaults to add to each connected route. + * If you have no parameters, this argument can be a Closure. + * @param \Closure|null $callback The callback to invoke with the scoped collection. + * @throws \InvalidArgumentException When an invalid callback is provided. * @return void */ - public static function scope(string $path, $params = [], $callback = null): void + public static function scope(string $path, $params = [], ?Closure $callback = null): void { $options = []; if (is_array($params)) { @@ -816,15 +817,15 @@ public static function scope(string $path, $params = [], $callback = null): void * to the `Controller\Admin\Api\` namespace. * * @param string $name The prefix name to use. - * @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|null $callback The callback to invoke that builds the prefixed routes. + * @param array|\Closure $params An array of routing defaults to add to each connected route. + * If you have no parameters, this argument can be a Closure. + * @param \Closure|null $callback The callback to invoke that builds the prefixed routes. * @return void */ - public static function prefix(string $name, $params = [], ?callable $callback = null): void + public static function prefix(string $name, $params = [], ?Closure $callback = null): void { if ($callback === null) { - /** @var callable $callback */ + /** @var \Closure $callback */ $callback = $params; $params = []; } @@ -850,16 +851,16 @@ public static function prefix(string $name, $params = [], ?callable $callback = * prepended, and have a matching plugin routing key set. * * @param string $name The plugin name to build routes for - * @param array|callable $options Either the options to use, or a callback - * @param callable|null $callback The callback to invoke that builds the plugin routes. + * @param array|\Closure $options Either the options to use, or a callback + * @param \Closure|null $callback The callback to invoke that builds the plugin routes. * Only required when $options is defined * @return void * @psalm-suppress PossiblyInvalidArrayAccess */ - public static function plugin(string $name, $options = [], ?callable $callback = null): void + public static function plugin(string $name, $options = [], ?Closure $callback = null): void { if ($callback === null) { - /** @var callable $callback */ + /** @var \Closure $callback */ $callback = $options; $options = []; } diff --git a/tests/TestCase/Routing/RouterTest.php b/tests/TestCase/Routing/RouterTest.php index 003ecef45ff..912760961b6 100644 --- a/tests/TestCase/Routing/RouterTest.php +++ b/tests/TestCase/Routing/RouterTest.php @@ -1158,7 +1158,9 @@ public function testUrlGenerationWithUrlFilterFailureMethod() ]); Router::setRequest($request); - Router::addUrlFilter([$this, 'badFilter']); + Router::addUrlFilter(function () { + return $this->badFilter(); + }); Router::url(['controller' => 'posts', 'action' => 'index', 'lang' => 'en']); }