PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.0.2
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.0.2
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 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 All 29 releases
xspeed / includes / modules / Cloudflare / CloudflareModule.php

CloudflareModule.php in xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN 1.0.2, at includes/modules/Cloudflare/CloudflareModule.php

216 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cloudflare module — connect a CF zone for purge + dev-mode toggles.
4 *
5 * Free tier (this module): API token / global key auth, zone
6 * verification, manual purge, auto purge on xSpeed's own purge, dev
7 * mode toggle.
8 *
9 * Pro tier (xspeed-pro): APO toggle, edge cache rules, edge cache TTL.
10 * Per FEATURES.md "Cloudflare Integration" §8-10.
11 *
12 * @package XSpeed
13 */
14
15 declare(strict_types=1);
16
17 namespace XSpeed\Modules\Cloudflare;
18
19 use XSpeed\Cloudflare;
20 use XSpeed\Module;
21
22 final class CloudflareModule extends Module {
23
24 public const SLUG = 'cloudflare';
25 public const TIER = self::TIER_FREE;
26 public const VERSION = '1.0.0';
27
28 public function ui_metadata(): array {
29 return array(
30 'label' => 'Cloudflare',
31 'icon' => 'Cloud',
32 'description' => 'Connect a Cloudflare zone for automatic edge purging when xSpeed clears its cache, plus a dev-mode toggle.',
33 'custom_panel' => 'CloudflarePanel',
34 );
35 }
36
37 public function settings_schema(): array {
38 return array(
39 'enabled' => array(
40 'type' => 'bool',
41 'default' => false,
42 'label' => 'Enable Cloudflare integration',
43 'description' => 'Use the credentials below to verify your zone and run purges.',
44 ),
45 'auth_method' => array(
46 'type' => 'enum',
47 'default' => 'token',
48 'options' => array( 'token', 'key' ),
49 'option_labels' => array(
50 'token' => 'API Token',
51 'key' => 'Global API Key',
52 ),
53 'label' => 'Authentication',
54 'description' => 'API Tokens (scoped, recommended) or the legacy Global API Key with your account email.',
55 ),
56 'api_token' => array(
57 'type' => 'string',
58 'default' => '',
59 'label' => 'API Token',
60 'description' => 'Create a token at dash.cloudflare.com → My Profile → API Tokens. Needs "Zone → Cache Purge" + "Zone Settings" permissions.',
61 ),
62 'email' => array(
63 'type' => 'string',
64 'default' => '',
65 'label' => 'Account Email',
66 'description' => 'Only used when Authentication is set to Global API Key.',
67 ),
68 'api_key' => array(
69 'type' => 'string',
70 'default' => '',
71 'label' => 'Global API Key',
72 'description' => 'Found at dash.cloudflare.com → My Profile → API Tokens → Global API Key.',
73 ),
74 'zone_id' => array(
75 'type' => 'string',
76 'default' => '',
77 'label' => 'Zone ID',
78 'description' => 'The 32-character hex Zone ID from your domain overview page.',
79 ),
80 'auto_purge_on_update' => array(
81 'type' => 'bool',
82 'default' => true,
83 'label' => 'Auto-purge Cloudflare on xSpeed purge',
84 'description' => 'When xSpeed clears its own cache (post save, settings change, manual purge), trigger a Cloudflare purge too.',
85 ),
86 );
87 }
88
89 public function rest_routes(): array {
90 $default = parent::rest_routes();
91 return array_merge(
92 $default,
93 array(
94 array(
95 'path' => '/verify',
96 'methods' => 'POST',
97 'callback' => array( $this, 'rest_verify' ),
98 ),
99 array(
100 'path' => '/purge',
101 'methods' => 'POST',
102 'callback' => array( $this, 'rest_purge' ),
103 ),
104 array(
105 'path' => '/dev-mode',
106 'methods' => 'POST',
107 'callback' => array( $this, 'rest_dev_mode' ),
108 ),
109 )
110 );
111 }
112
113 public function conflicts(): array {
114 return array(
115 array(
116 'plugin' => 'cloudflare/cloudflare.php',
117 'feature' => 'cloudflare.purge',
118 'strategy' => \XSpeed\Conflict_Registry::STRATEGY_WARN,
119 'reason' => 'The official Cloudflare plugin also auto-purges; keep auto-purge enabled in only one to avoid double API calls.',
120 ),
121 );
122 }
123
124 public function boot(): void {
125 $opts = $this->get_settings();
126 if ( empty( $opts['enabled'] ) ) {
127 return;
128 }
129 if ( ! empty( $opts['auto_purge_on_update'] ) ) {
130 // xSpeed fires this action whenever it purges its own
131 // cache (see Cache::purge_all). Listening here keeps
132 // CF in sync without any new wiring elsewhere.
133 add_action( 'xspeed_after_purge_all', array( $this, 'on_xspeed_purge' ), 10, 0 );
134 }
135 }
136
137 public function on_xspeed_purge(): void {
138 $opts = $this->get_settings();
139 if ( empty( $opts['enabled'] ) || empty( $opts['zone_id'] ) ) {
140 return;
141 }
142 $result = Cloudflare::purge_all( $opts );
143 if ( ! $result['ok'] && class_exists( '\\XSpeed\\Activity_Log' ) ) {
144 \XSpeed\Activity_Log::record(
145 'cloudflare_purge_failed',
146 'Cloudflare auto-purge failed: ' . ( $result['body']['message'] ?? 'unknown error' ),
147 \XSpeed\Activity_Log::WARN
148 );
149 }
150 }
151
152 public function rest_verify( \WP_REST_Request $request ) {
153 return rest_ensure_response( Cloudflare::verify( $this->get_settings() ) );
154 }
155
156 public function rest_purge( \WP_REST_Request $request ) {
157 $params = $request->get_json_params();
158 if ( ! is_array( $params ) ) {
159 $params = array();
160 }
161 $opts = $this->get_settings();
162 if ( isset( $params['urls'] ) && is_array( $params['urls'] ) && ! empty( $params['urls'] ) ) {
163 return rest_ensure_response( Cloudflare::purge_urls( $opts, $params['urls'] ) );
164 }
165 return rest_ensure_response( Cloudflare::purge_all( $opts ) );
166 }
167
168 public function rest_dev_mode( \WP_REST_Request $request ) {
169 $params = $request->get_json_params();
170 $on = ! empty( $params['on'] );
171 return rest_ensure_response( Cloudflare::set_dev_mode( $this->get_settings(), $on ) );
172 }
173
174 public function cli_commands(): array {
175 return array(
176 array(
177 'name' => 'xspeed cf',
178 'callback' => array( $this, 'cli_handler' ),
179 'shortdesc' => 'Cloudflare verify / purge / dev-mode helpers.',
180 'synopsis' => array(
181 array(
182 'type' => 'positional',
183 'name' => 'action',
184 'options' => array( 'verify', 'purge', 'dev-on', 'dev-off' ),
185 'optional' => false,
186 ),
187 ),
188 ),
189 );
190 }
191
192 public function cli_handler( array $args, array $assoc ): void {
193 $opts = $this->get_settings();
194 $action = $args[0] ?? 'verify';
195 switch ( $action ) {
196 case 'verify':
197 $res = Cloudflare::verify( $opts );
198 break;
199 case 'purge':
200 $res = Cloudflare::purge_all( $opts );
201 break;
202 case 'dev-on':
203 $res = Cloudflare::set_dev_mode( $opts, true );
204 break;
205 case 'dev-off':
206 $res = Cloudflare::set_dev_mode( $opts, false );
207 break;
208 default:
209 \WP_CLI::error( "Unknown action: $action" );
210 return;
211 }
212 \WP_CLI::log( 'HTTP ' . $res['status'] . '' . ( $res['ok'] ? 'ok' : 'failed' ) );
213 \WP_CLI::log( wp_json_encode( $res['body'] ) );
214 }
215 }
216