PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.0
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.0
4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / admin / controllers / class-plugin-reset-controller.php
superb-blocks / src / admin / controllers Last commit date
wizard 1 month ago class-dashboard-controller.php 1 month ago class-license-resolve-controller.php 1 month ago class-newsletter-signup-controller.php 1 month ago class-notice-controller.php 1 month ago class-plugin-reset-controller.php 1 month ago class-rewrite-check-controller.php 1 month ago class-settings-controller.php 1 month ago class-troubleshooting-controller.php 1 month ago
class-plugin-reset-controller.php
162 lines
1 <?php
2
3 namespace SuperbAddons\Admin\Controllers;
4
5 defined('ABSPATH') || exit();
6
7 use Exception;
8 use SuperbAddons\Data\Controllers\KeyController;
9 use SuperbAddons\Data\Controllers\LogController;
10 use SuperbAddons\Data\Controllers\Option;
11 use SuperbAddons\Gutenberg\Controllers\GutenbergEnhancementsController;
12 use SuperbAddons\Library\Controllers\FavoritesController;
13 use SuperbAddons\Gutenberg\Form\FormGoogleAuth;
14 use SuperbAddons\Gutenberg\Form\FormRegistry;
15 use SuperbAddons\Gutenberg\Form\FormSettings;
16 use SuperbAddons\Gutenberg\Form\FormSubmissionCPT;
17 use SuperbAddons\Gutenberg\Form\FormSubmissionHandler;
18 use SuperbAddons\Gutenberg\Popup\PopupRegistry;
19 use SuperbAddons\Tours\Controllers\TourController;
20
21 class PluginResetController
22 {
23 /**
24 * Completely wipe every trace of plugin data from this site.
25 *
26 * Order matters: license removal must run before its option row is deleted
27 * so the remote server is notified; the form registry must be read before
28 * its option row is deleted so every dynamic config option gets cleaned up.
29 *
30 * @param bool $include_submissions When true, also deletes every stored form submission CPT post.
31 * @return bool
32 */
33 public static function RemoveAllPluginData($include_submissions = false)
34 {
35 // 1. License first — notify remote server before the option row is deleted locally.
36 // Guarded so we don't make a pointless remote call when no key is registered.
37 if (KeyController::HasRegisteredKey()) {
38 try {
39 KeyController::RemoveKey();
40 } catch (Exception $e) {
41 // RemoveKey already logs internally; swallow so a network failure
42 // does not block the rest of the local cleanup.
43 }
44 }
45
46 // 2. Unschedule cron hooks.
47 $cron_hooks = array(
48 'superbaddons_share_error_logs',
49 'superb_blocks_template_restoration_cleanup',
50 'spb_form_spam_purge',
51 'spb_form_retention_purge',
52 );
53 foreach ($cron_hooks as $hook) {
54 wp_clear_scheduled_hook($hook);
55 }
56
57 // 3. Iterate form registry BEFORE deleting it so we can clean up every
58 // dynamic spb_form_cfg_{form_id} option row.
59 $form_registry = get_option(FormRegistry::OPTION_KEY, array());
60 if (is_array($form_registry)) {
61 foreach ($form_registry as $form_id => $_unused) {
62 delete_option(FormRegistry::CONFIG_PREFIX . sanitize_key($form_id));
63 }
64 }
65
66 // 4. Delete every option row the plugin has ever written.
67 $option_keys = array(
68 // Core plugin options (with constants where available)
69 Option::KEY_DOMAIN,
70 Option::SETTINGS,
71 Option::COMPATIBILITY_SETTINGS,
72 Option::DISABLED_BLOCKS,
73 Option::GLOBAL_ENHANCEMENTS,
74 // Core plugin options without constants
75 'superbaddonslibrary_service_version',
76 'superbaddonslibrary_gutenberg_patterns',
77 'superbaddonslibrary_gutenberg_pages',
78 'superbaddonslibrary_elementor_sections',
79 'superbaddons_errorlogs',
80 'superbaddons_wizard_completed_themes',
81 'superbaddons_wizard_navigation_post_id',
82 'superbaddons_elementor_tour_id',
83 'superbaddons_pre_activation',
84 'superbaddons_css_block_target_valid_labels',
85 // Form settings
86 FormSettings::OPTION_HCAPTCHA_SITE_KEY,
87 FormSettings::OPTION_HCAPTCHA_SECRET_KEY,
88 FormSettings::OPTION_RECAPTCHA_SITE_KEY,
89 FormSettings::OPTION_RECAPTCHA_SECRET_KEY,
90 FormSettings::OPTION_TURNSTILE_SITE_KEY,
91 FormSettings::OPTION_TURNSTILE_SECRET_KEY,
92 FormSettings::OPTION_MAILCHIMP_API_KEY,
93 FormSettings::OPTION_BREVO_API_KEY,
94 FormSettings::OPTION_GOOGLE_SHEETS_CLIENT_EMAIL,
95 FormSettings::OPTION_GOOGLE_SHEETS_PRIVATE_KEY,
96 FormSettings::OPTION_WEBHOOK_SECRETS,
97 'superbaddons_form_role_permissions',
98 'superbaddons_form_access_control_enabled',
99 'superbaddons_form_default_email',
100 'superbaddons_form_data_retention',
101 // Registries (delete AFTER iterating above)
102 FormRegistry::OPTION_KEY,
103 PopupRegistry::OPTION_KEY,
104 );
105 foreach ($option_keys as $option_key) {
106 delete_option($option_key);
107 }
108
109 // 5. Delete transients.
110 $transient_keys = array(
111 'superbaddons_activation_redirect',
112 'superbaddons_wizard_recommender_transient',
113 'superbaddons_wizard_woocommerce_transient',
114 'superb_blocks_template_restoration',
115 'superbaddons_template_part_preview',
116 FormGoogleAuth::TRANSIENT_KEY,
117 );
118 foreach ($transient_keys as $transient_key) {
119 delete_transient($transient_key);
120 }
121
122 // 5b. Purge namespaced commerce transients (product/stock/search caches).
123 // Keys look like: _transient_superb_commerce_product_123_1700000000 etc.
124 // Direct query: no WP API exists for bulk-deleting transients by prefix; iterating get_option() to find them would itself bypass caching and is far slower. Pattern is a constant string with literal underscores escaped so they aren't treated as LIKE wildcards. Caching does not apply to a DELETE; this runs once during plugin reset.
125 global $wpdb;
126 if (isset($wpdb) && is_object($wpdb)) {
127 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
128 $wpdb->query(
129 "DELETE FROM {$wpdb->options}
130 WHERE option_name LIKE '_transient_superb_commerce\\_%'
131 OR option_name LIKE '_transient_timeout_superb_commerce\\_%'"
132 );
133 }
134
135 // 6. Delete user meta (site-wide).
136 AdminNoticeController::Cleanup();
137 NewsletterSignupController::Cleanup();
138 delete_metadata('user', 0, TourController::TOUR_DASHBOARD_WELCOME_META, false, true);
139 delete_metadata('user', 0, TourController::TOUR_BLOCK_THEME_META, false, true);
140 delete_metadata('user', 0, GutenbergEnhancementsController::ENHANCEMENTS_OPTION, false, true);
141 delete_metadata('user', 0, FavoritesController::FAVORITES_META_KEY, false, true);
142
143 // 7. Optionally wipe every stored form submission.
144 if ($include_submissions) {
145 $submission_ids = get_posts(array(
146 'post_type' => FormSubmissionCPT::POST_TYPE,
147 'post_status' => 'any',
148 'posts_per_page' => -1,
149 'fields' => 'ids',
150 'no_found_rows' => true,
151 'update_post_meta_cache' => false,
152 'update_post_term_cache' => false,
153 ));
154 if (!empty($submission_ids)) {
155 FormSubmissionHandler::BulkDelete($submission_ids);
156 }
157 }
158
159 return true;
160 }
161 }
162