FluentUI: javni API pomočnika
Nazaj: FluentUI (knjižnica oblikovalskega sistema)
Javni PHP-API knjižnice wkfluentui: šest razredov pomočnikov, katerih metode vrnejo gradnike HTML brez ogrodja – mreže, polja, predale, letve. Ta stran je vir resnice zanje.
1. Pregled in namen
Stanje: stopnja 1 – opisuje dejansko izvedeno kodo.
Ta stran je vir resnice za javni PHP API wkfluentui: šest
samostojnih razredov pomočnikov s skupno 77 javnimi metodami
(widgets 67, formpage 5, nav 2, adminrail/gallery/user
po 1), ki zagotavljajo gradnike HTML brez ogrodja (drevo, zavihki, predal/modalno
okno, mreža obrazca, podatkovna preglednica, tree list, družina vnosnih polj,
NavBar, kartica, števčna značka, filter seznama, vrstica zavihkov
urejevalnika, paleta ukazov, vir priročnega menija, aktivacija
urejevalnika kode, orodna vrstica, izvoz CSV), strani obrazcev na podlagi
sheme (formpage) ter pridobivanje podatkov s preverjanjem ACL
(skrbniška vrstica, galerija slik, navigacija med vtičniki, inicialke
avatarja). Ciljna skupina: vsak vtičnik ali predloga DokuWiki, ki želi
te gradnike uporabiti znova – API namenoma ni vezan na premium-navy-ivory.
Večina metod ima poleg tega lastno, poglobljeno stran komponente s
predstavitveno skico in podstranmi funkcij; ta stran se sklicuje tja
namesto podvajanja pogodbe (preslikava: tabela v odseku 6). Le
drawer(), modal(), rowActions() ter po ena metoda v
adminrail/gallery/nav/user nimajo druge strani –
tukaj je njihova popolna pogodba.
2. Predpogoji
- DokuWiki z omogočenim vtičnikom
wkfluentui(lib/plugins/wkfluentui/). - PHP kontekst tekočega zahtevka DokuWiki (metode uporabljajo globalne funkcije DokuWiki, kot so
hsc(),wl(),cleanID(),auth_quickaclcheck()– klic zunaj instance DokuWiki ni mogoč). - Za metode, preverjene z ACL (
listImages(),getAdminRailItems()): že inicializiran uporabniški/ACL kontekst (privzeto v vsakem rednem zahtevku DokuWiki).
3. Koncepti
Šest ločenih razredov pomočnika, brez skupnega helper.php.
wkfluentui namenoma nima lastnega korenskega helper.php –
plugin_load('helper', 'wkfluentui') zato vedno vrne null, tiho,
brez napake ali opozorila. Vsaka komponenta je pod
helper/<component>.php in se naloži posamično (podrobnosti v odseku
11, odpravljanje težav, nižje na tej strani) – ta napaka poimenovanja je
v wk-dw-msqlite-plugin ostala neopažena skozi več funkcij, ker
DokuWiki sam ne izda opozorila za neznano ime pomočnika.
Konvencija ubežanja (enotno velja za vse metode): vsaka metoda sama
ubeži vrednosti navadnega besedila, ki so ji posredovane (oznaka,
naslov, href), prek hsc() (ščiti pred CWE-79/XSS). Parametri, katerih
ime se konča na Html (controlHtml, bodyHtml, element), so
nasprotno HTML, ki ga je že ustvaril klicatelj in mu je mogoče
zaupati – klicatelj tam nosi odgovornost za ubežanje. Izjema od prvega
pravila je dokumentirana v odseku
»gallery« spodaj.
Ustreznica CSS: odsek WIDGETS v wkfluentui/style.css
(samodejno vključen za celotno spletno mesto prek css_pluginstyles()
DokuWiki).
4. Prvi koraki
Minimalni primer: naložite pomočnika orodne vrstice in izrišite enovrstično akcijsko vrstico.
/** @var helper_plugin_wkfluentui_widgets $widgets */ $widgets = plugin_load('helper', 'wkfluentui_widgets'); echo $widgets->toolbar([ ['label' => 'Novo', 'element' => '<button type="submit" name="do" value="new">Novo</button>'], ]);
Napačno: plugin_load('helper', 'wkfluentui') (brez pripone) –
vrne null, vsak naslednji klic metode sproži usodno napako »Call to a
member function … on null«.
5. Uporaba
| Pomočnik | Porabnik | Uporabljene metode |
|---|---|---|
adminrail | lib/tpl/wkbizway/inc/wkbizway-render.php | getAdminRailItems() |
gallery | lib/tpl/wkbizway/inc/wkbizway-render.php | listImages() 1) |
nav | lib/tpl/wkbizway/inc/nav.php | getBlogCategoryNav(), getAcmenuFlyout() 2) |
user | lib/tpl/wkbizway/main.php, inc/wiki-shell.php | avatarInitials() 3) |
widgets | lib/plugins/wksqliteds/dbadmin/*.php | devet uveljavljenih metod (Table Designer, Object Explorer, pogovorno okno »Connect to…«); na novo dodane metode (družina polj obrazca, treeList(), navBar() idr.) čakajo na svojega prvega porabnika |
Drugi vtičniki WvdS so vabljeni k uporabi istih pomočnikov (glej FluentUI (knjižnica oblikovalskega sistema), odsek »Vloga«).
6. Referenca API
| Razred | Datoteka | Klic plugin_load() | Metoda/e | Pogodba |
|---|---|---|---|---|
helper_plugin_wkfluentui_adminrail | helper/adminrail.php | plugin_load('helper', 'wkfluentui_adminrail') | getAdminRailItems() | spodaj, odsek »adminrail« |
helper_plugin_wkfluentui_gallery | helper/gallery.php | plugin_load('helper', 'wkfluentui_gallery') | listImages() | spodaj, odsek »gallery« |
helper_plugin_wkfluentui_nav | helper/nav.php | plugin_load('helper', 'wkfluentui_nav') | getBlogCategoryNav(), getAcmenuFlyout() | spodaj, odsek »nav« |
helper_plugin_wkfluentui_user | helper/user.php | plugin_load('helper', 'wkfluentui_user') | avatarInitials() | spodaj, odsek »user« |
helper_plugin_wkfluentui_formpage | helper/formpage.php | plugin_load('helper', 'wkfluentui_formpage') | loadSchema(), validate(), serialize(), parse(), formFields() | formpage → strani obrazcev, podprte s shemo |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | tree() | treeview → osnove |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | tabs() | tabcontrol → osnove |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | drawer() | spodaj, odsek »drawer« |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | modal() | spodaj, odsek »modal« |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | propertyGrid() | property-grid → osnove |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | dataGrid() | datagrid → osnove |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | rowActions() | spodaj, odsek »rowActions« |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | codeEditor() | editors → gradnik codeEditor() |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | toolbar() | toolbar → osnove |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | treeList() | treelist → osnove |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | navBar() | navbar → osnove |
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 (filter InputBox) |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | editorTabs() | widgets → katalog (vrstica zavihkov urejevalnika) |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | commandPalette() | widgets → katalog (paleta ukazov) |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | workbench() | spodaj, odsek »workbench« |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | statusbar() | spodaj, odsek »statusbar« |
helper_plugin_wkfluentui_widgets | helper/widgets.php | plugin_load('helper', 'wkfluentui_widgets') | accordion() | spodaj, odsek »accordion« |
helper_plugin_wkfluentui_coreform | helper/coreform.php | plugin_load('helper', 'wkfluentui_coreform') | render(), trigger(), formOpen(), elements(), formClose() | core-screens → obrazci jedra |
adminrail
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_adminrail |
| Datoteka | lib/plugins/wkfluentui/helper/adminrail.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
getAdminRailItems(string $currentPage): array – vrne z ACL
filtriran seznam skrbniških vtičnikov, vidnih prijavljenemu uporabniku,
razvrščen v enake tri fiksne skupine admin/manager/other in
abecedno urejen (nadomestilo: indeks razvrščanja menija), kot v lastnem
ploščičnem pogledu DokuWiki za do=admin (\dokuwiki\Ui\Admin),
vendar plosko namesto razvrščeno v skupine, in razširjen s poljem
icon za vgrajen SVG ter zastavico active za $currentPage.
| Parameter | Tip | Obvezno | Opis |
|---|---|---|---|
$currentPage | string | Da | parameter zahtevka page trenutno prikazanega skrbniškega zaslona ($INPUT->str('page')); prazen niz na golem skrbniškem indeksu |
Povratna vrednost: polje ['id' => string, 'label' => string, 'href' => string, 'icon' => string, 'active' => bool] na vidljivi skrbniški vtičnik. Vrstni red: skupina admin → manager → other, znotraj vsake skupine abecedno po oznaki. Prazno polje, če uporabnik ne sme videti nobenega skrbniškega vtičnika – ni napaka.
Varnost: pripadnost skupini (kateri ID-ji vtičnikov štejejo za
admin/manager) je dobesedna podvojitev seznama v lastnem
\dokuwiki\Ui\Admin DokuWiki – namenoma, tako da ista namestitev v
obeh pogledih prikaže enako razvrščanje; posodobitev jedra, ki spremeni
ta seznam, zahteva sinhrono uskladitev tukaj. Preverjanje ACL prek
isAccessibleByCurrentUser() po vtičniku (CWE-284/pokvarjen nadzor
dostopa) – klicatelju ni treba dodatno filtrirati.
Stranski učinki: brez (čista metoda branja/naštevanja).
Obnašanje ob napaki: ne vrže izjem. Vtičnik, čija datoteka ikone
menija manjka/je prevelika/neberljiva, dobi icon' ⇒ ''`` — enaka tiha
degradacija kot v lastnem Ui\Admin::showMenuItem() DokuWiki (brez
nadomestne ikone).
$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>'; }
gallery
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_gallery |
| Datoteka | lib/plugins/wkfluentui/helper/gallery.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
listImages(string $ns, int $thumb = 200): array – vrne vse
berljive slikovne datoteke neposredno v $ns (ni rekurzivno, brez
podimenskih prostorov).
| Parameter | Tip | Obvezno | Privzeto | Opis |
|---|---|---|---|---|
$ns | string | Da | – | medijski imenski prostor; interno normaliziran prek cleanID() |
$thumb | int | Ne | 200 | širina sličice v pikslih, interno omejena na 32–1024 |
Povratna vrednost: polje
['id' => string, 'full' => string (ml()-URL), 'thumb' => string (ml()-URL), 'name' => string]
na sliko. Prazno polje pri neveljavnem/praznem $ns ali manjkajoči pravici branja.
Varnost – odstopajoče pravilo ubežanja (izjema od splošne konvencije
iz odseka 3): $ns se normalizira prek cleanID() (CWE-22, Path
Traversal) in pred dostopom do datotečnega sistema preveri prek
auth_quickaclcheck("$ns:*") < AUTH_READ (CWE-284). Polje
name v povratni vrednosti je surovo (noNS($id), ni
ubežano z hsc()) – v nasprotju z vsako drugo metodo v tem API-ju.
Klicatelj mora sam ubežati name pred izpisom; full/thumb
sta že dokončana, sama po sebi varna URL-ja (ml()).
Stranski učinki: pregled datotečnega sistema (search() prek
$conf['mediadir'], globina 1) na klic – brez predpomnilnika.
Obnašanje ob napaki: ne vrže izjem; vsi primeri napak (neveljaven
imenski prostor, manjkajoča pravica branja, prazen imenski prostor)
vrnejo prazno polje, ne null in ne false – klicatelj lahko vedno
neposredno iterira.
$gallery = plugin_load('helper', 'wkfluentui_gallery'); foreach ($gallery->listImages('de:blog:media', 300) as $img) { echo '<img src="' . $img['thumb'] . '" alt="' . hsc($img['name']) . '">'; }
nav
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_nav |
| Datoteka | lib/plugins/wkfluentui/helper/nav.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
Dve metodi, obe strpni do null: če je ustrezen ciljni vtičnik onemogočen/ni nameščen, obe vrneta prazen niz namesto napake.
getBlogCategoryNav(string $rootNs): string– fragment preliva kategorij bloga za korenski imenski prostor bloga (npr.de:blog), prenese nalogo nawkblog_tags::getCategoryTree().getAcmenuFlyout(string $rootNs): string– fragment preliva drevesa imenskih prostorov za korenski imenski prostor wikija (npr.de:wiki), prenese nalogo nawkacmenu::renderNavFlyout().
Povratna vrednost (obe): fragment HTML (en seznam <li>),
prazen niz, če ustrezen ciljni vtičnik manjka ali ne vrne podatkov.
Stranski učinki: obe metodi interno predpomnita (predpomnilnik
DokuWiki \dokuwiki\Cache\Cache, življenjska doba 1800 sekund,
konstanta CACHE_AGE) – po imenskem prostoru IN po naboru
članstva v skupinah trenutno prijavljenega uporabnika (varnostni
razlog, glej spodaj), ne globalno. getBlogCategoryNav() dodatno
priklopi svoj vnos predpomnilnika na lastno shranjevalno datoteko
wkblog_tags (cacheDependencyFile()), tako da čista sprememba
oznake (ki ne dotakne same strani bloga) takoj izniči predpomnilnik,
namesto da bi ostala zastarela do 1800 sekund. getAcmenuFlyout()
dodatno priklopi svoj vnos predpomnilnika na indeks strani DokuWiki
(data/index/page.idx): ta zraste takoj, ko se na novo ustvarjena
stran prvič indeksira (izvajalec nalog ob naslednjem ogledu strani) –
nove strani se tako pojavijo v prelivu brez 30-minutnega čakanja.
Dokumentirana omejitev: izbrisi ne dotaknejo page.idx (vrstice
PID ostanejo stabilne), zato lahko izbrisana stran ostane v prelivu do
poteka starostne meje.
Varnost: ključ predpomnilnika namenoma vsebuje članstvo uporabnika v
skupinah (urejen seznam @skupina) – brez te sestavine bi se
ACL-filtrirano navigacijsko drevo, ki ga prvi zahteva privilegiran
uporabnik, znašlo v predpomnilniku in bi se nato pomotoma streglo tudi
neprivilegiranemu uporabniku (uhajanje ACL na osnovi predpomnilnika,
CWE-284).
Obnašanje ob napaki: brez izjem; manjkajoč ciljni vtičnik → prazen niz (brez vnosa v dnevnik, brez napake).
$nav = plugin_load('helper', 'wkfluentui_nav'); echo $nav->getBlogCategoryNav('de:blog'); echo $nav->getAcmenuFlyout('de:wiki');
user
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_user |
| Datoteka | lib/plugins/wkfluentui/helper/user.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
avatarInitials(string $realName, string $login): string – vrne
eno do dve veliki črki inicialk za nadomestni avatar, kadar ne obstaja
naložena datoteka avatarja (logika iskanja datoteke sama namenoma ni
tukaj, glej razmejitev spodaj).
| Parameter | Tip | Obvezno | Opis |
|---|---|---|---|
$realName | string | Da (sme biti prazen) | prikazano ime uporabnika |
$login | string | Da | prijavno ime, uporabljeno le kot nadomestilo |
Algoritem: prva + zadnja beseda $realName pri 2+ besedah, prva
dva znaka $realName pri natanko eni besedi, prva dva znaka
$login kot nadomestilo, kadar je $realName prazen. Varno za
večbajtne znake (mb_substr/mb_strtoupper).
Povratna vrednost: string, vedno neprazen, dokler tudi
$login ni prazen.
Varnost: metoda ne ubeži sama svojega izpisa (v nasprotju s
splošno konvencijo iz odseka 3, ki velja le za widgets.php) –
$realName izhaja iz uporabniškega profila in lahko teoretično
vsebuje poljubne znake. Klicatelj mora sam ubežati povratno vrednost
z hsc() pred izpisom.
Razmejitev: namenoma ločeno od logike iskanja datoteke avatarja
v wvdsavatar/action.php::currentAvatarUrl() – majhna, stabilna
logika niza ostaja tukaj podvojena, namesto da bi za nekaj vrstic
uvedli togo časovno odvisnost med vtičniki (dokumentirana, namerna
odločitev, ne spregled).
$user = plugin_load('helper', 'wkfluentui_user'); $initials = $user->avatarInitials($INFO['userinfo']['name'] ?? '', $_SERVER['REMOTE_USER'] ?? ''); echo '<span class="avatar-placeholder">' . hsc($initials) . '</span>';
drawer
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_widgets |
| Datoteka | lib/plugins/wkfluentui/helper/widgets.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
drawer(string $title, string $bodyHtml, string $cancelHref): string
– desni izmikajoči predal: celopovršinska zatemnitev (cilj klika/escape
= $cancelHref, navadna povezava, ki torej deluje povsem brez
JavaScripta) plus podokno fiksne širine. Posploši strukturo, prej
podvojeno v DbAdmin::renderNewTableDrawer()/
renderAddColumnDrawer()/renderEditDrawer().
| Parameter | Tip | Opis |
|---|---|---|
$title | string | naslov predala, ubežan z hsc() |
$bodyHtml | string | HTML, ki mu je mogoče zaupati (npr. obrazec) – ubežanje na strani klicatelja |
$cancelHref | string | ciljni URL zatemnitve/preklica, ubežan z hsc() |
Ustvarjene oznake: <div class="wk-drawer"> →
<a class="wk-scrim" href="…"> → <div class="wk-drawer__panel" role="dialog" aria-modal="true">
z naslovom <h3> in $bodyHtml.
Stranski učinki: brez (čista metoda izrisovanja, brez dostopa do stanja/zahtevka).
Obnašanje ob napaki: nobeno – vsi trije parametri so obvezni nizi, prazen niz je za vsak parameter veljavna, čeprav funkcionalno nesmiselna vrednost (prazen naslov/telo/cilj zatemnitve).
echo $widgets->drawer( 'Nova tabela', $widgets->propertyGrid($poljaStolpcev), wl($ID, ['ns' => 'tabele']) );
modal
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_widgets |
| Datoteka | lib/plugins/wkfluentui/helper/widgets.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
modal(string $title, string $bodyHtml, string $cancelHref, array $opts = []): string
– sredinsko pogovorno okno, isto načelo zatemnitve kot drawer(),
zasidrano v sredini namesto ob strani.
| Parameter | Tip | Obvezno | Opis |
|---|---|---|---|
$title | string | Da | naslov pogovornega okna, ubežan z hsc() |
$bodyHtml | string | Da | HTML, ki mu je mogoče zaupati – ubežanje na strani klicatelja |
$cancelHref | string | Da | ciljni URL zatemnitve/preklica, ubežan z hsc() |
$opts['size'] | string | Ne | normal (privzeto, 640px) ali workbench (1024×768, resize:both, omejeno na vidno polje, pod 1024px čez cel zaslon) |
$opts['context'] | string | Ne | nastavi data-wk-dialog-context; scripts/dialog.js si zapomni nazadnje izbrano velikost po kontekstu v localStorage pod wk-dialog-size:<context> |
Povratna združljivost: oblika klica s 3 parametri (brez $opts)
se izriše bajtno enako prejšnji različici, razen dodatnega
tabindex=„-1“ na podoknu (programski cilj fokusa pasti fokusa –
brez učinka brez JavaScripta, brez vidne razlike).
Razmejitev: nalaganje tujega skrbniškega modula v pogovorno okno
ne poteka prek modal(), temveč prek pogodbe sprožilne povezave
a[data-wk-dialog-src] (povezava brez JavaScripta navigira
normalno in postane le postopno vstavljeno pogovorno okno delovnega
prostora) – podrobnosti:
admin-layout →
»Klici med moduli kot vstavljeno pogovorno okno«.
Stranski učinki: brez na strani strežnika; na strani odjemalca (z
scripts/dialog.js): past fokusa, upravljalnik Escape, pisanje v
localStorage pri velikosti workbench z nastavljenim context.
Obnašanje ob napaki: neznana vrednost $opts['size'] tiho
degradira na normal (brez napake, brez opozorila).
echo $widgets->modal( 'Vzpostavi povezavo', $widgets->propertyGrid($poljaPovezave), wl($ID), ['size' => 'workbench', 'context' => 'connect'] );
rowActions
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_widgets |
| Datoteka | lib/plugins/wkfluentui/helper/widgets.php |
| Vidnost | public |
| Stabilnost | stabilno (stopnja 1) |
rowActions(array $items): string – ovije že obstoječe, vidne
elemente dejanj vrstice drevesa/mreže v skrit
<ul class="wk-row-actions" hidden> (vir kontekstnega menija za
scripts/contextmenu.js, glej spodaj).
| Parameter | Tip | Opis |
|---|---|---|
$items | array | seznam ['label' => string, 'element' => string] – element je pravi, že vidno izrisan HTML <a>/<button> |
Povratna vrednost: niz HTML; prazen niz pri praznem $items (brez
prikaza menija za vrstico brez dejanj – brez praznega, zmedenega
kontekstnega menija).
Pomembna invarianta: rowActions() ne podvoji nobene logike –
vsak element mora biti enak elementu, ki je v vrstici že viden.
Kontekstni meni ob kliku sproži .click() na pravem izvirnem
elementu, ne odpre drugega poteka kode.
Odjemalska ustreznica scripts/contextmenu.js (postopna
nadgradnja): ob desnem kliku na element z data-wk-menu se potlači
nativni kontekstni meni in izriše pojavno okno iz sosednjega fragmenta
.wk-row-actions. Brez JavaScripta ostane vsako dejanje dosegljivo
prek vidnih gumbov. Edina dodatna funkcija brez ustreznice brez JS:
»Copy«/»Copy with Headers« prek atributov
data-wk-copy/data-wk-copy-headers
(navigator.clipboard.writeText(…)).
Tipkovnica (vzorec WAI-ARIA-Menu): vnosi nosijo
role="menuitem"; ob odprtju prvi vnos dobi fokus, puščica
gor/dol krožita, Home/End skočita na prvi/zadnji vnos,
Escape zapre; ob zaprtju se fokus vrne na najbližji fokusirljiv
element izvirne vrstice (enak mehanizem kot meniji
scripts/admin-rail.js). Opomba: trenutno noben porabnik v drevesu
lib/ ne izriše atributa data-wk-menu – pogodba je preverjena
glede na dobavljeno skripto (scripts/contextmenu.js), prejšnji prvi
porabnik (vrstice rezultatov SQL Workbencha) ga od svoje prenove ne
nastavlja več.
Stranski učinki: brez na strani strežnika.
Obnašanje ob napaki: nobeno – vrednost element, ki ni veljaven
HTML, se izpiše nespremenjena (klicatelj nosi odgovornost za veljaven,
varen HTML v element, glej konvencijo ubežanja v odseku 3).
$actions = $widgets->rowActions([ ['label' => 'Uredi', 'element' => '<a href="' . wl($ID, ['do' => 'edit']) . '">Uredi</a>'], ['label' => 'Izbriši', 'element' => '<button type="submit" name="do" value="delete">Izbriši</button>'], ]);
workbench
workbench(array $regions, array $opts = []): string – sestavi regije lupine v generično mrežo delovne površine .wk-workbench (plast postavitve; videz regij ostane pri primitivih .wk-shell-*, notranjost ostane HTML klicatelja).
$regions: ključicommandbar·sidebar·content(obvezen) ·auxbar·rail·statusbar. Vsaka vrednost je zaupanja vreden fragment HTML klicatelja (ubežanje opravi klicatelj – ista pogodba kot pridrawer()/modal()). Manjkajoče ali prazne regije ne izrišejo nobenega elementa (različica mreže stezo skrči, namesto da bi pustila mrtvo vrzel). Če najbolj zunanji element fragmenta že nosi razred regije, se preda nespremenjen (atributi, kot stais-collapsedalidata-wk-auxbar-src, ostanejo); gole fragmente ovije v privzeti element regije.$opts['variant']: '''' (4 stolpci) ·flat·no-sidebar·no-auxbar·auxbar-collapsed·split– mora ustrezati arhetipu CSS; neznane vrednosti se vrnejo na polno mrežo.splitpostavi vsebino in auxbar kot dve enako široki polovici drugo ob drugo (minmax(0,1fr) minmax(0,1fr)): arhetip za drugo, samostojno delovno površino ob prvi – v nasprotju zno-sidebar, katerega stalni stolpec 280px je namenjen »lastnostim izbire« in je za delovno površino preozek. Pod 1024px se polovici zložita druga pod drugo; druga ostane vidna (odprta je, ker jo je odprl uporabnik – drugače kot generični auxbar, ki je tam skrit).$opts['class']: dodatni razredi vsebnika (navadno besedilo, ubežano) – kavelj za obseg, lasten vtičniku (npr.wkq-shell).$opts['context']: stalni identifikator površine (navadno besedilo, ubežano) →data-wk-workbench-context, ključ za trajno shranjevanje nastavitev odjemalca (širine razdelilnikov). Brez konteksta ni trajnega shranjevanja.$opts['auxbarOpen']:truepove, da auxbar drži tisto, po čemer je bralec pravkar vprašal – izbrano datoteko, odprt zapis. Pod 1280px gascripts/workbench.jsob nalaganju odpre kot prekrivno plast, ne da bi premaknil fokus; brez JavaScripta pod 1024px steče pod vsebino. Učinkuje le, če auxbar obstaja. Ne nadomeščajte zis-opens strežnika: past za tabulator vworkbench.jspreverja le ta razred in bi tipkovnico sicer zadržala v stolpcu tudi pri namizni širini.$opts['sidebarDocked']:trueohrani stransko vrstico kot stolpec do širine okna 600px, namesto da bi jo pod 1024px spremenil v prekrivno plast (s skriptom) ali jo pod 768px skril (brez njega). Za orodno okno, katerega naloga je najti mesto – pojavno okno medijev urejevalnika se odpre v velikosti 750×500, drevo imenskih prostorov za preklopnikom pa je izbiro mape spremenilo v dva koraka. Pod 600px ostane prekrivna plast kot povsod: stolpec bi tam vsebini pustil premalo prostora. Zapiše se le, če stranska vrstica obstaja.$opts['sidebarTitle']: ime stranske vrstice (navadno besedilo, ubežano). Regija dobi lastno glavo s tem imenom, ki ostane pripeta na vrhu in v kateri je tudi gumb za pomanjšanje;scripts/workbench.jsz njim pri ozkih širinah označi lebdeči preklopnik stranske vrstice. Brez imena ni glave, preklopnik pa ostane neoznačen simbol.
Vedenjska plast: scripts/workbench.js (prekrivna plast, zatemnitev, preklopniki regij) in scripts/sash.js (spreminjanje velikosti) se priklopita prek razreda vsebnika oziroma atributa konteksta – pravila v FluentUI: skrbniško območje podrobno.
statusbar
statusbar(array $left, array $right = [], array $opts = []): string – regija vrstice stanja z anatomijo skupin in elementov ter pogodbo prednosti.
- Oblika elementa:
['text' => …](navadno besedilo, ubežano) ali['html' => …](zaupanja vreden HTML klicatelja, ima prednost predtext); neobvezno'priority' => int(signal je že prisotnost – elementi brez prednosti pod 1024px izginejo) in'title' => …(namig v navadnem besedilu, ubežan). - Oba razpona skupin se izrišeta vedno (sidro flex tudi pri prazni strani); srednje ločilo med elementi je dekorativni CSS, nikoli vsebina besedila.
$opts['class']: dodatni razredi vsebnika (navadno besedilo, ubežano).
Opozorilo: vrstica stanja, katere elementi nimajo prednosti, je pod 1024px prazna – elemente, ki morajo ostati vidni, vedno označite.
accordion
Od 2026-07-17 (poenotenje sistema oblikovanja, po zgledu WDX-WdxAccordion,
glej widgets → katalog (Accordion)).
accordion(array $items, array $opts = []): string – harmonika za postopno razkrivanje
iz izvornih, izključujočih skupin <details name="…"> (odprtje enega odseka
samodejno zapre druge iz iste skupine) – za osnovno delovanje JavaScript ni potreben.
$items: vsak vnos['summary' => string (navadno besedilo, ubežano), 'bodyHtml' => string (zaupanja vreden HTML klicatelja), 'id' => string (neobvezno, HTML-''id'' elementa ''<details>''), 'open' => bool (neobvezno, privzeto odprt odsek)].$opts['context']: ime izključujoče skupine, preverjeno z^[a-z][a-z0-9-]*$(neveljavno/manjkajoče →default). Dva klicaaccordion()z istim kontekstom na isti strani tvorita eno izključujočo skupino čez oba klica (vrednost se 1:1 prenese v<details name="wk-accordion-<context>">; HTML združuje ponamene glede na položaj v DOM) – koristno, ko klicatelj izriše več blokovaccordion(), ki naj kljub temu ostanejo skupaj izključujoči (prvi porabnik:wkfluentui/action/admintoc.php, en blok harmonike na odsekgetTOC(), skupni kontekstadmintoc).
Povratna vrednost: string – <div class="wk-accordion">…</div>. Prazen niz pri praznem $items.
Združljivost: izključljivost <details name> je prišla v Chrome/Edge 120, Firefox 122,
Safari 17.2 (~2023/24). Starejši brskalniki združevanje prezrejo in vsak odsek pustijo
neodvisno odprt – enako kot preprost seznam <details> brez name, brez izgube
funkcije, le brez izključljivosti.
$widgets = plugin_load('helper', 'wkfluentui_widgets'); echo $widgets->accordion([ ['summary' => 'Jezik', 'bodyHtml' => $langFieldsetHtml, 'id' => 'lang', 'open' => true], ['summary' => 'Naslov', 'bodyHtml' => $titleFieldsetHtml, 'id' => 'title'], ], ['context' => 'admintoc']);
Pogodbe JS: wkToast, Sash, gostota
wkToast(type, text, opts)(scripts/toast.js):type∈info/success/warning/error(neznano →info);textje navadno besedilo in se nikoli ne tolmači kot HTML;opts.timeoutv ms (privzeto 6000;errorga prezre in ostane do zaprtja); vrne funkcijo za zaprtje. Samo za asinhrone odzive JS –msg()ostaja kanal za pošiljanje celotne strani (POST).- Sash (
scripts/sash.js): za vsako obstoječo stransko vrstico in auxbar vstavi vrsticorole="separator";--wk-workbench-<region>-widthzapiše neposredno na vsebnik; trajno shranjevanje podwk-workbench-size:<context>:<region>(ponovno omejeno: stranska vrstica 180–480px, auxbar 200–520px). - Gostota:
body[data-wk-density="compact"]je edino stikalo učinkovne plasti (odsek DENSITY vstyle.css); kdo nastavi preklopnik (uporabniški meni predloge) in kako se shrani (wk-density:<login>), pripada predlogi.
Skrbniški zaslon: listView in kar spada zraven
Od 20. 9. 2026 imajo vsi skrbniški zasloni enako razporeditev, komplet
gradnikov pa jo ponudi kot en klic. Pravilo, kateremu delu pripada
katero mesto, je zapisano v docs/how-to-admin-screen.md.
listView(array $opts)– razporeditev od zgoraj navzdol:noticeHtml(izid zadnjega dejanja),views/active/viewsLabel(stranski pogledi kot zavihki, v poimenovanem<nav>),commands/commandsLabel(ukazi seznama),filtersHtml(kar seznam zoži),bodyHtml(delovna vsebina, navadno mreža, ki zapolni prostor),drawersHtml(ustvarjanje, urejanje, ogled – zaprti, dokler jih ukaz ne odpre). Preostalo višino zavzame le telo; mreža v njem pomika vrstice pod glavo, ki ostane na mestu.prose($html, $opts)– blok tekočega besedila na delovni površini. Ohranja dolžino vrstice (68 znakov) ter odreže prvi in zadnji razmik. Prazno besedilo ne izriše ničesar. Namenjeno že izrisanemu HTML-ju, nikoli vrednostim iz zahteve HTTP.menuButton($label, array $elements, array $opts)– sorodni ukazi za enim gumbom; zprimarynastane deljeni gumb (običajno dejanje ob meniju njegovih različic).rowMenu(array $elements, array $opts)– meni s tremi pikami (kebab) za poljem z imenom vrstice. Vnosi so že pripravljeni kontrolniki klicatelja;labelpoimenuje vrstico za dostopno ime.
Obstoječi gradniki so dobili še te možnosti:
button(['badge' => '23', 'badgeLabel' => '…'])– število na gumbu, iz istegacountBadge()kot na zavihku.textBox/textArea(['mono' => true])– vsebina je strojno besedilo (vrstica dnevnika, pot, ključ).textArea(['fill' => true])– polje zavzame preostalo višino svoje površine, kot mreža, ki zapolni prostor.form(['inline' => true])– vodoraven obrazec: vrstica s filtri nad seznamom.dataGrid([... 'selectionName' => 'sel', 'selectionForm' => 'wkq-bf'])– pod katerim imenom se označene vrstice pošljejo in s katerim obrazcem. Za zaslone, katerih strežniška stran je starejša od mreže.
detailLayout
Pogled enega samega zapisa: glavni stolpec za tisto, kar se bere (opis, pogovor),
in stranski stolpec za tisto, kar se poišče (lastnosti kot propertyGrid()). To je
razporeditev, v kateri referenčne delovne površine prikazujejo delovni element.
$w->detailLayout([ 'main' => $opisInKomentarji, // zaupanja vreden HTML 'aside' => $w->propertyGrid($vrstice, ['mode' => 'display']), 'asideLabel' => 'Polja', // ime stranskega stolpca 'stackBelow' => 720, // privzeto ]);
- Zlaganje sledi širini vsebnika, ne okna. Tak pogled se pogosto prikaže v bralnem stolpcu wikija; poizvedba po oknu bi tam vsilila dva stolpca, kjer je prostora le za enega. Meri se kot pri
propertyGrid()prekdata-wk-stack-belowinscripts/adaptive.js. Brez skripta pod širino okna 768 px vedno velja en stolpec. - Stranski stolpec ima stalno širino iz
--wk-detail-aside-width(320 px), glavni stolpec vzame preostanek. - Stranski stolpec je poimenovan
<aside>in v dokumentu sledi glavnemu – bralni vrstni red je v obeh razporeditvah enak. - Brez stranskega stolpca nastane en sam stolpec namesto praznega, ki bi zasedel 320 px.
- Površina vzpostavi pisavo kompleta (
--wk-fs-body/--wk-lh-body).
Prvi uporabnik: pogled delovnega elementa (wkdoadowi). Izmerjeno v živo: 527 px + 320 px v bralnem stolpcu pri oknu 1400 px, en stolpec pri 390 px.
recordHeader
Glava zapisa: majhna oznaka (kaj je), pod njo naslov, na desni ukazi. To je razporeditev, s katero referenčne delovne površine odprejo posamezen zapis – delovni element v Azure DevOps, objekt v Azure Data Studiu.
$w->recordHeader([ 'kickerHtml' => $ikona . '<span>User Story 2228</span>', // zaupanja vreden HTML 'titleField' => $w->textBox([... , 'heading' => true, 'bare' => true, 'form' => 'moj-obrazec']), 'title' => 'Brez titleField: naslov kot golo besedilo', 'commandsHtml' => $w->toolbar($ukazi, ['variant' => 'bare']), 'metaHtml' => '<span>1602 najdenih</span>', 'sticky' => true, // privzeto 'stackBelow' => 560, // privzeto ]);
- Uporabnik s pravico urejanja ureja naslov kar na njegovem mestu.
titleFieldsprejme vnosno polje (textBoxz'heading' => true) in ga postavi tja, kjer je sicer naslov – en naslov, ne naslov in pod njim polje z istim besedilom. Polje je v<h1>, da navigacija po naslovih v bralniku zaslona zapis še vedno najde. - Polje je videti kot polje šele ob dotiku: velikost naslova (
--wk-fs-heading/--wk-lh-heading), brez okvira, okvir ob prehodu miške, fokusni obroč ob fokusu. - Glava se lepi na vrh (
position: sticky) v drsečem vsebniku, da ostanejo ukazi – predvsem Shrani – dosegljivi med delom v dolgem opisu.'sticky' => falseza zaslone, ki ne drsijo. - Zlaganje sledi širini vsebnika (
data-wk-stack-below,scripts/adaptive.js): ukazi gredo pod naslov. - Polje naslova in ukazi so pred obrazcem; njemu pripadajo prek atributa
form.
Prvi uporabnik: pogled delovnega elementa, njegov seznam in obrazec za nov element (wkdoadowi).
8. Popolni primeri
Rail za administracijo poleg inicialk avatarja, združenih v glavi predloge (realističen izsek, kakršnega bi predloga uporabila po združitvi veje za prenovo):
<?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. Omejitve in robni primeri
- Noben pomočnik v tem API-ju ne dostopa do
$_REQUEST/$_POSTniti ne spreminja stanja — čiste metode izrisovanja/naštevanja. Obdelava obrazcev (obravnava POST, preverjanjesectok) v celoti ostaja na klicatelju. - Življenjska doba predpomnilnika
nav(1800s) je trdo kodirana (konstantaCACHE_AGE), ni nastavljiva prek$opts— sprememba zahteva poseg v kodo. gallery::listImages()ni rekurzivna — slike v podimenskih prostorih$nsse ne najdejo, to je namerno (brez naključne eksplozije globine pri velikih medijskih drevesih).
10. Dostopnost in združljivost
- PHP: združljivo z najnižjo različico PHP samega DokuWiki (brez zahtev po jezikovnih funkcijah, ki presegajo jedro, v tem API-ju).
- Brskalnik/JavaScript: vsaka metoda tega API-ja proizvede delujoče oznake brez JavaScripta (načelo, glej odsek 3/koncepti); pripadajoče datoteke
scripts/*.jsso brez izjeme postopne nadgradnje, nikoli predpogoj. - Podrobnosti o dostopnosti po metodi so v pripadajočem odseku zgoraj oz. — za metode z lastno stranjo komponente (
tree(),tabs(),propertyGrid(),dataGrid(),treeList(),toolbar(),navBar(),codeEditor()in družino polj obrazca) — na njihovih namenskih straneh (napotki: odsek 6).
11. Odpravljanje težav
Simptom: Fatal error: Call to a member function toolbar() on null
(ali katera koli druga metoda tega API-ja) neposredno po plugin_load('helper',
'wkfluentui').
Vzrok: wkfluentui nima korenskega helper.php — klic brez
pripone komponente vrne null, tiho, brez lastne napake (glej odsek
3). Ta napaka poimenovanja je v wk-dw-msqlite-plugin dlje časa
ostala neopažena, ker DokuWiki sam za to ne izda opozorila.
Rešitev: pokličite plugin_load('helper', 'wkfluentui_<component>')
s pravilno pripono — widgets, adminrail, gallery, nav,
user ali formpage (tabela v odseku 6).
12. Sorodne teme
- FluentUI (knjižnica oblikovalskega sistema) — pregled knjižnice, razvrstitev vlog
- FluentUI: osnovni katalog gradnikov — katalog gradnikov s preslikavo izvora VS Code/ADS (vkl. uveljavljene gradnike CountBadge, Card/Tile, DeclarativeTable, SplitView, Tooltip)
- FluentUI: namizni DataGrid – predstavitveni pregled · FluentUI: Vertical Grid (Property Grid) – predstavitveni pregled · FluentUI: TreeView – predstavitveni pregled · FluentUI: Tree List – predstavitveni pregled · FluentUI: Tab Control – predstavitveni pregled · FluentUI: Toolbar – predstavitveni pregled · FluentUI: NavBar – predstavitveni pregled · FluentUI: polja obrazca – predstavitveni pregled · FluentUI: urejevalniki in prikaz kode — poglobljeni predstavitveni portali metod z lastno stranjo
- FluentUI: skrbniško območje podrobno — pogodbe o obnašanju za
scripts/dialog.js/scripts/auxbar.js/scripts/admin-rail.js