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