diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 91330e6681..e97e9e3aad 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -56,7 +56,7 @@ * @var string * */ - const CI_VERSION = '3.4.6'; + const CI_VERSION = '3.4.7'; /* * ------------------------------------------------------ diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php index d691c253b3..d84437b591 100644 --- a/system/libraries/Cache/drivers/Cache_redis.php +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -162,18 +162,12 @@ public function __construct() public function get($key) { $data = $this->_redis->hMGet($key, array('__ci_type', '__ci_value')); - // Also serves scalars that 3.1.x cached as plain strings + if ($data === FALSE) { return $this->_get_v31($key); } - // Key doesn't exist (hMGet returns an array of FALSE values) - if ( ! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === FALSE) - { - return FALSE; - } - switch ($data['__ci_type']) { case 'array': @@ -295,15 +289,14 @@ public function decrement($id, $offset = 1) */ protected function _increment($id, $offset) { - // Also serves scalars that 3.1.x cached as plain strings, incrBy creates the key if not existing - if ($this->_redis->type($id) === Redis::REDIS_STRING) + $value = $this->_redis->incrBy($id, $offset); + + if ($value === FALSE) { - return $this->_redis->incrBy($id, $offset); + $value = $this->_redis->hIncrBy($id, '__ci_value', $offset); + $value === FALSE OR $this->_redis->hSet($id, '__ci_type', 'integer'); } - $value = $this->_redis->hIncrBy($id, '__ci_value', $offset); - $value === FALSE OR $this->_redis->hSet($id, '__ci_type', 'integer'); - return $value; } @@ -391,16 +384,16 @@ public function __destruct() // ------------------------------------------------------------------------ /** - * Get scalars that 3.1.x cached as plain strings + * Get a value stored as a Redis string: a counter from increment() or a value cached by 3.1.x * * @param string $key Cache ID * @return mixed */ - private function _get_v31($key) + protected function _get_v31($key) { $value = $this->_redis->get($key); - if ($value !== FALSE && $this->_redis->sIsMember('_ci_redis_serialized', $key)) + if ($value !== FALSE && ! is_numeric($value) && $this->_redis->sIsMember('_ci_redis_serialized', $key)) { return unserialize($value); } diff --git a/tests/codeigniter/libraries/Cache_redis_test.php b/tests/codeigniter/libraries/Cache_redis_test.php index 814d0e63c7..1ffec1493f 100644 --- a/tests/codeigniter/libraries/Cache_redis_test.php +++ b/tests/codeigniter/libraries/Cache_redis_test.php @@ -64,12 +64,35 @@ public function test_increment_non_numeric_value() $this->assertSame('string', $this->redis->hashes['data']['__ci_type']); } + // -------------------------------------------------------------------- + + public function test_get_value_cached_by_31x() + { + $this->redis->strings['plain'] = 'bar'; + $this->redis->strings['list'] = serialize(array('a' => 1)); + $this->redis->serialized[] = 'list'; + + $this->assertSame('bar', $this->cache->get('plain')); + $this->assertSame(array('a' => 1), $this->cache->get('list')); + } + + // -------------------------------------------------------------------- + + public function test_get_counter_named_in_stale_serialized_set() + { + $this->redis->serialized[] = 'hits'; + + $this->assertSame(5, $this->cache->increment('hits', 5)); + $this->assertEquals(5, $this->cache->get('hits')); + } + } class Cache_redis_server_stub { public $strings = array(); public $hashes = array(); + public $serialized = array(); public function incrBy($key, $offset) { @@ -134,7 +157,7 @@ public function get($key) public function sIsMember($key, $member) { - return FALSE; + return $key === '_ci_redis_serialized' && in_array($member, $this->serialized, TRUE); } public function close()