1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * Simple Machines Forum (SMF) |
||||
5 | * |
||||
6 | * @package SMF |
||||
7 | * @author Simple Machines https://www.simplemachines.org |
||||
8 | * @copyright 2022 Simple Machines and individual contributors |
||||
9 | * @license https://www.simplemachines.org/about/smf/license.php BSD |
||||
10 | * |
||||
11 | * @version 2.1.2 |
||||
12 | */ |
||||
13 | |||||
14 | namespace SMF\Cache\APIs; |
||||
15 | |||||
16 | use Memcache; |
||||
17 | use SMF\Cache\CacheApi; |
||||
18 | use SMF\Cache\CacheApiInterface; |
||||
19 | |||||
20 | if (!defined('SMF')) |
||||
21 | die('No direct access...'); |
||||
22 | |||||
23 | /** |
||||
24 | * Our Cache API class |
||||
25 | * |
||||
26 | * @package CacheAPI |
||||
27 | */ |
||||
28 | class MemcacheImplementation extends CacheApi implements CacheApiInterface |
||||
29 | { |
||||
30 | const CLASS_KEY = 'cache_memcached'; |
||||
31 | |||||
32 | /** |
||||
33 | * @var Memcache The memcache instance. |
||||
34 | */ |
||||
35 | private $memcache = null; |
||||
36 | |||||
37 | /** |
||||
38 | * {@inheritDoc} |
||||
39 | */ |
||||
40 | public function isSupported($test = false) |
||||
41 | { |
||||
42 | global $cache_memcached; |
||||
43 | |||||
44 | $supported = class_exists('Memcache'); |
||||
45 | |||||
46 | if ($test) |
||||
47 | return $supported; |
||||
48 | |||||
49 | return parent::isSupported() && $supported && !empty($cache_memcached); |
||||
50 | } |
||||
51 | |||||
52 | /** |
||||
53 | * {@inheritDoc} |
||||
54 | */ |
||||
55 | public function connect() |
||||
56 | { |
||||
57 | global $db_persist, $cache_memcached; |
||||
58 | |||||
59 | $this->memcache = new Memcache(); |
||||
60 | |||||
61 | $servers = explode(',', $cache_memcached); |
||||
62 | $port = 0; |
||||
63 | |||||
64 | // Don't try more times than we have servers! |
||||
65 | $connected = false; |
||||
66 | $level = 0; |
||||
67 | |||||
68 | // We should keep trying if a server times out, but only for the amount of servers we have. |
||||
69 | while (!$connected && $level < count($servers)) |
||||
70 | { |
||||
71 | ++$level; |
||||
72 | |||||
73 | $server = trim($servers[array_rand($servers)]); |
||||
74 | |||||
75 | // No server, can't connect to this. |
||||
76 | if (empty($server)) |
||||
77 | continue; |
||||
78 | |||||
79 | // Normal host names do not contain slashes, while e.g. unix sockets do. Assume alternative transport pipe with port 0. |
||||
80 | if (strpos($server, '/') !== false) |
||||
81 | $host = $server; |
||||
82 | |||||
83 | else |
||||
84 | { |
||||
85 | $server = explode(':', $server); |
||||
86 | $host = $server[0]; |
||||
87 | $port = isset($server[1]) ? $server[1] : 11211; |
||||
88 | } |
||||
89 | |||||
90 | // Don't wait too long: yes, we want the server, but we might be able to run the query faster! |
||||
91 | if (empty($db_persist)) |
||||
92 | $connected = $this->memcache->connect($host, $port); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
93 | |||||
94 | else |
||||
95 | $connected = $this->memcache->pconnect($host, $port); |
||||
0 ignored issues
–
show
It seems like
$port can also be of type string ; however, parameter $port of Memcache::pconnect() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
96 | } |
||||
97 | |||||
98 | return $connected; |
||||
99 | } |
||||
100 | |||||
101 | /** |
||||
102 | * {@inheritDoc} |
||||
103 | */ |
||||
104 | public function getData($key, $ttl = null) |
||||
105 | { |
||||
106 | $key = $this->prefix . strtr($key, ':/', '-_'); |
||||
107 | |||||
108 | $value = $this->memcache->get($key); |
||||
109 | |||||
110 | // $value should return either data or false (from failure, key not found or empty array). |
||||
111 | if ($value === false) |
||||
112 | return null; |
||||
113 | |||||
114 | return $value; |
||||
115 | } |
||||
116 | |||||
117 | /** |
||||
118 | * {@inheritDoc} |
||||
119 | */ |
||||
120 | public function putData($key, $value, $ttl = null) |
||||
121 | { |
||||
122 | $key = $this->prefix . strtr($key, ':/', '-_'); |
||||
123 | |||||
124 | return $this->memcache->set($key, $value, 0, $ttl !== null ? $ttl : $this->ttl); |
||||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * {@inheritDoc} |
||||
129 | */ |
||||
130 | public function quit() |
||||
131 | { |
||||
132 | return $this->memcache->close(); |
||||
133 | } |
||||
134 | |||||
135 | /** |
||||
136 | * {@inheritDoc} |
||||
137 | */ |
||||
138 | public function cleanCache($type = '') |
||||
139 | { |
||||
140 | $this->invalidateCache(); |
||||
141 | |||||
142 | return $this->memcache->flush(); |
||||
143 | } |
||||
144 | |||||
145 | /** |
||||
146 | * {@inheritDoc} |
||||
147 | */ |
||||
148 | public function cacheSettings(array &$config_vars) |
||||
149 | { |
||||
150 | global $context, $txt; |
||||
151 | |||||
152 | if (!in_array($txt[self::CLASS_KEY .'_settings'], $config_vars)) |
||||
153 | { |
||||
154 | $config_vars[] = $txt[self::CLASS_KEY .'_settings']; |
||||
155 | $config_vars[] = array( |
||||
156 | self::CLASS_KEY, |
||||
157 | $txt[self::CLASS_KEY .'_servers'], |
||||
158 | 'file', |
||||
159 | 'text', |
||||
160 | 0, |
||||
161 | 'subtext' => $txt[self::CLASS_KEY .'_servers_subtext']); |
||||
162 | } |
||||
163 | |||||
164 | if (!isset($context['settings_post_javascript'])) |
||||
165 | $context['settings_post_javascript'] = ''; |
||||
166 | |||||
167 | if (empty($context['settings_not_writable'])) |
||||
168 | $context['settings_post_javascript'] .= ' |
||||
169 | $("#cache_accelerator").change(function (e) { |
||||
170 | var cache_type = e.currentTarget.value; |
||||
171 | $("#'. self::CLASS_KEY .'").prop("disabled", cache_type != "MemcacheImplementation" && cache_type != "MemcachedImplementation"); |
||||
172 | });'; |
||||
173 | } |
||||
174 | |||||
175 | /** |
||||
176 | * {@inheritDoc} |
||||
177 | */ |
||||
178 | public function getVersion() |
||||
179 | { |
||||
180 | if (!is_object($this->memcache)) |
||||
181 | return false; |
||||
182 | |||||
183 | // This gets called in Subs-Admin getServerVersions when loading up support information. If we can't get a connection, return nothing. |
||||
184 | $result = $this->memcache->getVersion(); |
||||
185 | |||||
186 | if (!empty($result)) |
||||
187 | return $result; |
||||
188 | |||||
189 | return false; |
||||
190 | } |
||||
191 | } |
||||
192 | |||||
193 | ?> |