1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Cache
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Abstract cache storage handler
14 *
15 * @since 11.1
16 * @note As of 4.0 this class will be abstract
17 */
18 class JCacheStorage
19 {
20 /**
21 * The raw object name
22 *
23 * @var string
24 * @since 11.1
25 */
26 protected $rawname;
27
28 /**
29 * Time that the cache storage handler was instantiated
30 *
31 * @var integer
32 * @since 11.1
33 */
34 public $_now;
35
36 /**
37 * Cache lifetime
38 *
39 * @var integer
40 * @since 11.1
41 */
42 public $_lifetime;
43
44 /**
45 * Flag if locking is enabled
46 *
47 * @var boolean
48 * @since 11.1
49 */
50 public $_locking;
51
52 /**
53 * Language code
54 *
55 * @var string
56 * @since 11.1
57 */
58 public $_language;
59
60 /**
61 * Application name
62 *
63 * @var string
64 * @since 11.1
65 */
66 public $_application;
67
68 /**
69 * Object hash
70 *
71 * @var string
72 * @since 11.1
73 */
74 public $_hash;
75
76 /**
77 * Constructor
78 *
79 * @param array $options Optional parameters
80 *
81 * @since 11.1
82 */
83 public function __construct($options = array())
84 {
85 $config = JFactory::getConfig();
86
87 $this->_hash = md5($config->get('secret'));
88 $this->_application = (isset($options['application'])) ? $options['application'] : null;
89 $this->_language = (isset($options['language'])) ? $options['language'] : 'en-GB';
90 $this->_locking = (isset($options['locking'])) ? $options['locking'] : true;
91 $this->_lifetime = (isset($options['lifetime'])) ? $options['lifetime'] * 60 : $config->get('cachetime') * 60;
92 $this->_now = (isset($options['now'])) ? $options['now'] : time();
93
94 // Set time threshold value. If the lifetime is not set, default to 60 (0 is BAD)
95 // _threshold is now available ONLY as a legacy (it's deprecated). It's no longer used in the core.
96 if (empty($this->_lifetime))
97 {
98 $this->_threshold = $this->_now - 60;
99 $this->_lifetime = 60;
100 }
101 else
102 {
103 $this->_threshold = $this->_now - $this->_lifetime;
104 }
105 }
106
107 /**
108 * Returns a cache storage handler object.
109 *
110 * @param string $handler The cache storage handler to instantiate
111 * @param array $options Array of handler options
112 *
113 * @return JCacheStorage
114 *
115 * @since 11.1
116 * @throws UnexpectedValueException
117 * @throws JCacheExceptionUnsupported
118 */
119 public static function getInstance($handler = null, $options = array())
120 {
121 static $now = null;
122
123 // @deprecated 4.0 This class path is autoloaded, manual inclusion is no longer necessary
124 self::addIncludePath(JPATH_PLATFORM . '/joomla/cache/storage');
125
126 if (!isset($handler))
127 {
128 $handler = JFactory::getConfig()->get('cache_handler');
129
130 if (empty($handler))
131 {
132 throw new UnexpectedValueException('Cache Storage Handler not set.');
133 }
134 }
135
136 if (is_null($now))
137 {
138 $now = time();
139 }
140
141 $options['now'] = $now;
142
143 // We can't cache this since options may change...
144 $handler = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $handler));
145
146 /** @var JCacheStorage $class */
147 $class = 'JCacheStorage' . ucfirst($handler);
148
149 if (!class_exists($class))
150 {
151 // Search for the class file in the JCacheStorage include paths.
152 jimport('joomla.filesystem.path');
153
154 $path = JPath::find(self::addIncludePath(), strtolower($handler) . '.php');
155
156 if ($path === false)
157 {
158 throw new JCacheExceptionUnsupported(sprintf('Unable to load Cache Storage: %s', $handler));
159 }
160
161 JLoader::register($class, $path);
162
163 // The class should now be loaded
164 if (!class_exists($class))
165 {
166 throw new JCacheExceptionUnsupported(sprintf('Unable to load Cache Storage: %s', $handler));
167 }
168 }
169
170 // Validate the cache storage is supported on this platform
171 if (!$class::isSupported())
172 {
173 throw new JCacheExceptionUnsupported(sprintf('The %s Cache Storage is not supported on this platform.', $handler));
174 }
175
176 return new $class($options);
177 }
178
179 /**
180 * Check if the cache contains data stored by ID and group
181 *
182 * @param string $id The cache data ID
183 * @param string $group The cache data group
184 *
185 * @return boolean
186 *
187 * @since 3.7.0
188 */
189 public function contains($id, $group)
190 {
191 return false;
192 }
193
194 /**
195 * Get cached data by ID and group
196 *
197 * @param string $id The cache data ID
198 * @param string $group The cache data group
199 * @param boolean $checkTime True to verify cache time expiration threshold
200 *
201 * @return mixed Boolean false on failure or a cached data object
202 *
203 * @since 11.1
204 */
205 public function get($id, $group, $checkTime = true)
206 {
207 return false;
208 }
209
210 /**
211 * Get all cached data
212 *
213 * @return mixed Boolean false on failure or a cached data object
214 *
215 * @since 11.1
216 */
217 public function getAll()
218 {
219 return false;
220 }
221
222 /**
223 * Store the data to cache by ID and group
224 *
225 * @param string $id The cache data ID
226 * @param string $group The cache data group
227 * @param string $data The data to store in cache
228 *
229 * @return boolean
230 *
231 * @since 11.1
232 */
233 public function store($id, $group, $data)
234 {
235 return true;
236 }
237
238 /**
239 * Remove a cached data entry by ID and group
240 *
241 * @param string $id The cache data ID
242 * @param string $group The cache data group
243 *
244 * @return boolean
245 *
246 * @since 11.1
247 */
248 public function remove($id, $group)
249 {
250 return true;
251 }
252
253 /**
254 * Clean cache for a group given a mode.
255 *
256 * group mode : cleans all cache in the group
257 * notgroup mode : cleans all cache not in the group
258 *
259 * @param string $group The cache data group
260 * @param string $mode The mode for cleaning cache [group|notgroup]
261 *
262 * @return boolean
263 *
264 * @since 11.1
265 */
266 public function clean($group, $mode = null)
267 {
268 return true;
269 }
270
271 /**
272 * Flush all existing items in storage.
273 *
274 * @return boolean
275 *
276 * @since 3.6.3
277 */
278 public function flush()
279 {
280 return true;
281 }
282
283 /**
284 * Garbage collect expired cache data
285 *
286 * @return boolean
287 *
288 * @since 11.1
289 */
290 public function gc()
291 {
292 return true;
293 }
294
295 /**
296 * Test to see if the storage handler is available.
297 *
298 * @return boolean
299 *
300 * @since 12.1
301 */
302 public static function isSupported()
303 {
304 return true;
305 }
306
307 /**
308 * Test to see if the storage handler is available.
309 *
310 * @return boolean
311 *
312 * @since 11.1
313 * @deprecated 12.3 (Platform) & 4.0 (CMS)
314 */
315 public static function test()
316 {
317 JLog::add(__METHOD__ . '() is deprecated. Use JCacheStorage::isSupported() instead.', JLog::WARNING, 'deprecated');
318
319 return static::isSupported();
320 }
321
322 /**
323 * Lock cached item
324 *
325 * @param string $id The cache data ID
326 * @param string $group The cache data group
327 * @param integer $locktime Cached item max lock time
328 *
329 * @return mixed Boolean false if locking failed or an object containing properties lock and locklooped
330 *
331 * @since 11.1
332 */
333 public function lock($id, $group, $locktime)
334 {
335 return false;
336 }
337
338 /**
339 * Unlock cached item
340 *
341 * @param string $id The cache data ID
342 * @param string $group The cache data group
343 *
344 * @return boolean
345 *
346 * @since 11.1
347 */
348 public function unlock($id, $group = null)
349 {
350 return false;
351 }
352
353 /**
354 * Get a cache ID string from an ID/group pair
355 *
356 * @param string $id The cache data ID
357 * @param string $group The cache data group
358 *
359 * @return string
360 *
361 * @since 11.1
362 */
363 protected function _getCacheId($id, $group)
364 {
365 $name = md5($this->_application . '-' . $id . '-' . $this->_language);
366 $this->rawname = $this->_hash . '-' . $name;
367
368 return JCache::getPlatformPrefix() . $this->_hash . '-cache-' . $group . '-' . $name;
369 }
370
371 /**
372 * Add a directory where JCacheStorage should search for handlers. You may either pass a string or an array of directories.
373 *
374 * @param array|string $path A path to search.
375 *
376 * @return array An array with directory elements
377 *
378 * @since 11.1
379 */
380 public static function addIncludePath($path = '')
381 {
382 static $paths;
383
384 if (!isset($paths))
385 {
386 $paths = array();
387 }
388
389 if (!empty($path) && !in_array($path, $paths))
390 {
391 jimport('joomla.filesystem.path');
392 array_unshift($paths, JPath::clean($path));
393 }
394
395 return $paths;
396 }
397 }
398