diff --git a/README.md b/README.md index c40954f..0369ba0 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Ein kleines, dateibasiertes PHP-CMS für die Website der Walschleber KulTour. Ve - JSON-LD-Ausgabe für Veranstaltungssuchmaschinen - Dateibasierte Speicherung in `data/talks.json` - Automatische Konvertierung von JPG-, PNG- und WebP-Uploads nach WebP +- Admin-Migration für bereits vorhandene Bilder, die noch nicht als WebP gespeichert sind - Keine Composer-, Node.js- oder Build-Abhängigkeiten ## Voraussetzungen @@ -116,6 +117,8 @@ Diese Pfade enthalten den individuellen Datenbestand einer Installation: Beide Bereiche werden von Git ignoriert. Ein normaler `git pull` überschreibt oder löscht sie daher nach der Umstellung nicht. `uploads/.htaccess` und die `.gitignore`-Dateien bleiben Bestandteil des Repositorys. +Erkennt das Admin-Interface vorhandene JPG-/PNG-Bestandsbilder, erscheint automatisch der Hinweis „WebP-Migration verfügbar“. Der dortige Button konvertiert die erkannten Dateien, aktualisiert ihre Verweise in `data/talks.json` und entfernt die Originale erst nach erfolgreicher Datenbankaktualisierung. + > **Wichtig:** Auf einem Produktivserver niemals `git clean -fdx` ausführen. Der Parameter `-x` bezieht ignorierte Dateien ein und würde dadurch die JSON-Datenbank und Uploads löschen. ## Datensicherung @@ -136,15 +139,15 @@ Die Sicherung enthält damit Datenbank, Bilder und die installationsspezifische ### Reguläres Update -Zuerst den Arbeitsstand kontrollieren und eine Sicherung wie oben beschrieben erstellen: +Für Updates steht ein sicherer Updater bereit. Er sichert `data/`, `uploads/` und `config.php` außerhalb des Checkouts, aktualisiert ausschließlich per Fast-Forward und stellt die persistenten Dateien anschließend wieder her: ```bash cd /var/www/walschleber-kultour -git status --short -git fetch origin -git pull --ff-only origin main +bash scripts/update-server.sh . ``` +Der ausgegebene Backup-Ordner wird absichtlich nicht automatisch gelöscht. + Anschließend Schreibrechte und PHP-Syntax prüfen: ```bash @@ -159,7 +162,7 @@ Lokale Änderungen an Anwendungsdateien können ein Update blockieren. Sie sollt ### Lokale Änderungen an `config.php` -`config.php` gehört zum Repository, enthält aber installationsspezifische Werte. Die Datei deshalb immer zusammen mit den Daten sichern. Falls `git pull` meldet, dass lokale Änderungen an `config.php` überschrieben würden: +`config.php` gehört zum Repository, enthält aber installationsspezifische Werte. `scripts/update-server.sh` sichert und erhält diese Datei automatisch. Bei einem manuellen Update muss sie vor dem Pull gesichert werden: ```bash config_backup="../kultour-config-$(date +%Y%m%d-%H%M%S).php" @@ -174,30 +177,23 @@ Danach die Werte aus der gesicherten Datei manuell in die aktuelle `config.php` ## Einmaliges Update von einer älteren Version -In älteren Versionen wurden `data/talks.json` und vorhandene Uploads noch von Git verfolgt. Beim **ersten Update auf die bereinigte Version** müssen diese Daten deshalb gesichert und nach dem Pull wiederhergestellt werden. +In älteren Versionen wurden `data/talks.json` und vorhandene Uploads noch von Git verfolgt. Ein normales `git pull` würde diese Dateien beim ersten Wechsel auf die bereinigte Version entfernen. + +> **Vor diesem einmaligen Wechsel kein normales `git pull` ausführen.** Den aktuellen Updater zunächst außerhalb des alten Checkouts herunterladen und von dort starten: ```bash +curl -fL \ + https://git.mrblake.cc/MrBlake/Walschleber-Kultour-CMS/raw/branch/main/scripts/update-server.sh \ + -o /tmp/kultour-update-server.sh +chmod 700 /tmp/kultour-update-server.sh +bash /tmp/kultour-update-server.sh /var/www/walschleber-kultour + cd /var/www/walschleber-kultour - -install_backup="../kultour-migration-$(date +%Y%m%d-%H%M%S)" -mkdir -p "$install_backup" -cp -a data uploads config.php "$install_backup/" - -# Nur die früher getrackten Persistenzpfade auf den alten Git-Stand setzen. -git restore --source=HEAD --staged --worktree -- data uploads - -git pull --ff-only origin main - -# Den gesicherten Datenbestand wiederherstellen. -mkdir -p data uploads -cp -a "$install_backup/data/." data/ -cp -a "$install_backup/uploads/." uploads/ - chown -R www-data:www-data data uploads chmod 775 data uploads ``` -Falls das Update wegen einer lokal geänderten `config.php` stoppt, zusätzlich die Schritte aus „Lokale Änderungen an `config.php`“ durchführen. Nach dieser einmaligen Migration erscheinen Änderungen an der Datenbank und neue Uploads nicht mehr in `git status`. +Bei einem privaten Repository kann der Updater alternativ im angemeldeten Browser heruntergeladen und als Datei nach `/tmp/kultour-update-server.sh` übertragen werden. Nach dieser einmaligen Migration erscheinen Änderungen an der Datenbank und neue Uploads nicht mehr in `git status`. ## Wiederherstellung aus einem Backup diff --git a/admin.php b/admin.php index 5a11a86..1e879ef 100644 --- a/admin.php +++ b/admin.php @@ -26,8 +26,32 @@ if (isset($_GET['logout'])) { } if ($loggedIn) { + if (empty($_SESSION['migration_csrf'])) { + $_SESSION['migration_csrf'] = bin2hex(random_bytes(32)); + } + $migrationCsrf = (string)$_SESSION['migration_csrf']; + $migrationNotice = $_SESSION['migration_notice'] ?? null; + $migrationError = null; + unset($_SESSION['migration_notice']); + + // BESTANDS-UPLOADS NACH WEBP MIGRIEREN + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['migrate_uploads'])) { + $submittedToken = (string)($_POST['migration_csrf'] ?? ''); + if (!hash_equals($migrationCsrf, $submittedToken)) { + $migrationError = 'Die Migrationsanfrage ist abgelaufen. Bitte Seite neu laden und erneut versuchen.'; + } else { + try { + $_SESSION['migration_notice'] = migrate_uploads_to_webp(); + header('Location: admin.php?migration=done'); + exit; + } catch (Throwable $e) { + $migrationError = 'Migration fehlgeschlagen: ' . $e->getMessage(); + } + } + } + // CREATE/UPDATE - if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_event'])) { + elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_event'])) { $events = load_events(); $id = $_POST['id'] ?: 'evt_' . bin2hex(random_bytes(6)); $title = sanitize_text($_POST['title'] ?? ''); @@ -121,6 +145,13 @@ if ($loggedIn) { if ($e['id'] === $id) { $editEvent = $e; break; } } } + + try { + $nonWebpUploads = find_non_webp_uploads(); + } catch (Throwable $e) { + $nonWebpUploads = []; + $migrationError = 'Upload-Prüfung fehlgeschlagen: ' . $e->getMessage(); + } } ?> @@ -191,6 +222,43 @@ if ($loggedIn) { Gelöscht + +