Completed
Push — 14.x ( 855d13...227841 )
by Tim
02:29
created

LocalCacheAdapter   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 230
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 230
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
     *
94
     * @return string The generated cache key
95
     */
96 20
    public function cacheKey($data)
97
    {
98 20
        return $this->cacheKeyUtil->cacheKey($data);
99
    }
100
101
    /**
102
     * Query whether or not a cache value for the passed cache key is available.
103
     *
104
     * @param string $key The cache key to query for
105
     *
106
     * @return boolean TRUE if the a value is available, else FALSE
107
     */
108 20
    public function isCached($key)
109
    {
110 20
        return isset($this->cache[$this->resolveReference($this->cacheKey($key))]);
111
    }
112
113
    /**
114
     * Inversion of the isCached() method.
115
     *
116
     * @param string $key The cache key to query for
117
     *
118
     * @return boolean TRUE if the value is not available, else FALSE
119
     */
120
    public function notCached($key)
121
    {
122
        return !$this->isCached($key);
123
    }
124
125
    /**
126
     * Add's a cache reference from one key to another.
127
     *
128
     * @param string $from The key to reference from
129
     * @param string $to   The key to reference to
130
     *
131
     * @return void
132
     */
133 20
    public function addReference($from, $to)
134
    {
135 20
        $this->references[$this->cacheKey($from)] = $this->cacheKey($to);
136 20
    }
137
138
    /**
139
     * Resolve's the cache key.
140
     *
141
     * @param string $from The cache key to resolve
142
     *
143
     * @return string The resolved reference
144
     */
145 20
    protected function resolveReference($from)
146
    {
147
148
        // query whether or not a reference exists
149 20
        if (isset($this->references[$from])) {
150 20
            return $this->references[$from];
151
        }
152
153
        // return the passed reference
154 20
        return $from;
155
    }
156
157
    /**
158
     * Add the passed item to the cache.
159
     *
160
     * @param string  $key        The cache key to use
161
     * @param mixed   $value      The value that has to be cached
162
     * @param array   $references An array with references to add
163
     * @param array   $tags       An array with tags to add
164
     * @param boolean $override   Flag that allows to override an exising cache entry
165
     * @param integer $time       The TTL in seconds for the passed item
166
     *
167
     * @return void
168
     */
169 20
    public function toCache($key, $value, array $references = array(), array $tags = array(), $override = false, $time = null)
170
    {
171
172
        // query whether or not the key has already been used
173 20
        if (isset($this->cache[$this->resolveReference($uniqueKey = $this->cacheKey($key))]) && $override === false) {
174
            throw new \Exception(
175
                sprintf(
176
                    'Try to override data with key "%s"',
177
                    $uniqueKey
178
                )
179
            );
180
        }
181
182
        // set the attribute in the registry
183 20
        $this->cache[$uniqueKey] = $value;
184
185
        // prepend the tags with the cache key
186 20
        array_walk($tags, function (&$tag) {
187
            $tag = $this->cacheKey($tag);
188 20
        });
189
190
        // tag the unique key
191 20
        foreach ($tags as $tag) {
192
            $this->tags[$tag][] = $uniqueKey;
193
        }
194
195
        // also register the references if given
196 20
        foreach ($references as $from => $to) {
197 20
            $this->addReference($from, $to);
198
        }
199 20
    }
200
201
    /**
202
     * Returns a new cache item for the passed key
203
     *
204
     * @param string $key The cache key to return the item for
205
     *
206
     * @return mixed The value for the passed key
207
     */
208
    public function fromCache($key)
209
    {
210
        if (isset($this->cache[$uniqueKey = $this->resolveReference($this->cacheKey($key))])) {
211
            return $this->cache[$uniqueKey];
212
        }
213
    }
214
215
    /**
216
     * Flush the cache and remove the references.
217
     *
218
     * @return void
219
     */
220
    public function flushCache()
221
    {
222
        $this->tags = array();
223
        $this->cache = array();
224
        $this->references = array();
225
    }
226
227
    /**
228
     * Invalidate the cache entries for the passed tags.
229
     *
230
     * @param array $tags The tags to invalidate the cache for
231
     *
232
     * @return void
233
     */
234
    public function invalidateTags(array $tags)
235
    {
236
237
        // prepend the tags with the cache key
238
        array_walk($tags, function (&$tag) {
239
            $tag = $this->cacheKey($tag);
240
        });
241
242
        // remove all the references of items that has one of the passed tags
243
        foreach ($tags as $tag) {
244
            if (isset($this->tags[$tag])) {
245
                foreach ($this->tags[$tag] as $to) {
246
                    // clean-up the references that reference to the key
247
                    if ($from = array_search($to, $this->references)) {
248
                        unset($this->references[$from]);
249
                    }
250
                    // clean-up the cache entry itself
251
                    if (isset($this->cache[$to])) {
252
                        unset($this->cache[$to]);
253
                    }
254
                }
255
            }
256
        }
257
    }
258
259
    /**
260
     * Remove the item with the passed key and all its references from the cache.
261
     *
262
     * @param string $key The key of the cache item to Remove
263
     *
264
     * @return void
265
     */
266 10
    public function removeCache($key)
267
    {
268 10
        unset($this->cache[$this->resolveReference($this->cacheKey($key))]);
269 10
    }
270
}
271