PluginProbe
ezCache / 2.5.3
ezCache v2.5.3
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 2.5.3, at includes/Rest/SettingsController.php

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