Skip to content

Commit 7e34f1b

Browse files
committed
Add PSR-6 adapter
1 parent 968ba63 commit 7e34f1b

4 files changed

Lines changed: 721 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Psr\Cache;
13+
14+
use InvalidArgumentException;
15+
use Psr\Cache\InvalidArgumentException as CacheException;
16+
use Psr\SimpleCache\InvalidArgumentException as SimpleCacheException;
17+
18+
final class CacheArgumentException extends InvalidArgumentException implements CacheException, SimpleCacheException
19+
{
20+
}

system/Psr/Cache/Item.php

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Psr\Cache;
13+
14+
use CodeIgniter\I18n\Time;
15+
use DateInterval;
16+
use DateTime;
17+
use DateTimeInterface;
18+
use Psr\Cache\CacheItemInterface;
19+
20+
final class Item implements CacheItemInterface
21+
{
22+
/**
23+
* Reserved characters that cannot be used in a key or tag.
24+
*
25+
* @see https://github.com/symfony/cache-contracts/blob/c0446463729b89dd4fa62e9aeecc80287323615d/ItemInterface.php#L43
26+
*/
27+
public const RESERVED_CHARACTERS = '{}()/\@:';
28+
29+
/**
30+
* @var string
31+
*/
32+
protected $key;
33+
34+
/**
35+
* @var mixed
36+
*/
37+
protected $value;
38+
39+
/**
40+
* Whether this Item was the result
41+
* of a cache hit.
42+
*
43+
* @var boolean
44+
*/
45+
protected $hit;
46+
47+
/**
48+
* The expiration time
49+
*
50+
* @var Time|null
51+
*/
52+
protected $expiration;
53+
54+
/**
55+
* Validates a cache key according to PSR-6.
56+
*
57+
* @param string $key The key to validate
58+
*
59+
* @throws CacheArgumentException When $key is not valid
60+
*
61+
* @see https://github.com/symfony/cache/blob/7b024c6726af21fd4984ac8d1eae2b9f3d90de88/CacheItem.php#L158
62+
*/
63+
public static function validateKey($key): string
64+
{
65+
if (! is_string($key))
66+
{
67+
throw new CacheArgumentException('Cache key must be a string');
68+
}
69+
if ($key === '')
70+
{
71+
throw new CacheArgumentException('Cache key cannot be empty.');
72+
}
73+
if (strpbrk($key, self::RESERVED_CHARACTERS) !== false)
74+
{
75+
throw new CacheArgumentException('Cache key contains reserved characters ' . self::RESERVED_CHARACTERS);
76+
}
77+
78+
return $key;
79+
}
80+
81+
/**
82+
* Stores the Item's details.
83+
*
84+
* @param string $key
85+
* @param mixed $value
86+
* @param boolean $hit
87+
*/
88+
public function __construct(string $key, $value, bool $hit)
89+
{
90+
$this->key = $key;
91+
$this->value = $value;
92+
$this->hit = $hit;
93+
}
94+
95+
/**
96+
* Returns the key for the current cache item.
97+
*
98+
* The key is loaded by the Implementing Library, but should be available to
99+
* the higher level callers when needed.
100+
*
101+
* @return string
102+
* The key string for this cache item.
103+
*/
104+
public function getKey(): string
105+
{
106+
return $this->key;
107+
}
108+
109+
/**
110+
* Retrieves the value of the item from the cache associated with this object's key.
111+
*
112+
* The value returned must be identical to the value originally stored by set().
113+
*
114+
* If isHit() returns false, this method MUST return null. Note that null
115+
* is a legitimate cached value, so the isHit() method SHOULD be used to
116+
* differentiate between "null value was found" and "no value was found."
117+
*
118+
* @return mixed
119+
* The value corresponding to this cache item's key, or null if not found.
120+
*/
121+
public function get()
122+
{
123+
return $this->value;
124+
}
125+
126+
/**
127+
* Confirms if the cache item lookup resulted in a cache hit.
128+
*
129+
* Note: This method MUST NOT have a race condition between calling isHit()
130+
* and calling get().
131+
*
132+
* @return boolean
133+
* True if the request resulted in a cache hit. False otherwise.
134+
*/
135+
public function isHit(): bool
136+
{
137+
return $this->hit;
138+
}
139+
140+
/**
141+
* Sets the value represented by this cache item.
142+
*
143+
* The $value argument may be any item that can be serialized by PHP,
144+
* although the method of serialization is left up to the Implementing
145+
* Library.
146+
*
147+
* @param mixed $value
148+
* The serializable value to be stored.
149+
*
150+
* @return static
151+
* The invoked object.
152+
*/
153+
public function set($value): self
154+
{
155+
$this->value = $value;
156+
157+
return $this;
158+
}
159+
160+
/**
161+
* Sets the expiration time for this cache item.
162+
*
163+
* @param \DateTimeInterface|null $expiration
164+
* The point in time after which the item MUST be considered expired.
165+
* If null is passed explicitly, a default value MAY be used. If none is set,
166+
* the value should be stored permanently or for as long as the
167+
* implementation allows.
168+
*
169+
* @return static
170+
* The called object.
171+
*/
172+
public function expiresAt($expiration): self
173+
{
174+
if ($expiration === null)
175+
{
176+
$this->expiration = null;
177+
}
178+
elseif ($expiration instanceof DateTimeInterface)
179+
{
180+
$this->expiration = Time::createFromInstance($expiration);
181+
}
182+
else
183+
{
184+
throw new CacheArgumentException('Expiration date must be a DateTimeInterface or null');
185+
}
186+
187+
return $this;
188+
}
189+
190+
/**
191+
* Sets the expiration time for this cache item.
192+
*
193+
* @param integer|\DateInterval|null $time
194+
* The period of time from the present after which the item MUST be considered
195+
* expired. An integer parameter is understood to be the time in seconds until
196+
* expiration. If null is passed explicitly, a default value MAY be used.
197+
* If none is set, the value should be stored permanently or for as long as the
198+
* implementation allows.
199+
*
200+
* @return static
201+
* The called object.
202+
*/
203+
public function expiresAfter($time): self
204+
{
205+
if ($time === null)
206+
{
207+
$this->expiration = null;
208+
}
209+
elseif ($time instanceof DateInterval)
210+
{
211+
$this->expiration = Time::now()->add($time);
212+
}
213+
elseif (is_int($time))
214+
{
215+
$this->expiration = Time::now()->addSeconds($time);
216+
}
217+
else
218+
{
219+
throw new CacheArgumentException('Expiration date must be an integer, a DateInterval or null');
220+
}
221+
222+
return $this;
223+
}
224+
225+
/**
226+
* Returns the expiration Time.
227+
* This method is not a requirement of PSR-6 but is necessary
228+
* to pass "testExpiration".
229+
*
230+
* @see https://groups.google.com/g/php-fig/c/Qr4OxCf7J5Y
231+
*
232+
* @return Time|null
233+
*/
234+
public function getExpiration(): ?Time
235+
{
236+
return $this->expiration;
237+
}
238+
239+
/**
240+
* Returns whether or not this Item is expired.
241+
* This method is not a requirement of PSR-6 but is necessary
242+
* to pass "testSavedExpired".
243+
*
244+
* @see https://groups.google.com/g/php-fig/c/Qr4OxCf7J5Y
245+
*
246+
* @return boolean True if this Item is expired.
247+
*/
248+
public function isExpired(): bool
249+
{
250+
if (isset($this->expiration))
251+
{
252+
return $this->expiration->isBefore(Time::now());
253+
}
254+
255+
return false;
256+
}
257+
258+
/**
259+
* Sets the hit value.
260+
* This method is not a requirement of PSR-6 but is necessary
261+
* to allow deferred items to count as hits.
262+
*
263+
* @return $this
264+
*/
265+
public function setHit(bool $hit): self
266+
{
267+
$this->hit = $hit;
268+
269+
return $this;
270+
}
271+
}

0 commit comments

Comments
 (0)