# Feature: Data Removal ## Overview What deleting the plugin takes with it, and how the site owner says so. WordPress gives an uninstall no interface of its own: `uninstall.php` runs headless, after the plugin is already gone from the screen, with no opportunity to ask anything. So the answer is given in advance, on **Access → Plugin removal**, and read back at uninstall time. Two things are true at once, and the split below is how both are honoured: - **A studio's records are irreplaceable.** Lessons taught, payments taken, what families agreed to and when. A delete during a migration, or a delete-and-reinstall while troubleshooting, must not be the thing that loses them. So the data is **kept unless the owner explicitly says otherwise**. - **Credentials are not records.** A Stripe secret and webhook signing key can be re-pasted from the Stripe dashboard in under a minute. Live keys sitting in `wp_options` on a site that no longer has the code to use them are nothing but exposure. So those are **always** removed. ## Option `us_delete_data_on_uninstall` `'1'` or `'0'` (default `'0'`). Written only from the Access page. ## Always removed Whatever the setting says: | What | Why | |---|---| | `us_stripe_secret_key`, `us_stripe_webhook_secret`, `us_stripe_publishable_key`, `us_stripe_mode` | Credentials, not records — cheap to restore, dangerous to leave | | `us_schedular_latest_release` transient | Cached release metadata; meaningless without the plugin | | The `us_generate_due_payments` cron event | Deactivation clears it too, but a site whose plugin files simply vanished never ran that hook | | `users_can_register` / `default_role` | Restored from the snapshot open registration took (`us_registration_prev_*`). These are the *site's* settings, borrowed; leaving them behind would leave the site accepting public signups into a Student role that is about to stop existing. Only acts when a snapshot exists | ## Removed only on an explicit full purge - Every table in `Schema::TABLES` — all 14, dropped by name. - Every remaining `us_*` option, including the removal setting itself. - Every `us_*` user meta key, for all users (`delete_metadata( 'user', 0, $key, '', true )`) — billing overrides, child markers, birth years, pending-signup state. - The `us_studio_admin`, `us_instructor` and `us_student` roles. Roles go **only** on a full purge. A site keeping its data is keeping its students, and a student whose role was deleted out from under them holds no capabilities at all until the plugin is reinstalled. `Schema::TABLES` is the single list of tables the plugin owns; the `CREATE TABLE` statements in `Schema::tables()` spell their own names out, so a new table has to be added in both places or uninstalling will leave it behind. ## Admin Interface **Access → Plugin removal** (`manage_options` — the same capability as deleting a plugin, so the switch and the act it governs are in the same pair of hands): - A read-only note stating what is removed regardless. - **Erase everything when the plugin is deleted** — off by default. Turning it **on** takes the tick *and* the word `DELETE` typed into a confirmation box. It is the only place in the plugin where a stray click is unrecoverable, so the checkbox alone is not enough. A refused confirmation reports why and still saves everything else on the page — a mistyped word must not silently swallow a capability change made in the same submit. Turning it **off** needs nothing but unticking the box. Saving the page for some other reason while it is already on leaves it on, without asking for the word again. ## Implementation - `Unsupervised\Schedular\Uninstaller` — the option, and the whole of `run()` - `uninstall.php` — guards on `WP_UNINSTALL_PLUGIN`, loads the autoloader, calls `Uninstaller::run()` - `Unsupervised\Schedular\Schema::TABLES` — the table list - `Unsupervised\Schedular\Auth\AccessSettings` — the setting's UI and the typed confirmation - `templates/admin/access.php` ## Tests - `tests/Unit/UninstallerTest.php` - `tests/Unit/Auth/AccessSettingsTest.php` (the confirmation rules) ## Related - `payments.md` — the Stripe credentials this always forgets - `account-registration.md` — the core options open registration borrows