Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
Item
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
8 / 8
17
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 isHit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 set
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 expiresAt
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 expiresAfter
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 save
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
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;
17
18use DateInterval;
19use DateTimeInterface;
20use Psr\Cache\CacheItemInterface;
21
22use Aviat\Banker\Driver\DriverInterface;
23
24/**
25 * Base class for Cache items
26 */
27class Item implements CacheItemInterface {
28
29    /**
30     * The driver for the current cache backend
31     *
32     * @var DriverInterface
33     */
34    protected DriverInterface $driver;
35
36    /**
37     * The key of the cache item
38     *
39     * @var string
40     */
41    protected string $key;
42
43    /**
44     * The expiration time
45     *
46     * @var int | null
47     */
48    protected ?int $expiresAt;
49
50    /**
51     * The time to live
52     *
53     * @var int | null
54     */
55    protected ?int $ttl;
56
57    /**
58     * The value to save in the cache
59     *
60     * @var mixed
61     */
62    protected mixed $value = null;
63
64    /**
65     * Create a Cache Item object
66     *
67     * @param DriverInterface $driver
68     * @param string $key
69     */
70    public function __construct(DriverInterface $driver, string $key)
71    {
72        $this->driver = $driver;
73        $this->key = $key;
74
75        $this->expiresAt = NULL;
76        $this->ttl = NULL;
77    }
78
79    /**
80     * Returns the key for the current cache item.
81     *
82     * The key is loaded by the Implementing Library, but should be available to
83     * the higher level callers when needed.
84     *
85     * @return string
86     *   The key string for this cache item.
87     */
88    public function getKey(): string
89    {
90        return $this->key;
91    }
92
93    /**
94     * Retrieves the value of the item from the cache associated with this object's key.
95     *
96     * The value returned must be identical to the value originally stored by set().
97     *
98     * If isHit() returns false, this method MUST return null. Note that null
99     * is a legitimate cached value, so the isHit() method SHOULD be used to
100     * differentiate between "null value was found" and "no value was found."
101     *
102     * @return mixed
103     *   The value corresponding to this cache item's key, or null if not found.
104     */
105    public function get(): mixed
106    {
107        if ($this->isHit())
108        {
109            return $this->value ?? $this->driver->get($this->key);
110        }
111
112        return NULL;
113    }
114
115    /**
116     * Confirms if the cache item lookup resulted in a cache hit.
117     *
118     * Note: This method MUST NOT have a race condition between calling isHit()
119     * and calling get().
120     *
121     * @return bool
122     *   True if the request resulted in a cache hit. False otherwise.
123     */
124    public function isHit(): bool
125    {
126        return isset($this->value) || $this->driver->exists($this->key);
127    }
128
129    /**
130     * Sets the value represented by this cache item.
131     *
132     * The $value argument may be any item that can be serialized by PHP,
133     * although the method of serialization is left up to the Implementing
134     * Library.
135     *
136     * @param mixed $value
137     *   The serializable value to be stored.
138     *
139     * @return static
140     *   The invoked object.
141     */
142    public function set(mixed $value): static
143    {
144        $this->value = $value;
145        return $this;
146    }
147
148    /**
149     * Sets the expiration time for this cache item.
150     *
151     * @param DateTimeInterface|null $expiration
152     *   The point in time after which the item MUST be considered expired.
153     *   If null is passed explicitly, a default value MAY be used. If none is set,
154     *   the value should be stored permanently or for as long as the
155     *   implementation allows.
156     *
157     * @return static
158     *   The called object.
159     */
160    public function expiresAt(DateTimeInterface $expiration = NULL): static
161    {
162        if ($expiration instanceof DateTimeInterface)
163        {
164            $expiration = $expiration->getTimestamp();
165        }
166
167        $this->expiresAt = (int) $expiration;
168
169        return $this;
170    }
171
172    /**
173     * Sets the expiration time for this cache item.
174     *
175     * @param DateInterval|int|null $time
176     *   The period of time from the present after which the item MUST be considered
177     *   expired. An integer parameter is understood to be the time in seconds until
178     *   expiration. If null is passed explicitly, a default value MAY be used.
179     *   If none is set, the value should be stored permanently or for as long as the
180     *   implementation allows.
181     *
182     * @return static
183     *   The called object.
184     */
185    public function expiresAfter(DateInterval|int $time = NULL): static
186    {
187        if ($time instanceof DateInterval)
188        {
189            $time = $time->format("%s");
190        }
191
192        $this->ttl = (int) $time;
193        return $this;
194    }
195
196    /**
197     * Save the current value to the cache
198     *
199     * @return bool
200     */
201    public function save(): bool
202    {
203        if ($this->expiresAt !== NULL && $this->expiresAt !== 0)
204        {
205            $setResult = $this->driver->set($this->key, $this->value);
206            $expResult = $this->driver->expiresAt($this->key, $this->expiresAt);
207
208            return $setResult && $expResult;
209        }
210
211        if ($this->ttl !== NULL && $this->ttl !== 0)
212        {
213            return (bool) $this->driver->set($this->key, $this->value, $this->ttl);
214        }
215
216        return (bool) $this->driver->set($this->key, $this->value);
217    }
218}