PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.7
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.7
4.0.7 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 5 days ago class-dashboard-controller.php 5 days ago class-license-resolve-controller.php 5 days ago class-newsletter-signup-controller.php 5 days ago class-notice-controller.php 5 days ago class-plugin-reset-controller.php 5 days ago class-review-controller.php 5 days ago class-rewrite-check-controller.php 5 days ago class-settings-controller.php 5 days ago class-troubleshooting-controller.php 5 days ago
class-plugin-reset-controller.php
163 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_engagement',
85 'superbaddons_css_block_target_valid_labels',
86 // Form settings
87 FormSettings::OPTION_HCAPTCHA_SITE_KEY,
88 FormSettings::OPTION_HCAPTCHA_SECRET_KEY,
89 FormSettings::OPTION_RECAPTCHA_SITE_KEY,
90 FormSettings::OPTION_RECAPTCHA_SECRET_KEY,
91 FormSettings::OPTION_TURNSTILE_SITE_KEY,
92 FormSettings::OPTION_TURNSTILE_SECRET_KEY,
93 FormSettings::OPTION_MAILCHIMP_API_KEY,
94 FormSettings::OPTION_BREVO_API_KEY,
95 FormSettings::OPTION_GOOGLE_SHEETS_CLIENT_EMAIL,
96 FormSettings::OPTION_GOOGLE_SHEETS_PRIVATE_KEY,
97 FormSettings::OPTION_WEBHOOK_SECRETS,
98 'superbaddons_form_role_permissions',
99 'superbaddons_form_access_control_enabled',
100 'superbaddons_form_default_email',
101 'superbaddons_form_data_retention',
102 // Registries (delete AFTER iterating above)
103 FormRegistry::OPTION_KEY,
104 PopupRegistry::OPTION_KEY,
105 );
106 foreach ($option_keys as $option_key) {
107 delete_option($option_key);
108 }
109
110 // 5. Delete transients.
111 $transient_keys = array(
112 'superbaddons_activation_redirect',
113 'superbaddons_wizard_recommender_transient',
114 'superbaddons_wizard_woocommerce_transient',
115 'superb_blocks_template_restoration',
116 'superbaddons_template_part_preview',
117 FormGoogleAuth::TRANSIENT_KEY,
118 );
119 foreach ($transient_keys as $transient_key) {
120 delete_transient($transient_key);
121 }
122
123 // 5b. Purge namespaced commerce transients (product/stock/search caches).
124 // Keys look like: _transient_superb_commerce_product_123_1700000000 etc.
125 // 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.
126 global $wpdb;
127 if (isset($wpdb) && is_object($wpdb)) {
128 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
129 $wpdb->query(
130 "DELETE FROM {$wpdb->options}
131 WHERE option_name LIKE '_transient_superb_commerce\\_%'
132 OR option_name LIKE '_transient_timeout_superb_commerce\\_%'"
133 );
134 }
135
136 // 6. Delete user meta (site-wide).
137 AdminNoticeController::Cleanup();
138 NewsletterSignupController::Cleanup();
139 delete_metadata('user', 0, TourController::TOUR_DASHBOARD_WELCOME_META, false, true);
140 delete_metadata('user', 0, TourController::TOUR_BLOCK_THEME_META, false, true);
141 delete_metadata('user', 0, GutenbergEnhancementsController::ENHANCEMENTS_OPTION, false, true);
142 delete_metadata('user', 0, FavoritesController::FAVORITES_META_KEY, false, true);
143
144 // 7. Optionally wipe every stored form submission.
145 if ($include_submissions) {
146 $submission_ids = get_posts(array(
147 'post_type' => FormSubmissionCPT::POST_TYPE,
148 'post_status' => 'any',
149 'posts_per_page' => -1,
150 'fields' => 'ids',
151 'no_found_rows' => true,
152 'update_post_meta_cache' => false,
153 'update_post_term_cache' => false,
154 ));
155 if (!empty($submission_ids)) {
156 FormSubmissionHandler::BulkDelete($submission_ids);
157 }
158 }
159
160 return true;
161 }
162 }
163