Sie befinden sich hier: start » de » Interne Dokumentation » DokuWiki-Erweiterungen (WvdS) » FluentUI (Design-System-Bibliothek) » FluentUI: Komponenten-Referenzen » FluentUI: Öffentliche Helper-API

FluentUI: Öffentliche Helper-API

1. Übersicht und Zweck

Status: Tier 1 — beschreibt tatsächlich umgesetzten Code, verifiziert gegen wkfluentui@1366902.

Diese Seite ist die Quelle der Wahrheit für die öffentliche PHP-API von wkfluentui: sechs eigenständige Helper-Klassen mit zusammen 36 öffentlichen Methoden, die framework-freie HTML-Bausteine (Baum, Tabs, Drawer/Modal, Formular-Raster, Datentabelle, Tree List, Eingabefelder-Familie, NavBar, Card, CountBadge, Listen-Filter, Editor-Tab-Strip, Command-Palette, Kontextmenü-Quelle, Code-Editor-Aktivierung, Toolbar, CSV-Export), Schema-Formular-Seiten (formpage) sowie ACL-geprüfte Datenermittlung (Admin-Leiste, Bildergalerie, Cross-Plugin-Navigation, Avatar-Initialen) bereitstellen. Zielgruppe: jedes DokuWiki-Plugin oder -Template, das diese Bausteine wiederverwenden will — die API ist bewusst nicht an premium-navy-ivory gebunden.

Die meisten Methoden haben zusätzlich eine eigene, vertiefte Komponentenseite mit Demo-Skizze und Feature-Unterseiten; diese Seite verweist dort hin, statt den Vertrag zu duplizieren (Zuordnung: Tabelle in Abschnitt 6). Nur drawer(), modal(), rowActions() sowie je eine Methode in adminrail/gallery/nav/user haben keine andere Seite — hier steht ihr vollständiger Vertrag.

2. Voraussetzungen

  • DokuWiki mit aktiviertem Plugin wkfluentui (lib/plugins/wkfluentui/).
  • PHP-Kontext eines laufenden DokuWiki-Requests (die Methoden nutzen globale DokuWiki-Funktionen wie hsc(), wl(), cleanID(), auth_quickaclcheck() — kein Aufruf außerhalb einer DokuWiki-Instanz möglich).
  • Für ACL-geprüfte Methoden (listImages(), getAdminRailItems()): ein bereits initialisierter Nutzer-/ACL-Kontext (Standard in jedem regulären DokuWiki-Request).

3. Konzepte

Sechs getrennte Helper-Klassen, kein gemeinsames helper.php. wkfluentui hat bewusst kein eigenes Wurzel-helper.phpplugin_load('helper', 'wkfluentui') liefert deshalb immer null, lautlos, ohne Fehler oder Warnung. Jede Komponente liegt unter helper/<component>.php und wird einzeln geladen (Details siehe Abschnitt 11, Troubleshooting, weiter unten auf dieser Seite) — dieser Namensfehler blieb in wk-dw-msqlite-plugin mehrere Features lang unbemerkt, weil DokuWiki selbst keine Warnung für einen unbekannten Helper-Namen ausgibt.

Escaping-Konvention (gilt für alle Methoden einheitlich): jede Methode escaped die ihr übergebenen Klartext-Werte (Label, Titel, Href) selbst über hsc() (schützt gegen CWE-79/XSS). Parameter, deren Name auf Html endet (controlHtml, bodyHtml, element), sind dagegen bereits vom Aufrufer erzeugtes, vertrauenswürdiges HTML — der Aufrufer trägt dort die Escaping-Verantwortung. Eine Ausnahme von der ersten Regel ist dokumentiert in Abschnitt „gallery" unten.

CSS-Gegenstück: die Sektion WIDGETS in wkfluentui/style.css (site-weit automatisch eingebunden über DokuWikis css_pluginstyles()).

4. Erste Schritte

Minimalbeispiel: Toolbar-Helfer laden und eine einzeilige Aktionsleiste rendern.

/** @var helper_plugin_wkfluentui_widgets $widgets */
$widgets = plugin_load('helper', 'wkfluentui_widgets');
 
echo $widgets->toolbar([
    ['label' => 'Neu', 'element' => '<button type="submit" name="do" value="new">Neu</button>'],
]);

Falsch: plugin_load('helper', 'wkfluentui') (ohne Suffix) — liefert null, jeder nachfolgende Methodenaufruf löst einen Fatal Error „Call to a member function … on null„ aus.

5. Verwendung

Helper Konsument Verwendete Methoden
adminrail lib/tpl/wkbizway/inc/wkbizway-render.php getAdminRailItems() 1)
gallery lib/tpl/wkbizway/inc/wkbizway-render.php listImages() 2)
nav lib/tpl/wkbizway/inc/nav.php getBlogCategoryNav(), getAcmenuFlyout() 3)
user lib/tpl/wkbizway/main.php, inc/wiki-shell.php avatarInitials() 4)
widgets lib/plugins/wksqliteds/dbadmin/*.php die neun Bestandsmethoden (Table Designer, Object Explorer, „Connect to…“-Dialog); die neu hinzugekommenen Methoden (Eingabefelder-Familie, treeList(), navBar() u. a.) warten auf ihren ersten Konsumenten

Weitere WvdS-Plugins sind eingeladen, dieselben Helper zu nutzen (siehe FluentUI (Design-System-Bibliothek), Abschnitt „Rolle„).

6. API-Referenz

Klasse Datei plugin_load()-Aufruf Methode(n) Vertrag
helper_plugin_wkfluentui_adminrail helper/adminrail.php plugin_load('helper', 'wkfluentui_adminrail') getAdminRailItems() unten, Abschnitt „adminrail"
helper_plugin_wkfluentui_gallery helper/gallery.php plugin_load('helper', 'wkfluentui_gallery') listImages() unten, Abschnitt „gallery"
helper_plugin_wkfluentui_nav helper/nav.php plugin_load('helper', 'wkfluentui_nav') getBlogCategoryNav(), getAcmenuFlyout() unten, Abschnitt „nav"
helper_plugin_wkfluentui_user helper/user.php plugin_load('helper', 'wkfluentui_user') avatarInitials() unten, Abschnitt „user"
helper_plugin_wkfluentui_formpage helper/formpage.php plugin_load('helper', 'wkfluentui_formpage') loadSchema(), validate(), serialize(), parse(), formFields() formpage → Schema-Formular-Seiten
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') tree() treeview → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') tabs() tabcontrol → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') drawer() unten, Abschnitt „drawer"
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') modal() unten, Abschnitt „modal"
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') propertyGrid() property-grid → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') dataGrid() datagrid → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') rowActions() unten, Abschnitt „rowActions"
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') codeEditor() editors → codeEditor()-Baustein
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') toolbar() toolbar → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') treeList() treelist → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') navBar() navbar → Grundlagen
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') button() form-fields → Button
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') calendar() form-fields → Calendar
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') checkbox() form-fields → Checkbox
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') comboBox() form-fields → ComboBox
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') dateTime() form-fields → DateTime
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') dropdown() form-fields → Dropdown Editor
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') listEditor() form-fields → List Editor
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') progressBar() form-fields → ProgressBar
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') exportRows() datagrid → Data Export
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') countBadge() widgets → Katalog (CountBadge)
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') card() widgets → Katalog (Card/Tile)
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') declarativeTable() widgets → Katalog (DeclarativeTable)
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') listFilter() widgets → Katalog (InputBox-Filter)
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') editorTabs() widgets → Katalog (Editor-Tab-Strip)
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') commandPalette() widgets → Katalog (Command-Palette)
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') workbench() unten, Abschnitt „workbench"
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') statusbar() unten, Abschnitt „statusbar"
helper_plugin_wkfluentui_widgets helper/widgets.php plugin_load('helper', 'wkfluentui_widgets') accordion() unten, Abschnitt „accordion"

adminrail

Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_adminrail
Datei lib/plugins/wkfluentui/helper/adminrail.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

getAdminRailItems(string $currentPage): array — liefert die ACL-gefilterte, in die drei festen Buckets admin/manager/other gruppierte und alphabetisch (Fallback: Menü-Sortierindex) sortierte Liste aller für den angemeldeten Nutzer sichtbaren Admin-Plugins, im selben Format wie DokuWikis eigene do=admin-Kachelansicht (\dokuwiki\Ui\Admin), aber flach statt gruppiert und um ein Inline-SVG-icon-Feld sowie ein active-Flag für $currentPage ergänzt.

Parameter Typ Erforderlich Beschreibung
$currentPage string Ja der page-Request-Parameter des aktuell angezeigten Admin-Screens ($INPUT->str('page')); leerer String auf dem nackten Admin-Index

Rückgabewert: Array von ['id' => string, 'label' => string, 'href' => string, 'icon' => string, 'active' => bool] je sichtbarem Admin-Plugin. Reihenfolge: Bucket adminmanagerother, innerhalb jedes Buckets alphabetisch nach Label. Leeres Array, wenn der Nutzer kein einziges Admin-Plugin sehen darf — kein Fehler.

Sicherheit: Die Bucket-Zugehörigkeit (welche Plugin-IDs zu admin/ manager zählen) ist ein wörtliches Duplikat der Liste in DokuWikis eigenem \dokuwiki\Ui\Admin — bewusst, damit dieselbe Installation in beiden Ansichten dieselbe Gruppierung zeigt; ein Core-Update, das diese Liste ändert, erfordert einen synchronen Abgleich hier. ACL-Prüfung über isAccessibleByCurrentUser() je Plugin (CWE-284/Broken Access Control) — der Aufrufer muss nicht zusätzlich filtern.

Nebenwirkungen: keine (reine Lese-/Enumerationsmethode).

Fehlerverhalten: wirft keine Exceptions. Ein Plugin, dessen Menü-Icon-Datei fehlt/zu groß/unlesbar ist, erhält icon' ⇒ ''`` — dieselbe stille Degradation wie in DokuWikis eigenem Ui\Admin::showMenuItem() (kein Platzhalter-Icon).

$rail = plugin_load('helper', 'wkfluentui_adminrail');
$items = $rail->getAdminRailItems($INPUT->str('page'));
foreach ($items as $item) {
    echo '<a href="' . $item['href'] . '"' . ($item['active'] ? ' class="active"' : '') . '>'
        . $item['icon'] . hsc($item['label']) . '</a>';
}
Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_gallery
Datei lib/plugins/wkfluentui/helper/gallery.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

listImages(string $ns, int $thumb = 200): array — liefert alle lesbaren Bilddateien direkt in $ns (nicht rekursiv, keine Unter-Namespaces).

Parameter Typ Erforderlich Standardwert Beschreibung
$ns string Ja Medien-Namespace; wird intern über cleanID() normalisiert
$thumb int Nein 200 Thumbnail-Breite in Pixeln, intern auf 32–1024 begrenzt

Rückgabewert: Array von ['id' => string, 'full' => string (ml()-URL), 'thumb' => string (ml()-URL), 'name' => string] je Bild. Leeres Array bei ungültigem/leerem $ns oder fehlendem Leserecht.

Sicherheit — abweichende Escaping-Regel (Ausnahme zur allgemeinen Konvention aus Abschnitt 3): $ns wird über cleanID() normalisiert (CWE-22, Path Traversal) und vor dem Dateisystemzugriff per auth_quickaclcheck("$ns:*") < AUTH_READ geprüft (CWE-284). Das name-Feld im Rückgabewert ist roh (noNS($id), nicht hsc()-escaped) — anders als bei jeder anderen Methode dieser API. Der Aufrufer muss name vor der Ausgabe selbst escapen; full/thumb sind bereits fertige, in sich sichere URLs (ml()).

Nebenwirkungen: ein Dateisystem-Scan (search() über $conf['mediadir'], Tiefe 1) je Aufruf — kein Cache.

Fehlerverhalten: wirft keine Exceptions; alle Fehlerfälle (ungültiger Namespace, fehlendes Leserecht, leerer Namespace) liefern ein leeres Array, nicht null und nicht false — ein Aufrufer kann immer direkt iterieren.

$gallery = plugin_load('helper', 'wkfluentui_gallery');
foreach ($gallery->listImages('de:blog:media', 300) as $img) {
    echo '<img src="' . $img['thumb'] . '" alt="' . hsc($img['name']) . '">';
}
Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_nav
Datei lib/plugins/wkfluentui/helper/nav.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

Zwei Methoden, beide null-tolerant: ist das jeweilige Ziel-Plugin deaktiviert/nicht installiert, liefern beide den leeren String statt eines Fehlers.

  • getBlogCategoryNav(string $rootNs): string — Blog-Kategorie-Flyout-Fragment für einen Blog-Root-Namespace (z. B. de:blog), delegiert an wkblog_tags::getCategoryTree().
  • getAcmenuFlyout(string $rootNs): string — Namespace-Baum-Flyout-Fragment für einen Wiki-Root-Namespace (z. B. de:wiki), delegiert an wkacmenu::renderNavFlyout().

Rückgabewert (beide): HTML-Fragment (eine <li>-Liste), leerer String wenn das jeweilige Ziel-Plugin fehlt oder keine Daten liefert.

Nebenwirkungen: beide Methoden cachen intern (DokuWikis \dokuwiki\Cache\Cache, 1800 Sekunden Lebensdauer, CACHE_AGE-Konstante) — je Namespace UND je Gruppenmitgliedschaft-Set des aktuell angemeldeten Nutzers (Sicherheitsgrund, s. u.), nicht global. getBlogCategoryNav() hängt seinen Cache-Eintrag zusätzlich an wkblog_tagss eigene Speicherdatei (cacheDependencyFile()), damit eine reine Tag-Änderung (die die Blogseite selbst nicht berührt) den Cache sofort invalidiert statt bis zu 1800 Sekunden veraltet zu bleiben. getAcmenuFlyout() hängt seinen Cache-Eintrag zusätzlich an DokuWikis Seitenindex (data/index/page.idx): der wächst, sobald eine neu angelegte Seite erstindiziert wird (Taskrunner beim nächsten Seitenaufruf) — neue Seiten erscheinen damit ohne 30-Minuten-Wartezeit im Flyout. Dokumentierte Grenze: Löschungen berühren page.idx nicht (die PID-Zeilen bleiben stabil), eine gelöschte Seite kann daher bis zum Ablauf der Altersgrenze im Flyout verbleiben.

Sicherheit: Der Cache-Schlüssel enthält bewusst die Gruppenmitgliedschaft des Nutzers (sortierte @Gruppe-Liste) — ohne diesen Bestandteil würde ein ACL-gefilterter Navigationsbaum, den ein privilegierter Nutzer zuerst aufruft, im Cache landen und danach fälschlicherweise auch einem nicht-privilegierten Nutzer ausgeliefert (Cache-basiertes ACL-Leck, CWE-284).

Fehlerverhalten: keine Exceptions; fehlendes Ziel-Plugin → leerer String (kein Log-Eintrag, kein Fehler).

$nav = plugin_load('helper', 'wkfluentui_nav');
echo $nav->getBlogCategoryNav('de:blog');
echo $nav->getAcmenuFlyout('de:wiki');

user

Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_user
Datei lib/plugins/wkfluentui/helper/user.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

avatarInitials(string $realName, string $login): string — liefert ein bis zwei Großbuchstaben-Initialen für einen Avatar-Platzhalter, wenn keine hochgeladene Avatar-Datei existiert (die Datei-Lookup-Logik selbst liegt bewusst nicht hier, s. Abgrenzung unten).

Parameter Typ Erforderlich Beschreibung
$realName string Ja (darf leer sein) Anzeigename des Nutzers
$login string Ja Login-Name, nur als Fallback genutzt

Algorithmus: erstes + letztes Wort von $realName bei 2+ Wörtern, erste zwei Zeichen von $realName bei genau einem Wort, erste zwei Zeichen von $login als Fallback wenn $realName leer ist. Multibyte- sicher (mb_substr/mb_strtoupper).

Rückgabewert: string, immer nicht-leer, sofern $login nicht ebenfalls leer ist.

Sicherheit: Die Methode escaped ihre Ausgabe nicht selbst (anders als die allgemeine Konvention aus Abschnitt 3, die nur für widgets.php gilt) — $realName stammt aus dem Nutzerprofil und kann theoretisch beliebige Zeichen enthalten. Der Aufrufer muss den Rückgabewert vor der Ausgabe selbst hsc()-escapen.

Abgrenzung: bewusst getrennt von der Avatar-Datei-Lookup-Logik in wvdsavatar/action.php::currentAvatarUrl() — kleine, stabile String-Logik bleibt hier dupliziert statt eine harte Cross-Plugin- Laufzeitabhängigkeit für wenige Zeilen einzuführen (dokumentierte, bewusste Entscheidung, kein Versehen).

$user = plugin_load('helper', 'wkfluentui_user');
$initials = $user->avatarInitials($INFO['userinfo']['name'] ?? '', $_SERVER['REMOTE_USER'] ?? '');
echo '<span class="avatar-placeholder">' . hsc($initials) . '</span>';

drawer

Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_widgets
Datei lib/plugins/wkfluentui/helper/widgets.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

drawer(string $title, string $bodyHtml, string $cancelHref): string — rechtsseitiges Slide-in-Panel: ein Vollflächen-Scrim (Klick-/Escape-Ziel = $cancelHref, ein normaler Link, funktioniert dadurch vollständig ohne JavaScript) plus ein Panel fester Breite. Generalisiert die zuvor in DbAdmin::renderNewTableDrawer()/renderAddColumnDrawer()/ renderEditDrawer() duplizierte Struktur.

Parameter Typ Beschreibung
$title string Drawer-Überschrift, hsc()-escaped
$bodyHtml string vertrauenswürdiges HTML (z. B. ein Formular) — Aufrufer-escaped
$cancelHref string Scrim-/Abbrechen-Ziel-URL, hsc()-escaped

Erzeugtes Markup: <div class="wk-drawer"><a class="wk-scrim" href="…"><div class="wk-drawer__panel" role="dialog" aria-modal="true"> mit <h3>-Titel und $bodyHtml.

Nebenwirkungen: keine (reine Render-Methode, kein State/Request-Zugriff).

Fehlerverhalten: keines — alle drei Parameter sind Pflicht-Strings, ein leerer String ist für jeden Parameter ein gültiger, wenn auch funktional sinnloser Wert (leerer Titel/Body/Scrim-Ziel).

echo $widgets->drawer(
    'Neue Tabelle',
    $widgets->propertyGrid($spaltenFelder),
    wl($ID, ['ns' => 'tabellen'])
);
Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_widgets
Datei lib/plugins/wkfluentui/helper/widgets.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

modal(string $title, string $bodyHtml, string $cancelHref, array $opts = []): string — zentriertes Dialogfenster, gleiches Scrim-Prinzip wie drawer(), mittig statt seitlich verankert.

Parameter Typ Erforderlich Beschreibung
$title string Ja Dialog-Überschrift, hsc()-escaped
$bodyHtml string Ja vertrauenswürdiges HTML — Aufrufer-escaped
$cancelHref string Ja Scrim-/Abbrechen-Ziel-URL, hsc()-escaped
$opts['size'] string Nein normal (Default, 640px) oder workbench (1024×768, resize:both, Viewport-Clamp, <1024px vollflächig)
$opts['context'] string Nein setzt data-wk-dialog-context; scripts/dialog.js merkt die zuletzt gewählte Größe je Kontext in localStorage unter wk-dialog-size:<context>

Rückwärtskompatibilität: die 3-Parameter-Aufrufform (ohne $opts) rendert byte-identisch zur Vorversion bis auf ein zusätzliches tabindex=“-1„ am Panel (programmatisches Fokusziel der Fokusfalle — ohne JavaScript wirkungslos, kein sichtbarer Unterschied).

Abgrenzung: das Laden eines fremden Admin-Moduls in einen Dialog läuft nicht über modal(), sondern über den a[data-wk-dialog-src]-Trigger-Link-Vertrag (der Link navigiert ohne JavaScript normal und wird nur progressiv zum Inline-Workbench-Dialog) — Details: admin-layout → „Fremd-Modul-Aufrufe als Inline-Dialog".

Nebenwirkungen: keine serverseitig; clientseitig (mit scripts/dialog.js): Fokusfalle, Escape-Handler, localStorage- Schreibzugriff bei workbench-Größe mit gesetztem context.

Fehlerverhalten: unbekannter $opts['size']-Wert degradiert still auf normal (kein Fehler, keine Warnung).

echo $widgets->modal(
    'Verbindung herstellen',
    $widgets->propertyGrid($verbindungsFelder),
    wl($ID),
    ['size' => 'workbench', 'context' => 'connect']
);

rowActions

Metadatum Wert
Sprache PHP
Namespace helper_plugin_wkfluentui_widgets
Datei lib/plugins/wkfluentui/helper/widgets.php
Sichtbarkeit public
Stabilität stabil (Tier 1)

rowActions(array $items): string — verpackt bereits vorhandene, sichtbare Aktions-Elemente einer Baum-/Grid-Zeile als versteckte <ul class="wk-row-actions" hidden> (Kontextmenü-Quelle für scripts/contextmenu.js, s. u.).

Parameter Typ Beschreibung
$items array Liste ['label' => string, 'element' => string]element ist das echte, bereits sichtbar gerenderte <a>-/<button>-HTML

Rückgabewert: HTML-String; leerer String bei leerem $items (keine Menü-Anzeige für eine Zeile ohne Aktionen — kein leeres, verwirrendes Kontextmenü).

Wichtige Invariante: rowActions() dupliziert keine Logik — jedes element muss identisch mit dem Element sein, das bereits sichtbar in der Zeile steht. Das Kontextmenü triggert bei Klick .click() auf das echte Original-Element, es öffnet keinen zweiten Code-Pfad.

Client-Gegenstück scripts/contextmenu.js (progressive Erweiterung): bei Rechtsklick auf ein Element mit data-wk-menu wird das native Kontextmenü unterdrückt und ein Popup aus dem benachbarten .wk-row-actions-Fragment gerendert. Ohne JavaScript bleibt jede Aktion über die sichtbaren Buttons erreichbar. Einzige Zusatzfunktion ohne No-JS-Äquivalent: „Copy“/„Copy with Headers„ über data-wk-copy/data-wk-copy-headers-Attribute (navigator.clipboard.writeText(…)).

Tastatur (WAI-ARIA-Menu-Muster): Die Einträge tragen role="menuitem"; beim Öffnen erhält der erste Eintrag den Fokus, Pfeil hoch/runter wandern zyklisch, Pos1/Ende springen zum ersten/letzten Eintrag, Escape schließt; beim Schließen kehrt der Fokus zum nächstliegenden fokussierbaren Element der Ursprungszeile zurück (dieselbe Mechanik wie die Menüs von scripts/admin-rail.js). Hinweis: derzeit rendert kein Konsument im lib/-Baum das data-wk-menu-Attribut — der Vertrag ist gegen das ausgelieferte Skript (scripts/contextmenu.js) verifiziert, der frühere Erstkonsument (SQL-Workbench-Ergebniszeilen) setzt es seit seiner Umstrukturierung nicht mehr.

Nebenwirkungen: keine serverseitig.

Fehlerverhalten: keines — ein element-Wert, der kein valides HTML ist, wird unverändert ausgegeben (der Aufrufer trägt die Verantwortung für valides, sicheres HTML in element, s. Escaping-Konvention Abschnitt 3).

$actions = $widgets->rowActions([
    ['label' => 'Bearbeiten', 'element' => '<a href="' . wl($ID, ['do' => 'edit']) . '">Bearbeiten</a>'],
    ['label' => 'Löschen', 'element' => '<button type="submit" name="do" value="delete">Löschen</button>'],
]);

workbench

workbench(array $regions, array $opts = []): string — komponiert die Shell-Regionen in das generische Workbench-Grid .wk-workbench (Layout-Schicht; die Region-Optik bleibt bei den .wk-shell-*-Primitives, die Innenleben bleiben Aufrufer-HTML).

  • $regions: Schlüssel commandbar · sidebar · content (Pflicht) · auxbar · rail · statusbar. Jeder Wert ist ein vertrauenswürdiges Aufrufer-HTML-Fragment (Aufrufer escapet — derselbe Vertrag wie drawer()/modal()). Fehlende/leere Regionen emittieren kein Element (die Grid-Variante lässt den Track kollabieren statt eine tote Lücke zu lassen). Trägt das äußerste Element des Fragments bereits die Region-Klasse, wird es unverändert durchgereicht (Attribute wie is-collapsed oder data-wk-auxbar-src bleiben erhalten); nackte Fragmente werden in das Standard-Element der Region gehüllt.
  • $opts['variant']: '''' (4-spaltig) · flat · no-sidebar · no-auxbar · auxbar-collapsed · split — muss einem CSS-Archetyp entsprechen; unbekannte Werte fallen auf das volle Grid zurück. split stellt Content und Auxbar als zwei gleich breite Hälften nebeneinander (minmax(0,1fr) minmax(0,1fr)): der Archetyp für eine zweite, eigenständige Arbeitsfläche neben der ersten — im Unterschied zu no-sidebar, dessen feste 280px-Spalte für „Eigenschaften der Auswahl“ gedacht ist und für eine Arbeitsfläche zu schmal. Unter 1024px stapeln die Hälften; die zweite bleibt sichtbar (sie ist offen, weil der Benutzer sie geöffnet hat — anders als die generische Auxbar, die dort ausgeblendet wird).
  • $opts['class']: zusätzliche Container-Klassen (Klartext, escaped) — der plugin-lokale Scope-Hook (z. B. wkq-shell).
  • $opts['context']: stabiler Flächen-Bezeichner (Klartext, escaped) → data-wk-workbench-context, der Persistenz-Schlüssel für Client-Präferenzen (Sash-Breiten). Ohne Kontext keine Persistenz.

Verhaltens-Schicht: scripts/workbench.js (Overlay/Scrim/Region-Toggles) und scripts/sash.js (Resize) docken über die Container-Klasse bzw. das Kontext-Attribut an — Regeln in FluentUI: Admin-Bereich (vertieft).

statusbar

statusbar(array $left, array $right = [], array $opts = []): string — Statusbar-Region mit Gruppen-/Item-Anatomie und Prioritäts-Vertrag.

  • Item-Form: ['text' => …] (Klartext, escaped) oder ['html' => …] (vertrauenswürdiges Aufrufer-HTML, gewinnt über text); optional 'priority' => int (bereits die Anwesenheit ist das Signal — Items ohne Priorität verschwinden unter 1024px) und 'title' => … (Klartext-Tooltip, escaped).
  • Beide Gruppen-Spans rendern immer (Flex-Anker auch bei leerer Seite); der Mitteltrenner zwischen Items ist dekoratives CSS, nie Textinhalt.
  • $opts['class']: zusätzliche Container-Klassen (Klartext, escaped).

Warnung: eine Statusbar, deren Items alle keine Priorität tragen, ist unter 1024px leer — die überlebenswichtigen Items immer markieren.

accordion

Seit 2026-07-17 (Design-System-Vereinheitlichung, WDX-WdxAccordion-inspiriert, s. widgets → Katalog (Accordion)).

accordion(array $items, array $opts = []): string — Progressive-Disclosure-Akkordeon aus nativen, exklusiven <details name="…">-Gruppen (Öffnen eines Abschnitts schließt die anderen derselben Gruppe automatisch) — kein JavaScript für die Kernfunktion nötig.

  • $items: je Eintrag ['summary' => string (Klartext, escaped), 'bodyHtml' => string (vertrauenswürdiges Aufrufer-HTML), 'id' => string (optional, HTML-''id'' des ''<details>''), 'open' => bool (optional, Standard-offener Abschnitt)].
  • $opts['context']: Exklusivitäts-Gruppenname, validiert gegen ^[a-z][a-z0-9-]*$ (ungültig/fehlend → default). Zwei accordion()-Aufrufe mit demselben Kontext auf derselben Seite bilden eine Exklusivitätsgruppe über beide Aufrufe hinweg (der Wert wandert 1:1 in <details name="wk-accordion-<context>">; HTML gruppiert per name unabhängig von der DOM-Position) — nützlich, wenn ein Aufrufer mehrere accordion()-Blöcke rendert, die trotzdem gemeinsam exklusiv bleiben sollen (Erstkonsument: wkfluentui/action/admintoc.php, ein Akkordeon-Block je getTOC()-Abschnitt, gemeinsamer Kontext admintoc).

Rückgabewert: string<div class="wk-accordion">…</div>. Leerer String bei leerem $items.

Kompatibilität: <details name>-Exklusivität landete in Chrome/Edge 120, Firefox 122, Safari 17.2 (~2023/24). Ältere Browser ignorieren die Gruppierung und lassen jeden Abschnitt unabhängig offen — identisch zu einer einfachen <details>-Liste ohne name, kein Funktionsverlust, nur ohne die Exklusivitäts-Politur.

$widgets = plugin_load('helper', 'wkfluentui_widgets');
echo $widgets->accordion([
    ['summary' => 'Sprache', 'bodyHtml' => $langFieldsetHtml, 'id' => 'lang', 'open' => true],
    ['summary' => 'Titel', 'bodyHtml' => $titleFieldsetHtml, 'id' => 'title'],
], ['context' => 'admintoc']);

JS-Verträge: wkToast, Sash, Dichte

  • wkToast(type, text, opts) (scripts/toast.js): typeinfo/success/warning/error (unbekannt → info); text ist Klartext und wird nie als HTML interpretiert; opts.timeout in ms (Default 6000; error ignoriert ihn und bleibt bis zum Schließen); Rückgabe ist eine Dismiss-Funktion. Nur für asynchrone JS-Rückmeldungen — msg() bleibt der Kanal für Vollseiten-POSTs.
  • Sash (scripts/sash.js): injiziert je vorhandener Sidebar/Auxbar eine role="separator"-Leiste; schreibt --wk-workbench-<region>-width inline auf den Container; Persistenz unter wk-workbench-size:<context>:<region> (re-geklemmt: Sidebar 180–480px, Auxbar 200–520px).
  • Dichte: body[data-wk-density="compact"] ist der einzige Schalter der Wirkschicht (Sektion DENSITY in style.css); wer den Umschalter stellt (Template-User-Menü) und wie persistiert wird (wk-density:<login>), gehört dem Template.

8. Vollständige Beispiele

Admin-Rail plus Avatar-Initialen in einer Template-Kopfzeile kombiniert (realistischer Ausschnitt, wie ihn ein Template nach Merge des Refactor-Branches einsetzen würde):

<?php
/** @var helper_plugin_wkfluentui_adminrail $rail */
$rail = plugin_load('helper', 'wkfluentui_adminrail');
/** @var helper_plugin_wkfluentui_user $userHelper */
$userHelper = plugin_load('helper', 'wkfluentui_user');
 
global $INFO, $INPUT;
?>
<nav class="wk-shell-rail">
<?php foreach ($rail->getAdminRailItems($INPUT->str('page')) as $item): ?>
    <a href="<?php echo $item['href']; ?>"<?php echo $item['active'] ? ' class="active"' : ''; ?>
       aria-current="<?php echo $item['active'] ? 'page' : 'false'; ?>">
        <?php echo $item['icon']; ?>
        <span class="a11y"><?php echo hsc($item['label']); ?></span>
    </a>
<?php endforeach; ?>
</nav>
<div class="wk-avatar-placeholder">
    <?php echo hsc($userHelper->avatarInitials($INFO['userinfo']['name'] ?? '', $INFO['userinfo']['login'] ?? '')); ?>
</div>

9. Einschränkungen und Randfälle

  • Kein Helper dieser API greift auf $_REQUEST/$_POST zu oder verändert Zustand — reine Render-/Enumerations-Methoden. Formular-Verarbeitung (POST-Handling, sectok-Prüfung) bleibt vollständig Sache des Aufrufers.
  • navs Cache-Lebensdauer (1800s) ist fest verdrahtet (CACHE_AGE-Konstante), nicht konfigurierbar über $opts — eine Änderung erfordert einen Code-Eingriff.
  • gallery::listImages() ist nicht rekursiv — Bilder in Unter-Namespaces von $ns werden nicht gefunden, das ist bewusst so (keine versehentliche Tiefenexplosion bei großen Medienbäumen).

10. Accessibility und Kompatibilität

  • PHP: kompatibel mit der PHP-Mindestversion von DokuWiki selbst (keine über den Core hinausgehenden Sprachfeature-Anforderungen in dieser API).
  • Browser/JavaScript: jede Methode dieser API liefert funktionsfähiges Markup ohne JavaScript (Grundsatz, s. Abschnitt 3/Konzepte); die zugehörigen scripts/*.js-Dateien sind ausnahmslos progressive Erweiterungen, nie Voraussetzung.
  • Barrierefreiheits-Details je Methode stehen in ihrem jeweiligen Abschnitt oben bzw. — für die Methoden mit eigener Komponentenseite (tree(), tabs(), propertyGrid(), dataGrid(), treeList(), toolbar(), navBar(), codeEditor() und die Eingabefelder-Familie) — auf deren dedizierten Seiten (Verweise: Abschnitt 6).

11. Troubleshooting

Symptom: Fatal error: Call to a member function toolbar() on null (oder jede andere Methode dieser API) direkt nach plugin_load('helper', 'wkfluentui').

Ursache: wkfluentui hat kein Wurzel-helper.php — der Aufruf ohne Komponenten-Suffix liefert null, lautlos, ohne eigenen Fehler (s. Abschnitt 3). Dieser Namensfehler blieb in wk-dw-msqlite-plugin längere Zeit unbemerkt, weil DokuWiki selbst keine Warnung dafür ausgibt.

Lösung: plugin_load('helper', 'wkfluentui_<component>') mit dem korrekten Suffix aufrufen — widgets, adminrail, gallery, nav, user oder formpage (Tabelle in Abschnitt 6).

12. Verwandte Themen


Verifiziert gegen: wkfluentui@274a7d9 (Branch feature/454-workbench-grid: workbench()/statusbar()/wkToast()/Sash/Dichte), wk-dw-sqliteds-plugin@24b83d2

1)
Template-Konsum erst ab Merge des offenen Refactor-Branches feature/707-komponenten-soc-helper-rewiring — der Template-master lädt aktuell noch keinen wkfluentui-Helper; Merge-Entscheidung liegt beim Nutzer.
2) , 3) , 4)
s. vorige Fußnote — erst ab Merge des Branches.
de/wiki/dwe/wkfluentui/component/api.txt · Zuletzt geändert: von 0.0.0.0