=== Dotance Settings History and Restore ===
Contributors: dotance
Tags: undo, rollback, settings, restore, history
Requires at least: 5.9
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.1.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Records every settings change: who, what, before and after. Undo in one click or roll back to a checkpoint. Works with any plugin or theme.

== Description ==

WordPress keeps revisions for posts and pages. It keeps nothing for settings. Save the wrong value on a plugin's options screen, or watch a colleague change something on Friday evening, and there is no history to go back to.

Dotance Settings History and Restore is that history. It records every real change to the options table made by a logged-in user – in WordPress itself, in any plugin, in any theme – and puts a timeline under **Tools → Settings Undo** with an Undo button on every entry.

**What you see for each change**

* Who made it, and when
* Which plugin, theme or WordPress core wrote it
* Which screen it came from – "Settings › Reading", a plugin's admin page, the Customizer, a REST route
* The value before and after: short values right on the row ("10 → 12"), arrays as a key-level diff that reaches into nested keys (added, removed and changed), collapsed to what moved
* A short note you can add to any change set, so the timeline says why

**Undo and roll back**

* Undo one option, or every option a single save touched, in one click
* **Checkpoints**: save a named marker ("Before the redesign") and later roll every setting back to how it was at that moment, after a preview of every option and its value
* **Roll back one person or one plugin**: put back everything a user changed, or everything a plugin or theme wrote, in the last hour, day, week or month
* **Update markers**: plugin, theme and core updates and activations show up on the timeline, so "what changed after that update?" has an answer and a Roll back button
* Every rollback shows a preview first, flags options that someone else changed afterwards, and is itself recorded, so it can be undone too
* Options that could lock you out – site URL, home URL, active plugins, theme, user roles – ask you to type the option name before they are restored

**Know when something critical changes**

* Optional email when site URL, home URL, admin email, search-engine visibility, open registration or the default role changes, with who changed it and from which plugin (off by default)
* A "noisy options" hint shows options a plugin rewrites over and over, with one click to ignore them
* An admin-bar menu shows the last few changes and an "Undo the last change set" shortcut

**Designed to be quiet**

A settings log is only useful if it is readable, so the plugin does not record everything. Transients, cron state, rewrite rules, update-check timestamps, cache keys and plugin version bumps are ignored. One settings form save that writes twelve options is one card in the timeline, not twelve. A plugin that changes a value and puts it straight back within the same request leaves no entry. Changes made by cron, WP-CLI or anonymous requests are off by default and can be switched on, and you can add your own option names (with `*` wildcards) to the ignore list on the Settings tab.

**Safe by default**

* Only administrators (`manage_options`) can view the timeline or undo anything
* Values under keys that look like passwords, tokens or API keys are masked in the display and in exports; the stored value is intact, so an undo still works
* Old rows are pruned daily by age and by row count, both configurable
* Deleting the plugin keeps the history unless you tick "delete data on uninstall"; a "Delete all history" button clears it on demand
* Nothing is sent anywhere. The plugin makes no external requests and loads no remote fonts or scripts; its two typefaces are bundled (SIL Open Font License)

**Export, WP-CLI and REST**

* Download the filtered history as CSV or JSON, for an audit or a support ticket
* WP-CLI: `wp settings-undo list|diff|undo|undo-group|checkpoint|checkpoints|rollback|export|prune|clear`
* A read-only REST route (`/wp-json/settings-undo/v1/changes`) and, on WordPress 6.9+, a read-only Ability for AI assistants. Neither can change a setting.

**For developers**

* `settings_undo_ignored_options` – filter an array of option names or `*` globs to ignore
* `settings_undo_max_value_size` – filter the byte cap above which a value is logged but not stored (default 512 KB)
* `settings_undo_alert_options` – filter the options that trigger the critical-change email
* `settings_undo_recorded` – action fired after a change is stored

Not in this version: multisite network options, and post content (WordPress revisions already cover that).

== Installation ==

1. Upload the `settings-undo` folder to `/wp-content/plugins/`, or install it from the Plugins screen.
2. Activate it. The history tables are created on activation.
3. Go to **Tools → Settings Undo**. Save any settings page and it will appear there.

== Frequently Asked Questions ==

= Does it slow the site down? =

No. Nothing runs on the front end for visitors, apart from the admin-bar menu for logged-in administrators, which you can switch off. Recording happens only when an option actually changes, and only after a cheap check that the option is not on the ignore list. Reading the timeline is a handful of queries per page.

= Why does a change I made not appear? =

Either the option is on the ignore list (transients, cron, caches, version numbers and similar noise), or the value was written by a background process – cron, WP-CLI or an anonymous request – which is not recorded unless you switch that on under Settings.

= How does a checkpoint work? =

It records a position in the history, not a copy of your database. Rolling back replays the earliest recorded value of every option changed since then, shows you the result first, and lets you untick anything you want to keep. It can only restore settings the plugin recorded, so a checkpoint is only as complete as the history behind it.

= Can I undo activating or deactivating a plugin? =

The `active_plugins` option is recorded and can be restored, with a typed confirmation. Note that restoring the list does not run a plugin's own activation or deactivation routines.

= Where is the data stored? =

In two tables, `{prefix}settings_undo_log` and `{prefix}settings_undo_marks` (checkpoints, update markers and notes). Uninstalling the plugin leaves them in place unless "delete data on uninstall" is enabled.

= Is the diff available for every change? =

Values larger than 512 KB (serialised) are logged as "too large to store": you can see that the option changed, who changed it and when, but not the values, and they cannot be undone. The cap can be raised with the `settings_undo_max_value_size` filter.

= Does it work on multisite? =

This version is built and tested for single sites. Network options are not recorded.

== Screenshots ==

1. The timeline: one card per save, with who, when, which plugin, and which screen. Checkpoints and update markers sit between them.
2. Inside a change set: every option the save touched, with Diff and Undo per row.
3. A key-level diff of an array option, collapsed to the keys that changed.
4. Undoing a protected option asks you to type its name.
5. Rolling back to a checkpoint: a preview of every option before anything changes.
6. Settings: retention, what is recorded, noisy options, critical-change alerts.

== Changelog ==

= 1.1.0 =
* New: checkpoints and rollback – save a named marker and roll all settings back to it, or roll back everything one person or one plugin changed, with a preview and per-option control.
* New: plugin, theme and core update markers on the timeline, with a Roll back button.
* New: notes on change sets.
* New: optional email alert when a critical option changes (site URL, home URL, admin email, search-engine visibility, open registration, default role).
* New: noisy-options hint with one-click ignore.
* New: CSV and JSON export, WP-CLI commands, read-only REST route and WordPress Ability.
* New: admin-bar menu with the last changes and "Undo the last change set".
* New: redesigned timeline and detail panel, a roomier diff view, and a redesigned Settings screen.
* Bundled Onest and JetBrains Mono fonts (SIL Open Font License); nothing is loaded from the internet.

= 1.0.2 =
* The history table is now recreated automatically if it goes missing while the plugin is active, for example after a migration or restore that skips custom tables.
* Readme: describes the ignore list, the Dashboard widget, Delete all history and the inline before/after values.

= 1.0.1 =
* New animated Settings Undo icon beside the page title.

= 1.0.0 =
* First release: records add, update and delete of any option by a logged-in user; groups a request's writes into one change set; timeline with source, user, date and option filters; key-level diffs; undo one entry or a whole change set; typed confirmation for protected options; masking of secret-looking keys; daily pruning by age and row count.

== Upgrade Notice ==

= 1.1.0 =
Adds checkpoints and rollback, update markers, critical-change alerts, export, WP-CLI and a redesigned screen. A second table is created automatically on upgrade.

= 1.0.2 =
Recreates the history table automatically if a migration or restore dropped it.

= 1.0.0 =
First release.
