PluginProbe
WDesignKit – AI Templates, Widget Builder & MCP Workflow / trunk
WDesignKit – AI Templates, Widget Builder & MCP Workflow vtrunk
2.6.6 2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.4.0 2.3.3 2.3.2 2.3.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 All 128 releases
wdesignkit / includes / abilities / settings / wdesignkit-remove-database.php

wdesignkit-remove-database.php in WDesignKit – AI Templates, Widget Builder & MCP Workflow trunk, at includes/abilities/settings/wdesignkit-remove-database.php

260 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Ability: Configure or execute WDesignKit database cleanup.
4 */
5
6 declare(strict_types=1);
7
8 if (!defined('ABSPATH')) {
9 exit();
10 }
11
12 wp_register_ability('wdesignkit/remove-database', [
13 'label' => __('WDesignKit Remove Database', 'wdesignkit'),
14 'description' => __(
15 'Manages the WDesignKit database-cleanup configuration and can execute an immediate cleanup. "get" reads the current config; "configure" saves which data should be removed on uninstall; "execute" runs the cleanup immediately. Destructive execute requires confirm: true; use dry_run: true to preview.',
16 'wdesignkit',
17 ),
18 'category' => 'wdesignkit',
19 'input_schema' => [
20 'type' => 'object',
21 'properties' => [
22 'action' => [
23 'type' => 'string',
24 'description' => '"get" reads current config, "configure" saves cleanup settings, "execute" runs immediate cleanup.',
25 'enum' => ['get', 'configure', 'execute'],
26 ],
27 'remove_entries' => [
28 'type' => 'boolean',
29 'description' => 'Master toggle: whether any cleanup runs on uninstall (or immediate execute).',
30 ],
31 'promotion_data' => [
32 'type' => 'boolean',
33 'description' => 'Delete user meta: wdkit_rating_banner_start_date for all users.',
34 ],
35 'widget_builder_data' => [
36 'type' => 'boolean',
37 'description' => 'Delete options: wkit_deactivate_widgets and wkit_builder.',
38 ],
39 'all_data' => [
40 'type' => 'boolean',
41 'description' => 'Delete all plugin data including settings, onboarding, and user meta. Superset of the other flags.',
42 ],
43 'confirm' => [
44 'type' => 'boolean',
45 'description' => 'Required when action is "execute". Must be true to run the cleanup immediately.',
46 ],
47 'dry_run' => [
48 'type' => 'boolean',
49 'description' => 'When true with action "execute", previews what would be deleted without making changes.',
50 ],
51 ],
52 'additionalProperties' => false,
53 ],
54 'output_schema' => [
55 'type' => 'object',
56 'properties' => [
57 'success' => ['type' => 'boolean'],
58 'message' => ['type' => 'string'],
59 'config' => ['type' => 'object'],
60 'deleted' => ['type' => 'array', 'items' => ['type' => 'string']],
61 'dry_run' => ['type' => 'boolean'],
62 ],
63 ],
64 'execute_callback' => 'wdesignkit_mcp_remove_database',
65 'permission_callback' => 'wdesignkit_mcp_permission_callback',
66 'meta' => [
67 // action "execute" irreversibly deletes the plugin's stored data, which is the data half
68 // of deleting the plugin — gated on delete_plugins so a multisite site admin (who has
69 // manage_options but not delete_plugins) cannot wipe it. Enforced via
70 // wp_ability_permission_result (WP 7.1+); see class-wdk-ability-lifecycle.php.
71 'required_capability' => 'delete_plugins',
72 'public' => false,
73 'show_in_rest' => true,
74 'mcp' => ['public' => false],
75 'annotations' => [
76 'instructions' => implode("\n", [
77 'Manages WDesignKit database cleanup.',
78 'action "get": returns current remove_db config (default if action omitted).',
79 'action "configure": saves settings that take effect on next plugin uninstall.',
80 'action "execute": runs cleanup NOW — requires confirm: true. Use dry_run: true to preview first.',
81 'WARNING: execute with all_data: true deletes ALL WDesignKit settings and cannot be undone.',
82 'Deleted items by flag — widget_builder_data: wkit_deactivate_widgets, wkit_builder; all_data: additionally wkit_settings_panel, wkit_onbording_end, wdkit_dark_mode, wdkit_wintersale_notice_dismissed, user meta wdkit_rating_banner_start_date.',
83 ]),
84 'readonly' => false,
85 'destructive' => true,
86 'idempotent' => false,
87 ],
88 ],
89 ]);
90
91 function wdesignkit_mcp_remove_database(array $input): array {
92 $action = sanitize_text_field((string) ($input['action'] ?? 'get'));
93
94 $settings = get_option('wkit_settings_panel', []);
95 if (!is_array($settings)) {
96 $settings = [];
97 }
98
99 $stored = is_array($settings['remove_db'] ?? null) ? $settings['remove_db'] : [];
100 $current_config = [
101 'remove_entries' => ($stored['remove_entries'] ?? '') === 'on',
102 'promotion_data' => !empty($stored['promotion_data']),
103 'widget_builder_data' => !empty($stored['widget_builder_data']),
104 'all_data' => !empty($stored['all_data']),
105 ];
106
107 if ($action === 'get') {
108 return [
109 'success' => true,
110 'message' => 'Current remove_db configuration.',
111 'config' => $current_config,
112 ];
113 }
114
115 // Merge caller's overrides into current config
116 $new_config = $current_config;
117 foreach (['remove_entries', 'promotion_data', 'widget_builder_data', 'all_data'] as $key) {
118 if (isset($input[$key])) {
119 $new_config[$key] = (bool) $input[$key];
120 }
121 }
122
123 if ($action === 'configure') {
124 $settings['remove_db'] = [
125 'remove_entries' => $new_config['remove_entries'] ? 'on' : 'off',
126 'promotion_data' => $new_config['promotion_data'],
127 'widget_builder_data' => $new_config['widget_builder_data'],
128 'all_data' => $new_config['all_data'],
129 ];
130 update_option('wkit_settings_panel', $settings);
131
132 return [
133 'success' => true,
134 'message' => 'Database cleanup configuration saved. Settings take effect on next plugin uninstall.',
135 'config' => $new_config,
136 ];
137 }
138
139 // action === 'execute'
140 // Use the stored configure() settings as the baseline so that a plain
141 // dry_run: true call (no extra flags) previews exactly what configure() set up.
142 // Per-call params override the stored values when explicitly provided.
143 $new_config = [
144 'remove_entries' => isset($input['remove_entries']) ? (bool) $input['remove_entries'] : $current_config['remove_entries'],
145 'promotion_data' => isset($input['promotion_data']) ? (bool) $input['promotion_data'] : $current_config['promotion_data'],
146 'widget_builder_data' => isset($input['widget_builder_data']) ? (bool) $input['widget_builder_data'] : $current_config['widget_builder_data'],
147 'all_data' => isset($input['all_data']) ? (bool) $input['all_data'] : $current_config['all_data'],
148 ];
149
150 $dry_run = (bool) ($input['dry_run'] ?? false);
151 $confirm = (bool) ($input['confirm'] ?? false);
152
153 if (!$dry_run && !$confirm) {
154 return [
155 'success' => false,
156 'message' => 'Immediate cleanup requires confirm: true (or dry_run: true to preview).',
157 'config' => $new_config,
158 'dry_run' => false,
159 ];
160 }
161
162 // Resolve what would be deleted
163 $to_delete_options = [];
164 $to_delete_user_meta = [];
165
166 if ($new_config['remove_entries']) {
167 if ($new_config['promotion_data']) {
168 $to_delete_user_meta[] = 'wdkit_rating_banner_start_date (all users)';
169 }
170 if ($new_config['widget_builder_data']) {
171 $to_delete_options[] = 'wkit_deactivate_widgets';
172 $to_delete_options[] = 'wkit_builder';
173 }
174 if ($new_config['all_data']) {
175 $to_delete_options = array_unique(array_merge($to_delete_options, [
176 'wkit_deactivate_widgets',
177 'wkit_builder',
178 'wkit_settings_panel',
179 'wkit_onbording_end',
180 'wdkit_dark_mode',
181 'wdkit_wintersale_notice_dismissed',
182 ]));
183 $to_delete_user_meta = ['wdkit_rating_banner_start_date (all users)'];
184 }
185 }
186
187 $preview = array_merge(array_values($to_delete_options), $to_delete_user_meta);
188
189 if ($dry_run) {
190 return [
191 'success' => true,
192 'message' => empty($preview) ? 'Nothing would be deleted with these settings.' : 'Dry run: the following would be deleted.',
193 'config' => $new_config,
194 'deleted' => $preview,
195 'dry_run' => true,
196 ];
197 }
198
199 // Execute
200 $actually_deleted = [];
201
202 if ($new_config['remove_entries']) {
203 if ($new_config['promotion_data']) {
204 foreach (get_users() as $user) {
205 delete_user_meta((int) $user->ID, 'wdkit_rating_banner_start_date');
206 }
207 $actually_deleted[] = 'wdkit_rating_banner_start_date (all users)';
208 }
209
210 if ($new_config['widget_builder_data']) {
211 delete_option('wkit_deactivate_widgets');
212 delete_option('wkit_builder');
213 $actually_deleted[] = 'wkit_deactivate_widgets';
214 $actually_deleted[] = 'wkit_builder';
215 }
216
217 if ($new_config['all_data']) {
218 delete_option('wkit_deactivate_widgets');
219 delete_option('wkit_builder');
220 delete_option('wkit_settings_panel');
221 delete_option('wkit_onbording_end');
222 delete_option('wdkit_dark_mode');
223 delete_option('wdkit_wintersale_notice_dismissed');
224 foreach (get_users() as $user) {
225 delete_user_meta((int) $user->ID, 'wdkit_rating_banner_start_date');
226 }
227 $actually_deleted = [
228 'wkit_deactivate_widgets',
229 'wkit_builder',
230 'wkit_settings_panel',
231 'wkit_onbording_end',
232 'wdkit_dark_mode',
233 'wdkit_wintersale_notice_dismissed',
234 'wdkit_rating_banner_start_date (all users)',
235 ];
236 }
237
238 // Both branches above delete wkit_deactivate_widgets, and the cached widget registry bakes
239 // that option's membership in. The cache is a no-expiry transient, so without this the
240 // widgets the reset was meant to re-enable stayed unregistered indefinitely
241 // (ClickUp 86d41cd18 — same root cause as the admin activate/deactivate path, 86d41cck1).
242 if (($new_config['widget_builder_data'] || $new_config['all_data'])
243 && function_exists('wdesignkit_invalidate_widget_registry')) {
244 foreach (['elementor', 'gutenberg', 'gutenberg_core', 'bricks'] as $builder_slug) {
245 wdesignkit_invalidate_widget_registry($builder_slug);
246 }
247 }
248 }
249
250 return [
251 'success' => true,
252 'message' => empty($actually_deleted)
253 ? 'Cleanup executed but nothing was deleted (remove_entries is off or no data flags selected).'
254 : 'Database cleanup executed successfully.',
255 'config' => $new_config,
256 'deleted' => $actually_deleted,
257 'dry_run' => false,
258 ];
259 }
260