LruCache   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 133
ccs 28
cts 28
cp 1
rs 10
wmc 12

7 Methods

Rating   Name   Duplication   Size   Complexity  
A has() 0 3 1
A getWith() 0 7 2
A __construct() 0 7 2
A put() 0 6 2
A putNew() 0 10 2
A putExisting() 0 5 1
A get() 0 7 2
1
<?php declare(strict_types=1);
2
3
namespace Twistor;
4
5
use InvalidArgumentException;
6
use function array_key_exists;
7
use function key;
8
9
/**
10
 * @template TKey as array-key
11
 * @template TValue
12
 */
13
final class LruCache
14
{
15
    /**
16
     * @var array
17
     *
18
     * @psalm-var array<TKey, TValue>
19
     */
20
    private $cache = [];
21
22
    /**
23
     * @var int
24
     */
25
    private $capacity;
26
27
    /**
28
     * @var int
29
     */
30
    private $size = 0;
31
32 21
    public function __construct(int $capacity)
33
    {
34 21
        if ($capacity < 1) {
35 3
            throw new InvalidArgumentException('Capacity must be greater than 0.');
36
        }
37
38 21
        $this->capacity = $capacity;
39 21
    }
40
41
    /**
42
     * Checks if a key exists in the cache.
43
     *
44
     * @param string|int $key
45
     * @return bool
46
     *
47
     * @psalm-param TKey $key
48
     * @psalm-return bool
49
     */
50 21
    public function has($key): bool
51
    {
52 21
        return array_key_exists($key, $this->cache);
53
    }
54
55
    /**
56
     * Returns a cache entry if it exists.
57
     *
58
     * @param string|int $key
59
     * @return mixed|null
60
     *
61
     * @psalm-param TKey $key
62
     * @psalm-return TValue|null
63
     */
64 12
    public function get($key)
65
    {
66 12
        if ($this->has($key)) {
67 12
            return $this->putExisting($key, $this->cache[$key]);
68
        }
69
70 12
        return null;
71
    }
72
73
    /**
74
     * Returns an existing cache entry or calls the callback to retrieve it.
75
     *
76
     * @param string|int $key
77
     * @param callable $callback
78
     * @return mixed
79
     *
80
     * @psalm-param TKey $key
81
     * @psalm-param callable(TKey): TValue $callback
82
     * @psalm-return TValue
83
     */
84 3
    public function getWith($key, callable $callback)
85
    {
86 3
        if ($this->has($key)) {
87 3
            return $this->putExisting($key, $this->cache[$key]);
88
        }
89
90 3
        return $this->putNew($key, $callback($key));
91
    }
92
93
    /**
94
     * Sets a cache entry.
95
     *
96
     * @param string|int $key
97
     * @param mixed $value
98
     *
99
     * @psalm-param TKey $key
100
     * @psalm-param TValue $value
101
     */
102 21
    public function put($key, $value): void
103
    {
104 21
        if ($this->has($key)) {
105 3
            $this->putExisting($key, $value);
106
        } else {
107 21
            $this->putNew($key, $value);
108
        }
109 21
    }
110
111
    /**
112
     * @param string|int $key
113
     * @param mixed $value
114
     * @return mixed
115
     *
116
     * @psalm-param TKey $key
117
     * @psalm-param TValue $value
118
     * @psalm-return TValue
119
     */
120 15
    private function putExisting($key, $value)
121
    {
122 15
        unset($this->cache[$key]);
123
124 15
        return $this->cache[$key] = $value;
125
    }
126
127
    /**
128
     * @param string|int $key
129
     * @param mixed $value
130
     * @return mixed
131
     *
132
     * @psalm-param TKey $key
133
     * @psalm-param TValue $value
134
     * @psalm-return TValue
135
     */
136 21
    private function putNew($key, $value)
137
    {
138
        // We're at capacity; delete the least recently used cache entry.
139 21
        if ($this->size === $this->capacity) {
140 12
            unset($this->cache[key($this->cache)]);
141
        } else {
142 21
            ++$this->size;
143
        }
144
145 21
        return $this->cache[$key] = $value;
146
    }
147
}
148