Redis Object Cache - Version 1.5.0

Version Description

Since Predis isn't maintained any longer, it's highly recommended to switch over to PhpRedis (the Redis PECL extention).

  • Improved Redis key name builder
  • Added support for PhpRedis serializers
  • Added redis_object_cache_error action
  • Added timeout, read-timeout and retry configuration
  • Added unflushable groups (defaults to ['userlogins'])
  • Fixed passwords not showing in server list
Download this release

Release Info

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

Code changes from version 1.4.3 to 1.5.0

includes/diagnostics.php CHANGED
@@ -47,6 +47,9 @@ $constants = array(
47
  'WP_REDIS_HOST',
48
  'WP_REDIS_PORT',
49
  'WP_REDIS_DATABASE',
 
 
 
50
  'WP_REDIS_SERVERS',
51
  'WP_REDIS_CLUSTER',
52
  'WP_REDIS_SHARDS',
@@ -56,6 +59,7 @@ $constants = array(
56
  'WP_CACHE_KEY_SALT',
57
  'WP_REDIS_GLOBAL_GROUPS',
58
  'WP_REDIS_IGNORED_GROUPS',
 
59
  );
60
 
61
  foreach ( $constants as $constant ) {
@@ -71,6 +75,7 @@ if ( defined( 'WP_REDIS_PASSWORD' ) ) {
71
  if ( $dropin ) {
72
  $info[ 'Global Groups' ] = json_encode( $wp_object_cache->global_groups, JSON_PRETTY_PRINT );
73
  $info[ 'Ignored Groups' ] = json_encode( $wp_object_cache->ignored_groups, JSON_PRETTY_PRINT );
 
74
  }
75
 
76
  foreach ( $info as $name => $value ) {
47
  'WP_REDIS_HOST',
48
  'WP_REDIS_PORT',
49
  'WP_REDIS_DATABASE',
50
+ 'WP_REDIS_TIMEOUT',
51
+ 'WP_REDIS_READ_TIMEOUT',
52
+ 'WP_REDIS_RETRY_INTERVAL',
53
  'WP_REDIS_SERVERS',
54
  'WP_REDIS_CLUSTER',
55
  'WP_REDIS_SHARDS',
59
  'WP_CACHE_KEY_SALT',
60
  'WP_REDIS_GLOBAL_GROUPS',
61
  'WP_REDIS_IGNORED_GROUPS',
62
+ 'WP_REDIS_UNFLUSHABLE_GROUPS',
63
  );
64
 
65
  foreach ( $constants as $constant ) {
75
  if ( $dropin ) {
76
  $info[ 'Global Groups' ] = json_encode( $wp_object_cache->global_groups, JSON_PRETTY_PRINT );
77
  $info[ 'Ignored Groups' ] = json_encode( $wp_object_cache->ignored_groups, JSON_PRETTY_PRINT );
78
+ $info[ 'Unflushable Groups' ] = json_encode( $wp_object_cache->unflushable_groups, JSON_PRETTY_PRINT );
79
  }
80
 
81
  foreach ( $info as $name => $value ) {
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, HHVM, replication, clustering and WP-CLI.
6
- Version: 1.4.3
7
  Author: Till Krüss
8
  Author URI: https://till.im/
9
  License: GPLv3
@@ -341,6 +341,13 @@ class WP_Object_Cache
341
  'userslugs',
342
  );
343
 
 
 
 
 
 
 
 
344
  /**
345
  * List of groups not saved to Redis.
346
  *
@@ -390,10 +397,13 @@ class WP_Object_Cache
390
  $parameters = array(
391
  'scheme' => 'tcp',
392
  'host' => '127.0.0.1',
393
- 'port' => 6379
 
 
 
394
  );
395
 
396
- foreach (array('scheme', 'host', 'port', 'path', 'password', 'database') as $setting) {
397
  $constant = sprintf('WP_REDIS_%s', strtoupper($setting));
398
 
399
  if (defined($constant)) {
@@ -409,6 +419,10 @@ class WP_Object_Cache
409
  $this->ignored_groups = WP_REDIS_IGNORED_GROUPS;
410
  }
411
 
 
 
 
 
412
  $client = defined('WP_REDIS_CLIENT') ? WP_REDIS_CLIENT : null;
413
 
414
  if (class_exists('Redis') && strcasecmp('predis', $client) !== 0) {
@@ -428,7 +442,11 @@ class WP_Object_Cache
428
  $parameters['port'] = 0;
429
  }
430
 
431
- $this->redis->connect($parameters['host'], $parameters['port']);
 
 
 
 
432
  }
433
 
434
  if (strcasecmp('pecl', $client) === 0) {
@@ -442,11 +460,15 @@ class WP_Object_Cache
442
  $this->redis = new Redis();
443
 
444
  if (strcasecmp('unix', $parameters['scheme']) === 0) {
445
- $this->redis->connect($parameters['path']);
446
  } else {
447
- $this->redis->connect($parameters['host'], $parameters['port']);
448
  }
449
  }
 
 
 
 
450
  }
451
 
452
  if (strcasecmp('pecl', $client) === 0 || strcasecmp('hhvm', $client) === 0) {
@@ -455,6 +477,10 @@ class WP_Object_Cache
455
  }
456
 
457
  if (isset($parameters['database'])) {
 
 
 
 
458
  $this->redis->select($parameters['database']);
459
  }
460
  }
@@ -495,6 +521,10 @@ class WP_Object_Cache
495
  } elseif (defined('WP_REDIS_CLUSTER')) {
496
  $parameters = WP_REDIS_CLUSTER;
497
  $options['cluster'] = 'redis';
 
 
 
 
498
  }
499
 
500
  foreach (array('WP_REDIS_SERVERS', 'WP_REDIS_SHARDS', 'WP_REDIS_CLUSTER') as $constant) {
@@ -699,21 +729,14 @@ class WP_Object_Cache
699
  $selective = defined('WP_REDIS_SELECTIVE_FLUSH') ? WP_REDIS_SELECTIVE_FLUSH : null;
700
 
701
  if ($salt && $selective) {
702
- $script = "
703
- local i = 0
704
- for _,k in ipairs(redis.call('keys', '{$salt}*')) do
705
- redis.call('del', k)
706
- i = i + 1
707
- end
708
- return i
709
- ";
710
 
711
  if (defined('WP_REDIS_CLUSTER')) {
712
  try {
713
  foreach ($this->redis->_masters() as $master) {
714
  $redis = new Redis;
715
  $redis->connect($master[0], $master[1]);
716
- $results[] = $this->parse_redis_response($this->redis->eval($script));
717
  unset($redis);
718
  }
719
  } catch (Exception $exception) {
@@ -723,12 +746,7 @@ class WP_Object_Cache
723
  }
724
  } else {
725
  try {
726
- $results[] = $this->parse_redis_response(
727
- $this->redis->eval(
728
- $script,
729
- $this->redis instanceof Predis\Client ? 0 : []
730
- )
731
- );
732
  } catch (Exception $exception) {
733
  $this->handle_exception($exception);
734
 
@@ -775,6 +793,102 @@ class WP_Object_Cache
775
  return true;
776
  }
777
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
  /**
779
  * Retrieve object from cache.
780
  *
@@ -1078,7 +1192,12 @@ class WP_Object_Cache
1078
  $salt = defined('WP_CACHE_KEY_SALT') ? trim(WP_CACHE_KEY_SALT) : '';
1079
  $prefix = in_array($group, $this->global_groups) ? $this->global_prefix : $this->blog_prefix;
1080
 
1081
- return "{$salt}{$prefix}:{$group}:{$key}";
 
 
 
 
 
1082
  }
1083
 
1084
  /**
@@ -1197,6 +1316,18 @@ class WP_Object_Cache
1197
  $this->ignored_groups = array_unique(array_merge($this->ignored_groups, $groups));
1198
  }
1199
 
 
 
 
 
 
 
 
 
 
 
 
 
1200
  /**
1201
  * Wrapper to validate the cache keys expiration value
1202
  *
@@ -1225,6 +1356,10 @@ class WP_Object_Cache
1225
  */
1226
  protected function maybe_unserialize($original)
1227
  {
 
 
 
 
1228
  if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY && function_exists('igbinary_unserialize')) {
1229
  return igbinary_unserialize($original);
1230
  }
@@ -1244,6 +1379,10 @@ class WP_Object_Cache
1244
  */
1245
  protected function maybe_serialize($data)
1246
  {
 
 
 
 
1247
  if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY && function_exists('igbinary_serialize')) {
1248
  return igbinary_serialize($data);
1249
  }
@@ -1357,6 +1496,10 @@ class WP_Object_Cache
1357
  }
1358
 
1359
  error_log($exception);
 
 
 
 
1360
  }
1361
  }
1362
 
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, HHVM, replication, clustering and WP-CLI.
6
+ Version: 1.5.0
7
  Author: Till Krüss
8
  Author URI: https://till.im/
9
  License: GPLv3
341
  'userslugs',
342
  );
343
 
344
+ /**
345
+ * List of groups that will not be flushed.
346
+ *
347
+ * @var array
348
+ */
349
+ public $unflushable_groups = array();
350
+
351
  /**
352
  * List of groups not saved to Redis.
353
  *
397
  $parameters = array(
398
  'scheme' => 'tcp',
399
  'host' => '127.0.0.1',
400
+ 'port' => 6379,
401
+ 'timeout' => 5,
402
+ 'read_timeout' => 5,
403
+ 'retry_interval' => null
404
  );
405
 
406
+ foreach (array('scheme', 'host', 'port', 'path', 'password', 'database', 'timeout', 'read_timeout', 'retry_interval') as $setting) {
407
  $constant = sprintf('WP_REDIS_%s', strtoupper($setting));
408
 
409
  if (defined($constant)) {
419
  $this->ignored_groups = WP_REDIS_IGNORED_GROUPS;
420
  }
421
 
422
+ if (defined('WP_REDIS_UNFLUSHABLE_GROUPS') && is_array(WP_REDIS_UNFLUSHABLE_GROUPS)) {
423
+ $this->unflushable_groups = WP_REDIS_UNFLUSHABLE_GROUPS;
424
+ }
425
+
426
  $client = defined('WP_REDIS_CLIENT') ? WP_REDIS_CLIENT : null;
427
 
428
  if (class_exists('Redis') && strcasecmp('predis', $client) !== 0) {
442
  $parameters['port'] = 0;
443
  }
444
 
445
+ $this->redis->connect($parameters['host'], $parameters['port'], $parameters['timeout'], null, $parameters['retry_interval']);
446
+
447
+ if ($parameters['read_timeout']) {
448
+ $this->redis->setOption(Redis::OPT_READ_TIMEOUT, $parameters['read_timeout']);
449
+ }
450
  }
451
 
452
  if (strcasecmp('pecl', $client) === 0) {
460
  $this->redis = new Redis();
461
 
462
  if (strcasecmp('unix', $parameters['scheme']) === 0) {
463
+ $this->redis->connect($parameters['path'], null, $parameters['timeout'], null, $parameters['retry_interval'], $parameters['read_timeout']);
464
  } else {
465
+ $this->redis->connect($parameters['host'], $parameters['port'], $parameters['timeout'], null, $parameters['retry_interval'], $parameters['read_timeout']);
466
  }
467
  }
468
+
469
+ if (defined('WP_REDIS_SERIALIZER') && ! empty(WP_REDIS_SERIALIZER)) {
470
+ $this->redis->setOption(Redis::OPT_SERIALIZER, WP_REDIS_SERIALIZER);
471
+ }
472
  }
473
 
474
  if (strcasecmp('pecl', $client) === 0 || strcasecmp('hhvm', $client) === 0) {
477
  }
478
 
479
  if (isset($parameters['database'])) {
480
+ if (ctype_digit($parameters['database'])) {
481
+ $parameters['database'] = intval($parameters['database']);
482
+ }
483
+
484
  $this->redis->select($parameters['database']);
485
  }
486
  }
521
  } elseif (defined('WP_REDIS_CLUSTER')) {
522
  $parameters = WP_REDIS_CLUSTER;
523
  $options['cluster'] = 'redis';
524
+ }
525
+
526
+ if ($parameters['read_timeout']) {
527
+ $parameters['read_write_timeout'] = $parameters['read_timeout'];
528
  }
529
 
530
  foreach (array('WP_REDIS_SERVERS', 'WP_REDIS_SHARDS', 'WP_REDIS_CLUSTER') as $constant) {
729
  $selective = defined('WP_REDIS_SELECTIVE_FLUSH') ? WP_REDIS_SELECTIVE_FLUSH : null;
730
 
731
  if ($salt && $selective) {
732
+ $script = $this->get_flush_closure($salt);
 
 
 
 
 
 
 
733
 
734
  if (defined('WP_REDIS_CLUSTER')) {
735
  try {
736
  foreach ($this->redis->_masters() as $master) {
737
  $redis = new Redis;
738
  $redis->connect($master[0], $master[1]);
739
+ $results[] = $this->parse_redis_response($script());
740
  unset($redis);
741
  }
742
  } catch (Exception $exception) {
746
  }
747
  } else {
748
  try {
749
+ $results[] = $this->parse_redis_response($script());
 
 
 
 
 
750
  } catch (Exception $exception) {
751
  $this->handle_exception($exception);
752
 
793
  return true;
794
  }
795
 
796
+ /**
797
+ * Returns a closure to flush selectively.
798
+ *
799
+ * @param string $salt The salt to be used to differentiate.
800
+ * @return callable Generated callable executing the lua script.
801
+ */
802
+ protected function get_flush_closure($salt)
803
+ {
804
+ if ($this->unflushable_groups) {
805
+ return $this->lua_flush_extended_closure($salt);
806
+ } else {
807
+ return $this->lua_flush_closure($salt);
808
+ }
809
+ }
810
+
811
+ /**
812
+ * Returns a closure ready to be called to flush selectively ignoring unflushable groups.
813
+ *
814
+ * @param string $salt The salt to be used to differentiate.
815
+ * @return callable Generated callable executing the lua script.
816
+ */
817
+ protected function lua_flush_closure($salt)
818
+ {
819
+ return function () use ($salt) {
820
+ $script = <<<LUA
821
+ local cur = 0
822
+ local i = 0
823
+ local tmp
824
+ repeat
825
+ tmp = redis.call('SCAN', cur, 'MATCH', '{$salt}*')
826
+ cur = tonumber(tmp[1])
827
+ if tmp[2] then
828
+ for _, v in pairs(tmp[2]) do
829
+ redis.call('del', v)
830
+ i = i + 1
831
+ end
832
+ end
833
+ until 0 == cur
834
+ return i
835
+ LUA;
836
+
837
+ $args = ($this->redis instanceof Predis\Client)
838
+ ? [$script, 0]
839
+ : [$script];
840
+
841
+ return call_user_func_array([$this->redis, 'eval'], $args);
842
+ };
843
+ }
844
+
845
+ /**
846
+ * Returns a closure ready to be called to flush selectively.
847
+ *
848
+ * @param string $salt The salt to be used to differentiate.
849
+ * @return callable Generated callable executing the lua script.
850
+ */
851
+ protected function lua_flush_extended_closure($salt)
852
+ {
853
+ return function () use ($salt) {
854
+ $salt_length = strlen($salt);
855
+
856
+ $unflushable = array_map(function ($group) {
857
+ return ":{$group}:";
858
+ }, $this->unflushable_groups);
859
+
860
+ $script = <<<LUA
861
+ local cur = 0
862
+ local i = 0
863
+ local d, tmp
864
+ repeat
865
+ tmp = redis.call('SCAN', cur, 'MATCH', '{$salt}*')
866
+ cur = tonumber(tmp[1])
867
+ if tmp[2] then
868
+ for _, v in pairs(tmp[2]) do
869
+ d = true
870
+ for _, s in pairs(KEYS) do
871
+ d = d and not v:find(s, {$salt_length})
872
+ if not d then break end
873
+ end
874
+ if d then
875
+ redis.call('del', v)
876
+ i = i + 1
877
+ end
878
+ end
879
+ end
880
+ until 0 == cur
881
+ return i
882
+ LUA;
883
+
884
+ $args = ($this->redis instanceof Predis\Client)
885
+ ? array_merge([$script, count($unflushable)], $unflushable)
886
+ : [$script, $unflushable, count($unflushable)];
887
+
888
+ return call_user_func_array([$this->redis, 'eval'], $args);
889
+ };
890
+ }
891
+
892
  /**
893
  * Retrieve object from cache.
894
  *
1192
  $salt = defined('WP_CACHE_KEY_SALT') ? trim(WP_CACHE_KEY_SALT) : '';
1193
  $prefix = in_array($group, $this->global_groups) ? $this->global_prefix : $this->blog_prefix;
1194
 
1195
+ $key = str_replace(':', '-', $key);
1196
+ $group = str_replace(':', '-', $group);
1197
+
1198
+ $prefix = trim($prefix, '_-:$');
1199
+
1200
+ return mb_strtolower("{$salt}{$prefix}:{$group}:{$key}");
1201
  }
1202
 
1203
  /**
1316
  $this->ignored_groups = array_unique(array_merge($this->ignored_groups, $groups));
1317
  }
1318
 
1319
+ /**
1320
+ * Sets the list of groups not to flushed cached.
1321
+ *
1322
+ * @param array $groups List of groups that are unflushable.
1323
+ */
1324
+ public function add_unflushable_groups($groups)
1325
+ {
1326
+ $groups = (array) $groups;
1327
+
1328
+ $this->unflushable_groups = array_unique(array_merge($this->unflushable_groups, $groups));
1329
+ }
1330
+
1331
  /**
1332
  * Wrapper to validate the cache keys expiration value
1333
  *
1356
  */
1357
  protected function maybe_unserialize($original)
1358
  {
1359
+ if (defined('WP_REDIS_SERIALIZER') && ! empty(WP_REDIS_SERIALIZER)) {
1360
+ return $original;
1361
+ }
1362
+
1363
  if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY && function_exists('igbinary_unserialize')) {
1364
  return igbinary_unserialize($original);
1365
  }
1379
  */
1380
  protected function maybe_serialize($data)
1381
  {
1382
+ if (defined('WP_REDIS_SERIALIZER') && ! empty(WP_REDIS_SERIALIZER)) {
1383
+ return $data;
1384
+ }
1385
+
1386
  if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY && function_exists('igbinary_serialize')) {
1387
  return igbinary_serialize($data);
1388
  }
1496
  }
1497
 
1498
  error_log($exception);
1499
+
1500
+ if (function_exists('do_action')) {
1501
+ do_action('redis_object_cache_error', $exception);
1502
+ }
1503
  }
1504
  }
1505
 
includes/servers-list.php CHANGED
@@ -3,13 +3,11 @@
3
  class Servers_List extends WP_List_Table {
4
 
5
  public function __construct() {
6
-
7
- parent::__construct( array(
8
- 'singular' => __( 'Server', 'redis-cache' ),
9
- 'plural' => __( 'Servers', 'redis-cache' ),
10
  'ajax' => false
11
- ) );
12
-
13
  }
14
 
15
  public function get_columns() {
@@ -27,26 +25,23 @@ class Servers_List extends WP_List_Table {
27
  }
28
 
29
  public function get_hidden_columns() {
 
30
 
31
- $hidden = array( 'host', 'port', 'path' );
32
-
33
- array_walk_recursive( $this->items, function ( $value, $key ) use ( &$hidden ) {
34
- if ( $key == 'scheme' ) {
35
- if ( strcasecmp( 'unix', $value ) === 0 ) {
36
- $hidden = array_diff( $hidden, array( 'path' ) );
37
  } else {
38
- $hidden = array_diff( $hidden, array( 'host', 'port' ) );
39
  }
40
  }
41
- } );
42
 
43
  return $hidden;
44
-
45
  }
46
 
47
  public function prepare_items() {
48
-
49
- if ( ! class_exists( 'Predis\Client' ) ) {
50
  require_once dirname(__FILE__) . '/predis/autoload.php';
51
  }
52
 
@@ -57,74 +52,72 @@ class Servers_List extends WP_List_Table {
57
  $this->get_hidden_columns(),
58
  array()
59
  );
60
-
61
  }
62
 
63
- public function column_default( $item, $column_name ) {
64
-
65
- switch ( $column_name ) {
66
-
67
  case 'scheme':
68
- return isset( $item[ 'scheme' ] ) ? strtoupper( $item[ 'scheme' ] ) : 'TCP';
69
-
70
  case 'host':
71
- return isset( $item[ 'host' ] ) ? $item[ 'host' ] : '127.0.0.1';
72
-
73
  case 'port':
74
- return isset( $item[ 'port' ] ) ? $item[ 'port' ] : '6379';
75
-
76
  case 'database':
77
- return isset( $item[ 'database' ] ) ? $item[ 'database' ] : '0';
78
-
79
  case 'password':
80
- return isset( $item[ 'password' ] ) ? __( 'Yes', 'redis-cache' ) : __( 'No', 'redis-cache' );
81
-
82
  default:
83
- return isset( $item[ $column_name ] ) ? $item[ $column_name ] : '';
84
  }
85
-
86
  }
87
 
88
- protected function display_tablenav($which)
89
- {
90
  // hide table navigation
91
  }
92
 
93
  protected function get_servers() {
94
-
95
  $server = array(
96
  'alias' => 'Master',
97
  'scheme' => 'tcp',
98
  );
99
 
100
- foreach ( array( 'scheme', 'host', 'port', 'path', 'password', 'database' ) as $setting ) {
101
- $constant = sprintf( 'WP_REDIS_%s', strtoupper( $setting ) );
102
 
103
- if ( defined( $constant ) ) {
104
- $server[ $setting ] = constant( $constant );
105
  }
106
  }
107
 
108
- if ( defined( 'WP_REDIS_SHARDS' ) ) {
109
  $servers = WP_REDIS_SHARDS;
110
  }
111
 
112
- if ( defined( 'WP_REDIS_CLUSTER' ) ) {
113
  $servers = WP_REDIS_CLUSTER;
114
  }
115
 
116
- if ( defined( 'WP_REDIS_SERVERS' ) ) {
117
  $servers = WP_REDIS_SERVERS;
118
  }
119
 
120
- if ( ! isset( $servers ) ) {
121
- $servers = array( $server );
122
  }
123
 
124
- return array_map( function ( $parameters ) {
125
- return is_string( $parameters ) ? Predis\Connection\Parameters::parse( $parameters ) : $parameters;
126
- }, $servers );
127
 
128
- }
 
 
 
 
 
 
 
 
129
 
 
 
 
130
  }
3
  class Servers_List extends WP_List_Table {
4
 
5
  public function __construct() {
6
+ parent::__construct(array(
7
+ 'singular' => __('Server', 'redis-cache'),
8
+ 'plural' => __('Servers', 'redis-cache'),
 
9
  'ajax' => false
10
+ ));
 
11
  }
12
 
13
  public function get_columns() {
25
  }
26
 
27
  public function get_hidden_columns() {
28
+ $hidden = array('host', 'port', 'path');
29
 
30
+ array_walk_recursive($this->items, function ($value, $key) use (&$hidden) {
31
+ if ($key == 'scheme') {
32
+ if (strcasecmp('unix', $value) === 0) {
33
+ $hidden = array_diff($hidden, array('path'));
 
 
34
  } else {
35
+ $hidden = array_diff($hidden, array('host', 'port'));
36
  }
37
  }
38
+ });
39
 
40
  return $hidden;
 
41
  }
42
 
43
  public function prepare_items() {
44
+ if (! class_exists('Predis\Client')) {
 
45
  require_once dirname(__FILE__) . '/predis/autoload.php';
46
  }
47
 
52
  $this->get_hidden_columns(),
53
  array()
54
  );
 
55
  }
56
 
57
+ public function column_default($item, $column_name) {
58
+ switch ($column_name) {
 
 
59
  case 'scheme':
60
+ return isset($item['scheme']) ? strtoupper($item['scheme']) : 'TCP';
 
61
  case 'host':
62
+ return isset($item['host']) ? $item['host'] : '127.0.0.1';
 
63
  case 'port':
64
+ return isset($item['port']) ? $item['port'] : '6379';
 
65
  case 'database':
66
+ return isset($item['database']) ? $item['database'] : '0';
 
67
  case 'password':
68
+ return isset($item['password']) ? __('Yes', 'redis-cache') : __('No', 'redis-cache');
 
69
  default:
70
+ return isset($item[$column_name]) ? $item[$column_name] : '';
71
  }
 
72
  }
73
 
74
+ protected function display_tablenav($which) {
 
75
  // hide table navigation
76
  }
77
 
78
  protected function get_servers() {
 
79
  $server = array(
80
  'alias' => 'Master',
81
  'scheme' => 'tcp',
82
  );
83
 
84
+ foreach (array('scheme', 'host', 'port', 'path', 'password', 'database', 'timeout', 'read_timeout', 'retry_interval') as $setting) {
85
+ $constant = sprintf('WP_REDIS_%s', strtoupper($setting));
86
 
87
+ if (defined($constant)) {
88
+ $server[$setting] = constant($constant);
89
  }
90
  }
91
 
92
+ if (defined('WP_REDIS_SHARDS')) {
93
  $servers = WP_REDIS_SHARDS;
94
  }
95
 
96
+ if (defined('WP_REDIS_CLUSTER')) {
97
  $servers = WP_REDIS_CLUSTER;
98
  }
99
 
100
+ if (defined('WP_REDIS_SERVERS')) {
101
  $servers = WP_REDIS_SERVERS;
102
  }
103
 
104
+ if (! isset($servers)) {
105
+ $servers = array($server);
106
  }
107
 
108
+ $servers = array_map(function ($server) {
 
 
109
 
110
+ return is_string($server)
111
+ ? Predis\Connection\Parameters::parse($server)
112
+ : $server;
113
+ }, $servers);
114
+
115
+ return array_map(function ($server) {
116
+ if (defined('WP_REDIS_PASSWORD') && ! empty(WP_REDIS_PASSWORD)) {
117
+ $server['password'] = '********';
118
+ }
119
 
120
+ return $server;
121
+ }, $servers);
122
+ }
123
  }
includes/wp-cli-commands.php CHANGED
@@ -2,6 +2,11 @@
2
 
3
  WP_CLI::add_command( 'redis', 'RedisObjectCache_CLI_Commands' );
4
 
 
 
 
 
 
5
  class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
6
 
7
  /**
2
 
3
  WP_CLI::add_command( 'redis', 'RedisObjectCache_CLI_Commands' );
4
 
5
+ /**
6
+ * Enables, disabled, updates, and checks the status of the Redis object cache.
7
+ *
8
+ * @package wp-cli
9
+ */
10
  class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
11
 
12
  /**
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: redis, predis, phpredis, hhvm, pecl, caching, cache, object cache, perform
5
  Requires at least: 3.3
6
  Tested up to: 5.2
7
  Requires PHP: 5.4
8
- Stable tag: 1.4.3
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -67,6 +67,18 @@ To adjust the connection parameters, define any of the following constants in yo
67
 
68
  Accepts a value used to authenticate with a Redis server protected by password with the `AUTH` command.
69
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
  == Configuration Parameters ==
72
 
@@ -92,6 +104,10 @@ To adjust the configuration, define any of the following constants in your `wp-c
92
 
93
  Set the cache groups that should not be cached in Redis.
94
 
 
 
 
 
95
  * `WP_REDIS_DISABLED` (default: _not set_)
96
 
97
  Set to `true` to disable the object cache at runtime.
@@ -100,9 +116,13 @@ To adjust the configuration, define any of the following constants in your `wp-c
100
 
101
  Set to `false` to disable graceful failures and throw exceptions.
102
 
 
 
 
 
103
  * `WP_REDIS_IGBINARY` (default: _not set_)
104
 
105
- Set to `true` to enable the [igbinary](https://github.com/igbinary/igbinary) serializer.
106
 
107
 
108
  == Replication & Clustering ==
@@ -180,6 +200,17 @@ The following commands are supported:
180
 
181
  == Changelog ==
182
 
 
 
 
 
 
 
 
 
 
 
 
183
  = 1.4.3 =
184
 
185
  * Require PHP 5.4 or newer
5
  Requires at least: 3.3
6
  Tested up to: 5.2
7
  Requires PHP: 5.4
8
+ Stable tag: 1.5.0
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
67
 
68
  Accepts a value used to authenticate with a Redis server protected by password with the `AUTH` command.
69
 
70
+ * `WP_REDIS_TIMEOUT` (default: `5`)
71
+
72
+ Amount of time in seconds (fractions of a second allowed) to attempt initial connection to Redis server before failing.
73
+
74
+ * `WP_REDIS_READ_TIMEOUT` (default: `5`)
75
+
76
+ Amount of time in seconds (fractions of a second allowed) to attempt a read from the Redis server before failing.
77
+
78
+ * `WP_REDIS_RETRY_INTERVAL` (default: _not set_)
79
+
80
+ Amount of time in miliseconds to retry a failed connection attempt.
81
+
82
 
83
  == Configuration Parameters ==
84
 
104
 
105
  Set the cache groups that should not be cached in Redis.
106
 
107
+ * `WP_REDIS_UNFLUSHABLE_GROUPS` (default: _not set_)
108
+
109
+ Set groups not being flushed during a selective cache flush.
110
+
111
  * `WP_REDIS_DISABLED` (default: _not set_)
112
 
113
  Set to `true` to disable the object cache at runtime.
116
 
117
  Set to `false` to disable graceful failures and throw exceptions.
118
 
119
+ * `WP_REDIS_SERIALIZER` (default: _not set_)
120
+
121
+ Use PhpRedis’ built-in serializers. Supported values are `Redis::SERIALIZER_PHP` and `Redis::SERIALIZER_IGBINARY`.
122
+
123
  * `WP_REDIS_IGBINARY` (default: _not set_)
124
 
125
+ Set to `true` to enable the [igbinary](https://github.com/igbinary/igbinary) serializer. Ignored when `WP_REDIS_SERIALIZER` is set.
126
 
127
 
128
  == Replication & Clustering ==
200
 
201
  == Changelog ==
202
 
203
+ = 1.5.0 =
204
+
205
+ Since Predis isn't maintained any longer, it's highly recommended to switch over to PhpRedis (the Redis PECL extention).
206
+
207
+ * Improved Redis key name builder
208
+ * Added support for PhpRedis serializers
209
+ * Added `redis_object_cache_error` action
210
+ * Added timeout, read-timeout and retry configuration
211
+ * Added unflushable groups (defaults to `['userlogins']`)
212
+ * Fixed passwords not showing in server list
213
+
214
  = 1.4.3 =
215
 
216
  * Require PHP 5.4 or newer
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, HHVM, replication, clustering and WP-CLI.
6
- Version: 1.4.3
7
  Text Domain: redis-cache
8
  Domain Path: /languages
9
  Author: Till Krüss
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, HHVM, replication, clustering and WP-CLI.
6
+ Version: 1.5.0
7
  Text Domain: redis-cache
8
  Domain Path: /languages
9
  Author: Till Krüss