1: <?php
2: /**
3: * Wei Framework
4: *
5: * @copyright Copyright (c) 2008-2015 Twin Huang
6: * @license http://opensource.org/licenses/mit-license.php MIT License
7: */
8:
9: namespace Wei;
10:
11: /**
12: * The base class for cache services
13: *
14: * @author Twin Huang <twinhuang@qq.com>
15: */
16: abstract class BaseCache extends Base
17: {
18: /**
19: * The string prepend to the cache key
20: *
21: * @var string
22: */
23: protected $namespace = '';
24:
25: /**
26: * Retrieve or store an item
27: *
28: * @param string $key The name of item
29: * @param mixed $value The value of item
30: * @param int $expire The expire seconds, defaults to 0, means never expired
31: * @return mixed
32: */
33: public function __invoke($key, $value = null, $expire = 0)
34: {
35: if (1 == func_num_args()) {
36: return $this->get($key);
37: } else {
38: return $this->set($key, $value, $expire);
39: }
40: }
41:
42: /**
43: * Retrieve an item
44: *
45: * ```php
46: * $cache = wei()->cache;
47: *
48: * // Retrieve cache by key
49: * $cache->get('key');
50: *
51: * // Get cache value from callback
52: * $cache->get('key', function($wei){
53: * return 'value';
54: * });
55: *
56: * // Get cache value from callback with timeout
57: * $cache->get('key', 10, function($wei){
58: * return 'value';
59: * });
60: * ```
61: *
62: * @param string $key The name of item
63: * @param int $expire The expire seconds of callback return value
64: * @param callable $fn The callback to execute when cache not found
65: * @throws \RuntimeException When set cache return false
66: * @return mixed
67: */
68: abstract public function get($key, $expire = null, $fn = null);
69:
70: /**
71: * Store data to cache when data is not false and callback is provided
72: *
73: * @param string $key
74: * @param mixed $result
75: * @param int $expire
76: * @param callable $fn
77: * @throws \RuntimeException
78: * @throws \InvalidArgumentException
79: * @return mixed
80: */
81: protected function processGetResult($key, $result, $expire, $fn)
82: {
83: if (false === $result && ($expire || $fn)) {
84: // Avoid using null as expire second, for null will be convert to 0
85: // which means that store the cache forever, and make it hart to debug.
86: if (!is_numeric($expire) && $fn) {
87: throw new \InvalidArgumentException(sprintf(
88: 'Expire time for cache "%s" must be numeric, %s given',
89: $key,
90: is_object($expire) ? get_class($expire) : gettype($expire)
91: ));
92: }
93:
94: // get($key, function(){});
95: if ($expire && !$fn) {
96: $fn = $expire;
97: $expire = 0;
98: }
99:
100: $result = call_user_func($fn, $this->wei, $this);
101: $setResult = $this->set($key, $result, $expire);
102:
103: if (false === $setResult) {
104: throw new \RuntimeException('Fail to store cache from callback', 1020);
105: }
106: }
107: return $result;
108: }
109:
110: /**
111: * Store an item
112: *
113: * @param string $key The name of item
114: * @param mixed $value The value of item
115: * @param int $expire The expire seconds, defaults to 0, means never expired
116: * @return bool
117: */
118: abstract public function set($key, $value, $expire = 0);
119:
120: /**
121: * Remove an item
122: *
123: * @param string $key The name of item
124: * @return bool
125: */
126: abstract public function remove($key);
127:
128: /**
129: * Check if an item is exists
130: *
131: * @param string $key
132: * @return bool
133: */
134: abstract public function exists($key);
135:
136: /**
137: * Add an item
138: *
139: * @param string $key The name of item
140: * @param mixed $value The value of item
141: * @param int $expire The expire seconds, defaults to 0, means never expired
142: * @return bool
143: */
144: abstract public function add($key, $value, $expire = 0);
145:
146: /**
147: * Replace an existing item
148: *
149: * @param string $key The name of item
150: * @param mixed $value The value of item
151: * @param int $expire The expire seconds, defaults to 0, means never expired
152: * @return bool
153: */
154: abstract public function replace($key, $value, $expire = 0);
155:
156: /**
157: * Increment an item
158: *
159: * @param string $key The name of item
160: * @param int $offset The value to increased
161: * @return int|false Returns the new value on success, or false on failure
162: */
163: abstract public function incr($key, $offset = 1);
164:
165: /**
166: * Decrement an item
167: *
168: * @param string $key The name of item
169: * @param int $offset The value to be decreased
170: * @return int|false Returns the new value on success, or false on failure
171: */
172: public function decr($key, $offset = 1)
173: {
174: return $this->incr($key, -$offset);
175: }
176:
177: /**
178: * Retrieve multiple items
179: *
180: * @param array $keys The name of items
181: * @return array
182: */
183: public function getMulti(array $keys)
184: {
185: $results = array();
186: foreach ($keys as $key) {
187: $results[$key] = $this->get($key);
188: }
189: return $results;
190: }
191:
192: /**
193: * Store multiple items
194: *
195: * @param array $keys The name of items
196: * @param int $expire
197: * @return array
198: */
199: public function setMulti(array $keys, $expire = 0)
200: {
201: $results = array();
202: foreach ($keys as $key => $value) {
203: $results[$key] = $this->set($key, $value, $expire);
204: }
205: return $results;
206: }
207:
208: /**
209: * Use the file modify time as cache key to store an item from a callback
210: *
211: * @param string $file The path of file
212: * @param callable $fn The callback to get and parse file content
213: * @return mixed
214: */
215: public function getFileContent($file, $fn)
216: {
217: $key = $file . filemtime($file);
218: return $this->get($key, function($wei, $cache) use ($file, $fn) {
219: return $fn($file, $wei, $cache);
220: });
221: }
222:
223: /**
224: * Returns the key prefix
225: *
226: * @return string
227: */
228: public function getNamespace()
229: {
230: return $this->namespace;
231: }
232:
233: /**
234: * Set the cache key prefix
235: *
236: * @param string $namespace
237: * @return $this
238: */
239: public function setNamespace($namespace)
240: {
241: $this->namespace = $namespace;
242: return $this;
243: }
244:
245: /**
246: * Clear all items
247: *
248: * @return boolean
249: */
250: abstract public function clear();
251: }
252: