1: <?php
  2: 
  3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24: 
 25:  26:  27:  28:  29:  30: 
 31: class Cache extends Object {
 32:  33:  34:  35:  36:  37: 
 38:     var $_Engine = null;
 39:  40:  41:  42:  43:  44: 
 45:     var $__config = array();
 46:  47:  48:  49:  50:  51: 
 52:     var $__name = 'default';
 53:  54:  55:  56:  57:  58: 
 59:     var $__reset = false;
 60:  61:  62:  63:  64:  65:  66: 
 67:     function &getInstance() {
 68:         static $instance = array();
 69:         if (!$instance) {
 70:             $instance[0] =& new Cache();
 71:         }
 72:         return $instance[0];
 73:     }
 74:  75:  76:  77:  78:  79:  80: 
 81:     function __loadEngine($name) {
 82:         if (!class_exists($name . 'Engine')) {
 83:             require LIBS . 'cache' . DS . strtolower($name) . '.php';
 84:         }
 85:         return true;
 86:     }
 87:  88:  89:  90:  91:  92:  93:  94:  95:  96: 
 97:     function config($name = null, $settings = array()) {
 98:         $_this =& Cache::getInstance();
 99:         if (is_array($name)) {
100:             $settings = $name;
101:         }
102: 
103:         if ($name === null || !is_string($name)) {
104:             $name = $_this->__name;
105:         }
106: 
107:         $current = array();
108:         if (isset($_this->__config[$name])) {
109:             $current = $_this->__config[$name];
110:         }
111: 
112:         if (!empty($settings)) {
113:             $_this->__name = null;
114:             $_this->__config[$name] = array_merge($current, $settings);
115:         }
116: 
117:         if (empty($_this->__config[$name]['engine'])) {
118:             return false;
119:         }
120: 
121:         $_this->__name = $name;
122:         $engine = $_this->__config[$name]['engine'];
123: 
124:         if (!$_this->isInitialized($engine)) {
125:             if ($_this->engine($engine, $_this->__config[$name]) === false) {
126:                 return false;
127:             }
128:             $settings = $_this->__config[$name] = $_this->settings($engine);
129:         } else {
130:             $settings = $_this->__config[$name] = $_this->set($_this->__config[$name]);
131:         }
132:         return compact('engine', 'settings');
133:     }
134: 135: 136: 137: 138: 139: 140: 141: 142: 
143:     function engine($name = 'File', $settings = array()) {
144:         $cacheClass = $name . 'Engine';
145:         $_this =& Cache::getInstance();
146:         if (!isset($_this->_Engine[$name])) {
147:             if ($_this->__loadEngine($name) === false) {
148:                 return false;
149:             }
150:             $_this->_Engine[$name] =& new $cacheClass();
151:         }
152: 
153:         if ($_this->_Engine[$name]->init($settings)) {
154:             if (time() % $_this->_Engine[$name]->settings['probability'] === 0) {
155:                 $_this->_Engine[$name]->gc();
156:             }
157:             return true;
158:         }
159:         $_this->_Engine[$name] = null;
160:         return false;
161:     }
162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 
172:     function set($settings = array(), $value = null) {
173:         $_this =& Cache::getInstance();
174:         if (!isset($_this->__config[$_this->__name])) {
175:             return false;
176:         }
177: 
178:         $engine = $_this->__config[$_this->__name]['engine'];   
179:         if (isset($settings['engine'])) {
180:             $engine = $settings['engine'];
181:         }
182: 
183:         if (!empty($settings)) {
184:             $_this->__reset = true;
185:         }
186: 
187:         if ($_this->__reset === true) {
188:             if (empty($settings)) {
189:                 $_this->__reset = false;
190:                 $settings = $_this->__config[$_this->__name];
191:             } else {
192:                 if (is_string($settings) && $value !== null) {
193:                     $settings = array($settings => $value);
194:                 }
195:                 $settings = array_merge($_this->__config[$_this->__name], $settings);
196:             }
197:             $_this->_Engine[$engine]->init($settings);
198:         }
199: 
200:         return $_this->settings($engine);
201:     }
202: 203: 204: 205: 206: 207: 208: 209: 210: 
211:     function gc() {
212:         $_this =& Cache::getInstance();
213:         $config = $_this->config();
214:         $_this->_Engine[$config['engine']]->gc();
215:     }
216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 
226:     function write($key, $value, $config = null) {
227:         $_this =& Cache::getInstance();
228: 
229:         if (is_array($config)) {
230:             extract($config);
231:         } else if ($config && (is_numeric($config) || is_numeric($config[0]) || (isset($config[1]) && is_numeric($config[1])))) {
232:             $config = null;
233:         }
234: 
235:         if ($config && isset($_this->__config[$config])) {
236:             $settings = $_this->set($_this->__config[$config]);
237:         } else {
238:             $settings = $_this->settings();
239:         }
240: 
241:         if (empty($settings)) {
242:             return null;
243:         }
244:         extract($settings);
245: 
246:         if (!$_this->isInitialized($engine)) {
247:             return false;
248:         }
249: 
250:         if (!$key = $_this->_Engine[$engine]->key($key)) {
251:             return false;
252:         }
253: 
254:         if (is_resource($value)) {
255:             return false;
256:         }
257: 
258:         if ($duration < 1) {
259:             return false;
260:         }
261: 
262:         $success = $_this->_Engine[$engine]->write($settings['prefix'] . $key, $value, $duration);
263:         $settings = $_this->set();
264:         return $success;
265:     }
266: 267: 268: 269: 270: 271: 272: 273: 274: 
275:     function read($key, $config = null) {
276:         $_this =& Cache::getInstance();
277: 
278:         if (isset($_this->__config[$config])) {
279:             $settings = $_this->set($_this->__config[$config]);
280:         } else {
281:             $settings = $_this->settings();
282:         }
283: 
284:         if (empty($settings)) {
285:             return null;
286:         }
287:         extract($settings);
288: 
289:         if (!$_this->isInitialized($engine)) {
290:             return false;
291:         }
292:         if (!$key = $_this->_Engine[$engine]->key($key)) {
293:             return false;
294:         }
295:     
296:         $success = $_this->_Engine[$engine]->read($settings['prefix'] . $key);
297: 
298:         if ($config !== null && $config !== $_this->__name) {
299:             $settings = $_this->set();
300:         }
301:         return $success;
302:     }
303: 304: 305: 306: 307: 308: 309: 310: 311: 
312:     function delete($key, $config = null) {
313:         $_this =& Cache::getInstance();
314:         if (isset($_this->__config[$config])) {
315:             $settings = $_this->set($_this->__config[$config]);
316:         } else {
317:             $settings = $_this->settings();
318:         }
319: 
320:         if (empty($settings)) {
321:             return null;
322:         }
323:         extract($settings);
324: 
325:         if (!$_this->isInitialized($engine)) {
326:             return false;
327:         }
328: 
329:         if (!$key = $_this->_Engine[$engine]->key($key)) {
330:             return false;
331:         }
332: 
333:         $success = $_this->_Engine[$engine]->delete($settings['prefix'] . $key);
334:         $settings = $_this->set();
335:         return $success;
336:     }
337: 338: 339: 340: 341: 342: 343: 344: 345: 
346:     function clear($check = false, $config = null) {
347:         $_this =& Cache::getInstance();
348:         if (isset($_this->__config[$config])) {
349:             $settings = $_this->set($_this->__config[$config]);
350:         } else {
351:             $settings = $_this->settings();
352:         }
353: 
354:         if (empty($settings)) {
355:             return null;
356:         }
357:         extract($settings);
358: 
359:         if (isset($engine) && !$_this->isInitialized($engine)) {
360:             return false;
361:         }
362:         $success = $_this->_Engine[$engine]->clear($check);
363:         $settings = $_this->set();
364:         return $success;
365:     }
366: 367: 368: 369: 370: 371: 372: 373: 374: 
375:     function isInitialized($engine = null) {
376:         if (Configure::read('Cache.disable')) {
377:             return false;
378:         }
379:         $_this =& Cache::getInstance();
380:         if (!$engine && isset($_this->__config[$_this->__name]['engine'])) {
381:             $engine = $_this->__config[$_this->__name]['engine'];
382:         }
383:         return isset($_this->_Engine[$engine]);
384:     }
385: 
386: 387: 388: 389: 390: 391: 392: 393: 
394:     function settings($engine = null) {
395:         $_this =& Cache::getInstance();
396:         if (!$engine && isset($_this->__config[$_this->__name]['engine'])) {
397:             $engine = $_this->__config[$_this->__name]['engine'];
398:         }
399: 
400:         if (isset($_this->_Engine[$engine]) && !is_null($_this->_Engine[$engine])) {
401:             return $_this->_Engine[$engine]->settings();
402:         }
403:         return array();
404:     }
405: }
406: 407: 408: 409: 410: 411: 
412: class CacheEngine extends Object {
413: 414: 415: 416: 417: 418: 
419:     var $settings = array();
420: 421: 422: 423: 424: 425: 426: 427: 428: 
429:     function init($settings = array()) {
430:         $this->settings = array_merge(array('prefix' => 'cake_', 'duration'=> 3600, 'probability'=> 100), $this->settings, $settings);
431:         if (!is_numeric($this->settings['duration'])) {
432:             $this->settings['duration'] = strtotime($this->settings['duration']) - time();
433:         }
434:         return true;
435:     }
436: 437: 438: 439: 440: 441: 442: 
443:     function gc() {
444:     }
445: 446: 447: 448: 449: 450: 451: 452: 453: 
454:     function write($key, &$value, $duration) {
455:         trigger_error(sprintf(__('Method write() not implemented in %s', true), get_class($this)), E_USER_ERROR);
456:     }
457: 458: 459: 460: 461: 462: 463: 
464:     function read($key) {
465:         trigger_error(sprintf(__('Method read() not implemented in %s', true), get_class($this)), E_USER_ERROR);
466:     }
467: 468: 469: 470: 471: 472: 473: 
474:     function delete($key) {
475:     }
476: 477: 478: 479: 480: 481: 482: 
483:     function clear($check) {
484:     }
485: 486: 487: 488: 489: 490: 
491:     function settings() {
492:         return $this->settings;
493:     }
494: 495: 496: 497: 498: 499: 500: 
501:     function key($key) {
502:         if (empty($key)) {
503:             return false;
504:         }
505:         $key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
506:         return $key;
507:     }
508: }
509: ?>