Version Description
- Fixed bytes metrics calculation
- Fixed an issue with non-standard Predis configurations
- Improve WordPress Coding Standards
Download this release
Release Info
Developer | tillkruess |
Plugin | Redis Object Cache |
Version | 2.0.12 |
Comparing to | |
See all releases |
Code changes from version 2.0.11 to 2.0.12
- assets/js/admin.js +5 -2
- includes/class-plugin.php +283 -58
- includes/class-qm-collector.php +29 -6
- includes/class-qm-output.php +36 -2
- includes/class-ui.php +1 -7
- includes/object-cache.php +132 -113
- includes/ui/class-tab.php +219 -0
- includes/ui/diagnostics.php +8 -8
- includes/ui/settings.php +13 -17
- includes/ui/tabs/diagnostics.php +0 -2
- includes/ui/tabs/overview.php +18 -19
- languages/redis-cache.pot +96 -96
- readme.txt +8 -2
- redis-cache.php +1 -1
assets/js/admin.js
CHANGED
@@ -354,7 +354,7 @@
|
|
354 |
time: function ( entry ) {
|
355 |
return [ entry[0], entry[1] * 0.5 ]
|
356 |
},
|
357 |
-
|
358 |
return [ entry[0], entry[1] * 0.3 ]
|
359 |
},
|
360 |
calls: function ( entry ) {
|
@@ -449,9 +449,12 @@
|
|
449 |
function ( event ) {
|
450 |
event.preventDefault();
|
451 |
|
|
|
|
|
452 |
$.post( ajaxurl, {
|
453 |
-
notice: $
|
454 |
action: 'roc_dismiss_notice',
|
|
|
455 |
} );
|
456 |
}
|
457 |
);
|
354 |
time: function ( entry ) {
|
355 |
return [ entry[0], entry[1] * 0.5 ]
|
356 |
},
|
357 |
+
bytes: function ( entry ) {
|
358 |
return [ entry[0], entry[1] * 0.3 ]
|
359 |
},
|
360 |
calls: function ( entry ) {
|
449 |
function ( event ) {
|
450 |
event.preventDefault();
|
451 |
|
452 |
+
var $parent = $( this ).parent();
|
453 |
+
|
454 |
$.post( ajaxurl, {
|
455 |
+
notice: $parent.data( 'dismissible' ),
|
456 |
action: 'roc_dismiss_notice',
|
457 |
+
_ajax_nonce: $parent.data( 'nonce' ),
|
458 |
} );
|
459 |
}
|
460 |
);
|
includes/class-plugin.php
CHANGED
@@ -12,12 +12,30 @@ use Exception;
|
|
12 |
|
13 |
defined( '\\ABSPATH' ) || exit;
|
14 |
|
|
|
|
|
|
|
15 |
class Plugin {
|
16 |
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
18 |
|
|
|
|
|
|
|
|
|
|
|
19 |
private $screen = '';
|
20 |
|
|
|
|
|
|
|
|
|
|
|
21 |
private $actions = array(
|
22 |
'enable-cache',
|
23 |
'disable-cache',
|
@@ -26,14 +44,14 @@ class Plugin {
|
|
26 |
);
|
27 |
|
28 |
/**
|
29 |
-
* Plugin instance property
|
30 |
*
|
31 |
* @var Plugin
|
32 |
*/
|
33 |
private static $instance;
|
34 |
|
35 |
/**
|
36 |
-
* Plugin instanciation method
|
37 |
*
|
38 |
* @return Plugin
|
39 |
*/
|
@@ -45,6 +63,9 @@ class Plugin {
|
|
45 |
return self::$instance;
|
46 |
}
|
47 |
|
|
|
|
|
|
|
48 |
private function __construct() {
|
49 |
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
50 |
|
@@ -66,6 +87,11 @@ class Plugin {
|
|
66 |
}
|
67 |
}
|
68 |
|
|
|
|
|
|
|
|
|
|
|
69 |
public function add_actions_and_filters() {
|
70 |
add_action( 'deactivate_plugin', array( $this, 'on_deactivation' ) );
|
71 |
add_action( 'admin_init', array( $this, 'maybe_update_dropin' ) );
|
@@ -97,8 +123,12 @@ class Plugin {
|
|
97 |
add_filter( 'qm/outputter/html', array( $this, 'register_qm_output' ) );
|
98 |
}
|
99 |
|
|
|
|
|
|
|
|
|
|
|
100 |
public function add_admin_menu_page() {
|
101 |
-
// add sub-page to "Settings"
|
102 |
add_submenu_page(
|
103 |
is_multisite() ? 'settings.php' : 'options-general.php',
|
104 |
__( 'Redis Object Cache', 'redis-cache' ),
|
@@ -109,18 +139,24 @@ class Plugin {
|
|
109 |
);
|
110 |
}
|
111 |
|
|
|
|
|
|
|
|
|
|
|
112 |
public function show_admin_page() {
|
113 |
-
//
|
114 |
if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) {
|
115 |
-
$action = $_GET['action'];
|
|
|
116 |
|
117 |
foreach ( $this->actions as $name ) {
|
118 |
-
//
|
119 |
-
if ( $action === $name && wp_verify_nonce( $
|
120 |
$url = $this->action_link( $action );
|
121 |
|
122 |
if ( $this->initialize_filesystem( $url ) === false ) {
|
123 |
-
return; //
|
124 |
}
|
125 |
}
|
126 |
}
|
@@ -147,10 +183,15 @@ class Plugin {
|
|
147 |
__( 'Diagnostics', 'redis-cache' )
|
148 |
);
|
149 |
|
150 |
-
//
|
151 |
require_once WP_REDIS_PLUGIN_PATH . '/includes/ui/settings.php';
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
|
|
154 |
public function setup_dashboard_widget() {
|
155 |
if ( defined( 'WP_REDIS_DISABLE_METRICS' ) && WP_REDIS_DISABLE_METRICS ) {
|
156 |
return;
|
@@ -163,18 +204,33 @@ class Plugin {
|
|
163 |
);
|
164 |
}
|
165 |
|
|
|
|
|
|
|
|
|
|
|
166 |
public function show_dashboard_widget() {
|
167 |
require_once WP_REDIS_PLUGIN_PATH . '/includes/ui/widget.php';
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
public function add_plugin_actions_links( $links ) {
|
171 |
-
// add settings link to plugin actions
|
172 |
return array_merge(
|
173 |
[ sprintf( '<a href="%s">%s</a>', network_admin_url( $this->page ), esc_html__( 'Settings', 'redis-cache' ) ) ],
|
174 |
$links
|
175 |
);
|
176 |
}
|
177 |
|
|
|
|
|
|
|
|
|
|
|
178 |
public function enqueue_admin_styles() {
|
179 |
$screen = get_current_screen();
|
180 |
|
@@ -188,13 +244,18 @@ class Plugin {
|
|
188 |
'dashboard-network',
|
189 |
);
|
190 |
|
191 |
-
if ( ! in_array( $screen->id, $screens ) ) {
|
192 |
return;
|
193 |
}
|
194 |
|
195 |
wp_enqueue_style( 'redis-cache', WP_REDIS_DIR . '/assets/css/admin.css', null, WP_REDIS_VERSION );
|
196 |
}
|
197 |
|
|
|
|
|
|
|
|
|
|
|
198 |
public function enqueue_admin_scripts() {
|
199 |
$screen = get_current_screen();
|
200 |
|
@@ -211,7 +272,7 @@ class Plugin {
|
|
211 |
'woocommerce_page_wc-admin',
|
212 |
);
|
213 |
|
214 |
-
if ( ! in_array( $screen->id, $screens ) ) {
|
215 |
return;
|
216 |
}
|
217 |
|
@@ -219,7 +280,8 @@ class Plugin {
|
|
219 |
'redis-cache',
|
220 |
plugins_url( 'assets/js/admin.js', WP_REDIS_FILE ),
|
221 |
array( 'jquery', 'underscore' ),
|
222 |
-
WP_REDIS_VERSION
|
|
|
223 |
);
|
224 |
|
225 |
wp_localize_script(
|
@@ -242,6 +304,11 @@ class Plugin {
|
|
242 |
);
|
243 |
}
|
244 |
|
|
|
|
|
|
|
|
|
|
|
245 |
public function enqueue_redis_metrics() {
|
246 |
global $wp_object_cache;
|
247 |
|
@@ -255,7 +322,7 @@ class Plugin {
|
|
255 |
return;
|
256 |
}
|
257 |
|
258 |
-
if ( ! in_array( $screen->id, array( $this->screen, 'dashboard', 'dashboard-network' ) ) ) {
|
259 |
return;
|
260 |
}
|
261 |
|
@@ -263,7 +330,8 @@ class Plugin {
|
|
263 |
'redis-cache-charts',
|
264 |
plugins_url( 'assets/js/apexcharts.min.js', WP_REDIS_FILE ),
|
265 |
null,
|
266 |
-
WP_REDIS_VERSION
|
|
|
267 |
);
|
268 |
|
269 |
if ( ! method_exists( $wp_object_cache, 'redis_instance' ) ) {
|
@@ -279,17 +347,29 @@ class Plugin {
|
|
279 |
);
|
280 |
|
281 |
wp_localize_script( 'redis-cache', 'rediscache_metrics', $metrics );
|
282 |
-
} catch (Exception $exception) {
|
283 |
-
error_log($exception);
|
284 |
}
|
285 |
}
|
286 |
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
public function register_qm_collector( array $collectors ) {
|
288 |
$collectors['cache'] = new QM_Collector();
|
289 |
|
290 |
return $collectors;
|
291 |
}
|
292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
public function register_qm_output( $output ) {
|
294 |
$collector = \QM_Collectors::get( 'cache' );
|
295 |
|
@@ -303,10 +383,20 @@ class Plugin {
|
|
303 |
return $output;
|
304 |
}
|
305 |
|
|
|
|
|
|
|
|
|
|
|
306 |
public function object_cache_dropin_exists() {
|
307 |
return file_exists( WP_CONTENT_DIR . '/object-cache.php' );
|
308 |
}
|
309 |
|
|
|
|
|
|
|
|
|
|
|
310 |
public function validate_object_cache_dropin() {
|
311 |
if ( ! $this->object_cache_dropin_exists() ) {
|
312 |
return false;
|
@@ -318,6 +408,11 @@ class Plugin {
|
|
318 |
return $dropin['PluginURI'] === $plugin['PluginURI'];
|
319 |
}
|
320 |
|
|
|
|
|
|
|
|
|
|
|
321 |
public function object_cache_dropin_outdated() {
|
322 |
if ( ! $this->object_cache_dropin_exists() ) {
|
323 |
return false;
|
@@ -333,6 +428,11 @@ class Plugin {
|
|
333 |
return false;
|
334 |
}
|
335 |
|
|
|
|
|
|
|
|
|
|
|
336 |
public function get_status() {
|
337 |
global $wp_object_cache;
|
338 |
|
@@ -380,6 +480,12 @@ class Plugin {
|
|
380 |
return $wp_object_cache->redis_status();
|
381 |
}
|
382 |
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
public function get_redis_version() {
|
384 |
global $wp_object_cache;
|
385 |
|
@@ -392,6 +498,11 @@ class Plugin {
|
|
392 |
}
|
393 |
}
|
394 |
|
|
|
|
|
|
|
|
|
|
|
395 |
public function get_redis_client_name() {
|
396 |
global $wp_object_cache;
|
397 |
|
@@ -404,6 +515,11 @@ class Plugin {
|
|
404 |
}
|
405 |
}
|
406 |
|
|
|
|
|
|
|
|
|
|
|
407 |
public function get_diagnostics() {
|
408 |
global $wp_object_cache;
|
409 |
|
@@ -412,21 +528,36 @@ class Plugin {
|
|
412 |
}
|
413 |
}
|
414 |
|
|
|
|
|
|
|
|
|
|
|
415 |
public function get_redis_prefix() {
|
416 |
return defined( 'WP_REDIS_PREFIX' ) ? WP_REDIS_PREFIX : null;
|
417 |
}
|
418 |
|
|
|
|
|
|
|
|
|
|
|
419 |
public function get_redis_maxttl() {
|
420 |
return defined( 'WP_REDIS_MAXTTL' ) ? WP_REDIS_MAXTTL : null;
|
421 |
}
|
422 |
|
|
|
|
|
|
|
|
|
|
|
423 |
public function show_admin_notices() {
|
424 |
if ( ! defined( 'WP_REDIS_DISABLE_BANNERS' ) || ! WP_REDIS_DISABLE_BANNERS ) {
|
425 |
$this->pro_notice();
|
426 |
$this->wc_pro_notice();
|
427 |
}
|
428 |
|
429 |
-
//
|
430 |
if ( ! current_user_can( is_multisite() ? 'manage_network_options' : 'manage_options' ) ) {
|
431 |
return;
|
432 |
}
|
@@ -436,34 +567,40 @@ class Plugin {
|
|
436 |
|
437 |
if ( $this->validate_object_cache_dropin() ) {
|
438 |
if ( $this->object_cache_dropin_outdated() ) {
|
439 |
-
// translators: %s = Action link to update the drop-in
|
440 |
$message = sprintf( __( 'The Redis object cache drop-in is outdated. Please <a href="%s">update the drop-in</a>.', 'redis-cache' ), $url );
|
441 |
}
|
442 |
} else {
|
443 |
-
// translators: %s = Action link to update the drop-in
|
444 |
$message = sprintf( __( 'A foreign object cache drop-in was found. To use Redis for object caching, please <a href="%s">enable the drop-in</a>.', 'redis-cache' ), $url );
|
445 |
}
|
446 |
|
447 |
if ( isset( $message ) ) {
|
448 |
-
printf( '<div class="update-nag">%s</div>', $message );
|
449 |
}
|
450 |
}
|
451 |
}
|
452 |
|
|
|
|
|
|
|
|
|
|
|
453 |
public function do_admin_actions() {
|
454 |
global $wp_filesystem;
|
455 |
|
456 |
if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) {
|
457 |
-
$action = $_GET['action'];
|
|
|
458 |
|
459 |
-
//
|
460 |
foreach ( $this->actions as $name ) {
|
461 |
-
if ( $action === $name && ! wp_verify_nonce( $
|
462 |
return;
|
463 |
}
|
464 |
}
|
465 |
|
466 |
-
if ( in_array( $action, $this->actions ) ) {
|
467 |
$url = $this->action_link( $action );
|
468 |
|
469 |
if ( $action === 'flush-cache' ) {
|
@@ -518,12 +655,14 @@ class Plugin {
|
|
518 |
$result
|
519 |
? add_settings_error(
|
520 |
'redis-cache',
|
521 |
-
'dropin',
|
|
|
522 |
'updated'
|
523 |
)
|
524 |
: add_settings_error(
|
525 |
'redis-cache',
|
526 |
-
'dropin',
|
|
|
527 |
'error'
|
528 |
);
|
529 |
}
|
@@ -552,7 +691,6 @@ class Plugin {
|
|
552 |
'error'
|
553 |
);
|
554 |
}
|
555 |
-
|
556 |
}
|
557 |
|
558 |
$messages = get_settings_errors( 'redis-cache' );
|
@@ -569,17 +707,31 @@ class Plugin {
|
|
569 |
}
|
570 |
}
|
571 |
|
|
|
|
|
|
|
|
|
|
|
572 |
public function dismiss_notice() {
|
573 |
-
$notice
|
574 |
-
'
|
575 |
-
|
576 |
-
|
|
|
|
|
|
|
577 |
|
578 |
-
|
|
|
579 |
|
580 |
wp_die();
|
581 |
}
|
582 |
|
|
|
|
|
|
|
|
|
|
|
583 |
public function pro_notice() {
|
584 |
$screen = get_current_screen();
|
585 |
|
@@ -587,7 +739,7 @@ class Plugin {
|
|
587 |
return;
|
588 |
}
|
589 |
|
590 |
-
if ( ! in_array( $screen->id, array( 'dashboard', 'dashboard-network' ) ) ) {
|
591 |
return;
|
592 |
}
|
593 |
|
@@ -595,21 +747,27 @@ class Plugin {
|
|
595 |
return;
|
596 |
}
|
597 |
|
598 |
-
if ( get_user_meta( get_current_user_id(), 'roc_dismissed_pro_release_notice', true )
|
599 |
return;
|
600 |
}
|
601 |
|
602 |
printf(
|
603 |
-
'<div class="notice notice-info is-dismissible" data-dismissible="pro_release_notice"><p><strong>%s</strong> %s</p></div>',
|
604 |
-
|
|
|
605 |
sprintf(
|
606 |
-
// translators: %s = Link to the plugin setting screen
|
607 |
-
__( 'A <u>business class</u> object cache backend. Truly reliable, highly-optimized and fully customizable, with a <u>dedicated engineer</u> when you most need it. <a href="%s">Learn more »</a>', 'redis-cache' ),
|
608 |
-
network_admin_url( $this->page )
|
609 |
)
|
610 |
);
|
611 |
}
|
612 |
|
|
|
|
|
|
|
|
|
|
|
613 |
public function wc_pro_notice() {
|
614 |
if ( ! class_exists( 'WooCommerce' ) ) {
|
615 |
return;
|
@@ -621,7 +779,7 @@ class Plugin {
|
|
621 |
return;
|
622 |
}
|
623 |
|
624 |
-
if ( ! in_array( $screen->id, array( 'edit-shop_order', 'edit-product', 'woocommerce_page_wc-admin' ) ) ) {
|
625 |
return;
|
626 |
}
|
627 |
|
@@ -629,27 +787,38 @@ class Plugin {
|
|
629 |
return;
|
630 |
}
|
631 |
|
632 |
-
if ( get_user_meta( get_current_user_id(), 'roc_dismissed_wc_pro_notice', true )
|
633 |
return;
|
634 |
}
|
635 |
|
636 |
printf(
|
637 |
-
'<div class="notice woocommerce-message woocommerce-admin-promo-messages is-dismissible" data-dismissible="wc_pro_notice"><p><strong>%s</strong></p><p>%s</p></div>',
|
638 |
-
|
|
|
639 |
sprintf(
|
640 |
-
// translators: %s = Link to the plugin's settings screen
|
641 |
-
__( 'Object Cache Pro is a <u>business class</u> object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. <a style="color: #bb77ae;" href="%s">Learn more »</a>', 'redis-cache' ),
|
642 |
-
network_admin_url( $this->page )
|
643 |
)
|
644 |
);
|
645 |
}
|
646 |
|
|
|
|
|
|
|
|
|
|
|
647 |
public function register_shutdown_hooks() {
|
648 |
if ( ! defined( 'WP_REDIS_DISABLE_COMMENT' ) || ! WP_REDIS_DISABLE_COMMENT ) {
|
649 |
add_action( 'shutdown', array( $this, 'maybe_print_comment' ), 0 );
|
650 |
}
|
651 |
}
|
652 |
|
|
|
|
|
|
|
|
|
|
|
653 |
public function record_metrics() {
|
654 |
global $wp_object_cache;
|
655 |
|
@@ -683,11 +852,16 @@ class Plugin {
|
|
683 |
time(),
|
684 |
http_build_query( $metrics, null, ';' )
|
685 |
);
|
686 |
-
} catch (Exception $exception) {
|
687 |
-
error_log($exception);
|
688 |
}
|
689 |
}
|
690 |
|
|
|
|
|
|
|
|
|
|
|
691 |
public function discard_metrics() {
|
692 |
global $wp_object_cache;
|
693 |
|
@@ -709,11 +883,16 @@ class Plugin {
|
|
709 |
0,
|
710 |
time() - HOUR_IN_SECONDS
|
711 |
);
|
712 |
-
} catch (Exception $exception) {
|
713 |
-
error_log($exception);
|
714 |
}
|
715 |
}
|
716 |
|
|
|
|
|
|
|
|
|
|
|
717 |
public function maybe_print_comment() {
|
718 |
global $wp_object_cache;
|
719 |
|
@@ -747,12 +926,13 @@ class Plugin {
|
|
747 |
);
|
748 |
|
749 |
if ( ! WP_DEBUG ) {
|
|
|
750 |
printf( "\n<!-- %s -->\n", $message );
|
751 |
|
752 |
return;
|
753 |
}
|
754 |
|
755 |
-
$bytes = strlen( serialize( $wp_object_cache->cache ) );
|
756 |
|
757 |
$debug = sprintf(
|
758 |
// translators: %1$d = number of objects. %2$s = human-readable size of cache. %3$s = name of the used client.
|
@@ -762,15 +942,28 @@ class Plugin {
|
|
762 |
$wp_object_cache->diagnostics['client']
|
763 |
);
|
764 |
|
765 |
-
printf(
|
|
|
|
|
|
|
|
|
766 |
}
|
767 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
768 |
public function initialize_filesystem( $url, $silent = false ) {
|
769 |
if ( $silent ) {
|
770 |
ob_start();
|
771 |
}
|
772 |
|
773 |
-
|
|
|
|
|
774 |
if ( $silent ) {
|
775 |
ob_end_clean();
|
776 |
}
|
@@ -791,8 +984,12 @@ class Plugin {
|
|
791 |
return true;
|
792 |
}
|
793 |
|
794 |
-
|
795 |
-
|
|
|
|
|
|
|
|
|
796 |
global $wp_filesystem;
|
797 |
|
798 |
if ( ! $this->initialize_filesystem( '', true ) ) {
|
@@ -833,6 +1030,11 @@ class Plugin {
|
|
833 |
return true;
|
834 |
}
|
835 |
|
|
|
|
|
|
|
|
|
|
|
836 |
public function maybe_update_dropin() {
|
837 |
if ( defined( 'WP_REDIS_DISABLE_DROPIN_AUTOUPDATE' ) && WP_REDIS_DISABLE_DROPIN_AUTOUPDATE ) {
|
838 |
return;
|
@@ -843,6 +1045,11 @@ class Plugin {
|
|
843 |
}
|
844 |
}
|
845 |
|
|
|
|
|
|
|
|
|
|
|
846 |
public function update_dropin() {
|
847 |
global $wp_filesystem;
|
848 |
|
@@ -862,13 +1069,21 @@ class Plugin {
|
|
862 |
}
|
863 |
}
|
864 |
|
|
|
|
|
|
|
|
|
|
|
|
|
865 |
public function on_deactivation( $plugin ) {
|
866 |
global $wp_filesystem;
|
867 |
|
868 |
ob_start();
|
869 |
|
870 |
if ( $plugin === WP_REDIS_BASENAME ) {
|
871 |
-
|
|
|
|
|
872 |
wp_unschedule_event( $timestamp, 'rediscache_discard_metrics' );
|
873 |
}
|
874 |
|
@@ -882,7 +1097,17 @@ class Plugin {
|
|
882 |
ob_end_clean();
|
883 |
}
|
884 |
|
|
|
|
|
|
|
|
|
|
|
|
|
885 |
public function action_link( $action ) {
|
|
|
|
|
|
|
|
|
886 |
return wp_nonce_url(
|
887 |
network_admin_url( add_query_arg( 'action', $action, $this->page ) ),
|
888 |
$action
|
12 |
|
13 |
defined( '\\ABSPATH' ) || exit;
|
14 |
|
15 |
+
/**
|
16 |
+
* Main plugin class definition
|
17 |
+
*/
|
18 |
class Plugin {
|
19 |
|
20 |
+
/**
|
21 |
+
* Settings page uri
|
22 |
+
*
|
23 |
+
* @var string $page
|
24 |
+
*/
|
25 |
+
private $page = '';
|
26 |
|
27 |
+
/**
|
28 |
+
* Settings page slug
|
29 |
+
*
|
30 |
+
* @var string $screen
|
31 |
+
*/
|
32 |
private $screen = '';
|
33 |
|
34 |
+
/**
|
35 |
+
* Allowed setting page actions
|
36 |
+
*
|
37 |
+
* @var string[] $actions
|
38 |
+
*/
|
39 |
private $actions = array(
|
40 |
'enable-cache',
|
41 |
'disable-cache',
|
44 |
);
|
45 |
|
46 |
/**
|
47 |
+
* Plugin instance property
|
48 |
*
|
49 |
* @var Plugin
|
50 |
*/
|
51 |
private static $instance;
|
52 |
|
53 |
/**
|
54 |
+
* Plugin instanciation method
|
55 |
*
|
56 |
* @return Plugin
|
57 |
*/
|
63 |
return self::$instance;
|
64 |
}
|
65 |
|
66 |
+
/**
|
67 |
+
* Constructor
|
68 |
+
*/
|
69 |
private function __construct() {
|
70 |
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
71 |
|
87 |
}
|
88 |
}
|
89 |
|
90 |
+
/**
|
91 |
+
* Adds all necessary hooks
|
92 |
+
*
|
93 |
+
* @return void
|
94 |
+
*/
|
95 |
public function add_actions_and_filters() {
|
96 |
add_action( 'deactivate_plugin', array( $this, 'on_deactivation' ) );
|
97 |
add_action( 'admin_init', array( $this, 'maybe_update_dropin' ) );
|
123 |
add_filter( 'qm/outputter/html', array( $this, 'register_qm_output' ) );
|
124 |
}
|
125 |
|
126 |
+
/**
|
127 |
+
* Adds a submenu page to "Settings"
|
128 |
+
*
|
129 |
+
* @return void
|
130 |
+
*/
|
131 |
public function add_admin_menu_page() {
|
|
|
132 |
add_submenu_page(
|
133 |
is_multisite() ? 'settings.php' : 'options-general.php',
|
134 |
__( 'Redis Object Cache', 'redis-cache' ),
|
139 |
);
|
140 |
}
|
141 |
|
142 |
+
/**
|
143 |
+
* Displays the settings page
|
144 |
+
*
|
145 |
+
* @return void
|
146 |
+
*/
|
147 |
public function show_admin_page() {
|
148 |
+
// Request filesystem credentials?
|
149 |
if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) {
|
150 |
+
$action = sanitize_key( $_GET['action'] );
|
151 |
+
$nonce = sanitize_key( $_GET['_wpnonce'] );
|
152 |
|
153 |
foreach ( $this->actions as $name ) {
|
154 |
+
// Nonce verification.
|
155 |
+
if ( $action === $name && wp_verify_nonce( $nonce, $action ) ) {
|
156 |
$url = $this->action_link( $action );
|
157 |
|
158 |
if ( $this->initialize_filesystem( $url ) === false ) {
|
159 |
+
return; // Request filesystem credentials.
|
160 |
}
|
161 |
}
|
162 |
}
|
183 |
__( 'Diagnostics', 'redis-cache' )
|
184 |
);
|
185 |
|
186 |
+
// Show the admin page.
|
187 |
require_once WP_REDIS_PLUGIN_PATH . '/includes/ui/settings.php';
|
188 |
}
|
189 |
|
190 |
+
/**
|
191 |
+
* Adds the dashboard metrics widget
|
192 |
+
*
|
193 |
+
* @return void
|
194 |
+
*/
|
195 |
public function setup_dashboard_widget() {
|
196 |
if ( defined( 'WP_REDIS_DISABLE_METRICS' ) && WP_REDIS_DISABLE_METRICS ) {
|
197 |
return;
|
204 |
);
|
205 |
}
|
206 |
|
207 |
+
/**
|
208 |
+
* Displays the dashboard widget
|
209 |
+
*
|
210 |
+
* @return void
|
211 |
+
*/
|
212 |
public function show_dashboard_widget() {
|
213 |
require_once WP_REDIS_PLUGIN_PATH . '/includes/ui/widget.php';
|
214 |
}
|
215 |
|
216 |
+
/**
|
217 |
+
* Adds the settings page to the plugin action links on the plugin page
|
218 |
+
*
|
219 |
+
* @param string[] $links The current plugin action links.
|
220 |
+
* @return string[]
|
221 |
+
*/
|
222 |
public function add_plugin_actions_links( $links ) {
|
|
|
223 |
return array_merge(
|
224 |
[ sprintf( '<a href="%s">%s</a>', network_admin_url( $this->page ), esc_html__( 'Settings', 'redis-cache' ) ) ],
|
225 |
$links
|
226 |
);
|
227 |
}
|
228 |
|
229 |
+
/**
|
230 |
+
* Enqueues admin style resources
|
231 |
+
*
|
232 |
+
* @return void
|
233 |
+
*/
|
234 |
public function enqueue_admin_styles() {
|
235 |
$screen = get_current_screen();
|
236 |
|
244 |
'dashboard-network',
|
245 |
);
|
246 |
|
247 |
+
if ( ! in_array( $screen->id, $screens, true ) ) {
|
248 |
return;
|
249 |
}
|
250 |
|
251 |
wp_enqueue_style( 'redis-cache', WP_REDIS_DIR . '/assets/css/admin.css', null, WP_REDIS_VERSION );
|
252 |
}
|
253 |
|
254 |
+
/**
|
255 |
+
* Enqueues admin script resources
|
256 |
+
*
|
257 |
+
* @return void
|
258 |
+
*/
|
259 |
public function enqueue_admin_scripts() {
|
260 |
$screen = get_current_screen();
|
261 |
|
272 |
'woocommerce_page_wc-admin',
|
273 |
);
|
274 |
|
275 |
+
if ( ! in_array( $screen->id, $screens, true ) ) {
|
276 |
return;
|
277 |
}
|
278 |
|
280 |
'redis-cache',
|
281 |
plugins_url( 'assets/js/admin.js', WP_REDIS_FILE ),
|
282 |
array( 'jquery', 'underscore' ),
|
283 |
+
WP_REDIS_VERSION,
|
284 |
+
true
|
285 |
);
|
286 |
|
287 |
wp_localize_script(
|
304 |
);
|
305 |
}
|
306 |
|
307 |
+
/**
|
308 |
+
* Enqueues scripts to display recorded metrics
|
309 |
+
*
|
310 |
+
* @return void
|
311 |
+
*/
|
312 |
public function enqueue_redis_metrics() {
|
313 |
global $wp_object_cache;
|
314 |
|
322 |
return;
|
323 |
}
|
324 |
|
325 |
+
if ( ! in_array( $screen->id, array( $this->screen, 'dashboard', 'dashboard-network' ), true ) ) {
|
326 |
return;
|
327 |
}
|
328 |
|
330 |
'redis-cache-charts',
|
331 |
plugins_url( 'assets/js/apexcharts.min.js', WP_REDIS_FILE ),
|
332 |
null,
|
333 |
+
WP_REDIS_VERSION,
|
334 |
+
true
|
335 |
);
|
336 |
|
337 |
if ( ! method_exists( $wp_object_cache, 'redis_instance' ) ) {
|
347 |
);
|
348 |
|
349 |
wp_localize_script( 'redis-cache', 'rediscache_metrics', $metrics );
|
350 |
+
} catch ( Exception $exception ) {
|
351 |
+
error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
352 |
}
|
353 |
}
|
354 |
|
355 |
+
/**
|
356 |
+
* Registers a new cache collector for the Query Monitor plugin
|
357 |
+
*
|
358 |
+
* @param array $collectors Array of currently registered collectors.
|
359 |
+
* @return array
|
360 |
+
*/
|
361 |
public function register_qm_collector( array $collectors ) {
|
362 |
$collectors['cache'] = new QM_Collector();
|
363 |
|
364 |
return $collectors;
|
365 |
}
|
366 |
|
367 |
+
/**
|
368 |
+
* Registers a new cache output using our collector for the Query Monitor plugin
|
369 |
+
*
|
370 |
+
* @param array $output Array of current QM_Output handlers.
|
371 |
+
* @return array
|
372 |
+
*/
|
373 |
public function register_qm_output( $output ) {
|
374 |
$collector = \QM_Collectors::get( 'cache' );
|
375 |
|
383 |
return $output;
|
384 |
}
|
385 |
|
386 |
+
/**
|
387 |
+
* Checks if the `object-cache.php` drop-in exists
|
388 |
+
*
|
389 |
+
* @return bool
|
390 |
+
*/
|
391 |
public function object_cache_dropin_exists() {
|
392 |
return file_exists( WP_CONTENT_DIR . '/object-cache.php' );
|
393 |
}
|
394 |
|
395 |
+
/**
|
396 |
+
* Validates the `object-cache.php` drop-in
|
397 |
+
*
|
398 |
+
* @return bool
|
399 |
+
*/
|
400 |
public function validate_object_cache_dropin() {
|
401 |
if ( ! $this->object_cache_dropin_exists() ) {
|
402 |
return false;
|
408 |
return $dropin['PluginURI'] === $plugin['PluginURI'];
|
409 |
}
|
410 |
|
411 |
+
/**
|
412 |
+
* Checks if the `object-cache.php` drop-in is outdated
|
413 |
+
*
|
414 |
+
* @return bool
|
415 |
+
*/
|
416 |
public function object_cache_dropin_outdated() {
|
417 |
if ( ! $this->object_cache_dropin_exists() ) {
|
418 |
return false;
|
428 |
return false;
|
429 |
}
|
430 |
|
431 |
+
/**
|
432 |
+
* Retrieves the current human-readable status
|
433 |
+
*
|
434 |
+
* @return string
|
435 |
+
*/
|
436 |
public function get_status() {
|
437 |
global $wp_object_cache;
|
438 |
|
480 |
return $wp_object_cache->redis_status();
|
481 |
}
|
482 |
|
483 |
+
/**
|
484 |
+
* Returns the redis version if possible
|
485 |
+
*
|
486 |
+
* @see WP_Object_Cache::redis_version()
|
487 |
+
* @return null|string
|
488 |
+
*/
|
489 |
public function get_redis_version() {
|
490 |
global $wp_object_cache;
|
491 |
|
498 |
}
|
499 |
}
|
500 |
|
501 |
+
/**
|
502 |
+
* Returns the currently used redis client (if any)
|
503 |
+
*
|
504 |
+
* @return null|string
|
505 |
+
*/
|
506 |
public function get_redis_client_name() {
|
507 |
global $wp_object_cache;
|
508 |
|
515 |
}
|
516 |
}
|
517 |
|
518 |
+
/**
|
519 |
+
* Fetches the redis diagnostics data
|
520 |
+
*
|
521 |
+
* @return null|array
|
522 |
+
*/
|
523 |
public function get_diagnostics() {
|
524 |
global $wp_object_cache;
|
525 |
|
528 |
}
|
529 |
}
|
530 |
|
531 |
+
/**
|
532 |
+
* Retrieves the redis prefix
|
533 |
+
*
|
534 |
+
* @return null|mixed
|
535 |
+
*/
|
536 |
public function get_redis_prefix() {
|
537 |
return defined( 'WP_REDIS_PREFIX' ) ? WP_REDIS_PREFIX : null;
|
538 |
}
|
539 |
|
540 |
+
/**
|
541 |
+
* Retrieves the redis maximum time to live
|
542 |
+
*
|
543 |
+
* @return null|mixed
|
544 |
+
*/
|
545 |
public function get_redis_maxttl() {
|
546 |
return defined( 'WP_REDIS_MAXTTL' ) ? WP_REDIS_MAXTTL : null;
|
547 |
}
|
548 |
|
549 |
+
/**
|
550 |
+
* Displays admin notices
|
551 |
+
*
|
552 |
+
* @return void
|
553 |
+
*/
|
554 |
public function show_admin_notices() {
|
555 |
if ( ! defined( 'WP_REDIS_DISABLE_BANNERS' ) || ! WP_REDIS_DISABLE_BANNERS ) {
|
556 |
$this->pro_notice();
|
557 |
$this->wc_pro_notice();
|
558 |
}
|
559 |
|
560 |
+
// Only show admin notices to users with the right capability.
|
561 |
if ( ! current_user_can( is_multisite() ? 'manage_network_options' : 'manage_options' ) ) {
|
562 |
return;
|
563 |
}
|
567 |
|
568 |
if ( $this->validate_object_cache_dropin() ) {
|
569 |
if ( $this->object_cache_dropin_outdated() ) {
|
570 |
+
// translators: %s = Action link to update the drop-in.
|
571 |
$message = sprintf( __( 'The Redis object cache drop-in is outdated. Please <a href="%s">update the drop-in</a>.', 'redis-cache' ), $url );
|
572 |
}
|
573 |
} else {
|
574 |
+
// translators: %s = Action link to update the drop-in.
|
575 |
$message = sprintf( __( 'A foreign object cache drop-in was found. To use Redis for object caching, please <a href="%s">enable the drop-in</a>.', 'redis-cache' ), $url );
|
576 |
}
|
577 |
|
578 |
if ( isset( $message ) ) {
|
579 |
+
printf( '<div class="update-nag">%s</div>', wp_kses_post( $message ) );
|
580 |
}
|
581 |
}
|
582 |
}
|
583 |
|
584 |
+
/**
|
585 |
+
* Executes admin actions
|
586 |
+
*
|
587 |
+
* @return void
|
588 |
+
*/
|
589 |
public function do_admin_actions() {
|
590 |
global $wp_filesystem;
|
591 |
|
592 |
if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) {
|
593 |
+
$action = sanitize_key( $_GET['action'] );
|
594 |
+
$nonce = sanitize_key( $_GET['_wpnonce'] );
|
595 |
|
596 |
+
// Nonce verification.
|
597 |
foreach ( $this->actions as $name ) {
|
598 |
+
if ( $action === $name && ! wp_verify_nonce( $nonce, $action ) ) {
|
599 |
return;
|
600 |
}
|
601 |
}
|
602 |
|
603 |
+
if ( in_array( $action, $this->actions, true ) ) {
|
604 |
$url = $this->action_link( $action );
|
605 |
|
606 |
if ( $action === 'flush-cache' ) {
|
655 |
$result
|
656 |
? add_settings_error(
|
657 |
'redis-cache',
|
658 |
+
'dropin',
|
659 |
+
__( 'Object cache disabled.', 'redis-cache' ),
|
660 |
'updated'
|
661 |
)
|
662 |
: add_settings_error(
|
663 |
'redis-cache',
|
664 |
+
'dropin',
|
665 |
+
__( 'Object cache could not be disabled.', 'redis-cache' ),
|
666 |
'error'
|
667 |
);
|
668 |
}
|
691 |
'error'
|
692 |
);
|
693 |
}
|
|
|
694 |
}
|
695 |
|
696 |
$messages = get_settings_errors( 'redis-cache' );
|
707 |
}
|
708 |
}
|
709 |
|
710 |
+
/**
|
711 |
+
* Dismisses the admin notice for the current user
|
712 |
+
*
|
713 |
+
* @return void
|
714 |
+
*/
|
715 |
public function dismiss_notice() {
|
716 |
+
if ( isset( $_POST['notice'] ) ) {
|
717 |
+
check_ajax_referer( 'roc_dismiss_notice' );
|
718 |
+
|
719 |
+
$notice = sprintf(
|
720 |
+
'roc_dismissed_%s',
|
721 |
+
sanitize_key( $_POST['notice'] )
|
722 |
+
);
|
723 |
|
724 |
+
update_user_meta( get_current_user_id(), $notice, '1' );
|
725 |
+
}
|
726 |
|
727 |
wp_die();
|
728 |
}
|
729 |
|
730 |
+
/**
|
731 |
+
* Displays a redis cache pro admin notice
|
732 |
+
*
|
733 |
+
* @return void
|
734 |
+
*/
|
735 |
public function pro_notice() {
|
736 |
$screen = get_current_screen();
|
737 |
|
739 |
return;
|
740 |
}
|
741 |
|
742 |
+
if ( ! in_array( $screen->id, array( 'dashboard', 'dashboard-network' ), true ) ) {
|
743 |
return;
|
744 |
}
|
745 |
|
747 |
return;
|
748 |
}
|
749 |
|
750 |
+
if ( 1 === intval( get_user_meta( get_current_user_id(), 'roc_dismissed_pro_release_notice', true ) ) ) {
|
751 |
return;
|
752 |
}
|
753 |
|
754 |
printf(
|
755 |
+
'<div class="notice notice-info is-dismissible" data-dismissible="pro_release_notice" data-nonce="%s"><p><strong>%s</strong> %s</p></div>',
|
756 |
+
esc_attr( wp_create_nonce( 'roc_dismiss_notice' ) ),
|
757 |
+
esc_html__( 'Object Cache Pro is out!', 'redis-cache' ),
|
758 |
sprintf(
|
759 |
+
// translators: %s = Link to the plugin setting screen.
|
760 |
+
wp_kses_post( __( 'A <u>business class</u> object cache backend. Truly reliable, highly-optimized and fully customizable, with a <u>dedicated engineer</u> when you most need it. <a href="%s">Learn more »</a>', 'redis-cache' ) ),
|
761 |
+
esc_url( network_admin_url( $this->page ) )
|
762 |
)
|
763 |
);
|
764 |
}
|
765 |
|
766 |
+
/**
|
767 |
+
* Displays a redis cache pro admin notice specifically for WooCommerce
|
768 |
+
*
|
769 |
+
* @return void
|
770 |
+
*/
|
771 |
public function wc_pro_notice() {
|
772 |
if ( ! class_exists( 'WooCommerce' ) ) {
|
773 |
return;
|
779 |
return;
|
780 |
}
|
781 |
|
782 |
+
if ( ! in_array( $screen->id, array( 'edit-shop_order', 'edit-product', 'woocommerce_page_wc-admin' ), true ) ) {
|
783 |
return;
|
784 |
}
|
785 |
|
787 |
return;
|
788 |
}
|
789 |
|
790 |
+
if ( 1 === intval( get_user_meta( get_current_user_id(), 'roc_dismissed_wc_pro_notice', true ) ) ) {
|
791 |
return;
|
792 |
}
|
793 |
|
794 |
printf(
|
795 |
+
'<div class="notice woocommerce-message woocommerce-admin-promo-messages is-dismissible" data-dismissible="wc_pro_notice" data-nonce="%s"><p><strong>%s</strong></p><p>%s</p></div>',
|
796 |
+
esc_attr( wp_create_nonce( 'roc_dismiss_notice' ) ),
|
797 |
+
esc_html__( 'Object Cache Pro + WooCommerce = ❤️', 'redis-cache' ),
|
798 |
sprintf(
|
799 |
+
// translators: %s = Link to the plugin's settings screen.
|
800 |
+
wp_kses_post( __( 'Object Cache Pro is a <u>business class</u> object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. <a style="color: #bb77ae;" href="%s">Learn more »</a>', 'redis-cache' ) ),
|
801 |
+
esc_url( network_admin_url( $this->page ) )
|
802 |
)
|
803 |
);
|
804 |
}
|
805 |
|
806 |
+
/**
|
807 |
+
* Registers all hooks associated with the shutdown hook
|
808 |
+
*
|
809 |
+
* @return void
|
810 |
+
*/
|
811 |
public function register_shutdown_hooks() {
|
812 |
if ( ! defined( 'WP_REDIS_DISABLE_COMMENT' ) || ! WP_REDIS_DISABLE_COMMENT ) {
|
813 |
add_action( 'shutdown', array( $this, 'maybe_print_comment' ), 0 );
|
814 |
}
|
815 |
}
|
816 |
|
817 |
+
/**
|
818 |
+
* Adds the recorded metrics to redis
|
819 |
+
*
|
820 |
+
* @return void
|
821 |
+
*/
|
822 |
public function record_metrics() {
|
823 |
global $wp_object_cache;
|
824 |
|
852 |
time(),
|
853 |
http_build_query( $metrics, null, ';' )
|
854 |
);
|
855 |
+
} catch ( Exception $exception ) {
|
856 |
+
error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
857 |
}
|
858 |
}
|
859 |
|
860 |
+
/**
|
861 |
+
* Removes recorded metrics after an hour
|
862 |
+
*
|
863 |
+
* @return void
|
864 |
+
*/
|
865 |
public function discard_metrics() {
|
866 |
global $wp_object_cache;
|
867 |
|
883 |
0,
|
884 |
time() - HOUR_IN_SECONDS
|
885 |
);
|
886 |
+
} catch ( Exception $exception ) {
|
887 |
+
error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
888 |
}
|
889 |
}
|
890 |
|
891 |
+
/**
|
892 |
+
* Displays the redis cache html comment
|
893 |
+
*
|
894 |
+
* @return void
|
895 |
+
*/
|
896 |
public function maybe_print_comment() {
|
897 |
global $wp_object_cache;
|
898 |
|
926 |
);
|
927 |
|
928 |
if ( ! WP_DEBUG ) {
|
929 |
+
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
930 |
printf( "\n<!-- %s -->\n", $message );
|
931 |
|
932 |
return;
|
933 |
}
|
934 |
|
935 |
+
$bytes = strlen( serialize( $wp_object_cache->cache ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
|
936 |
|
937 |
$debug = sprintf(
|
938 |
// translators: %1$d = number of objects. %2$s = human-readable size of cache. %3$s = name of the used client.
|
942 |
$wp_object_cache->diagnostics['client']
|
943 |
);
|
944 |
|
945 |
+
printf(
|
946 |
+
"<!--\n%s\n\n%s\n-->\n",
|
947 |
+
$message, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
948 |
+
esc_html( $debug )
|
949 |
+
);
|
950 |
}
|
951 |
|
952 |
+
/**
|
953 |
+
* Initializes the WP filesystem API to be ready for use
|
954 |
+
*
|
955 |
+
* @param string $url The URL to post the form to.
|
956 |
+
* @param bool $silent Wheather to ask the user for credentials if necessary or not.
|
957 |
+
* @return bool
|
958 |
+
*/
|
959 |
public function initialize_filesystem( $url, $silent = false ) {
|
960 |
if ( $silent ) {
|
961 |
ob_start();
|
962 |
}
|
963 |
|
964 |
+
$credentials = request_filesystem_credentials( $url );
|
965 |
+
|
966 |
+
if ( false === $credentials ) {
|
967 |
if ( $silent ) {
|
968 |
ob_end_clean();
|
969 |
}
|
984 |
return true;
|
985 |
}
|
986 |
|
987 |
+
/**
|
988 |
+
* Test if we can write in the WP_CONTENT_DIR and modify the `object-cache.php` drop-in
|
989 |
+
*
|
990 |
+
* @return true|WP_Error
|
991 |
+
*/
|
992 |
+
public function test_filesystem_writing() {
|
993 |
global $wp_filesystem;
|
994 |
|
995 |
if ( ! $this->initialize_filesystem( '', true ) ) {
|
1030 |
return true;
|
1031 |
}
|
1032 |
|
1033 |
+
/**
|
1034 |
+
* Calls the drop-in update method if necessary
|
1035 |
+
*
|
1036 |
+
* @return void
|
1037 |
+
*/
|
1038 |
public function maybe_update_dropin() {
|
1039 |
if ( defined( 'WP_REDIS_DISABLE_DROPIN_AUTOUPDATE' ) && WP_REDIS_DISABLE_DROPIN_AUTOUPDATE ) {
|
1040 |
return;
|
1045 |
}
|
1046 |
}
|
1047 |
|
1048 |
+
/**
|
1049 |
+
* Updates the `object-cache.php` drop-in
|
1050 |
+
*
|
1051 |
+
* @return void
|
1052 |
+
*/
|
1053 |
public function update_dropin() {
|
1054 |
global $wp_filesystem;
|
1055 |
|
1069 |
}
|
1070 |
}
|
1071 |
|
1072 |
+
/**
|
1073 |
+
* Plugin deactivation hook
|
1074 |
+
*
|
1075 |
+
* @param string $plugin Plugin basename.
|
1076 |
+
* @return void
|
1077 |
+
*/
|
1078 |
public function on_deactivation( $plugin ) {
|
1079 |
global $wp_filesystem;
|
1080 |
|
1081 |
ob_start();
|
1082 |
|
1083 |
if ( $plugin === WP_REDIS_BASENAME ) {
|
1084 |
+
$timestamp = wp_next_scheduled( 'rediscache_discard_metrics' );
|
1085 |
+
|
1086 |
+
if ( $timestamp ) {
|
1087 |
wp_unschedule_event( $timestamp, 'rediscache_discard_metrics' );
|
1088 |
}
|
1089 |
|
1097 |
ob_end_clean();
|
1098 |
}
|
1099 |
|
1100 |
+
/**
|
1101 |
+
* Helper method to retrieve a nonced plugin action link
|
1102 |
+
*
|
1103 |
+
* @param string $action The action to be executed once the link is followed.
|
1104 |
+
* @return string
|
1105 |
+
*/
|
1106 |
public function action_link( $action ) {
|
1107 |
+
if ( ! in_array( $action, $this->actions, true ) ) {
|
1108 |
+
return '';
|
1109 |
+
}
|
1110 |
+
|
1111 |
return wp_nonce_url(
|
1112 |
network_admin_url( add_query_arg( 'action', $action, $this->page ) ),
|
1113 |
$action
|
includes/class-qm-collector.php
CHANGED
@@ -11,24 +11,42 @@ use QM_Collector as Base_Collector;
|
|
11 |
|
12 |
defined( '\\ABSPATH' ) || exit;
|
13 |
|
|
|
|
|
|
|
14 |
class QM_Collector extends Base_Collector {
|
15 |
|
|
|
|
|
|
|
|
|
|
|
16 |
public $id = 'cache';
|
17 |
|
|
|
|
|
|
|
|
|
|
|
18 |
public function name() {
|
19 |
return __( 'Object Cache', 'redis-cache' );
|
20 |
}
|
21 |
|
|
|
|
|
|
|
|
|
|
|
22 |
public function process() {
|
23 |
-
|
24 |
|
25 |
$this->process_defaults();
|
26 |
|
27 |
-
$
|
28 |
|
29 |
-
$this->data['status'] = $
|
30 |
-
$this->data['has_dropin'] = $
|
31 |
-
$this->data['valid_dropin'] = $
|
32 |
|
33 |
if ( ! method_exists( $wp_object_cache, 'info' ) ) {
|
34 |
return;
|
@@ -54,12 +72,17 @@ class QM_Collector extends Base_Collector {
|
|
54 |
'unflushable' => $info->groups->unflushable,
|
55 |
];
|
56 |
|
57 |
-
//
|
58 |
$this->data['stats']['cache_hits'] = $info->hits;
|
59 |
$this->data['stats']['cache_misses'] = $info->misses;
|
60 |
$this->data['cache_hit_percentage'] = $info->ratio;
|
61 |
}
|
62 |
|
|
|
|
|
|
|
|
|
|
|
63 |
public function process_defaults() {
|
64 |
$this->data['hits'] = 0;
|
65 |
$this->data['misses'] = 0;
|
11 |
|
12 |
defined( '\\ABSPATH' ) || exit;
|
13 |
|
14 |
+
/**
|
15 |
+
* Query Monitor data collector class definition
|
16 |
+
*/
|
17 |
class QM_Collector extends Base_Collector {
|
18 |
|
19 |
+
/**
|
20 |
+
* Collector id
|
21 |
+
*
|
22 |
+
* @var string $id
|
23 |
+
*/
|
24 |
public $id = 'cache';
|
25 |
|
26 |
+
/**
|
27 |
+
* Retrieves the collector name
|
28 |
+
*
|
29 |
+
* @return string
|
30 |
+
*/
|
31 |
public function name() {
|
32 |
return __( 'Object Cache', 'redis-cache' );
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* Fills the collector with data
|
37 |
+
*
|
38 |
+
* @return void
|
39 |
+
*/
|
40 |
public function process() {
|
41 |
+
global $wp_object_cache;
|
42 |
|
43 |
$this->process_defaults();
|
44 |
|
45 |
+
$roc = Plugin::instance();
|
46 |
|
47 |
+
$this->data['status'] = $roc->get_status();
|
48 |
+
$this->data['has_dropin'] = $roc->object_cache_dropin_exists();
|
49 |
+
$this->data['valid_dropin'] = $roc->validate_object_cache_dropin();
|
50 |
|
51 |
if ( ! method_exists( $wp_object_cache, 'info' ) ) {
|
52 |
return;
|
72 |
'unflushable' => $info->groups->unflushable,
|
73 |
];
|
74 |
|
75 |
+
// These are used by Query Monitor.
|
76 |
$this->data['stats']['cache_hits'] = $info->hits;
|
77 |
$this->data['stats']['cache_misses'] = $info->misses;
|
78 |
$this->data['cache_hit_percentage'] = $info->ratio;
|
79 |
}
|
80 |
|
81 |
+
/**
|
82 |
+
* Sets collector defaults
|
83 |
+
*
|
84 |
+
* @return void
|
85 |
+
*/
|
86 |
public function process_defaults() {
|
87 |
$this->data['hits'] = 0;
|
88 |
$this->data['misses'] = 0;
|
includes/class-qm-output.php
CHANGED
@@ -11,8 +11,16 @@ use QM_Output_Html;
|
|
11 |
|
12 |
defined( '\\ABSPATH' ) || exit;
|
13 |
|
|
|
|
|
|
|
14 |
class QM_Output extends QM_Output_Html {
|
15 |
|
|
|
|
|
|
|
|
|
|
|
16 |
public function __construct( QM_Collector $collector ) {
|
17 |
parent::__construct( $collector );
|
18 |
|
@@ -20,10 +28,20 @@ class QM_Output extends QM_Output_Html {
|
|
20 |
add_filter( 'qm/output/panel_menus', [ $this, 'panel_menu' ] );
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
23 |
public function name() {
|
24 |
return __( 'Object Cache', 'redis cache' );
|
25 |
}
|
26 |
|
|
|
|
|
|
|
|
|
|
|
27 |
public function admin_menu( array $menu ) {
|
28 |
$data = $this->collector->get_data();
|
29 |
|
@@ -48,6 +66,11 @@ class QM_Output extends QM_Output_Html {
|
|
48 |
return $menu;
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
51 |
public function panel_menu( array $menu ) {
|
52 |
$ids = array_keys( $menu );
|
53 |
$request = array_search( 'qm-request', $ids, true );
|
@@ -64,12 +87,20 @@ class QM_Output extends QM_Output_Html {
|
|
64 |
);
|
65 |
}
|
66 |
|
|
|
|
|
|
|
|
|
|
|
67 |
public function output() {
|
68 |
$data = $this->collector->get_data();
|
69 |
|
70 |
if ( ! $data['has_dropin'] ) {
|
71 |
$this->before_non_tabular_output();
|
72 |
-
|
|
|
|
|
|
|
73 |
$this->after_non_tabular_output();
|
74 |
|
75 |
return;
|
@@ -77,7 +108,10 @@ class QM_Output extends QM_Output_Html {
|
|
77 |
|
78 |
if ( ! $data['valid_dropin'] ) {
|
79 |
$this->before_non_tabular_output();
|
80 |
-
|
|
|
|
|
|
|
81 |
$this->after_non_tabular_output();
|
82 |
|
83 |
return;
|
11 |
|
12 |
defined( '\\ABSPATH' ) || exit;
|
13 |
|
14 |
+
/**
|
15 |
+
* Query Monitor output logic class definition
|
16 |
+
*/
|
17 |
class QM_Output extends QM_Output_Html {
|
18 |
|
19 |
+
/**
|
20 |
+
* Contructor
|
21 |
+
*
|
22 |
+
* @param QM_Collector $collector The corresponding collector instance.
|
23 |
+
*/
|
24 |
public function __construct( QM_Collector $collector ) {
|
25 |
parent::__construct( $collector );
|
26 |
|
28 |
add_filter( 'qm/output/panel_menus', [ $this, 'panel_menu' ] );
|
29 |
}
|
30 |
|
31 |
+
/**
|
32 |
+
* Output class name
|
33 |
+
*
|
34 |
+
* @return string
|
35 |
+
*/
|
36 |
public function name() {
|
37 |
return __( 'Object Cache', 'redis cache' );
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* Adds a menu to the panel navigation menu in Query Monitor's output
|
42 |
+
*
|
43 |
+
* @param array $menu Array of menus.
|
44 |
+
*/
|
45 |
public function admin_menu( array $menu ) {
|
46 |
$data = $this->collector->get_data();
|
47 |
|
66 |
return $menu;
|
67 |
}
|
68 |
|
69 |
+
/**
|
70 |
+
* Adds a menu item in the panel navigation menu in Query Monitor's output.
|
71 |
+
*
|
72 |
+
* @param array $menu Array of menus.
|
73 |
+
*/
|
74 |
public function panel_menu( array $menu ) {
|
75 |
$ids = array_keys( $menu );
|
76 |
$request = array_search( 'qm-request', $ids, true );
|
87 |
);
|
88 |
}
|
89 |
|
90 |
+
/**
|
91 |
+
* Renders the output
|
92 |
+
*
|
93 |
+
* @return void
|
94 |
+
*/
|
95 |
public function output() {
|
96 |
$data = $this->collector->get_data();
|
97 |
|
98 |
if ( ! $data['has_dropin'] ) {
|
99 |
$this->before_non_tabular_output();
|
100 |
+
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
101 |
+
echo $this->build_notice(
|
102 |
+
esc_html__( 'The Redis Object Cache drop-in is not installed. Use WP CLI or go to "Settings -> Redis" to enable drop-in.', 'redis-cache' )
|
103 |
+
);
|
104 |
$this->after_non_tabular_output();
|
105 |
|
106 |
return;
|
108 |
|
109 |
if ( ! $data['valid_dropin'] ) {
|
110 |
$this->before_non_tabular_output();
|
111 |
+
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
112 |
+
echo $this->build_notice(
|
113 |
+
esc_html__( 'WordPress is using a foreign object cache drop-in and Redis Object Cache is not being used. Use WP CLI or go to "Settings -> Redis" to enable drop-in.', 'redis-cache' )
|
114 |
+
);
|
115 |
$this->after_non_tabular_output();
|
116 |
|
117 |
return;
|
includes/class-ui.php
CHANGED
@@ -30,13 +30,7 @@ class UI {
|
|
30 |
* @return void
|
31 |
*/
|
32 |
public static function register_tab( $slug, $label, $args = [] ) {
|
33 |
-
self::$tabs[ $slug ] =
|
34 |
-
'label' => $label,
|
35 |
-
'file' => WP_REDIS_PLUGIN_PATH . "/includes/ui/tabs/{$slug}.php",
|
36 |
-
'slug' => $slug,
|
37 |
-
'default' => false,
|
38 |
-
'disabled' => false,
|
39 |
-
] );
|
40 |
}
|
41 |
|
42 |
/**
|
30 |
* @return void
|
31 |
*/
|
32 |
public static function register_tab( $slug, $label, $args = [] ) {
|
33 |
+
self::$tabs[ $slug ] = new UI\Tab( $slug, $label, $args );
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
}
|
35 |
|
36 |
/**
|
includes/object-cache.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Redis Object Cache Drop-In
|
4 |
* Plugin URI: http://wordpress.org/plugins/redis-cache/
|
5 |
* Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, Credis, HHVM, replication, clustering and WP-CLI.
|
6 |
-
* Version: 2.0.
|
7 |
* Author: Till Krüss
|
8 |
* Author URI: https://objectcache.pro
|
9 |
* License: GPLv3
|
@@ -14,6 +14,7 @@
|
|
14 |
|
15 |
defined( '\\ABSPATH' ) || exit;
|
16 |
|
|
|
17 |
if ( ! defined( 'WP_REDIS_DISABLED' ) || ! WP_REDIS_DISABLED ) :
|
18 |
|
19 |
/**
|
@@ -46,7 +47,7 @@ function wp_cache_add( $key, $value, $group = '', $expiration = 0 ) {
|
|
46 |
* @return bool Always returns True
|
47 |
*/
|
48 |
function wp_cache_close() {
|
49 |
-
|
50 |
}
|
51 |
|
52 |
/**
|
@@ -102,7 +103,7 @@ function wp_cache_flush( $delay = 0 ) {
|
|
102 |
* @param string $group The group value appended to the $key.
|
103 |
* @param bool $force Optional. Whether to force an update of the local cache from the persistent
|
104 |
* cache. Default false.
|
105 |
-
* @param bool
|
106 |
* a storable value. Passed by reference. Default null.
|
107 |
*
|
108 |
* @return bool|mixed Cached object value.
|
@@ -151,7 +152,7 @@ function wp_cache_incr( $key, $offset = 1, $group = '' ) {
|
|
151 |
function wp_cache_init() {
|
152 |
global $wp_object_cache;
|
153 |
|
154 |
-
//
|
155 |
if ( defined( 'WP_CACHE_KEY_SALT' ) && ! defined( 'WP_REDIS_PREFIX' ) ) {
|
156 |
define( 'WP_REDIS_PREFIX', WP_CACHE_KEY_SALT );
|
157 |
}
|
@@ -159,6 +160,8 @@ function wp_cache_init() {
|
|
159 |
if ( ! ( $wp_object_cache instanceof WP_Object_Cache ) ) {
|
160 |
$fail_gracefully = ! defined( 'WP_REDIS_GRACEFUL' ) || WP_REDIS_GRACEFUL;
|
161 |
|
|
|
|
|
162 |
$wp_object_cache = new WP_Object_Cache( $fail_gracefully );
|
163 |
}
|
164 |
}
|
@@ -205,7 +208,7 @@ function wp_cache_set( $key, $value, $group = '', $expiration = 0 ) {
|
|
205 |
*
|
206 |
* This changes the blog id used to create keys in blog specific groups.
|
207 |
*
|
208 |
-
* @param int $_blog_id
|
209 |
*
|
210 |
* @return bool
|
211 |
*/
|
@@ -241,6 +244,9 @@ function wp_cache_add_non_persistent_groups( $groups ) {
|
|
241 |
$wp_object_cache->add_non_persistent_groups( $groups );
|
242 |
}
|
243 |
|
|
|
|
|
|
|
244 |
class WP_Object_Cache {
|
245 |
|
246 |
/**
|
@@ -380,7 +386,7 @@ class WP_Object_Cache {
|
|
380 |
/**
|
381 |
* Instantiate the Redis class.
|
382 |
*
|
383 |
-
* @param bool $fail_gracefully
|
384 |
*/
|
385 |
public function __construct( $fail_gracefully = true ) {
|
386 |
global $blog_id, $table_prefix;
|
@@ -405,17 +411,17 @@ class WP_Object_Cache {
|
|
405 |
try {
|
406 |
switch ( $client ) {
|
407 |
case 'hhvm':
|
408 |
-
$this->
|
409 |
break;
|
410 |
case 'phpredis':
|
411 |
-
$this->
|
412 |
break;
|
413 |
case 'credis':
|
414 |
-
$this->
|
415 |
break;
|
416 |
case 'predis':
|
417 |
default:
|
418 |
-
$this->
|
419 |
break;
|
420 |
}
|
421 |
|
@@ -432,7 +438,7 @@ class WP_Object_Cache {
|
|
432 |
$this->handle_exception( $exception );
|
433 |
}
|
434 |
|
435 |
-
// Assign global and blog prefixes for use with keys
|
436 |
if ( function_exists( 'is_multisite' ) ) {
|
437 |
$this->global_prefix = is_multisite() ? '' : $table_prefix;
|
438 |
$this->blog_prefix = is_multisite() ? $blog_id : $table_prefix;
|
@@ -509,10 +515,10 @@ class WP_Object_Cache {
|
|
509 |
/**
|
510 |
* Connect to Redis using the PhpRedis (PECL) extention.
|
511 |
*
|
512 |
-
* @param array $parameters
|
513 |
* @return void
|
514 |
*/
|
515 |
-
protected function
|
516 |
$version = phpversion( 'redis' );
|
517 |
|
518 |
$this->diagnostics[ 'client' ] = sprintf( 'PhpRedis (v%s)', $version );
|
@@ -593,25 +599,20 @@ class WP_Object_Cache {
|
|
593 |
/**
|
594 |
* Connect to Redis using the Predis library.
|
595 |
*
|
596 |
-
* @param array $parameters
|
|
|
597 |
* @return void
|
598 |
*/
|
599 |
-
protected function
|
600 |
$client = 'Predis';
|
601 |
|
602 |
-
//
|
603 |
-
if ( version_compare( PHP_VERSION, '5.4.0', '<' ) ) {
|
604 |
-
throw new Exception( 'Predis requires PHP 5.4 or newer.' );
|
605 |
-
}
|
606 |
-
|
607 |
-
// Load bundled Predis library
|
608 |
if ( ! class_exists( 'Predis\Client' ) ) {
|
609 |
$predis = sprintf(
|
610 |
'%s/redis-cache/dependencies/predis/predis/autoload.php',
|
611 |
defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins'
|
612 |
);
|
613 |
|
614 |
-
|
615 |
if ( is_readable( $predis ) ) {
|
616 |
require_once $predis;
|
617 |
} else {
|
@@ -621,19 +622,24 @@ class WP_Object_Cache {
|
|
621 |
}
|
622 |
}
|
623 |
|
|
|
624 |
$options = array();
|
625 |
|
626 |
if ( defined( 'WP_REDIS_SHARDS' ) ) {
|
627 |
-
$
|
|
|
628 |
} elseif ( defined( 'WP_REDIS_SENTINEL' ) ) {
|
629 |
-
$
|
|
|
630 |
$options['replication'] = 'sentinel';
|
631 |
$options['service'] = WP_REDIS_SENTINEL;
|
632 |
} elseif ( defined( 'WP_REDIS_SERVERS' ) ) {
|
633 |
-
$
|
|
|
634 |
$options['replication'] = true;
|
635 |
} elseif ( defined( 'WP_REDIS_CLUSTER' ) ) {
|
636 |
-
$
|
|
|
637 |
$options['cluster'] = 'redis';
|
638 |
}
|
639 |
|
@@ -653,7 +659,7 @@ class WP_Object_Cache {
|
|
653 |
}
|
654 |
}
|
655 |
|
656 |
-
$this->redis = new Predis\Client( $parameters, $options );
|
657 |
$this->redis->connect();
|
658 |
|
659 |
$this->diagnostics = array_merge(
|
@@ -666,17 +672,15 @@ class WP_Object_Cache {
|
|
666 |
/**
|
667 |
* Connect to Redis using the Credis library.
|
668 |
*
|
669 |
-
* @param array $parameters
|
|
|
|
|
|
|
670 |
* @return void
|
671 |
*/
|
672 |
-
protected function
|
673 |
$client = 'Credis';
|
674 |
|
675 |
-
// Require PHP 5.4 or greater
|
676 |
-
if ( version_compare( PHP_VERSION, '5.4.0', '<' ) ) {
|
677 |
-
throw new Exception( 'Predis requires PHP 5.4 or newer.' );
|
678 |
-
}
|
679 |
-
|
680 |
$creds_path = sprintf(
|
681 |
'%s/redis-cache/dependencies/colinmollenhour/credis/',
|
682 |
defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins'
|
@@ -688,10 +692,12 @@ class WP_Object_Cache {
|
|
688 |
$to_load[] = 'Client.php';
|
689 |
}
|
690 |
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
)
|
|
|
|
|
695 |
$to_load[] = 'Cluster.php';
|
696 |
|
697 |
if ( defined( 'WP_REDIS_SENTINEL' ) && ! class_exists( 'Credis_Sentinel' ) ) {
|
@@ -720,7 +726,7 @@ class WP_Object_Cache {
|
|
720 |
if ( defined( 'WP_REDIS_SENTINEL' ) ) {
|
721 |
if ( is_array( WP_REDIS_SERVERS ) && count( WP_REDIS_SERVERS ) > 1 ) {
|
722 |
throw new Exception(
|
723 |
-
'Multipe sentinel servers are not supported by the bundled Credis library. Please review your Redis Cache
|
724 |
);
|
725 |
}
|
726 |
|
@@ -735,7 +741,7 @@ class WP_Object_Cache {
|
|
735 |
$clients = $is_cluster ? WP_REDIS_CLUSTER : WP_REDIS_SERVERS;
|
736 |
|
737 |
foreach ( $clients as $index => &$connection_string ) {
|
738 |
-
$url_components =
|
739 |
parse_str( $url_components['query'], $add_params );
|
740 |
|
741 |
if ( ! $is_cluster && isset( $add_params['alias'] ) ) {
|
@@ -767,7 +773,7 @@ class WP_Object_Cache {
|
|
767 |
$this->redis = new Credis_Client( ...array_values( $args ) );
|
768 |
}
|
769 |
|
770 |
-
// Don't use PhpRedis
|
771 |
$this->redis->forceStandalone();
|
772 |
|
773 |
$this->redis->connect();
|
@@ -786,13 +792,13 @@ class WP_Object_Cache {
|
|
786 |
/**
|
787 |
* Connect to Redis using HHVM's Redis extention.
|
788 |
*
|
789 |
-
* @param array $parameters
|
790 |
* @return void
|
791 |
*/
|
792 |
-
protected function
|
793 |
$this->redis = new Redis();
|
794 |
|
795 |
-
// Adjust host and port
|
796 |
if ( strcasecmp( 'unix', $parameters['scheme'] ) === 0 ) {
|
797 |
$parameters['host'] = 'unix://' . $parameters['path'];
|
798 |
$parameters['port'] = 0;
|
@@ -863,7 +869,7 @@ class WP_Object_Cache {
|
|
863 |
* @return bool
|
864 |
*/
|
865 |
public function redis_status() {
|
866 |
-
|
867 |
}
|
868 |
|
869 |
/**
|
@@ -872,7 +878,7 @@ class WP_Object_Cache {
|
|
872 |
* @return mixed
|
873 |
*/
|
874 |
public function redis_instance() {
|
875 |
-
|
876 |
}
|
877 |
|
878 |
/**
|
@@ -881,7 +887,7 @@ class WP_Object_Cache {
|
|
881 |
* @return null|string
|
882 |
*/
|
883 |
public function redis_version() {
|
884 |
-
|
885 |
}
|
886 |
|
887 |
/**
|
@@ -921,7 +927,7 @@ class WP_Object_Cache {
|
|
921 |
*
|
922 |
* Add does not set the value if the key exists; replace does not replace if the value doesn't exist.
|
923 |
*
|
924 |
-
* @param bool $add True if should only add if value doesn't exist, false to only add when value already exists
|
925 |
* @param string $key The key under which to store the value.
|
926 |
* @param mixed $value The value to store.
|
927 |
* @param string $group The group value appended to the $key.
|
@@ -940,7 +946,7 @@ class WP_Object_Cache {
|
|
940 |
$result = true;
|
941 |
$derived_key = $this->build_key( $key, $group );
|
942 |
|
943 |
-
//
|
944 |
if ( ! $this->is_ignored_group( $group ) && $this->redis_status() ) {
|
945 |
try {
|
946 |
$expiration = apply_filters( 'redis_cache_expiration', $this->validate_expiration( $expiration ), $key, $group );
|
@@ -993,7 +999,7 @@ class WP_Object_Cache {
|
|
993 |
|
994 |
$exists = isset( $this->cache[ $derived_key ] );
|
995 |
|
996 |
-
if ( $add
|
997 |
return false;
|
998 |
}
|
999 |
|
@@ -1148,6 +1154,12 @@ class WP_Object_Cache {
|
|
1148 |
}
|
1149 |
}
|
1150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1151 |
protected function glob_quote( $string ) {
|
1152 |
$characters = [ '*', '+', '?', '!', '{', '}', '[', ']', '(', ')', '|', '@' ];
|
1153 |
|
@@ -1265,7 +1277,7 @@ LUA;
|
|
1265 |
* @param string $group The group value appended to the $key.
|
1266 |
* @param string $force Optional. Whether to force a refetch rather than relying on the local
|
1267 |
* cache. Default false.
|
1268 |
-
* @param bool
|
1269 |
* false, a storable value. Passed by reference. Default null.
|
1270 |
* @return bool|mixed Cached object value.
|
1271 |
*/
|
@@ -1368,9 +1380,12 @@ LUA;
|
|
1368 |
}
|
1369 |
}
|
1370 |
|
1371 |
-
$remaining_keys = array_filter(
|
1372 |
-
|
1373 |
-
|
|
|
|
|
|
|
1374 |
|
1375 |
if ( empty( $remaining_keys ) ) {
|
1376 |
return $cache;
|
@@ -1379,9 +1394,12 @@ LUA;
|
|
1379 |
$start_time = microtime( true );
|
1380 |
|
1381 |
try {
|
1382 |
-
$remaining_ids = array_map(
|
1383 |
-
|
1384 |
-
|
|
|
|
|
|
|
1385 |
|
1386 |
$results = array_combine(
|
1387 |
$remaining_keys,
|
@@ -1442,7 +1460,7 @@ LUA;
|
|
1442 |
|
1443 |
$start_time = microtime( true );
|
1444 |
|
1445 |
-
//
|
1446 |
if ( ! $this->is_ignored_group( $group ) && $this->redis_status() ) {
|
1447 |
$expiration = apply_filters( 'redis_cache_expiration', $this->validate_expiration( $expiration ), $key, $group );
|
1448 |
|
@@ -1462,7 +1480,7 @@ LUA;
|
|
1462 |
$this->cache_time += ( microtime( true ) - $start_time );
|
1463 |
}
|
1464 |
|
1465 |
-
//
|
1466 |
if ( $result ) {
|
1467 |
$this->add_to_internal_cache( $derived_key, $value );
|
1468 |
}
|
@@ -1479,16 +1497,16 @@ LUA;
|
|
1479 |
/**
|
1480 |
* Increment a Redis counter by the amount specified
|
1481 |
*
|
1482 |
-
* @param string $key
|
1483 |
-
* @param int $offset
|
1484 |
-
* @param string $group
|
1485 |
* @return int|bool
|
1486 |
*/
|
1487 |
public function increment( $key, $offset = 1, $group = 'default' ) {
|
1488 |
$offset = (int) $offset;
|
1489 |
$derived_key = $this->build_key( $key, $group );
|
1490 |
|
1491 |
-
// If group is a non-Redis group, save to internal cache, not Redis
|
1492 |
if ( $this->is_ignored_group( $group ) || ! $this->redis_status() ) {
|
1493 |
$value = $this->get_from_internal_cache( $derived_key );
|
1494 |
$value += $offset;
|
@@ -1520,10 +1538,11 @@ LUA;
|
|
1520 |
/**
|
1521 |
* Alias of `increment()`.
|
1522 |
*
|
1523 |
-
* @
|
1524 |
-
* @param
|
1525 |
-
* @param
|
1526 |
-
* @
|
|
|
1527 |
*/
|
1528 |
public function incr( $key, $offset = 1, $group = 'default' ) {
|
1529 |
return $this->increment( $key, $offset, $group );
|
@@ -1532,16 +1551,16 @@ LUA;
|
|
1532 |
/**
|
1533 |
* Decrement a Redis counter by the amount specified
|
1534 |
*
|
1535 |
-
* @param string $key
|
1536 |
-
* @param int $offset
|
1537 |
-
* @param string $group
|
1538 |
* @return int|bool
|
1539 |
*/
|
1540 |
public function decrement( $key, $offset = 1, $group = 'default' ) {
|
1541 |
$derived_key = $this->build_key( $key, $group );
|
1542 |
$offset = (int) $offset;
|
1543 |
|
1544 |
-
// If group is a non-Redis group, save to internal cache, not Redis
|
1545 |
if ( $this->is_ignored_group( $group ) || ! $this->redis_status() ) {
|
1546 |
$value = $this->get_from_internal_cache( $derived_key );
|
1547 |
$value -= $offset;
|
@@ -1553,7 +1572,7 @@ LUA;
|
|
1553 |
$start_time = microtime( true );
|
1554 |
|
1555 |
try {
|
1556 |
-
// Save to Redis
|
1557 |
$result = $this->parse_redis_response( $this->redis->decrBy( $derived_key, $offset ) );
|
1558 |
|
1559 |
$this->add_to_internal_cache( $derived_key, (int) $this->redis->get( $derived_key ) );
|
@@ -1573,33 +1592,28 @@ LUA;
|
|
1573 |
|
1574 |
/**
|
1575 |
* Render data about current cache requests
|
|
|
1576 |
*
|
1577 |
-
* @return
|
1578 |
*/
|
1579 |
public function stats() {
|
1580 |
-
|
1581 |
-
|
1582 |
-
|
1583 |
-
|
1584 |
-
|
1585 |
-
|
1586 |
-
|
1587 |
-
|
1588 |
-
|
1589 |
-
|
1590 |
-
|
1591 |
-
|
1592 |
-
|
1593 |
-
|
1594 |
-
|
1595 |
-
|
1596 |
-
|
1597 |
-
<strong>Cache Misses:</strong>
|
1598 |
-
<?php echo $this->cache_misses; ?>
|
1599 |
-
<br />
|
1600 |
-
<strong>Cache Size:</strong>
|
1601 |
-
<?php echo number_format( array_sum( $bytes ) / 1024, 2 ); ?> kB
|
1602 |
-
</p>
|
1603 |
<?php
|
1604 |
}
|
1605 |
|
@@ -1613,14 +1627,13 @@ LUA;
|
|
1613 |
|
1614 |
$bytes = array_map(
|
1615 |
function ( $keys ) {
|
|
|
1616 |
return strlen( serialize( $keys ) );
|
1617 |
},
|
1618 |
$this->cache
|
1619 |
);
|
1620 |
|
1621 |
return (object) [
|
1622 |
-
// Connected, Disabled, Unknown, Not connected
|
1623 |
-
'status' => '...',
|
1624 |
'hits' => $this->cache_hits,
|
1625 |
'misses' => $this->cache_misses,
|
1626 |
'ratio' => $total > 0 ? round( $this->cache_hits / ( $total / 100 ), 1 ) : 100,
|
@@ -1671,13 +1684,13 @@ LUA;
|
|
1671 |
* @return string Sanitized string.
|
1672 |
*/
|
1673 |
protected function sanitize_key_part( $part ) {
|
1674 |
-
|
1675 |
}
|
1676 |
|
1677 |
/**
|
1678 |
* Checks if the given group is part the ignored group array
|
1679 |
*
|
1680 |
-
* @param string $group Name of the group to check
|
1681 |
* @return bool
|
1682 |
*/
|
1683 |
protected function is_ignored_group( $group ) {
|
@@ -1687,7 +1700,7 @@ LUA;
|
|
1687 |
/**
|
1688 |
* Checks if the given group is part the global group array
|
1689 |
*
|
1690 |
-
* @param string $group Name of the group to check
|
1691 |
* @return bool
|
1692 |
*/
|
1693 |
protected function is_global_group( $group ) {
|
@@ -1697,7 +1710,7 @@ LUA;
|
|
1697 |
/**
|
1698 |
* Checks if the given group is part the unflushable group array
|
1699 |
*
|
1700 |
-
* @param string $group Name of the group to check
|
1701 |
* @return bool
|
1702 |
*/
|
1703 |
protected function is_unflushable_group( $group ) {
|
@@ -1707,7 +1720,7 @@ LUA;
|
|
1707 |
/**
|
1708 |
* Convert Redis responses into something meaningful
|
1709 |
*
|
1710 |
-
* @param mixed $response
|
1711 |
* @return mixed
|
1712 |
*/
|
1713 |
protected function parse_redis_response( $response ) {
|
@@ -1762,7 +1775,7 @@ LUA;
|
|
1762 |
/**
|
1763 |
* In multisite, switch blog prefix when switching blogs
|
1764 |
*
|
1765 |
-
* @param int $_blog_id
|
1766 |
* @return bool
|
1767 |
*/
|
1768 |
public function switch_to_blog( $_blog_id ) {
|
@@ -1815,7 +1828,7 @@ LUA;
|
|
1815 |
/**
|
1816 |
* Wrapper to validate the cache keys expiration value
|
1817 |
*
|
1818 |
-
* @param mixed $expiration Incoming expiration value (whatever it is)
|
1819 |
*/
|
1820 |
protected function validate_expiration( $expiration ) {
|
1821 |
$expiration = is_int( $expiration ) || ctype_digit( $expiration ) ? (int) $expiration : 0;
|
@@ -1846,8 +1859,9 @@ LUA;
|
|
1846 |
return igbinary_unserialize( $original );
|
1847 |
}
|
1848 |
|
1849 |
-
//
|
1850 |
if ( $this->is_serialized( $original ) ) {
|
|
|
1851 |
$value = @unserialize( $original );
|
1852 |
|
1853 |
return is_object( $value ) ? clone $value : $value;
|
@@ -1876,10 +1890,12 @@ LUA;
|
|
1876 |
}
|
1877 |
|
1878 |
if ( is_array( $data ) || is_object( $data ) ) {
|
|
|
1879 |
return serialize( $data );
|
1880 |
}
|
1881 |
|
1882 |
if ( $this->is_serialized( $data, false ) ) {
|
|
|
1883 |
return serialize( $data );
|
1884 |
}
|
1885 |
|
@@ -1904,7 +1920,7 @@ LUA;
|
|
1904 |
|
1905 |
$data = trim( $data );
|
1906 |
|
1907 |
-
if ( 'N;'
|
1908 |
return true;
|
1909 |
}
|
1910 |
|
@@ -1951,8 +1967,8 @@ LUA;
|
|
1951 |
} elseif ( false === strpos( $data, '"' ) ) {
|
1952 |
return false;
|
1953 |
}
|
1954 |
-
//
|
1955 |
-
//
|
1956 |
case 'a':
|
1957 |
case 'O':
|
1958 |
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
|
@@ -1971,11 +1987,13 @@ LUA;
|
|
1971 |
* Handle the redis failure gracefully or throw an exception.
|
1972 |
*
|
1973 |
* @param \Exception $exception Exception thrown.
|
|
|
|
|
1974 |
*/
|
1975 |
protected function handle_exception( $exception ) {
|
1976 |
$this->redis_connected = false;
|
1977 |
|
1978 |
-
// When Redis is unavailable, fall back to the internal cache by forcing all groups to be "no redis" groups
|
1979 |
$this->ignored_groups = array_unique( array_merge( $this->ignored_groups, $this->global_groups ) );
|
1980 |
|
1981 |
if ( ! $this->fail_gracefully ) {
|
@@ -1984,7 +2002,7 @@ LUA;
|
|
1984 |
|
1985 |
$this->errors[] = $exception->getMessage();
|
1986 |
|
1987 |
-
error_log( $exception );
|
1988 |
|
1989 |
if ( function_exists( 'do_action' ) ) {
|
1990 |
do_action( 'redis_object_cache_error', $exception );
|
@@ -1994,12 +2012,13 @@ LUA;
|
|
1994 |
/**
|
1995 |
* Allows access to private properties for backwards compatibility.
|
1996 |
*
|
1997 |
-
* @param string $name
|
1998 |
* @return mixed
|
1999 |
*/
|
2000 |
public function __get( $name ) {
|
2001 |
-
return isset($this->{$name}) ? $this->{$name} : null;
|
2002 |
}
|
2003 |
}
|
2004 |
|
2005 |
endif;
|
|
3 |
* Plugin Name: Redis Object Cache Drop-In
|
4 |
* Plugin URI: http://wordpress.org/plugins/redis-cache/
|
5 |
* Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, Credis, HHVM, replication, clustering and WP-CLI.
|
6 |
+
* Version: 2.0.12
|
7 |
* Author: Till Krüss
|
8 |
* Author URI: https://objectcache.pro
|
9 |
* License: GPLv3
|
14 |
|
15 |
defined( '\\ABSPATH' ) || exit;
|
16 |
|
17 |
+
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact, Generic.WhiteSpace.ScopeIndent.Incorrect
|
18 |
if ( ! defined( 'WP_REDIS_DISABLED' ) || ! WP_REDIS_DISABLED ) :
|
19 |
|
20 |
/**
|
47 |
* @return bool Always returns True
|
48 |
*/
|
49 |
function wp_cache_close() {
|
50 |
+
return true;
|
51 |
}
|
52 |
|
53 |
/**
|
103 |
* @param string $group The group value appended to the $key.
|
104 |
* @param bool $force Optional. Whether to force an update of the local cache from the persistent
|
105 |
* cache. Default false.
|
106 |
+
* @param bool $found Optional. Whether the key was found in the cache. Disambiguates a return of false,
|
107 |
* a storable value. Passed by reference. Default null.
|
108 |
*
|
109 |
* @return bool|mixed Cached object value.
|
152 |
function wp_cache_init() {
|
153 |
global $wp_object_cache;
|
154 |
|
155 |
+
// Backwards compatibility: map `WP_CACHE_KEY_SALT` constant to `WP_REDIS_PREFIX`.
|
156 |
if ( defined( 'WP_CACHE_KEY_SALT' ) && ! defined( 'WP_REDIS_PREFIX' ) ) {
|
157 |
define( 'WP_REDIS_PREFIX', WP_CACHE_KEY_SALT );
|
158 |
}
|
160 |
if ( ! ( $wp_object_cache instanceof WP_Object_Cache ) ) {
|
161 |
$fail_gracefully = ! defined( 'WP_REDIS_GRACEFUL' ) || WP_REDIS_GRACEFUL;
|
162 |
|
163 |
+
// We need to override this WordPress global in order to inject our cache.
|
164 |
+
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
165 |
$wp_object_cache = new WP_Object_Cache( $fail_gracefully );
|
166 |
}
|
167 |
}
|
208 |
*
|
209 |
* This changes the blog id used to create keys in blog specific groups.
|
210 |
*
|
211 |
+
* @param int $_blog_id The blog ID.
|
212 |
*
|
213 |
* @return bool
|
214 |
*/
|
244 |
$wp_object_cache->add_non_persistent_groups( $groups );
|
245 |
}
|
246 |
|
247 |
+
/**
|
248 |
+
* Object cache class definition
|
249 |
+
*/
|
250 |
class WP_Object_Cache {
|
251 |
|
252 |
/**
|
386 |
/**
|
387 |
* Instantiate the Redis class.
|
388 |
*
|
389 |
+
* @param bool $fail_gracefully Handles and logs errors if true throws exceptions otherwise.
|
390 |
*/
|
391 |
public function __construct( $fail_gracefully = true ) {
|
392 |
global $blog_id, $table_prefix;
|
411 |
try {
|
412 |
switch ( $client ) {
|
413 |
case 'hhvm':
|
414 |
+
$this->connect_using_hhvm( $parameters );
|
415 |
break;
|
416 |
case 'phpredis':
|
417 |
+
$this->connect_using_phpredis( $parameters );
|
418 |
break;
|
419 |
case 'credis':
|
420 |
+
$this->connect_using_credis( $parameters );
|
421 |
break;
|
422 |
case 'predis':
|
423 |
default:
|
424 |
+
$this->connect_using_predis( $parameters );
|
425 |
break;
|
426 |
}
|
427 |
|
438 |
$this->handle_exception( $exception );
|
439 |
}
|
440 |
|
441 |
+
// Assign global and blog prefixes for use with keys.
|
442 |
if ( function_exists( 'is_multisite' ) ) {
|
443 |
$this->global_prefix = is_multisite() ? '' : $table_prefix;
|
444 |
$this->blog_prefix = is_multisite() ? $blog_id : $table_prefix;
|
515 |
/**
|
516 |
* Connect to Redis using the PhpRedis (PECL) extention.
|
517 |
*
|
518 |
+
* @param array $parameters Connection parameters built by the `build_parameters` method.
|
519 |
* @return void
|
520 |
*/
|
521 |
+
protected function connect_using_phpredis( $parameters ) {
|
522 |
$version = phpversion( 'redis' );
|
523 |
|
524 |
$this->diagnostics[ 'client' ] = sprintf( 'PhpRedis (v%s)', $version );
|
599 |
/**
|
600 |
* Connect to Redis using the Predis library.
|
601 |
*
|
602 |
+
* @param array $parameters Connection parameters built by the `build_parameters` method.
|
603 |
+
* @throws \Exception If the Predis library was not found or is unreadable.
|
604 |
* @return void
|
605 |
*/
|
606 |
+
protected function connect_using_predis( $parameters ) {
|
607 |
$client = 'Predis';
|
608 |
|
609 |
+
// Load bundled Predis library.
|
|
|
|
|
|
|
|
|
|
|
610 |
if ( ! class_exists( 'Predis\Client' ) ) {
|
611 |
$predis = sprintf(
|
612 |
'%s/redis-cache/dependencies/predis/predis/autoload.php',
|
613 |
defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins'
|
614 |
);
|
615 |
|
|
|
616 |
if ( is_readable( $predis ) ) {
|
617 |
require_once $predis;
|
618 |
} else {
|
622 |
}
|
623 |
}
|
624 |
|
625 |
+
$servers = false;
|
626 |
$options = array();
|
627 |
|
628 |
if ( defined( 'WP_REDIS_SHARDS' ) ) {
|
629 |
+
$servers = WP_REDIS_SHARDS;
|
630 |
+
$parameters['shards'] = $servers;
|
631 |
} elseif ( defined( 'WP_REDIS_SENTINEL' ) ) {
|
632 |
+
$servers = WP_REDIS_SERVERS;
|
633 |
+
$parameters['servers'] = $servers;
|
634 |
$options['replication'] = 'sentinel';
|
635 |
$options['service'] = WP_REDIS_SENTINEL;
|
636 |
} elseif ( defined( 'WP_REDIS_SERVERS' ) ) {
|
637 |
+
$servers = WP_REDIS_SERVERS;
|
638 |
+
$parameters['servers'] = $servers;
|
639 |
$options['replication'] = true;
|
640 |
} elseif ( defined( 'WP_REDIS_CLUSTER' ) ) {
|
641 |
+
$servers = WP_REDIS_CLUSTER;
|
642 |
+
$parameters['cluster'] = $servers;
|
643 |
$options['cluster'] = 'redis';
|
644 |
}
|
645 |
|
659 |
}
|
660 |
}
|
661 |
|
662 |
+
$this->redis = new Predis\Client( $servers ?: $parameters, $options );
|
663 |
$this->redis->connect();
|
664 |
|
665 |
$this->diagnostics = array_merge(
|
672 |
/**
|
673 |
* Connect to Redis using the Credis library.
|
674 |
*
|
675 |
+
* @param array $parameters Connection parameters built by the `build_parameters` method.
|
676 |
+
* @throws \Exception If the Credis library was not found or is unreadable.
|
677 |
+
* @throws \Exception If redis sharding should be configured as Credis does not support sharding.
|
678 |
+
* @throws \Exception If more than one seninel is configured as Credis does not support multiple sentinel servers.
|
679 |
* @return void
|
680 |
*/
|
681 |
+
protected function connect_using_credis( $parameters ) {
|
682 |
$client = 'Credis';
|
683 |
|
|
|
|
|
|
|
|
|
|
|
684 |
$creds_path = sprintf(
|
685 |
'%s/redis-cache/dependencies/colinmollenhour/credis/',
|
686 |
defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins'
|
692 |
$to_load[] = 'Client.php';
|
693 |
}
|
694 |
|
695 |
+
$has_shards = defined( 'WP_REDIS_SHARDS' );
|
696 |
+
$has_sentinel = defined( 'WP_REDIS_SENTINEL' );
|
697 |
+
$has_servers = defined( 'WP_REDIS_SERVERS' );
|
698 |
+
$has_cluster = defined( 'WP_REDIS_CLUSTER' );
|
699 |
+
|
700 |
+
if ( ( $has_shards || $has_sentinel || $has_servers || $has_cluster ) && ! class_exists( 'Credis_Cluster' ) ) {
|
701 |
$to_load[] = 'Cluster.php';
|
702 |
|
703 |
if ( defined( 'WP_REDIS_SENTINEL' ) && ! class_exists( 'Credis_Sentinel' ) ) {
|
726 |
if ( defined( 'WP_REDIS_SENTINEL' ) ) {
|
727 |
if ( is_array( WP_REDIS_SERVERS ) && count( WP_REDIS_SERVERS ) > 1 ) {
|
728 |
throw new Exception(
|
729 |
+
'Multipe sentinel servers are not supported by the bundled Credis library. Please review your Redis Cache configuration.'
|
730 |
);
|
731 |
}
|
732 |
|
741 |
$clients = $is_cluster ? WP_REDIS_CLUSTER : WP_REDIS_SERVERS;
|
742 |
|
743 |
foreach ( $clients as $index => &$connection_string ) {
|
744 |
+
$url_components = wp_parse_url( $connection_string );
|
745 |
parse_str( $url_components['query'], $add_params );
|
746 |
|
747 |
if ( ! $is_cluster && isset( $add_params['alias'] ) ) {
|
773 |
$this->redis = new Credis_Client( ...array_values( $args ) );
|
774 |
}
|
775 |
|
776 |
+
// Don't use PhpRedis if it is available.
|
777 |
$this->redis->forceStandalone();
|
778 |
|
779 |
$this->redis->connect();
|
792 |
/**
|
793 |
* Connect to Redis using HHVM's Redis extention.
|
794 |
*
|
795 |
+
* @param array $parameters Connection parameters built by the `build_parameters` method.
|
796 |
* @return void
|
797 |
*/
|
798 |
+
protected function connect_using_hhvm( $parameters ) {
|
799 |
$this->redis = new Redis();
|
800 |
|
801 |
+
// Adjust host and port if the scheme is `unix`.
|
802 |
if ( strcasecmp( 'unix', $parameters['scheme'] ) === 0 ) {
|
803 |
$parameters['host'] = 'unix://' . $parameters['path'];
|
804 |
$parameters['port'] = 0;
|
869 |
* @return bool
|
870 |
*/
|
871 |
public function redis_status() {
|
872 |
+
return (bool) $this->redis_connected;
|
873 |
}
|
874 |
|
875 |
/**
|
878 |
* @return mixed
|
879 |
*/
|
880 |
public function redis_instance() {
|
881 |
+
return $this->redis;
|
882 |
}
|
883 |
|
884 |
/**
|
887 |
* @return null|string
|
888 |
*/
|
889 |
public function redis_version() {
|
890 |
+
return $this->redis_version;
|
891 |
}
|
892 |
|
893 |
/**
|
927 |
*
|
928 |
* Add does not set the value if the key exists; replace does not replace if the value doesn't exist.
|
929 |
*
|
930 |
+
* @param bool $add True if should only add if value doesn't exist, false to only add when value already exists.
|
931 |
* @param string $key The key under which to store the value.
|
932 |
* @param mixed $value The value to store.
|
933 |
* @param string $group The group value appended to the $key.
|
946 |
$result = true;
|
947 |
$derived_key = $this->build_key( $key, $group );
|
948 |
|
949 |
+
// Save if group not excluded and redis is up.
|
950 |
if ( ! $this->is_ignored_group( $group ) && $this->redis_status() ) {
|
951 |
try {
|
952 |
$expiration = apply_filters( 'redis_cache_expiration', $this->validate_expiration( $expiration ), $key, $group );
|
999 |
|
1000 |
$exists = isset( $this->cache[ $derived_key ] );
|
1001 |
|
1002 |
+
if ( (bool) $add === $exists ) {
|
1003 |
return false;
|
1004 |
}
|
1005 |
|
1154 |
}
|
1155 |
}
|
1156 |
|
1157 |
+
/**
|
1158 |
+
* Quotes a string for usage in the `glob` function
|
1159 |
+
*
|
1160 |
+
* @param string $string The string to quote.
|
1161 |
+
* @return string
|
1162 |
+
*/
|
1163 |
protected function glob_quote( $string ) {
|
1164 |
$characters = [ '*', '+', '?', '!', '{', '}', '[', ']', '(', ')', '|', '@' ];
|
1165 |
|
1277 |
* @param string $group The group value appended to the $key.
|
1278 |
* @param string $force Optional. Whether to force a refetch rather than relying on the local
|
1279 |
* cache. Default false.
|
1280 |
+
* @param bool $found Optional. Whether the key was found in the cache. Disambiguates a return of
|
1281 |
* false, a storable value. Passed by reference. Default null.
|
1282 |
* @return bool|mixed Cached object value.
|
1283 |
*/
|
1380 |
}
|
1381 |
}
|
1382 |
|
1383 |
+
$remaining_keys = array_filter(
|
1384 |
+
$keys,
|
1385 |
+
function ( $key ) use ( $cache ) {
|
1386 |
+
return ! isset( $cache[ $key ] );
|
1387 |
+
}
|
1388 |
+
);
|
1389 |
|
1390 |
if ( empty( $remaining_keys ) ) {
|
1391 |
return $cache;
|
1394 |
$start_time = microtime( true );
|
1395 |
|
1396 |
try {
|
1397 |
+
$remaining_ids = array_map(
|
1398 |
+
function ( $key ) use ( $derived_keys ) {
|
1399 |
+
return $derived_keys[ $key ];
|
1400 |
+
},
|
1401 |
+
$remaining_keys
|
1402 |
+
);
|
1403 |
|
1404 |
$results = array_combine(
|
1405 |
$remaining_keys,
|
1460 |
|
1461 |
$start_time = microtime( true );
|
1462 |
|
1463 |
+
// Save if group not excluded from redis and redis is up.
|
1464 |
if ( ! $this->is_ignored_group( $group ) && $this->redis_status() ) {
|
1465 |
$expiration = apply_filters( 'redis_cache_expiration', $this->validate_expiration( $expiration ), $key, $group );
|
1466 |
|
1480 |
$this->cache_time += ( microtime( true ) - $start_time );
|
1481 |
}
|
1482 |
|
1483 |
+
// If the set was successful, or we didn't go to redis.
|
1484 |
if ( $result ) {
|
1485 |
$this->add_to_internal_cache( $derived_key, $value );
|
1486 |
}
|
1497 |
/**
|
1498 |
* Increment a Redis counter by the amount specified
|
1499 |
*
|
1500 |
+
* @param string $key The key name.
|
1501 |
+
* @param int $offset Optional. The increment. Defaults to 1.
|
1502 |
+
* @param string $group Optional. The key group. Default is 'default'.
|
1503 |
* @return int|bool
|
1504 |
*/
|
1505 |
public function increment( $key, $offset = 1, $group = 'default' ) {
|
1506 |
$offset = (int) $offset;
|
1507 |
$derived_key = $this->build_key( $key, $group );
|
1508 |
|
1509 |
+
// If group is a non-Redis group, save to internal cache, not Redis.
|
1510 |
if ( $this->is_ignored_group( $group ) || ! $this->redis_status() ) {
|
1511 |
$value = $this->get_from_internal_cache( $derived_key );
|
1512 |
$value += $offset;
|
1538 |
/**
|
1539 |
* Alias of `increment()`.
|
1540 |
*
|
1541 |
+
* @see self::increment()
|
1542 |
+
* @param string $key The key name.
|
1543 |
+
* @param int $offset Optional. The increment. Defaults to 1.
|
1544 |
+
* @param string $group Optional. The key group. Default is 'default'.
|
1545 |
+
* @return int|bool
|
1546 |
*/
|
1547 |
public function incr( $key, $offset = 1, $group = 'default' ) {
|
1548 |
return $this->increment( $key, $offset, $group );
|
1551 |
/**
|
1552 |
* Decrement a Redis counter by the amount specified
|
1553 |
*
|
1554 |
+
* @param string $key The key name.
|
1555 |
+
* @param int $offset Optional. The decrement. Defaults to 1.
|
1556 |
+
* @param string $group Optional. The key group. Default is 'default'.
|
1557 |
* @return int|bool
|
1558 |
*/
|
1559 |
public function decrement( $key, $offset = 1, $group = 'default' ) {
|
1560 |
$derived_key = $this->build_key( $key, $group );
|
1561 |
$offset = (int) $offset;
|
1562 |
|
1563 |
+
// If group is a non-Redis group, save to internal cache, not Redis.
|
1564 |
if ( $this->is_ignored_group( $group ) || ! $this->redis_status() ) {
|
1565 |
$value = $this->get_from_internal_cache( $derived_key );
|
1566 |
$value -= $offset;
|
1572 |
$start_time = microtime( true );
|
1573 |
|
1574 |
try {
|
1575 |
+
// Save to Redis.
|
1576 |
$result = $this->parse_redis_response( $this->redis->decrBy( $derived_key, $offset ) );
|
1577 |
|
1578 |
$this->add_to_internal_cache( $derived_key, (int) $this->redis->get( $derived_key ) );
|
1592 |
|
1593 |
/**
|
1594 |
* Render data about current cache requests
|
1595 |
+
* Used by the Debug bar plugin
|
1596 |
*
|
1597 |
+
* @return void
|
1598 |
*/
|
1599 |
public function stats() {
|
1600 |
+
?>
|
1601 |
+
<p>
|
1602 |
+
<strong>Redis Status:</strong>
|
1603 |
+
<?php echo $this->redis_status() ? 'Connected' : 'Not connected'; ?>
|
1604 |
+
<br />
|
1605 |
+
<strong>Redis Client:</strong>
|
1606 |
+
<?php echo $this->diagnostics['client'] ?: 'Unknown'; ?>
|
1607 |
+
<br />
|
1608 |
+
<strong>Cache Hits:</strong>
|
1609 |
+
<?php echo intval( $this->cache_hits ); ?>
|
1610 |
+
<br />
|
1611 |
+
<strong>Cache Misses:</strong>
|
1612 |
+
<?php echo intval( $this->cache_misses ); ?>
|
1613 |
+
<br />
|
1614 |
+
<strong>Cache Size:</strong>
|
1615 |
+
<?php echo number_format( strlen( serialize( $this->cache ) ) / 1024, 2 ); ?> kB
|
1616 |
+
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
1617 |
<?php
|
1618 |
}
|
1619 |
|
1627 |
|
1628 |
$bytes = array_map(
|
1629 |
function ( $keys ) {
|
1630 |
+
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
|
1631 |
return strlen( serialize( $keys ) );
|
1632 |
},
|
1633 |
$this->cache
|
1634 |
);
|
1635 |
|
1636 |
return (object) [
|
|
|
|
|
1637 |
'hits' => $this->cache_hits,
|
1638 |
'misses' => $this->cache_misses,
|
1639 |
'ratio' => $total > 0 ? round( $this->cache_hits / ( $total / 100 ), 1 ) : 100,
|
1684 |
* @return string Sanitized string.
|
1685 |
*/
|
1686 |
protected function sanitize_key_part( $part ) {
|
1687 |
+
return str_replace( ':', '-', $part );
|
1688 |
}
|
1689 |
|
1690 |
/**
|
1691 |
* Checks if the given group is part the ignored group array
|
1692 |
*
|
1693 |
+
* @param string $group Name of the group to check.
|
1694 |
* @return bool
|
1695 |
*/
|
1696 |
protected function is_ignored_group( $group ) {
|
1700 |
/**
|
1701 |
* Checks if the given group is part the global group array
|
1702 |
*
|
1703 |
+
* @param string $group Name of the group to check.
|
1704 |
* @return bool
|
1705 |
*/
|
1706 |
protected function is_global_group( $group ) {
|
1710 |
/**
|
1711 |
* Checks if the given group is part the unflushable group array
|
1712 |
*
|
1713 |
+
* @param string $group Name of the group to check.
|
1714 |
* @return bool
|
1715 |
*/
|
1716 |
protected function is_unflushable_group( $group ) {
|
1720 |
/**
|
1721 |
* Convert Redis responses into something meaningful
|
1722 |
*
|
1723 |
+
* @param mixed $response Response sent from the redis instance.
|
1724 |
* @return mixed
|
1725 |
*/
|
1726 |
protected function parse_redis_response( $response ) {
|
1775 |
/**
|
1776 |
* In multisite, switch blog prefix when switching blogs
|
1777 |
*
|
1778 |
+
* @param int $_blog_id Blog ID.
|
1779 |
* @return bool
|
1780 |
*/
|
1781 |
public function switch_to_blog( $_blog_id ) {
|
1828 |
/**
|
1829 |
* Wrapper to validate the cache keys expiration value
|
1830 |
*
|
1831 |
+
* @param mixed $expiration Incoming expiration value (whatever it is).
|
1832 |
*/
|
1833 |
protected function validate_expiration( $expiration ) {
|
1834 |
$expiration = is_int( $expiration ) || ctype_digit( $expiration ) ? (int) $expiration : 0;
|
1859 |
return igbinary_unserialize( $original );
|
1860 |
}
|
1861 |
|
1862 |
+
// Don't attempt to unserialize data that wasn't serialized going in.
|
1863 |
if ( $this->is_serialized( $original ) ) {
|
1864 |
+
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
|
1865 |
$value = @unserialize( $original );
|
1866 |
|
1867 |
return is_object( $value ) ? clone $value : $value;
|
1890 |
}
|
1891 |
|
1892 |
if ( is_array( $data ) || is_object( $data ) ) {
|
1893 |
+
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
|
1894 |
return serialize( $data );
|
1895 |
}
|
1896 |
|
1897 |
if ( $this->is_serialized( $data, false ) ) {
|
1898 |
+
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
|
1899 |
return serialize( $data );
|
1900 |
}
|
1901 |
|
1920 |
|
1921 |
$data = trim( $data );
|
1922 |
|
1923 |
+
if ( 'N;' === $data ) {
|
1924 |
return true;
|
1925 |
}
|
1926 |
|
1967 |
} elseif ( false === strpos( $data, '"' ) ) {
|
1968 |
return false;
|
1969 |
}
|
1970 |
+
// Or else fall through.
|
1971 |
+
// No break!
|
1972 |
case 'a':
|
1973 |
case 'O':
|
1974 |
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
|
1987 |
* Handle the redis failure gracefully or throw an exception.
|
1988 |
*
|
1989 |
* @param \Exception $exception Exception thrown.
|
1990 |
+
* @throws \Exception If `fail_gracefully` flag is set to a falsy value.
|
1991 |
+
* @return void
|
1992 |
*/
|
1993 |
protected function handle_exception( $exception ) {
|
1994 |
$this->redis_connected = false;
|
1995 |
|
1996 |
+
// When Redis is unavailable, fall back to the internal cache by forcing all groups to be "no redis" groups.
|
1997 |
$this->ignored_groups = array_unique( array_merge( $this->ignored_groups, $this->global_groups ) );
|
1998 |
|
1999 |
if ( ! $this->fail_gracefully ) {
|
2002 |
|
2003 |
$this->errors[] = $exception->getMessage();
|
2004 |
|
2005 |
+
error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
2006 |
|
2007 |
if ( function_exists( 'do_action' ) ) {
|
2008 |
do_action( 'redis_object_cache_error', $exception );
|
2012 |
/**
|
2013 |
* Allows access to private properties for backwards compatibility.
|
2014 |
*
|
2015 |
+
* @param string $name Name of the property.
|
2016 |
* @return mixed
|
2017 |
*/
|
2018 |
public function __get( $name ) {
|
2019 |
+
return isset( $this->{$name} ) ? $this->{$name} : null;
|
2020 |
}
|
2021 |
}
|
2022 |
|
2023 |
endif;
|
2024 |
+
// phpcs:enable Generic.WhiteSpace.ScopeIndent.IncorrectExact, Generic.WhiteSpace.ScopeIndent.Incorrect
|
includes/ui/class-tab.php
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Tab utility class
|
4 |
+
*
|
5 |
+
* @package Rhubarb\RedisCache
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Rhubarb\RedisCache\UI;
|
9 |
+
|
10 |
+
use Rhubarb\RedisCache\Plugin;
|
11 |
+
|
12 |
+
defined( '\\ABSPATH' ) || exit;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Tab class definition
|
16 |
+
*/
|
17 |
+
class Tab {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Tab slug
|
21 |
+
*
|
22 |
+
* @var string $slug
|
23 |
+
*/
|
24 |
+
protected $slug = '';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Tab label
|
28 |
+
*
|
29 |
+
* @var string $label
|
30 |
+
*/
|
31 |
+
protected $label = '';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Tab template file
|
35 |
+
*
|
36 |
+
* @var string $file
|
37 |
+
*/
|
38 |
+
protected $file = '';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Tab default state
|
42 |
+
*
|
43 |
+
* @var bool $default
|
44 |
+
*/
|
45 |
+
protected $default = false;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Tab disabled state
|
49 |
+
*
|
50 |
+
* @var bool $disabled
|
51 |
+
*/
|
52 |
+
protected $disabled = false;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Tab custom data
|
56 |
+
*
|
57 |
+
* @var array $custom
|
58 |
+
*/
|
59 |
+
protected $custom = [];
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Constructor
|
63 |
+
*
|
64 |
+
* @param string $slug Slug to identify the tab.
|
65 |
+
* @param string $label Tab label.
|
66 |
+
* @param array $args Optional arguments describing the tab.
|
67 |
+
*/
|
68 |
+
public function __construct( $slug, $label, $args = [] ) {
|
69 |
+
$args = wp_parse_args(
|
70 |
+
$args,
|
71 |
+
[
|
72 |
+
'slug' => $slug,
|
73 |
+
'label' => $label,
|
74 |
+
'file' => WP_REDIS_PLUGIN_PATH . "/includes/ui/tabs/{$slug}.php",
|
75 |
+
]
|
76 |
+
);
|
77 |
+
foreach ( $args ?: [] as $property => $value ) {
|
78 |
+
if ( property_exists( $this, $property ) ) {
|
79 |
+
$this->{$property} = $value;
|
80 |
+
} else {
|
81 |
+
$this->custom[ $property ] = $value;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Getter for tab slug
|
88 |
+
*
|
89 |
+
* @return string
|
90 |
+
*/
|
91 |
+
public function slug() {
|
92 |
+
return $this->slug;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Getter for tab label
|
97 |
+
*
|
98 |
+
* @return string
|
99 |
+
*/
|
100 |
+
public function label() {
|
101 |
+
return $this->label;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Getter for tab file
|
106 |
+
*
|
107 |
+
* @return string
|
108 |
+
*/
|
109 |
+
public function file() {
|
110 |
+
return $this->file;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Getter for tab disabled state
|
115 |
+
*
|
116 |
+
* @return bool
|
117 |
+
*/
|
118 |
+
public function is_disabled() {
|
119 |
+
return $this->disabled;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Getter for tab default state
|
124 |
+
*
|
125 |
+
* @return bool
|
126 |
+
*/
|
127 |
+
public function is_default() {
|
128 |
+
return $this->default;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Getter for tab custom data
|
133 |
+
*
|
134 |
+
* @param $string $key Custom data key.
|
135 |
+
* @return mixed
|
136 |
+
*/
|
137 |
+
public function custom( $key ) {
|
138 |
+
if ( ! isset( $this->custom[ $key ] ) ) {
|
139 |
+
return null;
|
140 |
+
}
|
141 |
+
return $this->custom[ $key ];
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Disabled notice for tab
|
146 |
+
*
|
147 |
+
* @return string
|
148 |
+
*/
|
149 |
+
public function disabled_notice() {
|
150 |
+
return sprintf(
|
151 |
+
// translators: %s = Tab label.
|
152 |
+
__( '%s are disabled for this site.', 'redis-cache' ),
|
153 |
+
$this->label
|
154 |
+
);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Displays the tab template
|
159 |
+
*
|
160 |
+
* @return void
|
161 |
+
*/
|
162 |
+
public function display() {
|
163 |
+
$roc = Plugin::instance();
|
164 |
+
include $this->file;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Returns the tab nav id attribute
|
169 |
+
*
|
170 |
+
* @return string
|
171 |
+
*/
|
172 |
+
public function nav_id() {
|
173 |
+
return apply_filters( 'roc_tab_nav_id', "{$this->slug}-tab", $this );
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Returns the tab nav css classes
|
178 |
+
*
|
179 |
+
* @return string
|
180 |
+
*/
|
181 |
+
public function nav_classes() {
|
182 |
+
$classes = [
|
183 |
+
'nav-tab',
|
184 |
+
];
|
185 |
+
if ( $this->default ) {
|
186 |
+
$classes[] = 'nav-tab-active';
|
187 |
+
}
|
188 |
+
if ( $this->disabled ) {
|
189 |
+
$classes[] = 'nav-tab-disabled';
|
190 |
+
}
|
191 |
+
return implode( ' ', apply_filters( 'roc_tab_nav_classes', $classes, $this ) );
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Returns the tab id attribute
|
196 |
+
*
|
197 |
+
* @return string
|
198 |
+
*/
|
199 |
+
public function id() {
|
200 |
+
return apply_filters( 'roc_tab_id', "{$this->slug}-pane", $this );
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Returns the tab css classes
|
205 |
+
*
|
206 |
+
* @return string
|
207 |
+
*/
|
208 |
+
public function classes() {
|
209 |
+
$classes = [
|
210 |
+
'tab-pane',
|
211 |
+
"tab-pane-{$this->slug}",
|
212 |
+
];
|
213 |
+
if ( $this->default ) {
|
214 |
+
$classes[] = 'active';
|
215 |
+
}
|
216 |
+
return implode( ' ', apply_filters( 'roc_tab_classes', $classes, $this ) );
|
217 |
+
}
|
218 |
+
|
219 |
+
}
|
includes/ui/diagnostics.php
CHANGED
@@ -10,14 +10,14 @@ defined( '\\ABSPATH' ) || exit;
|
|
10 |
global $wp_object_cache;
|
11 |
|
12 |
$info = [];
|
13 |
-
$filesystem = $
|
14 |
-
$dropin = $
|
15 |
$disabled = defined( 'WP_REDIS_DISABLED' ) && WP_REDIS_DISABLED;
|
16 |
|
17 |
-
$info['Status'] = $
|
18 |
-
$info['Client'] = $
|
19 |
-
$info['Drop-in'] = $
|
20 |
-
? ($dropin ? 'Valid' : 'Invalid')
|
21 |
: 'Not installed';
|
22 |
$info['Disabled'] = $disabled ? 'Yes' : 'No';
|
23 |
$info['Filesystem'] = is_wp_error( $filesystem ) ? $filesystem->get_error_message() : 'Working';
|
@@ -52,7 +52,7 @@ if ( defined( 'HHVM_VERSION' ) ) {
|
|
52 |
}
|
53 |
|
54 |
$info['Plugin Version'] = WP_REDIS_VERSION;
|
55 |
-
$info['Redis Version'] = $
|
56 |
|
57 |
$info['Multisite'] = is_multisite() ? 'Yes' : 'No';
|
58 |
|
@@ -140,6 +140,6 @@ foreach ( $info as $name => $value ) {
|
|
140 |
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
141 |
WP_CLI::line( "{$name}: $value" );
|
142 |
} else {
|
143 |
-
echo "{$name}: {$value}\r\n";
|
144 |
}
|
145 |
}
|
10 |
global $wp_object_cache;
|
11 |
|
12 |
$info = [];
|
13 |
+
$filesystem = $roc->test_filesystem_writing();
|
14 |
+
$dropin = $roc->validate_object_cache_dropin();
|
15 |
$disabled = defined( 'WP_REDIS_DISABLED' ) && WP_REDIS_DISABLED;
|
16 |
|
17 |
+
$info['Status'] = $roc->get_status();
|
18 |
+
$info['Client'] = $roc->get_redis_client_name();
|
19 |
+
$info['Drop-in'] = $roc->object_cache_dropin_exists()
|
20 |
+
? ( $dropin ? 'Valid' : 'Invalid' )
|
21 |
: 'Not installed';
|
22 |
$info['Disabled'] = $disabled ? 'Yes' : 'No';
|
23 |
$info['Filesystem'] = is_wp_error( $filesystem ) ? $filesystem->get_error_message() : 'Working';
|
52 |
}
|
53 |
|
54 |
$info['Plugin Version'] = WP_REDIS_VERSION;
|
55 |
+
$info['Redis Version'] = $roc->get_redis_version() ?: 'Unknown';
|
56 |
|
57 |
$info['Multisite'] = is_multisite() ? 'Yes' : 'No';
|
58 |
|
140 |
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
141 |
WP_CLI::line( "{$name}: $value" );
|
142 |
} else {
|
143 |
+
echo esc_textarea( "{$name}: {$value}\r\n" );
|
144 |
}
|
145 |
}
|
includes/ui/settings.php
CHANGED
@@ -26,28 +26,24 @@ defined( '\\ABSPATH' ) || exit;
|
|
26 |
|
27 |
<h2 class="nav-tab-wrapper">
|
28 |
<?php foreach ( UI::get_tabs() as $ui_tab ) : ?>
|
29 |
-
<?php if ( $ui_tab->
|
30 |
|
31 |
<span
|
32 |
-
class="
|
33 |
-
title="<?php
|
34 |
-
// translators: %s = Tab label
|
35 |
-
esc_html__( '%s are disabled for this site.', 'redis-cache' ),
|
36 |
-
esc_html( $ui_tab->label )
|
37 |
-
) ?>"
|
38 |
>
|
39 |
-
<?php echo esc_html( $ui_tab->label ); ?>
|
40 |
</span>
|
41 |
|
42 |
<?php else : ?>
|
43 |
|
44 |
<a
|
45 |
-
id="<?php echo esc_attr( $ui_tab->
|
46 |
-
class="
|
47 |
-
data-toggle="<?php echo esc_attr( $ui_tab->slug ); ?>"
|
48 |
-
href="#<?php echo esc_attr( $ui_tab->slug ); ?>"
|
49 |
>
|
50 |
-
<?php echo esc_html( $ui_tab->label ); ?>
|
51 |
</a>
|
52 |
|
53 |
<?php endif; ?>
|
@@ -56,11 +52,11 @@ defined( '\\ABSPATH' ) || exit;
|
|
56 |
|
57 |
<div class="tab-content">
|
58 |
<?php foreach ( UI::get_tabs() as $ui_tab ) : ?>
|
59 |
-
<?php if ( ! $ui_tab->
|
60 |
-
<div id="<?php echo esc_attr( $ui_tab->
|
61 |
-
class="
|
62 |
>
|
63 |
-
<?php
|
64 |
</div>
|
65 |
<?php endif; ?>
|
66 |
<?php endforeach; ?>
|
26 |
|
27 |
<h2 class="nav-tab-wrapper">
|
28 |
<?php foreach ( UI::get_tabs() as $ui_tab ) : ?>
|
29 |
+
<?php if ( $ui_tab->is_disabled() ) : ?>
|
30 |
|
31 |
<span
|
32 |
+
class="<?php echo esc_attr( $ui_tab->nav_classes() ); ?>"
|
33 |
+
title="<?php echo esc_attr( $ui_tab->disabled_notice() ); ?>"
|
|
|
|
|
|
|
|
|
34 |
>
|
35 |
+
<?php echo esc_html( $ui_tab->label() ); ?>
|
36 |
</span>
|
37 |
|
38 |
<?php else : ?>
|
39 |
|
40 |
<a
|
41 |
+
id="<?php echo esc_attr( $ui_tab->nav_id() ); ?>"
|
42 |
+
class="<?php echo esc_attr( $ui_tab->nav_classes() ); ?>"
|
43 |
+
data-toggle="<?php echo esc_attr( $ui_tab->slug() ); ?>"
|
44 |
+
href="#<?php echo esc_attr( $ui_tab->slug() ); ?>"
|
45 |
>
|
46 |
+
<?php echo esc_html( $ui_tab->label() ); ?>
|
47 |
</a>
|
48 |
|
49 |
<?php endif; ?>
|
52 |
|
53 |
<div class="tab-content">
|
54 |
<?php foreach ( UI::get_tabs() as $ui_tab ) : ?>
|
55 |
+
<?php if ( ! $ui_tab->is_disabled() ) : ?>
|
56 |
+
<div id="<?php echo esc_attr( $ui_tab->id() ); ?>"
|
57 |
+
class="<?php echo esc_attr( $ui_tab->classes() ); ?>"
|
58 |
>
|
59 |
+
<?php $ui_tab->display(); ?>
|
60 |
</div>
|
61 |
<?php endif; ?>
|
62 |
<?php endforeach; ?>
|
includes/ui/tabs/diagnostics.php
CHANGED
@@ -7,8 +7,6 @@
|
|
7 |
|
8 |
defined( '\\ABSPATH' ) || exit;
|
9 |
|
10 |
-
$plugin = $this;
|
11 |
-
|
12 |
?>
|
13 |
|
14 |
<p>
|
7 |
|
8 |
defined( '\\ABSPATH' ) || exit;
|
9 |
|
|
|
|
|
10 |
?>
|
11 |
|
12 |
<p>
|
includes/ui/tabs/overview.php
CHANGED
@@ -7,14 +7,12 @@
|
|
7 |
|
8 |
defined( '\\ABSPATH' ) || exit;
|
9 |
|
10 |
-
$
|
|
|
|
|
|
|
11 |
|
12 |
-
$
|
13 |
-
$redis_prefix = $plugin->get_redis_prefix();
|
14 |
-
$redis_maxttl = $plugin->get_redis_maxttl();
|
15 |
-
$redis_version = $plugin->get_redis_version();
|
16 |
-
|
17 |
-
$diagnostics = $plugin->get_diagnostics();
|
18 |
|
19 |
?>
|
20 |
|
@@ -37,14 +35,15 @@ $diagnostics = $plugin->get_diagnostics();
|
|
37 |
<th><?php esc_html_e( 'Drop-in:', 'redis-cache' ); ?></th>
|
38 |
<td>
|
39 |
<code>
|
40 |
-
<?php if ( ! $
|
41 |
<?php esc_html_e( 'Not installed', 'redis-cache' ); ?>
|
42 |
-
<?php elseif ( $
|
43 |
<?php esc_html_e( 'Outdated', 'redis-cache' ); ?>
|
44 |
<?php else : ?>
|
45 |
-
<?php
|
46 |
-
|
47 |
-
|
|
|
48 |
?>
|
49 |
<?php endif; ?>
|
50 |
</code>
|
@@ -94,7 +93,7 @@ $diagnostics = $plugin->get_diagnostics();
|
|
94 |
|
95 |
<tr>
|
96 |
<th><?php esc_html_e( 'Status:', 'redis-cache' ); ?></th>
|
97 |
-
<td><code><?php echo esc_html( $
|
98 |
</tr>
|
99 |
|
100 |
<?php if ( ! empty( $diagnostics['host'] ) ) : ?>
|
@@ -161,7 +160,7 @@ $diagnostics = $plugin->get_diagnostics();
|
|
161 |
<tr>
|
162 |
<th><?php esc_html_e( 'Password:', 'redis-cache' ); ?></th>
|
163 |
<td>
|
164 |
-
<code
|
165 |
</td>
|
166 |
</tr>
|
167 |
<?php endif; ?>
|
@@ -235,18 +234,18 @@ $diagnostics = $plugin->get_diagnostics();
|
|
235 |
|
236 |
<p class="submit">
|
237 |
|
238 |
-
<?php if ( $
|
239 |
-
<a href="<?php echo esc_attr( $
|
240 |
<?php esc_html_e( 'Flush Cache', 'redis-cache' ); ?>
|
241 |
</a>
|
242 |
<?php endif; ?>
|
243 |
|
244 |
-
<?php if ( $
|
245 |
-
<a href="<?php echo esc_attr( $
|
246 |
<?php esc_html_e( 'Disable Object Cache', 'redis-cache' ); ?>
|
247 |
</a>
|
248 |
<?php else : ?>
|
249 |
-
<a href="<?php echo esc_attr( $
|
250 |
<?php esc_html_e( 'Enable Object Cache', 'redis-cache' ); ?>
|
251 |
</a>
|
252 |
<?php endif; ?>
|
7 |
|
8 |
defined( '\\ABSPATH' ) || exit;
|
9 |
|
10 |
+
$redis_client = $roc->get_redis_client_name();
|
11 |
+
$redis_prefix = $roc->get_redis_prefix();
|
12 |
+
$redis_maxttl = $roc->get_redis_maxttl();
|
13 |
+
$redis_version = $roc->get_redis_version();
|
14 |
|
15 |
+
$diagnostics = $roc->get_diagnostics();
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
?>
|
18 |
|
35 |
<th><?php esc_html_e( 'Drop-in:', 'redis-cache' ); ?></th>
|
36 |
<td>
|
37 |
<code>
|
38 |
+
<?php if ( ! $roc->object_cache_dropin_exists() ) : ?>
|
39 |
<?php esc_html_e( 'Not installed', 'redis-cache' ); ?>
|
40 |
+
<?php elseif ( $roc->object_cache_dropin_outdated() ) : ?>
|
41 |
<?php esc_html_e( 'Outdated', 'redis-cache' ); ?>
|
42 |
<?php else : ?>
|
43 |
+
<?php
|
44 |
+
$roc->validate_object_cache_dropin()
|
45 |
+
? esc_html_e( 'Valid', 'redis-cache' )
|
46 |
+
: esc_html_e( 'Invalid', 'redis-cache' );
|
47 |
?>
|
48 |
<?php endif; ?>
|
49 |
</code>
|
93 |
|
94 |
<tr>
|
95 |
<th><?php esc_html_e( 'Status:', 'redis-cache' ); ?></th>
|
96 |
+
<td><code><?php echo esc_html( $roc->get_status() ); ?></code></td>
|
97 |
</tr>
|
98 |
|
99 |
<?php if ( ! empty( $diagnostics['host'] ) ) : ?>
|
160 |
<tr>
|
161 |
<th><?php esc_html_e( 'Password:', 'redis-cache' ); ?></th>
|
162 |
<td>
|
163 |
+
<code>••••••••</code>
|
164 |
</td>
|
165 |
</tr>
|
166 |
<?php endif; ?>
|
234 |
|
235 |
<p class="submit">
|
236 |
|
237 |
+
<?php if ( $roc->get_redis_status() ) : ?>
|
238 |
+
<a href="<?php echo esc_attr( $roc->action_link( 'flush-cache' ) ); ?>" class="button button-primary button-large">
|
239 |
<?php esc_html_e( 'Flush Cache', 'redis-cache' ); ?>
|
240 |
</a>
|
241 |
<?php endif; ?>
|
242 |
|
243 |
+
<?php if ( $roc->validate_object_cache_dropin() ) : ?>
|
244 |
+
<a href="<?php echo esc_attr( $roc->action_link( 'disable-cache' ) ); ?>" class="button button-secondary button-large">
|
245 |
<?php esc_html_e( 'Disable Object Cache', 'redis-cache' ); ?>
|
246 |
</a>
|
247 |
<?php else : ?>
|
248 |
+
<a href="<?php echo esc_attr( $roc->action_link( 'enable-cache' ) ); ?>" class="button button-primary button-large">
|
249 |
<?php esc_html_e( 'Enable Object Cache', 'redis-cache' ); ?>
|
250 |
</a>
|
251 |
<?php endif; ?>
|
languages/redis-cache.pot
CHANGED
@@ -2,21 +2,21 @@
|
|
2 |
# This file is distributed under the GPLv3.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: Redis Object Cache 2.0.
|
6 |
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/redis-cache\n"
|
7 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
8 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=UTF-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
12 |
-
"POT-Creation-Date: 2020-08-
|
13 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
14 |
"X-Generator: WP-CLI 2.4.0\n"
|
15 |
"X-Domain: redis-cache\n"
|
16 |
|
17 |
#. Plugin Name of the plugin
|
18 |
-
#: includes/class-plugin.php:
|
19 |
-
#: includes/class-plugin.php:
|
20 |
#: includes/ui/settings.php:18
|
21 |
msgid "Redis Object Cache"
|
22 |
msgstr ""
|
@@ -37,198 +37,198 @@ msgstr ""
|
|
37 |
msgid "https://objectcache.pro"
|
38 |
msgstr ""
|
39 |
|
40 |
-
#: includes/class-plugin.php:
|
41 |
msgid "Redis"
|
42 |
msgstr ""
|
43 |
|
44 |
-
#: includes/class-plugin.php:
|
45 |
-
#: includes/ui/tabs/overview.php:
|
46 |
msgid "Overview"
|
47 |
msgstr ""
|
48 |
|
49 |
-
#: includes/class-plugin.php:
|
50 |
msgid "Metrics"
|
51 |
msgstr ""
|
52 |
|
53 |
-
#: includes/class-plugin.php:
|
54 |
msgid "Diagnostics"
|
55 |
msgstr ""
|
56 |
|
57 |
-
#: includes/class-plugin.php:
|
58 |
msgid "Settings"
|
59 |
msgstr ""
|
60 |
|
61 |
-
#: includes/class-plugin.php:
|
62 |
#: includes/ui/tabs/metrics.php:17
|
63 |
#: includes/ui/widget.php:16
|
64 |
msgid "Time"
|
65 |
msgstr ""
|
66 |
|
67 |
-
#: includes/class-plugin.php:
|
68 |
#: includes/ui/tabs/metrics.php:22
|
69 |
#: includes/ui/widget.php:21
|
70 |
msgid "Bytes"
|
71 |
msgstr ""
|
72 |
|
73 |
-
#: includes/class-plugin.php:
|
74 |
#: includes/ui/tabs/metrics.php:27
|
75 |
#: includes/ui/widget.php:26
|
76 |
msgid "Ratio"
|
77 |
msgstr ""
|
78 |
|
79 |
-
#: includes/class-plugin.php:
|
80 |
#: includes/ui/tabs/metrics.php:32
|
81 |
#: includes/ui/widget.php:31
|
82 |
msgid "Calls"
|
83 |
msgstr ""
|
84 |
|
85 |
-
#: includes/class-plugin.php:
|
86 |
msgid "Not enough data collected, yet."
|
87 |
msgstr ""
|
88 |
|
89 |
-
#: includes/class-plugin.php:
|
90 |
msgid "Enable object cache to collect data."
|
91 |
msgstr ""
|
92 |
|
93 |
-
#: includes/class-plugin.php:
|
94 |
-
#: includes/class-qm-collector.php:
|
95 |
msgid "Disabled"
|
96 |
msgstr ""
|
97 |
|
98 |
-
#: includes/class-plugin.php:
|
99 |
msgid "Drop-in not installed"
|
100 |
msgstr ""
|
101 |
|
102 |
-
#: includes/class-plugin.php:
|
103 |
msgid "Drop-in is invalid"
|
104 |
msgstr ""
|
105 |
|
106 |
-
#: includes/class-plugin.php:
|
107 |
msgid "Connected"
|
108 |
msgstr ""
|
109 |
|
110 |
-
#: includes/class-plugin.php:
|
111 |
msgid "Not connected"
|
112 |
msgstr ""
|
113 |
|
114 |
-
#: includes/class-plugin.php:
|
115 |
-
#: includes/ui/tabs/overview.php:
|
116 |
msgid "Unknown"
|
117 |
msgstr ""
|
118 |
|
119 |
-
#. translators: %s = Action link to update the drop-in
|
120 |
-
#: includes/class-plugin.php:
|
121 |
msgid "The Redis object cache drop-in is outdated. Please <a href=\"%s\">update the drop-in</a>."
|
122 |
msgstr ""
|
123 |
|
124 |
-
#. translators: %s = Action link to update the drop-in
|
125 |
-
#: includes/class-plugin.php:
|
126 |
msgid "A foreign object cache drop-in was found. To use Redis for object caching, please <a href=\"%s\">enable the drop-in</a>."
|
127 |
msgstr ""
|
128 |
|
129 |
-
#: includes/class-plugin.php:
|
130 |
msgid "Object cache flushed."
|
131 |
msgstr ""
|
132 |
|
133 |
-
#: includes/class-plugin.php:
|
134 |
msgid "Object cache could not be flushed."
|
135 |
msgstr ""
|
136 |
|
137 |
-
#: includes/class-plugin.php:
|
138 |
#: includes/cli/class-commands.php:74
|
139 |
msgid "Object cache enabled."
|
140 |
msgstr ""
|
141 |
|
142 |
-
#: includes/class-plugin.php:
|
143 |
#: includes/cli/class-commands.php:76
|
144 |
msgid "Object cache could not be enabled."
|
145 |
msgstr ""
|
146 |
|
147 |
-
#: includes/class-plugin.php:
|
148 |
#: includes/cli/class-commands.php:113
|
149 |
msgid "Object cache disabled."
|
150 |
msgstr ""
|
151 |
|
152 |
-
#: includes/class-plugin.php:
|
153 |
#: includes/cli/class-commands.php:115
|
154 |
msgid "Object cache could not be disabled."
|
155 |
msgstr ""
|
156 |
|
157 |
-
#: includes/class-plugin.php:
|
158 |
#: includes/cli/class-commands.php:147
|
159 |
msgid "Updated object cache drop-in and enabled Redis object cache."
|
160 |
msgstr ""
|
161 |
|
162 |
-
#: includes/class-plugin.php:
|
163 |
#: includes/cli/class-commands.php:149
|
164 |
msgid "Object cache drop-in could not be updated."
|
165 |
msgstr ""
|
166 |
|
167 |
-
#: includes/class-plugin.php:
|
168 |
msgid "Object Cache Pro is out!"
|
169 |
msgstr ""
|
170 |
|
171 |
-
#. translators: %s = Link to the plugin setting screen
|
172 |
-
#: includes/class-plugin.php:
|
173 |
msgid "A <u>business class</u> object cache backend. Truly reliable, highly-optimized and fully customizable, with a <u>dedicated engineer</u> when you most need it. <a href=\"%s\">Learn more »</a>"
|
174 |
msgstr ""
|
175 |
|
176 |
-
#: includes/class-plugin.php:
|
177 |
msgid "Object Cache Pro + WooCommerce = ❤️"
|
178 |
msgstr ""
|
179 |
|
180 |
-
#. translators: %s = Link to the plugin's settings screen
|
181 |
-
#: includes/class-plugin.php:
|
182 |
msgid "Object Cache Pro is a <u>business class</u> object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. <a style=\"color: #bb77ae;\" href=\"%s\">Learn more »</a>"
|
183 |
msgstr ""
|
184 |
|
185 |
#. translators: %1$d = number of objects. %2$s = human-readable size of cache. %3$s = name of the used client.
|
186 |
-
#: includes/class-plugin.php:
|
187 |
msgid "Retrieved %1$d objects (%2$s) from Redis using %3$s."
|
188 |
msgstr ""
|
189 |
|
190 |
-
#: includes/class-plugin.php:
|
191 |
msgid "Could not initialize filesystem."
|
192 |
msgstr ""
|
193 |
|
194 |
-
#: includes/class-plugin.php:
|
195 |
msgid "Object cache file doesn’t exist."
|
196 |
msgstr ""
|
197 |
|
198 |
-
#: includes/class-plugin.php:
|
199 |
msgid "Test file exists, but couldn’t be deleted."
|
200 |
msgstr ""
|
201 |
|
202 |
-
#: includes/class-plugin.php:
|
203 |
msgid "Failed to copy test file."
|
204 |
msgstr ""
|
205 |
|
206 |
-
#: includes/class-plugin.php:
|
207 |
msgid "Copied test file doesn’t exist."
|
208 |
msgstr ""
|
209 |
|
210 |
-
#: includes/class-plugin.php:
|
211 |
msgid "Couldn’t verify test file contents."
|
212 |
msgstr ""
|
213 |
|
214 |
-
#: includes/class-plugin.php:
|
215 |
msgid "Copied test file couldn’t be deleted."
|
216 |
msgstr ""
|
217 |
|
218 |
-
#: includes/class-qm-collector.php:
|
219 |
msgid "Object Cache"
|
220 |
msgstr ""
|
221 |
|
222 |
-
#: includes/class-qm-collector.php:
|
223 |
-
#: includes/ui/tabs/overview.php:
|
224 |
msgid "Yes"
|
225 |
msgstr ""
|
226 |
|
227 |
-
#: includes/class-qm-output.php:
|
228 |
msgid "The Redis Object Cache drop-in is not installed. Use WP CLI or go to \"Settings -> Redis\" to enable drop-in."
|
229 |
msgstr ""
|
230 |
|
231 |
-
#: includes/class-qm-output.php:
|
232 |
msgid "WordPress is using a foreign object cache drop-in and Redis Object Cache is not being used. Use WP CLI or go to \"Settings -> Redis\" to enable drop-in."
|
233 |
msgstr ""
|
234 |
|
@@ -245,6 +245,11 @@ msgstr ""
|
|
245 |
msgid "No object cache drop-in found."
|
246 |
msgstr ""
|
247 |
|
|
|
|
|
|
|
|
|
|
|
248 |
#: includes/ui/query-monitor.php:15
|
249 |
msgid "Status"
|
250 |
msgstr ""
|
@@ -285,152 +290,147 @@ msgstr ""
|
|
285 |
msgid "Metadata"
|
286 |
msgstr ""
|
287 |
|
288 |
-
|
289 |
-
#: includes/ui/settings.php:35
|
290 |
-
msgid "%s are disabled for this site."
|
291 |
-
msgstr ""
|
292 |
-
|
293 |
-
#: includes/ui/settings.php:74
|
294 |
msgid "Resources"
|
295 |
msgstr ""
|
296 |
|
297 |
-
#: includes/ui/settings.php:
|
298 |
msgid "Your site meets the system requirements for the Pro version."
|
299 |
msgstr ""
|
300 |
|
301 |
-
#: includes/ui/settings.php:
|
302 |
msgid "Your site <i>does not</i> meet the requirements for the Pro version:"
|
303 |
msgstr ""
|
304 |
|
305 |
#. translators: %s = PHP Version.
|
306 |
-
#: includes/ui/settings.php:
|
307 |
msgid "The current version of PHP (%s) is too old. PHP 7.0 or newer is required."
|
308 |
msgstr ""
|
309 |
|
310 |
-
#: includes/ui/settings.php:
|
311 |
msgid "The PhpRedis extension is not installed."
|
312 |
msgstr ""
|
313 |
|
314 |
#. translators: %s = Version of the PhpRedis extension.
|
315 |
-
#: includes/ui/settings.php:
|
316 |
msgid "The current version of the PhpRedis extension (%s) is too old. PhpRedis 3.1.1 or newer is required."
|
317 |
msgstr ""
|
318 |
|
319 |
-
#: includes/ui/tabs/overview.php:
|
320 |
msgid "Client:"
|
321 |
msgstr ""
|
322 |
|
323 |
-
#: includes/ui/tabs/overview.php:
|
324 |
msgid "Drop-in:"
|
325 |
msgstr ""
|
326 |
|
327 |
-
#: includes/ui/tabs/overview.php:
|
328 |
msgid "Not installed"
|
329 |
msgstr ""
|
330 |
|
331 |
-
#: includes/ui/tabs/overview.php:
|
332 |
msgid "Outdated"
|
333 |
msgstr ""
|
334 |
|
335 |
-
#: includes/ui/tabs/overview.php:
|
336 |
msgid "Valid"
|
337 |
msgstr ""
|
338 |
|
339 |
-
#: includes/ui/tabs/overview.php:
|
340 |
msgid "Invalid"
|
341 |
msgstr ""
|
342 |
|
343 |
-
#: includes/ui/tabs/overview.php:
|
344 |
msgid "Disabled:"
|
345 |
msgstr ""
|
346 |
|
347 |
-
#: includes/ui/tabs/overview.php:
|
348 |
msgid "Key Prefix:"
|
349 |
msgstr ""
|
350 |
|
351 |
-
#: includes/ui/tabs/overview.php:
|
352 |
msgid "Max. TTL:"
|
353 |
msgstr ""
|
354 |
|
355 |
-
#: includes/ui/tabs/overview.php:
|
356 |
msgid "This doesn’t appear to be a valid number."
|
357 |
msgstr ""
|
358 |
|
359 |
-
#: includes/ui/tabs/overview.php:
|
360 |
msgid "Connection"
|
361 |
msgstr ""
|
362 |
|
363 |
-
#: includes/ui/tabs/overview.php:
|
364 |
msgid "Status:"
|
365 |
msgstr ""
|
366 |
|
367 |
-
#: includes/ui/tabs/overview.php:
|
368 |
msgid "Host:"
|
369 |
msgstr ""
|
370 |
|
371 |
-
#: includes/ui/tabs/overview.php:
|
372 |
msgid "Cluster:"
|
373 |
msgstr ""
|
374 |
|
375 |
-
#: includes/ui/tabs/overview.php:
|
376 |
msgid "Shards:"
|
377 |
msgstr ""
|
378 |
|
379 |
-
#: includes/ui/tabs/overview.php:
|
380 |
msgid "Servers:"
|
381 |
msgstr ""
|
382 |
|
383 |
-
#: includes/ui/tabs/overview.php:
|
384 |
msgid "Port:"
|
385 |
msgstr ""
|
386 |
|
387 |
-
#: includes/ui/tabs/overview.php:
|
388 |
msgid "Username:"
|
389 |
msgstr ""
|
390 |
|
391 |
-
#: includes/ui/tabs/overview.php:
|
392 |
msgid "Password:"
|
393 |
msgstr ""
|
394 |
|
395 |
-
#: includes/ui/tabs/overview.php:
|
396 |
msgid "Database:"
|
397 |
msgstr ""
|
398 |
|
399 |
-
#: includes/ui/tabs/overview.php:
|
400 |
msgid "Connection Timeout:"
|
401 |
msgstr ""
|
402 |
|
403 |
#. translators: %s = Redis connection/read timeout in seconds.
|
404 |
-
#: includes/ui/tabs/overview.php:
|
405 |
-
#: includes/ui/tabs/overview.php:
|
406 |
msgid "%ss"
|
407 |
msgstr ""
|
408 |
|
409 |
-
#: includes/ui/tabs/overview.php:
|
410 |
msgid "Read Timeout:"
|
411 |
msgstr ""
|
412 |
|
413 |
-
#: includes/ui/tabs/overview.php:
|
414 |
msgid "Retry Interval:"
|
415 |
msgstr ""
|
416 |
|
417 |
#. translators: %s = Redis retry interval in milliseconds.
|
418 |
-
#: includes/ui/tabs/overview.php:
|
419 |
msgid "%sms"
|
420 |
msgstr ""
|
421 |
|
422 |
-
#: includes/ui/tabs/overview.php:
|
423 |
msgid "Redis Version:"
|
424 |
msgstr ""
|
425 |
|
426 |
-
#: includes/ui/tabs/overview.php:
|
427 |
msgid "Flush Cache"
|
428 |
msgstr ""
|
429 |
|
430 |
-
#: includes/ui/tabs/overview.php:
|
431 |
msgid "Disable Object Cache"
|
432 |
msgstr ""
|
433 |
|
434 |
-
#: includes/ui/tabs/overview.php:
|
435 |
msgid "Enable Object Cache"
|
436 |
msgstr ""
|
2 |
# This file is distributed under the GPLv3.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: Redis Object Cache 2.0.12\n"
|
6 |
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/redis-cache\n"
|
7 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
8 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=UTF-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
12 |
+
"POT-Creation-Date: 2020-08-19T14:37:52+00:00\n"
|
13 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
14 |
"X-Generator: WP-CLI 2.4.0\n"
|
15 |
"X-Domain: redis-cache\n"
|
16 |
|
17 |
#. Plugin Name of the plugin
|
18 |
+
#: includes/class-plugin.php:134
|
19 |
+
#: includes/class-plugin.php:202
|
20 |
#: includes/ui/settings.php:18
|
21 |
msgid "Redis Object Cache"
|
22 |
msgstr ""
|
37 |
msgid "https://objectcache.pro"
|
38 |
msgstr ""
|
39 |
|
40 |
+
#: includes/class-plugin.php:135
|
41 |
msgid "Redis"
|
42 |
msgstr ""
|
43 |
|
44 |
+
#: includes/class-plugin.php:171
|
45 |
+
#: includes/ui/tabs/overview.php:20
|
46 |
msgid "Overview"
|
47 |
msgstr ""
|
48 |
|
49 |
+
#: includes/class-plugin.php:177
|
50 |
msgid "Metrics"
|
51 |
msgstr ""
|
52 |
|
53 |
+
#: includes/class-plugin.php:183
|
54 |
msgid "Diagnostics"
|
55 |
msgstr ""
|
56 |
|
57 |
+
#: includes/class-plugin.php:224
|
58 |
msgid "Settings"
|
59 |
msgstr ""
|
60 |
|
61 |
+
#: includes/class-plugin.php:295
|
62 |
#: includes/ui/tabs/metrics.php:17
|
63 |
#: includes/ui/widget.php:16
|
64 |
msgid "Time"
|
65 |
msgstr ""
|
66 |
|
67 |
+
#: includes/class-plugin.php:296
|
68 |
#: includes/ui/tabs/metrics.php:22
|
69 |
#: includes/ui/widget.php:21
|
70 |
msgid "Bytes"
|
71 |
msgstr ""
|
72 |
|
73 |
+
#: includes/class-plugin.php:297
|
74 |
#: includes/ui/tabs/metrics.php:27
|
75 |
#: includes/ui/widget.php:26
|
76 |
msgid "Ratio"
|
77 |
msgstr ""
|
78 |
|
79 |
+
#: includes/class-plugin.php:298
|
80 |
#: includes/ui/tabs/metrics.php:32
|
81 |
#: includes/ui/widget.php:31
|
82 |
msgid "Calls"
|
83 |
msgstr ""
|
84 |
|
85 |
+
#: includes/class-plugin.php:299
|
86 |
msgid "Not enough data collected, yet."
|
87 |
msgstr ""
|
88 |
|
89 |
+
#: includes/class-plugin.php:300
|
90 |
msgid "Enable object cache to collect data."
|
91 |
msgstr ""
|
92 |
|
93 |
+
#: includes/class-plugin.php:440
|
94 |
+
#: includes/class-qm-collector.php:66
|
95 |
msgid "Disabled"
|
96 |
msgstr ""
|
97 |
|
98 |
+
#: includes/class-plugin.php:444
|
99 |
msgid "Drop-in not installed"
|
100 |
msgstr ""
|
101 |
|
102 |
+
#: includes/class-plugin.php:448
|
103 |
msgid "Drop-in is invalid"
|
104 |
msgstr ""
|
105 |
|
106 |
+
#: includes/class-plugin.php:453
|
107 |
msgid "Connected"
|
108 |
msgstr ""
|
109 |
|
110 |
+
#: includes/class-plugin.php:454
|
111 |
msgid "Not connected"
|
112 |
msgstr ""
|
113 |
|
114 |
+
#: includes/class-plugin.php:457
|
115 |
+
#: includes/ui/tabs/overview.php:229
|
116 |
msgid "Unknown"
|
117 |
msgstr ""
|
118 |
|
119 |
+
#. translators: %s = Action link to update the drop-in.
|
120 |
+
#: includes/class-plugin.php:571
|
121 |
msgid "The Redis object cache drop-in is outdated. Please <a href=\"%s\">update the drop-in</a>."
|
122 |
msgstr ""
|
123 |
|
124 |
+
#. translators: %s = Action link to update the drop-in.
|
125 |
+
#: includes/class-plugin.php:575
|
126 |
msgid "A foreign object cache drop-in was found. To use Redis for object caching, please <a href=\"%s\">enable the drop-in</a>."
|
127 |
msgstr ""
|
128 |
|
129 |
+
#: includes/class-plugin.php:611
|
130 |
msgid "Object cache flushed."
|
131 |
msgstr ""
|
132 |
|
133 |
+
#: includes/class-plugin.php:617
|
134 |
msgid "Object cache could not be flushed."
|
135 |
msgstr ""
|
136 |
|
137 |
+
#: includes/class-plugin.php:639
|
138 |
#: includes/cli/class-commands.php:74
|
139 |
msgid "Object cache enabled."
|
140 |
msgstr ""
|
141 |
|
142 |
+
#: includes/class-plugin.php:645
|
143 |
#: includes/cli/class-commands.php:76
|
144 |
msgid "Object cache could not be enabled."
|
145 |
msgstr ""
|
146 |
|
147 |
+
#: includes/class-plugin.php:659
|
148 |
#: includes/cli/class-commands.php:113
|
149 |
msgid "Object cache disabled."
|
150 |
msgstr ""
|
151 |
|
152 |
+
#: includes/class-plugin.php:665
|
153 |
#: includes/cli/class-commands.php:115
|
154 |
msgid "Object cache could not be disabled."
|
155 |
msgstr ""
|
156 |
|
157 |
+
#: includes/class-plugin.php:684
|
158 |
#: includes/cli/class-commands.php:147
|
159 |
msgid "Updated object cache drop-in and enabled Redis object cache."
|
160 |
msgstr ""
|
161 |
|
162 |
+
#: includes/class-plugin.php:690
|
163 |
#: includes/cli/class-commands.php:149
|
164 |
msgid "Object cache drop-in could not be updated."
|
165 |
msgstr ""
|
166 |
|
167 |
+
#: includes/class-plugin.php:757
|
168 |
msgid "Object Cache Pro is out!"
|
169 |
msgstr ""
|
170 |
|
171 |
+
#. translators: %s = Link to the plugin setting screen.
|
172 |
+
#: includes/class-plugin.php:760
|
173 |
msgid "A <u>business class</u> object cache backend. Truly reliable, highly-optimized and fully customizable, with a <u>dedicated engineer</u> when you most need it. <a href=\"%s\">Learn more »</a>"
|
174 |
msgstr ""
|
175 |
|
176 |
+
#: includes/class-plugin.php:797
|
177 |
msgid "Object Cache Pro + WooCommerce = ❤️"
|
178 |
msgstr ""
|
179 |
|
180 |
+
#. translators: %s = Link to the plugin's settings screen.
|
181 |
+
#: includes/class-plugin.php:800
|
182 |
msgid "Object Cache Pro is a <u>business class</u> object cache that’s highly-optimized for WooCommerce to provide true reliability, peace of mind and faster load times for your store. <a style=\"color: #bb77ae;\" href=\"%s\">Learn more »</a>"
|
183 |
msgstr ""
|
184 |
|
185 |
#. translators: %1$d = number of objects. %2$s = human-readable size of cache. %3$s = name of the used client.
|
186 |
+
#: includes/class-plugin.php:939
|
187 |
msgid "Retrieved %1$d objects (%2$s) from Redis using %3$s."
|
188 |
msgstr ""
|
189 |
|
190 |
+
#: includes/class-plugin.php:996
|
191 |
msgid "Could not initialize filesystem."
|
192 |
msgstr ""
|
193 |
|
194 |
+
#: includes/class-plugin.php:1003
|
195 |
msgid "Object cache file doesn’t exist."
|
196 |
msgstr ""
|
197 |
|
198 |
+
#: includes/class-plugin.php:1008
|
199 |
msgid "Test file exists, but couldn’t be deleted."
|
200 |
msgstr ""
|
201 |
|
202 |
+
#: includes/class-plugin.php:1013
|
203 |
msgid "Failed to copy test file."
|
204 |
msgstr ""
|
205 |
|
206 |
+
#: includes/class-plugin.php:1017
|
207 |
msgid "Copied test file doesn’t exist."
|
208 |
msgstr ""
|
209 |
|
210 |
+
#: includes/class-plugin.php:1023
|
211 |
msgid "Couldn’t verify test file contents."
|
212 |
msgstr ""
|
213 |
|
214 |
+
#: includes/class-plugin.php:1027
|
215 |
msgid "Copied test file couldn’t be deleted."
|
216 |
msgstr ""
|
217 |
|
218 |
+
#: includes/class-qm-collector.php:32
|
219 |
msgid "Object Cache"
|
220 |
msgstr ""
|
221 |
|
222 |
+
#: includes/class-qm-collector.php:66
|
223 |
+
#: includes/ui/tabs/overview.php:57
|
224 |
msgid "Yes"
|
225 |
msgstr ""
|
226 |
|
227 |
+
#: includes/class-qm-output.php:102
|
228 |
msgid "The Redis Object Cache drop-in is not installed. Use WP CLI or go to \"Settings -> Redis\" to enable drop-in."
|
229 |
msgstr ""
|
230 |
|
231 |
+
#: includes/class-qm-output.php:113
|
232 |
msgid "WordPress is using a foreign object cache drop-in and Redis Object Cache is not being used. Use WP CLI or go to \"Settings -> Redis\" to enable drop-in."
|
233 |
msgstr ""
|
234 |
|
245 |
msgid "No object cache drop-in found."
|
246 |
msgstr ""
|
247 |
|
248 |
+
#. translators: %s = Tab label.
|
249 |
+
#: includes/ui/class-tab.php:152
|
250 |
+
msgid "%s are disabled for this site."
|
251 |
+
msgstr ""
|
252 |
+
|
253 |
#: includes/ui/query-monitor.php:15
|
254 |
msgid "Status"
|
255 |
msgstr ""
|
290 |
msgid "Metadata"
|
291 |
msgstr ""
|
292 |
|
293 |
+
#: includes/ui/settings.php:70
|
|
|
|
|
|
|
|
|
|
|
294 |
msgid "Resources"
|
295 |
msgstr ""
|
296 |
|
297 |
+
#: includes/ui/settings.php:108
|
298 |
msgid "Your site meets the system requirements for the Pro version."
|
299 |
msgstr ""
|
300 |
|
301 |
+
#: includes/ui/settings.php:115
|
302 |
msgid "Your site <i>does not</i> meet the requirements for the Pro version:"
|
303 |
msgstr ""
|
304 |
|
305 |
#. translators: %s = PHP Version.
|
306 |
+
#: includes/ui/settings.php:124
|
307 |
msgid "The current version of PHP (%s) is too old. PHP 7.0 or newer is required."
|
308 |
msgstr ""
|
309 |
|
310 |
+
#: includes/ui/settings.php:133
|
311 |
msgid "The PhpRedis extension is not installed."
|
312 |
msgstr ""
|
313 |
|
314 |
#. translators: %s = Version of the PhpRedis extension.
|
315 |
+
#: includes/ui/settings.php:140
|
316 |
msgid "The current version of the PhpRedis extension (%s) is too old. PhpRedis 3.1.1 or newer is required."
|
317 |
msgstr ""
|
318 |
|
319 |
+
#: includes/ui/tabs/overview.php:27
|
320 |
msgid "Client:"
|
321 |
msgstr ""
|
322 |
|
323 |
+
#: includes/ui/tabs/overview.php:35
|
324 |
msgid "Drop-in:"
|
325 |
msgstr ""
|
326 |
|
327 |
+
#: includes/ui/tabs/overview.php:39
|
328 |
msgid "Not installed"
|
329 |
msgstr ""
|
330 |
|
331 |
+
#: includes/ui/tabs/overview.php:41
|
332 |
msgid "Outdated"
|
333 |
msgstr ""
|
334 |
|
335 |
+
#: includes/ui/tabs/overview.php:45
|
336 |
msgid "Valid"
|
337 |
msgstr ""
|
338 |
|
339 |
+
#: includes/ui/tabs/overview.php:46
|
340 |
msgid "Invalid"
|
341 |
msgstr ""
|
342 |
|
343 |
+
#: includes/ui/tabs/overview.php:55
|
344 |
msgid "Disabled:"
|
345 |
msgstr ""
|
346 |
|
347 |
+
#: includes/ui/tabs/overview.php:64
|
348 |
msgid "Key Prefix:"
|
349 |
msgstr ""
|
350 |
|
351 |
+
#: includes/ui/tabs/overview.php:73
|
352 |
msgid "Max. TTL:"
|
353 |
msgstr ""
|
354 |
|
355 |
+
#: includes/ui/tabs/overview.php:79
|
356 |
msgid "This doesn’t appear to be a valid number."
|
357 |
msgstr ""
|
358 |
|
359 |
+
#: includes/ui/tabs/overview.php:89
|
360 |
msgid "Connection"
|
361 |
msgstr ""
|
362 |
|
363 |
+
#: includes/ui/tabs/overview.php:95
|
364 |
msgid "Status:"
|
365 |
msgstr ""
|
366 |
|
367 |
+
#: includes/ui/tabs/overview.php:101
|
368 |
msgid "Host:"
|
369 |
msgstr ""
|
370 |
|
371 |
+
#: includes/ui/tabs/overview.php:108
|
372 |
msgid "Cluster:"
|
373 |
msgstr ""
|
374 |
|
375 |
+
#: includes/ui/tabs/overview.php:121
|
376 |
msgid "Shards:"
|
377 |
msgstr ""
|
378 |
|
379 |
+
#: includes/ui/tabs/overview.php:134
|
380 |
msgid "Servers:"
|
381 |
msgstr ""
|
382 |
|
383 |
+
#: includes/ui/tabs/overview.php:147
|
384 |
msgid "Port:"
|
385 |
msgstr ""
|
386 |
|
387 |
+
#: includes/ui/tabs/overview.php:154
|
388 |
msgid "Username:"
|
389 |
msgstr ""
|
390 |
|
391 |
+
#: includes/ui/tabs/overview.php:161
|
392 |
msgid "Password:"
|
393 |
msgstr ""
|
394 |
|
395 |
+
#: includes/ui/tabs/overview.php:170
|
396 |
msgid "Database:"
|
397 |
msgstr ""
|
398 |
|
399 |
+
#: includes/ui/tabs/overview.php:177
|
400 |
msgid "Connection Timeout:"
|
401 |
msgstr ""
|
402 |
|
403 |
#. translators: %s = Redis connection/read timeout in seconds.
|
404 |
+
#: includes/ui/tabs/overview.php:183
|
405 |
+
#: includes/ui/tabs/overview.php:200
|
406 |
msgid "%ss"
|
407 |
msgstr ""
|
408 |
|
409 |
+
#: includes/ui/tabs/overview.php:194
|
410 |
msgid "Read Timeout:"
|
411 |
msgstr ""
|
412 |
|
413 |
+
#: includes/ui/tabs/overview.php:211
|
414 |
msgid "Retry Interval:"
|
415 |
msgstr ""
|
416 |
|
417 |
#. translators: %s = Redis retry interval in milliseconds.
|
418 |
+
#: includes/ui/tabs/overview.php:217
|
419 |
msgid "%sms"
|
420 |
msgstr ""
|
421 |
|
422 |
+
#: includes/ui/tabs/overview.php:228
|
423 |
msgid "Redis Version:"
|
424 |
msgstr ""
|
425 |
|
426 |
+
#: includes/ui/tabs/overview.php:239
|
427 |
msgid "Flush Cache"
|
428 |
msgstr ""
|
429 |
|
430 |
+
#: includes/ui/tabs/overview.php:245
|
431 |
msgid "Disable Object Cache"
|
432 |
msgstr ""
|
433 |
|
434 |
+
#: includes/ui/tabs/overview.php:249
|
435 |
msgid "Enable Object Cache"
|
436 |
msgstr ""
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: redis, predis, phpredis, credis, hhvm, pecl, caching, cache, object cache,
|
|
5 |
Requires at least: 3.3
|
6 |
Tested up to: 5.5
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag: 2.0.
|
9 |
License: GPLv3
|
10 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
11 |
|
@@ -83,6 +83,12 @@ To see a list of all available WP-CLI commands, please see the [WP CLI commands
|
|
83 |
|
84 |
== Changelog ==
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
= 2.0.11 =
|
87 |
|
88 |
- Fixed an issue in `wp_cache_get_multiple()` when using Predis
|
@@ -444,6 +450,6 @@ Since Predis isn't maintained any longer, it's highly recommended to switch over
|
|
444 |
|
445 |
== Upgrade Notice ==
|
446 |
|
447 |
-
= 2.0.
|
448 |
|
449 |
Version 2.0 is a significant rewrite of the plugin. Please read the v2.0.0 release notes.
|
5 |
Requires at least: 3.3
|
6 |
Tested up to: 5.5
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 2.0.12
|
9 |
License: GPLv3
|
10 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
11 |
|
83 |
|
84 |
== Changelog ==
|
85 |
|
86 |
+
= 2.0.12 =
|
87 |
+
|
88 |
+
- Fixed bytes metrics calculation
|
89 |
+
- Fixed an issue with non-standard Predis configurations
|
90 |
+
- Improve WordPress Coding Standards
|
91 |
+
|
92 |
= 2.0.11 =
|
93 |
|
94 |
- Fixed an issue in `wp_cache_get_multiple()` when using Predis
|
450 |
|
451 |
== Upgrade Notice ==
|
452 |
|
453 |
+
= 2.0.12 =
|
454 |
|
455 |
Version 2.0 is a significant rewrite of the plugin. Please read the v2.0.0 release notes.
|
redis-cache.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Redis Object Cache
|
4 |
* Plugin URI: https://wordpress.org/plugins/redis-cache/
|
5 |
* Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, Credis, HHVM, replication, clustering and WP-CLI.
|
6 |
-
* Version: 2.0.
|
7 |
* Text Domain: redis-cache
|
8 |
* Domain Path: /languages
|
9 |
* Network: true
|
3 |
* Plugin Name: Redis Object Cache
|
4 |
* Plugin URI: https://wordpress.org/plugins/redis-cache/
|
5 |
* Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, Credis, HHVM, replication, clustering and WP-CLI.
|
6 |
+
* Version: 2.0.12
|
7 |
* Text Domain: redis-cache
|
8 |
* Domain Path: /languages
|
9 |
* Network: true
|