1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
* This file is part of phpFastCache. |
5
|
|
|
* |
6
|
|
|
* @license MIT License (MIT) |
7
|
|
|
* |
8
|
|
|
* For full copyright and license information, please see the docs/CREDITS.txt file. |
9
|
|
|
* |
10
|
|
|
* @author Khoa Bui (khoaofgod) <[email protected]> http://www.phpfastcache.com |
11
|
|
|
* @author Georges.L (Geolim4) <[email protected]> |
12
|
|
|
* |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace phpFastCache\Core\Pool; |
16
|
|
|
|
17
|
|
|
use InvalidArgumentException; |
18
|
|
|
use phpFastCache\Core\Item\ExtendedCacheItemInterface; |
19
|
|
|
use phpFastCache\EventManager; |
20
|
|
|
use Psr\Cache\CacheItemInterface; |
21
|
|
|
|
22
|
|
|
|
23
|
|
|
trait ExtendedCacheItemPoolTrait |
24
|
|
|
{ |
25
|
|
|
use CacheItemPoolTrait; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @inheritdoc |
29
|
|
|
*/ |
30
|
|
|
public function clean() |
31
|
|
|
{ |
32
|
|
|
trigger_error('Cache clean() method is deprecated, use clear() method instead', E_USER_DEPRECATED); |
33
|
|
|
return $this->clear(); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @inheritdoc |
38
|
|
|
*/ |
39
|
|
|
public function getItemsAsJsonString(array $keys = [], $option = 0, $depth = 512) |
40
|
|
|
{ |
41
|
|
|
$callback = function (CacheItemInterface $item) { |
42
|
|
|
return $item->get(); |
43
|
|
|
}; |
44
|
|
|
return json_encode(array_map($callback, array_values($this->getItems($keys))), $option, $depth); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @inheritdoc |
49
|
|
|
*/ |
50
|
|
|
public function getItemsByTag($tagName) |
51
|
|
|
{ |
52
|
|
|
if (is_string($tagName)) { |
53
|
|
|
$driverResponse = $this->getItem($this->getTagKey($tagName)); |
54
|
|
|
if ($driverResponse->isHit()) { |
55
|
|
|
$items = (array)$driverResponse->get(); |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* getItems() may provides expired item(s) |
59
|
|
|
* themselves provided by a cache of item |
60
|
|
|
* keys based stored the tag item. |
61
|
|
|
* Therefore we pass a filter callback |
62
|
|
|
* to remove the expired Item(s) provided by |
63
|
|
|
* the item keys passed through getItems() |
64
|
|
|
* |
65
|
|
|
* #headache |
66
|
|
|
*/ |
67
|
|
|
return array_filter($this->getItems(array_unique(array_keys($items))), function (ExtendedCacheItemInterface $item) { |
68
|
|
|
return $item->isHit(); |
69
|
|
|
}); |
70
|
|
|
} else { |
71
|
|
|
return []; |
72
|
|
|
} |
73
|
|
|
} else { |
74
|
|
|
throw new InvalidArgumentException('$tagName must be a string'); |
75
|
|
|
} |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @inheritdoc |
80
|
|
|
*/ |
81
|
|
|
public function getItemsByTags(array $tagNames) |
82
|
|
|
{ |
83
|
|
|
$items = []; |
84
|
|
|
foreach (array_unique($tagNames) as $tagName) { |
85
|
|
|
if(is_string($tagName)){ |
86
|
|
|
$items = array_merge($items, $this->getItemsByTag($tagName)); |
87
|
|
|
}else{ |
88
|
|
|
throw new InvalidArgumentException('$tagName must be a a string'); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
return $items; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @inheritdoc |
98
|
|
|
*/ |
99
|
|
|
public function getItemsByTagsAll(array $tagNames) |
100
|
|
|
{ |
101
|
|
|
$items = $this->getItemsByTags($tagNames); |
102
|
|
|
|
103
|
|
|
foreach ($items as $key => $item) { |
104
|
|
|
if (array_diff($tagNames, $item->getTags())) { |
105
|
|
|
unset($items[ $key ]); |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
return $items; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* @inheritdoc |
115
|
|
|
*/ |
116
|
|
|
public function getItemsByTagsAsJsonString(array $tagNames, $option = 0, $depth = 512) |
117
|
|
|
{ |
118
|
|
|
$callback = function (CacheItemInterface $item) { |
119
|
|
|
return $item->get(); |
120
|
|
|
}; |
121
|
|
|
|
122
|
|
|
return json_encode(array_map($callback, array_values($this->getItemsByTags($tagNames))), $option, $depth); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @inheritdoc |
127
|
|
|
*/ |
128
|
|
|
public function deleteItemsByTag($tagName) |
129
|
|
|
{ |
130
|
|
|
if (is_string($tagName)) { |
131
|
|
|
$return = null; |
132
|
|
|
foreach ($this->getItemsByTag($tagName) as $item) { |
133
|
|
|
$result = $this->deleteItem($item->getKey()); |
134
|
|
|
if ($return !== false) { |
135
|
|
|
$return = $result; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
return $return; |
140
|
|
|
} else { |
141
|
|
|
throw new InvalidArgumentException('$tagName must be a string'); |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @inheritdoc |
147
|
|
|
*/ |
148
|
|
View Code Duplication |
public function deleteItemsByTags(array $tagNames) |
|
|
|
|
149
|
|
|
{ |
150
|
|
|
$return = null; |
151
|
|
|
foreach ($tagNames as $tagName) { |
152
|
|
|
$result = $this->deleteItemsByTag($tagName); |
153
|
|
|
if ($return !== false) { |
154
|
|
|
$return = $result; |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
return $return; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* @inheritdoc |
163
|
|
|
*/ |
164
|
|
|
public function deleteItemsByTagsAll(array $tagNames) |
165
|
|
|
{ |
166
|
|
|
$return = null; |
167
|
|
|
$items = $this->getItemsByTagsAll($tagNames); |
168
|
|
|
|
169
|
|
|
foreach ($items as $key => $item) { |
170
|
|
|
$result = $this->deleteItem($item->getKey()); |
171
|
|
|
if ($return !== false) { |
172
|
|
|
$return = $result; |
173
|
|
|
} |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
return $return; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @inheritdoc |
181
|
|
|
*/ |
182
|
|
View Code Duplication |
public function incrementItemsByTag($tagName, $step = 1) |
|
|
|
|
183
|
|
|
{ |
184
|
|
|
if (is_string($tagName) && is_int($step)) { |
185
|
|
|
foreach ($this->getItemsByTag($tagName) as $item) { |
186
|
|
|
$item->increment($step); |
187
|
|
|
$this->saveDeferred($item); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
return $this->commit(); |
191
|
|
|
} else { |
192
|
|
|
throw new InvalidArgumentException('$tagName must be a string and $step an integer'); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @inheritdoc |
198
|
|
|
*/ |
199
|
|
View Code Duplication |
public function incrementItemsByTags(array $tagNames, $step = 1) |
|
|
|
|
200
|
|
|
{ |
201
|
|
|
$return = null; |
202
|
|
|
foreach ($tagNames as $tagName) { |
203
|
|
|
$result = $this->incrementItemsByTag($tagName, $step); |
204
|
|
|
if ($return !== false) { |
205
|
|
|
$return = $result; |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
return $return; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @inheritdoc |
214
|
|
|
*/ |
215
|
|
View Code Duplication |
public function incrementItemsByTagsAll(array $tagNames, $step = 1) |
|
|
|
|
216
|
|
|
{ |
217
|
|
|
if (is_int($step)) { |
218
|
|
|
$items = $this->getItemsByTagsAll($tagNames); |
219
|
|
|
|
220
|
|
|
foreach ($items as $key => $item) { |
221
|
|
|
$item->increment($step); |
222
|
|
|
$this->saveDeferred($item); |
223
|
|
|
} |
224
|
|
|
return $this->commit(); |
225
|
|
|
} else { |
226
|
|
|
throw new InvalidArgumentException('$step must be an integer'); |
227
|
|
|
} |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* @inheritdoc |
232
|
|
|
*/ |
233
|
|
View Code Duplication |
public function decrementItemsByTag($tagName, $step = 1) |
|
|
|
|
234
|
|
|
{ |
235
|
|
|
if (is_string($tagName) && is_int($step)) { |
236
|
|
|
foreach ($this->getItemsByTag($tagName) as $item) { |
237
|
|
|
$item->decrement($step); |
238
|
|
|
$this->saveDeferred($item); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
return $this->commit(); |
242
|
|
|
} else { |
243
|
|
|
throw new InvalidArgumentException('$tagName must be a string and $step an integer'); |
244
|
|
|
} |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* @inheritdoc |
249
|
|
|
*/ |
250
|
|
View Code Duplication |
public function decrementItemsByTags(array $tagNames, $step = 1) |
|
|
|
|
251
|
|
|
{ |
252
|
|
|
$return = null; |
253
|
|
|
foreach ($tagNames as $tagName) { |
254
|
|
|
$result = $this->decrementItemsByTag($tagName, $step); |
255
|
|
|
if ($return !== false) { |
256
|
|
|
$return = $result; |
257
|
|
|
} |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
return $return; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* @inheritdoc |
265
|
|
|
*/ |
266
|
|
View Code Duplication |
public function decrementItemsByTagsAll(array $tagNames, $step = 1) |
|
|
|
|
267
|
|
|
{ |
268
|
|
|
if (is_int($step)) { |
269
|
|
|
$items = $this->getItemsByTagsAll($tagNames); |
270
|
|
|
|
271
|
|
|
foreach ($items as $key => $item) { |
272
|
|
|
$item->decrement($step); |
273
|
|
|
$this->saveDeferred($item); |
274
|
|
|
} |
275
|
|
|
return $this->commit(); |
276
|
|
|
} else { |
277
|
|
|
throw new InvalidArgumentException('$step must be an integer'); |
278
|
|
|
} |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* @inheritdoc |
283
|
|
|
*/ |
284
|
|
View Code Duplication |
public function appendItemsByTag($tagName, $data) |
|
|
|
|
285
|
|
|
{ |
286
|
|
|
if (is_string($tagName)) { |
287
|
|
|
foreach ($this->getItemsByTag($tagName) as $item) { |
288
|
|
|
$item->append($data); |
289
|
|
|
$this->saveDeferred($item); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
return $this->commit(); |
293
|
|
|
} else { |
294
|
|
|
throw new InvalidArgumentException('$tagName must be a string'); |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* @inheritdoc |
300
|
|
|
*/ |
301
|
|
View Code Duplication |
public function appendItemsByTags(array $tagNames, $data) |
|
|
|
|
302
|
|
|
{ |
303
|
|
|
$return = null; |
304
|
|
|
foreach ($tagNames as $tagName) { |
305
|
|
|
$result = $this->appendItemsByTag($tagName, $data); |
306
|
|
|
if ($return !== false) { |
307
|
|
|
$return = $result; |
308
|
|
|
} |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
return $return; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* @inheritdoc |
316
|
|
|
*/ |
317
|
|
|
public function appendItemsByTagsAll(array $tagNames, $data) |
318
|
|
|
{ |
319
|
|
|
if (is_scalar($data)) { |
320
|
|
|
$items = $this->getItemsByTagsAll($tagNames); |
321
|
|
|
|
322
|
|
|
foreach ($items as $key => $item) { |
323
|
|
|
$item->append($data); |
324
|
|
|
$this->saveDeferred($item); |
325
|
|
|
} |
326
|
|
|
return $this->commit(); |
327
|
|
|
} else { |
328
|
|
|
throw new InvalidArgumentException('$data must be scalar'); |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* @inheritdoc |
334
|
|
|
*/ |
335
|
|
View Code Duplication |
public function prependItemsByTag($tagName, $data) |
|
|
|
|
336
|
|
|
{ |
337
|
|
|
if (is_string($tagName)) { |
338
|
|
|
foreach ($this->getItemsByTag($tagName) as $item) { |
339
|
|
|
$item->prepend($data); |
340
|
|
|
$this->saveDeferred($item); |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
return $this->commit(); |
344
|
|
|
} else { |
345
|
|
|
throw new InvalidArgumentException('$tagName must be a string'); |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* @inheritdoc |
351
|
|
|
*/ |
352
|
|
View Code Duplication |
public function prependItemsByTags(array $tagNames, $data) |
|
|
|
|
353
|
|
|
{ |
354
|
|
|
$return = null; |
355
|
|
|
foreach ($tagNames as $tagName) { |
356
|
|
|
$result = $this->decrementItemsByTag($tagName, $data); |
357
|
|
|
if ($return !== false) { |
358
|
|
|
$return = $result; |
359
|
|
|
} |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
return $return; |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* @inheritdoc |
367
|
|
|
*/ |
368
|
|
|
public function prependItemsByTagsAll(array $tagNames, $data) |
369
|
|
|
{ |
370
|
|
|
if (is_scalar($data)) { |
371
|
|
|
$items = $this->getItemsByTagsAll($tagNames); |
372
|
|
|
|
373
|
|
|
foreach ($items as $key => $item) { |
374
|
|
|
$item->prepend($data); |
375
|
|
|
$this->saveDeferred($item); |
376
|
|
|
} |
377
|
|
|
return $this->commit(); |
378
|
|
|
} else { |
379
|
|
|
throw new InvalidArgumentException('$data must be scalar'); |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
385
|
|
|
* @return void |
386
|
|
|
*/ |
387
|
|
|
public function detachItem(CacheItemInterface $item) |
388
|
|
|
{ |
389
|
|
|
if (isset($this->itemInstances[ $item->getKey() ])) { |
390
|
|
|
$this->deregisterItem($item); |
391
|
|
|
} |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* @inheritdoc |
396
|
|
|
*/ |
397
|
|
|
public function detachAllItems() |
398
|
|
|
{ |
399
|
|
|
foreach ($this->itemInstances as $item) { |
400
|
|
|
$this->detachItem($item); |
401
|
|
|
} |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* @inheritdoc |
406
|
|
|
*/ |
407
|
|
|
public function attachItem(CacheItemInterface $item) |
408
|
|
|
{ |
409
|
|
View Code Duplication |
if (isset($this->itemInstances[ $item->getKey() ]) && spl_object_hash($item) !== spl_object_hash($this->itemInstances[ $item->getKey() ])) { |
|
|
|
|
410
|
|
|
throw new \LogicException('The item already exists and cannot be overwritten because the Spl object hash mismatches ! You probably tried to re-attach a detached item which has been already retrieved from cache.'); |
411
|
|
|
} else { |
412
|
|
|
$this->itemInstances[ $item->getKey() ] = $item; |
413
|
|
|
} |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* @internal This method de-register an item from $this->itemInstances |
419
|
|
|
* @param CacheItemInterface|string $item |
420
|
|
|
* @throws \InvalidArgumentException |
421
|
|
|
*/ |
422
|
|
|
protected function deregisterItem($item) |
423
|
|
|
{ |
424
|
|
|
if ($item instanceof CacheItemInterface) { |
425
|
|
|
unset($this->itemInstances[ $item->getKey() ]); |
426
|
|
|
|
427
|
|
|
} else if (is_string($item)) { |
428
|
|
|
unset($this->itemInstances[ $item ]); |
429
|
|
|
} else { |
430
|
|
|
throw new \InvalidArgumentException('Invalid type for $item variable'); |
431
|
|
|
} |
432
|
|
|
if (gc_enabled()) { |
433
|
|
|
gc_collect_cycles(); |
434
|
|
|
} |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* Returns true if the item exists, is attached and the Spl Hash matches |
439
|
|
|
* Returns false if the item exists, is attached and the Spl Hash mismatches |
440
|
|
|
* Returns null if the item does not exists |
441
|
|
|
* |
442
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
443
|
|
|
* @return bool|null |
444
|
|
|
* @throws \LogicException |
445
|
|
|
*/ |
446
|
|
View Code Duplication |
public function isAttached(CacheItemInterface $item) |
|
|
|
|
447
|
|
|
{ |
448
|
|
|
if (isset($this->itemInstances[ $item->getKey() ])) { |
449
|
|
|
return spl_object_hash($item) === spl_object_hash($this->itemInstances[ $item->getKey() ]); |
450
|
|
|
} |
451
|
|
|
return null; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* Set the EventManager instance |
456
|
|
|
* |
457
|
|
|
* @param EventManager $em |
458
|
|
|
*/ |
459
|
|
|
public function setEventManager(EventManager $em) |
460
|
|
|
{ |
461
|
|
|
$this->eventManager = $em; |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* @inheritdoc |
466
|
|
|
*/ |
467
|
|
|
public function saveMultiple(...$items) |
468
|
|
|
{ |
469
|
|
|
if (isset($items[ 0 ]) && is_array($items[ 0 ])) { |
470
|
|
|
foreach ($items[ 0 ] as $item) { |
471
|
|
|
$this->save($item); |
472
|
|
|
} |
473
|
|
|
return true; |
474
|
|
|
} else if (is_array($items)) { |
475
|
|
|
foreach ($items as $item) { |
476
|
|
|
$this->save($item); |
477
|
|
|
} |
478
|
|
|
return true; |
479
|
|
|
} |
480
|
|
|
return false; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Driver-related methods |
485
|
|
|
*/ |
486
|
|
|
|
487
|
|
|
/** |
488
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
489
|
|
|
* @return array [ |
490
|
|
|
* 'd' => 'THE ITEM DATA' |
491
|
|
|
* 't' => 'THE ITEM DATE EXPIRATION' |
492
|
|
|
* 'g' => 'THE ITEM TAGS' |
493
|
|
|
* ] |
494
|
|
|
* |
495
|
|
|
*/ |
496
|
|
|
abstract protected function driverRead(CacheItemInterface $item); |
497
|
|
|
|
498
|
|
|
/** |
499
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
500
|
|
|
* @return mixed |
501
|
|
|
*/ |
502
|
|
|
abstract protected function driverWrite(CacheItemInterface $item); |
503
|
|
|
|
504
|
|
|
/** |
505
|
|
|
* @return bool |
506
|
|
|
*/ |
507
|
|
|
abstract protected function driverClear(); |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* @return bool |
511
|
|
|
*/ |
512
|
|
|
abstract protected function driverConnect(); |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
516
|
|
|
* @return bool |
517
|
|
|
*/ |
518
|
|
|
abstract protected function driverDelete(CacheItemInterface $item); |
519
|
|
|
} |
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.