Merge pull request #14987 from civicrm/5.16
[civicrm-core.git] / CRM / Utils / Cache / ArrayDecorator.php
CommitLineData
5876627a
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28/**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2019
32 */
33
34/**
35 * Class CRM_Utils_Cache_ArrayDecorator
36 *
37 * This creates a two-tier cache-hierarchy: a thread-local, array-based cache
38 * combined with some third-party cache driver.
39 *
40 * Ex: $cache = new CRM_Utils_Cache_ArrayDecorator(new CRM_Utils_Cache_Redis(...));
41 */
42class CRM_Utils_Cache_ArrayDecorator implements CRM_Utils_Cache_Interface {
43
6714d8d2
SL
44 // TODO Consider native implementation.
45 use CRM_Utils_Cache_NaiveMultipleTrait;
5876627a
TO
46
47 /**
48 * @var int
49 * Default time-to-live (seconds) for cache items that don't have a TTL.
50 */
51 protected $defaultTimeout;
52
53 /**
54 * @var CRM_Utils_Cache_Interface
55 */
56 private $delegate;
57
58 /**
59 * @var array
60 * Array(string $cacheKey => mixed $cacheValue).
61 */
62 private $values = [];
63
64 /**
65 * @var array
66 * Array(string $cacheKey => int $expirationTime).
67 */
68 private $expires = [];
69
70 /**
71 * CRM_Utils_Cache_ArrayDecorator constructor.
72 * @param \CRM_Utils_Cache_Interface $delegate
73 * @param int $defaultTimeout
74 * Default number of seconds each cache-item should endure.
75 */
76 public function __construct(\CRM_Utils_Cache_Interface $delegate, $defaultTimeout = 3600) {
77 $this->defaultTimeout = $defaultTimeout;
78 $this->delegate = $delegate;
79 }
80
81 public function set($key, $value, $ttl = NULL) {
82 if (is_int($ttl) && $ttl <= 0) {
83 return $this->delete($key);
84 }
85
86 $expiresAt = CRM_Utils_Date::convertCacheTtlToExpires($ttl, $this->defaultTimeout);
87 if ($this->delegate->set($key, [$expiresAt, $value], $ttl)) {
88 $this->values[$key] = $this->reobjectify($value);
89 $this->expires[$key] = $expiresAt;
90 return TRUE;
91 }
92 else {
93 return FALSE;
94 }
95 }
96
97 public function get($key, $default = NULL) {
8a8cbada 98 CRM_Utils_Cache::assertValidKey($key);
5876627a
TO
99 if (array_key_exists($key, $this->values) && $this->expires[$key] > CRM_Utils_Time::getTimeRaw()) {
100 return $this->reobjectify($this->values[$key]);
101 }
102
103 $nack = CRM_Utils_Cache::nack();
104 $value = $this->delegate->get($key, $nack);
105 if ($value === $nack) {
106 return $default;
107 }
108
109 $this->expires[$key] = $value[0];
110 $this->values[$key] = $value[1];
111 return $this->reobjectify($this->values[$key]);
112 }
113
114 public function delete($key) {
8a8cbada 115 CRM_Utils_Cache::assertValidKey($key);
5876627a
TO
116 unset($this->values[$key]);
117 unset($this->expires[$key]);
118 return $this->delegate->delete($key);
119 }
120
121 public function flush() {
122 return $this->clear();
123 }
124
125 public function clear() {
126 $this->values = [];
127 $this->expires = [];
128 return $this->delegate->clear();
129 }
130
131 public function has($key) {
8a8cbada 132 CRM_Utils_Cache::assertValidKey($key);
5876627a
TO
133 if (array_key_exists($key, $this->values) && $this->expires[$key] > CRM_Utils_Time::getTimeRaw()) {
134 return TRUE;
135 }
136 return $this->delegate->has($key);
137 }
138
139 private function reobjectify($value) {
140 return is_object($value) ? unserialize(serialize($value)) : $value;
141 }
142
143}