feat: assign custom 404 pages with the website theme (1.8.0)
This commit is contained in:
1 parent
a3c89bb69d
commit
16da844934
17 files changed
+638
-92
No files matched your search
@@ -3,6 +3,7 @@
|
||||
namespace App\Content;
|
||||
|
||||
use App\Domain\InvalidPage;
|
||||
use App\Domain\StaleWrite;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Exception\TableNotFoundException;
|
||||
|
||||
@@ -53,6 +54,7 @@ final class SiteSettings
|
||||
'robotsExtra' => '',
|
||||
// Which stored page answers at the site root. Everything else derives from this.
|
||||
'homePath' => 'home',
|
||||
'notFoundPageId' => '',
|
||||
// The consent question. Off by default, because a site that loads nothing from third
|
||||
// parties has nothing to ask about, and a banner without a reason is only in the way.
|
||||
'consentBanner' => false,
|
||||
@@ -96,6 +98,8 @@ final class SiteSettings
|
||||
public function save(array $input): void
|
||||
{
|
||||
$values = self::DEFAULTS;
|
||||
// Assigned separately, so saving company data cannot clear the error page.
|
||||
$values['notFoundPageId'] = $this->load()['notFoundPageId'];
|
||||
foreach (['legalName' => 200, 'description' => 300, 'phone' => 40, 'email' => 120, 'street' => 120, 'postalCode' => 16, 'city' => 120] as $key => $max) {
|
||||
$values[$key] = mb_substr(trim((string) ($input[$key] ?? '')), 0, $max);
|
||||
}
|
||||
@@ -194,9 +198,13 @@ final class SiteSettings
|
||||
throw new InvalidPage('Die Startseite braucht eine gültige Adresse.');
|
||||
}
|
||||
// A root that points nowhere would answer every visit with 404, so it must exist.
|
||||
if (false === $this->db->fetchOne('SELECT id FROM page WHERE website_id = ? AND path = ? AND deleted_at IS NULL', ['default', $home])) {
|
||||
$homeId = $this->db->fetchOne('SELECT id FROM page WHERE website_id = ? AND path = ? AND deleted_at IS NULL', ['default', $home]);
|
||||
if (false === $homeId) {
|
||||
throw new InvalidPage(sprintf('Es gibt keine Seite mit der Adresse /%s.', $home));
|
||||
}
|
||||
if ($homeId === $values['notFoundPageId']) {
|
||||
throw new InvalidPage('Die 404-Seite kann nicht gleichzeitig die Startseite sein.');
|
||||
}
|
||||
$values['homePath'] = $home;
|
||||
|
||||
$values['consentBanner'] = (bool) ($input['consentBanner'] ?? false);
|
||||
@@ -237,6 +245,41 @@ final class SiteSettings
|
||||
]);
|
||||
}
|
||||
|
||||
/** Change only the 404 assignment, preserving settings saved in other forms. */
|
||||
public function assignNotFoundPage(string $id, string $expectedId): void
|
||||
{
|
||||
$this->db->transactional(function () use ($id, $expectedId): void {
|
||||
$lock = $this->db->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SQLitePlatform ? '' : ' FOR UPDATE';
|
||||
$raw = $this->db->fetchOne('SELECT settings FROM website WHERE id = ?'.$lock, ['default']);
|
||||
$stored = is_string($raw) ? json_decode($raw, true, 512, JSON_THROW_ON_ERROR) : [];
|
||||
$stored = is_array($stored) ? $stored : [];
|
||||
$current = $stored['notFoundPageId'] ?? '';
|
||||
if ($current !== $expectedId) {
|
||||
throw new StaleWrite('Die 404-Zuordnung wurde inzwischen geändert. Lade die Einstellungen neu.');
|
||||
}
|
||||
if ('' !== $id) {
|
||||
$page = $this->db->fetchAssociative('SELECT path, type FROM page WHERE id = ? AND website_id = ? AND deleted_at IS NULL', [$id, 'default']);
|
||||
if (false === $page || 'page' !== $page['type']) {
|
||||
throw new InvalidPage('Bitte wähle eine vorhandene Seite als 404-Seite.');
|
||||
}
|
||||
if ($page['path'] === ($stored['homePath'] ?? self::DEFAULTS['homePath'])) {
|
||||
throw new InvalidPage('Die Startseite kann nicht gleichzeitig die 404-Seite sein.');
|
||||
}
|
||||
}
|
||||
if ($current === $id) {
|
||||
return;
|
||||
}
|
||||
$stored['notFoundPageId'] = $id;
|
||||
$changed = $this->db->executeStatement('UPDATE website SET settings = ? WHERE id = ?', [
|
||||
json_encode($stored, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE), 'default',
|
||||
]);
|
||||
if (1 !== $changed) {
|
||||
throw new StaleWrite('Die Einstellungen wurden inzwischen geändert. Lade die Seite neu.');
|
||||
}
|
||||
});
|
||||
$this->loaded = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Which of the two mandatory pages are missing, by their settings key.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user