1: <?php
2: /**
3: * Xcache storage engine for cache.
4: *
5: * PHP 5
6: *
7: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8: * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
9: *
10: * Licensed under The MIT License
11: * For full copyright and license information, please see the LICENSE.txt
12: * Redistributions of files must retain the above copyright notice.
13: *
14: * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
15: * @link http://cakephp.org CakePHP(tm) Project
16: * @package Cake.Cache.Engine
17: * @since CakePHP(tm) v 1.2.0.4947
18: * @license http://www.opensource.org/licenses/mit-license.php MIT License
19: */
20:
21: /**
22: * Xcache storage engine for cache
23: *
24: * @link http://trac.lighttpd.net/xcache/ Xcache
25: * @package Cake.Cache.Engine
26: */
27: class XcacheEngine extends CacheEngine {
28:
29: /**
30: * Settings
31: *
32: * - PHP_AUTH_USER = xcache.admin.user, default cake
33: * - PHP_AUTH_PW = xcache.admin.password, default cake
34: *
35: * @var array
36: */
37: public $settings = array();
38:
39: /**
40: * Initialize the Cache Engine
41: *
42: * Called automatically by the cache frontend
43: * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
44: *
45: * @param array $settings array of setting for the engine
46: * @return boolean True if the engine has been successfully initialized, false if not
47: */
48: public function init($settings = array()) {
49: if (php_sapi_name() !== 'cli') {
50: parent::init(array_merge(array(
51: 'engine' => 'Xcache',
52: 'prefix' => Inflector::slug(APP_DIR) . '_',
53: 'PHP_AUTH_USER' => 'user',
54: 'PHP_AUTH_PW' => 'password'
55: ), $settings)
56: );
57: return function_exists('xcache_info');
58: }
59: return false;
60: }
61:
62: /**
63: * Write data for key into cache
64: *
65: * @param string $key Identifier for the data
66: * @param mixed $value Data to be cached
67: * @param integer $duration How long to cache the data, in seconds
68: * @return boolean True if the data was successfully cached, false on failure
69: */
70: public function write($key, $value, $duration) {
71: $expires = time() + $duration;
72: xcache_set($key . '_expires', $expires, $duration);
73: return xcache_set($key, $value, $duration);
74: }
75:
76: /**
77: * Read a key from the cache
78: *
79: * @param string $key Identifier for the data
80: * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
81: */
82: public function read($key) {
83: if (xcache_isset($key)) {
84: $time = time();
85: $cachetime = intval(xcache_get($key . '_expires'));
86: if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
87: return false;
88: }
89: return xcache_get($key);
90: }
91: return false;
92: }
93:
94: /**
95: * Increments the value of an integer cached key
96: * If the cache key is not an integer it will be treated as 0
97: *
98: * @param string $key Identifier for the data
99: * @param integer $offset How much to increment
100: * @return New incremented value, false otherwise
101: */
102: public function increment($key, $offset = 1) {
103: return xcache_inc($key, $offset);
104: }
105:
106: /**
107: * Decrements the value of an integer cached key.
108: * If the cache key is not an integer it will be treated as 0
109: *
110: * @param string $key Identifier for the data
111: * @param integer $offset How much to subtract
112: * @return New decremented value, false otherwise
113: */
114: public function decrement($key, $offset = 1) {
115: return xcache_dec($key, $offset);
116: }
117:
118: /**
119: * Delete a key from the cache
120: *
121: * @param string $key Identifier for the data
122: * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
123: */
124: public function delete($key) {
125: return xcache_unset($key);
126: }
127:
128: /**
129: * Delete all keys from the cache
130: *
131: * @param boolean $check
132: * @return boolean True if the cache was successfully cleared, false otherwise
133: */
134: public function clear($check) {
135: $this->_auth();
136: $max = xcache_count(XC_TYPE_VAR);
137: for ($i = 0; $i < $max; $i++) {
138: xcache_clear_cache(XC_TYPE_VAR, $i);
139: }
140: $this->_auth(true);
141: return true;
142: }
143:
144: /**
145: * Returns the `group value` for each of the configured groups
146: * If the group initial value was not found, then it initializes
147: * the group accordingly.
148: *
149: * @return array
150: */
151: public function groups() {
152: $result = array();
153: foreach ($this->settings['groups'] as $group) {
154: $value = xcache_get($this->settings['prefix'] . $group);
155: if (!$value) {
156: $value = 1;
157: xcache_set($this->settings['prefix'] . $group, $value, 0);
158: }
159: $result[] = $group . $value;
160: }
161: return $result;
162: }
163:
164: /**
165: * Increments the group value to simulate deletion of all keys under a group
166: * old values will remain in storage until they expire.
167: *
168: * @return boolean success
169: */
170: public function clearGroup($group) {
171: return (bool)xcache_inc($this->settings['prefix'] . $group, 1);
172: }
173:
174: /**
175: * Populates and reverses $_SERVER authentication values
176: * Makes necessary changes (and reverting them back) in $_SERVER
177: *
178: * This has to be done because xcache_clear_cache() needs to pass Basic Http Auth
179: * (see xcache.admin configuration settings)
180: *
181: * @param boolean $reverse Revert changes
182: * @return void
183: */
184: protected function _auth($reverse = false) {
185: static $backup = array();
186: $keys = array('PHP_AUTH_USER' => 'user', 'PHP_AUTH_PW' => 'password');
187: foreach ($keys as $key => $setting) {
188: if ($reverse) {
189: if (isset($backup[$key])) {
190: $_SERVER[$key] = $backup[$key];
191: unset($backup[$key]);
192: } else {
193: unset($_SERVER[$key]);
194: }
195: } else {
196: $value = env($key);
197: if (!empty($value)) {
198: $backup[$key] = $value;
199: }
200: if (!empty($this->settings[$setting])) {
201: $_SERVER[$key] = $this->settings[$setting];
202: } elseif (!empty($this->settings[$key])) {
203: $_SERVER[$key] = $this->settings[$key];
204: } else {
205: $_SERVER[$key] = $value;
206: }
207: }
208: }
209: }
210: }
211: