Passed
Push — master ( 5b8b5c...553fa0 )
by Stephen
02:00 queued 11s
created

RedisCache::setIfMissing()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 3
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
4
namespace Sfneal\Helpers\Redis;
5
6
7
use Closure;
8
use Illuminate\Support\Facades\Cache;
9
use Illuminate\Support\Facades\Redis;
10
use Sfneal\Actions\AbstractService;
11
12
class RedisCache extends AbstractService
13
{
14
    /**
15
     * Retrieve a formatted RedisKey with the environment prefix included.
16
     *
17
     * @param string $key
18
     * @return string
19
     */
20
    public static function key(string $key): string
21
    {
22
        return env('REDIS_KEY_PREFIX', 'app').":$key";
23
    }
24
25
    /**
26
     * Retrieve an array of keys that begin with a prefix.
27
     *
28
     * @param string $prefix
29
     * @return mixed list of keys without prefix
30
     */
31
    public static function keys(string $prefix): string
32
    {
33
        return array_map(
34
        // Remove prefix from each key so it is not concatenated twice
35
            function ($key) {
36
                return substr($key, strlen(env('REDIS_KEY_PREFIX')) + 1);
37
            },
38
39
            // List of Redis key's matching pattern
40
            Redis::connection('default')->client()->keys(self::key($prefix.'*'))
41
        );
42
    }
43
44
    /**
45
     * Get items from the cache.
46
     *
47
     * @param string $key
48
     * @return mixed
49
     */
50
    public static function get(string $key)
51
    {
52
        return Cache::get(self::key($key));
53
    }
54
55
    /**
56
     * Put items in the cache with a TTL.
57
     *
58
     * Use's environment's REDIS_KEY_EXPIRATION value if $expiration is null.
59
     *
60
     * @param string $key
61
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
62
     * @param null $expiration
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $expiration is correct as it would always require null to be passed?
Loading history...
63
     * @return string
64
     */
65
    public static function set(string $key, $value = null, $expiration = null)
66
    {
67
        // Store the $value in the Cache
68
        Cache::put(
69
            $key,
70
            $value,
71
            (isset($expiration) ? $expiration : env('REDIS_KEY_EXPIRATION', 3600))
72
        );
73
74
        // Return the $value
75
        return $value;
76
    }
77
78
    /**
79
     * Add a TTL attribute (time to live or time til expiration) to a Redis key.
80
     *
81
     * @param string $key
82
     * @param null $expiration
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $expiration is correct as it would always require null to be passed?
Loading history...
83
     * @return string|null
84
     */
85
    public static function expire(string $key, $expiration = null)
86
    {
87
        // Use environment REDIS_KEY_EXPIRATION value if not set
88
        if (!$expiration) {
0 ignored issues
show
introduced by
$expiration is of type null, thus it always evaluated to false.
Loading history...
89
            $expiration = env('REDIS_KEY_EXPIRATION', 3600);
90
        }
91
92
        // Create a key value pair with a null value and a TTL if the key is missing
93
        if (self::missing($key)) {
94
            return self::set($key, null, $expiration);
95
        }
96
97
        // Create a key value pair with original value and a TTL if the key exists
98
        else {
99
            return self::set($key, self::get($key), $expiration);
100
        }
101
    }
102
103
    /**
104
     * Delete Redis key's from the Cache.
105
     *
106
     * @param $key array|string
107
     * @return mixed
108
     */
109
    public static function delete($key)
110
    {
111
        // Empty array of keys to delete
112
        $keys = [];
113
114
        // Check if an array of keys has been passed
115
        if (gettype($key) == 'array') {
116
            // Recursively merge arrays of keys found matching pattern
117
            foreach (array_values($key) as $value) {
118
                $keys = array_merge($keys, self::keys($value));
0 ignored issues
show
Bug introduced by
self::keys($value) of type string is incompatible with the type array|null expected by parameter $array2 of array_merge(). ( Ignorable by Annotation )

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

118
                $keys = array_merge($keys, /** @scrutinizer ignore-type */ self::keys($value));
Loading history...
119
            }
120
        } else {
121
            // All keys matching pattern
122
            $keys = array_merge($keys, self::keys($key));
123
        }
124
125
        // Remove all keys that match param patterns
126
        $to_remove = array_values($keys);
127
        foreach ($to_remove as $value) {
128
            Cache::forget($value);
129
        }
130
131
        // Return array of deleted keys
132
        return array_values($to_remove);
133
    }
134
135
    /**
136
     * Determine if a redis key exists in the cache.
137
     *
138
     * @param string $key
139
     * @return bool
140
     */
141
    public static function exists(string $key): bool
142
    {
143
        return Cache::has(self::key($key));
144
    }
145
146
    /**
147
     * Determine if a redis key is missing from the cache.
148
     *
149
     * @param string $key
150
     * @return bool
151
     */
152
    public static function missing(string $key): bool
153
    {
154
        return Cache::missing(self::key($key));
155
    }
156
157
    /**
158
     * Create a Redis Key with a null value if it is missing.
159
     *
160
     * @param string $key
161
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
162
     * @param null $expiration
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $expiration is correct as it would always require null to be passed?
Loading history...
163
     * @return bool
164
     */
165
    public static function setIfMissing(string $key, $value = null, $expiration = null): bool
166
    {
167
        // Create the redis Key with an expiration
168
        if (self::missing($key)) {
169
            self::set($key, $value, $expiration);
170
171
            return true;
172
        }
173
174
        // Not created
175
        return false;
176
    }
177
178
    /**
179
     * Increment a Redis Key's value & return the new value.
180
     *
181
     * @param string $key
182
     * @param int $value
183
     * @param int|null $expiration
184
     * @return mixed
185
     */
186
    public static function increment(string $key, int $value = 1, int $expiration = null)
187
    {
188
        // Create the Key if it's missing
189
        self::setIfMissing($key, 0, $expiration);
0 ignored issues
show
Bug introduced by
It seems like $expiration can also be of type integer; however, parameter $expiration of Sfneal\Helpers\Redis\RedisCache::setIfMissing() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

189
        self::setIfMissing($key, 0, /** @scrutinizer ignore-type */ $expiration);
Loading history...
190
191
        // Increment the value
192
        Cache::increment(self::key($key), $value);
193
194
        // Return the new value
195
        // todo: check if this is neeeded
196
        return self::get($key);
197
    }
198
199
    /**
200
     * Flush the entire redis cache.
201
     *
202
     * @return mixed
203
     */
204
    public static function flush()
205
    {
206
        return Redis::connection('default')->client()->flushAll();
207
    }
208
209
    /**
210
     * Flush the redis cache of all keys with environment's prefix.
211
     *
212
     * @return mixed
213
     */
214
    public static function clear()
215
    {
216
        return self::delete('');
217
    }
218
219
    /**
220
     * Pass a $callback function to be stored in the Cache for an amount of time
221
     *
222
     * @param string $key
223
     * @param int $ttl
224
     * @param Closure $callback
225
     * @return mixed
226
     */
227
    public static function remember(string $key, int $ttl, Closure $callback)
228
    {
229
        return Cache::remember($key, $ttl, $callback);
230
    }
231
232
    /**
233
     * Pass a $callback function to be stored in the Cache forever
234
     *
235
     * @param string $key
236
     * @param Closure $callback
237
     * @return mixed
238
     */
239
    public static function rememberForever(string $key, Closure $callback)
240
    {
241
        return Cache::rememberForever($key, $callback);
242
    }
243
}
244