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 /lib/middleware | |
| parent | 1284a27e6cf95a55f8cce006a670396045ca2e7a (diff) | |
add legacy route director that should fix all forum links, fixes #5698
Closes #5698
Merge request studip/studip!4326
Diffstat (limited to 'lib/middleware')
| -rw-r--r-- | lib/middleware/LegacyRedirectorMiddleware.php | 105 |
1 files changed, 105 insertions, 0 deletions
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; + } +} |
