PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.4.1
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.4.1
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 1.1.2 All 35 releases
← All changes | includes/modules/Cloudflare/CloudflareModule.php +37 -22 1.3.5 → 1.4.1 View file →
@@ -75,10 +75,11 @@
75 75 public function ui_metadata(): array {
76 76 return array(
77 77 'label' => __( 'Cloudflare', 'xspeed' ),
78 78 'icon' => 'Cloud',
79 - 'description' => __( 'Connect a Cloudflare zone for automatic edge purging when xSpeed clears its cache, plus a dev-mode toggle.', 'xspeed' ),
79 + 'description' => __( 'Clear the Cloudflare cache whenever xSpeed clears its own cache.', 'xspeed' ),
80 80 'custom_panel' => 'CloudflarePanel',
81 + 'group' => 'network',
81 82 );
82 83 }
83 84
84 85 /**
@@ -98,10 +99,10 @@
98 99 return array(
99 100 'enabled' => array(
100 101 'type' => 'bool',
101 102 'default' => false,
102 - 'label' => __( 'Enable Cloudflare integration', 'xspeed' ),
103 - 'description' => __( 'Use the credentials below to verify your zone and run purges.', 'xspeed' ),
103 + 'label' => __( 'Connect Cloudflare', 'xspeed' ),
104 + 'description' => __( 'Lets xSpeed clear the Cloudflare cache for your domain, using the details below.', 'xspeed' ),
104 105 ),
105 106 'auth_method' => array(
106 107 'type' => 'enum',
107 108 'default' => 'token',
@@ -110,9 +111,9 @@
110 111 'token' => 'API Token',
111 112 'key' => 'Global API Key',
112 113 ),
113 114 'label' => __( 'Authentication', 'xspeed' ),
114 - 'description' => __( 'API Tokens (scoped, recommended) or the legacy Global API Key with your account email.', 'xspeed' ),
115 + 'description' => __( 'An API token is safer and recommended. The older Global API Key also needs your account email.', 'xspeed' ),
115 116 'dependsOn' => array( 'field' => 'enabled' ),
116 117 ),
117 118 'api_token' => array(
118 119 'type' => 'secret',
@@ -117,9 +118,9 @@
117 118 'api_token' => array(
118 119 'type' => 'secret',
119 120 'default' => '',
120 121 'label' => __( 'API Token', 'xspeed' ),
121 - 'description' => __( 'Create a token at dash.cloudflare.com → My Profile → API Tokens. Needs "Zone → Cache Purge" + "Zone Settings" permissions.', 'xspeed' ),
122 + 'description' => __( 'Create one at dash.cloudflare.com → My Profile → API Tokens. Give it the "Zone → Cache Purge" and "Zone Settings" permissions.', 'xspeed' ),
122 123 // Only the token auth branch (and only while CF is enabled, via
123 124 // the transitive gate on auth_method → enabled).
124 125 'dependsOn' => array( 'field' => 'auth_method', 'value' => 'token' ),
125 126 ),
@@ -125,10 +126,10 @@
125 126 ),
126 127 'email' => array(
127 128 'type' => 'string',
128 129 'default' => '',
129 - 'label' => __( 'Account Email', 'xspeed' ),
130 - 'description' => __( 'Only used when Authentication is set to Global API Key.', 'xspeed' ),
130 + 'label' => __( 'Account email', 'xspeed' ),
131 + 'description' => __( 'The email address of your Cloudflare account.', 'xspeed' ),
131 132 'dependsOn' => array( 'field' => 'auth_method', 'value' => 'key' ),
132 133 ),
133 134 'api_key' => array(
134 135 'type' => 'secret',
@@ -133,9 +134,9 @@
133 134 'api_key' => array(
134 135 'type' => 'secret',
135 136 'default' => '',
136 137 'label' => __( 'Global API Key', 'xspeed' ),
137 - 'description' => __( 'Found at dash.cloudflare.com → My Profile → API Tokens → Global API Key.', 'xspeed' ),
138 + 'description' => __( 'Find it at dash.cloudflare.com → My Profile → API Tokens → Global API Key.', 'xspeed' ),
138 139 'dependsOn' => array( 'field' => 'auth_method', 'value' => 'key' ),
139 140 ),
140 141 'zone_id' => array(
141 142 'type' => 'string',
@@ -140,16 +141,16 @@
140 141 'zone_id' => array(
141 142 'type' => 'string',
142 143 'default' => '',
143 144 'label' => __( 'Zone ID', 'xspeed' ),
144 - 'description' => __( 'The 32-character hex Zone ID from your domain overview page.', 'xspeed' ),
145 + 'description' => __( 'The 32-character Zone ID shown on your domain overview page in Cloudflare.', 'xspeed' ),
145 146 'dependsOn' => array( 'field' => 'enabled' ),
146 147 ),
147 148 'auto_purge_on_update' => array(
148 149 'type' => 'bool',
149 150 'default' => true,
150 - 'label' => __( 'Auto-purge Cloudflare on xSpeed purge', 'xspeed' ),
151 - 'description' => __( 'When xSpeed clears its own cache (post save, settings change, manual purge), trigger a Cloudflare purge too.', 'xspeed' ),
151 + 'label' => __( 'Clear Cloudflare with xSpeed', 'xspeed' ),
152 + 'description' => __( 'Clear the Cloudflare cache each time xSpeed clears its own, for example after you save a post.', 'xspeed' ),
152 153 'dependsOn' => array( 'field' => 'enabled' ),
153 154 ),
154 155 );
155 156 }
@@ -248,8 +249,14 @@
248 249 $opts = $this->get_settings();
249 250 if ( empty( $opts['enabled'] ) ) {
250 251 return;
251 252 }
253 + // Something else on the site is already the Cloudflare layer in front
254 + // of it. The switch stays as the owner left it, and this zone is not
255 + // purged while the block lasts. See Module::blocked_by().
256 + if ( null !== $this->blocked_by() ) {
257 + return;
258 + }
252 259 if ( ! empty( $opts['auto_purge_on_update'] ) ) {
253 260 // xSpeed fires this action whenever it purges its own
254 261 // cache (see Cache::purge_all). Listening here keeps
255 262 // CF in sync without any new wiring elsewhere.
@@ -284,11 +291,12 @@
284 291
285 292 /**
286 293 * Mirror a single-URL purge at the edge.
287 294 *
288 - * NOT about post edits — `on_save_post()` calls `purge_all()`, so those
289 - * have always reached Cloudflare through the full-purge listener above.
290 - * What reaches `purge_url()` is the narrower set: the two admin purge
295 + * Post edits arrive here too when they clear only their affected pages
296 + * (`Cache::purge_urls()` publishes one event with every URL); an edit
297 + * that clears the whole site comes through the full-purge listener
298 + * above. What else reaches `purge_url()` is the narrower set: the two admin purge
291 299 * buttons, an approved comment, a user change, a WooCommerce product or
292 300 * stock change, `--url` on the CLI and REST, and MCP. Every one of those
293 301 * cleared xSpeed's copy and left Cloudflare's, so the page stayed stale
294 302 * at the edge until its lifetime ran out or somebody pressed Purge All —
@@ -320,11 +328,11 @@
320 328 if ( true !== $this->can_purge_edge() ) {
321 329 return;
322 330 }
323 331
324 - // Collected and sent once, not one API call per URL. `Purge_Ui`'s
325 - // post purge and the WooCommerce product path both fire a handful of
326 - // these in a loop, and a round trip each would be a wait each.
332 + // Collected and sent once, not one API call per URL. A request can
333 + // raise several of these (a bulk edit, a stock change on each item
334 + // of an order), and a round trip each would be a wait each.
327 335 if ( array() === $this->pending_edge_urls ) {
328 336 add_action( 'shutdown', array( $this, 'flush_edge_url_purges' ), 20 );
329 337 }
330 338 $blog = function_exists( 'get_current_blog_id' ) ? (int) get_current_blog_id() : 0;
@@ -330,8 +338,9 @@
330 338 $blog = function_exists( 'get_current_blog_id' ) ? (int) get_current_blog_id() : 0;
331 339 foreach ( $urls as $url ) {
332 340 $this->pending_edge_urls[ $blog ][ $url ] = true;
333 341 }
342 + \XSpeed\Cache::note_purge_forwarded( 'Cloudflare' );
334 343 }
335 344
336 345 /**
337 346 * Hand whatever `on_xspeed_purge_url()` collected to cron.
@@ -604,8 +613,12 @@
604 613 $opts = $this->get_settings();
605 614 if ( empty( $opts['enabled'] ) ) {
606 615 return __( 'the Cloudflare integration is switched off', 'xspeed' );
607 616 }
617 + $blocked = $this->blocked_by();
618 + if ( null !== $blocked ) {
619 + return $blocked;
620 + }
608 621 if ( ! $this->has_credentials( $opts ) ) {
609 622 return __( 'no zone ID or API credentials are configured', 'xspeed' );
610 623 }
611 624
@@ -673,17 +686,19 @@
673 686 * Persist any settings sent with the save, then verify the credentials
674 687 * immediately so an invalid or newly-changed token surfaces on the panel
675 688 * instead of failing silently the next time xSpeed purges. Response shape
676 689 * is unchanged (flat settings) so the autosave client is unaffected. (#119)
690 + *
691 + * The parent writes the settings, so its licence, blocked-by and
692 + * wp-config refusals apply here too; a refused write is not verified.
677 693 */
678 694 public function rest_update_settings( \WP_REST_Request $request ) {
679 - $params = $request->get_json_params();
680 - if ( ! is_array( $params ) ) {
681 - $params = $request->get_params();
695 + $response = parent::rest_update_settings( $request );
696 + if ( is_wp_error( $response ) ) {
697 + return $response;
682 698 }
683 - $settings = $this->update_settings( is_array( $params ) ? $params : array() );
684 699 $this->verify_and_record();
685 - return rest_ensure_response( $settings );
700 + return $response;
686 701 }
687 702
688 703 public function rest_verify( \WP_REST_Request $request ) {
689 704 $res = Cloudflare::verify( $this->get_settings() );