From ea3dd4ddf2b3c61a15350dd62a9ee0c77fb2f8f8 Mon Sep 17 00:00:00 2001 From: Umut Kantarci Date: Sun, 13 Sep 2026 21:56:17 +0200 Subject: [PATCH] Fassung 1.4.2: die Systempruefung nennt die SQLite-Fassung Auf dem Hosting brach die Installation im dritten Schritt ab: near "(": syntax error. Dort laeuft SQLite in einer Fassung vor 3.16, und Doctrine liest das Schema mit Tabellenfunktionen wie pragma_table_info(...), die es erst seit 3.16 gibt. Die Pruefung nennt die gefundene Fassung jetzt vor der Wahl der Datenbank, und der Datenbankschritt bietet SQLite gar nicht erst an, wenn sie zu alt ist - mit dem Hinweis auf MySQL. Eine Voraussetzung, die erst mitten in der Installation auffaellt, ist keine Pruefung wert. Co-Authored-By: Claude Opus 5 --- README.md | 2 ++ VERSION | 2 +- docs/STATUS.md | 1 + src/Controller/InstallController.php | 7 +++++- src/Ops/Installation.php | 35 ++++++++++++++++++++++++++++ templates/install/database.html.twig | 2 +- tests/InstallationTest.php | 27 +++++++++++++++++++++ 7 files changed, 73 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 997a227..f4ef856 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ npm.cmd run audit Unter Linux/macOS `npm` und `npx` ohne `.cmd`; in CI `npx playwright install --with-deps chromium`. `test:browser` und `audit` benötigen den laufenden lokalen Produktionsmodus auf Port 8080. Ein anderes Ziel lässt sich über `CMS_URL` konfigurieren. `test:editor` startet einen eigenen PHP-Prozess auf einem freien Port mit isolierter Datenbank und zufälligem Testkonto; es ändert keine echten Seiten oder Benutzer. `PHP_BINARY` kann dafür einen alternativen PHP-Pfad angeben. Testdaten bleiben unter `var/browser-tests`, Berichte/Screenshots unter `reports/`. Das Skript erneuert zuvor den Produktionscache. +**Datenbank:** SQLite ab Fassung 3.16 (Doctrine liest das Schema mit Tabellenfunktionen, die es erst seit dieser Fassung gibt) oder MySQL/MariaDB. Auf älteren Systemen – manche Shared Hoster liefern noch SQLite 3.7 – bleibt MySQL; die Systemprüfung des Installers nennt die gefundene Fassung und bietet SQLite gar nicht erst an, wenn sie zu alt ist. + Die Verwaltung liegt unter `/admin`. `php bin/console cms:admin:path meine-verwaltung` legt sie auf eine andere Adresse: der Wert landet in `.env.local`, gilt für Routen, Firewall und Schutzkopfzeilen, und wird in der `robots.txt` bewusst nicht genannt. Ohne Argument zeigt der Befehl die aktuelle Adresse. `composer format` formatiert PHP. `composer build` wärmt den Symfony-Produktionscache; öffentliche CSS-Dateien sind direkt auslieferbar, es ist kein Frontend-Bundler nötig. Bei Änderungen an `public/assets/design-tokens.json` einmal `npm.cmd run build:design` ausführen und die erzeugte CSS-Datei mitliefern; Node ist auf dem Hosting nicht erforderlich. Nach Änderungen an Produktionskonfiguration/Templates `php bin/console cache:clear --env=prod --no-debug` ausführen. Falls lokale Tests alte Templates verwenden, vor PHPUnit auch `php bin/console cache:clear --env=test --no-debug` ausführen. diff --git a/VERSION b/VERSION index 347f583..9df886c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.1 +1.4.2 diff --git a/docs/STATUS.md b/docs/STATUS.md index 4f2e10e..10d5567 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -37,6 +37,7 @@ Erster Commit angelegt (`82b0782`); das Projekt hat damit einen Rückfallpunkt. - **Das erste Bild einer Seite lädt sofort**, alles darunter weiterhin verzögert. Es ist meistens das größte Ding über der Falz. - **Slider mit Punkten ohne Skript** (ADR 044): `::scroll-marker` zeichnet je Folie einen Punkt, der aktive ist erkennbar, die Rollleiste entfällt; ältere Browser behalten das wischbare Schiebefeld. Beitragskarten sind echte Karten (Bild 16:10, 18 px Ecken). Überschriften dürfen ein Wort hervorheben (``, in Akzentfarbe). Behoben: die Theme-Schriftskala überschrieb die Größen in Karten und Aufruf-Bändern. - **„Weiterlesen" ist jetzt ein Link.** In der wechselseitigen Beitragsliste stand dort eine reine Beschriftung: sie sah aus wie ein Knopf und war keiner. Der Titel steckt für Vorlesesoftware im Linktext, damit nicht zwölf Links gleich heißen. +- **Behoben in 1.4.2: die Systemprüfung nennt jetzt die SQLite-Fassung.** Auf dem Hosting scheiterte die Installation im dritten Schritt mit „near \"(\": syntax error" – dort läuft SQLite in einer Fassung vor 3.16, und Doctrine liest das Schema mit Tabellenfunktionen (`pragma_table_info(...)`), die es erst seit 3.16 gibt. Die Prüfung nennt die gefundene Fassung vor der Wahl der Datenbank, und der Datenbankschritt bietet SQLite gar nicht erst an, wenn sie zu alt ist – mit dem Hinweis auf MySQL. Eine Voraussetzung, die erst mitten in der Installation auffällt, ist keine Prüfung wert. - **Behoben in 1.4.1: dem Releasearchiv fehlten `migrations.php` und `cli-config.php`.** Auf dem Hosting brach die Installation deshalb im dritten Schritt ab – „The configuration file does not exist", genau dort, wo die Tabellen entstehen sollten. Die beiden Dateien standen weder in der Mitnahme- noch in der Ausschlussliste des Releaseskripts, also fiel niemandem auf, dass sie fehlen. Ein Test ordnet jetzt **jeden** Eintrag im Projektstamm einer der beiden Listen zu; was neu dazukommt und unbedacht bleibt, lässt ihn fehlschlagen. Der Installationsweg wurde anschließend vollständig durchgespielt: 3504 Dateien entpackt, 14 Migrationen ausgeführt, 15 Tabellen angelegt. - **Fassung 1.4.0 ist veröffentlicht** und der Installationsweg einmal vollständig durchgespielt: `install.php` aus dem Release geladen (anonym, ohne Anmeldung), in ein leeres Verzeichnis gelegt, aufgerufen – es lädt `kantsites-1.4.0.zip` (4,7 MB, 3502 Dateien mit `vendor/`), prüft die SHA-256-Summe, entpackt und löscht sich selbst. Die frische Installation antwortet mit der Systemprüfung unter `/install`. **Das Repository ist dafür öffentlich** – ein privates liefert die Downloadadresse ohne Anmeldung nicht aus. - **Die Verwaltung kann umziehen** (ADR 065): `php bin/console cms:admin:path meine-verwaltung` legt sie auf eine andere Adresse – geprüft wird, dass der Name frei ist und keine Seite verdeckt. Der Wert steht in `.env.local` und gilt für Routen, Firewall, Schutzkopfzeilen und Statistik. **In der `robots.txt` wird ein geänderter Name nicht genannt**; beim Standardnamen `admin` bleibt die Zeile, weil diese Adresse ohnehin bekannt ist. Die Systemseite zeigt die aktuelle Adresse an. diff --git a/src/Controller/InstallController.php b/src/Controller/InstallController.php index 3247278..f98bf4b 100644 --- a/src/Controller/InstallController.php +++ b/src/Controller/InstallController.php @@ -76,7 +76,12 @@ final class InstallController extends AbstractController 'error' => $error, 'values' => $request->request->all(), 'mysql' => \extension_loaded('pdo_mysql'), - 'sqlite' => \extension_loaded('pdo_sqlite'), + // SQLite nur, wenn die Fassung die Tabellenfunktionen kennt, mit denen Doctrine das + // Schema liest - sonst scheitert erst der naechste Schritt, und zwar unverstaendlich. + 'sqlite' => \extension_loaded('pdo_sqlite') && null !== $this->installation->sqliteVersion() + && version_compare((string) $this->installation->sqliteVersion(), Installation::MIN_SQLITE, '>='), + 'sqliteVersion' => $this->installation->sqliteVersion(), + 'minSqlite' => Installation::MIN_SQLITE, ...$this->token('datenbank'), ]); } diff --git a/src/Ops/Installation.php b/src/Ops/Installation.php index 0eaf07e..20bbd93 100644 --- a/src/Ops/Installation.php +++ b/src/Ops/Installation.php @@ -71,6 +71,25 @@ final class Installation * Every failing check names the file or path that has to change. A check that is merely * advisable is marked as such, so a missing `proc_open` does not look like a reason to stop. */ + /** Ab dieser Fassung kennt SQLite die Tabellenfunktionen, mit denen Doctrine das Schema liest. */ + public const MIN_SQLITE = '3.16.0'; + + /** Die Fassung der eingebauten SQLite-Bibliothek, oder null wenn es keine gibt. */ + public function sqliteVersion(): ?string + { + if (!extension_loaded('pdo_sqlite')) { + return null; + } + + try { + $version = (new \PDO('sqlite::memory:'))->query('SELECT sqlite_version()')?->fetchColumn(); + } catch (\PDOException) { + return null; + } + + return is_string($version) ? $version : null; + } + public function checks(): array { $checks = []; @@ -83,6 +102,22 @@ final class Installation $drivers = array_values(array_intersect(['pdo_sqlite', 'pdo_mysql'], get_loaded_extensions())); $checks[] = $this->check('Datenbanktreiber', [] !== $drivers, 'Weder pdo_sqlite noch pdo_mysql ist vorhanden. Ohne einen von beiden gibt es keine Datenbank.', true, implode(', ', $drivers)); + // Die Fassung von SQLite, und zwar vor der Wahl der Datenbank. Doctrine liest das Schema + // mit Tabellenfunktionen wie `pragma_table_info(...)`; die gibt es erst seit SQLite 3.16 + // (Januar 2017). Auf einem Hosting mit aelterem SQLite bricht sonst mitten in der + // Installation eine Abfrage mit `near "(": syntax error` ab - eine Meldung, die niemandem + // sagt, was zu tun ist. Gefunden auf einem echten Hosting, nicht hier. + $sqlite = $this->sqliteVersion(); + if (null !== $sqlite) { + $checks[] = $this->check( + 'SQLite-Fassung', + version_compare($sqlite, self::MIN_SQLITE, '>='), + sprintf('Gefunden: %s. Für eine SQLite-Datenbank wird mindestens %s gebraucht. Diese Installation läuft trotzdem – aber mit MySQL statt SQLite; eine Datenbank legt man beim Hoster im Kundenmenü an.', $sqlite, self::MIN_SQLITE), + false, + $sqlite, + ); + } + $webp = extension_loaded('gd') && (gd_info()['WebP Support'] ?? false); $checks[] = $this->check('GD mit WebP', $webp, 'Bilder werden beim Hochladen in WebP umgewandelt. Ohne GD mit WebP-Unterstützung schlägt jeder Upload fehl. Der Rest der Website funktioniert.', false); $checks[] = $this->check('ZIP-Erweiterung', class_exists(\ZipArchive::class), 'Wird für Sicherungen als Archiv gebraucht. Ohne sie bleibt die Sicherung ein Verzeichnis.', false); diff --git a/templates/install/database.html.twig b/templates/install/database.html.twig index 90549c4..a4d1c82 100644 --- a/templates/install/database.html.twig +++ b/templates/install/database.html.twig @@ -12,7 +12,7 @@ Art der Datenbank