PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.1.6
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.1.6
1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.2.0 All 28 releases
xspeed / uninstall.php

uninstall.php in xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN 1.1.6, at uninstall.php

113 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Uninstall handler — deletes options, cache, and drop-in.
4 *
5 * @package XSpeed
6 */
7
8 if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
9 exit;
10 }
11
12 xspeed_uninstall_cleanup();
13
14 /**
15 * Run all uninstall cleanup. Wrapped in a function so locals don't pollute global scope.
16 */
17 function xspeed_uninstall_cleanup() {
18 delete_option( 'xspeed_options' );
19 delete_option( 'xspeed_stats' );
20 delete_option( 'xspeed_gc_cursor' );
21 wp_clear_scheduled_hook( 'xspeed_gc' );
22
23 // Score history — the plugin's own table, plus the legacy option the
24 // table was migrated from (kept on upgrade so a bad migration is
25 // recoverable; there is nothing to recover on uninstall).
26 global $wpdb;
27 // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- own table, uninstall.
28 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'xspeed_scores' );
29 delete_option( 'xspeed_score_schema' );
30 delete_option( 'xspeed_score_history' );
31
32 if ( ! function_exists( 'WP_Filesystem' ) ) {
33 require_once ABSPATH . 'wp-admin/includes/file.php';
34 }
35 WP_Filesystem();
36 global $wp_filesystem;
37 if ( ! $wp_filesystem ) {
38 return;
39 }
40
41 $cache_dir = WP_CONTENT_DIR . '/cache/xspeed';
42 if ( $wp_filesystem->is_dir( $cache_dir ) ) {
43 $wp_filesystem->delete( $cache_dir, true );
44 }
45
46 // nginx hit log (FBS-82478). It lives under uploads/xspeed/, NOT the
47 // cache dir, precisely so that a pasted nginx `access_log` directive
48 // pointing at it does NOT get its parent directory deleted here — if it
49 // did, `nginx -t` would fail [emerg] and refuse to (re)start, taking
50 // down EVERY vhost on the host until someone manually finds the orphaned
51 // directive. We therefore EMPTY the log file but DELIBERATELY LEAVE THE
52 // DIRECTORY in place, so any still-pasted directive keeps a valid,
53 // openable target after the plugin is gone. (A stray empty dir is
54 // harmless; a broken nginx is not.) Users are also warned in the admin
55 // UI to remove the snippet before uninstalling.
56 $hits_log = WP_CONTENT_DIR . '/uploads/xspeed/hits.log';
57 if ( function_exists( 'wp_upload_dir' ) ) {
58 $uploads = wp_upload_dir( null, false );
59 if ( is_array( $uploads ) && empty( $uploads['error'] ) && ! empty( $uploads['basedir'] ) ) {
60 $hits_log = rtrim( (string) $uploads['basedir'], '/' ) . '/xspeed/hits.log';
61 }
62 }
63 if ( $wp_filesystem->exists( $hits_log ) ) {
64 // Truncate, don't delete the dir — keep the access_log target openable.
65 $wp_filesystem->put_contents( $hits_log, '', FS_CHMOD_FILE );
66 }
67
68 // Static-cache tree — separate from the flat-hash cache dir, holds
69 // the {host}/{path}/index.html files the .htaccess rewrite block
70 // serves directly. Same teardown rules as XSPEED_CACHE_DIR.
71 $static_dir = WP_CONTENT_DIR . '/cache/xspeed-static';
72 if ( $wp_filesystem->is_dir( $static_dir ) ) {
73 $wp_filesystem->delete( $static_dir, true );
74 }
75
76 // Rewrite block in site-root .htaccess. WP's marker helpers handle
77 // the "remove only our block" semantics — passing an empty array
78 // strips the markers in place.
79 $htaccess = ABSPATH . '.htaccess';
80 if ( $wp_filesystem->exists( $htaccess ) && $wp_filesystem->is_writable( $htaccess ) ) {
81 if ( ! function_exists( 'insert_with_markers' ) ) {
82 require_once ABSPATH . 'wp-admin/includes/misc.php';
83 }
84 insert_with_markers( $htaccess, 'xSpeed Static Cache', array() );
85 }
86
87 $drop_in = WP_CONTENT_DIR . '/advanced-cache.php';
88 if ( $wp_filesystem->exists( $drop_in ) ) {
89 $contents = $wp_filesystem->get_contents( $drop_in );
90 if ( is_string( $contents ) && false !== strpos( $contents, 'XSPEED_DROPIN' ) ) {
91 $wp_filesystem->delete( $drop_in );
92 }
93 }
94
95 $wp_config = ABSPATH . 'wp-config.php';
96 // `defined()` alone, not `&& WP_CACHE`: the old truthiness test skipped
97 // the removal whenever the constant was false/0 — exactly the orphan we
98 // are here to clean up — while still entering it for TRUE/1, where the
99 // hardcoded-lowercase regex then matched nothing and reported success.
100 // Strip whatever spelling is there. (#9)
101 if ( defined( 'WP_CACHE' ) && $wp_filesystem->is_writable( $wp_config ) ) {
102 $config = $wp_filesystem->get_contents( $wp_config );
103 if ( is_string( $config ) ) {
104 // Same helper Cache::set_wp_cache_constant() uses — one pattern,
105 // one place. uninstall.php loads no plugin classes, hence a
106 // plain requirable function rather than a method.
107 require_once __DIR__ . '/includes/wp-cache-constant.php';
108 $config = xspeed_strip_wp_cache_define( $config );
109 $wp_filesystem->put_contents( $wp_config, $config, FS_CHMOD_FILE );
110 }
111 }
112 }
113