Workbench Plugin Contract v1
Der verbindliche, versionierte Vertrag, über den ein Plugin zur Werkbank
beiträgt – Aktivitätsleiste, Seitenspalte, Zusatzspalte, unteres Panel,
Statusleiste, Befehlsleiste/-palette und das Modulverzeichnis. Diese Seite
ist die deutsche Kurzfassung für Betreiber und Autoren; die verbindliche,
vollständige Spezifikation (API, Lebenszyklus, Fehlerverhalten, Beispiel)
steht im Repository: lib/plugins/wkfluentui/docs/contract-v1.md.
Verwandt: wkfluentui-Übersicht · Styles-Contract
Warum es diesen Vertrag gibt
Bis Contract v1 lief ein Beitrag zur Werkbank über fünf getrennte, nur über
method_exists() erkannte Mechanismen (getModuleInfo(),
getShellRegions(), getShellBadge(), getShellViews(), das Ereignis
WKFLUENTUI_ADMIN_COMMANDS). Mindestens einer davon transportierte gar
keine echte Information mehr: der Rückgabewert von getShellRegions() wird
nirgends gelesen – allein die Existenz der Methode war das Signal. Es gab
keine Möglichkeit zu fragen „unterstützt die Werkbank ein unteres Panel
überhaupt“, bevor man eines benutzt, und keine Stelle, an der ein Plugin eine
Berechtigung enger als „darf dieser Benutzer den Bildschirm überhaupt öffnen“
erklären konnte.
Nichts davon wird abgeschaltet. Ein Plugin, das eine der fünf alten
Methoden benutzt, funktioniert unverändert weiter – ein Adapter
(helper/legacyadapter.php) übersetzt sie automatisch in dieselbe
Beschreibungsform, die Contract v1 selbst benutzt.
Die drei Bauflächen
| Fläche | Bedeutung |
|---|---|
classic | reines do=admin (ohne mode=fluentui), oder eine gewöhnliche Wiki-Seite ohne <module>-Tag – keine Werkbank-Beteiligung |
contributed | Regelfall: wkfluentui baut die komplette Schale um den vom Bildschirm gelieferten Inhalt, allein aus dessen erklärten Beiträgen |
selfHosted | das Plugin ruft widgets→workbench() selbst auf, aus seinem eigenen html() heraus – erklärt durch eine bloße Ankündigung ohne kind |
Die sieben Bereiche
| Bereich | Erscheint in | Anmerkung |
|---|---|---|
activityBar | Modul-Wechselleiste | nur ein Abzeichen ist hier beitragbar – das Symbol selbst kommt automatisch aus der Aufzählung installierter Verwaltungs-Plugins |
sidebar | linke Ansichts-Spalte | wie im bisherigen Ansichts-Register benannt |
auxbar | rechte Ansichts-Spalte (oder zweites Dokument im geteilten Ansicht) | dito |
bottomPanel | unteres Panel | im bisherigen Register panel – hier umbenannt, weil das bloße Wort außerhalb seiner Definitionsdatei als „irgendein Panel“ gelesen wird |
statusBar | Statuszeile | ein kind: view-Beitrag nennt eine Tatsache darüber, wo der Leser ist – siehe unten |
commandPalette | Befehlsleiste (sichtbar) und Befehlspalette (durchsuchbar, Strg+Umschalt+P) | siehe unten |
adminModule | Modulverzeichnis für <module name=„…“> | v1-Entsprechung von getModuleInfo() |
Die Statuszeile nimmt Tatsachen, keine Auszeichnung
Jeder andere Bereich trägt vertrauenswürdiges HTML des Aufrufers; dieser trägt reinen Text und maskiert ihn selbst. Die Statuszeile hat eine Zeile, und ein Beitrag, der ein Element öffnen könnte, nähme den Rest davon.
| Feld | Bedeutung |
|---|---|
label | der Text |
href | wohin er führt, wenn er irgendwohin führt |
disabledReason | wird als Titel (Kurzhinweis beim Zeigen) gerendert |
badge.tone | warning oder error für die Einfärbung |
priority | wie wichtig die Angabe ist – siehe unten |
Gültigkeitsbereich wie bei einem Befehl: ein Beitrag, dessen Besitzer der gerade gezeigte Bildschirm ist, erscheint; einer, dessen Besitzer überhaupt keinen Verwaltungsbildschirm hat, gilt als allgemeingültig; einer, der zu einem anderen Bildschirm gehört, erscheint nicht. Es ist buchstäblich dieselbe Prüfung, nicht eine zweite mit gleichem Wortlaut.
Zwei Stufen des Überlebens, aus einer Zahl. Unter 1024 px fällt weg, was
keine Priorität trägt; unter 768 px zusätzlich alles unterhalb von
helper_plugin_wkfluentui_widgets::STATUS_PHONE_PRIORITY (80). Ein Beitrag
darf priority selbst nennen; der Wert wird auf 10–95 geklemmt, damit nichts
Beigetragenes den Rückweg aus der Werkbank überholt, und ein Beitrag ohne
Angabe bekommt 85.
priority ist nicht order. order sortiert innerhalb eines
Bereichs, priority entscheidet über das Überleben bei schmaler Breite. Wären
sie ein Feld, würde ein Umsortieren der Seitenleiste ändern, was ein Telefon in
der Statuszeile zeigt.
Eine Ansicht darf ihr ''html'' als Callable liefern
Die Deskriptor-Tabelle nennt html als string | callable; viewStack()
lässt eine Ansicht mit leerem Körper weg.
Der Unterschied ist nicht kosmetisch. Das Registrierungs-Ereignis feuert
einmal, und bei einem Verwaltungsbildschirm geschieht das, bevor der
Bildschirm gerendert hat. Eine Zeichenkette muss also zur Registrierungszeit
berechenbar sein; ein Callable wird zur Kompositionszeit aufgelöst, also
nachdem das eigene html() gelaufen ist. Genau dafür ist es da.
Ein werfendes Callable kostet diese eine Ansicht und wird protokolliert.
Fähigkeit: workbench.view.html.callable.
Ein Bildschirm darf seine Arbeitsobjekte als Reiter beitragen
Die Registratur der Reiterleiste führt eine geordnete Liste undurchsichtiger Zeichenketten je Arbeitsbereich; die Leiste benennt deshalb außer Modulen auch die Arbeitsobjekte eines Bildschirms – etwa beim Einstellungs-Editor, dessen Arbeitsobjekt ein Bereich ist, oder bei einer Abfrage-Werkbank, deren Arbeitsobjekt eine Abfrage ist. Das ist einmal im Wirt gebaut, weil die Alternative in beiden Fällen eine zweite Reiterleiste im Inhalt wäre.
| Regel | Warum |
|---|---|
Die Marke wird von der Schale zu <modul>:<objekt> erweitert | eine gespeicherte Marke sagt damit immer, wer sie zurückübersetzen kann |
| Die Reiter eines Bildschirms ersetzen dessen Modulreiter | ein Reiter für „der Konfigurationsmanager“ neben Reitern für die Bereiche, die er verwaltet, wäre eine zweite Reiterebene in den Kleidern der ersten |
| Nur Modulreiter bekommen Verschiebe-Bedienelemente | das Formular sendet die sichtbare Reihenfolge in die Modulliste; eine Objektmarke dort wäre beim nächsten Aufruf nicht auflösbar und nähme die umsortierten Modulreiter mit |
| Der Bildschirm schreibt seine eigene Anheftung | die Schale weiß absichtlich nicht, was die Marke benennt |
| Ein Reiter ohne Titel oder Adresse wird verworfen | er wäre nicht erreichbar, nicht als Lesezeichen zu setzen und von seinem Nachbarn nicht zu unterscheiden |
Fähigkeit: workbench.screen.tabs.v1.
Vier Haken für einen mitgelieferten Bildschirm
Ein Ersatzbildschirm wird von wkfluentui für ein mitgeliefertes
Plugin gezeichnet, und der Vertrag v1 erreicht ihn deshalb nicht:
nativeViewsFor($owner) vergleicht den Besitzer eines Beitrags mit dem
gerade gezeigten Bildschirm – der Besitzer wäre wkfluentui, der Bildschirm
config, und die beiden treffen sich nie. Unter dem Namen des
mitgelieferten Plugins zu registrieren hiesse, dieses Plugin gäbe vor, ein
anderes zu sein.
Ein solcher Bildschirm beantwortet deshalb vier optionale Methoden unmittelbar:
commands(), views(), statusItems(), tabs(). Alle vier laufen
durch eine abgesicherte Naht, ein Fehlschlag kostet also genau diese eine
Antwort und erreicht das Protokoll.
Die eigene Ansicht eines Bildschirms verdrängt die generische der Schale für
denselben Bereich. Ein Bildschirm, der seine eigene Navigation zeichnet, darf
nicht zusätzlich das generische Inhaltsverzeichnis danebengestellt bekommen; und
einer mit eigener Kontextspalte nicht zusätzlich plugin.info.txt. Dieselbe
Regel, die für ein selbst-hostendes Plugin schon gilt – und derselbe
Fehlermodus: nichts schlägt fehl, es erscheint einfach eine zweite Seitenleiste.
Berechtigungen
permission ist ein Callable (keine Argumente, liefert bool) oder
null. Zusätzlich zur ACL, nie an ihrer Stelle – der zugrundeliegende
Verwaltungsbildschirm bleibt unverändert durch DokuWikis eigene
isAccessibleByCurrentUser()-Prüfung geschützt. Ein permission-Wert,
der weder null noch aufrufbar ist, gilt als fehlerhafte Erklärung und
schließt aus – nicht als fehlende und lässt damit durch. Eine werfende Prüfung
gilt als Verweigerung, nicht als Absturz, und wird nicht als Fehler
protokolliert: „dieser Benutzer darf es nicht sehen“ ist der Mechanismus, der
funktioniert, kein Defekt.
Fähigkeits-Erkennung
helper_plugin_wkfluentui_capabilities::has($name) – ein Name, den ein
Plugin vor der Benutzung abfragt, statt eine Versionsnummer oder eine
Klasse zu prüfen. Der Grund: eine Fähigkeit kann später ausgeliefert werden
als die Version, die sie ankündigte.
Zwei weitere Namen:
| Fähigkeit | Bedeutung |
|---|---|
workbench.view.html.callable | das html einer Ansicht darf ein Callable sein und wird zur Kompositionszeit aufgelöst |
workbench.screen.tabs.v1 | ein Bildschirm darf seine eigenen Arbeitsobjekte in der einen Reiterleiste benennen |
Aus dem Registrierungs-Ereignis heraus antwortet has() nur mit dem
Kernwortschatz – und das ist die vollständige Wahrheit, kein Kompromiss. Wenn
der eigene Handler läuft, ist noch kein provides irgendeines anderen
Beitragenden eingesammelt. Eine Frage nach der Fähigkeit eines fremden
Pakets hat zu diesem Zeitpunkt keine Antwort und bekommt false.
all() markiert sich für die Dauer des Ereignisses, und list() antwortet
solange mit dem Kernwortschatz, ohne zu merken – eine Fähigkeitsabfrage aus dem
eigenen Handler löst das Ereignis also nicht erneut aus.