Passed
Push — master ( b2988e...9f380c )
by Jonathan
33:05
created

CacheProvider::fetch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Doctrine\Common\Cache;
4
5
use function array_combine;
6
use function array_key_exists;
7
use function array_map;
8
use function sprintf;
9
10
/**
11
 * Base class for cache provider implementations.
12
 *
13
 */
14
abstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiOperationCache
15
{
16
    public const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]';
17
18
    /**
19
     * The namespace to prefix all cache ids with.
20
     *
21
     * @var string
22
     */
23
    private $namespace = '';
24
25
    /**
26
     * The namespace version.
27
     *
28
     * @var int|null
29
     */
30
    private $namespaceVersion;
31
32
    /**
33
     * Sets the namespace to prefix all cache ids with.
34
     *
35
     * @param string $namespace
36
     *
37
     * @return void
38
     */
39
    public function setNamespace($namespace)
40
    {
41
        $this->namespace        = (string) $namespace;
42
        $this->namespaceVersion = null;
43
    }
44
45
    /**
46
     * Retrieves the namespace that prefixes all cache ids.
47
     *
48
     * @return string
49
     */
50
    public function getNamespace()
51
    {
52
        return $this->namespace;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58 25
    public function fetch($id)
59
    {
60 25
        return $this->doFetch($this->getNamespacedId($id));
61 25
    }
62 25
63
    /**
64
     * {@inheritdoc}
65
     */
66
    public function fetchMultiple(array $keys)
67
    {
68
        if (empty($keys)) {
69 1
            return [];
70
        }
71 1
72
        // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys
73
        $namespacedKeys = array_combine($keys, array_map([$this, 'getNamespacedId'], $keys));
74
        $items          = $this->doFetchMultiple($namespacedKeys);
75
        $foundItems     = [];
76
77 750
        // no internal array function supports this sort of mapping: needs to be iterative
78
        // this filters and combines keys in one pass
79 750
        foreach ($namespacedKeys as $requestedKey => $namespacedKey) {
80
            if (! isset($items[$namespacedKey]) && ! array_key_exists($namespacedKey, $items)) {
81
                continue;
82
            }
83
84
            $foundItems[$requestedKey] = $items[$namespacedKey];
85 39
        }
86
87 39
        return $foundItems;
88 12
    }
89
90
    /**
91
     * {@inheritdoc}
92 27
     */
93 27
    public function saveMultiple(array $keysAndValues, $lifetime = 0)
94 27
    {
95
        $namespacedKeysAndValues = [];
96
        foreach ($keysAndValues as $key => $value) {
97
            $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value;
98 27
        }
99 27
100 27
        return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime);
101
    }
102
103
    /**
104 27
     * {@inheritdoc}
105
     */
106
    public function contains($id)
107
    {
108
        return $this->doContains($this->getNamespacedId($id));
109
    }
110 15
111
    /**
112 15
     * {@inheritdoc}
113 15
     */
114 15
    public function save($id, $data, $lifeTime = 0)
115
    {
116
        return $this->doSave($this->getNamespacedId($id), $data, $lifeTime);
117 15
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122
    public function deleteMultiple(array $keys)
123 842
    {
124
        return $this->doDeleteMultiple(array_map([$this, 'getNamespacedId'], $keys));
125 842
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function delete($id)
131 878
    {
132
        return $this->doDelete($this->getNamespacedId($id));
133 878
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138
    public function getStats()
139 14
    {
140
        return $this->doGetStats();
141 14
    }
142
143
    /**
144
     * {@inheritDoc}
145
     */
146
    public function flushAll()
147 524
    {
148
        return $this->doFlush();
149 524
    }
150
151
    /**
152
     * {@inheritDoc}
153
     */
154
    public function deleteAll()
155 14
    {
156
        $namespaceCacheKey = $this->getNamespaceCacheKey();
157 14
        $namespaceVersion  = $this->getNamespaceVersion() + 1;
158
159
        if ($this->doSave($namespaceCacheKey, $namespaceVersion)) {
160
            $this->namespaceVersion = $namespaceVersion;
161
162
            return true;
163 26
        }
164
165 26
        return false;
166
    }
167
168
    /**
169
     * Prefixes the passed id with the configured namespace value.
170
     *
171 78
     * @param string $id The id to namespace.
172
     *
173 78
     * @return string The namespaced id.
174 78
     */
175
    private function getNamespacedId(string $id) : string
176 78
    {
177 77
        $namespaceVersion = $this->getNamespaceVersion();
178
179 77
        return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion);
180
    }
181
182 1
    /**
183
     * Returns the namespace cache key.
184
     */
185
    private function getNamespaceCacheKey() : string
186
    {
187
        return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
188
    }
189
190
    /**
191
     * Returns the namespace version.
192 923
     */
193
    private function getNamespaceVersion() : int
194 923
    {
195
        if ($this->namespaceVersion !== null) {
196 923
            return $this->namespaceVersion;
197
        }
198
199
        $namespaceCacheKey      = $this->getNamespaceCacheKey();
200
        $this->namespaceVersion = (int) $this->doFetch($namespaceCacheKey) ?: 1;
201
202
        return $this->namespaceVersion;
203
    }
204 924
205
    /**
206 924
     * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it.
207
     *
208
     * @param array $keys Array of keys to retrieve from cache
209
     * @return array Array of values retrieved for the given keys.
210
     */
211
    protected function doFetchMultiple(array $keys)
212
    {
213
        $returnValues = [];
214 924
215
        foreach ($keys as $key) {
216 924
            $item = $this->doFetch($key);
217 908
            if ($item === false && ! $this->doContains($key)) {
218
                continue;
219
            }
220 924
221 924
            $returnValues[$key] = $item;
222
        }
223 924
224
        return $returnValues;
225
    }
226
227
    /**
228
     * Fetches an entry from the cache.
229
     *
230
     * @param string $id The id of the cache entry to fetch.
231
     *
232 18
     * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id.
233
     */
234 18
    abstract protected function doFetch($id);
235
236 18
    /**
237 18
     * Tests if an entry exists in the cache.
238 18
     *
239
     * @param string $id The cache id of the entry to check for.
240
     *
241
     * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise.
242 18
     */
243
    abstract protected function doContains($id);
244
245
    /**
246
     * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it.
247
     *
248
     * @param array $keysAndValues Array of keys and values to save in cache
249
     * @param int   $lifetime      The lifetime. If != 0, sets a specific lifetime for these
250
     *                             cache entries (0 => infinite lifeTime).
251
     *
252
     * @return bool TRUE if the operation was successful, FALSE if it wasn't.
253
     */
254
    protected function doSaveMultiple(array $keysAndValues, $lifetime = 0)
255
    {
256
        $success = true;
257
258
        foreach ($keysAndValues as $key => $value) {
259
            if ($this->doSave($key, $value, $lifetime)) {
260
                continue;
261
            }
262
263
            $success = false;
264
        }
265
266
        return $success;
267
    }
268
269
    /**
270
     * Puts data into the cache.
271
     *
272 11
     * @param string $id       The cache id.
273
     * @param string $data     The cache entry/data.
274 11
     * @param int    $lifeTime The lifetime. If != 0, sets a specific lifetime for this
275
     *                           cache entry (0 => infinite lifeTime).
276 11
     *
277 11
     * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise.
278 11
     */
279
    abstract protected function doSave($id, $data, $lifeTime = 0);
280
281
    /**
282 11
     * Default implementation of doDeleteMultiple. Each driver that supports multi-delete should override it.
283
     *
284
     * @param array $keys Array of keys to delete from cache
285
     *
286
     * @return bool TRUE if the operation was successful, FALSE if it wasn't
287
     */
288
    protected function doDeleteMultiple(array $keys)
289
    {
290
        $success = true;
291
292
        foreach ($keys as $key) {
293
            if ($this->doDelete($key)) {
294
                continue;
295
            }
296
297
            $success = false;
298
        }
299
300
        return $success;
301
    }
302
303
    /**
304 9
     * Deletes a cache entry.
305
     *
306 9
     * @param string $id The cache id.
307
     *
308 9
     * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise.
309 9
     */
310 9
    abstract protected function doDelete($id);
311
312
    /**
313
     * Flushes all cache entries.
314 9
     *
315
     * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise.
316
     */
317
    abstract protected function doFlush();
318
319
    /**
320
     * Retrieves cached information from the data store.
321
     *
322
     * @return array|null An associative array with server's statistics if available, NULL otherwise.
323
     */
324
    abstract protected function doGetStats();
325
}
326