PageRenderTime 26ms CodeModel.GetById 10ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/system/libraries/Cache/drivers/Cache_redis.php

https://bitbucket.org/Naked_Yoshi/sq_kanban
PHP | 328 lines | 136 code | 40 blank | 152 comment | 16 complexity | 3fabd34b8a3cd5eee7dce7d055172bd6 MD5 | raw file
  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 *
  9 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
 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/)
 32 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
 33 * @license	http://opensource.org/licenses/MIT	MIT License
 34 * @link	https://codeigniter.com
 35 * @since	Version 3.0.0
 36 * @filesource
 37 */
 38defined('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 */
 49class 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
 79	// ------------------------------------------------------------------------
 80
 81	/**
 82	 * Class constructor
 83	 *
 84	 * Setup Redis
 85	 *
 86	 * Loads Redis config file if present. Will halt execution
 87	 * if a Redis connection can't be established.
 88	 *
 89	 * @return	void
 90	 * @see		Redis::connect()
 91	 */
 92	public function __construct()
 93	{
 94		if ( ! $this->is_supported())
 95		{
 96			log_message('error', 'Cache: Failed to create Redis object; extension not loaded?');
 97			return;
 98		}
 99
100		$CI =& get_instance();
101
102		if ($CI->config->load('redis', TRUE, TRUE))
103		{
104			$config = array_merge(self::$_default_config, $CI->config->item('redis'));
105		}
106		else
107		{
108			$config = self::$_default_config;
109		}
110
111		$this->_redis = new Redis();
112
113		try
114		{
115			if ($config['socket_type'] === 'unix')
116			{
117				$success = $this->_redis->connect($config['socket']);
118			}
119			else // tcp socket
120			{
121				$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
122			}
123
124			if ( ! $success)
125			{
126				log_message('error', 'Cache: Redis connection failed. Check your configuration.');
127			}
128
129			if (isset($config['password']) && ! $this->_redis->auth($config['password']))
130			{
131				log_message('error', 'Cache: Redis authentication failed.');
132			}
133		}
134		catch (RedisException $e)
135		{
136			log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
137		}
138
139		// Initialize the index of serialized values.
140		$serialized = $this->_redis->sMembers('_ci_redis_serialized');
141		empty($serialized) OR $this->_serialized = array_flip($serialized);
142	}
143
144	// ------------------------------------------------------------------------
145
146	/**
147	 * Get cache
148	 *
149	 * @param	string	$key	Cache ID
150	 * @return	mixed
151	 */
152	public function get($key)
153	{
154		$value = $this->_redis->get($key);
155
156		if ($value !== FALSE && isset($this->_serialized[$key]))
157		{
158			return unserialize($value);
159		}
160
161		return $value;
162	}
163
164	// ------------------------------------------------------------------------
165
166	/**
167	 * Save cache
168	 *
169	 * @param	string	$id	Cache ID
170	 * @param	mixed	$data	Data to save
171	 * @param	int	$ttl	Time to live in seconds
172	 * @param	bool	$raw	Whether to store the raw value (unused)
173	 * @return	bool	TRUE on success, FALSE on failure
174	 */
175	public function save($id, $data, $ttl = 60, $raw = FALSE)
176	{
177		if (is_array($data) OR is_object($data))
178		{
179			if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))
180			{
181				return FALSE;
182			}
183
184			isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;
185			$data = serialize($data);
186		}
187		elseif (isset($this->_serialized[$id]))
188		{
189			$this->_serialized[$id] = NULL;
190			$this->_redis->sRemove('_ci_redis_serialized', $id);
191		}
192
193		return $this->_redis->set($id, $data, $ttl);
194	}
195
196	// ------------------------------------------------------------------------
197
198	/**
199	 * Delete from cache
200	 *
201	 * @param	string	$key	Cache key
202	 * @return	bool
203	 */
204	public function delete($key)
205	{
206		if ($this->_redis->delete($key) !== 1)
207		{
208			return FALSE;
209		}
210
211		if (isset($this->_serialized[$key]))
212		{
213			$this->_serialized[$key] = NULL;
214			$this->_redis->sRemove('_ci_redis_serialized', $key);
215		}
216
217		return TRUE;
218	}
219
220	// ------------------------------------------------------------------------
221
222	/**
223	 * Increment a raw value
224	 *
225	 * @param	string	$id	Cache ID
226	 * @param	int	$offset	Step/value to add
227	 * @return	mixed	New value on success or FALSE on failure
228	 */
229	public function increment($id, $offset = 1)
230	{
231		return $this->_redis->incr($id, $offset);
232	}
233
234	// ------------------------------------------------------------------------
235
236	/**
237	 * Decrement a raw value
238	 *
239	 * @param	string	$id	Cache ID
240	 * @param	int	$offset	Step/value to reduce by
241	 * @return	mixed	New value on success or FALSE on failure
242	 */
243	public function decrement($id, $offset = 1)
244	{
245		return $this->_redis->decr($id, $offset);
246	}
247
248	// ------------------------------------------------------------------------
249
250	/**
251	 * Clean cache
252	 *
253	 * @return	bool
254	 * @see		Redis::flushDB()
255	 */
256	public function clean()
257	{
258		return $this->_redis->flushDB();
259	}
260
261	// ------------------------------------------------------------------------
262
263	/**
264	 * Get cache driver info
265	 *
266	 * @param	string	$type	Not supported in Redis.
267	 *				Only included in order to offer a
268	 *				consistent cache API.
269	 * @return	array
270	 * @see		Redis::info()
271	 */
272	public function cache_info($type = NULL)
273	{
274		return $this->_redis->info();
275	}
276
277	// ------------------------------------------------------------------------
278
279	/**
280	 * Get cache metadata
281	 *
282	 * @param	string	$key	Cache key
283	 * @return	array
284	 */
285	public function get_metadata($key)
286	{
287		$value = $this->get($key);
288
289		if ($value !== FALSE)
290		{
291			return array(
292				'expire' => time() + $this->_redis->ttl($key),
293				'data' => $value
294			);
295		}
296
297		return FALSE;
298	}
299
300	// ------------------------------------------------------------------------
301
302	/**
303	 * Check if Redis driver is supported
304	 *
305	 * @return	bool
306	 */
307	public function is_supported()
308	{
309		return extension_loaded('redis');
310	}
311
312	// ------------------------------------------------------------------------
313
314	/**
315	 * Class destructor
316	 *
317	 * Closes the connection to Redis if present.
318	 *
319	 * @return	void
320	 */
321	public function __destruct()
322	{
323		if ($this->_redis)
324		{
325			$this->_redis->close();
326		}
327	}
328}