PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / trunk
ووسلام – همگام سازی ووکامرس و باسلام vtrunk
1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 1.8.6 1.8.7 1.8.4 1.7.6 All 50 releases
sync-basalam / uninstall.php

uninstall.php in ووسلام – همگام سازی ووکامرس و باسلام trunk, at uninstall.php

358 lines 12.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Sync Basalam Uninstall
5 *
6 * Default uninstall:
7 * - Removes runtime jobs/queues/cron markers so no background process remains.
8 *
9 * Full data wipe:
10 * - Define SYNC_BASALAM_REMOVE_ALL_DATA as true in wp-config.php before uninstall.
11 * - Removes plugin tables, options, usermeta, and postmeta.
12 */
13
14 defined('WP_UNINSTALL_PLUGIN') || exit;
15
16 $sync_basalam_remove_all_data = defined('SYNC_BASALAM_REMOVE_ALL_DATA') && true === SYNC_BASALAM_REMOVE_ALL_DATA;
17
18 sync_basalam_uninstall_site($sync_basalam_remove_all_data);
19
20 function sync_basalam_uninstall_site(bool $remove_all_data): void
21 {
22 sync_basalam_cleanup_runtime_data();
23
24 if ($remove_all_data) {
25 sync_basalam_remove_all_plugin_data();
26 }
27 }
28
29 function sync_basalam_cleanup_runtime_data(): void
30 {
31 global $wpdb;
32
33 sync_basalam_clear_wp_cron_events();
34 sync_basalam_clear_wc_queue_actions();
35 sync_basalam_delete_action_scheduler_rows();
36
37 $job_manager_table = $wpdb->prefix . 'sync_basalam_job_manager';
38 if (sync_basalam_table_exists($job_manager_table)) {
39 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom plugin table; identifier from $wpdb->prefix, not user input.
40 $wpdb->query("DELETE FROM {$job_manager_table}");
41 }
42
43 sync_basalam_delete_option_rows_like(
44 [
45 'sync_basalam_%_last_run',
46 'sync_basalam_last_creatable_product_id',
47 'CreateSingleProduct_%_batch_%',
48 'sync_basalam_update_single_product_%_batch_%',
49 'UpdateSingleProduct_%_batch_%',
50 'sync_basalam_%_batch_%',
51 '_transient_sync_basalam_%_lock',
52 '_transient_timeout_sync_basalam_%_lock',
53 '_transient_CreateSingleProduct_%_lock',
54 '_transient_timeout_CreateSingleProduct_%_lock',
55 '_transient_UpdateSingleProduct_%_lock',
56 '_transient_timeout_UpdateSingleProduct_%_lock',
57 '_site_transient_sync_basalam_%_process_lock',
58 '_site_transient_timeout_sync_basalam_%_process_lock',
59 '_site_transient_CreateSingleProduct_%_process_lock',
60 '_site_transient_timeout_CreateSingleProduct_%_process_lock',
61 '_site_transient_UpdateSingleProduct_%_process_lock',
62 '_site_transient_timeout_UpdateSingleProduct_%_process_lock',
63 ]
64 );
65 }
66
67 function sync_basalam_remove_all_plugin_data(): void
68 {
69 global $wpdb;
70
71 $tables = [
72 $wpdb->prefix . 'sync_basalam_payments',
73 $wpdb->prefix . 'sync_basalam_map_options',
74 $wpdb->prefix . 'sync_basalam_uploaded_media',
75 $wpdb->prefix . 'sync_basalam_debug_logs',
76 $wpdb->prefix . 'sync_basalam_discount_tasks',
77 $wpdb->prefix . 'sync_basalam_category_mappings',
78 $wpdb->prefix . 'sync_basalam_job_manager',
79 // Legacy tables from older naming/migrations.
80 $wpdb->prefix . 'sync_basalam_uploaded_photo',
81 $wpdb->prefix . 'bsl_payments',
82 $wpdb->prefix . 'bsl_map_options',
83 $wpdb->prefix . 'bsl_uploaded_photo',
84 $wpdb->prefix . 'bsl_payments_old',
85 $wpdb->prefix . 'bsl_map_options_old',
86 $wpdb->prefix . 'bsl_uploaded_photo_old',
87 ];
88
89 foreach ($tables as $table) {
90 if (sync_basalam_table_exists($table)) {
91 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin uninstall drops own tables; identifier from $wpdb->prefix, not user input.
92 $wpdb->query("DROP TABLE IF EXISTS {$table}");
93 }
94 }
95
96 sync_basalam_delete_option_rows_like(
97 [
98 'sync_basalam_%',
99 '_transient_sync_basalam_%',
100 '_transient_timeout_sync_basalam_%',
101 '_site_transient_sync_basalam_%',
102 '_site_transient_timeout_sync_basalam_%',
103 'CreateSingleProduct_%_batch_%',
104 'sync_basalam_update_single_product_%_batch_%',
105 'UpdateSingleProduct_%_batch_%',
106 'sync_basalam_%_batch_%',
107 '_transient_CreateSingleProduct_%_lock',
108 '_transient_timeout_CreateSingleProduct_%_lock',
109 '_transient_UpdateSingleProduct_%_lock',
110 '_transient_timeout_UpdateSingleProduct_%_lock',
111 '_site_transient_CreateSingleProduct_%_process_lock',
112 '_site_transient_timeout_CreateSingleProduct_%_process_lock',
113 '_site_transient_UpdateSingleProduct_%_process_lock',
114 '_site_transient_timeout_UpdateSingleProduct_%_process_lock',
115 ]
116 );
117
118 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin uninstall cleanup on core usermeta table; no object cache applicable.
119 $wpdb->query(
120 $wpdb->prepare(
121 "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s",
122 'sync_basalam_%'
123 )
124 );
125
126 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin uninstall cleanup on core postmeta table; no object cache applicable.
127 $wpdb->query(
128 $wpdb->prepare(
129 "DELETE FROM {$wpdb->postmeta}
130 WHERE meta_key LIKE %s
131 OR meta_key LIKE %s
132 OR meta_key = %s
133 OR meta_key = %s
134 OR meta_key = %s
135 OR meta_key = %s
136 OR meta_key = %s
137 OR meta_key = %s",
138 'sync_basalam_%',
139 '_sync_basalam_%',
140 '_is_sync_basalam_order',
141 '_basalam_order_tracking_code',
142 '_basalam_fee_amount',
143 '_basalam_balance_amount',
144 '_basalam_purchase_count',
145 '_sync_basalam_price_change_value'
146 )
147 );
148
149 wp_cache_flush();
150 }
151
152 function sync_basalam_clear_wp_cron_events(): void
153 {
154 $known_hooks = sync_basalam_get_known_hooks();
155
156 foreach ($known_hooks as $hook) {
157 wp_clear_scheduled_hook($hook);
158 }
159
160 if (!function_exists('_get_cron_array')) {
161 return;
162 }
163
164 $cron = _get_cron_array();
165 if (!is_array($cron)) {
166 return;
167 }
168
169 foreach (array_keys($cron) as $hook) {
170 $hook = (string) $hook;
171
172 if (sync_basalam_is_related_hook($hook)) {
173 wp_clear_scheduled_hook($hook);
174 }
175 }
176 }
177
178 function sync_basalam_clear_wc_queue_actions(): void
179 {
180 $queue_hooks = [
181 'sync_basalam_plugin_debug',
182 'sync_basalam_fetch_version_detail',
183 ];
184
185 if (function_exists('as_unschedule_all_actions')) {
186 foreach ($queue_hooks as $hook) {
187 as_unschedule_all_actions($hook);
188 as_unschedule_all_actions($hook, [], 'sync-basalam');
189 }
190 }
191
192 if (!function_exists('WC')) {
193 return;
194 }
195
196 $wc = WC();
197 if (!is_object($wc) || !method_exists($wc, 'queue')) {
198 return;
199 }
200
201 $queue = $wc->queue();
202 if (!is_object($queue) || !method_exists($queue, 'cancel_all')) {
203 return;
204 }
205
206 foreach ($queue_hooks as $hook) {
207 $queue->cancel_all($hook);
208 }
209 }
210
211 function sync_basalam_delete_action_scheduler_rows(): void
212 {
213 global $wpdb;
214
215 $actions_table = $wpdb->prefix . 'actionscheduler_actions';
216 $groups_table = $wpdb->prefix . 'actionscheduler_groups';
217
218 if (!sync_basalam_table_exists($actions_table)) {
219 return;
220 }
221
222 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Action Scheduler table; identifier from $wpdb->prefix, not user input.
223 $wpdb->query(
224 $wpdb->prepare(
225 "DELETE FROM {$actions_table}
226 WHERE hook LIKE %s
227 OR hook LIKE %s
228 OR hook LIKE %s",
229 'sync_basalam_%',
230 'CreateSingleProduct_%',
231 'UpdateSingleProduct_%'
232 )
233 );
234
235 if (!sync_basalam_table_exists($groups_table)) {
236 return;
237 }
238
239 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Action Scheduler table; identifier from $wpdb->prefix, not user input.
240 $group_ids = $wpdb->get_col(
241 $wpdb->prepare(
242 "SELECT group_id FROM {$groups_table} WHERE slug = %s",
243 'sync-basalam'
244 )
245 );
246
247 if (empty($group_ids)) {
248 return;
249 }
250
251 $group_ids = array_map('intval', $group_ids);
252 $group_ids = array_filter($group_ids);
253
254 if (empty($group_ids)) {
255 return;
256 }
257
258 $ids = implode(',', $group_ids);
259
260 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Action Scheduler table; identifier from $wpdb->prefix and intval-sanitized ID list, not user input.
261 $wpdb->query("DELETE FROM {$actions_table} WHERE group_id IN ({$ids})");
262 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Action Scheduler table; identifier from $wpdb->prefix and intval-sanitized ID list, not user input.
263 $wpdb->query("DELETE FROM {$groups_table} WHERE group_id IN ({$ids})");
264 }
265
266 function sync_basalam_cleanup_network_site_transients(): void
267 {
268 global $wpdb;
269
270 if (!is_multisite() || empty($wpdb->sitemeta)) {
271 return;
272 }
273
274 $patterns = [
275 '_site_transient_sync_basalam_%',
276 '_site_transient_timeout_sync_basalam_%',
277 '_site_transient_CreateSingleProduct_%',
278 '_site_transient_timeout_CreateSingleProduct_%',
279 '_site_transient_UpdateSingleProduct_%',
280 '_site_transient_timeout_UpdateSingleProduct_%',
281 ];
282
283 foreach ($patterns as $pattern) {
284 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Multisite uninstall cleanup on core sitemeta table; no object cache applicable.
285 $wpdb->query(
286 $wpdb->prepare(
287 "DELETE FROM {$wpdb->sitemeta} WHERE meta_key LIKE %s",
288 $pattern
289 )
290 );
291 }
292 }
293
294 function sync_basalam_delete_option_rows_like(array $patterns): void
295 {
296 global $wpdb;
297
298 foreach ($patterns as $pattern) {
299 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin uninstall cleanup on core options table; no object cache applicable.
300 $wpdb->query(
301 $wpdb->prepare(
302 "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
303 $pattern
304 )
305 );
306 }
307 }
308
309 function sync_basalam_table_exists(string $table_name): bool
310 {
311 global $wpdb;
312
313 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Table existence check; no object cache applicable.
314 $table = $wpdb->get_var(
315 $wpdb->prepare(
316 'SHOW TABLES LIKE %s',
317 $table_name
318 )
319 );
320
321 return $table === $table_name;
322 }
323
324 function sync_basalam_get_known_hooks(): array
325 {
326 $create_identifier = 'CreateSingleProduct_' . substr(md5('SyncBasalam\\Queue\\Tasks\\CreateProduct'), 0, 8);
327 $update_identifier = 'sync_basalam_update_single_product_' . substr(md5('SyncBasalam\\Queue\\Tasks\\UpdateProduct'), 0, 8);
328 $legacy_update_identifier = 'UpdateSingleProduct_' . substr(md5('SyncBasalam\\Queue\\Tasks\\UpdateProduct'), 0, 8);
329
330 return [
331 'sync_basalam_plugin_debug',
332 'sync_basalam_fetch_version_detail',
333 $create_identifier . '_cron',
334 $create_identifier . '_immediate',
335 $update_identifier . '_cron',
336 $update_identifier . '_immediate',
337 $legacy_update_identifier . '_cron',
338 $legacy_update_identifier . '_immediate',
339 ];
340 }
341
342 function sync_basalam_is_related_hook(string $hook): bool
343 {
344 $prefixes = [
345 'sync_basalam_',
346 'CreateSingleProduct_',
347 'UpdateSingleProduct_',
348 ];
349
350 foreach ($prefixes as $prefix) {
351 if (strpos($hook, $prefix) === 0) {
352 return true;
353 }
354 }
355
356 return false;
357 }
358