# Walschleber KulTour CMS

Ein kleines, dateibasiertes PHP-CMS für die Website der Walschleber KulTour. Veranstaltungen werden ohne SQL-Datenbank in einer JSON-Datei verwaltet. Das integrierte Admin-Interface ermöglicht das Anlegen, Bearbeiten und Löschen von Veranstaltungen sowie den Upload von Plakaten.

## Funktionen

- Verwaltung zukünftiger und vergangener Veranstaltungen
- Öffentliche Programm-, Archiv- und Detailseiten
- 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

- Git
- Webserver mit PHP **7.4 oder neuer**
- PHP-Erweiterungen `fileinfo` und `mbstring`
- PHP-GD mit JPEG-, PNG- und WebP-Unterstützung oder alternativ Imagick
- optional `exif`, damit die Kameraausrichtung von JPEG-Dateien übernommen wird
- Schreibrechte des Webservers auf `data/` und `uploads/`

Die Anwendung verwendet absolute Pfade wie `/assets/` und `/uploads/`. Das Projekt sollte deshalb im Document-Root einer Domain oder Subdomain liegen.

## Installation über Git

Repository:

<https://git.mrblake.cc/MrBlake/Walschleber-Kultour-CMS.git>

### 1. Repository klonen

```bash
cd /var/www
git clone --branch main --single-branch https://git.mrblake.cc/MrBlake/Walschleber-Kultour-CMS.git walschleber-kultour
cd walschleber-kultour
```

Den Zielpfad `/var/www/walschleber-kultour` bei Bedarf an die Serverumgebung anpassen.

### 2. Anwendung konfigurieren

Die Grundeinstellungen befinden sich in `config.php`:

| Einstellung | Bedeutung |
| --- | --- |
| `SITE_NAME` | Name der Website |
| `BASE_URL` | Vollständige öffentliche URL ohne abschließenden Slash |
| `CONTACT_EMAIL` | Allgemeine Kontaktadresse |
| `ADMIN_PASSWORD_PLAIN` | Passwort für das Admin-Interface |
| `WEBP_QUALITY` | WebP-Qualität von 0 bis 100, Standard: 85 |
| `DEFAULT_OG_IMAGE` | Standardbild für Social Media und SEO |

Vor der Veröffentlichung müssen mindestens `BASE_URL`, `CONTACT_EMAIL` und `ADMIN_PASSWORD_PLAIN` geprüft beziehungsweise geändert werden. Für das Admin-Passwort ein langes, nur für diese Installation verwendetes Passwort einsetzen.

### 3. Schreibrechte setzen

Die Verzeichnisse sind bereits im Repository angelegt. Der Benutzer des Webservers muss darin Dateien erstellen und ändern dürfen:

```bash
cd /var/www/walschleber-kultour
chown -R www-data:www-data data uploads
chmod 775 data uploads
```

`www-data` ist ein häufig verwendeter Webserver-Benutzer. Auf Managed Hosting, Plesk, cPanel oder anderen Distributionen muss stattdessen der dort konfigurierte Benutzer verwendet werden.

Beim ersten Seitenaufruf erzeugt die Anwendung automatisch eine leere `data/talks.json`, sofern noch keine Datenbank vorhanden ist.

### 4. Webserver konfigurieren

Der Document-Root muss auf das Projektverzeichnis zeigen. Anschließend müssen mindestens diese URLs erreichbar sein:

- `https://example.org/` – Startseite
- `https://example.org/programm.php` – Veranstaltungsprogramm
- `https://example.org/admin.php` – Administration

Apache muss die Datei `uploads/.htaccess` berücksichtigen, damit hochgeladene Dateien nicht als PHP oder CGI ausgeführt werden. Zusätzlich müssen HTTP-Zugriffe auf `/data/` und `/.git/` durch die Webserver-Konfiguration gesperrt werden.

Beispiel für Apache innerhalb der VirtualHost-Konfiguration:

```apache
<Directory "/var/www/walschleber-kultour">
    AllowOverride All
    Require all granted
</Directory>

<Directory "/var/www/walschleber-kultour/data">
    Require all denied
</Directory>

<Directory "/var/www/walschleber-kultour/.git">
    Require all denied
</Directory>
```

Bei Nginx oder einer anderen Webserver-Konfiguration müssen `/data/` und `/.git/` ebenfalls gesperrt sowie die Ausführung von Skripten unter `/uploads/` verhindert werden.

### 5. Installation prüfen

```bash
php -l admin.php
php -l functions.php
php -m | grep -Ei 'fileinfo|mbstring|gd|imagick|exif'
php -r "var_export(function_exists('imagewebp') || class_exists('Imagick'));"
```

Der letzte Befehl muss `true` ausgeben. Danach unter `/admin.php` anmelden und testweise eine Veranstaltung mit Bild anlegen. Das Bild muss im Verzeichnis `uploads/` mit der Endung `.webp` gespeichert werden.

## Persistente Daten

Diese Pfade enthalten den individuellen Datenbestand einer Installation:

- `data/talks.json` – Veranstaltungen
- `uploads/` – hochgeladene Plakate und Bilder

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

Vor jedem Update sollte eine Sicherung außerhalb des Git-Checkouts angelegt werden:

```bash
cd /var/www/walschleber-kultour
install_backup="../kultour-backup-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$install_backup"
cp -a data uploads config.php "$install_backup/"
echo "Backup: $install_backup"
```

Die Sicherung enthält damit Datenbank, Bilder und die installationsspezifische Konfiguration.

## Update über Git

### Reguläres Update

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
bash scripts/update-server.sh .
```

Der ausgegebene Backup-Ordner wird absichtlich nicht automatisch gelöscht.

Anschließend Schreibrechte und PHP-Syntax prüfen:

```bash
chown -R www-data:www-data data uploads
chmod 775 data uploads
php -l admin.php
php -l functions.php
git log -1 --oneline
```

Lokale Änderungen an Anwendungsdateien können ein Update blockieren. Sie sollten vor dem Update geprüft und entweder committed, extern gesichert oder bewusst zurückgenommen werden.

### Lokale Änderungen an `config.php`

`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"
cp config.php "$config_backup"
echo "Konfigurations-Backup: $config_backup"
git diff -- config.php
git restore --source=HEAD --worktree -- config.php
git pull --ff-only origin main
```

Danach die Werte aus der gesicherten Datei manuell in die aktuelle `config.php` übernehmen. Die komplette alte Datei nicht blind zurückkopieren, weil neue Versionen zusätzliche Einstellungen enthalten können.

## Einmaliges Update von einer älteren Version

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
chown -R www-data:www-data data uploads
chmod 775 data uploads
```

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

```bash
cd /var/www/walschleber-kultour
cp -a /pfad/zum/backup/data/. data/
cp -a /pfad/zum/backup/uploads/. uploads/
chown -R www-data:www-data data uploads
chmod 775 data uploads
```

Die gesicherte `config.php` nur vollständig zurückkopieren, wenn sie zur aktuell installierten Softwareversion gehört. Andernfalls die individuellen Werte manuell übertragen.

## Fehlerbehebung

### Datenbank kann nicht geschrieben werden

Schreibrechte und Besitzer prüfen:

```bash
ls -la data uploads
```

### WebP-Konvertierung ist nicht verfügbar

Prüfen, ob GD mit WebP-Unterstützung oder Imagick aktiv ist:

```bash
php -r "var_dump(function_exists('imagewebp'), class_exists('Imagick'));"
```

Nach dem Aktivieren einer PHP-Erweiterung muss je nach Serverkonfiguration PHP-FPM oder der Webserver neu gestartet werden.

### Git-Update wird durch lokale Änderungen blockiert

Zuerst mit `git status --short` und `git diff` prüfen, welche Dateien geändert wurden. Daten niemals mit `git reset --hard` oder `git clean -fdx` „bereinigen“. Vor jeder Korrektur mindestens `data/`, `uploads/` und `config.php` außerhalb des Repositorys sichern.

## Sicherheitshinweise

- Standard-Admin-Passwort vor dem ersten Einsatz ändern.
- Website und Admin-Interface ausschließlich über HTTPS betreiben.
- `data/` und `uploads/` regelmäßig extern sichern.
- Skriptausführung im Upload-Verzeichnis auf Webserver-Ebene blockieren.
- Git-Verzeichnis `.git/` darf nicht öffentlich ausgeliefert werden. Der Webserver muss Zugriffe darauf sperren.
