1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace BenTools\Currency\Cache; |
4
|
|
|
|
5
|
|
|
use Psr\SimpleCache\CacheInterface; |
6
|
|
|
use Traversable; |
7
|
|
|
|
8
|
|
|
class ArrayCache implements CacheInterface |
9
|
|
|
{ |
10
|
|
|
|
11
|
|
|
private $defaultTtl; |
12
|
|
|
private $storage = []; |
13
|
|
|
private $expiries = []; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* ArrayCache constructor. |
17
|
|
|
* @param int|null $defaultTtl |
18
|
|
|
*/ |
19
|
|
|
public function __construct(int $defaultTtl = null) |
20
|
|
|
{ |
21
|
|
|
$this->defaultTtl = $defaultTtl; |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @inheritDoc |
26
|
|
|
*/ |
27
|
|
|
public function get($key, $default = null) |
28
|
|
|
{ |
29
|
|
|
if ($this->has($key)) { |
30
|
|
|
return $this->storage[$key]; |
31
|
|
|
} |
32
|
|
|
if ($this->isExpired($key)) { |
33
|
|
|
$this->delete($key); |
34
|
|
|
} |
35
|
|
|
return $default; |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @inheritDoc |
40
|
|
|
*/ |
41
|
|
|
public function set($key, $value, $ttl = null) |
42
|
|
|
{ |
43
|
|
|
$this->storage[$key] = $value; |
44
|
|
|
$this->expiries[$key] = $this->computeExpiryTime($ttl); |
|
|
|
|
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @inheritDoc |
49
|
|
|
*/ |
50
|
|
|
public function delete($key) |
51
|
|
|
{ |
52
|
|
|
unset($this->storage[$key], $this->expiries[$key]); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @inheritDoc |
57
|
|
|
*/ |
58
|
|
|
public function clear() |
59
|
|
|
{ |
60
|
|
|
$this->storage = []; |
61
|
|
|
$this->expiries = []; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @inheritDoc |
66
|
|
|
*/ |
67
|
|
|
public function getMultiple($keys, $default = null) |
68
|
|
|
{ |
69
|
|
|
foreach ($keys as $key) { |
70
|
|
|
yield $key => $this->get($key, $default); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @inheritDoc |
76
|
|
|
*/ |
77
|
|
|
public function setMultiple($values, $ttl = null) |
78
|
|
|
{ |
79
|
|
|
if (!$this->isIterable($values)) { |
80
|
|
|
throw new \InvalidArgumentException("Values must be array or Traversable"); |
81
|
|
|
} |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @inheritDoc |
86
|
|
|
*/ |
87
|
|
|
public function deleteMultiple($keys) |
88
|
|
|
{ |
89
|
|
|
foreach ($keys as $key) { |
90
|
|
|
$this->delete($key); |
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @inheritDoc |
96
|
|
|
*/ |
97
|
|
|
public function has($key) |
98
|
|
|
{ |
99
|
|
|
return isset($this->storage[$key]) && !$this->isExpired($key); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* @param $values |
104
|
|
|
* @return bool |
105
|
|
|
*/ |
106
|
|
|
private function isIterable($values): bool |
107
|
|
|
{ |
108
|
|
|
return is_array($values) || $values instanceof Traversable; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* @param int|null $ttl |
113
|
|
|
* @return int|null |
114
|
|
|
*/ |
115
|
|
|
private function computeExpiryTime(int $ttl = null): ?int |
116
|
|
|
{ |
117
|
|
|
$ttl = $ttl ?? $this->defaultTtl; |
118
|
|
|
if (null === $ttl) { |
119
|
|
|
return null; |
120
|
|
|
} |
121
|
|
|
return time() + $ttl; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* @param $key |
126
|
|
|
* @return bool |
127
|
|
|
*/ |
128
|
|
|
private function isExpired($key): bool |
129
|
|
|
{ |
130
|
|
|
if (isset($this->expiries[$key]) && null !== $this->expiries[$key]) { |
131
|
|
|
return time() <= $this->expiries[$key]; |
132
|
|
|
} |
133
|
|
|
return false; |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.