diff options
| author | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2025-07-10 10:48:34 +0200 |
|---|---|---|
| committer | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2025-07-10 10:48:34 +0200 |
| commit | 7f557a0d69924597be5ca6b3aa8495ed26460429 (patch) | |
| tree | eaa918393753dca1ac74177c83bee7ed3c1d78b0 | |
| parent | 1284a27e6cf95a55f8cce006a670396045ca2e7a (diff) | |
add legacy route director that should fix all forum links, fixes #5698
Closes #5698
Merge request studip/studip!4326
| -rw-r--r-- | lib/classes/StudipDispatcher.php | 32 | ||||
| -rw-r--r-- | lib/middleware/LegacyRedirectorMiddleware.php | 105 | ||||
| -rw-r--r-- | public/dispatch.php | 4 |
3 files changed, 128 insertions, 13 deletions
diff --git a/lib/classes/StudipDispatcher.php b/lib/classes/StudipDispatcher.php index 10799c7..a54c45c 100644 --- a/lib/classes/StudipDispatcher.php +++ b/lib/classes/StudipDispatcher.php @@ -90,19 +90,25 @@ class StudipDispatcher extends Trails\Dispatcher return $this->container->make($class, ['dispatcher' => $this]); } - public function getRouteCallable($uri) + public function getRouteCallable($uri): callable { - $uri = $this->clean_request_uri((string) $uri); - [$controller_path, $unconsumed] = '' === $uri ? $this->default_route() : $this->parse($uri); - $controller = $this->load_controller($controller_path); - return function ( - \Psr\Http\Message\ServerRequestInterface $request, - \Psr\Http\Message\ResponseInterface $response, - array $args - ) use ($controller, $unconsumed): \Psr\Http\Message\ResponseInterface { - $controller->injectResponse($response); - $response = $controller->perform($unconsumed); - return $response->getPsrResponse(); - } ; + try { + $uri = $this->clean_request_uri((string) $uri); + [$controller_path, $unconsumed] = '' === $uri ? $this->default_route() : $this->parse($uri); + $controller = $this->load_controller($controller_path); + return function ( + \Psr\Http\Message\ServerRequestInterface $request, + \Psr\Http\Message\ResponseInterface $response, + array $args + ) use ($controller, $unconsumed): \Psr\Http\Message\ResponseInterface { + $controller->injectResponse($response); + $response = $controller->perform($unconsumed); + return $response->getPsrResponse(); + } ; + } catch (Exception $e) { + return function () use ($e) { + throw $e; + }; + } } } diff --git a/lib/middleware/LegacyRedirectorMiddleware.php b/lib/middleware/LegacyRedirectorMiddleware.php new file mode 100644 index 0000000..5b9960c --- /dev/null +++ b/lib/middleware/LegacyRedirectorMiddleware.php @@ -0,0 +1,105 @@ +<?php +namespace Studip\Middleware; + +use Forum\ForumTopic; +use NotificationCenter; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\{ResponseInterface as Response, + ServerRequestInterface as Request, + UriInterface +}; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Slim\App; + +final class LegacyRedirectorMiddleware implements MiddlewareInterface +{ + private array $legacyRoutes = []; + + public function __construct( + private readonly App $app, + private readonly ResponseFactoryInterface $response_factory + ) { + $this->addLegacyRoute( + '#^course/forum/index/index#', + [$this, 'redirectForumPost'] + ); + + NotificationCenter::postNotification('LEGACY_REDIRECTOR_DID_CREATE', $this); + } + + public function addLegacyRoute(string $route, callable $handler): void + { + $this->legacyRoutes[$route] = $handler; + } + + public function process(Request $request, RequestHandlerInterface $handler): Response + { + $path = $this->getRelativePath($request); + + foreach ($this->legacyRoutes as $legacyRoute => $routeHandler) { + if ($this->routeMatches($path, $legacyRoute)) { + /** @var UriInterface $newUri */ + $newUri = $routeHandler($request); + + $response = $this->response_factory->createResponse(301); + $response->getBody()->write(''); + return $response->withHeader('Location', (string) $newUri); + } + } + + return $handler->handle($request); + } + + private function getRelativePath(Request $request): string + { + $basePath = $this->app->getBasePath(); + $fullPath = $request->getUri()->getPath(); + + return ltrim(substr($fullPath, strlen($basePath)), '/'); + } + + private function routeMatches(string $path, string $route): bool + { + if (str_starts_with($route, '#') && str_ends_with($route, '#')) { + return preg_match($route, $path); + } + + return str_starts_with($path, $route); + } + + private function redirectForumPost(Request $request): UriInterface + { + $uri = $request->getUri(); + $range_id = $request->getQueryParams()['cid']; + $forum_id = explode('/', $this->getRelativePath($request))[4] ?? null; + + if ($forum_id === $range_id) { + $redirectUri = $uri->withPath( + str_replace( + 'course/forum/index/index/' . $forum_id, + 'course/forum/topics', + $uri->getPath() + ) + ); + } elseif (ForumTopic::exists($forum_id)) { + $redirectUri = $uri->withPath( + str_replace( + 'course/forum/index/index', + 'course/forum/topics/show', + $uri->getPath() + ) + ); + } else { + $redirectUri = $uri->withPath( + str_replace( + 'course/forum/index/index', + 'course/forum/discussions/show', + $uri->getPath() + ) + ); + } + + return $redirectUri; + } +} diff --git a/public/dispatch.php b/public/dispatch.php index c5c2b93..d2ebdaf 100644 --- a/public/dispatch.php +++ b/public/dispatch.php @@ -31,6 +31,10 @@ $app->setBasePath($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP'] . 'dispatch.php'); $studip_dispatcher = app(\Trails\Dispatcher::class); $route_callable = $studip_dispatcher->getRouteCallable(Request::pathInfo()); $app->any(Request::pathInfo(), $route_callable); + +// Add legacy director so links shall not break +$app->add(Studip\Middleware\LegacyRedirectorMiddleware::class); + NotificationCenter::postNotification('SLIM_BEFORE_RUN', $app); $app->run(); NotificationCenter::postNotification('SLIM_AFTER_RUN', $app); |
