MemcacheImplementation   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 60
dl 0
loc 162
rs 10
c 0
b 0
f 0
wmc 24

8 Methods

Rating   Name   Duplication   Size   Complexity  
A isSupported() 0 10 4
A getData() 0 11 2
B connect() 0 44 7
A putData() 0 5 2
A getVersion() 0 12 3
A cleanCache() 0 5 1
A quit() 0 3 1
A cacheSettings() 0 24 4
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
It seems like $port can also be of type string; however, parameter $port of MemcachePool::connect() 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 ignore-type  annotation

92
				$connected = $this->memcache->connect($host, /** @scrutinizer ignore-type */ $port);
Loading history...
93
94
			else
95
				$connected = $this->memcache->pconnect($host, $port);
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

95
				$connected = $this->memcache->pconnect($host, /** @scrutinizer ignore-type */ $port);
Loading history...
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
?>