PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.2.22
MxChat – AI Chatbot & Content Generation for WordPress v3.2.22
3.2.25 3.2.24 3.2.23 3.2.22 3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 All 156 releases
mxchat-basic / includes / class-mxchat-cache-purge.php

class-mxchat-cache-purge.php in MxChat – AI Chatbot & Content Generation for WordPress 3.2.22, at includes/class-mxchat-cache-purge.php

141 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) {
3 exit;
4 }
5
6 /**
7 * MxChat_Cache_Purge — purges known full-page caches when MxChat settings save.
8 *
9 * Widget settings are printed inline into page HTML (wp_localize_script in
10 * class-mxchat-integrator.php), so a full-page cache keeps serving the old
11 * snapshot after an admin changes a setting — toggles look broken until the
12 * cache is cleared by hand. This module clears the page caches we can reach
13 * from PHP the moment mxchat_options is written, using each cache plugin's
14 * own public purge API (guarded by existence checks, so absent plugins are
15 * a no-op). Companion to the 3.2.6 page-cache compatibility filters in
16 * mxchat-basic.php, which keep the chat AJAX endpoints out of those same
17 * caches; this handles the cached page HTML itself.
18 *
19 * Host-level caches and CDNs (Cloudflare APO etc.) cannot be purged from
20 * PHP — for those, the widget re-fetches its behavior settings when opened
21 * (see MxChat_Integrator::get_dynamic_widget_settings()).
22 *
23 * Debounce: the admin screen autosaves per field, so a settings session can
24 * write mxchat_options many times in a minute. We purge at most once per
25 * DEBOUNCE_SECONDS; writes that land inside the window schedule one deferred
26 * purge via wp-cron so the final state always gets flushed.
27 *
28 * @since 3.2.9 (plan-32db95)
29 */
30 class MxChat_Cache_Purge {
31
32 const DEBOUNCE_TRANSIENT = 'mxchat_cache_purge_debounce';
33 const DEBOUNCE_SECONDS = 30;
34 const DEFERRED_EVENT = 'mxchat_deferred_cache_purge';
35
36 private static $instance = null;
37
38 /**
39 * Whether this request already queued a shutdown purge (one per request).
40 *
41 * @var bool
42 */
43 private $purge_queued = false;
44
45 public static function init() {
46 if (self::$instance === null) {
47 self::$instance = new self();
48 }
49 return self::$instance;
50 }
51
52 private function __construct() {
53 foreach ($this->watched_options() as $option_name) {
54 add_action('update_option_' . $option_name, array($this, 'queue_purge'), 10, 0);
55 add_action('add_option_' . $option_name, array($this, 'queue_purge'), 10, 0);
56 }
57 add_action(self::DEFERRED_EVENT, array($this, 'purge_page_caches'));
58 }
59
60 /**
61 * Option names whose writes trigger a page-cache purge.
62 *
63 * Defaults cover every option whose values reach the cached page's inline
64 * widget payload: mxchat_options (settings/behavior gates),
65 * mxchat_theme_options (active AI theme CSS + bot theme assignments —
66 * written only by the MxChat Theme add-on's admin AJAX actions), and
67 * mxchat_prompts_options (Pinecone toggle — written only by the prompts
68 * autosave). All write sites are admin-action-driven; the debounce
69 * absorbs back-to-back writes like apply-and-save.
70 *
71 * @return string[]
72 */
73 private function watched_options() {
74 $defaults = array('mxchat_options', 'mxchat_theme_options', 'mxchat_prompts_options');
75 $options = apply_filters('mxchat_cache_purge_watched_options', $defaults);
76 return is_array($options) ? array_filter(array_map('strval', $options)) : $defaults;
77 }
78
79 /**
80 * Coalesce all option writes in this request into one shutdown purge.
81 */
82 public function queue_purge() {
83 if ($this->purge_queued) {
84 return;
85 }
86 $this->purge_queued = true;
87 add_action('shutdown', array($this, 'run_queued_purge'), 5);
88 }
89
90 /**
91 * Shutdown handler: purge unless one ran inside the debounce window; in
92 * that case schedule a single deferred purge so the last write still wins.
93 */
94 public function run_queued_purge() {
95 if (get_transient(self::DEBOUNCE_TRANSIENT)) {
96 if (!wp_next_scheduled(self::DEFERRED_EVENT)) {
97 wp_schedule_single_event(time() + self::DEBOUNCE_SECONDS, self::DEFERRED_EVENT);
98 }
99 return;
100 }
101 set_transient(self::DEBOUNCE_TRANSIENT, 1, self::DEBOUNCE_SECONDS);
102 $this->purge_page_caches();
103 }
104
105 /**
106 * Purge every supported page cache via its own public API. Each call is
107 * guarded so installs without that plugin skip it silently.
108 */
109 public function purge_page_caches() {
110 // WP Rocket — public helper, clears the whole domain's page cache.
111 if (function_exists('rocket_clean_domain')) {
112 rocket_clean_domain();
113 }
114
115 // LiteSpeed Cache — documented third-party purge API.
116 if (defined('LSCWP_V') || class_exists('LiteSpeed\Core')) {
117 do_action('litespeed_purge_all');
118 }
119
120 // W3 Total Cache — page-cache flush helper.
121 if (function_exists('w3tc_pgcache_flush')) {
122 w3tc_pgcache_flush();
123 }
124
125 // WP Super Cache — global cache clear.
126 if (function_exists('wp_cache_clear_cache')) {
127 wp_cache_clear_cache();
128 }
129
130 // FlyingPress — documented programmatic purge (purge_pages clears the
131 // HTML page cache without rebuilding optimized assets):
132 // https://docs.flyingpress.com/en/articles/11406092-programmatically-purge-and-preload-cache
133 if (class_exists('\FlyingPress\Purge') && method_exists('\FlyingPress\Purge', 'purge_pages')) {
134 \FlyingPress\Purge::purge_pages();
135 }
136
137 // Extension point for CDNs / host caches / custom setups.
138 do_action('mxchat_purge_page_caches');
139 }
140 }
141