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
powered-cache / includes / admin / notices.php

notices.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score trunk, at includes/admin/notices.php

524 lines 17.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Notices
4 *
5 * @package PoweredCache
6 */
7
8 namespace PoweredCache\Admin\Notices;
9
10 use function PoweredCache\Utils\can_configure_htaccess;
11 use function PoweredCache\Utils\can_configure_object_cache;
12 use function PoweredCache\Utils\can_control_all_settings;
13 use function PoweredCache\Utils\get_object_cache_dropins;
14 use function PoweredCache\Utils\is_premium;
15 use const PoweredCache\Constants\PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT;
16
17 /**
18 * Default setup routine
19 *
20 * @return void
21 */
22 function setup() {
23 if ( POWERED_CACHE_IS_NETWORK ) {
24 add_action( 'network_admin_notices', __NAMESPACE__ . '\\maybe_display_plugin_compatibility_notices' );
25 add_action( 'network_admin_notices', __NAMESPACE__ . '\\maybe_display_advanced_cache_notices' );
26 add_action( 'network_admin_notices', __NAMESPACE__ . '\\maybe_display_object_cache_notices' );
27 add_action( 'network_admin_notices', __NAMESPACE__ . '\\maybe_display_htaccess_notice' );
28 add_action( 'network_admin_notices', __NAMESPACE__ . '\\maybe_display_purge_cache_plugin_notice' );
29 add_action( 'network_admin_notices', __NAMESPACE__ . '\\maybe_display_dev_mode_notice' );
30 } else {
31 add_action( 'admin_notices', __NAMESPACE__ . '\\maybe_display_plugin_compatibility_notices' );
32 add_action( 'admin_notices', __NAMESPACE__ . '\\maybe_display_advanced_cache_notices' );
33 add_action( 'admin_notices', __NAMESPACE__ . '\\maybe_display_object_cache_notices' );
34 add_action( 'admin_notices', __NAMESPACE__ . '\\maybe_display_htaccess_notice' );
35 add_action( 'admin_notices', __NAMESPACE__ . '\\maybe_display_purge_cache_plugin_notice' );
36 add_action( 'admin_notices', __NAMESPACE__ . '\\maybe_display_dev_mode_notice' );
37 }
38
39 add_action( 'activated_plugin', __NAMESPACE__ . '\\observe_plugin_changes', 10, 2 );
40 add_action( 'deactivated_plugin', __NAMESPACE__ . '\\observe_plugin_changes', 10, 2 );
41 add_action( 'admin_post_powered_cache_dismiss_notice', __NAMESPACE__ . '\\dismiss_notice' );
42 add_action( 'wp_ajax_powered_cache_dismiss_notice_ajax', __NAMESPACE__ . '\\dismiss_notice_ajax' );
43 }
44
45 /**
46 * Display incompatible plugins
47 *
48 * @since 1.0
49 */
50 function maybe_display_plugin_compatibility_notices() {
51 $settings = \PoweredCache\Utils\get_settings();
52
53 $plugins = array(
54 'hummingbird-performance' => 'hummingbird-performance/wp-hummingbird.php',
55 'wp-rocket' => 'wp-rocket/wp-rocket.php',
56 'w3-total-cache' => 'w3-total-cache/w3-total-cache.php',
57 'wp-super-cache' => 'wp-super-cache/wp-cache.php',
58 'hyper-cache' => 'hyper-cache/plugin.php',
59 'hyper-cache-extended' => 'hyper-cache-extended/plugin.php',
60 'wp-fast-cache' => 'wp-fast-cache/wp-fast-cache.php',
61 'flexicache' => 'flexicache/wp-plugin.php',
62 'wp-fastest-cache' => 'wp-fastest-cache/wpFastestCache.php',
63 'wp-http-compression' => 'wp-http-compression/wp-http-compression.php',
64 'wordpress-gzip-compression' => 'wordpress-gzip-compression/ezgz.php',
65 'gzip-ninja-speed-compression' => 'gzip-ninja-speed-compression/gzip-ninja-speed.php',
66 'speed-booster-pack' => 'speed-booster-pack/speed-booster-pack.php',
67 'wp-performance-score-booster' => 'wp-performance-score-booster/wp-performance-score-booster.php',
68 'check-and-enable-gzip-compression' => 'check-and-enable-gzip-compression/richards-toolbox.php',
69 'swift-performance-lite' => 'swift-performance-lite/performance.php',
70 'swift-performance' => 'swift-performance/performance.php',
71 'litespeed-cache' => 'litespeed-cache/litespeed-cache.php',
72 'wp-optimize' => 'wp-optimize/wp-optimize.php',
73 );
74
75 if ( $settings['prefetch_links'] && is_premium() ) {
76 $plugins['quicklink'] = 'quicklink/quicklink.php';
77 $plugins['flying-pages'] = 'flying-pages/flying-pages.php';
78 $plugins['instant-page'] = 'instant-page/instantpage.php';
79 }
80
81 $callback = POWERED_CACHE_IS_NETWORK ? 'is_plugin_active_for_network' : 'is_plugin_active';
82
83 $plugins = array_filter( $plugins, $callback );
84
85 if ( 0 >= count( $plugins ) ) {
86 return;
87 }
88 ?>
89
90 <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
91 <div class="error">
92 <p><?php esc_html_e( 'The following plugins are not compatible with Powered Cache and may cause unintended results:', 'powered-cache' ); ?></p>
93 <ul class="incompatible-plugin-list">
94 <?php
95 foreach ( $plugins as $plugin ) {
96 $plugin_data = get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin );
97 echo '<li>' . esc_attr( $plugin_data['Name'] ) . '</span> <a href="' . esc_url_raw( wp_nonce_url( admin_url( 'admin-post.php?action=deactivate_plugin&plugin=' . rawurlencode( $plugin ) ), 'deactivate_plugin' ) ) . '" class="button-secondary">' . esc_html__( 'Deactivate', 'powered-cache' ) . '</a></li>'; // phpcs:ignore WordPressVIPMinimum.Security.ProperEscapingFunction.notAttrEscAttr
98 }
99 ?>
100 </ul>
101 </div>
102 <?php endif; ?>
103
104 <?php
105 }
106
107
108 /**
109 * Show notices about page cache
110 *
111 * @since 1.0
112 */
113 function maybe_display_advanced_cache_notices() {
114 /**
115 * Determine whether show or not show advanced cache related notices
116 * eg: Varnish users don't need to turning on page cache.
117 *
118 * @hook powered_cache_disable_advanced_cache_notices
119 *
120 * @param {boolean} $status false
121 *
122 * @return {boolean} New value
123 * @since 1.2
124 */
125 if ( apply_filters( 'powered_cache_disable_advanced_cache_notices', false ) ) {
126 return;
127 }
128
129 $settings = \PoweredCache\Utils\get_settings();
130
131 if ( ! $settings['enable_page_cache'] ) {
132
133 $settings_page = POWERED_CACHE_IS_NETWORK ? network_admin_url( 'admin.php?page=powered-cache#basic-options' ) : admin_url( 'admin.php?page=powered-cache#basic-options' );
134
135 /* translators: %s: Powered Cache settings page URL */
136 $message = sprintf( __( '<strong>Powered Cache:</strong> Page caching needs to be activated in order to speed up your website. Please activate it on <a href="%s">settings page</a>', 'powered-cache' ), esc_url( $settings_page ) );
137 ?>
138 <div class="notice notice-warning">
139 <p>
140 <?php echo wp_kses_post( $message ); ?>
141 </p>
142 </div>
143 <?php
144 return;
145 }
146
147 if ( file_exists( untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php' ) ) {
148 $modify_time = filemtime( untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php' );
149 if ( time() - absint( $modify_time ) < 10 ) {
150 /**
151 * Modify drop-ins and can take ~5 seconds to place the configuration and it might cause misinformation to the user
152 * So, suppress the error message here when doing something related to settings.
153 *
154 * This wouldn't be an issue if there is no immediate redirection right after saving the settings. However, in that case
155 * the admin bar items won't be properly utilized unless refreshing the page
156 */
157 return;
158 }
159 }
160
161 $err = array();
162
163 if ( ! defined( 'WP_CACHE' ) || true !== WP_CACHE ) {
164 /* translators: %s: WP_CACHE definition*/
165 $err['wp_cache'] = sprintf( __( '<code>%s</code> is not found in wp-config.php.', 'powered-cache' ), 'define("WP_CACHE", true);' );
166 }
167
168 if ( defined( 'WP_CACHE' ) && WP_CACHE && ( ! defined( 'POWERED_CACHE_PAGE_CACHING' ) || true !== POWERED_CACHE_PAGE_CACHING ) ) {
169 /* translators: %s: advanced-cache.php drop-in path */
170 $err['powered_cache_page_cache'] = sprintf( __( '<code>%s</code> file was edited or deleted. You can recreate the correct configuration files by saving Powered Cache settings.', 'powered-cache' ), basename( WP_CONTENT_DIR ) . '/advanced-cache.php' );
171 }
172
173 if ( defined( 'POWERED_CACHE_PAGE_CACHING_HAS_PROBLEM' ) && POWERED_CACHE_PAGE_CACHING_HAS_PROBLEM ) {
174 /* translators: %s: page-cache.php drop-in path */
175 $err['powered_cache_page_cache_has_problem'] = sprintf( __( 'Powered Cache could not access dropin. Please check <code>%s</code> exist and accessible on your server.', 'powered-cache' ), POWERED_CACHE_DROPIN_DIR . 'page-cache.php' );
176 }
177
178 // everything ok
179 if ( empty( $err ) ) {
180 return;
181 }
182
183 // dont show when settings just saved
184 if ( did_action( 'powered_cache_settings_saved' ) ) {
185 return;
186 }
187
188 $capability = POWERED_CACHE_IS_NETWORK ? 'manage_network' : 'manage_options';
189
190 if ( ! current_user_can( $capability ) ) {
191 return;
192 }
193 ?>
194 <div class="error">
195 <p>
196 <strong><?php esc_html_e( 'Page Cache is not working, because:', 'powered-cache' ); ?></strong>
197 </p>
198 <?php foreach ( $err as $error_msg ) : ?>
199 <p><?php echo wp_kses_post( $error_msg ); ?></p>
200 <?php endforeach; ?>
201 </div>
202 <?php
203
204 }
205
206
207 /**
208 * Display object cache broken msg
209 *
210 * @since 1.0
211 */
212 function maybe_display_object_cache_notices() {
213 $settings = \PoweredCache\Utils\get_settings();
214
215 $object_cache_backends = get_object_cache_dropins();
216 $object_cache_driver = $settings['object_cache'];
217 $object_cache_dropin = untrailingslashit( WP_CONTENT_DIR ) . '/object-cache.php';
218
219 if ( ! can_configure_object_cache() ) {
220 return;
221 }
222
223 // dont show when settings just saved
224 if ( did_action( 'powered_cache_settings_saved' ) ) {
225 return;
226 }
227
228 if ( file_exists( $object_cache_dropin ) ) {
229 $modify_time = filemtime( $object_cache_dropin );
230 if ( time() - absint( $modify_time ) < 10 ) { // just created
231 return;
232 }
233 }
234
235 // first check object cache file exist
236 if ( isset( $object_cache_backends[ $object_cache_driver ] ) && ! file_exists( $object_cache_dropin ) ) {
237 /* translators: %s: object cache dropin path */
238 $message = sprintf( __( 'The object cache file seems missing. Please check <code>%s</code> exist, writable and accessible on your server.', 'powered-cache' ), $object_cache_dropin );
239 ?>
240 <div class="error">
241 <p><strong><?php esc_html_e( 'Powered Cache:', 'powered-cache' ); ?></strong>
242 <?php echo wp_kses_post( $message ); ?>
243 </p>
244 </div>
245 <?php
246 return;
247 }
248
249 if ( defined( 'POWERED_OBJECT_CACHE_HAS_PROBLEM' ) && POWERED_OBJECT_CACHE_HAS_PROBLEM ) {
250 $broken_file = '';
251
252 if ( isset( $object_cache_backends[ $object_cache_driver ] ) ) {
253 $broken_file = $object_cache_backends[ $object_cache_driver ];
254 }
255 /* translators: %s: object cache dropin path */
256 $message = sprintf( __( 'The object cache file couldn\'t be loaded. Please check <code>%s</code> exist and accessible on your server.', 'powered-cache' ), $broken_file );
257 ?>
258 <div class="error">
259 <p><strong><?php esc_html_e( 'Powered Cache:', 'powered-cache' ); ?></strong>
260 <?php echo wp_kses_post( $message ); ?>
261 </p>
262 </div>
263 <?php
264 }
265
266 }
267
268 /**
269 * Notices for the .htaccess
270 *
271 * @since 1.2
272 */
273 function maybe_display_htaccess_notice() {
274 global $is_apache;
275
276 if ( ! $is_apache ) {
277 return;
278 }
279
280 $settings = \PoweredCache\Utils\get_settings();
281
282 if ( ! $settings['auto_configure_htaccess'] ) {
283 return;
284 }
285
286 if ( ! can_configure_htaccess() ) {
287 return;
288 }
289
290 // dont show when settings just saved
291 if ( did_action( 'powered_cache_settings_saved' ) ) {
292 return;
293 }
294
295 $htaccess_file = get_home_path() . '.htaccess';
296
297 if ( file_exists( $htaccess_file ) ) {
298 $modify_time = filemtime( $htaccess_file );
299 if ( time() - absint( $modify_time ) < 10 ) { // just modified
300 return;
301 }
302 }
303
304 $message = '';
305
306 if ( ! file_exists( $htaccess_file ) ) {
307 $message = __( 'The <code>.htaccess</code> couldn\'t be found on your server. Please create a new <code>.htaccess</code> file. (<a href="https://wordpress.org/support/article/htaccess/" target="_blank" rel="noopener">?</a>)', 'powered-cache' );
308 } elseif ( ! is_writeable( $htaccess_file ) ) {
309 $message = __( 'Oh no! It looks <code>.htaccess</code> file is not writable. Please make sure it is writable by the application server. Your website will be much faster when .htaccess is configured for Powered Cache.', 'powered-cache' );
310 }
311
312 if ( empty( $message ) ) {
313 return;
314 }
315
316 ?>
317
318 <div class="error">
319 <p><strong><?php esc_html_e( 'Powered Cache:', 'powered-cache' ); ?></strong>
320 <?php echo wp_kses_post( $message ); ?>
321 </p>
322 </div>
323
324 <?php
325 }
326
327 /**
328 * Observe new plugin activation/deactivation
329 *
330 * @param string $plugin file
331 * @param boolean $network_wide Whether plugin de/activated network wide or not
332 *
333 * @return void
334 * @since 3.2
335 */
336 function observe_plugin_changes( $plugin, $network_wide ) {
337 if ( false !== stripos( $plugin, 'powered-cache' ) ) {
338 return;
339 }
340
341 if ( $network_wide ) {
342 set_site_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT, '1' );
343
344 return;
345 }
346
347 set_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT, '1' );
348 }
349
350 /**
351 * Display cache purging notice upon a new plugin activated/deactivated
352 *
353 * @return void
354 * @since 3.2
355 */
356 function maybe_display_purge_cache_plugin_notice() {
357 $has_notice = false;
358
359 if ( POWERED_CACHE_IS_NETWORK && current_user_can( 'manage_network' ) ) {
360 $has_notice = get_site_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT );
361 $purge_url = wp_nonce_url( admin_url( 'admin-post.php?action=powered_cache_purge_page_cache_network' ), 'powered_cache_purge_page_cache_network' );
362 } elseif ( current_user_can( 'activate_plugins' ) ) {
363 $has_notice = get_transient( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT );
364 $purge_url = wp_nonce_url( admin_url( 'admin-post.php?action=powered_cache_purge_all_cache' ), 'powered_cache_purge_all_cache' );
365 }
366
367 if ( $has_notice ) {
368 $message = __( '<strong>Powered Cache:</strong> One or more plugins have been activated or deactivated; consider clearing the cache if these changes impact your site\'s front end.', 'powered-cache' );
369 $dismiss_nonce = wp_create_nonce( 'powered_cache_dismiss_notice_ajax' );
370 ?>
371 <div class="notice notice-warning is-dismissible powered-cache-dismissible-notice" data-notice-id="<?php echo esc_attr( PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT ); ?>" data-nonce="<?php echo esc_attr( $dismiss_nonce ); ?>">
372 <p>
373 <?php echo wp_kses_post( $message ); ?>
374 </p>
375 <p>
376 <a href="<?php echo esc_url_raw( $purge_url ); ?>" class="button-primary">
377 <?php esc_html_e( 'Purge Cache', 'powered-cache' ); ?>
378 </a>
379 <a href="<?php echo esc_url_raw( wp_nonce_url( admin_url( 'admin-post.php?action=powered_cache_dismiss_notice&notice=' . PURGE_CACHE_PLUGIN_NOTICE_TRANSIENT ), 'powered_cache_dismiss_notice' ) ); ?>" class="button-secondary powered-cache-dismiss-button">
380 <?php esc_html_e( 'Dismiss this notice', 'powered-cache' ); ?>
381 </a>
382 </p>
383 </div>
384 <script type="text/javascript">
385 (function() {
386 document.addEventListener('click', function(e) {
387 var button = e.target.closest('.notice-dismiss, .powered-cache-dismiss-button');
388 if (!button) {
389 return;
390 }
391
392 var notice = button.closest('.powered-cache-dismissible-notice');
393 if (!notice) {
394 return;
395 }
396
397 e.preventDefault();
398
399 var noticeId = notice.getAttribute('data-notice-id');
400 var nonce = notice.getAttribute('data-nonce');
401
402 if (button.classList.contains('powered-cache-dismiss-button')) {
403 e.preventDefault();
404 notice.style.opacity = '1';
405 notice.style.transition = 'opacity 0.3s';
406 notice.style.opacity = '0';
407
408 setTimeout(function() {
409 if (notice && notice.parentNode) {
410 notice.parentNode.removeChild(notice);
411 }
412 }, 300);
413 }
414
415 var xhr = new XMLHttpRequest();
416 xhr.open('POST', '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>', true);
417 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
418 xhr.onload = function () {
419 if (xhr.status !== 200) {
420 console.error('Dismiss failed');
421 }
422 };
423
424 xhr.send(
425 'action=powered_cache_dismiss_notice_ajax'
426 + '&notice=' + encodeURIComponent(noticeId)
427 + '&nonce=' + encodeURIComponent(nonce)
428 );
429 });
430 })();
431 </script>
432 <?php
433 }
434 }
435
436 /**
437 * Dismis given notice
438 *
439 * @return void
440 * @since 3.2
441 */
442 function dismiss_notice() {
443 $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
444 if ( ! wp_verify_nonce( $nonce, 'powered_cache_dismiss_notice' ) ) {
445 wp_nonce_ays( '' );
446 }
447
448 if ( current_user_can( 'manage_options' ) && ! empty( $_GET['notice'] ) ) {
449 $notice = sanitize_text_field( wp_unslash( $_GET['notice'] ) );
450
451 if ( POWERED_CACHE_IS_NETWORK ) {
452 delete_site_transient( $notice );
453 } else {
454 delete_transient( $notice );
455 }
456 }
457
458 wp_safe_redirect( esc_url_raw( wp_get_referer() ) );
459 exit;
460 }
461
462 /**
463 * Dismiss notice via AJAX
464 *
465 * @return void
466 * @since 3.7
467 */
468 function dismiss_notice_ajax() {
469 check_ajax_referer( 'powered_cache_dismiss_notice_ajax', 'nonce' );
470
471 if ( ! current_user_can( 'manage_options' ) ) {
472 wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'powered-cache' ) ) );
473 }
474
475 if ( empty( $_POST['notice'] ) ) {
476 wp_send_json_error( array( 'message' => esc_html__( 'Notice ID missing', 'powered-cache' ) ) );
477 }
478
479 $notice = sanitize_text_field( wp_unslash( $_POST['notice'] ) );
480
481 if ( POWERED_CACHE_IS_NETWORK ) {
482 delete_site_transient( $notice );
483 } else {
484 delete_transient( $notice );
485 }
486
487 wp_send_json_success( array( 'message' => esc_html__( 'Notice dismissed', 'powered-cache' ) ) );
488 }
489
490 /**
491 * Display a notice when development mode is active
492 *
493 * @return void
494 * @since 3.6
495 * @related \PoweredCache\DevMode
496 */
497 function maybe_display_dev_mode_notice() {
498 if ( ! \PoweredCache\Utils\is_dev_mode_active() ) {
499 return;
500 }
501
502 if ( ! current_user_can( 'manage_options' ) ) {
503 return;
504 }
505
506 // Only display on Powered Cache settings page
507 $current_screen = get_current_screen();
508
509 if (
510 ! $current_screen
511 || ( ! isset( $current_screen->id ) || false === strpos( $current_screen->id, 'powered-cache' ) )
512 ) {
513 return;
514 }
515
516 ?>
517 <div class="notice notice-warning is-dismissible">
518 <p><strong><?php esc_html_e( 'Development Mode is active.', 'powered-cache' ); ?></strong>
519 <?php esc_html_e( 'Caching and optimizations are currently disabled. Don’t forget to disable it when done.', 'powered-cache' ); ?>
520 </p>
521 </div>
522 <?php
523 }
524