From f6e981577a4b708b13057486e1a0e114cfc95335 Mon Sep 17 00:00:00 2001 From: jacobd91 Date: Thu, 19 Dec 2024 11:11:38 -0500 Subject: [PATCH 1/2] Final commit. Tested against dev API and working for all options. --- Generic_Plugin_Admin.php | 26 +++++- Generic_Plugin_Survey.php | 170 +++++++++++++++++++++++++++++++++++ Root_Loader.php | 1 + inc/lightbox/exit_survey.php | 97 ++++++++++++++++++++ pub/css/exit-survey.css | 9 ++ pub/js/exit-survey.js | 123 +++++++++++++++++++++++++ 6 files changed, 424 insertions(+), 2 deletions(-) create mode 100644 Generic_Plugin_Survey.php create mode 100644 inc/lightbox/exit_survey.php create mode 100644 pub/css/exit-survey.css create mode 100644 pub/js/exit-survey.js diff --git a/Generic_Plugin_Admin.php b/Generic_Plugin_Admin.php index 79b8cebcc..4c4a55d16 100644 --- a/Generic_Plugin_Admin.php +++ b/Generic_Plugin_Admin.php @@ -385,6 +385,23 @@ public function admin_enqueue_scripts() { wp_enqueue_script( 'w3tc-feature-counter' ); + // Conditional loading for the exit survey on the plugins page. + $current_screen = get_current_screen(); + if ( isset( $current_screen->id ) && 'plugins' === $current_screen->id ) { + wp_register_style( 'w3tc-exit-survey', plugins_url( 'pub/css/exit-survey.css', W3TC_FILE ), array(), W3TC_VERSION ); + wp_enqueue_style( 'w3tc-exit-survey' ); + wp_register_script( 'w3tc-exit-survey', plugins_url( 'pub/js/exit-survey.js', W3TC_FILE ), array(), W3TC_VERSION, true ); + wp_localize_script( + 'w3tc-exit-survey', + 'w3tc_nonce', + wp_create_nonce( 'w3tc' ) + ); + wp_enqueue_script( 'w3tc-exit-survey' ); + + wp_enqueue_style( 'w3tc-lightbox' ); + wp_enqueue_script( 'w3tc-lightbox' ); + } + // Messages. if ( ! is_null( $this->w3tc_message ) && isset( $this->w3tc_message['actions'] ) && is_array( $this->w3tc_message['actions'] ) ) { foreach ( $this->w3tc_message['actions'] as $action ) { @@ -421,8 +438,14 @@ public function admin_head() { global $wp_version; global $wpdb; + // Attempt to get the 'page' parameter from the request. $page = Util_Request::get_string( 'page', null ); + // If 'page' is null or an empty string, fallback to current screen ID. + if ( empty( $page ) ) { + $page = get_current_screen()->id ?? null; + } + if ( ( ! is_multisite() || is_super_admin() ) && false !== strpos( $page, 'w3tc' ) && 'w3tc_setup_guide' !== $page && ! get_site_option( 'w3tc_setupguide_completed' ) ) { $state_master = Dispatcher::config_state_master(); @@ -445,8 +468,7 @@ public function admin_head() { } } - if ( $this->_config->get_boolean( 'common.track_usage' ) && $this->is_w3tc_page ) { - + if ( $this->_config->get_boolean( 'common.track_usage' ) && ( $this->is_w3tc_page || 'plugins' === $page ) ) { $current_user = wp_get_current_user(); $page = Util_Request::get_string( 'page' ); if ( 'w3tc_extensions' === $page ) { diff --git a/Generic_Plugin_Survey.php b/Generic_Plugin_Survey.php new file mode 100644 index 000000000..bea9cf65e --- /dev/null +++ b/Generic_Plugin_Survey.php @@ -0,0 +1,170 @@ +_config = Dispatcher::config(); + + if ( Util_Environment::is_w3tc_pro( $this->_config ) ) { + $this->license_key = $this->_config->get_string( 'plugin.license_key' ); + $this->home_url = network_home_url(); + $this->item_name = W3TC_PURCHASE_PRODUCT_NAME; + } else { + $this->home_url = network_home_url(); + } + } + + /** + * Runs plugin + * + * @return void + */ + public function run() { + add_action( 'w3tc_ajax_exit_survey_render', array( $this, 'w3tc_ajax_exit_survey_render' ) ); + add_action( 'w3tc_ajax_exit_survey_submit', array( $this, 'w3tc_ajax_exit_survey_submit' ) ); + } + + /** + * Get API base URL. + * + * @since X.X.X + * + * @access private + */ + private function get_base_url() { + return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? esc_url( W3TC_API2_URL, 'https', '' ) : $this->base_url; + } + + /** + * Renders the exit survey lightbox content + * + * @return void + */ + public function w3tc_ajax_exit_survey_render() { + if ( ! \user_can( \get_current_user_id(), 'manage_options' ) ) { + return; + } + + include W3TC_INC_DIR . '/lightbox/exit_survey.php'; + } + + /** + * Processes the exit survey submission and sends it to the API. + * + * @return void + */ + public function w3tc_ajax_exit_survey_submit() { + if ( ! \user_can( \get_current_user_id(), 'manage_options' ) ) { + return; + } + + // Verify nonce. + if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( Util_Request::get_string( '_wpnonce' ), 'w3tc' ) ) { + wp_send_json_error( array( 'message' => 'Invalid nonce.' ) ); + } + + // Collect survey data. + $uninstall_reason = sanitize_text_field( Util_Request::get_string( 'reason' ) ); + $other_reason = sanitize_text_field( Util_Request::get_string( 'other' ) ); + + // Prepare the data to send to the API. + $data = array( + 'type' => 'exit', + 'license_key' => $this->license_key, + 'home_url' => $this->home_url, + 'item_name' => $this->item_name, + 'reason' => $uninstall_reason, + 'other' => $other_reason, + ); + + if ( ( defined( 'W3TC_PRO' ) && W3TC_PRO ) || ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE ) ) { + $data['pro_c'] = 1; + } + + // Send the data to your API server using wp_remote_post. + $response = wp_remote_post( + $this->get_base_url() . '/surveys', + array( + 'method' => 'POST', + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'body' => wp_json_encode( $data ), + ) + ); + + // Check the API response. + if ( is_wp_error( $response ) ) { + wp_send_json_error( array( 'message' => 'Failed to submit data to the API.' ) ); + } + + // Handle API response. + $response_body = wp_remote_retrieve_body( $response ); + $api_response = json_decode( $response_body ); + + if ( $api_response && isset( $api_response->status ) && 'Created' === $api_response->status ) { + wp_send_json_success( array( 'message' => 'Thank you for your feedback!' ) ); + } else { + wp_send_json_error( array( 'message' => 'API error: ' . $api_response->message ) ); + } + } +} diff --git a/Root_Loader.php b/Root_Loader.php index 08e089fe3..914c7359d 100644 --- a/Root_Loader.php +++ b/Root_Loader.php @@ -79,6 +79,7 @@ public function __construct() { if ( is_admin() ) { $plugins[] = new Generic_Plugin_Admin(); $plugins[] = new Generic_Plugin_AdminNotices(); + $plugins[] = new Generic_Plugin_Survey(); $plugins[] = new BrowserCache_Plugin_Admin(); $plugins[] = new DbCache_Plugin_Admin(); $plugins[] = new UserExperience_Plugin_Admin(); diff --git a/inc/lightbox/exit_survey.php b/inc/lightbox/exit_survey.php new file mode 100644 index 000000000..1084fc3fe --- /dev/null +++ b/inc/lightbox/exit_survey.php @@ -0,0 +1,97 @@ + +
+
+

+

+ + +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + +
+ + +
+
+
+
diff --git a/pub/css/exit-survey.css b/pub/css/exit-survey.css new file mode 100644 index 000000000..40080ea0b --- /dev/null +++ b/pub/css/exit-survey.css @@ -0,0 +1,9 @@ +#w3tc-exit-survey-modal { + padding: 0 15px; +} +#w3tc-exit-survey-skip { + float: right; +} +#w3tc_exit_survey_uninstall_reason_other { + display: none; +} \ No newline at end of file diff --git a/pub/js/exit-survey.js b/pub/js/exit-survey.js new file mode 100644 index 000000000..e07ebc06e --- /dev/null +++ b/pub/js/exit-survey.js @@ -0,0 +1,123 @@ +/** + * Display the exit servey modal on plugin deactivation. + * + * @since X.X.X + */ +function w3tc_exit_survey_render() { + W3tc_Lightbox.open({ + id: 'w3tc-overlay', + maxWidth: 600, + maxHeight: 425, + url: ajaxurl + + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce + '&w3tc_action=exit_survey_render' + + (w3tc_ga_cid ? '&client_id=' + encodeURIComponent(w3tc_ga_cid) : ''), + callback: function(lightbox) { + // Retrieve the original deactivation URL + var deactivateUrl = jQuery('#deactivate-w3-total-cache').attr('href'); + + // Cancel button action + jQuery('#w3tc-exit-survey-skip', lightbox.container).on( 'click', function() { + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'button', + { + eventCategory: 'click', + eventLabel: 'exit_survey_skip' + } + ); + } + + // Close the lightbox + lightbox.close(); + // Proceed with plugin deactivation + window.location.href = deactivateUrl; + }); + + // Handle form submission + jQuery('#w3tc-exit-survey-form', lightbox.container).on('submit', function(event) { + event.preventDefault(); + + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'button', + { + eventCategory: 'click', + eventLabel: 'exit_survey_submit' + } + ); + } + + // Collect form data + var reason = jQuery('input[name="reason"]:checked', lightbox.container).val(); + var other = jQuery('input[name="other"]', lightbox.container).val(); + + // Build the params object + var params = { + action: 'w3tc_ajax', + _wpnonce: w3tc_nonce, + w3tc_action: 'exit_survey_submit', + reason: reason, + other: other + }; + + // Send the survey data to your API server + jQuery.post( ajaxurl, params, function(response) { + if(response.success) { + console.log(response); + alert(response.data.message); + lightbox.close(); + window.location.href = deactivateUrl; + } else { + alert(response.data.message); + } + }); + }); + + lightbox.resize(); + } + }); +} + +// On document ready. +jQuery(function() { + /** + * Trigger display of exit survey on plugin deactivation link click. + * + * @since X.X.X + */ + jQuery('#deactivate-w3-total-cache').on( 'click', function(e) { + e.preventDefault(); + + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'button', + { + eventCategory: 'click', + eventLabel: 'exit_survey_open' + } + ); + } + + w3tc_exit_survey_render(); + return false; + }); + + // Listen for changes on the radio buttons + jQuery(document).on('change', 'input[name="reason"]', function() { + // Enable Submit & Deactivate button once an option is selected + if (jQuery('input[name="reason"]:checked').length > 0) { + jQuery('#w3tc-exit-survey-submit').prop('disabled', false); + } + + // If the "Other" option is selected, show the text box + if (jQuery(this).val() === 'other') { + jQuery('#w3tc_exit_survey_uninstall_reason_other').show(); + } else { + jQuery('#w3tc_exit_survey_uninstall_reason_other').hide(); + jQuery('#w3tc_exit_survey_uninstall_reason_other').val(''); // Clear the "Other" input when not selected + } + }); +}); \ No newline at end of file From e259fc578f7b7f3b4b9fc2a774be9591d731e426 Mon Sep 17 00:00:00 2001 From: jacobd91 Date: Thu, 2 Jan 2025 11:27:16 -0500 Subject: [PATCH 2/2] Added data removal option to exit survey. --- Generic_Plugin_Survey.php | 5 +++++ Root_AdminActivation.php | 5 +++++ Root_Environment.php | 20 ++++++++++++++++++ inc/lightbox/exit_survey.php | 40 +++++++++++++++++++++++++----------- pub/js/exit-survey.js | 6 ++++-- 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/Generic_Plugin_Survey.php b/Generic_Plugin_Survey.php index bea9cf65e..9a2a4ea9b 100644 --- a/Generic_Plugin_Survey.php +++ b/Generic_Plugin_Survey.php @@ -125,6 +125,7 @@ public function w3tc_ajax_exit_survey_submit() { // Collect survey data. $uninstall_reason = sanitize_text_field( Util_Request::get_string( 'reason' ) ); $other_reason = sanitize_text_field( Util_Request::get_string( 'other' ) ); + $remove_data = sanitize_text_field( Util_Request::get_string( 'remove' ) ); // Prepare the data to send to the API. $data = array( @@ -162,6 +163,10 @@ public function w3tc_ajax_exit_survey_submit() { $api_response = json_decode( $response_body ); if ( $api_response && isset( $api_response->status ) && 'Created' === $api_response->status ) { + if ( 'yes' === $remove_data ) { + update_option( 'w3tc_remove_data', true ); + } + wp_send_json_success( array( 'message' => 'Thank you for your feedback!' ) ); } else { wp_send_json_error( array( 'message' => 'API error: ' . $api_response->message ) ); diff --git a/Root_AdminActivation.php b/Root_AdminActivation.php index 8ba10a6c8..160d9104d 100644 --- a/Root_AdminActivation.php +++ b/Root_AdminActivation.php @@ -140,5 +140,10 @@ public static function deactivate() { // Delete cron events. require_once __DIR__ . '/Extension_ImageService_Cron.php'; Extension_ImageService_Cron::delete_cron(); + + // Check if data cleanup is required. + if ( get_option( 'w3tc_remove_data' ) ) { + Root_Environment::delete_plugin_data(); + } } } diff --git a/Root_Environment.php b/Root_Environment.php index 39619bc2e..f464b38e6 100644 --- a/Root_Environment.php +++ b/Root_Environment.php @@ -203,4 +203,24 @@ public function get_other_instructions( $config ) { } return $instructions_descriptors; } + + /** + * Deletes all W3 Total Cache data from the database. + * + * phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery + * phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching + * + * @since X.X.X + * + * @return void + */ + public static function delete_plugin_data() { + global $wpdb; + + // Delete all options with the 'w3tc_' prefix. + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'w3tc_%'" ); + + // Delete all transients with the 'w3tc_' prefix. + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_w3tc_%' OR option_name LIKE '_transient_timeout_w3tc_%'" ); + } } diff --git a/inc/lightbox/exit_survey.php b/inc/lightbox/exit_survey.php index 1084fc3fe..d1174d9c9 100644 --- a/inc/lightbox/exit_survey.php +++ b/inc/lightbox/exit_survey.php @@ -10,71 +10,71 @@ ?>
-

-

-
+

+

+
@@ -87,6 +87,22 @@
+

+ +
+ +
+ +
+ +
+
diff --git a/pub/js/exit-survey.js b/pub/js/exit-survey.js index e07ebc06e..4ab049aa2 100644 --- a/pub/js/exit-survey.js +++ b/pub/js/exit-survey.js @@ -7,7 +7,7 @@ function w3tc_exit_survey_render() { W3tc_Lightbox.open({ id: 'w3tc-overlay', maxWidth: 600, - maxHeight: 425, + maxHeight: 485, url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce + '&w3tc_action=exit_survey_render' + (w3tc_ga_cid ? '&client_id=' + encodeURIComponent(w3tc_ga_cid) : ''), @@ -52,6 +52,7 @@ function w3tc_exit_survey_render() { // Collect form data var reason = jQuery('input[name="reason"]:checked', lightbox.container).val(); var other = jQuery('input[name="other"]', lightbox.container).val(); + var remove = jQuery('input[name="remove"]', lightbox.container).val(); // Build the params object var params = { @@ -59,7 +60,8 @@ function w3tc_exit_survey_render() { _wpnonce: w3tc_nonce, w3tc_action: 'exit_survey_submit', reason: reason, - other: other + other: other, + remove: remove }; // Send the survey data to your API server