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
|
|
|
public function __construct(CacheKeyUtilInterface $cacheKeyUtil) |
85
|
|
|
{ |
86
|
|
|
$this->cacheKeyUtil = $cacheKeyUtil; |
87
|
|
|
} |
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
|
|
|
public function cacheKey($data) |
97
|
|
|
{ |
98
|
|
|
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
|
|
|
public function isCached($key) |
109
|
|
|
{ |
110
|
|
|
|
111
|
|
|
// query whether or not the item has been cached, and if yes if the cache is valid |
112
|
|
View Code Duplication |
if (isset($this->cache[$resolvedKey = $this->resolveReference($this->cacheKey($key))])) { |
|
|
|
|
113
|
|
|
return $this->cache[$resolvedKey]; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
// return FALSE in all other cases |
117
|
|
|
return false; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Inversion of the isCached() method. |
122
|
|
|
* |
123
|
|
|
* @param string $key The cache key to query for |
124
|
|
|
* |
125
|
|
|
* @return boolean TRUE if the value is not available, else FALSE |
126
|
|
|
*/ |
127
|
|
|
public function notCached($key) |
128
|
|
|
{ |
129
|
|
|
return !$this->isCached($key); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Add's a cache reference from one key to another. |
134
|
|
|
* |
135
|
|
|
* @param string $from The key to reference from |
136
|
|
|
* @param string $to The key to reference to |
137
|
|
|
* |
138
|
|
|
* @return void |
139
|
|
|
*/ |
140
|
|
|
public function addReference($from, $to) |
141
|
|
|
{ |
142
|
|
|
$this->references[$this->cacheKey($from)] = $this->cacheKey($to); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Resolve's the cache key. |
147
|
|
|
* |
148
|
|
|
* @param string $from The cache key to resolve |
149
|
|
|
* |
150
|
|
|
* @return string The resolved reference |
151
|
|
|
*/ |
152
|
|
|
protected function resolveReference($from) |
153
|
|
|
{ |
154
|
|
|
|
155
|
|
|
// query whether or not a reference exists |
156
|
|
|
if (isset($this->references[$from])) { |
157
|
|
|
return $this->references[$from]; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
// return the passed reference |
161
|
|
|
return $from; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Add the passed item to the cache. |
166
|
|
|
* |
167
|
|
|
* @param string $key The cache key to use |
168
|
|
|
* @param mixed $value The value that has to be cached |
169
|
|
|
* @param array $references An array with references to add |
170
|
|
|
* @param array $tags An array with tags to add |
171
|
|
|
* @param boolean $override Flag that allows to override an exising cache entry |
172
|
|
|
* @param integer $time The TTL in seconds for the passed item |
173
|
|
|
* |
174
|
|
|
* @return void |
175
|
|
|
*/ |
176
|
|
|
public function toCache($key, $value, array $references = array(), array $tags = array(), $override = false, $time = null) |
177
|
|
|
{ |
178
|
|
|
|
179
|
|
|
// query whether or not the key has already been used |
180
|
|
|
if (isset($this->cache[$this->resolveReference($uniqueKey = $this->cacheKey($key))]) && $override === false) { |
181
|
|
|
throw new \Exception( |
182
|
|
|
sprintf( |
183
|
|
|
'Try to override data with key "%s"', |
184
|
|
|
$uniqueKey |
185
|
|
|
) |
186
|
|
|
); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
// set the attribute in the registry |
190
|
|
|
$this->cache[$uniqueKey] = $value; |
191
|
|
|
|
192
|
|
|
// prepend the tags with the cache key |
193
|
|
|
array_walk($tags, function (&$tag) { |
194
|
|
|
$tag = $this->cacheKey($tag); |
195
|
|
|
}); |
196
|
|
|
|
197
|
|
|
// tag the unique key |
198
|
|
|
foreach ($tags as $tag) { |
199
|
|
|
$this->tags[$tag][] = $uniqueKey; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
// also register the references if given |
203
|
|
|
foreach ($references as $from => $to) { |
204
|
|
|
$this->addReference($from, $to); |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Returns a new cache item for the passed key |
210
|
|
|
* |
211
|
|
|
* @param string $key The cache key to return the item for |
212
|
|
|
* |
213
|
|
|
* @return mixed The value for the passed key |
214
|
|
|
*/ |
215
|
|
|
public function fromCache($key) |
216
|
|
|
{ |
217
|
|
View Code Duplication |
if (isset($this->cache[$uniqueKey = $this->resolveReference($this->cacheKey($key))])) { |
|
|
|
|
218
|
|
|
return $this->cache[$uniqueKey]; |
219
|
|
|
} |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Flush the cache and remove the references. |
224
|
|
|
* |
225
|
|
|
* @return void |
226
|
|
|
*/ |
227
|
|
|
public function flushCache() |
228
|
|
|
{ |
229
|
|
|
$this->tags = array(); |
230
|
|
|
$this->cache = array(); |
231
|
|
|
$this->references = array(); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Invalidate the cache entries for the passed tags. |
236
|
|
|
* |
237
|
|
|
* @param array $tags The tags to invalidate the cache for |
238
|
|
|
* |
239
|
|
|
* @return void |
240
|
|
|
*/ |
241
|
|
|
public function invalidateTags(array $tags) |
242
|
|
|
{ |
243
|
|
|
|
244
|
|
|
// prepend the tags with the cache key |
245
|
|
|
array_walk($tags, function (&$tag) { |
246
|
|
|
$tag = $this->cacheKey($tag); |
247
|
|
|
}); |
248
|
|
|
|
249
|
|
|
// remove all the references of items that has one of the passed tags |
250
|
|
|
foreach ($tags as $tag) { |
251
|
|
|
if (isset($this->tags[$tag])) { |
252
|
|
|
foreach ($this->tags[$tag] as $to) { |
253
|
|
|
if ($from = array_search($to, $this->references)) { |
254
|
|
|
unset($this->references[$from]); |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
} |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Remove the item with the passed key and all its references from the cache. |
263
|
|
|
* |
264
|
|
|
* @param string $key The key of the cache item to Remove |
265
|
|
|
* |
266
|
|
|
* @return void |
267
|
|
|
*/ |
268
|
|
|
public function removeCache($key) |
269
|
|
|
{ |
270
|
|
|
|
271
|
|
|
// delete the item with the passed key |
272
|
|
|
unset($this->cache[$this->resolveReference($uniqueKey = $this->cacheKey($key))]); |
273
|
|
|
|
274
|
|
|
// query whether or not the references exists and has to be removed |
275
|
|
|
if (isset($this->references[$uniqueKey])) { |
|
|
|
|
276
|
|
|
unset($this->references[$uniqueKey]); |
277
|
|
|
} |
278
|
|
|
} |
279
|
|
|
} |
280
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.