mirror of
https://github.com/nextcloud/server.git
synced 2026-06-08 16:26:59 -04:00
feat(router): Add fallback for legacy action and file routes
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
parent
216da3a81c
commit
446b22ac3c
2 changed files with 81 additions and 15 deletions
|
|
@ -23,6 +23,8 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
class CachingRouter extends Router {
|
||||
protected ICache $cache;
|
||||
|
||||
protected array $legacyCreatedRoutes = [];
|
||||
|
||||
public function __construct(
|
||||
ICacheFactory $cacheFactory,
|
||||
LoggerInterface $logger,
|
||||
|
|
@ -104,4 +106,52 @@ class CachingRouter extends Router {
|
|||
$this->eventLogger->end('cacheroute:match');
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{action:mixed, ...} $parameters
|
||||
*/
|
||||
protected function callLegacyActionRoute(array $parameters): void {
|
||||
/*
|
||||
* Closures cannot be serialized to cache, so for legacy routes calling an action we have to include the routes.php file again
|
||||
*/
|
||||
$app = $parameters['app'];
|
||||
$this->useCollection($app);
|
||||
parent::requireRouteFile($parameters['route-file'], $app);
|
||||
$collection = $this->getCollection($app);
|
||||
$parameters['action'] = $collection->get($parameters['_route'])?->getDefault('action');
|
||||
parent::callLegacyActionRoute($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a \OC\Route\Route.
|
||||
* Deprecated
|
||||
*
|
||||
* @param string $name Name of the route to create.
|
||||
* @param string $pattern The pattern to match
|
||||
* @param array $defaults An array of default parameter values
|
||||
* @param array $requirements An array of requirements for parameters (regexes)
|
||||
*/
|
||||
public function create($name, $pattern, array $defaults = [], array $requirements = []): Route {
|
||||
$this->legacyCreatedRoutes[] = $name;
|
||||
return parent::create($name, $pattern, $defaults, $requirements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Require a routes.php file
|
||||
*/
|
||||
protected function requireRouteFile(string $file, string $appName): void {
|
||||
$this->legacyCreatedRoutes = [];
|
||||
parent::requireRouteFile($file, $appName);
|
||||
foreach ($this->legacyCreatedRoutes as $routeName) {
|
||||
$route = $this->collection?->get($routeName);
|
||||
if ($route === null) {
|
||||
/* Should never happen */
|
||||
throw new \Exception("Could not find route $routeName");
|
||||
}
|
||||
if ($route->hasDefault('action')) {
|
||||
$route->setDefault('route-file', $file);
|
||||
$route->setDefault('app', $appName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -312,27 +312,43 @@ class Router implements IRouter {
|
|||
$application = $this->getApplicationClass($caller[0]);
|
||||
\OC\AppFramework\App::main($caller[1], $caller[2], $application->getContainer(), $parameters);
|
||||
} elseif (isset($parameters['action'])) {
|
||||
$action = $parameters['action'];
|
||||
if (!is_callable($action)) {
|
||||
throw new \Exception('not a callable action');
|
||||
}
|
||||
unset($parameters['action']);
|
||||
unset($parameters['caller']);
|
||||
$this->eventLogger->start('route:run:call', 'Run callable route');
|
||||
call_user_func($action, $parameters);
|
||||
$this->eventLogger->end('route:run:call');
|
||||
$this->logger->warning('Deprecated action route used', ['parameters' => $parameters]);
|
||||
$this->callLegacyActionRoute($parameters);
|
||||
} elseif (isset($parameters['file'])) {
|
||||
$param = $parameters;
|
||||
unset($param['_route']);
|
||||
$_GET = array_merge($_GET, $param);
|
||||
unset($param);
|
||||
include $parameters['file'];
|
||||
$this->logger->debug('Deprecated file route used', ['parameters' => $parameters]);
|
||||
$this->includeLegacyFileRoute($parameters);
|
||||
} else {
|
||||
throw new \Exception('no action available');
|
||||
}
|
||||
$this->eventLogger->end('route:run');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{file:mixed, ...} $parameters
|
||||
*/
|
||||
protected function includeLegacyFileRoute(array $parameters): void {
|
||||
$param = $parameters;
|
||||
unset($param['_route']);
|
||||
$_GET = array_merge($_GET, $param);
|
||||
unset($param);
|
||||
require_once $parameters['file'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{action:mixed, ...} $parameters
|
||||
*/
|
||||
protected function callLegacyActionRoute(array $parameters): void {
|
||||
$action = $parameters['action'];
|
||||
if (!is_callable($action)) {
|
||||
throw new \Exception('not a callable action');
|
||||
}
|
||||
unset($parameters['action']);
|
||||
unset($parameters['caller']);
|
||||
$this->eventLogger->start('route:run:call', 'Run callable route');
|
||||
call_user_func($action, $parameters);
|
||||
$this->eventLogger->end('route:run:call');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url generator
|
||||
*
|
||||
|
|
@ -496,7 +512,7 @@ class Router implements IRouter {
|
|||
* @param string $file the route file location to include
|
||||
* @param string $appName
|
||||
*/
|
||||
private function requireRouteFile($file, $appName) {
|
||||
protected function requireRouteFile(string $file, string $appName): void {
|
||||
$this->setupRoutes(include $file, $appName);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue