aboutsummaryrefslogtreecommitdiff
path: root/lib/middleware
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+studip@gmail.com>2025-07-10 10:48:34 +0200
committerJan-Hendrik Willms <tleilax+studip@gmail.com>2025-07-10 10:48:34 +0200
commit7f557a0d69924597be5ca6b3aa8495ed26460429 (patch)
treeeaa918393753dca1ac74177c83bee7ed3c1d78b0 /lib/middleware
parent1284a27e6cf95a55f8cce006a670396045ca2e7a (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.php105
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;
+ }
+}