1# User Settings plugin for DokuWiki 2 3A self-contained, server-side store of per-user preference toggles, with a 4self-service settings page for every logged-in user and an admin overview of 5everyone's choices. 6 7It is **infrastructure for other plugins**: a feature plugin (or a template's 8companion plugin) registers its own toggle with a single event handler, and 9this plugin renders it, stores it, and exposes it — without ever needing to be 10edited itself. 11 12## Why this plugin exists 13 14DokuWiki core has no server-side per-user preference store. The auth backend 15holds only name, e-mail, password and groups, and DokuWiki's built-in 16interface preferences live in a browser **cookie** — so they do not follow a 17user from one browser or device to another. 18 19This plugin fills that gap. Preferences are stored on the server, keyed by 20user, so they apply wherever the person is logged in. 21 22## What a user sees 23 24A **"Preferences"** item appears in the user menu, just to the left of 25"Update Profile". It opens a settings page (`do=usersettings`) listing every 26registered toggle as a checkbox or a drop-down. The page is a plain HTML form — 27no JavaScript — so it works in any browser. 28 29## What an admin sees 30 31Admin → **User Settings** shows a flat, sortable table — one row per 32(user × setting): *Display name · Setting · Value · Changed by · Changed at*. 33A row shows the user's explicit choice, or the toggle's default (marked as 34such) when they never set one. A filter narrows the table to a single setting, 35so it stays readable however many toggles exist. 36 37Clicking a display name opens an edit form for that user. This is **Model A+**: 38an admin may change anyone's preferences, and the change is recorded under the 39admin's name — but it is *not* enforced. The user can always change it back. 40This is how you roll out a new feature as default-on while pre-setting it off 41for specific people (for example, keeping two conservative admins on the old 42theme). 43 44## Storage 45 46One JSON file per user, under `{metadir}/usersettings/`, holding 47`{key: {value, changed_at, changed_by}}`. JSON and pretty-printed, so the files 48are easy to inspect or back up. The page text and the wiki changelog are never 49touched. `changed_by` records whoever made the change — the user, or an admin 50acting on their behalf — which is what the overview's "Changed by" column 51shows. 52 53## Registering a toggle from another plugin 54 55This is the integration point. Your plugin hooks the 56`PLUGIN_USERSETTINGS_REGISTER` event and appends one or more toggle 57definitions: 58 59```php 60class action_plugin_myfeature extends DokuWiki_Action_Plugin 61{ 62 public function register(Doku_Event_Handler $controller) 63 { 64 $controller->register_hook( 65 'PLUGIN_USERSETTINGS_REGISTER', 'BEFORE', $this, 'registerToggles' 66 ); 67 } 68 69 public function registerToggles(Doku_Event $event) 70 { 71 // a simple on/off toggle 72 $event->data[] = [ 73 'key' => 'myfeature_enabled', 74 'label' => 'Enable my feature', 75 'type' => 'checkbox', 76 'default' => 1, 77 'desc' => 'Show my feature on wiki pages.', 78 'plugin' => 'myfeature', 79 ]; 80 81 // a choice from a fixed list 82 $event->data[] = [ 83 'key' => 'myfeature_mode', 84 'label' => 'My feature mode', 85 'type' => 'select', 86 'options' => ['compact' => 'Compact', 'full' => 'Full view'], 87 'default' => 'full', 88 'plugin' => 'myfeature', 89 ]; 90 } 91} 92``` 93 94### Toggle definition fields 95 96| Field | Required | Notes | 97| --- | --- | --- | 98| `key` | yes | Unique identifier; `A-Z a-z 0-9 _` only. Also the storage key and HTML field name. Prefix it with your plugin name to avoid collisions. | 99| `label` | yes | Shown on the settings page and in the admin table. | 100| `type` | — | `checkbox` (default) or `select`. | 101| `default` | — | Default value. Checkbox: `0`/`1`. Select: one of the option keys. | 102| `options` | for `select` | A `value => label` map. Required and non-empty for selects. | 103| `desc` | — | Optional help text shown under the toggle. | 104| `plugin` | — | Optional identifier of the registering plugin/template. | 105 106Invalid definitions (missing key, illegal key characters, a select with no 107options) are silently dropped. If two plugins register the same `key`, the 108first registration wins. 109 110A toggle definition is plain data, so a **template** can have a toggle too — 111ship a tiny companion action plugin that does nothing but register it. 112 113## Built-in toggles 114 115### Interface language 116 117This plugin ships with a built-in **Interface language** toggle that allows 118each logged-in user to select their preferred language for DokuWiki's menus 119and messages, overriding the site-wide default (`$conf['lang']`). 120 121- **Key:** `lang` 122- **Type:** `select` 123- **Options:** All installed languages found in `inc/lang/`, displayed by their 124 native name (endonym) — e.g. *Deutsch*, *日本語*, *Français*. Unknown codes 125 fall back to the bare code. 126- **Default:** The site's configured default language 127 128The language preference is applied as early as possible in the request 129lifecycle (during `ACTION_ACT_PREPROCESS`), so all rendering — template hooks, 130plugins, the wiki text itself — sees the user's chosen language immediately. 131 132Users can change it in the Preferences page. Admins can set it per-user in the 133User Settings admin table. The language list is scanned from `inc/lang/` at 134registration time, which fires only once per request (when the settings page or 135admin table is actually visited), not on every page load. 136 137## Reading a preference 138 139Your plugin reads the effective value through the helper. `getPreference()` 140returns the user's stored value, or the registered default if they never set 141one: 142 143```php 144$prefs = plugin_load('helper', 'usersettings'); 145$enabled = $prefs ? $prefs->getPreference('myfeature_enabled', null) : 1; 146// pass a username as the 2nd argument, or null for the current user 147``` 148 149Always provide your own sensible fallback (`? ... : 1` above) in case the 150User Settings plugin is not installed. 151 152## Components 153 154| File | Role | 155| --- | --- | 156| `helper.php` | Storage, the registration event, the read/write API. | 157| `action.php` | The user-menu item, the `do=usersettings` settings page, and the built-in interface language toggle. | 158| `admin.php` | The admin overview table and per-user edit form. | 159| `MenuItem.php` | The user-menu item class. | 160 161## Install 162 163Drop the folder into `lib/plugins/usersettings/`, or use Admin → Extension 164Manager → Manual Install. There is nothing to configure. 165 166## Translations 167 168Included: English (`en`), German (`de`), Russian (`ru`), Japanese (`ja`). 169 170## Notes 171 172- The settings page and admin pages are plain HTML forms — no JavaScript — so 173 there are no old-browser concerns. 174- The **built-in interface language toggle** is registered automatically by 175 `action.php` and requires no configuration. It scans `inc/lang/` at 176 registration time to populate the option list, so all installed languages 177 are immediately available to users. The toggle applies the selected language 178 during `ACTION_ACT_PREPROCESS`, before any output is produced, ensuring 179 consistency throughout the request. 180- This is a new, locally-developed plugin with no upstream, so — unlike the 181 forked plugins on this wiki — it carries no update-suppression date. 182 183## License 184 185GPL 2, matching DokuWiki. 186