RedisCache::get()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Sfneal\Helpers\Redis;
4
5
use Closure;
6
use ErrorException;
7
use Illuminate\Support\Facades\Cache;
8
use Illuminate\Support\Facades\Redis;
9
10
class RedisCache
11
{
12
    /**
13
     * Retrieve the Redis Key TTL from the config.
14
     *
15
     * @return int
16
     */
17
    private static function defaultTTL(): int
18
    {
19
        return config('redis-helpers.ttl', 3600);
20
    }
21
22
    /**
23
     * Retrieve a redis key with the application prefix prepended.
24
     *
25
     *  - used when interacting directly with a Redis client instead of the `Cache` facade
26
     *
27
     * @param  string  $key
28
     * @return string
29
     */
30
    private static function keyWithPrefix(string $key): string
31
    {
32
        if (! is_null(config('cache.prefix'))) {
33
            return config('cache.prefix').":{$key}";
34
        }
35
36
        return $key;
37
    }
38
39
    /**
40
     * Retrieve a key's time to live in seconds.
41
     *
42
     * @param  string  $key
43
     * @return int
44
     */
45
    public static function ttl(string $key): int
46
    {
47
        return Redis::connection()->command('TTL', [self::keyWithPrefix($key)]);
48
    }
49
50
    /**
51
     * Retrieve an array of keys that begin with a prefix.
52
     *
53
     * @param  string  $prefix
54
     * @param  bool  $wildcard
55
     * @return array|false[]|string[] list of keys without prefix
56
     */
57
    public static function keys(string $prefix = '', bool $wildcard = true): array
58
    {
59
        try {
60
            return array_map(
61
                // Remove prefix from each key so that it's not concatenated twice
62
                function ($key) {
63
                    return substr($key, strlen(config('cache.prefix')) + 1);
64
                },
65
66
                // List of Redis key's matching pattern
67
                Redis::connection()
68
                    ->client()
69
                    ->keys(self::keyWithPrefix($prefix.($wildcard ? '*' : '')))
70
            );
71
        } catch (ErrorException $e) {
72
            return [$prefix];
73
        }
74
    }
75
76
    /**
77
     * Get items from the cache.
78
     *
79
     * @param  string  $key
80
     * @return mixed
81
     */
82
    public static function get(string $key)
83
    {
84
        return Cache::get($key);
85
    }
86
87
    /**
88
     * Put items in the cache with a TTL.
89
     *
90
     * Use's environment's REDIS_KEY_EXPIRATION value if $expiration is null.
91
     *
92
     * @param  string  $key
93
     * @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...
94
     * @param  int|null  $expiration
95
     * @return bool
96
     */
97
    public static function set(string $key, $value = null, int $expiration = null): bool
98
    {
99
        // Store the $value in the Cache
100
        return Cache::put(
101
            $key,
102
            $value,
103
            $expiration ?? self::defaultTTL()
104
        );
105
    }
106
107
    /**
108
     * Put an array of key value pairs into the cache with a TTL.
109
     *
110
     * @param  array  $array
111
     * @param  int|null  $expiration
112
     * @return array
113
     */
114
    public static function setMany(array $array, int $expiration = null): array
115
    {
116
        // todo: optimize by using collections
117
        foreach ($array as $key => $value) {
118
            self::set($key, $value, $expiration);
119
        }
120
121
        return array_values($array);
122
    }
123
124
    /**
125
     * Add a TTL attribute (time to live or time til expiration) to a Redis key.
126
     *
127
     * @param  string  $key
128
     * @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...
129
     * @return bool
130
     */
131
    public static function expire(string $key, $expiration = null): bool
132
    {
133
        // Use environment REDIS_KEY_EXPIRATION value if not set
134
        if (! $expiration) {
0 ignored issues
show
introduced by
$expiration is of type null, thus it always evaluated to false.
Loading history...
135
            $expiration = self::defaultTTL();
136
        }
137
138
        // Create a key value pair with a null value and a TTL if the key is missing
139
        if (self::missing($key)) {
140
            return self::set($key, null, $expiration);
141
        }
142
143
        // Create a key value pair with original value and a TTL if the key exists
144
        else {
145
            return self::set($key, self::get($key), $expiration);
146
        }
147
    }
148
149
    /**
150
     * Delete Redis key's from the Cache.
151
     *
152
     * @param  $keys  array|string
153
     * @param  bool  $children
154
     * @return array
155
     */
156
    public static function delete($keys, bool $children = true): array
157
    {
158
        // Returns an array of deleted keys with success values
159
        return collect((array) $keys)
0 ignored issues
show
Bug introduced by
(array)$keys of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

159
        return collect(/** @scrutinizer ignore-type */ (array) $keys)
Loading history...
160
            ->flatMap(function (string $key) use ($children) {
161
                return self::keys($key, $children);
162
            })
163
            ->mapWithKeys(function (string $key) {
164
                return [$key => Cache::forget($key)];
165
            })
166
            ->toArray();
167
    }
168
169
    /**
170
     * Determine if a redis key exists in the cache.
171
     *
172
     * @param  string  $key
173
     * @return bool
174
     */
175
    public static function exists(string $key): bool
176
    {
177
        return Cache::has($key);
178
    }
179
180
    /**
181
     * Determine if a redis key is missing from the cache.
182
     *
183
     * @param  string  $key
184
     * @return bool
185
     */
186
    public static function missing(string $key): bool
187
    {
188
        return Cache::missing($key);
189
    }
190
191
    /**
192
     * Create a Redis Key with a null value if it is missing.
193
     *
194
     * @param  string  $key
195
     * @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...
196
     * @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...
197
     * @return bool
198
     */
199
    public static function setIfMissing(string $key, $value = null, $expiration = null): bool
200
    {
201
        // Create the redis Key with an expiration
202
        if (self::missing($key)) {
203
            self::set($key, $value, $expiration);
204
205
            return true;
206
        }
207
208
        // Not created
209
        return false;
210
    }
211
212
    /**
213
     * Increment a Redis Key's value & return the new value.
214
     *
215
     * @param  string  $key
216
     * @param  int  $value
217
     * @param  int|null  $expiration
218
     * @return int
219
     */
220
    public static function increment(string $key, int $value = 1, int $expiration = null): int
221
    {
222
        // Create the Key if it's missing
223
        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

223
        self::setIfMissing($key, 0, /** @scrutinizer ignore-type */ $expiration);
Loading history...
224
225
        // Increment the value & return the new value
226
        return Cache::increment($key, $value);
227
    }
228
229
    /**
230
     * Flush the redis cache of all keys with environment's prefix.
231
     *
232
     * @return array
233
     */
234
    public static function clear(): array
235
    {
236
        return self::delete('');
237
    }
238
239
    /**
240
     * Pass a $callback function to be stored in the Cache for an amount of time.
241
     *
242
     * @param  string  $key
243
     * @param  Closure  $callback
244
     * @param  int|null  $ttl
245
     * @return mixed
246
     */
247
    public static function remember(string $key, Closure $callback, int $ttl = null)
248
    {
249
        return Cache::remember($key, $ttl ?? self::defaultTTL(), $callback);
250
    }
251
}
252