]> git.mxchange.org Git - friendica.git/blob - src/Core/Cache/APCuCache.php
Merge pull request #8996 from MrPetovan/bug/8995-profile-contacts-is-owner
[friendica.git] / src / Core / Cache / APCuCache.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2020, Friendica
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Core\Cache;
23
24 use Exception;
25 use Friendica\Core\BaseCache;
26
27 /**
28  * APCu Cache.
29  */
30 class APCuCache extends BaseCache implements IMemoryCache
31 {
32         use TraitCompareSet;
33         use TraitCompareDelete;
34
35         /**
36          * @throws Exception
37          */
38         public function __construct(string $hostname)
39         {
40                 if (!self::isAvailable()) {
41                         throw new Exception('APCu is not available.');
42                 }
43
44                 parent::__construct($hostname);
45         }
46
47         /**
48          * (@inheritdoc)
49          */
50         public function getAllKeys($prefix = null)
51         {
52                 $ns = $this->getCacheKey($prefix);
53                 $ns = preg_quote($ns, '/');
54
55                 if (class_exists('\APCIterator')) {
56                         $iterator = new \APCIterator('user', '/^' . $ns. '/', APC_ITER_KEY);
57                 } else {
58                         $iterator = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY);
59                 }
60
61                 $keys = [];
62                 foreach ($iterator as $item) {
63                         array_push($keys, $item['key']);
64                 }
65
66                 return $this->getOriginalKeys($keys);
67         }
68
69         /**
70          * (@inheritdoc)
71          */
72         public function get($key)
73         {
74                 $return = null;
75                 $cachekey = $this->getCacheKey($key);
76
77                 $cached = apcu_fetch($cachekey, $success);
78                 if (!$success) {
79                         return null;
80                 }
81
82                 $value = unserialize($cached);
83
84                 // Only return a value if the serialized value is valid.
85                 // We also check if the db entry is a serialized
86                 // boolean 'false' value (which we want to return).
87                 if ($cached === serialize(false) || $value !== false) {
88                         $return = $value;
89                 }
90
91                 return $return;
92         }
93
94         /**
95          * (@inheritdoc)
96          */
97         public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
98         {
99                 $cachekey = $this->getCacheKey($key);
100
101                 $cached = serialize($value);
102
103                 if ($ttl > 0) {
104                         return apcu_store(
105                                 $cachekey,
106                                 $cached,
107                                 $ttl
108                         );
109                 } else {
110                         return apcu_store(
111                                 $cachekey,
112                                 $cached
113                         );
114                 }
115         }
116
117         /**
118          * (@inheritdoc)
119          */
120         public function delete($key)
121         {
122                 $cachekey = $this->getCacheKey($key);
123                 return apcu_delete($cachekey);
124         }
125
126         /**
127          * (@inheritdoc)
128          */
129         public function clear($outdated = true)
130         {
131                 if ($outdated) {
132                         return true;
133                 } else {
134                         $prefix = $this->getPrefix();
135                         $prefix = preg_quote($prefix, '/');
136
137                         if (class_exists('\APCIterator')) {
138                                 $iterator = new \APCIterator('user', '/^' . $prefix . '/', APC_ITER_KEY);
139                         } else {
140                                 $iterator = new \APCUIterator('/^' . $prefix . '/', APC_ITER_KEY);
141                         }
142
143                         return apcu_delete($iterator);
144                 }
145         }
146
147         /**
148          * (@inheritdoc)
149          */
150         public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
151         {
152                 $cachekey = $this->getCacheKey($key);
153                 $cached = serialize($value);
154
155                 return apcu_add($cachekey, $cached);
156         }
157
158         public static function isAvailable()
159         {
160                 if (!extension_loaded('apcu')) {
161                         return false;
162                 } elseif (!ini_get('apc.enabled') && !ini_get('apc.enable_cli')) {
163                         return false;
164                 } elseif (
165                         version_compare(phpversion('apc') ?: '0.0.0', '4.0.6') === -1 &&
166                         version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0') === -1
167                 ) {
168                         return false;
169                 }
170
171                 return true;
172         }
173
174         /**
175          * {@inheritDoc}
176          */
177         public function getName()
178         {
179                 return Type::APCU;
180         }
181 }