1 <?php
2 3 4 5 6 7 8
9
10 defined('JPATH_PLATFORM') or die;
11
12 13 14 15 16
17 class JCacheStorageRedis extends JCacheStorage
18 {
19 20 21 22 23 24
25 protected static $_redis = null;
26
27 28 29 30 31 32
33 protected $_persistent = false;
34
35 36 37 38 39 40 41
42 public function __construct($options = array())
43 {
44 parent::__construct($options);
45
46 if (static::$_redis === null)
47 {
48 $this->getConnection();
49 }
50 }
51
52 53 54 55 56 57 58 59
60 protected function getConnection()
61 {
62 if (static::isSupported() == false)
63 {
64 return false;
65 }
66
67 $app = JFactory::getApplication();
68
69 $this->_persistent = $app->get('redis_persist', true);
70
71 $server = array(
72 'host' => $app->get('redis_server_host', 'localhost'),
73 'port' => $app->get('redis_server_port', 6379),
74 'auth' => $app->get('redis_server_auth', null),
75 'db' => (int) $app->get('redis_server_db', null),
76 );
77
78 static::$_redis = new Redis;
79
80 if ($this->_persistent)
81 {
82 try
83 {
84 $connection = static::$_redis->pconnect($server['host'], $server['port']);
85 $auth = (!empty($server['auth'])) ? static::$_redis->auth($server['auth']) : true;
86 }
87 catch (RedisException $e)
88 {
89 JLog::add($e->getMessage(), JLog::DEBUG);
90 }
91 }
92 else
93 {
94 try
95 {
96 $connection = static::$_redis->connect($server['host'], $server['port']);
97 $auth = (!empty($server['auth'])) ? static::$_redis->auth($server['auth']) : true;
98 }
99 catch (RedisException $e)
100 {
101 JLog::add($e->getMessage(), JLog::DEBUG);
102 }
103 }
104
105 if ($connection == false)
106 {
107 static::$_redis = null;
108
109 if ($app->isClient('administrator'))
110 {
111 JError::raiseWarning(500, 'Redis connection failed');
112 }
113
114 return false;
115 }
116
117 if ($auth == false)
118 {
119 if ($app->isClient('administrator'))
120 {
121 JError::raiseWarning(500, 'Redis authentication failed');
122 }
123
124 return false;
125 }
126
127 $select = static::$_redis->select($server['db']);
128
129 if ($select == false)
130 {
131 static::$_redis = null;
132
133 if ($app->isClient('administrator'))
134 {
135 JError::raiseWarning(500, 'Redis failed to select database');
136 }
137
138 return false;
139 }
140
141 try
142 {
143 static::$_redis->ping();
144 }
145 catch (RedisException $e)
146 {
147 static::$_redis = null;
148
149 if ($app->isClient('administrator'))
150 {
151 JError::raiseWarning(500, 'Redis ping failed');
152 }
153
154 return false;
155 }
156
157 return static::$_redis;
158 }
159
160 161 162 163 164 165 166 167 168 169
170 public function contains($id, $group)
171 {
172 if (static::isConnected() == false)
173 {
174 return false;
175 }
176
177 return static::$_redis->exists($this->_getCacheId($id, $group));
178 }
179
180 181 182 183 184 185 186 187 188 189 190
191 public function get($id, $group, $checkTime = true)
192 {
193 if (static::isConnected() == false)
194 {
195 return false;
196 }
197
198 return static::$_redis->get($this->_getCacheId($id, $group));
199 }
200
201 202 203 204 205 206 207
208 public function getAll()
209 {
210 if (static::isConnected() == false)
211 {
212 return false;
213 }
214
215 $allKeys = static::$_redis->keys('*');
216 $data = array();
217 $secret = $this->_hash;
218
219 if (!empty($allKeys))
220 {
221 foreach ($allKeys as $key)
222 {
223 $namearr = explode('-', $key);
224
225 if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
226 {
227 $group = $namearr[2];
228
229 if (!isset($data[$group]))
230 {
231 $item = new JCacheStorageHelper($group);
232 }
233 else
234 {
235 $item = $data[$group];
236 }
237
238 $item->updateSize(strlen($key)*8);
239 $data[$group] = $item;
240 }
241 }
242 }
243
244 return $data;
245 }
246
247 248 249 250 251 252 253 254 255 256 257
258 public function store($id, $group, $data)
259 {
260 if (static::isConnected() == false)
261 {
262 return false;
263 }
264
265 static::$_redis->setex($this->_getCacheId($id, $group), $this->_lifetime, $data);
266
267 return true;
268 }
269
270 271 272 273 274 275 276 277 278 279
280 public function remove($id, $group)
281 {
282 if (static::isConnected() == false)
283 {
284 return false;
285 }
286
287 return (bool) static::$_redis->delete($this->_getCacheId($id, $group));
288 }
289
290 291 292 293 294 295 296 297 298 299 300 301 302
303 public function clean($group, $mode = null)
304 {
305 if (static::isConnected() == false)
306 {
307 return false;
308 }
309
310 $allKeys = static::$_redis->keys('*');
311
312 if ($allKeys === false)
313 {
314 $allKeys = array();
315 }
316
317 $secret = $this->_hash;
318
319 foreach ($allKeys as $key)
320 {
321 if (strpos($key, $secret . '-cache-' . $group . '-') === 0 && $mode == 'group')
322 {
323 static::$_redis->delete($key);
324 }
325
326 if (strpos($key, $secret . '-cache-' . $group . '-') !== 0 && $mode != 'group')
327 {
328 static::$_redis->delete($key);
329 }
330 }
331
332 return true;
333 }
334
335 336 337 338 339 340 341
342 public static function isSupported()
343 {
344 return class_exists('Redis');
345 }
346
347 348 349 350 351 352 353
354 public static function isConnected()
355 {
356 return static::$_redis instanceof Redis;
357 }
358 }
359