PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / trunk
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score vtrunk
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
← All changes | includes/admin/dashboard.php +330 -80 2.1trunk View file →
@@ -7,13 +7,21 @@
7 7
8 8 namespace PoweredCache\Admin\Dashboard;
9 9
10 10 use PoweredCache\Async\CachePreloader;
11 +use PoweredCache\Async\CachePurger;
11 12 use PoweredCache\Async\DatabaseOptimizer;
12 13 use PoweredCache\Config;
14 +use PoweredCache\Encryption;
15 +use PoweredCache\Preloader;
16 +use function PoweredCache\Utils\is_dev_mode_active;
17 +use function PoweredCache\Utils\mask_string;
18 +use const PoweredCache\Constants\ALLOPTIONS_CRITICAL_THRESHOLD;
19 +use const PoweredCache\Constants\ALLOPTIONS_WARNING_THRESHOLD;
13 20 use const PoweredCache\Constants\ICON_BASE64;
14 21 use const PoweredCache\Constants\MENU_SLUG;
15 22 use const PoweredCache\Constants\PURGE_CACHE_CRON_NAME;
23 +use const PoweredCache\Constants\PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT;
16 24 use const PoweredCache\Constants\SETTING_OPTION;
17 25 use function PoweredCache\Utils\can_configure_htaccess;
18 26 use function PoweredCache\Utils\can_configure_object_cache;
19 27 use function PoweredCache\Utils\can_control_all_settings;
@@ -22,12 +30,12 @@
22 30 use function PoweredCache\Utils\get_available_object_caches;
23 31 use function PoweredCache\Utils\get_cache_dir;
24 32 use function PoweredCache\Utils\get_timeout_with_interval;
25 33 use function PoweredCache\Utils\is_premium;
26 -use function PoweredCache\Utils\js_execution_methods;
27 34 use function PoweredCache\Utils\powered_cache_flush;
28 35 use function PoweredCache\Utils\remove_dir;
29 36 use function PoweredCache\Utils\sanitize_css;
37 +use const PoweredCache\Constants\UNMASK_CHARACTER_LENGTH;
30 38
31 39 // phpcs:disable WordPress.WhiteSpace.PrecisionAlignment.Found
32 40 // phpcs:disable Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed
33 41 // phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
@@ -50,11 +58,12 @@
50 58 add_action( 'admin_init', __NAMESPACE__ . '\\process_form_submit' );
51 59 add_filter( 'admin_body_class', __NAMESPACE__ . '\\add_sui_admin_body_class' );
52 60 add_action( 'admin_bar_menu', __NAMESPACE__ . '\\admin_bar_menu', 999 );
53 61 add_action( 'admin_bar_menu', __NAMESPACE__ . '\\purge_all_admin_bar_menu' );
54 - add_action( 'admin_post_powered_cache_purge_all_cache', __NAMESPACE__ . '\\purge_all_cache' );
62 + add_action( 'admin_post_powered_cache_purge_all_cache', __NAMESPACE__ . '\\purge_all_cache_action' );
55 63 add_action( 'admin_post_powered_cache_download_rewrite_settings', __NAMESPACE__ . '\\download_rewrite_config' );
56 64 add_action( 'wp_ajax_powered_cache_run_diagnostic', __NAMESPACE__ . '\\run_diagnostic' );
65 + add_action( 'wp_ajax_powered_cache_check_alloptions', __NAMESPACE__ . '\\check_alloptions' );
57 66 add_action( 'admin_post_deactivate_plugin', __NAMESPACE__ . '\\deactivate_plugin' );
58 67 add_filter( 'plugin_action_links_' . plugin_basename( POWERED_CACHE_PLUGIN_FILE ), __NAMESPACE__ . '\\action_links' );
59 68 add_filter( 'network_admin_plugin_action_links_' . plugin_basename( POWERED_CACHE_PLUGIN_FILE ), __NAMESPACE__ . '\\action_links' );
60 69 }
@@ -67,9 +76,9 @@
67 76 * @return string
68 77 * @see https://wpmudev.github.io/shared-ui/installation/
69 78 */
70 79 function add_sui_admin_body_class( $classes ) {
71 - $classes .= ' sui-2-12-4 ';
80 + $classes .= ' sui-2-12-24 ';
72 81
73 82 return $classes;
74 83 }
75 84
@@ -129,13 +138,14 @@
129 138 if ( ! current_user_can( 'manage_options' ) ) {
130 139 return;
131 140 }
132 141
133 - $nonce = filter_input( INPUT_POST, 'powered_cache_settings_nonce', FILTER_SANITIZE_STRING );
142 + $nonce = filter_input( INPUT_POST, 'powered_cache_settings_nonce', FILTER_SANITIZE_SPECIAL_CHARS );
134 143 if ( wp_verify_nonce( $nonce, 'powered_cache_update_settings' ) ) {
135 - $action = $_POST['powered_cache_form_action'] ? $_POST['powered_cache_form_action'] : 'save_settings';
144 + $action = isset( $_POST['powered_cache_form_action'] ) ? sanitize_text_field( wp_unslash( $_POST['powered_cache_form_action'] ) ) : 'save_settings';
136 145 $old_options = \PoweredCache\Utils\get_settings();
137 146 $options = sanitize_options( $_POST );
147 + $options = maybe_process_cloudflare_settings( $options );
138 148
139 149 switch ( $action ) {
140 150 case 'reset_settings':
141 151 if ( POWERED_CACHE_IS_NETWORK ) {
@@ -153,13 +163,27 @@
153 163 break;
154 164 case 'export_settings':
155 165 $filename = sprintf( 'powered-cache-settings-%s-%s.json', gmdate( 'Y-m-d' ), uniqid() );
156 166 if ( POWERED_CACHE_IS_NETWORK ) {
157 - $options = wp_json_encode( get_site_option( SETTING_OPTION ), JSON_PRETTY_PRINT );
167 + $options = get_site_option( SETTING_OPTION );
158 168 } else {
159 - $options = wp_json_encode( get_option( SETTING_OPTION ), JSON_PRETTY_PRINT );
169 + $options = get_option( SETTING_OPTION );
160 170 }
161 171
172 + $sensitive_options = [
173 + 'cloudflare_email', // PII data
174 + 'cloudflare_api_key',
175 + 'cloudflare_api_token',
176 + ];
177 +
178 + foreach ( $sensitive_options as $option_key ) {
179 + if ( isset( $options[ $option_key ] ) ) {
180 + $options[ $option_key ] = '';
181 + }
182 + }
183 +
184 + $options = wp_json_encode( $options, JSON_PRETTY_PRINT );
185 +
162 186 nocache_headers();
163 187 // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
164 188 @header( 'Content-Type: application/json' );
165 189 @header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
@@ -169,17 +193,26 @@
169 193 // phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged
170 194 echo $options; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
171 195 exit;
172 196 case 'import_settings':
173 - if ( $_FILES['import_file'] && ! empty( $_FILES['import_file']['tmp_name'] ) ) {
174 - $import_data = file_get_contents( $_FILES['import_file']['tmp_name'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
197 + if ( $_FILES['import_file'] && ! empty( $_FILES['import_file']['tmp_name'] ) ) { // phpcs:ignore
198 + $import_data = file_get_contents( $_FILES['import_file']['tmp_name'] ); // phpcs:ignore
175 199 $import_settings = json_decode( $import_data, true );
176 200 $options = sanitize_options( $import_settings );
177 201 }
178 202 break;
203 + case 'enable_dev_mode':
204 + $options['dev_mode'] = true;
205 + break;
206 + case 'disable_dev_mode':
207 + $options['dev_mode'] = false;
208 + break;
179 209 case 'save_settings_and_optimize':
180 210 db_optimize( $options );
181 211 break;
212 + case 'save_settings_and_clear_cache':
213 + purge_all_cache( $options );
214 + break;
182 215 case 'save_settings':
183 216 default:
184 217 break;
185 218 }
@@ -196,18 +229,37 @@
196 229 if ( isset( $options['object_cache'] ) && $old_options['object_cache'] !== $options['object_cache'] ) {
197 230 wp_cache_flush();
198 231 }
199 232
233 + // Flush cache when Dev Mode is turned OFF
234 + if ( ! empty( $old_options['dev_mode'] ) && empty( $options['dev_mode'] ) ) {
235 + wp_cache_flush();
236 + }
237 +
200 238 // maybe cancel preloading process when it turned off
201 239 if ( $old_options['enable_cache_preload'] && ! $options['enable_cache_preload'] ) {
202 240 cancel_preloading();
203 241 }
204 242
243 + // start the preloading process when it is turned on
244 + if ( ! $old_options['enable_cache_preload'] && $options['enable_cache_preload'] ) {
245 + start_preloading();
246 + }
247 +
248 + if ( $old_options['async_cache_cleaning'] && ! $options['async_cache_cleaning'] ) {
249 + cancel_async_cache_cleaning();
250 + }
251 +
205 252 // cleanup existing cache on toggling cache option
206 253 if ( $old_options['enable_page_cache'] && ! $options['enable_page_cache'] ) {
207 254 clean_site_cache_dir();
208 255 }
209 256
257 + // cleanup existing cache due to optimized URL changes
258 + if ( $old_options['rewrite_file_optimizer'] && ! $options['rewrite_file_optimizer'] ) {
259 + clean_site_cache_dir();
260 + }
261 +
210 262 if ( $old_options['cache_timeout'] !== $options['cache_timeout'] ) {
211 263 $timestamp = wp_next_scheduled( PURGE_CACHE_CRON_NAME );
212 264
213 265 wp_unschedule_event( $timestamp, PURGE_CACHE_CRON_NAME );
@@ -226,10 +278,10 @@
226 278 do_action( 'powered_cache_settings_saved', $old_options, $options );
227 279
228 280 $redirect_url = wp_get_referer();
229 281
230 - if ( empty( $redirect_url ) ) {
231 - $redirect_url = $_SERVER['REQUEST_URI'];
282 + if ( empty( $redirect_url ) && isset( $_SERVER['REQUEST_URI'] ) ) {
283 + $redirect_url = wp_unslash( $_SERVER['REQUEST_URI'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
232 284 }
233 285
234 286 $redirect_url = add_query_arg(
235 287 [
@@ -258,47 +310,63 @@
258 310 } else {
259 311 $sanitized_options['object_cache'] = 'off';
260 312 }
261 313
262 - $sanitized_options['enable_page_cache'] = ! empty( $options['enable_page_cache'] );
263 - $sanitized_options['cache_mobile'] = ! empty( $options['cache_mobile'] );
264 - $sanitized_options['cache_mobile_separate_file'] = ! empty( $options['cache_mobile_separate_file'] );
265 - $sanitized_options['loggedin_user_cache'] = ! empty( $options['loggedin_user_cache'] );
266 - $sanitized_options['gzip_compression'] = ! empty( $options['gzip_compression'] );
267 - $sanitized_options['cache_timeout'] = absint( $options['cache_timeout'] );
268 - $sanitized_options['auto_configure_htaccess'] = ! empty( $options['auto_configure_htaccess'] );
269 - $sanitized_options['rejected_user_agents'] = sanitize_textarea_field( $options['rejected_user_agents'] );
270 - $sanitized_options['rejected_cookies'] = sanitize_textarea_field( $options['rejected_cookies'] );
271 - $sanitized_options['vary_cookies'] = sanitize_textarea_field( $options['vary_cookies'] );
272 - $sanitized_options['rejected_uri'] = sanitize_textarea_field( $options['rejected_uri'] );
273 - $sanitized_options['accepted_query_strings'] = sanitize_textarea_field( $options['accepted_query_strings'] );
274 - $sanitized_options['purge_additional_pages'] = sanitize_textarea_field( $options['purge_additional_pages'] );
275 - $sanitized_options['purge_additional_pages'] = sanitize_textarea_field( $options['purge_additional_pages'] );
276 - $sanitized_options['minify_html'] = ! empty( $options['minify_html'] );
277 - $sanitized_options['combine_google_fonts'] = ! empty( $options['combine_google_fonts'] );
278 - $sanitized_options['minify_css'] = ! empty( $options['minify_css'] );
279 - $sanitized_options['combine_css'] = ! empty( $options['combine_css'] );
280 - $sanitized_options['critical_css'] = ! empty( $options['critical_css'] );
281 - $sanitized_options['critical_css_additional_files'] = sanitize_textarea_field( $options['critical_css_additional_files'] );
282 - $sanitized_options['critical_css_excluded_files'] = sanitize_textarea_field( $options['critical_css_excluded_files'] );
283 - $sanitized_options['excluded_css_files'] = sanitize_textarea_field( $options['excluded_css_files'] );
284 - $sanitized_options['minify_js'] = ! empty( $options['minify_js'] );
285 - $sanitized_options['combine_js'] = ! empty( $options['combine_js'] );
286 - $sanitized_options['excluded_js_files'] = sanitize_textarea_field( $options['excluded_js_files'] );
287 - $sanitized_options['excluded_js_files'] = sanitize_textarea_field( $options['excluded_js_files'] );
288 - $sanitized_options['js_execution_method'] = sanitize_text_field( $options['js_execution_method'] );
289 - $sanitized_options['js_execution_optimized_only'] = ! empty( $options['js_execution_optimized_only'] );
290 - $sanitized_options['enable_lazy_load'] = ! empty( $options['enable_lazy_load'] );
291 - $sanitized_options['lazy_load_post_content'] = ! empty( $options['lazy_load_post_content'] );
292 - $sanitized_options['lazy_load_images'] = ! empty( $options['lazy_load_images'] );
293 - $sanitized_options['lazy_load_iframes'] = ! empty( $options['lazy_load_iframes'] );
294 - $sanitized_options['lazy_load_widgets'] = ! empty( $options['lazy_load_widgets'] );
295 - $sanitized_options['lazy_load_post_thumbnail'] = ! empty( $options['lazy_load_post_thumbnail'] );
296 - $sanitized_options['lazy_load_avatars'] = ! empty( $options['lazy_load_avatars'] );
297 - $sanitized_options['disable_wp_lazy_load'] = ! empty( $options['disable_wp_lazy_load'] );
298 - $sanitized_options['disable_wp_embeds'] = ! empty( $options['disable_wp_embeds'] );
299 - $sanitized_options['disable_emoji_scripts'] = ! empty( $options['disable_emoji_scripts'] );
300 - $sanitized_options['enable_cdn'] = ! empty( $options['enable_cdn'] );
314 + $sanitized_options['enable_page_cache'] = ! empty( $options['enable_page_cache'] );
315 + $sanitized_options['cache_mobile'] = ! empty( $options['cache_mobile'] );
316 + $sanitized_options['cache_mobile_separate_file'] = ! empty( $options['cache_mobile_separate_file'] );
317 + $sanitized_options['loggedin_user_cache'] = ! empty( $options['loggedin_user_cache'] );
318 + $sanitized_options['gzip_compression'] = ! empty( $options['gzip_compression'] );
319 + $sanitized_options['cache_timeout'] = absint( $options['cache_timeout'] );
320 + $sanitized_options['auto_configure_htaccess'] = ! empty( $options['auto_configure_htaccess'] );
321 + $sanitized_options['rewrite_file_optimizer'] = ! empty( $options['rewrite_file_optimizer'] );
322 + $sanitized_options['rejected_user_agents'] = sanitize_textarea_field( $options['rejected_user_agents'] );
323 + $sanitized_options['rejected_cookies'] = sanitize_textarea_field( $options['rejected_cookies'] );
324 + $sanitized_options['rejected_referrers'] = sanitize_textarea_field( $options['rejected_referrers'] );
325 + $sanitized_options['vary_cookies'] = sanitize_textarea_field( $options['vary_cookies'] );
326 + $sanitized_options['rejected_uri'] = sanitize_textarea_field( $options['rejected_uri'] );
327 + $sanitized_options['cache_query_strings'] = sanitize_textarea_field( $options['cache_query_strings'] );
328 + $sanitized_options['ignored_query_strings'] = sanitize_textarea_field( $options['ignored_query_strings'] );
329 + $sanitized_options['purge_additional_pages'] = sanitize_textarea_field( $options['purge_additional_pages'] );
330 + $sanitized_options['minify_html'] = ! empty( $options['minify_html'] );
331 + $sanitized_options['minify_html_dom_optimization'] = ! empty( $options['minify_html_dom_optimization'] );
332 + $sanitized_options['combine_google_fonts'] = ! empty( $options['combine_google_fonts'] );
333 + $sanitized_options['swap_google_fonts_display'] = ! empty( $options['swap_google_fonts_display'] );
334 + $sanitized_options['use_bunny_fonts'] = ! empty( $options['use_bunny_fonts'] );
335 + $sanitized_options['minify_css'] = ! empty( $options['minify_css'] );
336 + $sanitized_options['combine_css'] = ! empty( $options['combine_css'] );
337 + $sanitized_options['critical_css'] = ! empty( $options['critical_css'] );
338 + $sanitized_options['critical_css_additional_files'] = sanitize_textarea_field( $options['critical_css_additional_files'] );
339 + $sanitized_options['critical_css_excluded_files'] = sanitize_textarea_field( $options['critical_css_excluded_files'] );
340 + $sanitized_options['excluded_css_files'] = sanitize_textarea_field( $options['excluded_css_files'] );
341 + $sanitized_options['remove_unused_css'] = ! empty( $options['remove_unused_css'] );
342 + $sanitized_options['ucss_safelist'] = sanitize_textarea_field( $options['ucss_safelist'] );
343 + $sanitized_options['ucss_excluded_files'] = sanitize_textarea_field( $options['ucss_excluded_files'] );
344 + $sanitized_options['minify_js'] = ! empty( $options['minify_js'] );
345 + $sanitized_options['combine_js'] = ! empty( $options['combine_js'] );
346 + $sanitized_options['excluded_js_files'] = sanitize_textarea_field( $options['excluded_js_files'] );
347 + $sanitized_options['js_defer'] = ! empty( $options['js_defer'] );
348 + $sanitized_options['js_defer_exclusions'] = sanitize_textarea_field( $options['js_defer_exclusions'] );
349 + $sanitized_options['js_delay'] = ! empty( $options['js_delay'] );
350 + $sanitized_options['js_delay_exclusions'] = sanitize_textarea_field( $options['js_delay_exclusions'] );
351 + $sanitized_options['js_delay_timeout'] = absint( $options['js_delay_timeout'] );
352 + $sanitized_options['enable_image_optimization'] = ! empty( $options['enable_image_optimization'] );
353 + $sanitized_options['image_optimizer_preferred_format'] = isset( $options['image_optimizer_preferred_format'] ) ? sanitize_text_field( wp_unslash( $options['image_optimizer_preferred_format'] ) ) : '';
354 + $sanitized_options['enable_lazy_load'] = ! empty( $options['enable_lazy_load'] );
355 + $sanitized_options['lazy_load_post_content'] = ! empty( $options['lazy_load_post_content'] );
356 + $sanitized_options['lazy_load_images'] = ! empty( $options['lazy_load_images'] );
357 + $sanitized_options['lazy_load_iframes'] = ! empty( $options['lazy_load_iframes'] );
358 + $sanitized_options['lazy_load_widgets'] = ! empty( $options['lazy_load_widgets'] );
359 + $sanitized_options['lazy_load_post_thumbnail'] = ! empty( $options['lazy_load_post_thumbnail'] );
360 + $sanitized_options['lazy_load_avatars'] = ! empty( $options['lazy_load_avatars'] );
361 + $sanitized_options['lazy_load_youtube'] = ! empty( $options['lazy_load_youtube'] );
362 + $sanitized_options['lazy_load_exclusions'] = sanitize_textarea_field( $options['lazy_load_exclusions'] );
363 + $sanitized_options['lazy_load_skip_first_nth_img'] = absint( $options['lazy_load_skip_first_nth_img'] );
364 + $sanitized_options['disable_wp_lazy_load'] = ! empty( $options['disable_wp_lazy_load'] );
365 + $sanitized_options['add_missing_image_dimensions'] = ! empty( $options['add_missing_image_dimensions'] );
366 + $sanitized_options['disable_wp_embeds'] = ! empty( $options['disable_wp_embeds'] );
367 + $sanitized_options['disable_emoji_scripts'] = ! empty( $options['disable_emoji_scripts'] );
368 + $sanitized_options['enable_cdn'] = ! empty( $options['enable_cdn'] );
301 369
302 370 // convert TTL in minute
303 371 if ( $options['cache_timeout'] > 0 && isset( $options['cache_timeout_interval'] ) ) {
304 372 switch ( $options['cache_timeout_interval'] ) {
@@ -316,9 +384,14 @@
316 384
317 385 $cdn_hostname = [];
318 386 if ( isset( $options['cdn_hostname'] ) ) {
319 387 foreach ( (array) $options['cdn_hostname'] as $hostname ) {
320 - $cdn_hostname[] = esc_url_raw( $hostname );
388 + $hostname = trim( $hostname );
389 + if ( filter_var( $hostname, FILTER_VALIDATE_URL ) ) {
390 + $cdn_hostname[] = wp_parse_url( $hostname, PHP_URL_HOST );
391 + } else {
392 + $cdn_hostname[] = $hostname;
393 + }
321 394 }
322 395 }
323 396
324 397 $cdn_zone = [];
@@ -328,8 +401,16 @@
328 401 $cdn_zone[] = sanitize_text_field( $zone );
329 402 }
330 403 }
331 404
405 + if ( empty( $cdn_hostname ) ) {
406 + $cdn_hostname = [ '' ];
407 + }
408 +
409 + if ( empty( $cdn_zone ) ) {
410 + $cdn_zone = [ '' ];
411 + }
412 +
332 413 $sanitized_options['cdn_hostname'] = $cdn_hostname;
333 414 $sanitized_options['cdn_zone'] = $cdn_zone;
334 415 $sanitized_options['cdn_rejected_files'] = sanitize_textarea_field( $options['cdn_rejected_files'] );
335 416 $sanitized_options['enable_cache_preload'] = ! empty( $options['enable_cache_preload'] );
@@ -336,10 +417,14 @@
336 417 $sanitized_options['preload_homepage'] = ! empty( $options['preload_homepage'] );
337 418 $sanitized_options['preload_public_posts'] = ! empty( $options['preload_public_posts'] );
338 419 $sanitized_options['preload_public_tax'] = ! empty( $options['preload_public_tax'] );
339 420 $sanitized_options['enable_sitemap_preload'] = ! empty( $options['enable_sitemap_preload'] );
421 + $sanitized_options['preload_request_interval'] = absint( $options['preload_request_interval'] );
340 422 $sanitized_options['preload_sitemap'] = sanitize_textarea_field( $options['preload_sitemap'] );
341 423 $sanitized_options['prefetch_dns'] = sanitize_textarea_field( $options['prefetch_dns'] );
424 + $sanitized_options['preconnect_resource'] = sanitize_textarea_field( $options['preconnect_resource'] );
425 + $sanitized_options['enable_lcp_optimization'] = ! empty( $options['enable_lcp_optimization'] );
426 + $sanitized_options['prefetch_links'] = ! empty( $options['prefetch_links'] );
342 427 $sanitized_options['db_cleanup_post_revisions'] = ! empty( $options['db_cleanup_post_revisions'] );
343 428 $sanitized_options['db_cleanup_auto_drafts'] = ! empty( $options['db_cleanup_auto_drafts'] );
344 429 $sanitized_options['db_cleanup_trashed_posts'] = ! empty( $options['db_cleanup_trashed_posts'] );
345 430 $sanitized_options['db_cleanup_spam_comments'] = ! empty( $options['db_cleanup_spam_comments'] );
@@ -351,8 +436,9 @@
351 436 $sanitized_options['scheduled_db_cleanup_frequency'] = sanitize_text_field( $options['scheduled_db_cleanup_frequency'] );
352 437 $sanitized_options['enable_cloudflare'] = ! empty( $options['enable_cloudflare'] );
353 438 $sanitized_options['cloudflare_email'] = sanitize_email( $options['cloudflare_email'] );
354 439 $sanitized_options['cloudflare_api_key'] = sanitize_text_field( $options['cloudflare_api_key'] );
440 + $sanitized_options['cloudflare_api_token'] = sanitize_text_field( $options['cloudflare_api_token'] );
355 441 $sanitized_options['cloudflare_zone'] = sanitize_text_field( $options['cloudflare_zone'] );
356 442 $sanitized_options['enable_heartbeat'] = ! empty( $options['enable_heartbeat'] );
357 443 $sanitized_options['heartbeat_dashboard_status'] = sanitize_text_field( $options['heartbeat_dashboard_status'] );
358 444 $sanitized_options['heartbeat_editor_status'] = sanitize_text_field( $options['heartbeat_editor_status'] );
@@ -362,8 +448,10 @@
362 448 $sanitized_options['heartbeat_frontend_interval'] = absint( $options['heartbeat_frontend_interval'] );
363 449 $sanitized_options['enable_varnish'] = ! empty( $options['enable_varnish'] );
364 450 $sanitized_options['varnish_ip'] = sanitize_text_field( $options['varnish_ip'] );
365 451 $sanitized_options['cache_footprint'] = ! empty( $options['cache_footprint'] );
452 + $sanitized_options['async_cache_cleaning'] = ! empty( $options['async_cache_cleaning'] );
453 + $sanitized_options['dev_mode'] = ! empty( $options['dev_mode'] );
366 454 $sanitized_options['enable_google_tracking'] = ! empty( $options['enable_google_tracking'] );
367 455 $sanitized_options['enable_fb_tracking'] = ! empty( $options['enable_fb_tracking'] );
368 456
369 457 if ( isset( $options['critical_css_appended_content'] ) ) {
@@ -438,23 +526,32 @@
438 526
439 527 $screen = get_current_screen();
440 528
441 529 $success_messages = [
442 - 'flush_page_cache_network' => esc_html__( 'Page cache deleted for all websites!', 'powered-cache' ),
443 - 'flush_page_cache' => esc_html__( 'Page cache deleted successfully!', 'powered-cache' ),
444 - 'flush_object_cache' => esc_html__( 'Object cache deleted successfully!', 'powered-cache' ),
445 - 'flush_all_cache' => esc_html__( 'All cached items flushed successfully!', 'powered-cache' ),
446 - 'start_preload' => esc_html__( 'The cache preloading has been initialized!', 'powered-cache' ),
447 - 'generate_critical' => esc_html__( 'The Critical CSS generation process has been initialized!', 'powered-cache' ),
448 - 'generate_critical_network' => esc_html__( 'The Critical CSS generation process has been initialized for all sites! This might take a while, depending on the network size.', 'powered-cache' ),
449 - 'flush_cf_cache' => esc_html__( 'Cloudflare cache flushed, it can take up to 30 seconds to delete all cache from Cloudflare!', 'powered-cache' ),
450 - 'reset_settings' => esc_html__( 'Settings have been reset!', 'powered-cache' ),
451 - 'import_settings' => esc_html__( 'Settings have been imported!', 'powered-cache' ),
452 - 'save_settings_and_optimize' => esc_html__( 'Settings saved and database being optimized...', 'powered-cache' ),
453 - 'save_settings' => esc_html__( 'Settings saved.', 'powered-cache' ),
530 + 'purge_image_optimizer_cache' => esc_html__( 'Image optimizer cache purged successfully!', 'powered-cache' ),
531 + 'flush_page_cache_network' => esc_html__( 'Page cache deleted for all websites!', 'powered-cache' ),
532 + 'flush_page_cache' => esc_html__( 'Page cache deleted successfully!', 'powered-cache' ),
533 + 'flush_object_cache' => esc_html__( 'Object cache deleted successfully!', 'powered-cache' ),
534 + 'flush_all_cache' => esc_html__( 'All cached items flushed successfully!', 'powered-cache' ),
535 + 'start_preload' => esc_html__( 'The cache preloading has been initialized!', 'powered-cache' ),
536 + 'generate_critical' => esc_html__( 'The Critical CSS generation process has been initialized!', 'powered-cache' ),
537 + 'generate_critical_network' => esc_html__( 'The Critical CSS generation process has been initialized for all sites! This might take a while, depending on the network size.', 'powered-cache' ),
538 + 'generate_ucss' => esc_html__( 'The UCSS generation process has been initialized!', 'powered-cache' ),
539 + 'generate_ucss_network' => esc_html__( 'The UCSS generation process has been initialized for all sites! This might take a while, depending on the network size.', 'powered-cache' ),
540 + 'flush_cf_cache' => esc_html__( 'Cloudflare cache flushed, it can take up to 30 seconds to delete all cache from Cloudflare!', 'powered-cache' ),
541 + 'reset_settings' => esc_html__( 'Settings have been reset!', 'powered-cache' ),
542 + 'import_settings' => esc_html__( 'Settings have been imported!', 'powered-cache' ),
543 + 'save_settings_and_optimize' => esc_html__( 'Settings saved and database being optimized...', 'powered-cache' ),
544 + 'save_settings_and_clear_cache' => esc_html__( 'Settings have been successfully saved, and all cache has been cleared.', 'powered-cache' ),
545 + 'save_settings' => esc_html__( 'Settings saved.', 'powered-cache' ),
454 546 ];
455 547
548 + if ( isset( $_GET['language'] ) ) {
549 + $success_messages['flush_lang_cache'] = sprintf( esc_html__( 'Page cache for %s language has been deleted!', 'powered-cache' ), esc_attr( urldecode_deep( $_GET['language'] ) ) ); // phpcs:ignore
550 + }
551 +
456 552 $err_messages = [
553 + 'purge_image_optimizer_cache_failed' => esc_html__( 'Could not purge image optimizer cache. Please try again later and ensure your license key is activated!', 'powered-cache' ),
457 554 'generic_permission_err' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
458 555 'flush_page_cache_network_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
459 556 'flush_page_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
460 557 'flush_object_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
@@ -460,15 +557,17 @@
460 557 'flush_object_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
461 558 'flush_all_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
462 559 'start_preload_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
463 560 'start_critical_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
561 + 'start_ucss_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
464 562 'start_critical_err_license' => esc_html__( 'Your license key does not seem valid. A valid license is required for the Critical CSS!', 'powered-cache' ),
563 + 'start_ucss_err_license' => esc_html__( 'Your license key does not seem valid. A valid license is required for removing unused CSS!', 'powered-cache' ),
465 564 'flush_cf_cache_failed' => esc_html__( 'Could not flush Cloudflare cache. Please make sure you entered the correct credentials and zone id!', 'powered-cache' ),
466 565 ];
467 566
468 567 if ( isset( $success_messages[ $_GET['pc_action'] ] ) ) {
469 568 if ( MENU_SLUG === $screen->parent_base ) { // display with shared-ui on plugin page
470 - add_settings_error( $screen->parent_file, MENU_SLUG, $success_messages[ $_GET['pc_action'] ], 'success' );
569 + add_settings_error( $screen->parent_file, MENU_SLUG, $success_messages[ $_GET['pc_action'] ], 'success' ); // phpcs:ignore
471 570
472 571 return;
473 572 }
474 573
@@ -476,9 +575,9 @@
476 575 }
477 576
478 577 if ( isset( $err_messages[ $_GET['pc_action'] ] ) ) {
479 578 if ( MENU_SLUG === $screen->parent_base ) { // display with shared-ui on plugin page
480 - add_settings_error( $screen->parent_file, MENU_SLUG, $err_messages[ $_GET['pc_action'] ], 'error' );
579 + add_settings_error( $screen->parent_file, MENU_SLUG, $err_messages[ $_GET['pc_action'] ], 'error' ); // phpcs:ignore
481 580
482 581 return;
483 582 }
484 583
@@ -515,11 +614,12 @@
515 614 * Purges all cache related things
516 615 *
517 616 * @since 1.1
518 617 */
519 -function purge_all_cache() {
618 +function purge_all_cache_action() {
520 619
521 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_purge_all_cache' ) ) {
620 + $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
621 + if ( ! wp_verify_nonce( $nonce, 'powered_cache_purge_all_cache' ) ) {
522 622 wp_nonce_ays( '' );
523 623 }
524 624
525 625 if ( is_multisite() && ! current_user_can( 'manage_network' ) ) {
@@ -533,23 +633,53 @@
533 633 wp_safe_redirect( esc_url_raw( $redirect_url ) );
534 634 exit;
535 635 }
536 636
537 - powered_cache_flush();// cleans object cache + page cache dir
637 + purge_all_cache();
538 638
639 + $redirect_url = add_query_arg( 'pc_action', 'flush_all_cache', wp_get_referer() );
640 +
641 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
642 + exit;
643 +}
644 +
645 +
646 +/**
647 + * Purge all cache
648 + *
649 + * @param array $settings plugin settings
650 + *
651 + * @return void
652 + */
653 +function purge_all_cache( $settings = array() ) {
654 + $cache_purger = CachePurger::factory();
655 + if ( empty( $settings ) ) {
656 + $settings = \PoweredCache\Utils\get_settings();
657 + }
658 +
659 + if ( $settings['async_cache_cleaning'] ) {
660 + if ( function_exists( 'wp_cache_flush' ) ) {
661 + wp_cache_flush();
662 + }
663 + $cache_purger->push_to_queue( [ 'call' => 'powered_cache_flush' ] );
664 + $cache_purger->save()->dispatch();
665 + } else {
666 + powered_cache_flush();// cleans object cache + page cache dir
667 + }
668 +
539 669 /**
540 670 * Fires after purging all cache
541 671 *
542 672 * @hook powered_cache_purge_all_cache
543 - *
544 673 * @since 1.1
545 674 */
546 675 do_action( 'powered_cache_purge_all_cache' );
547 676
548 - $redirect_url = add_query_arg( 'pc_action', 'flush_all_cache', wp_get_referer() );
549 -
550 - wp_safe_redirect( esc_url_raw( $redirect_url ) );
551 - exit;
677 + if ( POWERED_CACHE_IS_NETWORK ) {
678 + delete_site_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT );
679 + } else {
680 + delete_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT );
681 + }
552 682 }
553 683
554 684
555 685 /**
@@ -557,9 +687,10 @@
557 687 *
558 688 * @since 1.1
559 689 */
560 690 function download_rewrite_config() {
561 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_download_rewrite' ) ) {
691 + $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
692 + if ( ! wp_verify_nonce( $nonce, 'powered_cache_download_rewrite' ) ) {
562 693 wp_nonce_ays( '' );
563 694 }
564 695
565 696 if ( ! can_control_all_settings() ) {
@@ -567,10 +698,12 @@
567 698 wp_safe_redirect( esc_url_raw( $redirect_url ) );
568 699 exit;
569 700 }
570 701
571 - $server = $_GET['server'];
572 - Config::factory()->download_rewrite_rules( $server );
702 + if ( ! empty( $_GET['server'] ) ) {
703 + $server = sanitize_text_field( wp_unslash( $_GET['server'] ) );
704 + Config::factory()->download_rewrite_rules( $server );
705 + }
573 706
574 707 wp_safe_redirect( wp_get_referer() );
575 708 die();
576 709 }
@@ -613,21 +746,45 @@
613 746 /**
614 747 * Cancel preloading process on toggling preload option
615 748 */
616 749 function cancel_preloading() {
617 - \PoweredCache\Utils\log( 'Cancel preload process' );
750 + \PoweredCache\Utils\log( 'Cancel preload process - Settings toggle' );
618 751 $cache_preloader = CachePreloader::factory();
619 752 $cache_preloader->cancel_process();
753 + $cache_preloader->delete_all();
620 754 }
621 755
756 +/**
757 + * Kick-start preloading process
758 + *
759 + * @return void
760 + */
761 +function start_preloading() {
762 + \PoweredCache\Utils\log( 'Enable Preloader - Settings toggle' );
763 + Preloader::factory()->setup_preload_queue();
764 + // kickstart the preloading process
765 + Preloader::factory()->dispatch_preload_queue();
766 +}
622 767
623 768 /**
769 + * Cancel async cache purging processes
770 + *
771 + * @since 2.3
772 + */
773 +function cancel_async_cache_cleaning() {
774 + \PoweredCache\Utils\log( 'Cancel CachePurger process' );
775 + $cache_preloader = CachePurger::factory();
776 + $cache_preloader->cancel_process();
777 +}
778 +
779 +
780 +/**
624 781 * Perform diagnostic checks
625 782 */
626 783 function run_diagnostic() {
627 784 global $is_apache;
628 785
629 - $nonce = $_POST['nonce'];
786 + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
630 787
631 788 if ( wp_verify_nonce( $nonce, 'powered_cache_run_diagnostic' ) ) {
632 789 $settings = \PoweredCache\Utils\get_settings();
633 790 $checks = array();
@@ -731,9 +888,55 @@
731 888
732 889 wp_send_json_error( [ esc_html__( 'Invalid request', 'powered-cache' ) ] );
733 890 }
734 891
892 +/**
893 + * Check alloptions size like performance lab does.
894 + * It's critical to know this before enabling memcached based persistent object cache backends.
895 + * When alloptions size is too big (1mb in this case), it will cause performance degradation instead of improvement.
896 + *
897 + * @return void
898 + * @since 3.4
899 + */
900 +function check_alloptions() {
901 + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
902 + if ( ! wp_verify_nonce( $nonce, 'powered_cache_update_settings' ) || ! can_configure_object_cache() ) {
903 + wp_send_json_error( [ 'message' => esc_html__( 'Invalid request', 'powered-cache' ) ] );
735 904
905 + return;
906 + }
907 +
908 + $autoload_option_size = \PoweredCache\Utils\autoloaded_options_size();
909 + $autoload_option_count = count( wp_load_alloptions() );
910 +
911 + if ( $autoload_option_size > ALLOPTIONS_CRITICAL_THRESHOLD ) {
912 + $status = 'critical';
913 + } elseif ( $autoload_option_size > ALLOPTIONS_WARNING_THRESHOLD && $autoload_option_size <= ALLOPTIONS_CRITICAL_THRESHOLD ) {
914 + $status = 'warning';
915 + } else {
916 + $status = 'good';
917 + }
918 +
919 + $message = '<p><b>' . esc_html__( 'Autoloaded options could affect performance:', 'powered-cache' ) . '</b> ' .
920 + sprintf(
921 + esc_html__(
922 + /* translators: 1: Number of autoloaded options. 2: Size of autoloaded options. */
923 + 'Your site has %1$s autoloaded options (size: %2$s) in the options table, which could cause your site to be slow. You can reduce the number of autoloaded options by cleaning up your site\'s options table.',
924 + 'powered-cache'
925 + ),
926 + esc_html( number_format_i18n( $autoload_option_count ) ),
927 + esc_html( size_format( $autoload_option_size ) )
928 + ) . '</p>';
929 +
930 + wp_send_json_success(
931 + [
932 + 'status' => $status,
933 + 'message' => $message,
934 + ]
935 + );
936 +}
937 +
938 +
736 939 /**
737 940 * Deactivate incompatible plugins
738 941 *
739 942 * @since 1.0
@@ -738,9 +941,10 @@
738 941 *
739 942 * @since 1.0
740 943 */
741 944 function deactivate_plugin() {
742 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'deactivate_plugin' ) ) {
945 + $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
946 + if ( ! wp_verify_nonce( $nonce, 'deactivate_plugin' ) ) {
743 947 wp_nonce_ays( '' );
744 948 }
745 949
746 950 if ( ! current_user_can( 'activate_plugins' ) ) {
@@ -748,9 +952,12 @@
748 952 wp_safe_redirect( esc_url_raw( $redirect_url ) );
749 953 exit;
750 954 }
751 955
752 - deactivate_plugins( $_GET['plugin'] );
956 + if ( isset( $_GET['plugin'] ) ) {
957 + $plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) );
958 + deactivate_plugins( $plugin );
959 + }
753 960
754 961 wp_safe_redirect( wp_get_referer() );
755 962 die();
756 963 }
@@ -774,5 +981,48 @@
774 981 $actions['get_premium'] = sprintf( '<a href="%s" style="color: red;">%s</a>', esc_url( $powered_cache_url ), esc_html__( 'Get Premium', 'powered-cache' ) );
775 982 }
776 983
777 984 return array_reverse( $actions );
985 +}
986 +
987 +/**
988 + * Conditionally process Cloudflare API key and token settings based on the form input.
989 + *
990 + * @param array $options The form options submitted by the user.
991 + *
992 + * @return array Updated options with processed Cloudflare settings.
993 + */
994 +function maybe_process_cloudflare_settings( $options ) {
995 + // Retrieve the previous Cloudflare API key and token values.
996 + $prev_cf_api_key = \PoweredCache\Extensions\Cloudflare\Cloudflare::get_cf_api_key();
997 + $prev_cf_api_token = \PoweredCache\Extensions\Cloudflare\Cloudflare::get_cf_api_token();
998 +
999 + // Check if the submitted Cloudflare API key matches the masked version of the previous key.
1000 + if ( isset( $options['cloudflare_api_key'] ) && mask_string( $prev_cf_api_key, UNMASK_CHARACTER_LENGTH ) === $options['cloudflare_api_key'] ) {
1001 + $options['cloudflare_api_key'] = $prev_cf_api_key; // Use the unmasked value.
1002 + }
1003 +
1004 + if ( isset( $options['cloudflare_api_token'] ) && mask_string( $prev_cf_api_token, UNMASK_CHARACTER_LENGTH ) === $options['cloudflare_api_token'] ) {
1005 + $options['cloudflare_api_token'] = $prev_cf_api_token; // Use the unmasked value.
1006 + }
1007 +
1008 + $encryption = new Encryption();
1009 + // Encrypt sensitive data if it's not empty.
1010 + if ( ! empty( $options['cloudflare_api_key'] ) ) {
1011 + $options['cloudflare_api_key'] = $encryption->encrypt( $options['cloudflare_api_key'] );
1012 + }
1013 +
1014 + if ( ! empty( $options['cloudflare_api_token'] ) ) {
1015 + $options['cloudflare_api_token'] = $encryption->encrypt( $options['cloudflare_api_token'] );
1016 + }
1017 +
1018 + // Override with empty values if constants are defined.
1019 + if ( defined( 'POWERED_CACHE_CF_API_KEY' ) && POWERED_CACHE_CF_API_KEY ) {
1020 + $options['cloudflare_api_key'] = '';
1021 + }
1022 +
1023 + if ( defined( 'POWERED_CACHE_CF_API_TOKEN' ) && POWERED_CACHE_CF_API_TOKEN ) {
1024 + $options['cloudflare_api_token'] = '';
1025 + }
1026 +
1027 + return $options;
778 1028 }