ElggMemcache::delete()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Memcache wrapper class.
4
 *
5
 * @package    Elgg.Core
6
 * @subpackage Memcache
7
 */
8
class ElggMemcache extends \ElggSharedMemoryCache {
9
	/**
10
	 * Global Elgg configuration
11
	 * 
12
	 * @var \stdClass
13
	 */
14
	private $CONFIG;
15
16
	/**
17
	 * Minimum version of memcached needed to run
18
	 *
19
	 */
20
	private static $MINSERVERVERSION = '1.1.12';
21
22
	/**
23
	 * Memcache object
24
	 */
25
	private $memcache;
26
27
	/**
28
	 * Expiry of saved items (default timeout after a day to prevent anything getting too stale)
29
	 */
30
	private $expires = 86400;
31
32
	/**
33
	 * The version of memcache running
34
	 */
35
	private $version = 0;
36
37
	/**
38
	 * Connect to memcache.
39
	 *
40
	 * @param string $namespace The namespace for this cache to write to -
41
	 * note, namespaces of the same name are shared!
42
	 *
43
	 * @throws ConfigurationException
44
	 */
45
	public function __construct($namespace = 'default') {
46
		global $CONFIG;
47
		$this->CONFIG = $CONFIG;
48
49
		$this->setNamespace($namespace);
50
51
		// Do we have memcache?
52
		if (!class_exists('Memcache')) {
53
			throw new \ConfigurationException('PHP memcache module not installed, you must install php5-memcache');
54
		}
55
56
		// Create memcache object
57
		$this->memcache	= new Memcache;
58
59
		// Now add servers
60
		if (!$this->CONFIG->memcache_servers) {
61
			throw new \ConfigurationException('No memcache servers defined, please populate the $this->CONFIG->memcache_servers variable');
62
		}
63
64
		if (is_callable(array($this->memcache, 'addServer'))) {
65
			foreach ($this->CONFIG->memcache_servers as $server) {
66
				if (is_array($server)) {
67
					$this->memcache->addServer(
68
						$server[0],
69
						isset($server[1]) ? $server[1] : 11211,
70
						isset($server[2]) ? $server[2] : false,
71
						isset($server[3]) ? $server[3] : 1,
72
						isset($server[4]) ? $server[4] : 1,
73
						isset($server[5]) ? $server[5] : 15,
74
						isset($server[6]) ? $server[6] : true
75
					);
76
77
				} else {
78
					$this->memcache->addServer($server, 11211);
79
				}
80
			}
81
		} else {
82
			// don't use _elgg_services()->translator->translate() here because most of the config hasn't been loaded yet
83
			// and it caches the language, which is hard coded in $this->CONFIG->language as en.
84
			// overriding it with real values later has no effect because it's already cached.
85
			_elgg_services()->logger->error("This version of the PHP memcache API doesn't support multiple servers.");
86
87
			$server = $this->CONFIG->memcache_servers[0];
88
			if (is_array($server)) {
89
				$this->memcache->connect($server[0], $server[1]);
90
			} else {
91
				$this->memcache->addServer($server, 11211);
92
			}
93
		}
94
95
		// Get version
96
		$this->version = $this->memcache->getVersion();
0 ignored issues
show
Documentation Bug introduced by
The property $version was declared of type integer, but $this->memcache->getVersion() is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
97
		if (version_compare($this->version, \ElggMemcache::$MINSERVERVERSION, '<')) {
98
			$msg = vsprintf('Memcache needs at least version %s to run, you are running %s',
99
				array(\ElggMemcache::$MINSERVERVERSION,
100
				$this->version
101
			));
102
103
			throw new \ConfigurationException($msg);
104
		}
105
106
		// Set some defaults
107
		if (isset($this->CONFIG->memcache_expires)) {
108
			$this->expires = $this->CONFIG->memcache_expires;
109
		}
110
		
111
		// make sure memcache is reset
112
		_elgg_services()->events->registerHandler('cache:flush', 'system', array($this, 'clear'));
113
	}
114
115
	/**
116
	 * Set the default expiry.
117
	 *
118
	 * @param int $expires The lifetime as a unix timestamp or time from now. Defaults forever.
119
	 *
120
	 * @return void
121
	 */
122
	public function setDefaultExpiry($expires = 0) {
123
		$this->expires = $expires;
124
	}
125
126
	/**
127
	 * Combine a key with the namespace.
128
	 * Memcache can only accept <250 char key. If the given key is too long it is shortened.
129
	 *
130
	 * @param string $key The key
131
	 *
132
	 * @return string The new key.
133
	 */
134
	private function makeMemcacheKey($key) {
135
		$prefix = $this->getNamespace() . ":";
136
137
		if (strlen($prefix . $key) > 250) {
138
			$key = md5($key);
139
		}
140
141
		return $prefix . $key;
142
	}
143
144
	/**
145
	 * Saves a name and value to the cache
146
	 *
147
	 * @param string  $key     Name
148
	 * @param string  $data    Value
149
	 * @param integer $expires Expires (in seconds)
150
	 *
151
	 * @return bool
152
	 */
153
	public function save($key, $data, $expires = null) {
154
		$key = $this->makeMemcacheKey($key);
155
156
		if ($expires === null) {
157
			$expires = $this->expires;
158
		}
159
160
		$result = $this->memcache->set($key, $data, null, $expires);
161 View Code Duplication
		if ($result === false) {
162
			_elgg_services()->logger->error("MEMCACHE: SAVE FAIL $key");
163
		} else {
164
			_elgg_services()->logger->info("MEMCACHE: SAVE SUCCESS $key");
165
		}
166
167
		return $result;
168
	}
169
170
	/**
171
	 * Retrieves data.
172
	 *
173
	 * @param string $key    Name of data to retrieve
174
	 * @param int    $offset Offset
175
	 * @param int    $limit  Limit
176
	 *
177
	 * @return mixed
178
	 */
179
	public function load($key, $offset = 0, $limit = null) {
180
		$key = $this->makeMemcacheKey($key);
181
182
		$result = $this->memcache->get($key);
183 View Code Duplication
		if ($result === false) {
184
			_elgg_services()->logger->info("MEMCACHE: LOAD MISS $key");
185
		} else {
186
			_elgg_services()->logger->info("MEMCACHE: LOAD HIT $key");
187
		}
188
189
		return $result;
190
	}
191
192
	/**
193
	 * Delete data
194
	 *
195
	 * @param string $key Name of data
196
	 *
197
	 * @return bool
198
	 */
199
	public function delete($key) {
200
		$key = $this->makeMemcacheKey($key);
201
202
		return $this->memcache->delete($key, 0);
203
	}
204
205
	/**
206
	 * Clears the entire cache
207
	 *
208
	 * @return true
209
	 */
210
	public function clear() {
211
		$result = $this->memcache->flush();
212
		if ($result === false) {
213
			_elgg_services()->logger->info("MEMCACHE: failed to flush {$this->getNamespace()}");
214
		} else {
215
			sleep(1); // needed because http://php.net/manual/en/memcache.flush.php#81420
216
			
217
			_elgg_services()->logger->info("MEMCACHE: flushed {$this->getNamespace()}");
218
		}
219
		
220
		return $result;
221
222
		// @todo Namespaces as in #532
223
	}
224
}
225