Test Failed
Push — master ( e503e7...ca58d9 )
by Sebastian
13:27
created

MemcachedCache::handleTtl()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 12
ccs 2
cts 2
cp 1
rs 10
cc 4
nc 4
nop 1
crap 4
1
<?php
2
3
/**
4
 * Linna Framework.
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2018, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types=1);
11
12
namespace Linna\Cache;
13
14
use DateInterval;
15
use Memcached;
16
use InvalidArgumentException;
17
use Psr\SimpleCache\CacheInterface;
18
19
/**
20
 * PSR-16 Memcached.
21
 */
22
class MemcachedCache implements CacheInterface
23
{
24
    use ActionMultipleTrait;
25
26
    /**
27
     * @var Memcached Memcached instance
28
     */
29
    private Memcached $memcached;
30
31
    /**
32
     * Constructor.
33
     *
34
     * @param array<mixed> $options
35
     *
36
     * @throws InvalidArgumentException if options not contain memcached resource
37 6
     */
38
    public function __construct(array $options)
39 6
    {
40 5
        if (!($options['resource'] instanceof Memcached)) {
41
            throw new InvalidArgumentException('MemcachedCache class need instance of Memcached passed as option. [\'resource\' => $memcached].');
42
        }
43 1
44 1
        $this->memcached = $options['resource'];
45
    }
46
47
    /**
48
     * Fetches a value from the cache.
49
     *
50
     * @param string $key     The unique key of this item in the cache.
51
     * @param mixed  $default Default value to return if the key does not exist.
52
     *
53
     * @return mixed The value of the item from the cache, or $default in case of cache miss.
54 7
     *
55
     * @throws \Psr\SimpleCache\InvalidArgumentException
56
     *   MUST be thrown if the $key string is not a legal value.
57 7
     */
58
    public function get(string $key, mixed $default = null): mixed
59
    {
60 7
        //get value from memcached
61 4
        $value = $this->memcached->get($key);
62
63
        //check if value was retrived
64 3
        if ($value === false) {
65
            return $default;
66
        }
67
68
        return $value;
69
    }
70
71
    /**
72
     * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
73
     *
74
     * @param string                 $key   The key of the item to store.
75
     * @param mixed                  $value The value of the item to store, must be serializable.
76
     * @param null|int|\DateInterval $ttl   Optional. The TTL value of this item. If no value is sent and
77
     *                                      the driver supports TTL then the library may set a default value
78 13
     *                                      for it or let the driver take care of that.
79
     *
80 13
     * @return bool True on success and false on failure.
81
     *
82
     * @throws \Psr\SimpleCache\InvalidArgumentException
83
     *   MUST be thrown if the $key string is not a legal value.
84
     */
85
    public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool
86
    {
87
        return $this->memcached->set($key, $value, $this->handleTtl($ttl));
88
    }
89
90 3
    /**
91
     * Handle ttl parameter.
92 3
     * 
93
     * @param null|int|\DateInterval $ttl   Optional. The TTL value of this item. If no value is sent and
94
     *                                      the driver supports TTL then the library may set a default value
95
     *                                      for it or let the driver take care of that.
96
     * 
97
     * @return int Ttl in seconds.
98
     */
99
    private function handleTtl(DateInterval|int|null $ttl): int
100 56
    {
101
        if ($ttl == null){
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $ttl of type DateInterval|integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
102 56
            return 0;
103
        }
104
        if (is_int($ttl)) {
105
            return $ttl;
106
        }
107
        if ($ttl instanceof DateInterval) {
0 ignored issues
show
introduced by
$ttl is always a sub-type of DateInterval.
Loading history...
108
            $now = new \DateTime();
109
            $now->add($ttl);
110
            return (int) $now->format('U');
111
        }
0 ignored issues
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 107 is false. This is incompatible with the type-hinted return integer. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
112
    }
113
    
114
    /**
115
     * Delete an item from the cache by its unique key.
116
     *
117 10
     * @param string $key The unique cache key of the item to delete.
118
     *
119 10
     * @return bool True if the item was successfully removed. False if there was an error.
120
     *
121
     * @throws \Psr\SimpleCache\InvalidArgumentException
122
     *   MUST be thrown if the $key string is not a legal value.
123
     */
124
    public function delete(string $key): bool
125
    {
126
        return $this->memcached->delete($key);
127
    }
128
129
    /**
130
     * Wipes clean the entire cache's keys.
131
     *
132
     * @return bool True on success and false on failure.
133
     */
134
    public function clear(): bool
135
    {
136
        return $this->memcached->flush();
137
    }
138
139
    /**
140
     * Determines whether an item is present in the cache.
141
     *
142
     * NOTE: It is recommended that has() is only to be used for cache warming type purposes
143
     * and not to be used within your live applications operations for get/set, as this method
144
     * is subject to a race condition where your has() will return true and immediately after,
145
     * another script can remove it making the state of your app out of date.
146
     *
147
     * @param string $key The cache item key.
148
     *
149
     * @return bool
150
     *
151
     * @throws \Psr\SimpleCache\InvalidArgumentException
152
     *   MUST be thrown if the $key string is not a legal value.
153
     */
154
    public function has(string $key): bool
155
    {
156
        return ($this->memcached->get($key) !== false) ? true : false;
157
    }
158
}
159