Passed
Push — feature-add-checkstyle ( f83c9d )
by Sébastien
18:53
created

CachableTrait   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 191
Duplicated Lines 0 %

Test Coverage

Coverage 89.09%

Importance

Changes 0
Metric Value
wmc 23
eloc 48
c 0
b 0
f 0
dl 0
loc 191
ccs 49
cts 55
cp 0.8909
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A cache() 0 3 1
A cacheNamespace() 0 9 2
A getCacheKey() 0 3 1
A clearCacheOnWrite() 0 4 3
A setCache() 0 5 1
A cacheKey() 0 3 1
A setCacheNamespace() 0 9 2
A setCacheKey() 0 9 2
A setCacheLifetime() 0 9 2
A useCache() 0 23 3
A executeCached() 0 22 5
1
<?php
2
3
namespace Bdf\Prime\Query\Extension;
4
5
use Bdf\Prime\Cache\CacheInterface;
6
use Bdf\Prime\Cache\CacheKey;
7
use Bdf\Prime\Connection\ConnectionInterface;
8
use Bdf\Prime\Connection\Result\ArrayResultSet;
9
use Bdf\Prime\Connection\Result\ResultSetInterface;
10
use Bdf\Prime\Query\Contract\Cachable;
11
use Bdf\Util\Arr;
12
13
/**
14
 * Provides result cache on queries
15
 *
16
 * @see Cachable
17
 *
18
 * @psalm-require-implements Cachable
19
 *
20
 * @todo Cache statement instead of assoc array result ?
21
 */
22
trait CachableTrait
23
{
24
    /**
25
     * @var null|CacheInterface
26
     */
27
    protected $cache;
28
29
    /**
30
     * @var CacheKey
31
     */
32
    protected $cacheKey = null;
33
34
35
    /**
36
     * {@inheritdoc}
37
     *
38
     * @see Cachable::cache()
39
     */
40 2
    public function cache(): ?CacheInterface
41
    {
42 2
        return $this->cache;
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     *
48
     * @see Cachable::useCache()
49
     */
50 13
    public function useCache(int $lifetime = 0, ?string $key = null)
51
    {
52 13
        if ($this->cacheKey === null) {
53 13
            $this->cacheKey = new CacheKey(
54 13
                function () {
55 13
                    return $this->cacheNamespace();
56
                },
57 13
                $key ?? function () {
58 12
                    return $this->cacheKey();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->cacheKey() targeting Bdf\Prime\Query\Extensio...chableTrait::cacheKey() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
59
                },
60
                $lifetime
61
            );
62
63 13
            return $this;
64
        }
65
66 1
        $this->cacheKey->setLifetime($lifetime);
67
68 1
        if ($key !== null) {
69 1
            $this->cacheKey->setKey($key);
70
        }
71
72 1
        return $this;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     *
78
     * @see Cachable::setCache()
79
     */
80 726
    public function setCache(CacheInterface $cache = null)
81
    {
82 726
        $this->cache = $cache;
83
84 726
        return $this;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     *
90
     * @see Cachable::setCacheLifetime()
91
     */
92 1
    public function setCacheLifetime(int $lifetime)
93
    {
94 1
        if (!$this->cacheKey) {
95
            $this->useCache();
96
        }
97
98 1
        $this->cacheKey->setLifetime($lifetime);
99
100 1
        return $this;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     *
106
     * @see Cachable::setCacheKey()
107
     */
108 2
    public function setCacheKey(?string $cacheKey)
109
    {
110 2
        if (!$this->cacheKey) {
111
            $this->useCache();
112
        }
113
114 2
        $this->cacheKey->setKey($cacheKey);
115
116 2
        return $this;
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     *
122
     * @see Cachable::setCacheNamespace()
123
     */
124 1
    public function setCacheNamespace(string $namespace)
125
    {
126 1
        if (!$this->cacheKey) {
127
            $this->useCache();
128
        }
129
130 1
        $this->cacheKey->setNamespace($namespace);
131
132 1
        return $this;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     *
138
     * @see Cachable::getCacheKey()
139
     */
140 2
    public function getCacheKey(): ?CacheKey
141
    {
142 2
        return $this->cacheKey;
143
    }
144
145
    /**
146
     * Retrieve data from cache, or execute the query and save into cache
147
     *
148
     * @return ResultSetInterface<array<string, mixed>>
149
     * @throws \Bdf\Prime\Exception\PrimeException
150
     */
151 793
    protected function executeCached(): ResultSetInterface
152
    {
153 793
        $key = $this->cacheKey;
154
155 793
        if (!$this->cache || !$key || !$key->valid()) {
156
            /** @psalm-suppress InvalidArgument */
157 782
            return $this->connection->execute($this);
158
        }
159
160 12
        $data = $this->cache->get($key);
161
162 12
        if ($data !== null) {
163 3
            return new ArrayResultSet($data);
164
        }
165
166
        /** @psalm-suppress InvalidArgument */
167 12
        $result = $this->connection->execute($this);
168
169 12
        $data = $result->all();
170 12
        $this->cache->set($key, $data);
171
172 12
        return new ArrayResultSet($data);
173
    }
174
175
    /**
176
     * Clear the cache when a write operation is performed
177
     *
178
     * @return void
179
     */
180 806
    protected function clearCacheOnWrite()
181
    {
182 806
        if ($this->cache) {
183 7
            $this->cache->flush($this->cacheKey ? $this->cacheKey->namespace() : $this->cacheNamespace());
184
        }
185
    }
186
187
    /**
188
     * Get the cache key
189
     * The cache key is generated from the query string
190
     *
191
     * @return string
192
     */
193
    protected function cacheKey(): ?string
194
    {
195
        return null;
196
    }
197
198
    /**
199
     * Get cache namespace
200
     * The namespace is in form : [connection name] ":" [table name]
201
     *
202
     * @return string
203
     */
204 11
    protected function cacheNamespace(): string
205
    {
206 11
        $ns = $this->connection->getName().':';
207
208 11
        foreach ($this->statements['tables'] as $from) {
209 11
            return $ns.$from['table'];
210
        }
211
212
        return $ns;
213
    }
214
}
215