Completed
Push — 17.x ( b10fe2...726eb0 )
by Tim
08:00 queued 06:27
created

LocalCacheAdapter::toCache()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6.1384

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 9
cts 14
cp 0.6429
rs 9.1128
c 0
b 0
f 0
cc 5
nc 5
nop 6
crap 6.1384
1
<?php
2
3
/**
4
 * TechDivision\Import\Cache\GenericCacheAdapter
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2019 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Cache;
22
23
use TechDivision\Import\Utils\CacheKeyUtilInterface;
24
25
/**
26
 * Local cache adapter implementation.
27
 *
28
 * This cache adapter guarantees maximum performance but can eventually not be used
29
 * in a distributed environemnt where you want to use e. g. Redis for caching.
30
 *
31
 * If you are in a distributed environment, have a look at the GenericCacheAdapter
32
 * that can wrap any PSR-6 compatible cache implementations.
33
 *
34
 * @author    Tim Wagner <[email protected]>
35
 * @copyright 2019 TechDivision GmbH <[email protected]>
36
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
37
 * @link      https://github.com/techdivision/import
38
 * @link      http://www.techdivision.com
39
 * @see       \TechDivision\Import\Cache\GenericCacheAdapter
40
 */
41
class LocalCacheAdapter implements CacheAdapterInterface
42
{
43
44
    /**
45
     * Trait that provides custom cache adapter functionality.
46
     *
47
     * @var TechDivision\Import\Cache\CacheAdapterTrait
48
     */
49
    use CacheAdapterTrait;
50
51
    /**
52
     * The array with the tags.
53
     *
54
     * @var array
55
     */
56
    protected $tags = array();
57
58
    /**
59
     * The cache for the query results.
60
     *
61
     * @var array
62
     */
63
    protected $cache = array();
64
65
    /**
66
     * References that links to another cache entry.
67
     *
68
     * @var array
69
     */
70
    protected $references = array();
71
72
    /**
73
     * The cache key utility instance.
74
     *
75
     * @var \TechDivision\Import\Utils\CacheKeyUtilInterface
76
     */
77
    protected $cacheKeyUtil;
78
79
    /**
80
     * Initialize the cache handler with the passed cache and configuration instances.
81
     *
82
     * @param \TechDivision\Import\Utils\CacheKeyUtilInterface $cacheKeyUtil The cache key utility instance
83
     */
84 20
    public function __construct(CacheKeyUtilInterface $cacheKeyUtil)
85
    {
86 20
        $this->cacheKeyUtil = $cacheKeyUtil;
87 20
    }
88
89
    /**
90
     * Creates a unique cache key from the passed data.
91
     *
92
     * @param mixed   $data      The date to create the cache key from
93
     * @param boolean $usePrefix Flag to signal using the prefix or not
94
     *
95
     * @return string The generated cache key
96
     */
97 20
    public function cacheKey($data, $usePrefix = true)
98
    {
99 20
        return $this->cacheKeyUtil->cacheKey($data, $usePrefix);
100
    }
101
102
    /**
103
     * Query whether or not a cache value for the passed cache key is available.
104
     *
105
     * @param string $key The cache key to query for
106
     *
107
     * @return boolean TRUE if the a value is available, else FALSE
108
     */
109 20
    public function isCached($key)
110
    {
111 20
        return isset($this->cache[$this->resolveReference($this->cacheKey($key))]);
112
    }
113
114
    /**
115
     * Inversion of the isCached() method.
116
     *
117
     * @param string $key The cache key to query for
118
     *
119
     * @return boolean TRUE if the value is not available, else FALSE
120
     */
121
    public function notCached($key)
122
    {
123
        return !$this->isCached($key);
124
    }
125
126
    /**
127
     * Add's a cache reference from one key to another.
128
     *
129
     * @param string $from The key to reference from
130
     * @param string $to   The key to reference to
131
     *
132
     * @return void
133
     */
134 20
    public function addReference($from, $to)
135
    {
136 20
        $this->references[$this->cacheKey($from)] = $this->cacheKey($to);
137 20
    }
138
139
    /**
140
     * Resolve's the cache key.
141
     *
142
     * @param string $from The cache key to resolve
143
     *
144
     * @return string The resolved reference
145
     */
146 20
    protected function resolveReference($from)
147
    {
148
149
        // query whether or not a reference exists
150 20
        if (isset($this->references[$from])) {
151 20
            return $this->references[$from];
152
        }
153
154
        // return the passed reference
155 20
        return $from;
156
    }
157
158
    /**
159
     * Add the passed item to the cache.
160
     *
161
     * @param string  $key        The cache key to use
162
     * @param mixed   $value      The value that has to be cached
163
     * @param array   $references An array with references to add
164
     * @param array   $tags       An array with tags to add
165
     * @param boolean $override   Flag that allows to override an exising cache entry
166
     * @param integer $time       The TTL in seconds for the passed item
167
     *
168
     * @return void
169
     */
170 20
    public function toCache($key, $value, array $references = array(), array $tags = array(), $override = true, $time = null)
171
    {
172
173
        // query whether or not the key has already been used
174 20
        if (isset($this->cache[$this->resolveReference($uniqueKey = $this->cacheKey($key))]) && $override === false) {
175
            throw new \Exception(
176
                sprintf(
177
                    'Try to override data with key "%s"',
178
                    $uniqueKey
179
                )
180
            );
181
        }
182
183
        // set the attribute in the registry
184 20
        $this->cache[$uniqueKey] = $value;
185
186
        // prepend the tags with the cache key
187 20
        array_walk($tags, function (&$tag) {
188
            $tag = $this->cacheKey($tag);
189 20
        });
190
191
        // tag the unique key
192 20
        foreach ($tags as $tag) {
193
            $this->tags[$tag][] = $uniqueKey;
194
        }
195
196
        // also register the references if given
197 20
        foreach ($references as $from => $to) {
198 20
            $this->addReference($from, $to);
199
        }
200 20
    }
201
202
    /**
203
     * Returns a new cache item for the passed key
204
     *
205
     * @param string $key The cache key to return the item for
206
     *
207
     * @return mixed The value for the passed key
208
     */
209
    public function fromCache($key)
210
    {
211
        if (isset($this->cache[$uniqueKey = $this->resolveReference($this->cacheKey($key))])) {
212
            return $this->cache[$uniqueKey];
213
        }
214
    }
215
216
    /**
217
     * Flush the cache and remove the references.
218
     *
219
     * @return void
220
     */
221
    public function flushCache()
222
    {
223
        $this->tags = array();
224
        $this->cache = array();
225
        $this->references = array();
226
    }
227
228
    /**
229
     * Invalidate the cache entries for the passed tags.
230
     *
231
     * @param array $tags The tags to invalidate the cache for
232
     *
233
     * @return void
234
     */
235
    public function invalidateTags(array $tags)
236
    {
237
238
        // prepend the tags with the cache key
239
        array_walk($tags, function (&$tag) {
240
            $tag = $this->cacheKey($tag);
241
        });
242
243
        // remove all the references of items that has one of the passed tags
244
        foreach ($tags as $tag) {
245
            if (isset($this->tags[$tag])) {
246
                foreach ($this->tags[$tag] as $to) {
247
                    // clean-up the references that reference to the key
248
                    if ($from = array_search($to, $this->references)) {
249
                        unset($this->references[$from]);
250
                    }
251
                    // clean-up the cache entry itself
252
                    if (isset($this->cache[$to])) {
253
                        unset($this->cache[$to]);
254
                    }
255
                }
256
            }
257
        }
258
    }
259
260
    /**
261
     * Remove the item with the passed key and all its references from the cache.
262
     *
263
     * @param string $key               The key of the cache item to Remove
264
     * @param bool   $cleanUpReferences TRUE if the references has to be cleaned-up, else FALSE (default)
265
     *
266
     * @return void
267
     */
268 10
    public function removeCache($key, $cleanUpReferences = false)
269
    {
270 10
        unset($this->cache[$this->resolveReference($uniqueKey = $this->cacheKey($key))]);
271
272
        // query whether or not we've to clean-up references
273 10
        if ($cleanUpReferences === true) {
274
            // load the keys of the references we want to remove
275
            $references = array_keys($this->references, $uniqueKey);
0 ignored issues
show
Bug introduced by
The variable $uniqueKey seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
276
277
            // remove ALL references to the passed unique key
278
            foreach ($references as $reference) {
279
                unset($this->references[$reference]);
280
            }
281
        }
282 10
    }
283
}
284