Subversion-Projekte lars-tiefland.ci

Revision

Revision 2257 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
68 lars 1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
2414 lars 9
 * Copyright (c) 2014 - 2019, British Columbia Institute of Technology
68 lars 10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
2414 lars 32
 * @copyright	Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
33
 * @license	https://opensource.org/licenses/MIT	MIT License
68 lars 34
 * @link	https://codeigniter.com
35
 * @since	Version 3.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
 
40
/**
41
 * CodeIgniter Redis Caching Class
42
 *
43
 * @package	   CodeIgniter
44
 * @subpackage Libraries
45
 * @category   Core
46
 * @author	   Anton Lindqvist <anton@qvister.se>
47
 * @link
48
 */
49
class CI_Cache_redis extends CI_Driver
50
{
51
	/**
52
	 * Default config
53
	 *
54
	 * @static
55
	 * @var	array
56
	 */
57
	protected static $_default_config = array(
58
		'socket_type' => 'tcp',
59
		'host' => '127.0.0.1',
60
		'password' => NULL,
61
		'port' => 6379,
62
		'timeout' => 0
63
	);
64
 
65
	/**
66
	 * Redis connection
67
	 *
68
	 * @var	Redis
69
	 */
70
	protected $_redis;
71
 
72
	/**
73
	 * An internal cache for storing keys of serialized values.
74
	 *
75
	 * @var	array
76
	 */
77
	protected $_serialized = array();
78
 
2414 lars 79
	/**
80
	 * del()/delete() method name depending on phpRedis version
81
	 *
82
	 * @var	string
83
	 */
84
	protected static $_delete_name;
85
 
68 lars 86
	// ------------------------------------------------------------------------
87
 
88
	/**
89
	 * Class constructor
90
	 *
91
	 * Setup Redis
92
	 *
93
	 * Loads Redis config file if present. Will halt execution
94
	 * if a Redis connection can't be established.
95
	 *
96
	 * @return	void
97
	 * @see		Redis::connect()
98
	 */
99
	public function __construct()
100
	{
101
		if ( ! $this->is_supported())
102
		{
103
			log_message('error', 'Cache: Failed to create Redis object; extension not loaded?');
104
			return;
105
		}
106
 
2414 lars 107
		isset(static::$_delete_name) OR static::$_delete_name = version_compare(phpversion('phpredis'), '5', '>=')
108
			? 'del'
109
			: 'delete';
110
 
68 lars 111
		$CI =& get_instance();
112
 
113
		if ($CI->config->load('redis', TRUE, TRUE))
114
		{
115
			$config = array_merge(self::$_default_config, $CI->config->item('redis'));
116
		}
117
		else
118
		{
119
			$config = self::$_default_config;
120
		}
121
 
122
		$this->_redis = new Redis();
123
 
124
		try
125
		{
126
			if ($config['socket_type'] === 'unix')
127
			{
128
				$success = $this->_redis->connect($config['socket']);
129
			}
130
			else // tcp socket
131
			{
132
				$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
133
			}
134
 
135
			if ( ! $success)
136
			{
137
				log_message('error', 'Cache: Redis connection failed. Check your configuration.');
138
			}
139
 
140
			if (isset($config['password']) && ! $this->_redis->auth($config['password']))
141
			{
142
				log_message('error', 'Cache: Redis authentication failed.');
143
			}
144
		}
145
		catch (RedisException $e)
146
		{
147
			log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
148
		}
149
	}
150
 
151
	// ------------------------------------------------------------------------
152
 
153
	/**
154
	 * Get cache
155
	 *
156
	 * @param	string	$key	Cache ID
157
	 * @return	mixed
158
	 */
159
	public function get($key)
160
	{
161
		$value = $this->_redis->get($key);
162
 
2414 lars 163
		if ($value !== FALSE && $this->_redis->sIsMember('_ci_redis_serialized', $key))
68 lars 164
		{
165
			return unserialize($value);
166
		}
167
 
168
		return $value;
169
	}
170
 
171
	// ------------------------------------------------------------------------
172
 
173
	/**
174
	 * Save cache
175
	 *
176
	 * @param	string	$id	Cache ID
177
	 * @param	mixed	$data	Data to save
178
	 * @param	int	$ttl	Time to live in seconds
179
	 * @param	bool	$raw	Whether to store the raw value (unused)
180
	 * @return	bool	TRUE on success, FALSE on failure
181
	 */
182
	public function save($id, $data, $ttl = 60, $raw = FALSE)
183
	{
184
		if (is_array($data) OR is_object($data))
185
		{
186
			if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))
187
			{
188
				return FALSE;
189
			}
190
 
191
			isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;
192
			$data = serialize($data);
193
		}
2414 lars 194
		else
68 lars 195
		{
196
			$this->_redis->sRemove('_ci_redis_serialized', $id);
197
		}
198
 
199
		return $this->_redis->set($id, $data, $ttl);
200
	}
201
 
202
	// ------------------------------------------------------------------------
203
 
204
	/**
205
	 * Delete from cache
206
	 *
207
	 * @param	string	$key	Cache key
208
	 * @return	bool
209
	 */
210
	public function delete($key)
211
	{
2414 lars 212
		if ($this->_redis->{static::$_delete_name}($key) !== 1)
68 lars 213
		{
214
			return FALSE;
215
		}
216
 
2414 lars 217
		$this->_redis->sRemove('_ci_redis_serialized', $key);
68 lars 218
 
219
		return TRUE;
220
	}
221
 
222
	// ------------------------------------------------------------------------
223
 
224
	/**
225
	 * Increment a raw value
226
	 *
227
	 * @param	string	$id	Cache ID
228
	 * @param	int	$offset	Step/value to add
229
	 * @return	mixed	New value on success or FALSE on failure
230
	 */
231
	public function increment($id, $offset = 1)
232
	{
2414 lars 233
		return $this->_redis->incrBy($id, $offset);
68 lars 234
	}
235
 
236
	// ------------------------------------------------------------------------
237
 
238
	/**
239
	 * Decrement a raw value
240
	 *
241
	 * @param	string	$id	Cache ID
242
	 * @param	int	$offset	Step/value to reduce by
243
	 * @return	mixed	New value on success or FALSE on failure
244
	 */
245
	public function decrement($id, $offset = 1)
246
	{
2414 lars 247
		return $this->_redis->decrBy($id, $offset);
68 lars 248
	}
249
 
250
	// ------------------------------------------------------------------------
251
 
252
	/**
253
	 * Clean cache
254
	 *
255
	 * @return	bool
256
	 * @see		Redis::flushDB()
257
	 */
258
	public function clean()
259
	{
260
		return $this->_redis->flushDB();
261
	}
262
 
263
	// ------------------------------------------------------------------------
264
 
265
	/**
266
	 * Get cache driver info
267
	 *
268
	 * @param	string	$type	Not supported in Redis.
269
	 *				Only included in order to offer a
270
	 *				consistent cache API.
271
	 * @return	array
272
	 * @see		Redis::info()
273
	 */
274
	public function cache_info($type = NULL)
275
	{
276
		return $this->_redis->info();
277
	}
278
 
279
	// ------------------------------------------------------------------------
280
 
281
	/**
282
	 * Get cache metadata
283
	 *
284
	 * @param	string	$key	Cache key
285
	 * @return	array
286
	 */
287
	public function get_metadata($key)
288
	{
289
		$value = $this->get($key);
290
 
291
		if ($value !== FALSE)
292
		{
293
			return array(
294
				'expire' => time() + $this->_redis->ttl($key),
295
				'data' => $value
296
			);
297
		}
298
 
299
		return FALSE;
300
	}
301
 
302
	// ------------------------------------------------------------------------
303
 
304
	/**
305
	 * Check if Redis driver is supported
306
	 *
307
	 * @return	bool
308
	 */
309
	public function is_supported()
310
	{
311
		return extension_loaded('redis');
312
	}
313
 
314
	// ------------------------------------------------------------------------
315
 
316
	/**
317
	 * Class destructor
318
	 *
319
	 * Closes the connection to Redis if present.
320
	 *
321
	 * @return	void
322
	 */
323
	public function __destruct()
324
	{
325
		if ($this->_redis)
326
		{
327
			$this->_redis->close();
328
		}
329
	}
330
}