Redis Object Cache - Version 2.0.3

Version Description

Version 2.0 is a significant rewrite of the plugin. Please read the v2.0.0 release notes.

  • Hide "Metrics" tab when metrics are disabled
  • Fixed admin.js not loading in multisite environments
  • Avoid fatal error when interacting with metrics but Redis went away
  • Added WP_Object_Cache::__get() for backwards compatibility
Download this release

Release Info

Developer tillkruess
Plugin Icon 128x128 Redis Object Cache
Version 2.0.3
Comparing to
See all releases

Code changes from version 2.0.2 to 2.0.3

assets/js/admin.js CHANGED
@@ -39,14 +39,21 @@
39
  '#72777c',
40
  ],
41
  annotations: {
42
- texts: [{ x: '15%', y: '30%', fontSize: '20px', fontWeight: 600, fontFamily: 'inherit', foreColor: '#72777c' }],
 
 
 
 
 
 
 
43
  },
44
  chart: {
45
  type: 'line',
46
  height: '100%',
47
  toolbar: { show: false },
48
  zoom: { enabled: false },
49
- animations: { enabled: false }
50
  },
51
  dataLabels: {
52
  enabled: false,
@@ -72,8 +79,8 @@
72
  min: 0,
73
  labels: {
74
  style: { colors: '#72777c', fontSize: '13px', fontFamily: 'inherit' },
75
- formatter: function (value) {
76
- return Math.round(value);
77
  },
78
  },
79
  },
@@ -121,7 +128,7 @@
121
  yaxis: {
122
  labels: {
123
  formatter: function ( value ) {
124
- return Math.round(value) + ' ms';
125
  },
126
  },
127
  },
@@ -129,12 +136,13 @@
129
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
130
  return [
131
  rediscache.templates.tooltip_title({
132
- title: new Date( w.globals.seriesX[seriesIndex][dataPointIndex] ).toTimeString().slice( 0, 5 ),
 
133
  }),
134
  rediscache.templates.series_group({
135
  color: rediscache.chart_defaults.colors[0],
136
  name: w.globals.seriesNames[0],
137
- value: series[0][dataPointIndex].toFixed(2) + ' ms',
138
  }),
139
  rediscache.templates.series_pro({
140
  color: rediscache.chart_defaults.colors[1],
@@ -156,12 +164,12 @@
156
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
157
  return [
158
  rediscache.templates.tooltip_title({
159
- title: new Date( w.globals.seriesX[seriesIndex][dataPointIndex] ).toTimeString().slice( 0, 5 ),
160
  }),
161
  rediscache.templates.series_group({
162
  color: rediscache.chart_defaults.colors[0],
163
  name: w.globals.seriesNames[0],
164
- value: Math.round( series[0][dataPointIndex] / 1024 ) + ' kb',
165
  }),
166
  rediscache.templates.series_pro({
167
  color: rediscache.chart_defaults.colors[1],
@@ -184,12 +192,13 @@
184
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
185
  return [
186
  rediscache.templates.tooltip_title({
187
- title: new Date( w.globals.seriesX[seriesIndex][dataPointIndex] ).toTimeString().slice( 0, 5 ),
 
188
  }),
189
  rediscache.templates.series_group({
190
  color: rediscache.chart_defaults.colors[0],
191
  name: w.globals.seriesNames[0],
192
- value: Math.round( series[0][dataPointIndex] * 100 ) / 100 + '%',
193
  }),
194
  ].join('');
195
  },
@@ -200,12 +209,13 @@
200
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
201
  return [
202
  rediscache.templates.tooltip_title({
203
- title: new Date( w.globals.seriesX[seriesIndex][dataPointIndex] ).toTimeString().slice( 0, 5 ),
 
204
  }),
205
  rediscache.templates.series_group({
206
  color: rediscache.chart_defaults.colors[0],
207
  name: w.globals.seriesNames[0],
208
- value: Math.round( series[0][dataPointIndex] ),
209
  }),
210
  rediscache.templates.series_pro({
211
  color: rediscache.chart_defaults.colors[1],
@@ -305,13 +315,13 @@
305
 
306
  var render_chart = function ( id ) {
307
  if ( rediscache.chart ) {
308
- rediscache.chart.updateOptions( rediscache.charts[id] );
309
  return;
310
  }
311
 
312
  var chart = new ApexCharts(
313
  document.querySelector( '#redis-stats-chart' ),
314
- rediscache.charts[id]
315
  );
316
 
317
  chart.render();
@@ -321,25 +331,25 @@
321
  var setup_charts = function () {
322
  var time = rediscache.metrics.computed.map(
323
  function ( entry ) {
324
- return [entry.date, entry.time];
325
  }
326
  );
327
 
328
  var bytes = rediscache.metrics.computed.map(
329
  function ( entry ) {
330
- return [entry.date, entry.bytes];
331
  }
332
  )
333
 
334
  var ratio = rediscache.metrics.computed.map(
335
  function ( entry ) {
336
- return [entry.date, entry.ratio];
337
  }
338
  );
339
 
340
  var calls = rediscache.metrics.computed.map(
341
  function ( entry ) {
342
- return [entry.date, entry.calls];
343
  }
344
  );
345
 
@@ -352,7 +362,7 @@
352
  type: 'line',
353
  data: time.map(
354
  function ( entry ) {
355
- return [entry[0], entry[1] * 0.5];
356
  }
357
  ),
358
  } ];
@@ -366,7 +376,7 @@
366
  type: 'line',
367
  data: bytes.map(
368
  function ( entry ) {
369
- return [entry[0], entry[1] * 0.3];
370
  }
371
  ),
372
  } ];
@@ -386,7 +396,7 @@
386
  type: 'line',
387
  data: calls.map(
388
  function ( entry ) {
389
- return [entry[0], Math.round( entry[1] / 50 ) + 5];
390
  }
391
  ),
392
  } ];
@@ -394,68 +404,66 @@
394
 
395
  // executed on page load
396
  $(function () {
 
397
 
398
- var $tabs = $('#redis-tabs');
399
- $tabs.find('a').on(
400
  'click.redis',
401
  function () {
402
- var $this = $(this),
403
- $target = $($this.data('target'));
404
- $tabs.find('a').removeClass('nav-tab-active');
405
- $('.section').removeClass('active');
406
- $target.addClass('active');
407
- $this.addClass('nav-tab-active');
408
- $(window).trigger('redis-tab-change', $target);
409
  }
410
  );
411
 
412
- var tabHash = window.location.hash.replace('#top#', '');
413
- if ( -1 !== tabHash.search('#top') ) {
414
- tabHash = window.location.hash.replace('#top%23', '');
415
- }
416
- if ( '' !== tabHash && '#' !== tabHash.charAt(0) ) {
417
- $tabs.find('a').removeClass('nav-tab-active');
418
- $('.section').removeClass('active');
419
- $('#' + tabHash).addClass('active');
420
- $('#' + tabHash + '-tab').addClass('nav-tab-active').trigger('click.redis');
421
  }
422
 
423
- if ($('#widget-redis-stats').length) {
424
  rediscache.metrics.computed = compute_metrics(
425
  root.rediscache_metrics,
426
  rediscache.metrics.names
427
  );
428
 
429
  setup_charts();
430
- render_chart('time');
431
  }
432
 
433
- $('#widget-redis-stats ul a').on(
434
  'click.redis',
435
- function (event) {
436
  event.preventDefault();
437
 
438
- $('#widget-redis-stats .active').removeClass('active');
439
- $(this).blur().addClass('active');
440
 
441
  render_chart(
442
- $(event.target).data('chart')
443
  );
444
  }
445
  );
446
 
447
- $('.notice.is-dismissible[data-dismissible]').on(
448
  'click.roc-dismiss-notice',
449
  '.notice-dismiss',
450
- function (event) {
451
  event.preventDefault();
452
 
453
- $.post(ajaxurl, {
454
- notice: $(this).parent().attr('data-dismissible'),
455
  action: 'roc_dismiss_notice',
456
- });
457
  }
458
  );
459
  });
460
 
461
- } ( window[rediscache.jQuery], window ) );
39
  '#72777c',
40
  ],
41
  annotations: {
42
+ texts: [{
43
+ x: '15%',
44
+ y: '30%',
45
+ fontSize: '20px',
46
+ fontWeight: 600,
47
+ fontFamily: 'inherit',
48
+ foreColor: '#72777c',
49
+ }],
50
  },
51
  chart: {
52
  type: 'line',
53
  height: '100%',
54
  toolbar: { show: false },
55
  zoom: { enabled: false },
56
+ animations: { enabled: false },
57
  },
58
  dataLabels: {
59
  enabled: false,
79
  min: 0,
80
  labels: {
81
  style: { colors: '#72777c', fontSize: '13px', fontFamily: 'inherit' },
82
+ formatter: function ( value ) {
83
+ return Math.round( value );
84
  },
85
  },
86
  },
128
  yaxis: {
129
  labels: {
130
  formatter: function ( value ) {
131
+ return Math.round( value ) + ' ms';
132
  },
133
  },
134
  },
136
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
137
  return [
138
  rediscache.templates.tooltip_title({
139
+ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] )
140
+ .toTimeString().slice( 0, 5 ),
141
  }),
142
  rediscache.templates.series_group({
143
  color: rediscache.chart_defaults.colors[0],
144
  name: w.globals.seriesNames[0],
145
+ value: series[0][ dataPointIndex ].toFixed(2) + ' ms',
146
  }),
147
  rediscache.templates.series_pro({
148
  color: rediscache.chart_defaults.colors[1],
164
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
165
  return [
166
  rediscache.templates.tooltip_title({
167
+ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] ).toTimeString().slice( 0, 5 ),
168
  }),
169
  rediscache.templates.series_group({
170
  color: rediscache.chart_defaults.colors[0],
171
  name: w.globals.seriesNames[0],
172
+ value: Math.round( series[0][ dataPointIndex ] / 1024 ) + ' kb',
173
  }),
174
  rediscache.templates.series_pro({
175
  color: rediscache.chart_defaults.colors[1],
192
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
193
  return [
194
  rediscache.templates.tooltip_title({
195
+ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] )
196
+ .toTimeString().slice( 0, 5 ),
197
  }),
198
  rediscache.templates.series_group({
199
  color: rediscache.chart_defaults.colors[0],
200
  name: w.globals.seriesNames[0],
201
+ value: Math.round( series[0][ dataPointIndex ] * 100 ) / 100 + '%',
202
  }),
203
  ].join('');
204
  },
209
  custom: function ({ series, seriesIndex, dataPointIndex, w }) {
210
  return [
211
  rediscache.templates.tooltip_title({
212
+ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] )
213
+ .toTimeString().slice( 0, 5 ),
214
  }),
215
  rediscache.templates.series_group({
216
  color: rediscache.chart_defaults.colors[0],
217
  name: w.globals.seriesNames[0],
218
+ value: Math.round( series[0][ dataPointIndex ] ),
219
  }),
220
  rediscache.templates.series_pro({
221
  color: rediscache.chart_defaults.colors[1],
315
 
316
  var render_chart = function ( id ) {
317
  if ( rediscache.chart ) {
318
+ rediscache.chart.updateOptions( rediscache.charts[ id ] );
319
  return;
320
  }
321
 
322
  var chart = new ApexCharts(
323
  document.querySelector( '#redis-stats-chart' ),
324
+ rediscache.charts[ id ]
325
  );
326
 
327
  chart.render();
331
  var setup_charts = function () {
332
  var time = rediscache.metrics.computed.map(
333
  function ( entry ) {
334
+ return [ entry.date, entry.time ];
335
  }
336
  );
337
 
338
  var bytes = rediscache.metrics.computed.map(
339
  function ( entry ) {
340
+ return [ entry.date, entry.bytes ];
341
  }
342
  )
343
 
344
  var ratio = rediscache.metrics.computed.map(
345
  function ( entry ) {
346
+ return [ entry.date, entry.ratio ];
347
  }
348
  );
349
 
350
  var calls = rediscache.metrics.computed.map(
351
  function ( entry ) {
352
+ return [ entry.date, entry.calls ];
353
  }
354
  );
355
 
362
  type: 'line',
363
  data: time.map(
364
  function ( entry ) {
365
+ return [ entry[0], entry[1] * 0.5 ];
366
  }
367
  ),
368
  } ];
376
  type: 'line',
377
  data: bytes.map(
378
  function ( entry ) {
379
+ return [ entry[0], entry[1] * 0.3 ];
380
  }
381
  ),
382
  } ];
396
  type: 'line',
397
  data: calls.map(
398
  function ( entry ) {
399
+ return [ entry[0], Math.round( entry[1] / 50 ) + 5 ];
400
  }
401
  ),
402
  } ];
404
 
405
  // executed on page load
406
  $(function () {
407
+ var $tabs = $( '#redis-tabs' );
408
 
409
+ $tabs.find( 'a' ).on(
 
410
  'click.redis',
411
  function () {
412
+ var $this = $( this );
413
+ var $target = $( $this.data( 'target' ) );
414
+
415
+ $tabs.find( 'a' ).removeClass( 'nav-tab-active' );
416
+ $( '.section' ).removeClass( 'active' );
417
+ $target.addClass( 'active' );
418
+ $this.addClass( 'nav-tab-active' );
419
  }
420
  );
421
 
422
+ var tabHash = window.location.hash.replace( '#', '' );
423
+
424
+ if ( tabHash !== '' ) {
425
+ $tabs.find( 'a' ).removeClass( 'nav-tab-active' );
426
+ $( '.section' ).removeClass( 'active' );
427
+ $( '#' + tabHash ).addClass( 'active' );
428
+ $( '#' + tabHash + '-tab' ).addClass( 'nav-tab-active' ).trigger( 'click.redis' );
 
 
429
  }
430
 
431
+ if ( $( '#widget-redis-stats' ).length ) {
432
  rediscache.metrics.computed = compute_metrics(
433
  root.rediscache_metrics,
434
  rediscache.metrics.names
435
  );
436
 
437
  setup_charts();
438
+ render_chart( 'time' );
439
  }
440
 
441
+ $( '#widget-redis-stats ul a' ).on(
442
  'click.redis',
443
+ function ( event ) {
444
  event.preventDefault();
445
 
446
+ $( '#widget-redis-stats .active' ).removeClass( 'active' );
447
+ $( this ).blur().addClass( 'active' );
448
 
449
  render_chart(
450
+ $( event.target ).data( 'chart' )
451
  );
452
  }
453
  );
454
 
455
+ $( '.notice.is-dismissible[data-dismissible]' ).on(
456
  'click.roc-dismiss-notice',
457
  '.notice-dismiss',
458
+ function ( event ) {
459
  event.preventDefault();
460
 
461
+ $.post( ajaxurl, {
462
+ notice: $( this ).parent().attr( 'data-dismissible' ),
463
  action: 'roc_dismiss_notice',
464
+ } );
465
  }
466
  );
467
  });
468
 
469
+ } ( window[ rediscache.jQuery ], window ) );
includes/class-plugin.php CHANGED
@@ -7,13 +7,15 @@
7
 
8
  namespace Rhubarb\RedisCache;
9
 
 
 
10
  defined( '\\ABSPATH' ) || exit;
11
 
12
  class Plugin {
13
 
14
  private $page;
15
 
16
- private $screen = 'settings_page_redis-cache';
17
 
18
  private $actions = array(
19
  'enable-cache',
@@ -29,19 +31,48 @@ class Plugin {
29
  */
30
  private static $instance;
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  private function __construct() {
33
  require_once ABSPATH . 'wp-admin/includes/plugin.php';
34
 
35
  load_plugin_textdomain( 'redis-cache', false, 'redis-cache/languages' );
36
  register_activation_hook( WP_REDIS_FILE, 'wp_cache_flush' );
37
 
38
- $this->page = is_multisite() ? 'settings.php?page=redis-cache' : 'options-general.php?page=redis-cache';
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
 
40
  add_action( 'deactivate_plugin', array( $this, 'on_deactivation' ) );
41
  add_action( 'upgrader_process_complete', array( $this, 'maybe_update_dropin' ), 10, 2 );
42
 
43
  add_action( is_multisite() ? 'network_admin_menu' : 'admin_menu', array( $this, 'add_admin_menu_page' ) );
44
 
 
 
45
  add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
46
  add_action( 'network_admin_notices', array( $this, 'show_admin_notices' ) );
47
 
@@ -66,23 +97,6 @@ class Plugin {
66
 
67
  add_filter( 'qm/collectors', array( $this, 'register_qm_collector' ), 25 );
68
  add_filter( 'qm/outputter/html', array( $this, 'register_qm_output' ) );
69
-
70
- if ( is_admin() && ! wp_next_scheduled( 'rediscache_discard_metrics' ) ) {
71
- wp_schedule_event( time(), 'hourly', 'rediscache_discard_metrics' );
72
- }
73
- }
74
-
75
- /**
76
- * Plugin instanciation method.
77
- *
78
- * @return Plugin
79
- */
80
- public static function instance() {
81
- if ( ! isset( self::$instance ) ) {
82
- self::$instance = new self();
83
- }
84
-
85
- return self::$instance;
86
  }
87
 
88
  public function add_admin_menu_page() {
@@ -97,6 +111,29 @@ class Plugin {
97
  );
98
  }
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  public function show_admin_page() {
101
  // request filesystem credentials?
102
  if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) {
@@ -119,7 +156,11 @@ class Plugin {
119
  }
120
 
121
  UI::register_tab( 'overview', __( 'Overview', 'redis-cache' ), [ 'default' => true ] );
122
- UI::register_tab( 'metrics', __( 'Metrics', 'redis-cache' ) );
 
 
 
 
123
  UI::register_tab( 'diagnostics', __( 'Diagnostics', 'redis-cache' ) );
124
 
125
  // show admin page
@@ -150,10 +191,24 @@ class Plugin {
150
  );
151
  }
152
 
153
- public function enqueue_admin_styles( $hook_suffix ) {
154
- if ( in_array( $hook_suffix, array( 'index.php', $this->screen ) ) ) {
155
- wp_enqueue_style( 'redis-cache', WP_REDIS_DIR . '/assets/css/admin.css', null, WP_REDIS_VERSION );
 
 
156
  }
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
 
159
  public function enqueue_admin_scripts() {
@@ -229,14 +284,18 @@ class Plugin {
229
  return;
230
  }
231
 
232
- $metrics = $wp_object_cache->redis_instance()->zrangebyscore(
233
- $wp_object_cache->build_key( 'metrics', 'redis-cache' ),
234
- time() - ( MINUTE_IN_SECONDS * 30 ),
235
- time() - MINUTE_IN_SECONDS,
236
- [ 'withscores' => true ]
237
- );
 
238
 
239
- wp_localize_script( 'redis-cache', 'rediscache_metrics', $metrics );
 
 
 
240
  }
241
 
242
  public function register_qm_collector( array $collectors ) {
@@ -594,11 +653,15 @@ class Plugin {
594
  'c' => $info->calls,
595
  ];
596
 
597
- $wp_object_cache->redis_instance()->zadd(
598
- $wp_object_cache->build_key( 'metrics', 'redis-cache' ),
599
- time(),
600
- http_build_query( $metrics, null, ';' )
601
- );
 
 
 
 
602
  }
603
 
604
  public function discard_metrics() {
@@ -616,11 +679,15 @@ class Plugin {
616
  return;
617
  }
618
 
619
- $wp_object_cache->redis_instance()->zremrangebyscore(
620
- $wp_object_cache->build_key( 'metrics', 'redis-cache' ),
621
- 0,
622
- time() - HOUR_IN_SECONDS
623
- );
 
 
 
 
624
  }
625
 
626
  public function maybe_print_comment() {
7
 
8
  namespace Rhubarb\RedisCache;
9
 
10
+ use Exception;
11
+
12
  defined( '\\ABSPATH' ) || exit;
13
 
14
  class Plugin {
15
 
16
  private $page;
17
 
18
+ private $screen = '';
19
 
20
  private $actions = array(
21
  'enable-cache',
31
  */
32
  private static $instance;
33
 
34
+ /**
35
+ * Plugin instanciation method.
36
+ *
37
+ * @return Plugin
38
+ */
39
+ public static function instance() {
40
+ if ( ! isset( self::$instance ) ) {
41
+ self::$instance = new self();
42
+ }
43
+
44
+ return self::$instance;
45
+ }
46
+
47
  private function __construct() {
48
  require_once ABSPATH . 'wp-admin/includes/plugin.php';
49
 
50
  load_plugin_textdomain( 'redis-cache', false, 'redis-cache/languages' );
51
  register_activation_hook( WP_REDIS_FILE, 'wp_cache_flush' );
52
 
53
+ if ( is_multisite() ) {
54
+ $this->page = 'settings.php?page=redis-cache';
55
+ $this->screen = 'settings_page_redis-cache-network';
56
+ } else {
57
+ $this->page = 'options-general.php?page=redis-cache';
58
+ $this->screen = 'settings_page_redis-cache';
59
+ }
60
+
61
+ $this->add_actions_and_filters();
62
+
63
+ if ( is_admin() && ! wp_next_scheduled( 'rediscache_discard_metrics' ) ) {
64
+ wp_schedule_event( time(), 'hourly', 'rediscache_discard_metrics' );
65
+ }
66
+ }
67
 
68
+ public function add_actions_and_filters() {
69
  add_action( 'deactivate_plugin', array( $this, 'on_deactivation' ) );
70
  add_action( 'upgrader_process_complete', array( $this, 'maybe_update_dropin' ), 10, 2 );
71
 
72
  add_action( is_multisite() ? 'network_admin_menu' : 'admin_menu', array( $this, 'add_admin_menu_page' ) );
73
 
74
+ add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_menu' ), 1000 );
75
+
76
  add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
77
  add_action( 'network_admin_notices', array( $this, 'show_admin_notices' ) );
78
 
97
 
98
  add_filter( 'qm/collectors', array( $this, 'register_qm_collector' ), 25 );
99
  add_filter( 'qm/outputter/html', array( $this, 'register_qm_output' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
 
102
  public function add_admin_menu_page() {
111
  );
112
  }
113
 
114
+ public function add_admin_bar_menu( $wp_admin_bar ) {
115
+ if ( ! current_user_can( is_multisite() ? 'manage_network_options' : 'manage_options' ) ) {
116
+ return;
117
+ }
118
+
119
+ if ( ! $this->get_redis_status() ) {
120
+ return;
121
+ }
122
+
123
+ if ( ! defined( 'WP_REDIS_DISABLE_ADMINBAR' ) || WP_REDIS_DISABLE_ADMINBAR ) {
124
+ return;
125
+ }
126
+
127
+ $wp_admin_bar->add_node( [
128
+ 'id' => 'redis-cache-flush',
129
+ 'title' => __( 'Flush Object Cache', 'redis-cache' ),
130
+ 'href' => $this->action_link( 'flush-cache' ),
131
+ 'meta' => [
132
+ 'title' => __( 'Flush the Redis object cache', 'redis-cache' ),
133
+ ],
134
+ ] );
135
+ }
136
+
137
  public function show_admin_page() {
138
  // request filesystem credentials?
139
  if ( isset( $_GET['_wpnonce'], $_GET['action'] ) ) {
156
  }
157
 
158
  UI::register_tab( 'overview', __( 'Overview', 'redis-cache' ), [ 'default' => true ] );
159
+
160
+ if ( ! defined( 'WP_REDIS_DISABLE_METRICS' ) || ! WP_REDIS_DISABLE_METRICS ) {
161
+ UI::register_tab( 'metrics', __( 'Metrics', 'redis-cache' ) );
162
+ }
163
+
164
  UI::register_tab( 'diagnostics', __( 'Diagnostics', 'redis-cache' ) );
165
 
166
  // show admin page
191
  );
192
  }
193
 
194
+ public function enqueue_admin_styles() {
195
+ $screen = get_current_screen();
196
+
197
+ if ( ! isset( $screen->id ) ) {
198
+ return;
199
  }
200
+
201
+ $screens = array(
202
+ $this->screen,
203
+ 'dashboard',
204
+ 'dashboard-network',
205
+ );
206
+
207
+ if ( ! in_array( $screen->id, $screens ) ) {
208
+ return;
209
+ }
210
+
211
+ wp_enqueue_style( 'redis-cache', WP_REDIS_DIR . '/assets/css/admin.css', null, WP_REDIS_VERSION );
212
  }
213
 
214
  public function enqueue_admin_scripts() {
284
  return;
285
  }
286
 
287
+ try {
288
+ $metrics = $wp_object_cache->redis_instance()->zrangebyscore(
289
+ $wp_object_cache->build_key( 'metrics', 'redis-cache' ),
290
+ time() - ( MINUTE_IN_SECONDS * 30 ),
291
+ time() - MINUTE_IN_SECONDS,
292
+ [ 'withscores' => true ]
293
+ );
294
 
295
+ wp_localize_script( 'redis-cache', 'rediscache_metrics', $metrics );
296
+ } catch (Exception $exception) {
297
+ error_log($exception);
298
+ }
299
  }
300
 
301
  public function register_qm_collector( array $collectors ) {
653
  'c' => $info->calls,
654
  ];
655
 
656
+ try {
657
+ $wp_object_cache->redis_instance()->zadd(
658
+ $wp_object_cache->build_key( 'metrics', 'redis-cache' ),
659
+ time(),
660
+ http_build_query( $metrics, null, ';' )
661
+ );
662
+ } catch (Exception $exception) {
663
+ error_log($exception);
664
+ }
665
  }
666
 
667
  public function discard_metrics() {
679
  return;
680
  }
681
 
682
+ try {
683
+ $wp_object_cache->redis_instance()->zremrangebyscore(
684
+ $wp_object_cache->build_key( 'metrics', 'redis-cache' ),
685
+ 0,
686
+ time() - HOUR_IN_SECONDS
687
+ );
688
+ } catch (Exception $exception) {
689
+ error_log($exception);
690
+ }
691
  }
692
 
693
  public function maybe_print_comment() {
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.2
7
  * Author: Till Krüss
8
  * Author URI: https://wprediscache.com
9
  * License: GPLv3
@@ -1610,6 +1610,8 @@ LUA;
1610
  );
1611
 
1612
  return (object) [
 
 
1613
  'hits' => $this->cache_hits,
1614
  'misses' => $this->cache_misses,
1615
  'ratio' => $total > 0 ? round( $this->cache_hits / ( $total / 100 ), 1 ) : 100,
@@ -1979,6 +1981,16 @@ LUA;
1979
  do_action( 'redis_object_cache_error', $exception );
1980
  }
1981
  }
 
 
 
 
 
 
 
 
 
 
1982
  }
1983
 
1984
  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.3
7
  * Author: Till Krüss
8
  * Author URI: https://wprediscache.com
9
  * License: GPLv3
1610
  );
1611
 
1612
  return (object) [
1613
+ // Connected, Disabled, Unknown, Not connected
1614
+ 'status' => '...',
1615
  'hits' => $this->cache_hits,
1616
  'misses' => $this->cache_misses,
1617
  'ratio' => $total > 0 ? round( $this->cache_hits / ( $total / 100 ), 1 ) : 100,
1981
  do_action( 'redis_object_cache_error', $exception );
1982
  }
1983
  }
1984
+
1985
+ /**
1986
+ * Allows access to private properties for backwards compatibility.
1987
+ *
1988
+ * @param string $name
1989
+ * @return mixed
1990
+ */
1991
+ public function __get( $name ) {
1992
+ return isset($this->{$name}) ? $this->{$name} : null;
1993
+ }
1994
  }
1995
 
1996
  endif;
includes/ui/settings.php CHANGED
@@ -27,7 +27,7 @@ defined( '\\ABSPATH' ) || exit;
27
  <a class="nav-tab <?php echo $ui_tab->default ? 'nav-tab-active' : ''; ?>"
28
  id="<?php echo esc_attr( $ui_tab->slug ); ?>-tab"
29
  data-target="<?php echo esc_attr( $ui_tab->target ); ?>"
30
- href="#top<?php echo esc_attr( $ui_tab->target ); ?>"
31
  >
32
  <?php echo esc_html( $ui_tab->label ); ?>
33
  </a>
27
  <a class="nav-tab <?php echo $ui_tab->default ? 'nav-tab-active' : ''; ?>"
28
  id="<?php echo esc_attr( $ui_tab->slug ); ?>-tab"
29
  data-target="<?php echo esc_attr( $ui_tab->target ); ?>"
30
+ href="<?php echo esc_attr( $ui_tab->target ); ?>"
31
  >
32
  <?php echo esc_html( $ui_tab->label ); ?>
33
  </a>
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.4
7
  Requires PHP: 5.6
8
- Stable tag: 2.0.2
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -83,16 +83,21 @@ To see a list of all available WP-CLI commands, please see the [WP CLI commands
83
 
84
  == Changelog ==
85
 
86
- = 2.0.2 =
 
 
87
 
88
- Version 2.0 is a significant rewrite. Please read the v2.0.0 release notes.
 
 
 
 
 
89
 
90
  - Updated POT file and comments for translators
91
 
92
  = 2.0.1 =
93
 
94
- Version 2.0 is a significant rewrite. Please read the v2.0.0 release notes.
95
-
96
  - Support older versions of Query Monitor
97
  - Made "Dropin" status more helpful
98
  - Hide Redis version in settings when it isn't available
@@ -384,6 +389,10 @@ Since Predis isn't maintained any longer, it's highly recommended to switch over
384
 
385
  == Upgrade Notice ==
386
 
 
 
 
 
387
  = 1.4.2 =
388
 
389
  This update renames the `redis_object_cache_get` filter to avoid conflicts. Update your code if necessary.
5
  Requires at least: 3.3
6
  Tested up to: 5.4
7
  Requires PHP: 5.6
8
+ Stable tag: 2.0.3
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
83
 
84
  == Changelog ==
85
 
86
+ = 2.0.3 =
87
+
88
+ Version 2.0 is a significant rewrite of the plugin. Please read the v2.0.0 release notes.
89
 
90
+ - Hide "Metrics" tab when metrics are disabled
91
+ - Fixed `admin.js` not loading in multisite environments
92
+ - Avoid fatal error when interacting with metrics but Redis went away
93
+ - Added `WP_Object_Cache::__get()` for backwards compatibility
94
+
95
+ = 2.0.2 =
96
 
97
  - Updated POT file and comments for translators
98
 
99
  = 2.0.1 =
100
 
 
 
101
  - Support older versions of Query Monitor
102
  - Made "Dropin" status more helpful
103
  - Hide Redis version in settings when it isn't available
389
 
390
  == Upgrade Notice ==
391
 
392
+ = 2.0.3 =
393
+
394
+ Version 2.0 is a significant rewrite of the plugin. Please read the v2.0.0 release notes.
395
+
396
  = 1.4.2 =
397
 
398
  This update renames the `redis_object_cache_get` filter to avoid conflicts. Update your code if necessary.
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.2
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.3
7
  * Text Domain: redis-cache
8
  * Domain Path: /languages
9
  * Network: true