Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.30% covered (success)
96.30%
26 / 27
90.00% covered (success)
90.00%
9 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApcuDriver
96.30% covered (success)
96.30%
26 / 27
90.00% covered (success)
90.00%
9 / 10
16
0.00% covered (danger)
0.00%
0 / 1
 __construct
n/a
0 / 0
n/a
0 / 0
2
 exists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMultiple
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 set
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setMultiple
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 delete
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deleteMultiple
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 flush
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 expiresAt
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 getTTLFromExpiration
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
3.14
1<?php declare(strict_types=1);
2/**
3 * Banker
4 *
5 * A Caching library implementing psr/cache (PSR 6) and psr/simple-cache (PSR 16)
6 *
7 * PHP version 8+
8 *
9 * @package     Banker
10 * @author      Timothy J. Warren <tim@timshomepage.net>
11 * @copyright   2016 - 2023  Timothy J. Warren
12 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
13 * @version     4.1.0
14 * @link        https://git.timshomepage.net/timw4mail/banker
15 */
16namespace Aviat\Banker\Driver;
17
18use Aviat\Banker\Exception\CacheException;
19
20use DateInterval;
21use function apcu_clear_cache;
22use function apcu_delete;
23use function apcu_exists;
24use function apcu_fetch;
25use function apcu_store;
26
27/**
28 * Memcached cache backend
29 */
30class ApcuDriver extends AbstractDriver {
31
32    /**
33     * Constructor
34     *
35     * @throws CacheException
36     * @codeCoverageIgnore
37     */
38    public function __construct()
39    {
40        if ( ! extension_loaded('apcu'))
41        {
42            throw new CacheException('This driver requires the APCU extension');
43        }
44    }
45
46    /**
47     * See if a key currently exists in the cache
48     *
49     * @param string $key
50     * @return bool
51     */
52    public function exists(string $key): bool
53    {
54        return apcu_exists($key) !== FALSE;
55    }
56
57    /**
58     * Get the value for the selected cache key
59     *
60     * @param string $key
61     * @return mixed
62     */
63    public function get(string $key): mixed
64    {
65        return apcu_fetch($key);
66    }
67
68    /**
69     * Retrieve a set of values by their cache key
70     *
71     * @param string[] $keys
72     * @return array
73     */
74    public function getMultiple(array $keys = []): array
75    {
76        $this->validateKeys($keys);
77
78        $status = FALSE;
79        return (array)apcu_fetch($keys, $status);
80    }
81
82    /**
83     * Set a cached value
84     *
85     * @param string $key
86     * @param mixed $value
87     * @param int|DateInterval|null $expires
88     * @return bool
89     */
90    public function set(string $key, mixed $value, int|DateInterval|null $expires = NULL): bool
91    {
92        $ttl = $this->getTTLFromExpiration($expires);
93
94        return apcu_store($key, $value, $ttl);
95    }
96
97    /**
98     * Set multiple cache values
99     *
100     * @param array $items
101     * @param DateInterval|int|null $expires
102     * @return bool
103     */
104    public function setMultiple(array $items, DateInterval|int|null $expires = NULL): bool
105    {
106        $this->validateKeys($items, TRUE);
107
108        $errorKeys = ($expires === NULL)
109            ? apcu_store($items)
110            : apcu_store($items, NULL, $this->getTTLFromExpiration($expires));
111
112        return empty($errorKeys);
113    }
114
115    /**
116     * Remove an item from the cache
117     *
118     * @param string $key
119     * @return boolean
120     */
121    public function delete(string $key): bool
122    {
123        return apcu_delete($key);
124    }
125
126    /**
127     * Remove multiple items from the cache
128     *
129     * @param string[] $keys
130     * @return boolean
131     */
132    public function deleteMultiple(array $keys = []): bool
133    {
134        $this->validateKeys($keys);
135
136        $failedToDelete = apcu_delete($keys);
137        return empty($failedToDelete);
138    }
139
140    /**
141     * Empty the cache
142     *
143     * @return boolean
144     */
145    public function flush(): bool
146    {
147        return apcu_clear_cache();
148    }
149
150    /**
151     * Set the specified key to expire at the given time
152     *
153     * @param string $key
154     * @param int $expires
155     * @return boolean
156     */
157    public function expiresAt(string $key, int $expires): bool
158    {
159        if ($this->exists($key))
160        {
161            $value = $this->get($key);
162            $ttl = $this->getTTLFromExpiration($expires);
163            return apcu_store($key, $value, $ttl);
164        }
165
166        $this->getLogger()->log('warning', 'Tried to set expiration on a key that does not exist');
167
168        return FALSE;
169    }
170
171    /**
172     * Convert expiration date argument into TTL argument
173     *
174     * @param DateInterval|int|null $expires
175     * @return int
176     */
177    protected function getTTLFromExpiration(DateInterval|int|null $expires): int
178    {
179        if ($expires instanceof DateInterval)
180        {
181            return $expires->s;
182        }
183
184        $ttl = (int)$expires - time();
185
186        return ($ttl < 0) ? 0 : $ttl;
187    }
188}