Let plugins run their own PHP code
A plugin can now bring a plugin.php that registers hooks, scheduled tasks, its own tables, public pages and admin screens. Failures stay contained to the plugin; a form on a plugin page can be submitted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b61f958ca1
commit
9825bac3b3
17 files changed
+897
-19
No files matched your search
+46
-3
@@ -5,9 +5,9 @@ Website. Farben, Schriften und Buttons fasst es nie an – das Design gehört de
|
||||
Stylesheets und Skripten. Eingeschaltet und eingestellt wird es in der Verwaltung unter **Plugins**
|
||||
(Administrator). Hintergrund und Grenzen: ADR 102 und ADR 103 in `docs/ARCHITECTURE.md`.
|
||||
|
||||
**Ein Plugin bringt keinen PHP-Code mit.** Alles ist Manifest plus Twig. Deshalb gibt es keine
|
||||
Hooks in Speichern oder Veröffentlichen und keine eigenen Tabellen – und deshalb kann ein Update
|
||||
des Kerns ein Plugin nicht brechen, solange die Übergaben unten stehen.
|
||||
Ein Plugin kann reines Manifest plus Twig sein. Braucht es mehr – eigene Tabellen, Aufgaben im
|
||||
Takt, Seiten aus eigenen Daten, Verwaltungsbildschirme –, bringt es wie bei WordPress eine
|
||||
`plugin.php` mit (siehe „Eigener PHP-Code“, ADR 127).
|
||||
|
||||
## Der Ordner
|
||||
|
||||
@@ -121,6 +121,49 @@ Stylesheet und die Design-Tokens des Kerns; Palette, Schriften und Buttons der W
|
||||
nur der Betreiber unter **Design**. So färbt kein Schalter eine Website um, und nichts, was dort
|
||||
eingestellt wurde, geht durch ein Plugin verloren (ADR 105).
|
||||
|
||||
## Eigener PHP-Code (`plugin.php`)
|
||||
|
||||
`"main": "plugin.php"` im Manifest lädt die Datei, solange das Plugin eingeschaltet ist. Sie gibt
|
||||
eine Funktion zurück und meldet sich dort beim Kern an:
|
||||
|
||||
```php
|
||||
<?php
|
||||
return static function (App\Plugin\PluginApi $api): void {
|
||||
$tabelle = $api->table('objekt'); // plugin_<name>_objekt
|
||||
$api->onInstall(fn () => $api->db()->executeStatement("CREATE TABLE IF NOT EXISTS $tabelle (id VARCHAR(20) PRIMARY KEY)"));
|
||||
$api->addTask('abgleich', 'Abgleich', 'Was ausbleibt, wenn sie nicht läuft.', 3600, fn (): string => 'Bericht');
|
||||
$api->addPage('/objekte/{slug}', fn (array $p): ?array => ['title' => 'Titel', 'description' => 'Text', 'blocks' => []]);
|
||||
$api->addData('liste', fn (array $argumente): array => []);
|
||||
$api->addFilter('sitemap.entries', fn (array $e, string $origin): array => $e);
|
||||
$api->addAdminPage('uebersicht', 'Übersicht', 'admin/uebersicht.html.twig', fn (): array => []);
|
||||
$api->addAdminAction('jetzt', 'Jetzt ausführen', 'abgleich'); // Aufgabenschlüssel oder Callback
|
||||
};
|
||||
```
|
||||
|
||||
| Methode | Zweck |
|
||||
|---|---|
|
||||
| `onInstall`, `onDeactivate` | Beim Einschalten und bei neuer Fassung; beim Ausschalten. Muss wiederholbar sein. Tabellen bleiben beim Ausschalten stehen. |
|
||||
| `addAction`, `addFilter` | Hooks wie bei WordPress, kleinere Priorität zuerst. |
|
||||
| `addTask` | Aufgabe im Plan des Kerns (Bildschirm „Aufgaben“); Fehler werfen, Rückgabe ist der Bericht. |
|
||||
| `addPage` | Öffentliche Seite im Rahmen der Website. Gibt `title`, `description`, `blocks` und optional `seoTitle`, `robots`, `status`, `image` zurück oder `null` für 404. Eine veröffentlichte Seite geht vor. |
|
||||
| `addData` | Werte für Vorlagen: `kant_plugin_data('name', 'schluessel', {…})`. |
|
||||
| `addAdminPage`, `addAdminAction` | Bildschirm und Knopf der Verwaltung, nur für Administratoren, Knöpfe mit CSRF-Schutz. |
|
||||
| `settings`, `db`, `table`, `media`, `fetch`, `storeImage`, `directory` | Einstellungen, Datenbank, Mediathek, HTTPS-Abruf, Bild ablegen. |
|
||||
|
||||
Der Kern ruft bisher diese Filter auf: `sitemap.entries` (`$entries`, `$origin`) und `form.context`
|
||||
(`$extra`, `$form`, `$path`: zusätzliche Angaben `Name => Text` für eine eingehende Anfrage).
|
||||
Weitere Hooks kommen in den
|
||||
Kern, wenn ein Plugin sie braucht.
|
||||
|
||||
Die SQL-Anweisungen müssen auf SQLite und MySQL laufen. Klassen und Funktionen gehören in einen
|
||||
eigenen Namensraum. Plugin-Tabellen gehören nicht zum Inhaltspaket; bei SQLite sind sie in jeder
|
||||
Sicherung, weil die ganze Datei gesichert wird.
|
||||
|
||||
**Rechte:** Der Code läuft mit den vollen Rechten der Anwendung. Das ist kein Sandkasten. Eine
|
||||
Ausnahme beim Laden, in einem Hook oder auf einer Seite nimmt nur das Plugin aus dem Spiel und
|
||||
steht auf dem Bildschirm „Plugins“. Einen echten PHP-Abbruch fängt das nicht ab: Dann den Ordner
|
||||
unter `plugins/` umbenennen.
|
||||
|
||||
## Die Vorlagen
|
||||
|
||||
### Bausteine
|
||||
|
||||
Reference in new issue
Block a user