Commit | Line | Data |
---|---|---|
5876627a TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
5876627a | 5 | | | |
bc77d7c0 TO |
6 | | This work is published under the GNU AGPLv3 license with some | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
5876627a TO |
9 | +--------------------------------------------------------------------+ |
10 | */ | |
11 | ||
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
5876627a TO |
16 | */ |
17 | ||
18 | /** | |
19 | * Class CRM_Utils_Cache_ArrayDecorator | |
20 | * | |
21 | * This creates a two-tier cache-hierarchy: a thread-local, array-based cache | |
22 | * combined with some third-party cache driver. | |
23 | * | |
24 | * Ex: $cache = new CRM_Utils_Cache_ArrayDecorator(new CRM_Utils_Cache_Redis(...)); | |
25 | */ | |
26 | class CRM_Utils_Cache_ArrayDecorator implements CRM_Utils_Cache_Interface { | |
27 | ||
6714d8d2 SL |
28 | // TODO Consider native implementation. |
29 | use CRM_Utils_Cache_NaiveMultipleTrait; | |
5876627a TO |
30 | |
31 | /** | |
32 | * @var int | |
33 | * Default time-to-live (seconds) for cache items that don't have a TTL. | |
34 | */ | |
35 | protected $defaultTimeout; | |
36 | ||
37 | /** | |
38 | * @var CRM_Utils_Cache_Interface | |
39 | */ | |
40 | private $delegate; | |
41 | ||
42 | /** | |
43 | * @var array | |
44 | * Array(string $cacheKey => mixed $cacheValue). | |
45 | */ | |
46 | private $values = []; | |
47 | ||
48 | /** | |
49 | * @var array | |
50 | * Array(string $cacheKey => int $expirationTime). | |
51 | */ | |
52 | private $expires = []; | |
53 | ||
54 | /** | |
55 | * CRM_Utils_Cache_ArrayDecorator constructor. | |
56 | * @param \CRM_Utils_Cache_Interface $delegate | |
57 | * @param int $defaultTimeout | |
58 | * Default number of seconds each cache-item should endure. | |
59 | */ | |
60 | public function __construct(\CRM_Utils_Cache_Interface $delegate, $defaultTimeout = 3600) { | |
61 | $this->defaultTimeout = $defaultTimeout; | |
62 | $this->delegate = $delegate; | |
63 | } | |
64 | ||
65 | public function set($key, $value, $ttl = NULL) { | |
66 | if (is_int($ttl) && $ttl <= 0) { | |
67 | return $this->delete($key); | |
68 | } | |
69 | ||
70 | $expiresAt = CRM_Utils_Date::convertCacheTtlToExpires($ttl, $this->defaultTimeout); | |
71 | if ($this->delegate->set($key, [$expiresAt, $value], $ttl)) { | |
72 | $this->values[$key] = $this->reobjectify($value); | |
73 | $this->expires[$key] = $expiresAt; | |
74 | return TRUE; | |
75 | } | |
76 | else { | |
77 | return FALSE; | |
78 | } | |
79 | } | |
80 | ||
81 | public function get($key, $default = NULL) { | |
8a8cbada | 82 | CRM_Utils_Cache::assertValidKey($key); |
5876627a TO |
83 | if (array_key_exists($key, $this->values) && $this->expires[$key] > CRM_Utils_Time::getTimeRaw()) { |
84 | return $this->reobjectify($this->values[$key]); | |
85 | } | |
86 | ||
87 | $nack = CRM_Utils_Cache::nack(); | |
88 | $value = $this->delegate->get($key, $nack); | |
89 | if ($value === $nack) { | |
90 | return $default; | |
91 | } | |
92 | ||
93 | $this->expires[$key] = $value[0]; | |
94 | $this->values[$key] = $value[1]; | |
95 | return $this->reobjectify($this->values[$key]); | |
96 | } | |
97 | ||
98 | public function delete($key) { | |
8a8cbada | 99 | CRM_Utils_Cache::assertValidKey($key); |
5876627a TO |
100 | unset($this->values[$key]); |
101 | unset($this->expires[$key]); | |
102 | return $this->delegate->delete($key); | |
103 | } | |
104 | ||
105 | public function flush() { | |
106 | return $this->clear(); | |
107 | } | |
108 | ||
109 | public function clear() { | |
110 | $this->values = []; | |
111 | $this->expires = []; | |
112 | return $this->delegate->clear(); | |
113 | } | |
114 | ||
115 | public function has($key) { | |
8a8cbada | 116 | CRM_Utils_Cache::assertValidKey($key); |
5876627a TO |
117 | if (array_key_exists($key, $this->values) && $this->expires[$key] > CRM_Utils_Time::getTimeRaw()) { |
118 | return TRUE; | |
119 | } | |
120 | return $this->delegate->has($key); | |
121 | } | |
122 | ||
123 | private function reobjectify($value) { | |
124 | return is_object($value) ? unserialize(serialize($value)) : $value; | |
125 | } | |
126 | ||
127 | } |