]> git.mxchange.org Git - friendica.git/blob - src/Core/Cache/Type/APCuCache.php
Restructure Cache to follow new paradigm
[friendica.git] / src / Core / Cache / Type / APCuCache.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
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\Type;
23
24 use Exception;
25 use Friendica\Core\Cache\Enum\Duration;
26 use Friendica\Core\Cache\IMemoryCache;
27 use Friendica\Core\Cache\Type\TraitCompareDelete;
28 use Friendica\Core\Cache\Type\TraitCompareSet;
29 use Friendica\Core\Cache\Enum\Type;
30
31 /**
32  * APCu Cache.
33  */
34 class APCuCache extends BaseCache implements IMemoryCache
35 {
36         use TraitCompareSet;
37         use TraitCompareDelete;
38
39         /**
40          * @throws Exception
41          */
42         public function __construct(string $hostname)
43         {
44                 if (!self::isAvailable()) {
45                         throw new Exception('APCu is not available.');
46                 }
47
48                 parent::__construct($hostname);
49         }
50
51         /**
52          * (@inheritdoc)
53          */
54         public function getAllKeys($prefix = null)
55         {
56                 $ns = $this->getCacheKey($prefix);
57                 $ns = preg_quote($ns, '/');
58
59                 if (class_exists('\APCIterator')) {
60                         $iterator = new \APCIterator('user', '/^' . $ns. '/', APC_ITER_KEY);
61                 } else {
62                         $iterator = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY);
63                 }
64
65                 $keys = [];
66                 foreach ($iterator as $item) {
67                         array_push($keys, $item['key']);
68                 }
69
70                 return $this->getOriginalKeys($keys);
71         }
72
73         /**
74          * (@inheritdoc)
75          */
76         public function get($key)
77         {
78                 $return = null;
79                 $cachekey = $this->getCacheKey($key);
80
81                 $cached = apcu_fetch($cachekey, $success);
82                 if (!$success) {
83                         return null;
84                 }
85
86                 $value = unserialize($cached);
87
88                 // Only return a value if the serialized value is valid.
89                 // We also check if the db entry is a serialized
90                 // boolean 'false' value (which we want to return).
91                 if ($cached === serialize(false) || $value !== false) {
92                         $return = $value;
93                 }
94
95                 return $return;
96         }
97
98         /**
99          * (@inheritdoc)
100          */
101         public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
102         {
103                 $cachekey = $this->getCacheKey($key);
104
105                 $cached = serialize($value);
106
107                 if ($ttl > 0) {
108                         return apcu_store(
109                                 $cachekey,
110                                 $cached,
111                                 $ttl
112                         );
113                 } else {
114                         return apcu_store(
115                                 $cachekey,
116                                 $cached
117                         );
118                 }
119         }
120
121         /**
122          * (@inheritdoc)
123          */
124         public function delete($key)
125         {
126                 $cachekey = $this->getCacheKey($key);
127                 return apcu_delete($cachekey);
128         }
129
130         /**
131          * (@inheritdoc)
132          */
133         public function clear($outdated = true)
134         {
135                 if ($outdated) {
136                         return true;
137                 } else {
138                         $prefix = $this->getPrefix();
139                         $prefix = preg_quote($prefix, '/');
140
141                         if (class_exists('\APCIterator')) {
142                                 $iterator = new \APCIterator('user', '/^' . $prefix . '/', APC_ITER_KEY);
143                         } else {
144                                 $iterator = new \APCUIterator('/^' . $prefix . '/', APC_ITER_KEY);
145                         }
146
147                         return apcu_delete($iterator);
148                 }
149         }
150
151         /**
152          * (@inheritdoc)
153          */
154         public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
155         {
156                 $cachekey = $this->getCacheKey($key);
157                 $cached = serialize($value);
158
159                 return apcu_add($cachekey, $cached);
160         }
161
162         public static function isAvailable()
163         {
164                 if (!extension_loaded('apcu')) {
165                         return false;
166                 } elseif (!ini_get('apc.enabled') && !ini_get('apc.enable_cli')) {
167                         return false;
168                 } elseif (
169                         version_compare(phpversion('apc') ?: '0.0.0', '4.0.6') === -1 &&
170                         version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0') === -1
171                 ) {
172                         return false;
173                 }
174
175                 return true;
176         }
177
178         /**
179          * {@inheritDoc}
180          */
181         public function getName()
182         {
183                 return Type::APCU;
184         }
185 }