<?php
namespace Cake\Cache\Engine;
use Cake\Cache\CacheEngine;
use Redis;
use RedisException;
class RedisEngine extends CacheEngine
{
protected $_Redis;
protected $_defaultConfig = [
'database' => 0,
'duration' => 3600,
'groups' => [],
'password' => false,
'persistent' => true,
'port' => 6379,
'prefix' => 'cake_',
'probability' => 100,
'host' => null,
'server' => '127.0.0.1',
'timeout' => 0,
'unix_socket' => false,
];
public function init(array $config = [])
{
if (!extension_loaded('redis')) {
return false;
}
if (!empty($config['host'])) {
$config['server'] = $config['host'];
}
parent::init($config);
return $this->_connect();
}
protected function _connect()
{
try {
$this->_Redis = new Redis();
if (!empty($this->_config['unix_socket'])) {
$return = $this->_Redis->connect($this->_config['unix_socket']);
} elseif (empty($this->_config['persistent'])) {
$return = $this->_Redis->connect($this->_config['server'], $this->_config['port'], $this->_config['timeout']);
} else {
$persistentId = $this->_config['port'] . $this->_config['timeout'] . $this->_config['database'];
$return = $this->_Redis->pconnect($this->_config['server'], $this->_config['port'], $this->_config['timeout'], $persistentId);
}
} catch (RedisException $e) {
return false;
}
if ($return && $this->_config['password']) {
$return = $this->_Redis->auth($this->_config['password']);
}
if ($return) {
$return = $this->_Redis->select($this->_config['database']);
}
return $return;
}
public function write($key, $value)
{
$key = $this->_key($key);
if (!is_int($value)) {
$value = serialize($value);
}
$duration = $this->_config['duration'];
if ($duration === 0) {
return $this->_Redis->set($key, $value);
}
return $this->_Redis->setEx($key, $duration, $value);
}
public function read($key)
{
$key = $this->_key($key);
$value = $this->_Redis->get($key);
if (preg_match('/^[-]?\d+$/', $value)) {
return (int)$value;
}
if ($value !== false && is_string($value)) {
return unserialize($value);
}
return $value;
}
public function increment($key, $offset = 1)
{
$duration = $this->_config['duration'];
$key = $this->_key($key);
$value = (int)$this->_Redis->incrBy($key, $offset);
if ($duration > 0) {
$this->_Redis->setTimeout($key, $duration);
}
return $value;
}
public function decrement($key, $offset = 1)
{
$duration = $this->_config['duration'];
$key = $this->_key($key);
$value = (int)$this->_Redis->decrBy($key, $offset);
if ($duration > 0) {
$this->_Redis->setTimeout($key, $duration);
}
return $value;
}
public function delete($key)
{
$key = $this->_key($key);
return $this->_Redis->delete($key) > 0;
}
public function clear($check)
{
if ($check) {
return true;
}
$keys = $this->_Redis->getKeys($this->_config['prefix'] . '*');
$result = [];
foreach ($keys as $key) {
$result[] = $this->_Redis->delete($key) > 0;
}
return !in_array(false, $result);
}
public function add($key, $value)
{
$duration = $this->_config['duration'];
$key = $this->_key($key);
if (!is_int($value)) {
$value = serialize($value);
}
if ($this->_Redis->setNx($key, $value)) {
return $this->_Redis->setTimeout($key, $duration);
}
return false;
}
public function groups()
{
$result = [];
foreach ($this->_config['groups'] as $group) {
$value = $this->_Redis->get($this->_config['prefix'] . $group);
if (!$value) {
$value = 1;
$this->_Redis->set($this->_config['prefix'] . $group, $value);
}
$result[] = $group . $value;
}
return $result;
}
public function clearGroup($group)
{
return (bool)$this->_Redis->incr($this->_config['prefix'] . $group);
}
public function __destruct()
{
if (empty($this->_config['persistent']) && $this->_Redis instanceof Redis) {
$this->_Redis->close();
}
}
}