<?php
/*
 * puyuetianPHP轻框架 核心函数
 * 作者：蒲乐天（puyuetian）
 * QQ：632827168
 * 官网：http://www.puyuetian.com
 *
 * 作者允许您转载和使用，但必须注明来自puyuetianPHP轻框架。
 */
/********************************************
Redis操作类 - 获取、修改、添加、删除
 *******************************************/
class KRedis
{
    protected $config, $redis, $error;

    public function __construct($config = [])
    {
        $keys = 'host,pass,port,timeout,expire,prefix,tables,dbno';
        $keys = explode(',', $keys);
        foreach ($keys as $key) {
            if (!isset($config[$key])) {
                $config[$key] = g('redis.' . $key);
            }
        }
        $this->config = $config;
    }

    public function error()
    {
        return $this->error;
    }

    public function close()
    {
        return $this->redis->close();
    }

    public function redis()
    {
        return $this->redis;
    }

    public function connect()
    {
        // 尝试连接
        if (!extension_loaded('redis')) {
            $this->error = '服务器PHP未开启Redis扩展组件';
            return false;
        }
        // 创建Redis连接
        $redis = new Redis();
        // 尝试连接Redis服务器
        try {
            if (!$redis->connect($this->config['host'], $this->config['port'], $this->config['timeout'])) {
                $this->error = '无法连接到Redis服务器';
                return false;
            }
        } catch (Throwable $e) {
            $this->error = $e->getMessage();
            return false;
        }

        // 认证密码
        if ($this->config['pass'] && !$redis->auth($this->config['pass'])) {
            $this->error = '连接密码错误';
            return false;
        }

        // 选择数据库
        if (!$redis->select($this->config['dbno'])) {
            $this->error = '不存在的Redis数据库编号';
            return false;
        }

        $this->redis = $redis;

        return $this;
    }

    public function select($dbno = 0)
    {
        return $this->redis->select($dbno);
    }

    /**
     * 获取redis的缓存数据
     * @param mixed $key 可以只获取一个键值，也可以通过数组方式传入多个键值，也可以使用,分割符一次性获取多个
     * @return mixed
     */
    public function get($key)
    {
        $keys = $key;
        if (!is_array($keys)) {
            $keys = explode(',', $keys);
        }
        $rs = [];
        foreach ($keys as $k) {
            $rs[$k] = $this->redis->get($this->config['prefix'] . $k);
        }
        // 读取前序列化
        foreach ($rs as $k => $v) {
            $rs[$k] = json_decode($v, true);
        }
        if (count($keys) == 1 && !is_array($key)) {
            $rs = current($rs);
            if (null === $rs) {
                return false;
            }
        }
        return $rs;
    }

    /**
     * 设置redis的缓存数据
     * @param mixed $key 可以只设置一个键值，也可以通过数组方式传入多个键值同时设置
     * @param mixed $value 被设置的键的值
     * @param int $expire 该数据过期时间
     * @return boolean
     */
    public function set($key, $value = null, $expire = null)
    {
        if (!is_array($key)) {
            return $this->set([$key => $value], $expire);
        }
        $keys = $key;

        // 第二个参数变为了expire
        $expire = $value;
        if (null === $expire) {
            $expire = $this->config['expire'];
        }
        if (!is_numeric($expire)) {
            $expire = 0;
        }

        // 添加前缀
        if ($this->config['prefix']) {
            $nks = [];
            foreach ($keys as $k => $v) {
                $nks[$this->config['prefix'] . $k] = $v;
            }
            $keys = $nks;
        }

        // 保存前序列化
        foreach ($keys as $k => $v) {
            $keys[$k] = json_encode($v);
        }
        // 设置数据
        try {
            $this->redis->mset($keys);
        } catch (Throwable $e) {
            $this->error = $e->getMessage();
            return false;
        }
        // 设置过期时间
        if ($expire) {
            foreach ($keys as $k => $v) {
                $this->redis->expire($k, $expire);
            }
        }
        return true;
    }

    /**
     * 删除redis的缓存数据
     * @param mixed $key 可以只删除一个键值，也可以通过数组方式传入多个键值，也可以使用,分割符一次性删除多个
     * @return mixed
     */
    public function del($key = null)
    {
        if (null === $key) {
            if ($this->config['prefix']) {
                $allkeys = $this->redis->keys('*');
                foreach ($allkeys as $k) {
                    if (strpos($k, $this->config['prefix']) === 0) {
                        $this->redis->delete($k);
                    }
                }
                return true;
            } else {
                return $this->flushAll();
            }
        }
        $keys = $key;
        if (!is_array($keys)) {
            $keys = explode(',', $keys);
        }
        foreach ($keys as $k) {
            $this->redis->delete($this->config['prefix'] . $k);
        }
        return true;
    }

    /**
     * 清空redis的所有缓存数据
     */
    public function flushAll()
    {
        $this->redis->flushAll();
        return true;
    }
}
