query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", $wpdb->esc_like( 'gemsecurity_quarantine_blob_' ) . '%' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery // Custom tables. Backup data (tables, archives, schedules) belongs to the // GemBackup plugin and is deliberately left alone — it may be the site's // only restore point, including any GemBackup has not imported yet. $tables = [ 'gemsecurity_logs', 'gemsecurity_bans', ]; foreach ( $tables as $table ) { $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $table ); // phpcs:ignore WordPress.DB } // User meta created by the plugin. $meta_keys = [ '_gemsecurity_login_time', '_gemsec_2fa_enabled', '_gemsec_2fa_method', '_gemsec_2fa_secret', '_gemsec_2fa_secret_pending', '_gemsec_2fa_backup_codes', '_gemsec_magic_hash', '_gemsec_magic_expires', '_gemsec_magic_sends', '_gemsec_ta', '_gemsec_ta_expires', '_gemsec_ta_revoked', '_gemsec_ta_ended', '_gemsec_ta_hash', '_gemsec_ta_link_expires', '_gemsec_ta_created', '_gemsec_ta_created_by', '_gemsec_ta_last_login', '_gemsec_ta_logins', '_gemsec_ta_history', '_gemsec_ta_role', '_gemsec_ta_prev_roles', '_gemsec_oauth_avatar', '_gemsec_oauth_registered_via', '_gemsec_geo_allowed_countries', '_gemsec_pw_set', '_gemsec_last_activity', ]; foreach ( $meta_keys as $key ) { $wpdb->delete( $wpdb->usermeta, [ 'meta_key' => $key ] ); // phpcs:ignore WordPress.DB } // OAuth provider id meta (one per provider). $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '\_gemsec\_oauth\_%\_id'" ); // phpcs:ignore WordPress.DB // Scheduled events. $hooks = [ 'gemsecurity_password_rotation', 'gemsecurity_prune_logs', 'gemsecurity_daily_scan', 'gemsecurity_weekly_digest', 'gemsecurity_admin_guard_sweep', 'gemsecurity_daily_report', 'gemsecurity_temp_access_sweep', ]; foreach ( $hooks as $hook ) { wp_clear_scheduled_hook( $hook ); } // Extended-protection mu-plugin. $mu = WPMU_PLUGIN_DIR . '/gemsecurity-extended-protection.php'; if ( file_exists( $mu ) ) { wp_delete_file( $mu ); }