xref: /plugin/usersettings/README.md (revision f51fe07cd1ae2d1dfd14f525b27faf57a788b46f)
11ab40613Stracker-user# User Settings plugin for DokuWiki
21ab40613Stracker-user
31ab40613Stracker-userA self-contained, server-side store of per-user preference toggles, with a
41ab40613Stracker-userself-service settings page for every logged-in user and an admin overview of
51ab40613Stracker-usereveryone's choices.
61ab40613Stracker-user
71ab40613Stracker-userIt is **infrastructure for other plugins**: a feature plugin (or a template's
81ab40613Stracker-usercompanion plugin) registers its own toggle with a single event handler, and
91ab40613Stracker-userthis plugin renders it, stores it, and exposes it — without ever needing to be
101ab40613Stracker-useredited itself.
111ab40613Stracker-user
121ab40613Stracker-user## Why this plugin exists
131ab40613Stracker-user
141ab40613Stracker-userDokuWiki core has no server-side per-user preference store. The auth backend
151ab40613Stracker-userholds only name, e-mail, password and groups, and DokuWiki's built-in
161ab40613Stracker-userinterface preferences live in a browser **cookie** — so they do not follow a
171ab40613Stracker-useruser from one browser or device to another.
181ab40613Stracker-user
191ab40613Stracker-userThis plugin fills that gap. Preferences are stored on the server, keyed by
201ab40613Stracker-useruser, so they apply wherever the person is logged in.
211ab40613Stracker-user
221ab40613Stracker-user## What a user sees
231ab40613Stracker-user
241ab40613Stracker-userA **"Preferences"** item appears in the user menu, just to the left of
251ab40613Stracker-user"Update Profile". It opens a settings page (`do=usersettings`) listing every
261ab40613Stracker-userregistered toggle as a checkbox or a drop-down. The page is a plain HTML form —
271ab40613Stracker-userno JavaScript — so it works in any browser.
281ab40613Stracker-user
291ab40613Stracker-user## What an admin sees
301ab40613Stracker-user
311ab40613Stracker-userAdmin → **User Settings** shows a flat, sortable table — one row per
321ab40613Stracker-user(user × setting): *Display name · Setting · Value · Changed by · Changed at*.
331ab40613Stracker-userA row shows the user's explicit choice, or the toggle's default (marked as
341ab40613Stracker-usersuch) when they never set one. A filter narrows the table to a single setting,
351ab40613Stracker-userso it stays readable however many toggles exist.
361ab40613Stracker-user
371ab40613Stracker-userClicking a display name opens an edit form for that user. This is **Model A+**:
381ab40613Stracker-useran admin may change anyone's preferences, and the change is recorded under the
391ab40613Stracker-useradmin's name — but it is *not* enforced. The user can always change it back.
401ab40613Stracker-userThis is how you roll out a new feature as default-on while pre-setting it off
411ab40613Stracker-userfor specific people (for example, keeping two conservative admins on the old
421ab40613Stracker-usertheme).
431ab40613Stracker-user
441ab40613Stracker-user## Storage
451ab40613Stracker-user
461ab40613Stracker-userOne JSON file per user, under `{metadir}/usersettings/`, holding
471ab40613Stracker-user`{key: {value, changed_at, changed_by}}`. JSON and pretty-printed, so the files
481ab40613Stracker-userare easy to inspect or back up. The page text and the wiki changelog are never
491ab40613Stracker-usertouched. `changed_by` records whoever made the change — the user, or an admin
501ab40613Stracker-useracting on their behalf — which is what the overview's "Changed by" column
511ab40613Stracker-usershows.
521ab40613Stracker-user
531ab40613Stracker-user## Registering a toggle from another plugin
541ab40613Stracker-user
551ab40613Stracker-userThis is the integration point. Your plugin hooks the
561ab40613Stracker-user`PLUGIN_USERSETTINGS_REGISTER` event and appends one or more toggle
571ab40613Stracker-userdefinitions:
581ab40613Stracker-user
591ab40613Stracker-user```php
601ab40613Stracker-userclass action_plugin_myfeature extends DokuWiki_Action_Plugin
611ab40613Stracker-user{
621ab40613Stracker-user    public function register(Doku_Event_Handler $controller)
631ab40613Stracker-user    {
641ab40613Stracker-user        $controller->register_hook(
651ab40613Stracker-user            'PLUGIN_USERSETTINGS_REGISTER', 'BEFORE', $this, 'registerToggles'
661ab40613Stracker-user        );
671ab40613Stracker-user    }
681ab40613Stracker-user
691ab40613Stracker-user    public function registerToggles(Doku_Event $event)
701ab40613Stracker-user    {
711ab40613Stracker-user        // a simple on/off toggle
721ab40613Stracker-user        $event->data[] = [
731ab40613Stracker-user            'key'     => 'myfeature_enabled',
741ab40613Stracker-user            'label'   => 'Enable my feature',
751ab40613Stracker-user            'type'    => 'checkbox',
761ab40613Stracker-user            'default' => 1,
771ab40613Stracker-user            'desc'    => 'Show my feature on wiki pages.',
781ab40613Stracker-user            'plugin'  => 'myfeature',
791ab40613Stracker-user        ];
801ab40613Stracker-user
811ab40613Stracker-user        // a choice from a fixed list
821ab40613Stracker-user        $event->data[] = [
831ab40613Stracker-user            'key'     => 'myfeature_mode',
841ab40613Stracker-user            'label'   => 'My feature mode',
851ab40613Stracker-user            'type'    => 'select',
861ab40613Stracker-user            'options' => ['compact' => 'Compact', 'full' => 'Full view'],
871ab40613Stracker-user            'default' => 'full',
881ab40613Stracker-user            'plugin'  => 'myfeature',
891ab40613Stracker-user        ];
901ab40613Stracker-user    }
911ab40613Stracker-user}
921ab40613Stracker-user```
931ab40613Stracker-user
941ab40613Stracker-user### Toggle definition fields
951ab40613Stracker-user
961ab40613Stracker-user| Field | Required | Notes |
971ab40613Stracker-user| --- | --- | --- |
981ab40613Stracker-user| `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. |
991ab40613Stracker-user| `label` | yes | Shown on the settings page and in the admin table. |
1001ab40613Stracker-user| `type` | — | `checkbox` (default) or `select`. |
1011ab40613Stracker-user| `default` | — | Default value. Checkbox: `0`/`1`. Select: one of the option keys. |
1021ab40613Stracker-user| `options` | for `select` | A `value => label` map. Required and non-empty for selects. |
1031ab40613Stracker-user| `desc` | — | Optional help text shown under the toggle. |
1041ab40613Stracker-user| `plugin` | — | Optional identifier of the registering plugin/template. |
1051ab40613Stracker-user
1061ab40613Stracker-userInvalid definitions (missing key, illegal key characters, a select with no
1071ab40613Stracker-useroptions) are silently dropped. If two plugins register the same `key`, the
1081ab40613Stracker-userfirst registration wins.
1091ab40613Stracker-user
1101ab40613Stracker-userA toggle definition is plain data, so a **template** can have a toggle too —
1111ab40613Stracker-usership a tiny companion action plugin that does nothing but register it.
1121ab40613Stracker-user
113cc98f4d1Stracker-user## Built-in toggles
114cc98f4d1Stracker-user
115cc98f4d1Stracker-user### Interface language
116cc98f4d1Stracker-user
117cc98f4d1Stracker-userThis plugin ships with a built-in **Interface language** toggle that allows
118cc98f4d1Stracker-usereach logged-in user to select their preferred language for DokuWiki's menus
119cc98f4d1Stracker-userand messages, overriding the site-wide default (`$conf['lang']`).
120cc98f4d1Stracker-user
121cc98f4d1Stracker-user- **Key:** `lang`
122cc98f4d1Stracker-user- **Type:** `select`
123cc98f4d1Stracker-user- **Options:** All installed languages found in `inc/lang/`
124cc98f4d1Stracker-user- **Default:** The site's configured default language
125cc98f4d1Stracker-user
126cc98f4d1Stracker-userThe language preference is applied as early as possible in the request
127cc98f4d1Stracker-userlifecycle (during `ACTION_ACT_PREPROCESS`), so all rendering — template hooks,
128cc98f4d1Stracker-userplugins, the wiki text itself — sees the user's chosen language immediately.
129cc98f4d1Stracker-user
130cc98f4d1Stracker-userUsers can change it in the Preferences page. Admins can set it per-user in the
131cc98f4d1Stracker-userUser Settings admin table. The language list is scanned from the same source
132cc98f4d1Stracker-useras DokuWiki's Configuration Manager.
133cc98f4d1Stracker-user
1341ab40613Stracker-user## Reading a preference
1351ab40613Stracker-user
1361ab40613Stracker-userYour plugin reads the effective value through the helper. `getPreference()`
1371ab40613Stracker-userreturns the user's stored value, or the registered default if they never set
1381ab40613Stracker-userone:
1391ab40613Stracker-user
1401ab40613Stracker-user```php
1411ab40613Stracker-user$prefs = plugin_load('helper', 'usersettings');
1421ab40613Stracker-user$enabled = $prefs ? $prefs->getPreference('myfeature_enabled', null) : 1;
1431ab40613Stracker-user// pass a username as the 2nd argument, or null for the current user
1441ab40613Stracker-user```
1451ab40613Stracker-user
1461ab40613Stracker-userAlways provide your own sensible fallback (`? ... : 1` above) in case the
1471ab40613Stracker-userUser Settings plugin is not installed.
1481ab40613Stracker-user
1491ab40613Stracker-user## Components
1501ab40613Stracker-user
1511ab40613Stracker-user| File | Role |
1521ab40613Stracker-user| --- | --- |
1531ab40613Stracker-user| `helper.php` | Storage, the registration event, the read/write API. |
154cc98f4d1Stracker-user| `action.php` | The user-menu item, the `do=usersettings` settings page, and the built-in interface language toggle. |
1551ab40613Stracker-user| `admin.php` | The admin overview table and per-user edit form. |
1561ab40613Stracker-user| `MenuItem.php` | The user-menu item class. |
1571ab40613Stracker-user
1581ab40613Stracker-user## Install
1591ab40613Stracker-user
1601ab40613Stracker-userDrop the folder into `lib/plugins/usersettings/`, or use Admin → Extension
1611ab40613Stracker-userManager → Manual Install. There is nothing to configure.
1621ab40613Stracker-user
163*f51fe07cStracker-user## Translations
164*f51fe07cStracker-user
165*f51fe07cStracker-userIncluded: English (`en`), German (`de`), Russian (`ru`), Japanese (`ja`).
166*f51fe07cStracker-user
1671ab40613Stracker-user## Notes
1681ab40613Stracker-user
1691ab40613Stracker-user- The settings page and admin pages are plain HTML forms — no JavaScript — so
1701ab40613Stracker-user  there are no old-browser concerns.
171cc98f4d1Stracker-user- The **built-in interface language toggle** is registered automatically by
172cc98f4d1Stracker-user  `action.php` and requires no configuration. It scans `inc/lang/` at
173cc98f4d1Stracker-user  registration time to populate the option list, so all installed languages
174cc98f4d1Stracker-user  are immediately available to users. The toggle applies the selected language
175cc98f4d1Stracker-user  during `ACTION_ACT_PREPROCESS`, before any output is produced, ensuring
176cc98f4d1Stracker-user  consistency throughout the request.
1771ab40613Stracker-user- This is a new, locally-developed plugin with no upstream, so — unlike the
1781ab40613Stracker-user  forked plugins on this wiki — it carries no update-suppression date.
1791ab40613Stracker-user
1801ab40613Stracker-user## License
1811ab40613Stracker-user
1821ab40613Stracker-userGPL 2, matching DokuWiki.
183