PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.0.4
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.0.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 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 All 29 releases
xspeed / includes / class-rest-api.php

class-rest-api.php in xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN 1.0.4, at includes/class-rest-api.php

219 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST API endpoints.
4 *
5 * @package XSpeed
6 */
7
8 namespace XSpeed;
9
10 defined( 'ABSPATH' ) || exit;
11
12 class Rest_Api {
13
14 const NAMESPACE_V1 = 'xspeed/v1';
15
16 public function __construct() {
17 add_action( 'rest_api_init', array( $this, 'register' ) );
18 }
19
20 public function register() {
21 register_rest_route(
22 self::NAMESPACE_V1,
23 '/status',
24 array(
25 'methods' => 'GET',
26 'callback' => array( $this, 'get_status' ),
27 'permission_callback' => array( $this, 'permissions' ),
28 )
29 );
30
31 register_rest_route(
32 self::NAMESPACE_V1,
33 '/settings',
34 array(
35 array(
36 'methods' => 'GET',
37 'callback' => array( $this, 'get_settings' ),
38 'permission_callback' => array( $this, 'permissions' ),
39 ),
40 array(
41 'methods' => 'POST',
42 'callback' => array( $this, 'update_settings' ),
43 'permission_callback' => array( $this, 'permissions' ),
44 ),
45 )
46 );
47
48 register_rest_route(
49 self::NAMESPACE_V1,
50 '/cache/purge',
51 array(
52 'methods' => 'POST',
53 'callback' => array( $this, 'purge' ),
54 'permission_callback' => array( $this, 'permissions' ),
55 )
56 );
57
58 register_rest_route(
59 self::NAMESPACE_V1,
60 '/cache/toggle',
61 array(
62 'methods' => 'POST',
63 'callback' => array( $this, 'toggle_cache' ),
64 'permission_callback' => array( $this, 'permissions' ),
65 )
66 );
67
68 register_rest_route(
69 self::NAMESPACE_V1,
70 '/cache/benchmark',
71 array(
72 'methods' => 'GET',
73 'callback' => array( $this, 'benchmark' ),
74 'permission_callback' => array( $this, 'permissions' ),
75 )
76 );
77
78 register_rest_route(
79 self::NAMESPACE_V1,
80 '/audit/pro',
81 array(
82 'methods' => 'GET',
83 'callback' => array( $this, 'pro_audit' ),
84 'permission_callback' => array( $this, 'permissions' ),
85 )
86 );
87
88 register_rest_route(
89 self::NAMESPACE_V1,
90 '/modules',
91 array(
92 'methods' => 'GET',
93 'callback' => array( $this, 'get_modules' ),
94 'permission_callback' => array( $this, 'permissions' ),
95 )
96 );
97 }
98
99 /**
100 * The registered-module descriptors — same payload baked into the
101 * admin bootstrap (Admin::modules_payload), re-evaluated live. The
102 * dashboard re-fetches this after a license activate/deactivate so a
103 * Pro module's custom_panel flips between its real surface and
104 * LicenseLockedPanel (decided server-side via the
105 * xspeed_module_descriptor filter) WITHOUT a full page reload.
106 */
107 public function get_modules() {
108 return rest_ensure_response( Admin::modules_payload() );
109 }
110
111 /**
112 * Run the Pro audit — scans current settings + cache stats,
113 * returns a personalized list of Pro features that would help
114 * THIS site. See Pro_Audit::run() for the rule set.
115 */
116 public function pro_audit( $request ) {
117 unset( $request );
118 return rest_ensure_response( array( 'suggestions' => Pro_Audit::run() ) );
119 }
120
121 /**
122 * Cache before/after benchmark — fetches home_url() twice (with +
123 * without the bypass header) and returns side-by-side timings for
124 * the dashboard widget.
125 */
126 public function benchmark( $request ) {
127 unset( $request );
128 return rest_ensure_response( Cache_Benchmark::run() );
129 }
130
131 public function permissions() {
132 return current_user_can( 'manage_options' );
133 }
134
135 public function get_status() {
136 $opts = Settings::get();
137 $stats = Cache::get_stats();
138
139 // rewrite_probe + nginx_server_block mirror the admin bootstrap
140 // payload (Admin::bootstrap_data). The dashboard re-fetches /status
141 // after every module save to refresh the consolidated nginx
142 // server-block snippet without a full page reload — if these were
143 // omitted here, the snippet would only ever update on reload (the
144 // QA bug: "Server config snippet requires full page reload to
145 // reflect toggle changes"). Keep this in sync with Admin.
146 $server_type = Server::type();
147 $rewrite_capable = ( $server_type === Server::NGINX || $server_type === Server::APACHE || $server_type === Server::LITESPEED );
148 $rewrite_probe = null;
149 if ( $opts['cache_enabled'] && $rewrite_capable ) {
150 $probe = Cache::probe_static_rewrite();
151 $rewrite_probe = array(
152 'active' => (bool) ( $probe['active'] ?? false ),
153 'server_type' => $server_type,
154 'snippet' => Cache::nginx_snippet(),
155 'topology' => Server::rewrite_topology(),
156 'behind_proxy' => Server::is_behind_proxy(),
157 );
158 }
159
160 return rest_ensure_response(
161 array(
162 'enabled' => (bool) $opts['cache_enabled'],
163 'stats' => $stats,
164 'server' => array(
165 'type' => $server_type,
166 'gzip_mode' => Server::gzip_mode(),
167 'gzip_active' => Gzip::probe_active(),
168 'nginx_snippet' => Gzip::nginx_snippet(),
169 ),
170 'rewrite_probe' => $rewrite_probe,
171 'nginx_server_block' => Cache::full_nginx_server_block(),
172 )
173 );
174 }
175
176 public function get_settings() {
177 return rest_ensure_response( Settings::get() );
178 }
179
180 public function update_settings( \WP_REST_Request $request ) {
181 $params = $request->get_json_params();
182 if ( ! is_array( $params ) ) {
183 $params = $request->get_params();
184 }
185 // `cache_enabled` is the trigger for drop-in install / wp-config.php
186 // edit and must only flow through the dedicated /cache/toggle
187 // endpoint. Strip it here so generic settings updates can never
188 // implicitly write a drop-in or modify wp-config.php.
189 unset( $params['cache_enabled'] );
190 $updated = Settings::update( $params );
191 return rest_ensure_response( $updated );
192 }
193
194 public function purge() {
195 Cache::purge_all();
196 return rest_ensure_response( array( 'stats' => Cache::get_stats() ) );
197 }
198
199 public function toggle_cache( \WP_REST_Request $request ) {
200 $params = $request->get_json_params();
201 $enabled = isset( $params['enabled'] ) ? (bool) $params['enabled'] : false;
202
203 // User-explicit drop-in install / wp-config.php edit happens here.
204 // permission_callback above already enforced current_user_can(
205 // 'manage_options' ); the REST nonce is verified by core via the
206 // X-WP-Nonce header.
207 $state = Cache::toggle( $enabled );
208 $updated = Settings::update( array( 'cache_enabled' => $state['enabled'] ) );
209
210 return rest_ensure_response(
211 array(
212 'enabled' => $updated['cache_enabled'],
213 'stats' => Cache::get_stats(),
214 'install_state' => $state,
215 )
216 );
217 }
218 }
219