first commit
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes;
|
||||
|
||||
/**
|
||||
* Collects data for auto route listing.
|
||||
*/
|
||||
final class AutoRouteCollector
|
||||
{
|
||||
/**
|
||||
* @var string namespace to search
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
private string $defaultController;
|
||||
private string $defaultMethod;
|
||||
|
||||
/**
|
||||
* @param string $namespace namespace to search
|
||||
*/
|
||||
public function __construct(string $namespace, string $defaultController, string $defaultMethod)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->defaultController = $defaultController;
|
||||
$this->defaultMethod = $defaultMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string>>
|
||||
* @phpstan-return list<list<string>>
|
||||
*/
|
||||
public function get(): array
|
||||
{
|
||||
$finder = new ControllerFinder($this->namespace);
|
||||
$reader = new ControllerMethodReader($this->namespace);
|
||||
|
||||
$tbody = [];
|
||||
|
||||
foreach ($finder->find() as $class) {
|
||||
$output = $reader->read(
|
||||
$class,
|
||||
$this->defaultController,
|
||||
$this->defaultMethod
|
||||
);
|
||||
|
||||
foreach ($output as $item) {
|
||||
$tbody[] = [
|
||||
'auto',
|
||||
$item['route'],
|
||||
$item['handler'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $tbody;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved;
|
||||
|
||||
use CodeIgniter\Commands\Utilities\Routes\ControllerFinder;
|
||||
use CodeIgniter\Commands\Utilities\Routes\FilterCollector;
|
||||
|
||||
/**
|
||||
* Collects data for Auto Routing Improved.
|
||||
*/
|
||||
final class AutoRouteCollector
|
||||
{
|
||||
/**
|
||||
* @var string namespace to search
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
private string $defaultController;
|
||||
private string $defaultMethod;
|
||||
private array $httpMethods;
|
||||
|
||||
/**
|
||||
* List of controllers in Defined Routes that should not be accessed via Auto-Routing.
|
||||
*
|
||||
* @var class-string[]
|
||||
*/
|
||||
private array $protectedControllers;
|
||||
|
||||
/**
|
||||
* @param string $namespace namespace to search
|
||||
*/
|
||||
public function __construct(
|
||||
string $namespace,
|
||||
string $defaultController,
|
||||
string $defaultMethod,
|
||||
array $httpMethods,
|
||||
array $protectedControllers
|
||||
) {
|
||||
$this->namespace = $namespace;
|
||||
$this->defaultController = $defaultController;
|
||||
$this->defaultMethod = $defaultMethod;
|
||||
$this->httpMethods = $httpMethods;
|
||||
$this->protectedControllers = $protectedControllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string>>
|
||||
* @phpstan-return list<list<string>>
|
||||
*/
|
||||
public function get(): array
|
||||
{
|
||||
$finder = new ControllerFinder($this->namespace);
|
||||
$reader = new ControllerMethodReader($this->namespace, $this->httpMethods);
|
||||
|
||||
$tbody = [];
|
||||
|
||||
foreach ($finder->find() as $class) {
|
||||
// Exclude controllers in Defined Routes.
|
||||
if (in_array('\\' . $class, $this->protectedControllers, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$routes = $reader->read(
|
||||
$class,
|
||||
$this->defaultController,
|
||||
$this->defaultMethod
|
||||
);
|
||||
|
||||
if ($routes === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$routes = $this->addFilters($routes);
|
||||
|
||||
foreach ($routes as $item) {
|
||||
$tbody[] = [
|
||||
strtoupper($item['method']) . '(auto)',
|
||||
$item['route'] . $item['route_params'],
|
||||
$item['handler'],
|
||||
$item['before'],
|
||||
$item['after'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $tbody;
|
||||
}
|
||||
|
||||
private function addFilters($routes)
|
||||
{
|
||||
$filterCollector = new FilterCollector(true);
|
||||
|
||||
foreach ($routes as &$route) {
|
||||
// Search filters for the URI with all params
|
||||
$sampleUri = $this->generateSampleUri($route);
|
||||
$filtersLongest = $filterCollector->get($route['method'], $route['route'] . $sampleUri);
|
||||
|
||||
// Search filters for the URI without optional params
|
||||
$sampleUri = $this->generateSampleUri($route, false);
|
||||
$filtersShortest = $filterCollector->get($route['method'], $route['route'] . $sampleUri);
|
||||
|
||||
// Get common array elements
|
||||
$filters['before'] = array_intersect($filtersLongest['before'], $filtersShortest['before']);
|
||||
$filters['after'] = array_intersect($filtersLongest['after'], $filtersShortest['after']);
|
||||
|
||||
$route['before'] = implode(' ', array_map('class_basename', $filters['before']));
|
||||
$route['after'] = implode(' ', array_map('class_basename', $filters['after']));
|
||||
}
|
||||
|
||||
return $routes;
|
||||
}
|
||||
|
||||
private function generateSampleUri(array $route, bool $longest = true): string
|
||||
{
|
||||
$sampleUri = '';
|
||||
|
||||
if (isset($route['params'])) {
|
||||
$i = 1;
|
||||
|
||||
foreach ($route['params'] as $required) {
|
||||
if ($longest && ! $required) {
|
||||
$sampleUri .= '/' . $i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sampleUri;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
* Reads a controller and returns a list of auto route listing.
|
||||
*/
|
||||
final class ControllerMethodReader
|
||||
{
|
||||
/**
|
||||
* @var string the default namespace
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
private array $httpMethods;
|
||||
|
||||
/**
|
||||
* @param string $namespace the default namespace
|
||||
*/
|
||||
public function __construct(string $namespace, array $httpMethods)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->httpMethods = $httpMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns found route info in the controller.
|
||||
*
|
||||
* @phpstan-param class-string $class
|
||||
*
|
||||
* @return array<int, array<string, array|string>>
|
||||
* @phpstan-return list<array<string, string|array>>
|
||||
*/
|
||||
public function read(string $class, string $defaultController = 'Home', string $defaultMethod = 'index'): array
|
||||
{
|
||||
$reflection = new ReflectionClass($class);
|
||||
|
||||
if ($reflection->isAbstract()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$classname = $reflection->getName();
|
||||
$classShortname = $reflection->getShortName();
|
||||
|
||||
$output = [];
|
||||
$classInUri = $this->getUriByClass($classname);
|
||||
|
||||
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
$methodName = $method->getName();
|
||||
|
||||
foreach ($this->httpMethods as $httpVerb) {
|
||||
if (strpos($methodName, $httpVerb) === 0) {
|
||||
// Remove HTTP verb prefix.
|
||||
$methodInUri = lcfirst(substr($methodName, strlen($httpVerb)));
|
||||
|
||||
if ($methodInUri === $defaultMethod) {
|
||||
$routeWithoutController = $this->getRouteWithoutController(
|
||||
$classShortname,
|
||||
$defaultController,
|
||||
$classInUri,
|
||||
$classname,
|
||||
$methodName,
|
||||
$httpVerb
|
||||
);
|
||||
|
||||
if ($routeWithoutController !== []) {
|
||||
$output = [...$output, ...$routeWithoutController];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Route for the default method.
|
||||
$output[] = [
|
||||
'method' => $httpVerb,
|
||||
'route' => $classInUri,
|
||||
'route_params' => '',
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
'params' => [],
|
||||
];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$route = $classInUri . '/' . $methodInUri;
|
||||
|
||||
$params = [];
|
||||
$routeParams = '';
|
||||
$refParams = $method->getParameters();
|
||||
|
||||
foreach ($refParams as $param) {
|
||||
$required = true;
|
||||
if ($param->isOptional()) {
|
||||
$required = false;
|
||||
|
||||
$routeParams .= '[/..]';
|
||||
} else {
|
||||
$routeParams .= '/..';
|
||||
}
|
||||
|
||||
// [variable_name => required?]
|
||||
$params[$param->getName()] = $required;
|
||||
}
|
||||
|
||||
$output[] = [
|
||||
'method' => $httpVerb,
|
||||
'route' => $route,
|
||||
'route_params' => $routeParams,
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
'params' => $params,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param class-string $classname
|
||||
*
|
||||
* @return string URI path part from the folder(s) and controller
|
||||
*/
|
||||
private function getUriByClass(string $classname): string
|
||||
{
|
||||
// remove the namespace
|
||||
$pattern = '/' . preg_quote($this->namespace, '/') . '/';
|
||||
$class = ltrim(preg_replace($pattern, '', $classname), '\\');
|
||||
|
||||
$classParts = explode('\\', $class);
|
||||
$classPath = '';
|
||||
|
||||
foreach ($classParts as $part) {
|
||||
// make the first letter lowercase, because auto routing makes
|
||||
// the URI path's first letter uppercase and search the controller
|
||||
$classPath .= lcfirst($part) . '/';
|
||||
}
|
||||
|
||||
return rtrim($classPath, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a route without default controller.
|
||||
*/
|
||||
private function getRouteWithoutController(
|
||||
string $classShortname,
|
||||
string $defaultController,
|
||||
string $uriByClass,
|
||||
string $classname,
|
||||
string $methodName,
|
||||
string $httpVerb
|
||||
): array {
|
||||
$output = [];
|
||||
|
||||
if ($classShortname === $defaultController) {
|
||||
$pattern = '#' . preg_quote(lcfirst($defaultController), '#') . '\z#';
|
||||
$routeWithoutController = rtrim(preg_replace($pattern, '', $uriByClass), '/');
|
||||
$routeWithoutController = $routeWithoutController ?: '/';
|
||||
|
||||
$output[] = [
|
||||
'method' => $httpVerb,
|
||||
'route' => $routeWithoutController,
|
||||
'route_params' => '',
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
'params' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes;
|
||||
|
||||
use CodeIgniter\Autoloader\FileLocator;
|
||||
use CodeIgniter\Config\Services;
|
||||
|
||||
/**
|
||||
* Finds all controllers in a namespace for auto route listing.
|
||||
*/
|
||||
final class ControllerFinder
|
||||
{
|
||||
/**
|
||||
* @var string namespace to search
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
private FileLocator $locator;
|
||||
|
||||
/**
|
||||
* @param string $namespace namespace to search
|
||||
*/
|
||||
public function __construct(string $namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->locator = Services::locator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @phpstan-return class-string[]
|
||||
*/
|
||||
public function find(): array
|
||||
{
|
||||
$nsArray = explode('\\', trim($this->namespace, '\\'));
|
||||
$count = count($nsArray);
|
||||
$ns = '';
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$ns .= '\\' . array_shift($nsArray);
|
||||
$path = implode('\\', $nsArray);
|
||||
|
||||
$files = $this->locator->listNamespaceFiles($ns, $path);
|
||||
|
||||
if ($files !== []) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (\is_file($file)) {
|
||||
$classnameOrEmpty = $this->locator->getClassname($file);
|
||||
|
||||
if ($classnameOrEmpty !== '') {
|
||||
/** @phpstan-var class-string $classname */
|
||||
$classname = $classnameOrEmpty;
|
||||
|
||||
$classes[] = $classname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
* Reads a controller and returns a list of auto route listing.
|
||||
*/
|
||||
final class ControllerMethodReader
|
||||
{
|
||||
/**
|
||||
* @var string the default namespace
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
/**
|
||||
* @param string $namespace the default namespace
|
||||
*/
|
||||
public function __construct(string $namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param class-string $class
|
||||
*
|
||||
* @return array<int, array{route: string, handler: string}>
|
||||
* @phpstan-return list<array{route: string, handler: string}>
|
||||
*/
|
||||
public function read(string $class, string $defaultController = 'Home', string $defaultMethod = 'index'): array
|
||||
{
|
||||
$reflection = new ReflectionClass($class);
|
||||
|
||||
if ($reflection->isAbstract()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$classname = $reflection->getName();
|
||||
$classShortname = $reflection->getShortName();
|
||||
|
||||
$output = [];
|
||||
$uriByClass = $this->getUriByClass($classname);
|
||||
|
||||
if ($this->hasRemap($reflection)) {
|
||||
$methodName = '_remap';
|
||||
|
||||
$routeWithoutController = $this->getRouteWithoutController(
|
||||
$classShortname,
|
||||
$defaultController,
|
||||
$uriByClass,
|
||||
$classname,
|
||||
$methodName
|
||||
);
|
||||
$output = [...$output, ...$routeWithoutController];
|
||||
|
||||
$output[] = [
|
||||
'route' => $uriByClass . '[/...]',
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
];
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
$methodName = $method->getName();
|
||||
|
||||
$route = $uriByClass . '/' . $methodName;
|
||||
|
||||
// Exclude BaseController and initController
|
||||
// See system/Config/Routes.php
|
||||
if (preg_match('#\AbaseController.*#', $route) === 1) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('#.*/initController\z#', $route) === 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($methodName === $defaultMethod) {
|
||||
$routeWithoutController = $this->getRouteWithoutController(
|
||||
$classShortname,
|
||||
$defaultController,
|
||||
$uriByClass,
|
||||
$classname,
|
||||
$methodName
|
||||
);
|
||||
$output = [...$output, ...$routeWithoutController];
|
||||
|
||||
$output[] = [
|
||||
'route' => $uriByClass,
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
];
|
||||
}
|
||||
|
||||
$output[] = [
|
||||
'route' => $route . '[/...]',
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the class has a _remap() method.
|
||||
*/
|
||||
private function hasRemap(ReflectionClass $class): bool
|
||||
{
|
||||
if ($class->hasMethod('_remap')) {
|
||||
$remap = $class->getMethod('_remap');
|
||||
|
||||
return $remap->isPublic();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param class-string $classname
|
||||
*
|
||||
* @return string URI path part from the folder(s) and controller
|
||||
*/
|
||||
private function getUriByClass(string $classname): string
|
||||
{
|
||||
// remove the namespace
|
||||
$pattern = '/' . preg_quote($this->namespace, '/') . '/';
|
||||
$class = ltrim(preg_replace($pattern, '', $classname), '\\');
|
||||
|
||||
$classParts = explode('\\', $class);
|
||||
$classPath = '';
|
||||
|
||||
foreach ($classParts as $part) {
|
||||
// make the first letter lowercase, because auto routing makes
|
||||
// the URI path's first letter uppercase and search the controller
|
||||
$classPath .= lcfirst($part) . '/';
|
||||
}
|
||||
|
||||
return rtrim($classPath, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a route without default controller.
|
||||
*/
|
||||
private function getRouteWithoutController(
|
||||
string $classShortname,
|
||||
string $defaultController,
|
||||
string $uriByClass,
|
||||
string $classname,
|
||||
string $methodName
|
||||
): array {
|
||||
$output = [];
|
||||
|
||||
if ($classShortname === $defaultController) {
|
||||
$pattern = '#' . preg_quote(lcfirst($defaultController), '#') . '\z#';
|
||||
$routeWithoutController = rtrim(preg_replace($pattern, '', $uriByClass), '/');
|
||||
$routeWithoutController = $routeWithoutController ?: '/';
|
||||
|
||||
$output[] = [
|
||||
'route' => $routeWithoutController,
|
||||
'handler' => '\\' . $classname . '::' . $methodName,
|
||||
];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes;
|
||||
|
||||
use CodeIgniter\Config\Services;
|
||||
use CodeIgniter\Filters\Filters;
|
||||
use CodeIgniter\HTTP\Request;
|
||||
use CodeIgniter\Router\Router;
|
||||
|
||||
/**
|
||||
* Collects filters for a route.
|
||||
*/
|
||||
final class FilterCollector
|
||||
{
|
||||
/**
|
||||
* Whether to reset Defined Routes.
|
||||
*
|
||||
* If set to true, route filters are not found.
|
||||
*/
|
||||
private bool $resetRoutes;
|
||||
|
||||
public function __construct(bool $resetRoutes = false)
|
||||
{
|
||||
$this->resetRoutes = $resetRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method HTTP method
|
||||
* @param string $uri URI path to find filters for
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of filter alias or classname
|
||||
*/
|
||||
public function get(string $method, string $uri): array
|
||||
{
|
||||
if ($method === 'cli') {
|
||||
return [
|
||||
'before' => [],
|
||||
'after' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$request = Services::request(null, false);
|
||||
$request->setMethod($method);
|
||||
|
||||
$router = $this->createRouter($request);
|
||||
$filters = $this->createFilters($request);
|
||||
|
||||
$finder = new FilterFinder($router, $filters);
|
||||
|
||||
return $finder->find($uri);
|
||||
}
|
||||
|
||||
private function createRouter(Request $request): Router
|
||||
{
|
||||
$routes = Services::routes();
|
||||
|
||||
if ($this->resetRoutes) {
|
||||
$routes->resetRoutes();
|
||||
}
|
||||
|
||||
return new Router($routes, $request);
|
||||
}
|
||||
|
||||
private function createFilters(Request $request): Filters
|
||||
{
|
||||
$config = config('Filters');
|
||||
|
||||
return new Filters($config, $request, Services::response());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes;
|
||||
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\Filters\Filters;
|
||||
use CodeIgniter\Router\Exceptions\RedirectException;
|
||||
use CodeIgniter\Router\Router;
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* Finds filters.
|
||||
*/
|
||||
final class FilterFinder
|
||||
{
|
||||
private Router $router;
|
||||
private Filters $filters;
|
||||
|
||||
public function __construct(?Router $router = null, ?Filters $filters = null)
|
||||
{
|
||||
$this->router = $router ?? Services::router();
|
||||
$this->filters = $filters ?? Services::filters();
|
||||
}
|
||||
|
||||
private function getRouteFilters(string $uri): array
|
||||
{
|
||||
$this->router->handle($uri);
|
||||
|
||||
$multipleFiltersEnabled = config('Feature')->multipleFilters ?? false;
|
||||
if (! $multipleFiltersEnabled) {
|
||||
$filter = $this->router->getFilter();
|
||||
|
||||
return $filter === null ? [] : [$filter];
|
||||
}
|
||||
|
||||
return $this->router->getFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri URI path to find filters for
|
||||
*
|
||||
* @return array{before: list<string>, after: list<string>} array of filter alias or classname
|
||||
*/
|
||||
public function find(string $uri): array
|
||||
{
|
||||
$this->filters->reset();
|
||||
|
||||
// Add route filters
|
||||
try {
|
||||
$routeFilters = $this->getRouteFilters($uri);
|
||||
$this->filters->enableFilters($routeFilters, 'before');
|
||||
$this->filters->enableFilters($routeFilters, 'after');
|
||||
|
||||
$this->filters->initialize($uri);
|
||||
|
||||
return $this->filters->getFilters();
|
||||
} catch (RedirectException $e) {
|
||||
return [
|
||||
'before' => [],
|
||||
'after' => [],
|
||||
];
|
||||
} catch (PageNotFoundException $e) {
|
||||
return [
|
||||
'before' => ['<unknown>'],
|
||||
'after' => ['<unknown>'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Commands\Utilities\Routes;
|
||||
|
||||
use CodeIgniter\Config\Services;
|
||||
use CodeIgniter\Router\RouteCollection;
|
||||
|
||||
/**
|
||||
* Generate a sample URI path from route key regex.
|
||||
*/
|
||||
final class SampleURIGenerator
|
||||
{
|
||||
private RouteCollection $routes;
|
||||
|
||||
/**
|
||||
* Sample URI path for placeholder.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private array $samples = [
|
||||
'any' => '123/abc',
|
||||
'segment' => 'abc_123',
|
||||
'alphanum' => 'abc123',
|
||||
'num' => '123',
|
||||
'alpha' => 'abc',
|
||||
'hash' => 'abc_123',
|
||||
];
|
||||
|
||||
public function __construct(?RouteCollection $routes = null)
|
||||
{
|
||||
$this->routes = $routes ?? Services::routes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $routeKey route key regex
|
||||
*
|
||||
* @return string sample URI path
|
||||
*/
|
||||
public function get(string $routeKey): string
|
||||
{
|
||||
$sampleUri = $routeKey;
|
||||
|
||||
foreach ($this->routes->getPlaceholders() as $placeholder => $regex) {
|
||||
$sample = $this->samples[$placeholder] ?? '::unknown::';
|
||||
|
||||
$sampleUri = str_replace('(' . $regex . ')', $sample, $sampleUri);
|
||||
}
|
||||
|
||||
// auto route
|
||||
return str_replace('[/...]', '/1/2/3/4/5', $sampleUri);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user