• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TYPO3-Headless / headless / 32254505608

19 Aug 2026 12:47PM UTC coverage: 83.425% (+8.0%) from 75.459%
32254505608

Pull #893

github

web-flow
Merge eb703c148 into 1c4be38e5
Pull Request #893: [TASK] Reintroduce missing features, extension cleanup

741 of 884 new or added lines in 45 files covered. (83.82%)

228 existing lines in 12 files now uncovered.

2114 of 2534 relevant lines covered (83.43%)

9.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.77
/Classes/Middleware/RedirectModuleSourceUrlRewriter.php
1
<?php
2

3
/*
4
 * This file is part of the "headless" Extension for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.md file that was distributed with this source code.
8
 */
9

10
declare(strict_types=1);
11

12
namespace FriendsOfTYPO3\Headless\Middleware;
13

14
use FriendsOfTYPO3\Headless\Redirects\SourceUrlResolver;
15
use Psr\Http\Message\ResponseInterface;
16
use Psr\Http\Message\ServerRequestInterface;
17
use Psr\Http\Server\MiddlewareInterface;
18
use Psr\Http\Server\RequestHandlerInterface;
19
use TYPO3\CMS\Backend\Module\ModuleInterface;
20
use TYPO3\CMS\Backend\Routing\Route;
21
use TYPO3\CMS\Core\Http\Stream;
22

23
use function htmlspecialchars;
24
use function htmlspecialchars_decode;
25
use function in_array;
26
use function preg_replace_callback;
27

28
/**
29
 * Rewrites redirect source URLs in the "QR Codes" and "Short URLs" backend
30
 * modules to the site's frontendBase, so scanned/copied links land on the
31
 * public frontend instead of the TYPO3 API host.
32
 */
33
class RedirectModuleSourceUrlRewriter implements MiddlewareInterface
34
{
35
    protected const MODULE_IDENTIFIERS = ['qrcodes', 'short_urls'];
36

37
    public function __construct(protected readonly SourceUrlResolver $sourceUrlResolver) {}
38

39
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
40
    {
41
        $response = $handler->handle($request);
6✔
42

43
        if (!$this->isRedirectModuleRequest($request)) {
6✔
44
            return $response;
2✔
45
        }
46

47
        $html = (string)$response->getBody();
4✔
48

49
        if ($html === '') {
4✔
NEW
50
            return $response;
×
51
        }
52

53
        $rewritten = preg_replace_callback(
4✔
54
            '/(?<=\s)(content|text)="https?:\/\/([^\/"]+)([^"]*)"/',
4✔
55
            function (array $matches) use ($request): string {
4✔
56
                $resolved = $this->sourceUrlResolver->resolve(
4✔
57
                    $matches[2],
4✔
58
                    htmlspecialchars_decode($matches[3], ENT_QUOTES | ENT_HTML5),
4✔
59
                    $request
4✔
60
                );
4✔
61

62
                if ($resolved === null) {
4✔
63
                    return $matches[0];
1✔
64
                }
65

66
                return $matches[1] . '="' . htmlspecialchars($resolved, ENT_QUOTES | ENT_HTML5) . '"';
3✔
67
            },
4✔
68
            $html
4✔
69
        );
4✔
70

71
        if ($rewritten === null || $rewritten === $html) {
4✔
72
            return $response;
1✔
73
        }
74

75
        $body = new Stream('php://temp', 'rw');
3✔
76
        $body->write($rewritten);
3✔
77

78
        return $response->withBody($body)->withoutHeader('Content-Length');
3✔
79
    }
80

81
    protected function isRedirectModuleRequest(ServerRequestInterface $request): bool
82
    {
83
        $route = $request->getAttribute('route');
6✔
84

85
        if (!$route instanceof Route) {
6✔
86
            return false;
1✔
87
        }
88

89
        $module = $route->getOption('module');
5✔
90

91
        return $module instanceof ModuleInterface
5✔
92
            && in_array($module->getIdentifier(), self::MODULE_IDENTIFIERS, true);
5✔
93
    }
94
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc