Files
KantSites/src/EventSubscriber/MaintenanceSubscriber.php
T
kantarciandClaude Opus 5 aaea385422 Die Verwaltung kann umziehen: /admin ist frei waehlbar
php bin/console cms:admin:path <neu> legt die Verwaltung auf eine
andere Adresse. Geprueft wird, dass der Name frei ist und keine Seite
verdeckt; der Wert steht in .env.local und fuellt einen Parameter, der
als Praefix in jeder Verwaltungsroute steht, in der Firewall, in den
Schutzkopfzeilen und in der Statistik.

Die robots.txt nennt einen geaenderten Namen nicht - sie ist oeffentlich
und waere sonst ein Wegweiser. Beim Standardnamen bleibt die Zeile,
weil diese Adresse ohnehin jeder kennt.

Die Auffangroute fuer Seiten steht jetzt zuletzt: sie kann einen frei
gewaehlten Namen nicht per Regex ausschliessen, und die Reihenfolge ist
ohnehin die richtige. Der Befehl raeumt den Zwischenspeicher auf, aber
nicht den, in dem er selbst laeuft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 20:51:55 +02:00

55 lines
2.1 KiB
PHP

<?php
namespace App\EventSubscriber;
use App\Ops\Updater;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;
/**
* While an update runs, the website answers with 503 and the administration stays open.
*
* 503 and not 200 with a notice: a search engine reads 503 with Retry-After as "come back later"
* and keeps the page in its index, while a 200 would teach it that the page now contains an
* excuse. The administration has to stay reachable, because otherwise nobody could finish or
* undo the update.
*/
final class MaintenanceSubscriber implements EventSubscriberInterface
{
public function __construct(private Environment $twig, private string $projectDir, private string $adminPath)
{
}
public static function getSubscribedEvents(): array
{
// Before the router: during maintenance no controller should run at all.
return [KernelEvents::REQUEST => ['onRequest', 40]];
}
public function onRequest(RequestEvent $event): void
{
if (!$event->isMainRequest() || !is_file($this->projectDir.'/'.Updater::MAINTENANCE_FILE)) {
return;
}
$path = $event->getRequest()->getPathInfo();
if (preg_match('#^/('.preg_quote($this->adminPath, '#').'|assets/|media/|favicon)#', $path)) {
return;
}
$since = @file_get_contents($this->projectDir.'/'.Updater::MAINTENANCE_FILE);
$response = new Response(
$this->twig->render('maintenance.html.twig', ['since' => trim((string) $since)]),
Response::HTTP_SERVICE_UNAVAILABLE,
[
'Retry-After' => '600',
'Cache-Control' => 'no-store',
'Content-Type' => 'text/html; charset=UTF-8',
'Content-Security-Policy' => "default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'",
],
);
$event->setResponse($response);
}
}