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