feature/707-komponenten-soc-helper-rewiring — master predloge trenutno še ne naloži nobenega pomočnika wkfluentui; odločitev o združitvi je na uporabniku.
Stanje: Tier 1 — opisuje dejansko uveljavljeno kodo, preverjeno glede na
wkfluentui@1366902.
Ta stran je vir resnice za javni PHP API wkfluentui: šest
samostojnih razredov pomočnika s skupno 36 javnimi metodami, ki
zagotavljajo gradnike HTML brez ogrodja (drevo, zavihki, predal/modalno
okno, mreža obrazca, podatkovna tabela, tree list, družina polj obrazca,
NavBar, kartica, štetna značka, filter seznama, vrstica zavihkov
urejevalnika, paleta ukazov, vir kontekstnega menija, aktivacija
urejevalnika kode, orodna vrstica, izvoz CSV), strani obrazcev, podprte s
shemo (formpage), ter iskanje podatkov,
preverjeno z ACL (rail za administracijo, galerija slik, navigacija med
vtičniki, inicialke avatarja). Ciljna publika: vsak vtičnik ali predloga
DokuWiki, ki želi ponovno uporabiti te gradnike — 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.
wkfluentui (lib/plugins/wkfluentui/).hsc(), wl(), cleanID(), auth_quickaclcheck() — klic zunaj instance DokuWiki ni mogoč).listImages(), getAdminRailItems()): že inicializiran uporabniški/ACL kontekst (privzeto v vsakem rednem zahtevku DokuWiki).
Š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).
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„.
| Pomočnik | Porabnik | Uporabljene metode |
|---|---|---|
adminrail | lib/tpl/premium-navy-ivory/inc/premiumnavyivory-render.php | getAdminRailItems() 1) |
gallery | lib/tpl/premium-navy-ivory/inc/premiumnavyivory-render.php | listImages() 2) |
nav | lib/tpl/premium-navy-ivory/inc/nav.php | getBlogCategoryNav(), getAcmenuFlyout() 3) |
user | lib/tpl/premium-navy-ivory/main.php, inc/wiki-shell.php | avatarInitials() 4) |
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„).
| 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) |
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_adminrail |
| Datoteka | lib/plugins/wkfluentui/helper/adminrail.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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>'; }
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_gallery |
| Datoteka | lib/plugins/wkfluentui/helper/gallery.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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']) . '">'; }
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_nav |
| Datoteka | lib/plugins/wkfluentui/helper/nav.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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 na wkblog_tags::getCategoryTree().getAcmenuFlyout(string $rootNs): string — fragment preliva drevesa imenskih prostorov za korenski imenski prostor wikija (npr. de:wiki), prenese nalogo na wkacmenu::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');
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_user |
| Datoteka | lib/plugins/wkfluentui/helper/user.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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>';
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_widgets |
| Datoteka | lib/plugins/wkfluentui/helper/widgets.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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']) );
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_widgets |
| Datoteka | lib/plugins/wkfluentui/helper/widgets.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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'] );
| Metapodatek | Vrednost |
|---|---|
| Jezik | PHP |
| Namespace | helper_plugin_wkfluentui_widgets |
| Datoteka | lib/plugins/wkfluentui/helper/widgets.php |
| Vidnost | public |
| Stabilnost | stabilno (Tier 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 že vidno stoji v vrstici.
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(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či commandbar · sidebar · content (obvezen) · auxbar · rail · statusbar. Vsaka vrednost je zaupanja vreden fragment HTML klicatelja (ubežanje opravi klicatelj — ista pogodba kot pri drawer()/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 sta is-collapsed ali data-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. split postavi 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 z no-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']: true pove, da auxbar drži tisto, po čemer je bralec pravkar vprašal — izbrano datoteko, odprt zapis. Pod 1280px ga scripts/workbench.js ob 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 z is-open s strežnika: past za tabulator v workbench.js preverja le ta razred in bi tipkovnico sicer zadržala v stolpcu tudi pri namizni širini.$opts['sidebarDocked']: true ohrani 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.js z 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(array $left, array $right = [], array $opts = []): string — regija vrstice stanja z anatomijo skupin in elementov ter pogodbo prednosti.
['text' => …] (navadno besedilo, ubežano) ali ['html' => …] (zaupanja vreden HTML klicatelja, ima prednost pred text); neobvezno 'priority' => int (signal je že prisotnost — elementi brez prednosti pod 1024px izginejo) in 'title' => … (namig v navadnem besedilu, ubežan).$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.
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 klica accordion() 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 po name ne glede na položaj v DOM) — koristno, ko klicatelj izriše več blokov accordion(), ki naj kljub temu ostanejo skupaj izključujoči (prvi porabnik: wkfluentui/action/admintoc.php, en blok harmonike na odsek getTOC(), skupni kontekst admintoc).
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']);
wkToast(type, text, opts) (scripts/toast.js): type ∈ info/success/warning/error (neznano → info); text je navadno besedilo in se nikoli ne tolmači kot HTML; opts.timeout v ms (privzeto 6000; error ga prezre in ostane do zaprtja); vrne funkcijo za zaprtje. Samo za asinhrone odzive JS — msg() ostaja kanal za pošiljanje celotne strani (POST).scripts/sash.js): za vsako obstoječo stransko vrstico in auxbar vstavi vrstico role="separator"; --wk-workbench-<region>-width zapiše neposredno na vsebnik; trajno shranjevanje pod wk-workbench-size:<context>:<region> (ponovno omejeno: stranska vrstica 180–480px, auxbar 200–520px).body[data-wk-density="compact"] je edino stikalo učinkovne plasti (odsek DENSITY v style.css); kdo nastavi preklopnik (uporabniški meni predloge) in kako se shrani (wk-density:<login>), pripada predlogi.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>
$_REQUEST/$_POST niti ne spreminja stanja — čiste metode izrisovanja/naštevanja. Obdelava obrazcev (obravnava POST, preverjanje sectok) v celoti ostaja na klicatelju.nav (1800s) je trdo kodirana (konstanta CACHE_AGE), ni nastavljiva prek $opts — sprememba zahteva poseg v kodo.gallery::listImages() ni rekurzivna — slike v podimenskih prostorih $ns se ne najdejo, to je namerno (brez naključne eksplozije globine pri velikih medijskih drevesih).scripts/*.js so brez izjeme postopne nadgradnje, nikoli predpogoj.tree(), tabs(), propertyGrid(), dataGrid(), treeList(), toolbar(), navBar(), codeEditor() in družino polj obrazca) — na njihovih namenskih straneh (napotki: odsek 6).
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).
scripts/dialog.js/scripts/auxbar.js/scripts/admin-rail.js
Preverjeno glede na: wkfluentui@1366902, wk-dw-msqlite-plugin@240c064