From adce4918d982f9871cc24b54c81473fbe1b6b570 Mon Sep 17 00:00:00 2001 From: Lonnie Ezell Date: Thu, 30 Aug 2018 00:10:41 -0500 Subject: [PATCH] Allow params in route filters. --- system/CodeIgniter.php | 6 ++--- system/Filters/Filters.php | 40 +++++++++++++++++++++++++++- system/Router/RouteCollection.php | 18 +++---------- tests/system/Filters/FiltersTest.php | 24 +++++++++++++++++ 4 files changed, 70 insertions(+), 18 deletions(-) diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index acbb21ccfd..7e62d43f8d 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -267,16 +267,16 @@ class CodeIgniter */ protected function handleRequest(RouteCollectionInterface $routes = null, $cacheConfig, bool $returnResponse = false) { - $routeFilters = $this->tryToRouteIt($routes); + $routeFilter = $this->tryToRouteIt($routes); // Run "before" filters $filters = Services::filters(); // If any filters were specified within the routes file, // we need to ensure it's active for the current request (before only) - if (! is_null($routeFilters)) + if (! is_null($routeFilter)) { - $filters->enableFilter($routeFilters['filter'], 'before'); + $filters->enableFilter($routeFilter, 'before'); } $uri = $this->request instanceof CLIRequest ? $this->request->getPath() : $this->request->uri->getPath(); diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index 6fffa3f226..09a8b83415 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -78,6 +78,13 @@ class Filters */ protected $initialized = false; + /** + * Any arguments to be passed to filters. + * + * @var array + */ + protected $arguments = []; + //-------------------------------------------------------------------- public function __construct($config, RequestInterface $request, ResponseInterface $response) @@ -124,7 +131,7 @@ class Filters if ($position == 'before') { - $result = $class->before($this->request); + $result = $class->before($this->request, $this->arguments[$alias] ?? null); if ($result instanceof RequestInterface) { @@ -250,6 +257,10 @@ class Filters /** * Ensures that a specific filter is on and enabled for the current request. * + * Filters can have "arguments". This is done by placing a colon immediately + * after the filter name, followed by a comma-separated list of arguments that + * are passed to the filter when executed. + * * @param string $name * @param string $when * @@ -257,6 +268,19 @@ class Filters */ public function enableFilter(string $name, string $when = 'before') { + // Get parameters and clean name + if (strpos($name, ':') !== false) + { + list($name, $params) = explode(':', $name); + + $params = explode(',', $params); + array_walk($params, function(&$item){ + $item = trim($item); + }); + + $this->arguments[$name] = $params; + } + if (! array_key_exists($name, $this->config->aliases)) { throw FilterException::forNoAlias($name); @@ -270,6 +294,20 @@ class Filters return $this; } + //-------------------------------------------------------------------- + + /** + * Returns the arguments for a specified key, or all. + * + * @return array + */ + public function getArguments(string $key = null) + { + return is_null($key) + ? $this->arguments + : $this->arguments[$key]; + } + //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Processors diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 58ea660949..7b96818dd5 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -1132,26 +1132,16 @@ class RouteCollection implements RouteCollectionInterface * * @param string $search * - * @return array + * @return string */ - public function getFilterForRoute(string $search): array + public function getFilterForRoute(string $search): string { if (! $this->isFiltered($search)) { - return []; + return ''; } - $params = explode(':', $this->routesOptions[$search]['filter']); - $filter = array_shift($params); - - $params = ! empty($params) - ? explode(',', $params[0]) - : null; - - return [ - 'filter' => $filter, - 'params' => $params - ]; + return $this->routesOptions[$search]['filter']; } //-------------------------------------------------------------------- diff --git a/tests/system/Filters/FiltersTest.php b/tests/system/Filters/FiltersTest.php index 6de774f91d..1a3bdc029c 100644 --- a/tests/system/Filters/FiltersTest.php +++ b/tests/system/Filters/FiltersTest.php @@ -520,4 +520,28 @@ class FiltersTest extends \CIUnitTestCase $this->assertTrue(in_array('google', $filters['before'])); } + + public function testEnableFilterWithArguments() + { + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $config = [ + 'aliases' => ['role' => 'CodeIgniter\Filters\fixtures\Role'], + 'globals' => [ + 'before' => [], + 'after' => [] + ] + ]; + + $filters = new Filters((object) $config, $this->request, $this->response); + + $filters = $filters->initialize('admin/foo/bar'); + + $filters->enableFilter('role:admin , super', 'before'); + + $found = $filters->getFilters(); + + $this->assertTrue(in_array('role', $found['before'])); + $this->assertEquals(['admin', 'super'], $filters->getArguments('role')); + } }