xref: /plugin/usersettings/README.md (revision f51fe07cd1ae2d1dfd14f525b27faf57a788b46f)
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/`
124- **Default:** The site's configured default language
125
126The language preference is applied as early as possible in the request
127lifecycle (during `ACTION_ACT_PREPROCESS`), so all rendering — template hooks,
128plugins, the wiki text itself — sees the user's chosen language immediately.
129
130Users can change it in the Preferences page. Admins can set it per-user in the
131User Settings admin table. The language list is scanned from the same source
132as DokuWiki's Configuration Manager.
133
134## Reading a preference
135
136Your plugin reads the effective value through the helper. `getPreference()`
137returns the user's stored value, or the registered default if they never set
138one:
139
140```php
141$prefs = plugin_load('helper', 'usersettings');
142$enabled = $prefs ? $prefs->getPreference('myfeature_enabled', null) : 1;
143// pass a username as the 2nd argument, or null for the current user
144```
145
146Always provide your own sensible fallback (`? ... : 1` above) in case the
147User Settings plugin is not installed.
148
149## Components
150
151| File | Role |
152| --- | --- |
153| `helper.php` | Storage, the registration event, the read/write API. |
154| `action.php` | The user-menu item, the `do=usersettings` settings page, and the built-in interface language toggle. |
155| `admin.php` | The admin overview table and per-user edit form. |
156| `MenuItem.php` | The user-menu item class. |
157
158## Install
159
160Drop the folder into `lib/plugins/usersettings/`, or use Admin → Extension
161Manager → Manual Install. There is nothing to configure.
162
163## Translations
164
165Included: English (`en`), German (`de`), Russian (`ru`), Japanese (`ja`).
166
167## Notes
168
169- The settings page and admin pages are plain HTML forms — no JavaScript — so
170  there are no old-browser concerns.
171- The **built-in interface language toggle** is registered automatically by
172  `action.php` and requires no configuration. It scans `inc/lang/` at
173  registration time to populate the option list, so all installed languages
174  are immediately available to users. The toggle applies the selected language
175  during `ACTION_ACT_PREPROCESS`, before any output is produced, ensuring
176  consistency throughout the request.
177- This is a new, locally-developed plugin with no upstream, so — unlike the
178  forked plugins on this wiki — it carries no update-suppression date.
179
180## License
181
182GPL 2, matching DokuWiki.
183