Completed
Push — 15.x ( dbfbe9...39dd4d )
by Tim
02:17
created

LocalCacheAdapter   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 48.15%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 2
dl 0
loc 231
ccs 26
cts 54
cp 0.4815
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A cacheKey() 0 4 1
A isCached() 0 4 1
A notCached() 0 4 1
A addReference() 0 4 1
A resolveReference() 0 11 2
A toCache() 0 31 5
A fromCache() 0 6 2
A flushCache() 0 6 1
B invalidateTags() 0 24 6
A removeCache() 0 4 1
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
     *
265
     * @return void
266
     */
267 10
    public function removeCache($key)
268
    {
269 10
        unset($this->cache[$this->resolveReference($this->cacheKey($key))]);
270 10
    }
271
}
272