diff --git a/Extension_ImageService_Api.php b/Extension_ImageService_Api.php index 3bb7a323c..acf3021f7 100644 --- a/Extension_ImageService_Api.php +++ b/Extension_ImageService_Api.php @@ -15,16 +15,6 @@ * @since 2.2.0 */ class Extension_ImageService_Api { - /** - * API Base URL. - * - * @since 2.2.0 - * @access private - * - * @var string - */ - private $base_url = 'https://api2.w3-edge.com'; - /** * W3TC Pro license key. * @@ -137,7 +127,7 @@ public function convert( $filepath, array $options = array() ) { 'optimize' => $options['optimize'], ); - if ( ( defined( 'W3TC_PRO' ) && W3TC_PRO ) || ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE ) ) { + if ( Util_Environment::is_pro_constant( $config ) ) { $post_fields['pro_c'] = 1; } @@ -153,7 +143,7 @@ public function convert( $filepath, array $options = array() ) { // Send request. $response = wp_remote_request( - $this->get_base_url() . $this->endpoints['convert']['uri'], + Util_Environment::get_api_base_url() . $this->endpoints['convert']['uri'], array( 'method' => $this->endpoints['convert']['method'], 'sslverify' => false, @@ -254,7 +244,7 @@ public function convert( $filepath, array $options = array() ) { */ public function get_status( $job_id, $signature ) { $response = wp_remote_request( - $this->get_base_url() . $this->endpoints['status']['uri'] . '/' . $job_id . '/' . $signature, + Util_Environment::get_api_base_url() . $this->endpoints['status']['uri'] . '/' . $job_id . '/' . $signature, array( 'method' => $this->endpoints['status']['method'], 'sslverify' => false, @@ -295,7 +285,7 @@ public function get_status( $job_id, $signature ) { */ public function download( $job_id, $signature ) { $response = wp_remote_request( - $this->get_base_url() . $this->endpoints['download']['uri'] . '/' . $job_id . '/' . $signature, + Util_Environment::get_api_base_url() . $this->endpoints['download']['uri'] . '/' . $job_id . '/' . $signature, array( 'method' => $this->endpoints['download']['method'], 'sslverify' => false, @@ -356,7 +346,7 @@ public function get_usage( bool $refresh = false ): array { $response = wp_remote_request( esc_url( - $this->get_base_url() . $this->endpoints['usage']['uri'] . + Util_Environment::get_api_base_url() . $this->endpoints['usage']['uri'] . '/' . rawurlencode( $this->license_key ) . '/' . urlencode( $this->item_name ) . // phpcs:ignore '/' . rawurlencode( $this->home_url ) @@ -392,19 +382,6 @@ public function get_usage( bool $refresh = false ): array { } } - /** - * Get base URL. - * - * @since 2.2.0 - * @access private - * - * @returns string - */ - private function get_base_url() { - return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? - esc_url( W3TC_API2_URL, 'https', '' ) : $this->base_url; - } - /** * Update usage transient data. * diff --git a/Generic_Plugin_Admin.php b/Generic_Plugin_Admin.php index 79b8cebcc..950f43e6c 100644 --- a/Generic_Plugin_Admin.php +++ b/Generic_Plugin_Admin.php @@ -385,6 +385,24 @@ 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_enqueue_style( 'w3tc-exit-survey', plugins_url( 'pub/css/exit-survey.css', W3TC_FILE ), array(), W3TC_VERSION, false ); + wp_register_script( 'w3tc-exit-survey', plugins_url( 'pub/js/exit-survey.js', W3TC_FILE ), array(), W3TC_VERSION, false ); + wp_localize_script( + 'w3tc-exit-survey', + 'w3tcData', + array( + '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 +439,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 +469,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 ) { @@ -492,7 +515,7 @@ function w3tc_ga(){dataLayer.push(arguments);} 'w3tc_install_date': '', 'w3tc_pro': '_config ) ? 1 : 0; ?>', 'w3tc_has_key': '_config->get_string( 'plugin.license_key' ) ? 1 : 0; ?>', - 'w3tc_pro_c': '', + 'w3tc_pro_c': '', 'w3tc_enterprise_c': '', 'w3tc_plugin_type': '_config->get_string( 'plugin.type' ) ); ?>', } diff --git a/Generic_Plugin_Survey.php b/Generic_Plugin_Survey.php new file mode 100644 index 000000000..f59458fb8 --- /dev/null +++ b/Generic_Plugin_Survey.php @@ -0,0 +1,177 @@ +_config = Dispatcher::config(); + + if ( Util_Environment::is_w3tc_pro( $this->_config ) ) { + $this->license_key = $this->_config->get_string( 'plugin.license_key' ); + $this->item_name = W3TC_PURCHASE_PRODUCT_NAME; + } + + $this->home_url = network_home_url(); + } + + /** + * Runs plugin + * + * @since X.X.X + * + * @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' ) ); + } + + /** + * Renders the exit survey lightbox content + * + * @since X.X.X + * + * @return void + */ + public function w3tc_ajax_exit_survey_render() { + if ( ! \user_can( \get_current_user_id(), 'manage_options' ) ) { + return; + } + + // Verify nonce. + if ( ! wp_verify_nonce( Util_Request::get_string( '_wpnonce' ), 'w3tc' ) ) { + wp_send_json_error( array( 'message' => 'Invalid nonce.' ) ); + } + + include W3TC_INC_DIR . '/lightbox/exit_survey.php'; + } + + /** + * Processes the exit survey submission and sends it to the API. + * + * @since X.X.X + * + * @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' ) ); + $remove_data = sanitize_text_field( Util_Request::get_string( 'remove' ) ); + + // 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, + ); + + // Add 'other' to $data only if the uninstall reason is "other" and $other_reason is non-blank. + if ( 'other' === $uninstall_reason && ! empty( $other_reason ) ) { + $data['other'] = $other_reason; + } + + if ( Util_Environment::is_pro_constant( $this->_config ) ) { + $data['pro_c'] = 1; + } + + // Send the data to your API server using wp_remote_post. + $response = wp_remote_post( + Util_Environment::get_api_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 && 201 === wp_remote_retrieve_response_code( $response ) ) { + 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/Licensing_Plugin_Admin.php b/Licensing_Plugin_Admin.php index 5271c766e..268fe4505 100644 --- a/Licensing_Plugin_Admin.php +++ b/Licensing_Plugin_Admin.php @@ -157,7 +157,7 @@ function admin_notices() { $state = Dispatcher::config_state(); $status = $state->get_string( 'license.status' ); - if ( defined( 'W3TC_PRO' ) ) { + if ( Util_Environment::is_pro_constant( $this->_config ) ) { } elseif ( 'no_key' === $status ) { } elseif ( $this->_status_is( $status, 'inactive.expired' ) ) { $message = wp_kses( @@ -254,7 +254,7 @@ function w3tc_notes( $notes ) { $terms = ''; $state_master = Dispatcher::config_state_master(); - if ( defined( 'W3TC_PRO' ) ) { + if ( Util_Environment::is_pro_constant( $this->_config ) ) { $terms = 'accept'; } elseif ( ! Util_Environment::is_w3tc_pro( $this->_config ) ) { $terms = $state_master->get_string( 'license.community_terms' ); diff --git a/PageSpeed_Api.php b/PageSpeed_Api.php index 32d228bbb..9c09f93af 100644 --- a/PageSpeed_Api.php +++ b/PageSpeed_Api.php @@ -31,13 +31,6 @@ class PageSpeed_Api { */ public $client; - /** - * W3TC API server base URL. Overwritten by W3TC_API2_URL constant. - * - * @var string - */ - private $w3tc_api_base_url = 'https://api2.w3-edge.com'; - /** * Retry Attemps. Overwritten by W3TC_PAGESPEED_MAX_ATTEMPTS constant. * @@ -249,7 +242,7 @@ public function refresh_token( $site_id, $w3tc_pagespeed_key ) { return; } - $request = $this->get_w3tc_api_url( 'google/refresh-token' ) . '/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); + $request = Util_Environment::get_api_base_url() . '/google/refresh-token/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); $response = wp_remote_get( $request, @@ -334,21 +327,6 @@ public function get_pagespeed_url() { return defined( 'W3TC_PAGESPEED_API_URL' ) && W3TC_PAGESPEED_API_URL ? W3TC_PAGESPEED_API_URL : $this->pagespeed_api_base_url; } - /** - * Get W3TC API server URL target. - * - * @since 2.3.0 - * - * @param string $target API target URI. - * - * @return string - */ - public function get_w3tc_api_url( $target ) { - return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? - trailingslashit( W3TC_API2_URL ) . $target : - trailingslashit( $this->w3tc_api_base_url ) . $target; - } - /** * PageSpeed authorize admin notice. * @@ -401,7 +379,7 @@ public function reset() { return; } - $request = $this->get_w3tc_api_url( 'google/revoke-token' ) . '/' . rawurlencode( $access_token ) . '/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); + $request = Util_Environment::get_api_base_url() . '/google/revoke-token/' . rawurlencode( $access_token ) . '/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); $response = wp_remote_get( $request, 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..61a05f1e0 100644 --- a/Root_Environment.php +++ b/Root_Environment.php @@ -203,4 +203,47 @@ 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 + * phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log + * + * @since X.X.X + * + * @return void + */ + public static function delete_plugin_data() { + global $wpdb; + + // Define prefixes for options and transients. + $prefixes = array( + 'w3tc_', // General options prefix. + 'w3tcps_', // Additional options prefix. + '_transient_w3tc_', // Transient prefix. + '_transient_timeout_w3tc_', // Transient timeout prefix. + ); + + // Delete options and transients with defined prefixes. + foreach ( $prefixes as $prefix ) { + $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", + $prefix . '%' + ) + ); + } + + // Remove plugin-created directories. + $directories = array( + defined( 'W3TC_CACHE_DIR' ) ? W3TC_CACHE_DIR : WP_CONTENT_DIR . '/cache', + defined( 'W3TC_CONFIG_DIR' ) ? W3TC_CONFIG_DIR : WP_CONTENT_DIR . '/w3tc-config', + ); + + foreach ( $directories as $dir ) { + Util_File::rmdir( $dir ); + } + } } 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/SetupGuide_Plugin_Admin.php b/SetupGuide_Plugin_Admin.php index 8e6cd36ce..1c59aa909 100644 --- a/SetupGuide_Plugin_Admin.php +++ b/SetupGuide_Plugin_Admin.php @@ -894,7 +894,8 @@ public function config_imageservice() { * @return bool */ private function maybe_ask_tos() { - if ( defined( 'W3TC_PRO' ) ) { + $config = new Config(); + if ( Util_Environment::is_pro_constant( $config ) ) { return false; } diff --git a/Util_Environment.php b/Util_Environment.php index e1b792de5..e849465b0 100644 --- a/Util_Environment.php +++ b/Util_Environment.php @@ -1396,6 +1396,21 @@ public static function is_w3tc_pro_dev() { return defined( 'W3TC_PRO_DEV_MODE' ) && W3TC_PRO_DEV_MODE; } + /** + * Pro constants? + * + * @since X.X.X + * + * @static + * + * @param Config $config Config. + * + * @return bool + */ + public static function is_pro_constant( $config = null ) { + return ( defined( 'W3TC_PRO' ) && W3TC_PRO ) || ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE ); + } + /** * Quotes regular expression string. * @@ -1834,4 +1849,17 @@ protected static function get_cron_spawn() { return $result; } + + /** + * Gets the BoldGrid API URL + * + * This URL can be overridden by defining W3TC_API2_URL + * + * @since X.X.X + * + * @return string The API URL to use for requests. + */ + public static function get_api_base_url() { + return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? esc_url( W3TC_API2_URL, array( 'https' ), '' ) : 'https://api2.w3-edge.com'; + } } diff --git a/inc/lightbox/exit_survey.php b/inc/lightbox/exit_survey.php new file mode 100644 index 000000000..c413993bc --- /dev/null +++ b/inc/lightbox/exit_survey.php @@ -0,0 +1,72 @@ + +