PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.4.2
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.4.2
1.4.2 1.4.1 1.4.0 1.3.7 1.3.6 1.3.5 1.3.4 1.3.3 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 All 36 releases
← All changes | includes/class-plugin.php +70 -3 1.3.7 → 1.4.2 View file →
@@ -80,8 +80,11 @@
80 80 // Single-URL purge entry points — row actions, the edit-screen
81 81 // button and the admin-post handler the admin-bar item also uses.
82 82 Purge_Ui::boot();
83 83
84 + // While the page cache is off, every admin page says so (#594).
85 + Cache_Off_Notice::boot();
86 +
84 87 // Phase 0 architecture — managers + Free modules. v1 services
85 88 // (Cache/Minifier/Gzip) are NOT yet Modules; they'll be refactored
86 89 // in a follow-up PR with parity tests.
87 90 Conflict_Registry::boot();
@@ -103,8 +106,15 @@
103 106 // purge that runs after an import, which the nginx adapter's import
104 107 // gate stands down in favour of.
105 108 Server_Caches::boot();
106 109
110 + // Remembers the terms a post had before a save, so a narrow purge
111 + // can clear the category it left as well as the one it joined.
112 + Affected_Pages::boot();
113 + // Records which pages run a post list of their own (a page builder
114 + // grid, a related-posts block), so a narrow purge clears them too.
115 + Listing_Pages::boot();
116 +
107 117 // Tell WP Statistics and Slimstat not to count the warmer, the
108 118 // benchmark and the verifier as visitors. Record-time filters only;
109 119 // see the class for why the tracking snippet itself is left alone.
110 120 Self_Traffic::boot();
@@ -202,9 +212,40 @@
202 212 // outlives it: nothing purges on upgrade, and the static serve path
203 213 // never revalidates. Clear the tree once. The flat cache is keyed
204 214 // correctly and is deliberately left alone. (issue #191)
205 215 if ( version_compare( $current, '1.1.6', '<' ) ) {
206 - Cache::purge_static_tree();
216 + $removed = Cache::purge_static_tree();
217 +
218 + /*
219 + * And tell anything caching in front of us, because the poisoned
220 + * entry is exactly the kind that reaches an edge: the web server
221 + * served it straight off disk as the homepage, so a CDN in front had
222 + * every opportunity to store it. Deleting our copy leaves that one
223 + * untouched, and the edge's lifetime is the longer of the two.
224 + *
225 + * Announced on `init` rather than here. This runs at
226 + * `plugins_loaded` 21, before an add-on has wired its purge
227 + * listeners, so firing it inline would announce to an empty room.
228 + * Priority 99 puts it after any reasonable `init` registration.
229 + *
230 + * Once per site, on the upgrade that clears the tree — never again,
231 + * since the data version is written immediately below.
232 + *
233 + * Through `Cache::announce_purge()` rather than a bare `do_action`,
234 + * because the purge-event contract (#348) is more than the payload:
235 + * it forwards to the server caches by direct call before the public
236 + * action runs, and it isolates listeners so one throwing add-on
237 + * cannot fatal the first admin request after an update. A raw
238 + * publish here would skip both and hand listeners the pre-contract
239 + * payload shape.
240 + */
241 + add_action(
242 + 'init',
243 + static function () use ( $removed ) {
244 + Cache::announce_purge( 'static cache repaired on upgrade', $removed );
245 + },
246 + 99
247 + );
207 248 }
208 249
209 250 // 1.3.6 — new click and campaign IDs in the default ignored list.
210 251 // A site that ever saved the Cache panel has its own copy of the list,
@@ -490,8 +531,22 @@
490 531 * @param string $profile Settings::PROFILE_* — which profile a fresh
491 532 * install came up with, '' if not fresh.
492 533 */
493 534 do_action( 'xspeed_activated', $installed_by, $profile );
535 +
536 + /*
537 + * Announce the change to anything caching in front of us.
538 + *
539 + * Activation writes the default settings and activates modules, so
540 + * every URL on the site starts returning different HTML. A CDN
541 + * holding renders from before goes on serving them for their whole
542 + * lifetime, and nothing told it.
543 + *
544 + * Cheap on a fresh install — there is nothing to sweep — and the
545 + * case it exists for is reactivation on a site that has been running
546 + * for months behind an edge.
547 + */
548 + Cache::purge_all( 'plugin activated' );
494 549 }
495 550
496 551 /**
497 552 * Restore the cache drop-in right after THIS plugin is updated.
@@ -534,9 +589,14 @@
534 589
535 590 Cache::restore_dropin_if_enabled();
536 591 }
537 592
538 - public static function deactivate() {
593 + /**
594 + * @param bool $network_wide Whether a network admin deactivated the
595 + * plugin for every site (WordPress passes this
596 + * to deactivation hooks).
597 + */
598 + public static function deactivate( $network_wide = false ) {
539 599 // Drop-in + WP_CACHE constant are NOT touched here. WordPress
540 600 // upgrades run as deactivate → wipe files → install → activate,
541 601 // so removing those artifacts on every deactivate would silently
542 602 // disable caching after each plugin update. uninstall.php
@@ -543,9 +603,16 @@
543 603 // handles full teardown when the user actually removes the
544 604 // plugin; auto_heal() restores state on the next admin_init if
545 605 // the drop-in or WP_CACHE went missing for any other reason.
546 606 Cache::purge_all();
547 - Minifier::purge_minified();
607 + // purge_all() is site-scoped and no longer touches min/, so clear it
608 + // here. On a network where only this site is deactivating, the other
609 + // sites still link those files: drop this site's manifests only.
610 + if ( is_multisite() && ! $network_wide ) {
611 + Minifier::purge_manifests( Asset_Manifest::blog_id() );
612 + } else {
613 + Minifier::purge_minified();
614 + }
548 615 Gzip::apply( false );
549 616
550 617 Module_Registry::deactivate_all();
551 618 }