Test Failed
Branch master (c50bb7)
by Terry
15:06 queued 10:08
created

Redis::doSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 1
b 0
f 0
nc 1
nop 4
dl 0
loc 15
ccs 9
cts 9
cp 1
crap 1
rs 9.9666
1
<?php
2
/*
3
 * This file is part of the Shieldon Simple Cache package.
4
 *
5
 * (c) Terry L. <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Shieldon\SimpleCache\Driver;
14
15
use Shieldon\SimpleCache\CacheProvider;
16
use Shieldon\SimpleCache\Exception\CacheException;
17
use Redis as RedisServer;
18
use Exception;
19
use function array_keys;
20
use function extension_loaded;
21
use function unserialize;
22
use function serialize;
23
use function is_bool;
24
25
/**
26
 * A cache driver class provided by Redis database.
27
 */
28
class Redis extends CacheProvider
29
{
30
    /**
31
     * The Redis instance.
32
     *
33
     * @var Redis|null
34
     */
35
    protected $redis = null;
36
37
    /**
38
     * Constructor.
39
     *
40
     * @param array $setting The settings.
41
     * 
42
     * @throws CacheException
43
     */
44 10
    public function __construct(array $setting = [])
45
    {
46
        $config = [
47 10
            'host' => '127.0.0.1',
48
            'port' => 6379,
49
            'user' => null,
50
            'pass' => null,
51
        ];
52
53 10
        foreach (array_keys($config) as $key) {
54 10
            if (isset($setting[$key])) {
55 10
                $config[$key] = $setting[$key];
56
            }
57
        }
58
59 10
        $this->connect($config);
60 10
    }
61
62
    /**
63
     * Connect to Redis server.
64
     *
65
     * @param array $config The settings.
66
     * 
67
     * @return void
68
     * 
69
     * @throws CacheException
70
     */
71 10
    protected function connect(array $config): void
72
    {
73 10
        if (extension_loaded('redis')) {
74
            try {
75 10
                $this->redis = new RedisServer();
0 ignored issues
show
Documentation Bug introduced by
It seems like new Redis() of type Redis is incompatible with the declared type Shieldon\SimpleCache\Driver\Redis|null of property $redis.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
76 10
                $this->redis->connect($config['host'], $config['port']);
77 10
                $this->auth($config);
78
79
            // @codeCoverageIgnoreStart
80
            } catch (Exception $e) {
81
                throw new CacheException($e->getMessage());
82
            }
83
            // @codeCoverageIgnoreEnd
84 10
            return;
85
        }
86
87
        // @codeCoverageIgnoreStart
88
        throw new CacheException(
89
            'PHP Redis extension is not installed on your system.'
90
        );
91
        // @codeCoverageIgnoreEnd
92
    }
93
94
    /**
95
     * Redis authentication.
96
     * @codeCoverageIgnore
97
     *
98
     * @param array $config The user / pass data.
99
     * 
100
     * @return void
101
     */
102
    protected function auth(array $config = []): void
103
    {
104
        if ($this->getVersion() >= 6) {
105
            if (!empty($config['user']) && !empty($config['pass'])) {
106
                $this->redis->auth([
0 ignored issues
show
Bug introduced by
The method auth() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

106
                $this->redis->/** @scrutinizer ignore-call */ 
107
                              auth([

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
107
                    $config['user'],
108
                    $config['pass'],
109
                ]);
110
            }
111
            return;
112
        }
113
114
        if (!empty($config['pass'])) {
115
            $this->redis->auth($config['pass']);
116
        }
117
    }
118
119
    /**
120
     * Get Redis version number.
121
     */
122 10
    protected function getVersion(): int
123
    {
124 10
        $info = $this->redis->info();
0 ignored issues
show
Bug introduced by
The method info() does not exist on Shieldon\SimpleCache\Driver\Redis. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
        /** @scrutinizer ignore-call */ 
125
        $info = $this->redis->info();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
125
126 10
        return (int) $info['redis_version'];
127
    }
128
129
    /**
130
     * Fetch a cache by an extended Cache Driver.
131
     *
132
     * @param string $key The key of a cache.
133
     *
134
     * @return array
135
     */
136 6
    protected function doGet(string $key): array
137
    {
138 6
        $content = $this->redis->get($this->getKeyName($key));
139
140 6
        if (empty($content)) {
141 6
            return [];
142
        }
143 6
        $data = unserialize($content);
144
145 6
        return $data;
146
    }
147
148
    /**
149
     * Set a cache by an extended Cache Driver.
150
     *
151
     * @param string $key       The key of a cache.
152
     * @param mixed  $value     The value of a cache. (serialized)
153
     * @param int    $ttl       The time to live for a cache.
154
     * @param int    $timestamp The time to store a cache.
155
     *
156
     * @return bool
157
     */
158 6
    protected function doSet(string $key, $value, int $ttl, int $timestamp): bool
159
    {
160
        $contents = [
161 6
            'timestamp' => $timestamp,
162 6
            'ttl'       => $ttl,
163 6
            'value'     => $value
164
        ];
165
166 6
        $result = $this->redis->set(
167 6
            $this->getKeyName($key),
168 6
            serialize($contents),
169 6
            $ttl
170
        );
171
172 6
        return $result;
173
    }
174
175
    /**
176
     * Delete a cache by an extended Cache Driver.
177
     *
178
     * @param string $key The key of a cache.
179
     * 
180
     * @return bool
181
     */
182 2
    protected function doDelete(string $key): bool
183
    {
184 2
        return $this->redis->del($this->getKeyName($key)) >= 0;
0 ignored issues
show
Bug introduced by
The method del() does not exist on Shieldon\SimpleCache\Driver\Redis. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

184
        return $this->redis->/** @scrutinizer ignore-call */ del($this->getKeyName($key)) >= 0;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
185
    }
186
187
    /**
188
     * Delete all caches by an extended Cache Driver.
189
     * 
190
     * @return bool
191
     */
192 2
    protected function doClear(): bool
193
    {
194 2
        $keys = $this->redis->keys('simple_cache:*');
0 ignored issues
show
Bug introduced by
The method keys() does not exist on Shieldon\SimpleCache\Driver\Redis. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

194
        /** @scrutinizer ignore-call */ 
195
        $keys = $this->redis->keys('simple_cache:*');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
195
196 2
        if (!empty($keys)) {
197 2
            foreach ($keys as $key) {
198 2
                $this->redis->del($key);
199
            }
200
        }
201
202 2
        return true;
203
    }
204
205
    /**
206
     * Check if the cache exists or not.
207
     *
208
     * @param string $key The key of a cache.
209
     *
210
     * @return bool
211
     */
212 4
    protected function doHas(string $key): bool
213
    {
214 4
        $exist = $this->redis->exists($this->getKeyName($key));
0 ignored issues
show
Bug introduced by
The method exists() does not exist on Shieldon\SimpleCache\Driver\Redis. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

214
        /** @scrutinizer ignore-call */ 
215
        $exist = $this->redis->exists($this->getKeyName($key));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
215
216
        // This function took a single argument and returned TRUE or FALSE in phpredis versions < 4.0.0.
217
218
        // @codeCoverageIgnoreStart
219
        if (is_bool($exist)) {
220
            return $exist;
221
        }
222
223
        return $exist > 0;
224
        // @codeCoverageIgnoreEnd
225
    }
226
227
    /**
228
     * Get the key name of a cache.
229
     *
230
     * @param string $key The key of a cache.
231
     *
232
     * @return string
233
     */
234 6
    private function getKeyName(string $key): string
235
    {
236 6
        return 'simple_cache:' . md5($key);
237
    }
238
}
239
240