Passed
Push — release-2.1 ( f28109...493a4c )
by Mathias
06:40
created

MemcachedImplementation::addServers()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 3 Features 0
Metric Value
cc 6
eloc 11
c 3
b 3
f 0
nc 7
nop 0
dl 0
loc 23
rs 9.2222
1
<?php
2
3
/**
4
 * Simple Machines Forum (SMF)
5
 *
6
 * @package SMF
7
 * @author Simple Machines https://www.simplemachines.org
8
 * @copyright 2020 Simple Machines and individual contributors
9
 * @license https://www.simplemachines.org/about/smf/license.php BSD
10
 *
11
 * @version 2.1 RC3
12
 */
13
14
namespace SMF\Cache\APIs;
15
16
use Memcached;
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 MemcachedImplementation extends CacheApi implements CacheApiInterface
29
{
30
	const CLASS_KEY = 'cache_memcached';
31
32
	/** @var Memcached The memcache instance. */
33
	private $memcached = null;
34
35
	/** @var string[] */
36
	private $servers;
37
38
	/**
39
	 * {@inheritDoc}
40
	 */
41
	public function __construct()
42
	{
43
		global $cache_memcached;
44
45
		$this->servers = array_map(
46
			function($server)
47
			{
48
				if (strpos($server, '/') !== false)
49
					return array($server, 0);
50
51
				else
52
					return array($server, isset($server[1]) ? $server[1] : 11211);
53
			},
54
			explode(',', $cache_memcached)
55
		);
56
57
		parent::__construct();
58
	}
59
60
	/**
61
	 * {@inheritDoc}
62
	 */
63
	public function isSupported($test = false)
64
	{
65
		global $cache_memcached;
66
67
		$supported = class_exists('Memcached');
68
69
		if ($test)
70
			return $supported;
71
72
		return parent::isSupported() && $supported && !empty($cache_memcached);
73
	}
74
75
	/**
76
	 * {@inheritDoc}
77
	 */
78
	public function connect()
79
	{
80
		$this->memcached = new Memcached;
81
82
		return $this->addServers();
83
	}
84
85
	/**
86
	 * Add memcached servers.
87
	 *
88
	 * Don't add servers if they already exist. Ideal for persistent connections.
89
	 *
90
	 * @return bool True if there are servers in the daemon, false if not.
91
	 */
92
	protected function addServers()
93
	{
94
		$currentServers = $this->memcached->getServerList();
95
		$retVal = !empty($currentServers);
96
		foreach ($this->servers as $server)
97
		{
98
			// Figure out if we have this server or not
99
			$foundServer = false;
100
			foreach ($currentServers as $currentServer)
101
			{
102
				if ($server[0] == $currentServer['host'] && $server[1] == $currentServer['port'])
103
				{
104
					$foundServer = true;
105
					break;
106
				}
107
			}
108
109
			// Found it?
110
			if (empty($foundServer))
111
				$retVal |= $this->memcached->addServer($server[0], $server[1]);
112
		}
113
114
		return $retVal;
115
	}
116
117
	/**
118
	 * {@inheritDoc}
119
	 */
120
	public function getData($key, $ttl = null)
121
	{
122
		$key = $this->prefix . strtr($key, ':/', '-_');
123
124
		$value = $this->memcached->get($key);
125
126
		// $value should return either data or false (from failure, key not found or empty array).
127
		if ($value === false)
128
			return null;
129
130
		return $value;
131
	}
132
133
	/**
134
	 * {@inheritDoc}
135
	 */
136
	public function putData($key, $value, $ttl = null)
137
	{
138
		$key = $this->prefix . strtr($key, ':/', '-_');
139
140
		return $this->memcached->set($key, $value, $ttl !== null ? $ttl : $this->ttl);
141
	}
142
143
	/**
144
	 * {@inheritDoc}
145
	 */
146
	public function cleanCache($type = '')
147
	{
148
		$this->invalidateCache();
149
150
		// Memcached accepts a delay parameter, always use 0 (instant).
151
		return $this->memcached->flush(0);
152
	}
153
154
	/**
155
	 * {@inheritDoc}
156
	 */
157
	public function quit()
158
	{
159
		return $this->memcached->quit();
160
	}
161
162
	/**
163
	 * {@inheritDoc}
164
	 */
165
	public function cacheSettings(array &$config_vars)
166
	{
167
		global $context, $txt;
168
169
		$class_name = $this->getImplementationClassKeyName();
170
		$class_name_txt_key = strtolower($class_name);
171
172
		$config_vars[] = $txt['cache_'. $class_name_txt_key .'_settings'];
173
		$config_vars[] = array(
174
			self::CLASS_KEY,
175
			$txt['cache_'. $class_name_txt_key .'_servers'],
176
			'file',
177
			'text',
178
			0,
179
			'cache_'. $class_name_txt_key,
180
			'subtext' => $txt['cache_'. $class_name_txt_key .'_servers_subtext']);
181
182
		if (!isset($context['settings_post_javascript']))
183
			$context['settings_post_javascript'] = '';
184
185
		$context['settings_post_javascript'] .= '
186
			$("#cache_accelerator").change(function (e) {
187
				var cache_type = e.currentTarget.value;
188
				$("#'. self::CLASS_KEY .'").prop("disabled", cache_type != "'. $class_name .'");
189
			});';
190
	}
191
192
	/**
193
	 * {@inheritDoc}
194
	 */
195
	public function getVersion()
196
	{
197
		if (is_object($this->memcached))
198
			return false;
199
200
		// This gets called in Subs-Admin getServerVersions when loading up support information.  If we can't get a connection, return nothing.
201
		$result = $this->memcached->getVersion();
202
203
		if (!empty($result))
204
			return current($result);
205
206
		return false;
207
	}
208
}
209
210
?>