PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 3.6.3
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v3.6.3
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 +350 -81 2.03.6.3 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;
@@ -20,14 +28,14 @@
20 28 use function PoweredCache\Utils\cdn_zones;
21 29 use function PoweredCache\Utils\clean_site_cache_dir;
22 30 use function PoweredCache\Utils\get_available_object_caches;
23 31 use function PoweredCache\Utils\get_cache_dir;
24 -use function PoweredCache\Utils\get_db_cleanup_counts;
25 32 use function PoweredCache\Utils\get_timeout_with_interval;
26 33 use function PoweredCache\Utils\is_premium;
27 -use function PoweredCache\Utils\js_execution_methods;
28 34 use function PoweredCache\Utils\powered_cache_flush;
29 35 use function PoweredCache\Utils\remove_dir;
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-10-11 ';
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 [
@@ -237,9 +289,9 @@
237 289 ],
238 290 $redirect_url
239 291 );
240 292
241 - wp_safe_redirect( $redirect_url );
293 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
242 294 exit;
243 295 }
244 296 }
245 297
@@ -258,44 +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['excluded_css_files'] = sanitize_textarea_field( $options['excluded_css_files'] );
281 - $sanitized_options['minify_js'] = ! empty( $options['minify_js'] );
282 - $sanitized_options['combine_js'] = ! empty( $options['combine_js'] );
283 - $sanitized_options['excluded_js_files'] = sanitize_textarea_field( $options['excluded_js_files'] );
284 - $sanitized_options['excluded_js_files'] = sanitize_textarea_field( $options['excluded_js_files'] );
285 - $sanitized_options['js_execution_method'] = sanitize_text_field( $options['js_execution_method'] );
286 - $sanitized_options['js_execution_optimized_only'] = ! empty( $options['js_execution_optimized_only'] );
287 - $sanitized_options['enable_lazy_load'] = ! empty( $options['enable_lazy_load'] );
288 - $sanitized_options['lazy_load_post_content'] = ! empty( $options['lazy_load_post_content'] );
289 - $sanitized_options['lazy_load_images'] = ! empty( $options['lazy_load_images'] );
290 - $sanitized_options['lazy_load_iframes'] = ! empty( $options['lazy_load_iframes'] );
291 - $sanitized_options['lazy_load_widgets'] = ! empty( $options['lazy_load_widgets'] );
292 - $sanitized_options['lazy_load_post_thumbnail'] = ! empty( $options['lazy_load_post_thumbnail'] );
293 - $sanitized_options['lazy_load_avatars'] = ! empty( $options['lazy_load_avatars'] );
294 - $sanitized_options['disable_wp_lazy_load'] = ! empty( $options['disable_wp_lazy_load'] );
295 - $sanitized_options['disable_wp_embeds'] = ! empty( $options['disable_wp_embeds'] );
296 - $sanitized_options['disable_emoji_scripts'] = ! empty( $options['disable_emoji_scripts'] );
297 - $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'] );
298 369
299 370 // convert TTL in minute
300 371 if ( $options['cache_timeout'] > 0 && isset( $options['cache_timeout_interval'] ) ) {
301 372 switch ( $options['cache_timeout_interval'] ) {
@@ -313,9 +384,14 @@
313 384
314 385 $cdn_hostname = [];
315 386 if ( isset( $options['cdn_hostname'] ) ) {
316 387 foreach ( (array) $options['cdn_hostname'] as $hostname ) {
317 - $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 + }
318 394 }
319 395 }
320 396
321 397 $cdn_zone = [];
@@ -325,8 +401,16 @@
325 401 $cdn_zone[] = sanitize_text_field( $zone );
326 402 }
327 403 }
328 404
405 + if ( empty( $cdn_hostname ) ) {
406 + $cdn_hostname = [ '' ];
407 + }
408 +
409 + if ( empty( $cdn_zone ) ) {
410 + $cdn_zone = [ '' ];
411 + }
412 +
329 413 $sanitized_options['cdn_hostname'] = $cdn_hostname;
330 414 $sanitized_options['cdn_zone'] = $cdn_zone;
331 415 $sanitized_options['cdn_rejected_files'] = sanitize_textarea_field( $options['cdn_rejected_files'] );
332 416 $sanitized_options['enable_cache_preload'] = ! empty( $options['enable_cache_preload'] );
@@ -333,10 +417,13 @@
333 417 $sanitized_options['preload_homepage'] = ! empty( $options['preload_homepage'] );
334 418 $sanitized_options['preload_public_posts'] = ! empty( $options['preload_public_posts'] );
335 419 $sanitized_options['preload_public_tax'] = ! empty( $options['preload_public_tax'] );
336 420 $sanitized_options['enable_sitemap_preload'] = ! empty( $options['enable_sitemap_preload'] );
421 + $sanitized_options['preload_request_interval'] = absint( $options['preload_request_interval'] );
337 422 $sanitized_options['preload_sitemap'] = sanitize_textarea_field( $options['preload_sitemap'] );
338 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['prefetch_links'] = ! empty( $options['prefetch_links'] );
339 426 $sanitized_options['db_cleanup_post_revisions'] = ! empty( $options['db_cleanup_post_revisions'] );
340 427 $sanitized_options['db_cleanup_auto_drafts'] = ! empty( $options['db_cleanup_auto_drafts'] );
341 428 $sanitized_options['db_cleanup_trashed_posts'] = ! empty( $options['db_cleanup_trashed_posts'] );
342 429 $sanitized_options['db_cleanup_spam_comments'] = ! empty( $options['db_cleanup_spam_comments'] );
@@ -348,8 +435,9 @@
348 435 $sanitized_options['scheduled_db_cleanup_frequency'] = sanitize_text_field( $options['scheduled_db_cleanup_frequency'] );
349 436 $sanitized_options['enable_cloudflare'] = ! empty( $options['enable_cloudflare'] );
350 437 $sanitized_options['cloudflare_email'] = sanitize_email( $options['cloudflare_email'] );
351 438 $sanitized_options['cloudflare_api_key'] = sanitize_text_field( $options['cloudflare_api_key'] );
439 + $sanitized_options['cloudflare_api_token'] = sanitize_text_field( $options['cloudflare_api_token'] );
352 440 $sanitized_options['cloudflare_zone'] = sanitize_text_field( $options['cloudflare_zone'] );
353 441 $sanitized_options['enable_heartbeat'] = ! empty( $options['enable_heartbeat'] );
354 442 $sanitized_options['heartbeat_dashboard_status'] = sanitize_text_field( $options['heartbeat_dashboard_status'] );
355 443 $sanitized_options['heartbeat_editor_status'] = sanitize_text_field( $options['heartbeat_editor_status'] );
@@ -359,11 +447,21 @@
359 447 $sanitized_options['heartbeat_frontend_interval'] = absint( $options['heartbeat_frontend_interval'] );
360 448 $sanitized_options['enable_varnish'] = ! empty( $options['enable_varnish'] );
361 449 $sanitized_options['varnish_ip'] = sanitize_text_field( $options['varnish_ip'] );
362 450 $sanitized_options['cache_footprint'] = ! empty( $options['cache_footprint'] );
451 + $sanitized_options['async_cache_cleaning'] = ! empty( $options['async_cache_cleaning'] );
452 + $sanitized_options['dev_mode'] = ! empty( $options['dev_mode'] );
363 453 $sanitized_options['enable_google_tracking'] = ! empty( $options['enable_google_tracking'] );
364 454 $sanitized_options['enable_fb_tracking'] = ! empty( $options['enable_fb_tracking'] );
365 455
456 + if ( isset( $options['critical_css_appended_content'] ) ) {
457 + $sanitized_options['critical_css_appended_content'] = sanitize_css( $options['critical_css_appended_content'] );
458 + }
459 +
460 + if ( isset( $options['critical_css_fallback'] ) ) {
461 + $sanitized_options['critical_css_fallback'] = sanitize_css( $options['critical_css_fallback'] );
462 + }
463 +
366 464 /**
367 465 * Filters sanitized options.
368 466 *
369 467 * @hook powered_cache_sanitized_options
@@ -427,32 +525,48 @@
427 525
428 526 $screen = get_current_screen();
429 527
430 528 $success_messages = [
431 - 'flush_page_cache_network' => esc_html__( 'Page cache deleted for all websites!', 'powered-cache' ),
432 - 'flush_page_cache' => esc_html__( 'Page cache deleted successfully!', 'powered-cache' ),
433 - 'flush_object_cache' => esc_html__( 'Object cache deleted successfully!', 'powered-cache' ),
434 - 'flush_all_cache' => esc_html__( 'All cached items flushed successfully!', 'powered-cache' ),
435 - 'start_preload' => esc_html__( 'The cache preloading has been initialized!', 'powered-cache' ),
436 - 'flush_cf_cache' => esc_html__( 'Cloudflare cache flushed, it can take up to 30 seconds to delete all cache from Cloudflare!', 'powered-cache' ),
437 - 'reset_settings' => esc_html__( 'Settings have been reset!', 'powered-cache' ),
438 - 'import_settings' => esc_html__( 'Settings has been imported!', 'powered-cache' ),
439 - 'save_settings_and_optimize' => esc_html__( 'Settings saved and database being optimized...', 'powered-cache' ),
440 - 'save_settings' => esc_html__( 'Settings saved.', 'powered-cache' ),
529 + 'purge_image_optimizer_cache' => esc_html__( 'Image optimizer cache purged successfully!', 'powered-cache' ),
530 + 'flush_page_cache_network' => esc_html__( 'Page cache deleted for all websites!', 'powered-cache' ),
531 + 'flush_page_cache' => esc_html__( 'Page cache deleted successfully!', 'powered-cache' ),
532 + 'flush_object_cache' => esc_html__( 'Object cache deleted successfully!', 'powered-cache' ),
533 + 'flush_all_cache' => esc_html__( 'All cached items flushed successfully!', 'powered-cache' ),
534 + 'start_preload' => esc_html__( 'The cache preloading has been initialized!', 'powered-cache' ),
535 + 'generate_critical' => esc_html__( 'The Critical CSS generation process has been initialized!', 'powered-cache' ),
536 + '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' ),
537 + 'generate_ucss' => esc_html__( 'The UCSS generation process has been initialized!', 'powered-cache' ),
538 + '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' ),
539 + 'flush_cf_cache' => esc_html__( 'Cloudflare cache flushed, it can take up to 30 seconds to delete all cache from Cloudflare!', 'powered-cache' ),
540 + 'reset_settings' => esc_html__( 'Settings have been reset!', 'powered-cache' ),
541 + 'import_settings' => esc_html__( 'Settings have been imported!', 'powered-cache' ),
542 + 'save_settings_and_optimize' => esc_html__( 'Settings saved and database being optimized...', 'powered-cache' ),
543 + 'save_settings_and_clear_cache' => esc_html__( 'Settings have been successfully saved, and all cache has been cleared.', 'powered-cache' ),
544 + 'save_settings' => esc_html__( 'Settings saved.', 'powered-cache' ),
441 545 ];
442 546
547 + if ( isset( $_GET['language'] ) ) {
548 + $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
549 + }
550 +
443 551 $err_messages = [
552 + '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' ),
553 + 'generic_permission_err' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
444 554 'flush_page_cache_network_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
445 555 'flush_page_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
446 556 'flush_object_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
447 557 'flush_all_cache_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
448 558 'start_preload_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
449 - 'flush_cf_cache_failed' => esc_html__( 'Could not flushed Cloudflare cache. Please make sure you entered the correct credentials and zone id!', 'powered-cache' ),
559 + 'start_critical_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
560 + 'start_ucss_err_permission' => esc_html__( 'You don\'t have permission to perform this action!', 'powered-cache' ),
561 + 'start_critical_err_license' => esc_html__( 'Your license key does not seem valid. A valid license is required for the Critical CSS!', 'powered-cache' ),
562 + 'start_ucss_err_license' => esc_html__( 'Your license key does not seem valid. A valid license is required for removing unused CSS!', 'powered-cache' ),
563 + 'flush_cf_cache_failed' => esc_html__( 'Could not flush Cloudflare cache. Please make sure you entered the correct credentials and zone id!', 'powered-cache' ),
450 564 ];
451 565
452 566 if ( isset( $success_messages[ $_GET['pc_action'] ] ) ) {
453 567 if ( MENU_SLUG === $screen->parent_base ) { // display with shared-ui on plugin page
454 - add_settings_error( $screen->parent_file, MENU_SLUG, $success_messages[ $_GET['pc_action'] ], 'success' );
568 + add_settings_error( $screen->parent_file, MENU_SLUG, $success_messages[ $_GET['pc_action'] ], 'success' ); // phpcs:ignore
455 569
456 570 return;
457 571 }
458 572
@@ -460,9 +574,9 @@
460 574 }
461 575
462 576 if ( isset( $err_messages[ $_GET['pc_action'] ] ) ) {
463 577 if ( MENU_SLUG === $screen->parent_base ) { // display with shared-ui on plugin page
464 - add_settings_error( $screen->parent_file, MENU_SLUG, $err_messages[ $_GET['pc_action'] ], 'error' );
578 + add_settings_error( $screen->parent_file, MENU_SLUG, $err_messages[ $_GET['pc_action'] ], 'error' ); // phpcs:ignore
465 579
466 580 return;
467 581 }
468 582
@@ -499,36 +613,71 @@
499 613 * Purges all cache related things
500 614 *
501 615 * @since 1.1
502 616 */
503 -function purge_all_cache() {
617 +function purge_all_cache_action() {
504 618
505 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_purge_all_cache' ) ) {
619 + if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_purge_all_cache' ) ) { // phpcs:ignore
506 620 wp_nonce_ays( '' );
507 621 }
508 622
509 623 if ( is_multisite() && ! current_user_can( 'manage_network' ) ) {
510 624 $redirect_url = add_query_arg( 'pc_action', 'flush_all_cache_err_permission', wp_get_referer() );
625 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
626 + exit;
627 + }
511 628
512 - wp_safe_redirect( $redirect_url );
629 + if ( ! current_user_can( 'manage_options' ) ) {
630 + $redirect_url = add_query_arg( 'pc_action', 'flush_all_cache_err_permission', wp_get_referer() );
631 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
513 632 exit;
514 633 }
515 634
516 - powered_cache_flush();// cleans object cache + page cache dir
635 + purge_all_cache();
517 636
637 + $redirect_url = add_query_arg( 'pc_action', 'flush_all_cache', wp_get_referer() );
638 +
639 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
640 + exit;
641 +}
642 +
643 +
644 +/**
645 + * Purge all cache
646 + *
647 + * @param array $settings plugin settings
648 + *
649 + * @return void
650 + */
651 +function purge_all_cache( $settings = array() ) {
652 + $cache_purger = CachePurger::factory();
653 + if ( empty( $settings ) ) {
654 + $settings = \PoweredCache\Utils\get_settings();
655 + }
656 +
657 + if ( $settings['async_cache_cleaning'] ) {
658 + if ( function_exists( 'wp_cache_flush' ) ) {
659 + wp_cache_flush();
660 + }
661 + $cache_purger->push_to_queue( [ 'call' => 'powered_cache_flush' ] );
662 + $cache_purger->save()->dispatch();
663 + } else {
664 + powered_cache_flush();// cleans object cache + page cache dir
665 + }
666 +
518 667 /**
519 668 * Fires after purging all cache
520 669 *
521 670 * @hook powered_cache_purge_all_cache
522 - *
523 671 * @since 1.1
524 672 */
525 673 do_action( 'powered_cache_purge_all_cache' );
526 674
527 - $redirect_url = add_query_arg( 'pc_action', 'flush_all_cache', wp_get_referer() );
528 -
529 - wp_safe_redirect( $redirect_url );
530 - exit;
675 + if ( POWERED_CACHE_IS_NETWORK ) {
676 + delete_site_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT );
677 + } else {
678 + delete_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT );
679 + }
531 680 }
532 681
533 682
534 683 /**
@@ -536,19 +685,22 @@
536 685 *
537 686 * @since 1.1
538 687 */
539 688 function download_rewrite_config() {
540 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_download_rewrite' ) ) {
689 + if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'powered_cache_download_rewrite' ) ) { // phpcs:ignore
541 690 wp_nonce_ays( '' );
542 691 }
543 692
544 693 if ( ! can_control_all_settings() ) {
545 - wp_safe_redirect( wp_get_referer() );
694 + $redirect_url = add_query_arg( 'pc_action', 'generic_permission_err', wp_get_referer() );
695 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
546 696 exit;
547 697 }
548 698
549 - $server = $_GET['server'];
550 - Config::factory()->download_rewrite_rules( $server );
699 + if ( ! empty( $_GET['server'] ) ) {
700 + $server = sanitize_text_field( wp_unslash( $_GET['server'] ) );
701 + Config::factory()->download_rewrite_rules( $server );
702 + }
551 703
552 704 wp_safe_redirect( wp_get_referer() );
553 705 die();
554 706 }
@@ -591,21 +743,45 @@
591 743 /**
592 744 * Cancel preloading process on toggling preload option
593 745 */
594 746 function cancel_preloading() {
595 - \PoweredCache\Utils\log( 'Cancel preload process' );
747 + \PoweredCache\Utils\log( 'Cancel preload process - Settings toggle' );
596 748 $cache_preloader = CachePreloader::factory();
597 749 $cache_preloader->cancel_process();
750 + $cache_preloader->delete_all();
598 751 }
599 752
753 +/**
754 + * Kick-start preloading process
755 + *
756 + * @return void
757 + */
758 +function start_preloading() {
759 + \PoweredCache\Utils\log( 'Enable Preloader - Settings toggle' );
760 + Preloader::factory()->setup_preload_queue();
761 + // kickstart the preloading process
762 + Preloader::factory()->dispatch_preload_queue();
763 +}
600 764
601 765 /**
766 + * Cancel async cache purging processes
767 + *
768 + * @since 2.3
769 + */
770 +function cancel_async_cache_cleaning() {
771 + \PoweredCache\Utils\log( 'Cancel CachePurger process' );
772 + $cache_preloader = CachePurger::factory();
773 + $cache_preloader->cancel_process();
774 +}
775 +
776 +
777 +/**
602 778 * Perform diagnostic checks
603 779 */
604 780 function run_diagnostic() {
605 781 global $is_apache;
606 782
607 - $nonce = $_POST['nonce'];
783 + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
608 784
609 785 if ( wp_verify_nonce( $nonce, 'powered_cache_run_diagnostic' ) ) {
610 786 $settings = \PoweredCache\Utils\get_settings();
611 787 $checks = array();
@@ -709,9 +885,55 @@
709 885
710 886 wp_send_json_error( [ esc_html__( 'Invalid request', 'powered-cache' ) ] );
711 887 }
712 888
889 +/**
890 + * Check alloptions size like performance lab does.
891 + * It's critical to know this before enabling memcached based persistent object cache backends.
892 + * When alloptions size is too big (1mb in this case), it will cause performance degradation instead of improvement.
893 + *
894 + * @return void
895 + * @since 3.4
896 + */
897 +function check_alloptions() {
898 + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
899 + if ( ! wp_verify_nonce( $nonce, 'powered_cache_update_settings' ) || ! can_configure_object_cache() ) {
900 + wp_send_json_error( [ 'message' => esc_html__( 'Invalid request', 'powered-cache' ) ] );
713 901
902 + return;
903 + }
904 +
905 + $autoload_option_size = \PoweredCache\Utils\autoloaded_options_size();
906 + $autoload_option_count = count( wp_load_alloptions() );
907 +
908 + if ( $autoload_option_size > ALLOPTIONS_CRITICAL_THRESHOLD ) {
909 + $status = 'critical';
910 + } elseif ( $autoload_option_size > ALLOPTIONS_WARNING_THRESHOLD && $autoload_option_size <= ALLOPTIONS_CRITICAL_THRESHOLD ) {
911 + $status = 'warning';
912 + } else {
913 + $status = 'good';
914 + }
915 +
916 + $message = '<p><b>' . esc_html__( 'Autoloaded options could affect performance:', 'powered-cache' ) . '</b> ' .
917 + sprintf(
918 + esc_html__(
919 + /* translators: 1: Number of autoloaded options. 2: Size of autoloaded options. */
920 + '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.',
921 + 'powered-cache'
922 + ),
923 + esc_html( number_format_i18n( $autoload_option_count ) ),
924 + esc_html( size_format( $autoload_option_size ) )
925 + ) . '</p>';
926 +
927 + wp_send_json_success(
928 + [
929 + 'status' => $status,
930 + 'message' => $message,
931 + ]
932 + );
933 +}
934 +
935 +
714 936 /**
715 937 * Deactivate incompatible plugins
716 938 *
717 939 * @since 1.0
@@ -716,18 +938,22 @@
716 938 *
717 939 * @since 1.0
718 940 */
719 941 function deactivate_plugin() {
720 - if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'deactivate_plugin' ) ) {
942 + if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'deactivate_plugin' ) ) { // phpcs:ignore
721 943 wp_nonce_ays( '' );
722 944 }
723 945
724 946 if ( ! current_user_can( 'activate_plugins' ) ) {
725 - wp_safe_redirect( wp_get_referer() );
947 + $redirect_url = add_query_arg( 'pc_action', 'generic_permission_err', wp_get_referer() );
948 + wp_safe_redirect( esc_url_raw( $redirect_url ) );
726 949 exit;
727 950 }
728 951
729 - deactivate_plugins( $_GET['plugin'] );
952 + if ( isset( $_GET['plugin'] ) ) {
953 + $plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) );
954 + deactivate_plugins( $plugin );
955 + }
730 956
731 957 wp_safe_redirect( wp_get_referer() );
732 958 die();
733 959 }
@@ -751,5 +977,48 @@
751 977 $actions['get_premium'] = sprintf( '<a href="%s" style="color: red;">%s</a>', esc_url( $powered_cache_url ), esc_html__( 'Get Premium', 'powered-cache' ) );
752 978 }
753 979
754 980 return array_reverse( $actions );
981 +}
982 +
983 +/**
984 + * Conditionally process Cloudflare API key and token settings based on the form input.
985 + *
986 + * @param array $options The form options submitted by the user.
987 + *
988 + * @return array Updated options with processed Cloudflare settings.
989 + */
990 +function maybe_process_cloudflare_settings( $options ) {
991 + // Retrieve the previous Cloudflare API key and token values.
992 + $prev_cf_api_key = \PoweredCache\Extensions\Cloudflare\Cloudflare::get_cf_api_key();
993 + $prev_cf_api_token = \PoweredCache\Extensions\Cloudflare\Cloudflare::get_cf_api_token();
994 +
995 + // Check if the submitted Cloudflare API key matches the masked version of the previous key.
996 + if ( isset( $options['cloudflare_api_key'] ) && mask_string( $prev_cf_api_key, UNMASK_CHARACTER_LENGTH ) === $options['cloudflare_api_key'] ) {
997 + $options['cloudflare_api_key'] = $prev_cf_api_key; // Use the unmasked value.
998 + }
999 +
1000 + if ( isset( $options['cloudflare_api_token'] ) && mask_string( $prev_cf_api_token, UNMASK_CHARACTER_LENGTH ) === $options['cloudflare_api_token'] ) {
1001 + $options['cloudflare_api_token'] = $prev_cf_api_token; // Use the unmasked value.
1002 + }
1003 +
1004 + $encryption = new Encryption();
1005 + // Encrypt sensitive data if it's not empty.
1006 + if ( ! empty( $options['cloudflare_api_key'] ) ) {
1007 + $options['cloudflare_api_key'] = $encryption->encrypt( $options['cloudflare_api_key'] );
1008 + }
1009 +
1010 + if ( ! empty( $options['cloudflare_api_token'] ) ) {
1011 + $options['cloudflare_api_token'] = $encryption->encrypt( $options['cloudflare_api_token'] );
1012 + }
1013 +
1014 + // Override with empty values if constants are defined.
1015 + if ( defined( 'POWERED_CACHE_CF_API_KEY' ) && POWERED_CACHE_CF_API_KEY ) {
1016 + $options['cloudflare_api_key'] = '';
1017 + }
1018 +
1019 + if ( defined( 'POWERED_CACHE_CF_API_TOKEN' ) && POWERED_CACHE_CF_API_TOKEN ) {
1020 + $options['cloudflare_api_token'] = '';
1021 + }
1022 +
1023 + return $options;
755 1024 }