| @@ -1,31 +1,119 @@ | ||
| 1 | -<?php | |
| 2 | - | |
| 3 | -/** | |
| 4 | - * Fired when the plugin is uninstalled. | |
| 5 | - * | |
| 6 | - * When populating this file, consider the following flow | |
| 7 | - * of control: | |
| 8 | - * | |
| 9 | - * - This method should be static | |
| 10 | - * - Check if the $_REQUEST content actually is the plugin name | |
| 11 | - * - Run an admin referrer check to make sure it goes through authentication | |
| 12 | - * - Verify the output of $_GET makes sense | |
| 13 | - * - Repeat with other user roles. Best directly by using the links/query string parameters. | |
| 14 | - * - Repeat things for multisite. Once for a single site in the network, once sitewide. | |
| 15 | - * | |
| 16 | - * This file may be updated more in future version of the Boilerplate; however, this is the | |
| 17 | - * general skeleton and outline for how the file should work. | |
| 18 | - * | |
| 19 | - * For more information, see the following discussion: | |
| 20 | - * https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate/pull/123#issuecomment-28541913 | |
| 21 | - * | |
| 22 | - * @link https://posimyth.com/ | |
| 23 | - * @since 1.0.0 | |
| 24 | - * | |
| 25 | - * @package Wdesignkit | |
| 26 | - */ | |
| 27 | - | |
| 28 | -// If uninstall not called from WordPress, then exit. | |
| 29 | -if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { | |
| 30 | - exit; | |
| 31 | -} | |
| 1 | +<?php | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Fired when the plugin is uninstalled. | |
| 5 | + * | |
| 6 | + * @link https://posimyth.com/ | |
| 7 | + * @since 1.0.0 | |
| 8 | + * | |
| 9 | + * @package Wdesignkit | |
| 10 | + */ | |
| 11 | + | |
| 12 | +// If uninstall not called from WordPress, then exit. | |
| 13 | +if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { | |
| 14 | + exit; | |
| 15 | +} | |
| 16 | + | |
| 17 | +// Get the plugin setting and remove entries before unistall plugin. | |
| 18 | +$get_setting = get_option( 'wkit_settings_panel', false ); | |
| 19 | + | |
| 20 | +if ( ! empty( $get_setting['remove_db']['remove_entries'] ) && $get_setting['remove_db']['remove_entries'] == 'on' ) { | |
| 21 | + | |
| 22 | + if ( ! empty( $get_setting['remove_db']['promotion_data'] ) && $get_setting['remove_db']['promotion_data'] == true ) { | |
| 23 | + $users = get_users(); | |
| 24 | + | |
| 25 | + if ( ! empty( $users ) ) { | |
| 26 | + foreach ( $users as $user ) { | |
| 27 | + $user_id = $user->ID; | |
| 28 | + | |
| 29 | + delete_user_meta( $user_id, 'wdkit_rating_banner_start_date' ); | |
| 30 | + } | |
| 31 | + } | |
| 32 | + } | |
| 33 | + | |
| 34 | + if ( ! empty( $get_setting['remove_db']['widget_builder_data'] ) && $get_setting['remove_db']['widget_builder_data'] == true ) { | |
| 35 | + delete_option( 'wkit_deactivate_widgets' ); | |
| 36 | + delete_option( 'wkit_builder' ); | |
| 37 | + } | |
| 38 | + | |
| 39 | + if ( ! empty( $get_setting['remove_db']['all_data'] ) && $get_setting['remove_db']['all_data'] == true ) { | |
| 40 | + delete_option( 'wkit_deactivate_widgets' ); | |
| 41 | + delete_option( 'wkit_builder' ); | |
| 42 | + delete_option( 'wkit_settings_panel' ); | |
| 43 | + delete_option( 'wkit_onbording_end' ); | |
| 44 | + delete_option( 'wdkit_dark_mode' ); | |
| 45 | + delete_option( 'wdkit_wintersale_notice_dismissed' ); | |
| 46 | + | |
| 47 | + $users = get_users(); | |
| 48 | + if ( ! empty( $users ) ) { | |
| 49 | + foreach ( $users as $user ) { | |
| 50 | + $user_id = $user->ID; | |
| 51 | + | |
| 52 | + delete_user_meta( $user_id, 'wdkit_rating_banner_start_date' ); | |
| 53 | + } | |
| 54 | + } | |
| 55 | + } | |
| 56 | +} | |
| 57 | + | |
| 58 | +/* | |
| 59 | + * Analytics state — removed UNCONDITIONALLY, outside the remove_db gate above. | |
| 60 | + * | |
| 61 | + * That gate is a housekeeping preference: "also delete my widget and settings data". Consent is not | |
| 62 | + * housekeeping. Someone who removes the plugin has withdrawn from the data-sharing arrangement, and | |
| 63 | + * leaving the opt-in behind means a reinstall silently resumes sending without ever asking again — | |
| 64 | + * which is the exact behaviour purge_state() exists to prevent. | |
| 65 | + * | |
| 66 | + * suite_key `wdk_suite` has exactly one member, so the suite-wide flag is safe to pass true here: | |
| 67 | + * there is no sibling product whose consent this could reset. | |
| 68 | + */ | |
| 69 | +require_once plugin_dir_path( __FILE__ ) . 'includes/posimyth-sdk/class-posimyth-tracker-wdk.php'; | |
| 70 | + | |
| 71 | +if ( class_exists( 'Posimyth_Tracker_WDK' ) ) { | |
| 72 | + Posimyth_Tracker_WDK::purge_state( true, 'wdk_suite' ); | |
| 73 | +} | |
| 74 | + | |
| 75 | +// Product-specific analytics state purge_state() does not know about. | |
| 76 | +delete_option( 'wdkit_template_imports' ); | |
| 77 | +delete_option( 'wdkit_cloud_usage' ); | |
| 78 | + | |
| 79 | +/* | |
| 80 | + * Widget caches — removed UNCONDITIONALLY, like the analytics state above and for the same reason: | |
| 81 | + * these are derived caches, not user data, so the "also delete my data" preference does not apply. | |
| 82 | + * Rebuilt from disk on demand while the plugin is installed, and meaningless once it is gone. | |
| 83 | + * | |
| 84 | + * Nothing removed these before. The registry options carry the plugin version in their names, so a | |
| 85 | + * site that had been through a few releases accumulated one row per builder per version and an | |
| 86 | + * uninstall left every one of them behind (verified: twelve rows across three versions, plus | |
| 87 | + * wdkit_widget_meta_cache at 32 KB on the QA site). They are written with autoload = false, so this | |
| 88 | + * is housekeeping rather than a performance fix — but "uninstall" should mean it. | |
| 89 | + * | |
| 90 | + * Matched by prefix with a LIKE sweep because the names are version-dependent and this file cannot | |
| 91 | + * know which versions a site has run. Deleted through delete_option() so the option cache is cleared | |
| 92 | + * and the documented hooks fire, which a bulk DELETE would skip. The prefix is written out literally | |
| 93 | + * rather than pulled from includes/abilities/class-wdk-ability-main.php: uninstall.php runs standalone | |
| 94 | + * (WordPress loads it in isolation, with none of the plugin's own files included) and requiring a | |
| 95 | + * 1,200-line abilities loader here to read one string would be the more fragile choice. If that | |
| 96 | + * prefix ever changes, wdesignkit_widget_registry_option_prefix() and this line change together. | |
| 97 | + */ | |
| 98 | +global $wpdb; | |
| 99 | + | |
| 100 | +$wdkit_registry_rows = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- version-dependent option names are only discoverable by pattern. | |
| 101 | + $wpdb->prepare( | |
| 102 | + "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s", | |
| 103 | + $wpdb->esc_like( 'wdkit_widget_registry_' ) . '%' | |
| 104 | + ) | |
| 105 | +); | |
| 106 | + | |
| 107 | +if ( ! empty( $wdkit_registry_rows ) ) { | |
| 108 | + foreach ( $wdkit_registry_rows as $wdkit_registry_row ) { | |
| 109 | + delete_option( $wdkit_registry_row ); | |
| 110 | + } | |
| 111 | +} | |
| 112 | + | |
| 113 | +delete_option( 'wdkit_widget_meta_cache' ); | |
| 114 | + | |
| 115 | +// Legacy autoloaded transients from 2.6.4, superseded by the options above. Named per builder, so | |
| 116 | +// they are cleared by name rather than by pattern. | |
| 117 | +foreach ( array( 'elementor', 'gutenberg', 'gutenberg_core', 'bricks' ) as $wdkit_builder_slug ) { | |
| 118 | + delete_transient( 'wdkit_registered_widgets_' . $wdkit_builder_slug ); | |
| 119 | +} | |