Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* SVN FILE: $Id: cache.php 8004 2009-01-16 20:15:21Z gwoo $ */
3
/**
4
 * Caching for CakePHP.
5
 *
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
10
 * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
11
 *
12
 * Licensed under The MIT License
13
 * Redistributions of files must retain the above copyright notice.
14
 *
15
 * @filesource
16
 * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
17
 * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
18
 * @package       cake
19
 * @subpackage    cake.cake.libs
20
 * @since         CakePHP(tm) v 1.2.0.4933
21
 * @version       $Revision: 8004 $
22
 * @modifiedby    $LastChangedBy: gwoo $
23
 * @lastmodified  $Date: 2009-01-16 12:15:21 -0800 (Fri, 16 Jan 2009) $
24
 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
25
 */
26
/**
27
 * Caching for CakePHP.
28
 *
29
 * @package       cake
30
 * @subpackage    cake.cake.libs
31
 */
32
class Cache extends Object {
33
/**
34
 * Cache engine to use
35
 *
36
 * @var object
37
 * @access protected
38
 */
39
	var $_Engine = null;
40
/**
41
 * Cache configuration stack
42
 *
43
 * @var array
44
 * @access private
45
 */
46
	var $__config = array();
47
/**
48
 * Holds name of the current configuration being used
49
 *
50
 * @var array
51
 * @access private
52
 */
53
	var $__name = 'default';
54
/**
55
 * whether to reset the settings with the next call to self::set();
56
 *
57
 * @var array
58
 * @access private
59
 */
60
	var $__reset = false;
61
/**
62
 * Returns a singleton instance
63
 *
64
 * @return object
65
 * @access public
66
 * @static
67
 */
68
	function &getInstance() {
69
		static $instance = array();
70
		if (!$instance) {
71
			$instance[0] =& new Cache();
72
		}
73
		return $instance[0];
74
	}
75
/**
76
 * Tries to find and include a file for a cache engine and returns object instance
77
 *
78
 * @param $name	Name of the engine (without 'Engine')
79
 * @return mixed $engine object or null
80
 * @access private
81
 */
82
	function __loadEngine($name) {
83
		if (!class_exists($name . 'Engine')) {
84
			require LIBS . DS . 'cache' . DS . strtolower($name) . '.php';
85
		}
86
		return true;
87
	}
88
/**
89
 * Set the cache configuration to use
90
 *
91
 * @see app/config/core.php for configuration settings
92
 * @param string $name Name of the configuration
93
 * @param array $settings Optional associative array of settings passed to the engine
94
 * @return array(engine, settings) on success, false on failure
95
 * @access public
96
 * @static
97
 */
98
	function config($name = null, $settings = array()) {
99
		$_this =& Cache::getInstance();
100
		if (is_array($name)) {
101
			$settings = $name;
102
		}
103
 
104
		if ($name === null || !is_string($name)) {
105
			$name = $_this->__name;
106
		}
107
 
108
		$current = array();
109
		if (isset($_this->__config[$name])) {
110
			$current = $_this->__config[$name];
111
		}
112
 
113
		if (!empty($settings)) {
114
			$_this->__name = null;
115
			$_this->__config[$name] = array_merge($current, $settings);
116
		}
117
 
118
		if (empty($_this->__config[$name]['engine'])) {
119
			return false;
120
		}
121
 
122
		$_this->__name = $name;
123
		$engine = $_this->__config[$name]['engine'];
124
 
125
		if (!$_this->isInitialized($engine)) {
126
			if ($_this->engine($engine, $_this->__config[$name]) === false) {
127
				return false;
128
			}
129
			$settings = $_this->__config[$name] = $_this->settings($engine);
130
		} else {
131
			$settings = $_this->__config[$name] = $_this->set($_this->__config[$name]);
132
		}
133
		return compact('engine', 'settings');
134
	}
135
/**
136
 * Set the cache engine to use or modify settings for one instance
137
 *
138
 * @param string $name Name of the engine (without 'Engine')
139
 * @param array $settings Optional associative array of settings passed to the engine
140
 * @return boolean True on success, false on failure
141
 * @access public
142
 * @static
143
 */
144
	function engine($name = 'File', $settings = array()) {
145
		if (!$name || Configure::read('Cache.disable')) {
146
			return false;
147
		}
148
 
149
		$cacheClass = $name . 'Engine';
150
		$_this =& Cache::getInstance();
151
		if (!isset($_this->_Engine[$name])) {
152
			if ($_this->__loadEngine($name) === false) {
153
				return false;
154
			}
155
			$_this->_Engine[$name] =& new $cacheClass();
156
		}
157
 
158
		if ($_this->_Engine[$name]->init($settings)) {
159
			if (time() % $_this->_Engine[$name]->settings['probability'] === 0) {
160
				$_this->_Engine[$name]->gc();
161
			}
162
			return true;
163
		}
164
		$_this->_Engine[$name] = null;
165
		return false;
166
	}
167
/**
168
 * Temporarily change settings to current config options. if no params are passed, resets settings if needed
169
 * Cache::write() will reset the configuration changes made
170
 *
171
 * @param mixed $settings Optional string for simple name-value pair or array
172
 * @param string $value Optional for a simple name-value pair
173
 * @return array of settings
174
 * @access public
175
 * @static
176
 */
177
	function set($settings = array(), $value = null) {
178
		$_this =& Cache::getInstance();
179
		if (!isset($_this->__config[$_this->__name])) {
180
			return false;
181
		}
182
 
183
		$engine = $_this->__config[$_this->__name]['engine'];
184
 
185
		if (!empty($settings)) {
186
			$_this->__reset = true;
187
		}
188
 
189
		if ($_this->__reset === true) {
190
			if (empty($settings)) {
191
				$_this->__reset = false;
192
				$settings = $_this->__config[$_this->__name];
193
			} else {
194
				if (is_string($settings) && $value !== null) {
195
					$settings = array($settings => $value);
196
				}
197
				$settings = array_merge($_this->__config[$_this->__name], $settings);
198
			}
199
			$_this->_Engine[$engine]->init($settings);
200
		}
201
 
202
		return $_this->settings($engine);
203
	}
204
/**
205
 * Garbage collection
206
 *
207
 * Permanently remove all expired and deleted data
208
 *
209
 * @return void
210
 * @access public
211
 * @static
212
 */
213
	function gc() {
214
		$_this =& Cache::getInstance();
215
		$config = $_this->config();
216
		$_this->_Engine[$config['engine']]->gc();
217
	}
218
/**
219
 * Write data for key into cache
220
 *
221
 * @param string $key Identifier for the data
222
 * @param mixed $value Data to be cached - anything except a resource
223
 * @param mixed $config Optional - string configuration name, a duration for expiration,
224
 *				or array('config' => 'string configuration name', 'duration' => 'duration for expiration')
225
 * @return boolean True if the data was successfully cached, false on failure
226
 * @access public
227
 * @static
228
 */
229
	function write($key, $value, $config = null) {
230
		$_this =& Cache::getInstance();
231
		$thisDuration = null;
232
		if (is_array($config)) {
233
			extract($config);
234
		} else if ($config && (is_numeric($config) || is_numeric($config[0]) || (isset($config[1]) && is_numeric($config[1])))) {
235
			$thisDuration = $config;
236
			$config = null;
237
		}
238
 
239
		if ($config && isset($_this->__config[$config])) {
240
			$settings = $_this->set($_this->__config[$config]);
241
		} else {
242
			$settings = $_this->settings();
243
		}
244
 
245
		if (empty($settings)) {
246
			return null;
247
		}
248
		extract($settings);
249
 
250
		if (!$_this->isInitialized($engine)) {
251
			return false;
252
		}
253
 
254
		if (!$key = $_this->_Engine[$engine]->key($key)) {
255
			return false;
256
		}
257
 
258
		if (is_resource($value)) {
259
			return false;
260
		}
261
 
262
		if ($thisDuration !== null) {
263
			if (!is_numeric($thisDuration)) {
264
				$thisDuration = strtotime($thisDuration) - time();
265
			}
266
			$duration = $thisDuration;
267
		}
268
 
269
		if ($duration < 1) {
270
			return false;
271
		}
272
 
273
		$success = $_this->_Engine[$engine]->write($settings['prefix'] . $key, $value, $duration);
274
		$settings = $_this->set();
275
		return $success;
276
	}
277
/**
278
 * Read a key from the cache
279
 *
280
 * @param string $key Identifier for the data
281
 * @param string $config name of the configuration to use
282
 * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
283
 * @access public
284
 * @static
285
 */
286
	function read($key, $config = null) {
287
		$_this =& Cache::getInstance();
288
 
289
		if (isset($_this->__config[$config])) {
290
			$settings = $_this->set($_this->__config[$config]);
291
		} else {
292
			$settings = $_this->settings();
293
		}
294
 
295
		if (empty($settings)) {
296
			return null;
297
		}
298
		extract($settings);
299
 
300
		if (!$_this->isInitialized($engine)) {
301
			return false;
302
		}
303
		if (!$key = $_this->_Engine[$engine]->key($key)) {
304
			return false;
305
		}
306
		$success = $_this->_Engine[$engine]->read($settings['prefix'] . $key);
307
 
308
		if ($config !== null && $config !== $_this->__name) {
309
			$settings = $_this->set();
310
		}
311
		return $success;
312
	}
313
/**
314
 * Delete a key from the cache
315
 *
316
 * @param string $key Identifier for the data
317
 * @param string $config name of the configuration to use
318
 * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
319
 * @access public
320
 * @static
321
 */
322
	function delete($key, $config = null) {
323
		$_this =& Cache::getInstance();
324
		if (isset($_this->__config[$config])) {
325
			$settings = $_this->set($_this->__config[$config]);
326
		} else {
327
			$settings = $_this->settings();
328
		}
329
 
330
		if (empty($settings)) {
331
			return null;
332
		}
333
		extract($settings);
334
 
335
		if (!$_this->isInitialized($engine)) {
336
			return false;
337
		}
338
 
339
		if (!$key = $_this->_Engine[$engine]->key($key)) {
340
			return false;
341
		}
342
 
343
		$success = $_this->_Engine[$engine]->delete($settings['prefix'] . $key);
344
		$settings = $_this->set();
345
		return $success;
346
	}
347
/**
348
 * Delete all keys from the cache
349
 *
350
 * @param boolean $check if true will check expiration, otherwise delete all
351
 * @param string $config name of the configuration to use
352
 * @return boolean True if the cache was succesfully cleared, false otherwise
353
 * @access public
354
 * @static
355
 */
356
	function clear($check = false, $config = null) {
357
		$_this =& Cache::getInstance();
358
		if (isset($_this->__config[$config])) {
359
			$settings = $_this->set($_this->__config[$config]);
360
		} else {
361
			$settings = $_this->settings();
362
		}
363
 
364
		if (empty($settings)) {
365
			return null;
366
		}
367
		extract($settings);
368
 
369
		if (isset($engine) && !$_this->isInitialized($engine)) {
370
			return false;
371
		}
372
		$success = $_this->_Engine[$engine]->clear($check);
373
		$settings = $_this->set();
374
		return $success;
375
	}
376
/**
377
 * Check if Cache has initialized a working storage engine
378
 *
379
 * @param string $engine Name of the engine
380
 * @param string $config Name of the configuration setting
381
 * @return bool
382
 * @access public
383
 * @static
384
 */
385
	function isInitialized($engine = null) {
386
		if (Configure::read('Cache.disable')) {
387
			return false;
388
		}
389
		$_this =& Cache::getInstance();
390
		if (!$engine && isset($_this->__config[$_this->__name]['engine'])) {
391
			$engine = $_this->__config[$_this->__name]['engine'];
392
		}
393
		return isset($_this->_Engine[$engine]);
394
	}
395
 
396
/**
397
 * Return the settings for current cache engine
398
 *
399
 * @param string $engine Name of the engine
400
 * @return array list of settings for this engine
401
 * @access public
402
 * @static
403
 */
404
	function settings($engine = null) {
405
		$_this =& Cache::getInstance();
406
		if (!$engine && isset($_this->__config[$_this->__name]['engine'])) {
407
			$engine = $_this->__config[$_this->__name]['engine'];
408
		}
409
 
410
		if (isset($_this->_Engine[$engine]) && !is_null($_this->_Engine[$engine])) {
411
			return $_this->_Engine[$engine]->settings();
412
		}
413
		return array();
414
	}
415
}
416
/**
417
 * Storage engine for CakePHP caching
418
 *
419
 * @package       cake
420
 * @subpackage    cake.cake.libs
421
 */
422
class CacheEngine extends Object {
423
/**
424
 * settings of current engine instance
425
 *
426
 * @var int
427
 * @access public
428
 */
429
	var $settings = array();
430
/**
431
 * Iitialize the cache engine
432
 *
433
 * Called automatically by the cache frontend
434
 *
435
 * @param array $params Associative array of parameters for the engine
436
 * @return boolean True if the engine has been succesfully initialized, false if not
437
 * @access public
438
 */
439
	function init($settings = array()) {
440
		$this->settings = array_merge(array('prefix' => 'cake_', 'duration'=> 3600, 'probability'=> 100), $this->settings, $settings);
441
		if (!is_numeric($this->settings['duration'])) {
442
			$this->settings['duration'] = strtotime($this->settings['duration']) - time();
443
		}
444
		return true;
445
	}
446
/**
447
 * Garbage collection
448
 *
449
 * Permanently remove all expired and deleted data
450
 *
451
 * @access public
452
 */
453
	function gc() {
454
	}
455
/**
456
 * Write value for a key into cache
457
 *
458
 * @param string $key Identifier for the data
459
 * @param mixed $value Data to be cached
460
 * @param mixed $duration How long to cache the data, in seconds
461
 * @return boolean True if the data was succesfully cached, false on failure
462
 * @access public
463
 */
464
	function write($key, &$value, $duration) {
465
		trigger_error(sprintf(__('Method write() not implemented in %s', true), get_class($this)), E_USER_ERROR);
466
	}
467
/**
468
 * Read a key from the cache
469
 *
470
 * @param string $key Identifier for the data
471
 * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
472
 * @access public
473
 */
474
	function read($key) {
475
		trigger_error(sprintf(__('Method read() not implemented in %s', true), get_class($this)), E_USER_ERROR);
476
	}
477
/**
478
 * Delete a key from the cache
479
 *
480
 * @param string $key Identifier for the data
481
 * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
482
 * @access public
483
 */
484
	function delete($key) {
485
	}
486
/**
487
 * Delete all keys from the cache
488
 *
489
 * @param boolean $check if true will check expiration, otherwise delete all
490
 * @return boolean True if the cache was succesfully cleared, false otherwise
491
 * @access public
492
 */
493
	function clear($check) {
494
	}
495
/**
496
 * Cache Engine settings
497
 *
498
 * @return array settings
499
 * @access public
500
 */
501
	function settings() {
502
		return $this->settings;
503
	}
504
/**
505
 * generates a safe key
506
 *
507
 * @param string $key the key passed over
508
 * @return mixed string $key or false
509
 * @access public
510
 */
511
	function key($key) {
512
		if (empty($key)) {
513
			return false;
514
		}
515
		$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
516
		return $key;
517
	}
518
}
519
?>