wp.org slug map: derived data, always removed. delete_option( 'babilim_plugin_slugs' ); // -- Babilim_Upload: an unfinished source upload. Its staging // directory is removed first (only a directory the packager // itself created is ever removed), then the option. $babilim_upload_pending = get_option( 'babilim_upload_pending', null ); if ( is_array( $babilim_upload_pending ) && is_string( $babilim_upload_pending['dir'] ?? null ) ) { try { require_once __DIR__ . '/includes/class-babilim-packager.php'; ( new Babilim_Packager() )->discard( $babilim_upload_pending['dir'] ); } catch ( \Throwable $babilim_upload_error ) { unset( $babilim_upload_error ); // Best effort: the daily sweep is gone with the plugin, nothing more to do. } } delete_option( 'babilim_upload_pending' ); delete_option( 'babilim_upload_done' ); delete_option( 'babilim_version' ); // -- Babilim_Manifest (cross-request write lock) -- short-TTL, but // still an option this plugin creates, so it is cleaned up the same // as everything else here rather than left to expire on its own. // It only ever lives in the main site's options table (see // Babilim_Manifest::lock_table()), which this runs against too. delete_option( 'babilim_manifest_lock' ); // -- Babilim_Consent / Babilim_Inventory / Babilim_Admin settings -- $babilim_keep_custom = (bool) get_option( 'babilim_keep_custom_on_purge', true ); delete_option( 'babilim_consent' ); delete_option( 'babilim_manual_locales' ); delete_option( 'babilim_disabled_locales' ); delete_option( 'babilim_keep_custom_on_purge' ); delete_option( 'babilim_toolbar_report' ); // Every user's dismissed verification notices (one unprefixed key holding a value per site). delete_metadata( 'user', 0, 'babilim_verification_dismissed', '', true ); delete_metadata( 'user', 0, 'babilim_error_notice_hidden', '', true ); delete_option( 'babilim_locale_names' ); delete_transient( 'babilim_meta_locales_cache' ); delete_transient( 'babilim_meta_locales_failed' ); // A restore code notice lives at most a minute (this clears the current user's). delete_transient( 'babilim_restore_code_notice_' . get_current_user_id() ); // -- Scheduled events ------------------------------------------------ wp_clear_scheduled_hook( 'babilim_sync' ); wp_clear_scheduled_hook( 'babilim_sync_once' ); wp_clear_scheduled_hook( 'babilim_maintenance' ); return $babilim_keep_custom; } } // OR'd across every site processed below: any one site asking to keep // custom/ makes the shared tree keep it -- see the file docblock above // for why, and why this must not depend on iteration order. $babilim_uninstall_keep_custom = false; if ( function_exists( 'is_multisite' ) && is_multisite() && function_exists( 'get_sites' ) ) { foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0 ) ) as $babilim_uninstall_site_id ) { switch_to_blog( (int) $babilim_uninstall_site_id ); $babilim_uninstall_keep_custom = babilim_uninstall_clean_current_site_state() || $babilim_uninstall_keep_custom; restore_current_blog(); } } else { $babilim_uninstall_keep_custom = babilim_uninstall_clean_current_site_state(); } // -- Babilim_Manifest (locally-recorded last write failure) -- one // network-wide option, like the shared `_manifest.json` it is about (see // Babilim_Manifest::WRITE_FAILURE_OPTION), so deleted once, not per site. // On a single site, delete_site_option() deletes the ordinary option. if ( function_exists( 'delete_site_option' ) ) { delete_site_option( 'babilim_manifest_write_failure' ); } // -- Everything below needs this plugin's own class files: the shared // WP_LANG_DIR/babilim/ language-file tree, purged exactly once, now that // every site's own setting has already been folded into // $babilim_uninstall_keep_custom above. Every option/transient/cron // deletion above has already happened by the time this runs, so nothing // here is allowed to -- or can -- undo it. // -- Installed language files themselves ---------------------------------- try { require_once __DIR__ . '/includes/class-babilim-paths.php'; require_once __DIR__ . '/includes/class-babilim-fs.php'; require_once __DIR__ . '/includes/class-babilim-wp-fs.php'; require_once __DIR__ . '/includes/class-babilim-manifest.php'; require_once __DIR__ . '/includes/class-babilim-result.php'; require_once __DIR__ . '/includes/class-babilim-installer.php'; $babilim_uninstall_fs = new Babilim_Wp_Fs(); $babilim_uninstall_manifest = new Babilim_Manifest( $babilim_uninstall_fs ); // The transform/parse/unzip callables are only ever used by // install() -- neither purge_all() nor remove_managed_tree() // touches them (see Babilim_Installer's own docblock). $babilim_uninstall_noop = static function () { return false; }; $babilim_uninstall_installer = new Babilim_Installer( $babilim_uninstall_fs, $babilim_uninstall_manifest, $babilim_uninstall_noop, $babilim_uninstall_noop, $babilim_uninstall_noop ); // Records first (a no-op error result if the manifest is unreadable), // then whatever else is left under the root, listed or not. $babilim_uninstall_installer->purge_all( $babilim_uninstall_keep_custom ); $babilim_uninstall_installer->remove_managed_tree( $babilim_uninstall_keep_custom ); } catch ( \Throwable $babilim_uninstall_error ) { // Best-effort -- see this section's own comment above. }