PluginProbe
ezCache / trunk
ezCache vtrunk
2.6.5 2.6.4 2.6.2 2.6.3 2.6.1 2.6.0 2.5.6 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5 2.2.1 2.2.2 trunk 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.10 1.3.11 All 49 releases
ezcache / includes / Rest / SettingsController.php

SettingsController.php in ezCache trunk, at includes/Rest/SettingsController.php

255 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Upress\EzCache\Rest;
4
5 use Upress\EzCache\Settings;
6 use Upress\EzCache\PremiumFeatures;
7
8 class SettingsController {
9
10 /**
11 * Allowed settings keys (whitelist)
12 */
13 private static $allowed_keys = [
14 // Core cache settings
15 'no_cache_known_users', 'no_cache_comment_authors', 'separate_mobile_cache',
16 'cache_lifetime', 'cache_expiry_interval',
17 // Optimization
18 'disable_wp_emoji', 'optimize_google_fonts',
19 'minify_html', 'minify_html_comments', 'minify_inline_js', 'minify_inline_css',
20 'minify_js', 'combine_head_js', 'combine_body_js', 'combine_head_inline_js',
21 'combine_body_inline_js', 'minify_css', 'combine_css', 'combine_css_footer',
22 'critical_css', 'enable_webp_support',
23 // Cache behavior
24 'no_cache_query_params', 'cache_clear_on_post_edit', 'cache_clear_home_on_post_edit',
25 'enable_varnish_purge',
26 'ignore_query_params', 'ignored_query_params_list',
27 'bypass_cache', 'rejected_uri', 'rejected_user_agent', 'rejected_cookies',
28 'excluded_minify_files',
29 ];
30
31 /**
32 * Boolean settings keys
33 */
34 private static $boolean_keys = [
35 'no_cache_known_users', 'no_cache_comment_authors', 'separate_mobile_cache',
36 'disable_wp_emoji', 'optimize_google_fonts',
37 'minify_html', 'minify_html_comments', 'minify_inline_js', 'minify_inline_css',
38 'minify_js', 'combine_head_js', 'combine_body_js', 'combine_head_inline_js',
39 'combine_body_inline_js', 'minify_css', 'combine_css', 'combine_css_footer',
40 'enable_webp_support',
41 'no_cache_query_params', 'cache_clear_on_post_edit', 'cache_clear_home_on_post_edit',
42 'enable_varnish_purge',
43 'ignore_query_params',
44 ];
45
46 /**
47 * Integer settings keys with [min, max] ranges
48 */
49 private static $integer_keys = [
50 'cache_lifetime' => [ 0, 31536000 ],
51 'cache_expiry_interval' => [ 60, 86400 ],
52 ];
53
54 function show() {
55 $settings = Settings::get_settings();
56
57 return wp_send_json_success( $settings );
58 }
59
60 function update( $request ) {
61 $json = $request->get_json_params();
62 $updated_settings = [];
63
64 foreach ( $json as $key => $value ) {
65 // Only allow known settings keys
66 if ( ! in_array( $key, self::$allowed_keys, true ) ) {
67 continue;
68 }
69 $updated_settings[ $key ] = self::sanitize_setting( $key, $value );
70 }
71
72 // Strip premium features for free users
73 if ( ! PremiumFeatures::is_premium() ) {
74 $premium = PremiumFeatures::get_premium_features();
75 foreach ( $premium as $key ) {
76 unset( $updated_settings[ $key ] );
77 }
78 }
79
80 Settings::set_settings( $updated_settings );
81
82 return wp_send_json_success( Settings::get_settings() );
83 }
84
85 function destroy() {
86 $default_settings = (array) Settings::get_default_settings();
87 Settings::set_settings( $default_settings );
88
89 return wp_send_json_success( Settings::get_settings() );
90 }
91
92 // ── Dev Mode ──────────────────────────────────────────
93
94 function devModeStatus() {
95 $status = \Upress\EzCache\Cache::get_dev_mode_status();
96 return wp_send_json_success( $status );
97 }
98
99 function enableDevMode( $request ) {
100 $duration = $request->get_param( 'duration' );
101 if ( $duration === 'permanent' || $duration === '0' ) {
102 $seconds = 0;
103 } else {
104 $seconds = max( (int) $duration, 3600 );
105 }
106 \Upress\EzCache\Cache::enable_dev_mode( $seconds );
107 return wp_send_json_success( [ 'active' => true, 'message' => 'Development mode enabled' ] );
108 }
109
110 function disableDevMode() {
111 \Upress\EzCache\Cache::disable_dev_mode();
112 return wp_send_json_success( [ 'active' => false, 'message' => 'Development mode disabled' ] );
113 }
114
115 // ── Diagnostics ──────────────────────────────────────
116
117 function diagnose( $request ) {
118 $site_url = home_url();
119
120 // Call Go diagnostic API
121 $response = wp_remote_post( 'https://api.ezcache-wp.com/analyze', [
122 'headers' => [ 'Content-Type' => 'application/json' ],
123 'body' => json_encode( [ 'url' => $site_url ] ),
124 'timeout' => 20,
125 ] );
126
127 if ( is_wp_error( $response ) ) {
128 return new \WP_Error( 'diag_error', $response->get_error_message(), [ 'status' => 500 ] );
129 }
130
131 $data = json_decode( wp_remote_retrieve_body( $response ), true );
132 return wp_send_json_success( $data );
133 }
134
135 // ── Settings Backup/Restore ──────────────────────────
136
137 private function get_backup_dir() {
138 $dir = WP_CONTENT_DIR . '/ezcache-backups';
139 if ( ! is_dir( $dir ) ) {
140 wp_mkdir_p( $dir );
141 file_put_contents( $dir . '/.htaccess', 'Deny from all' );
142 file_put_contents( $dir . '/index.php', '<?php // Silence is golden' );
143 }
144 return $dir;
145 }
146
147 function listBackups() {
148 $dir = $this->get_backup_dir();
149 $files = glob( $dir . '/*.json' );
150 $backups = [];
151
152 foreach ( $files as $file ) {
153 $content = json_decode( file_get_contents( $file ), true );
154 $backups[] = [
155 'filename' => basename( $file ),
156 'name' => isset( $content['name'] ) ? $content['name'] : basename( $file, '.json' ),
157 'created_at' => isset( $content['created_at'] ) ? $content['created_at'] : date( 'Y-m-d H:i:s', filemtime( $file ) ),
158 'size' => filesize( $file ),
159 ];
160 }
161
162 usort( $backups, function( $a, $b ) { return strcmp( $b['created_at'], $a['created_at'] ); } );
163
164 return wp_send_json_success( $backups );
165 }
166
167 function createBackup( $request ) {
168 $name = sanitize_text_field( $request->get_param( 'name' ) );
169 if ( empty( $name ) ) {
170 $name = 'Backup ' . date( 'Y-m-d H:i' );
171 }
172
173 $settings = \Upress\EzCache\Settings::get_settings();
174 $backup = [
175 'name' => $name,
176 'created_at' => date( 'Y-m-d H:i:s' ),
177 'version' => defined( 'EZCACHE_VERSION' ) ? EZCACHE_VERSION : '2.5.1',
178 'site_url' => home_url(),
179 'settings' => $settings,
180 ];
181
182 $dir = $this->get_backup_dir();
183 $filename = sanitize_file_name( strtolower( str_replace( ' ', '-', $name ) ) ) . '-' . date( 'Ymd-His' ) . '.json';
184 file_put_contents( $dir . '/' . $filename, json_encode( $backup, JSON_PRETTY_PRINT ) );
185
186 return wp_send_json_success( [
187 'filename' => $filename,
188 'message' => 'Backup created: ' . $name,
189 ] );
190 }
191
192 function restoreBackup( $request ) {
193 $filename = sanitize_file_name( $request->get_param( 'filename' ) );
194
195 // Handle file upload
196 $upload = $request->get_param( 'settings_json' );
197 if ( ! empty( $upload ) ) {
198 $backup = json_decode( $upload, true );
199 } else {
200 $dir = $this->get_backup_dir();
201 $filepath = $dir . '/' . $filename;
202
203 if ( ! file_exists( $filepath ) ) {
204 return new \WP_Error( 'not_found', 'Backup file not found', [ 'status' => 404 ] );
205 }
206
207 $backup = json_decode( file_get_contents( $filepath ), true );
208 }
209
210 if ( empty( $backup['settings'] ) ) {
211 return new \WP_Error( 'invalid_backup', 'Invalid backup file', [ 'status' => 400 ] );
212 }
213
214 \Upress\EzCache\Settings::set_settings( (array) $backup['settings'] );
215
216 return wp_send_json_success( [
217 'message' => 'Settings restored from: ' . ( $backup['name'] ?? $filename ),
218 'settings' => \Upress\EzCache\Settings::get_settings(),
219 ] );
220 }
221
222 /**
223 * Sanitize a single setting value based on its key
224 */
225 private static function sanitize_setting( $key, $value ) {
226 // Boolean fields
227 if ( in_array( $key, self::$boolean_keys, true ) ) {
228 return (bool) $value;
229 }
230
231 // Integer fields with range
232 if ( isset( self::$integer_keys[ $key ] ) ) {
233 [ $min, $max ] = self::$integer_keys[ $key ];
234 return max( $min, min( $max, (int) $value ) );
235 }
236
237 // bypass_cache is an associative array of booleans
238 if ( $key === 'bypass_cache' && is_array( $value ) ) {
239 $allowed_bypass = [ 'single', 'pages', 'frontpage', 'home', 'archives', 'tag', 'category', 'feed', 'search', 'author' ];
240 $sanitized = [];
241 foreach ( $allowed_bypass as $bypass_key ) {
242 $sanitized[ $bypass_key ] = isset( $value[ $bypass_key ] ) ? (bool) $value[ $bypass_key ] : false;
243 }
244 return $sanitized;
245 }
246
247 // Text/textarea fields
248 if ( is_string( $value ) ) {
249 return sanitize_textarea_field( $value );
250 }
251
252 return $value;
253 }
254 }
255