1 | <?php |
---|
2 | |
---|
3 | /** |
---|
4 | * This class extends Cache_Lite and can be used to cache the result and output of functions/methods |
---|
5 | * |
---|
6 | * This class is completly inspired from Sebastian Bergmann's |
---|
7 | * PEAR/Cache_Function class. This is only an adaptation to |
---|
8 | * Cache_Lite |
---|
9 | * |
---|
10 | * There are some examples in the 'docs/examples' file |
---|
11 | * Technical choices are described in the 'docs/technical' file |
---|
12 | * |
---|
13 | * @package Cache_Lite |
---|
14 | * @author Sebastian BERGMANN <sb@sebastian-bergmann.de> |
---|
15 | * @author Fabien MARTY <fab@php.net> |
---|
16 | */ |
---|
17 | |
---|
18 | require_once('Cache/Lite.php'); |
---|
19 | |
---|
20 | class Cache_Lite_Function extends Cache_Lite |
---|
21 | { |
---|
22 | |
---|
23 | // --- Private properties --- |
---|
24 | |
---|
25 | /** |
---|
26 | * Default cache group for function caching |
---|
27 | * |
---|
28 | * @var string $_defaultGroup |
---|
29 | */ |
---|
30 | var $_defaultGroup = 'Cache_Lite_Function'; |
---|
31 | |
---|
32 | /** |
---|
33 | * Don't cache the method call when its output contains the string "NOCACHE" |
---|
34 | * |
---|
35 | * if set to true, the output of the method will never be displayed (because the output is used |
---|
36 | * to control the cache) |
---|
37 | * |
---|
38 | * @var boolean $_dontCacheWhenTheOutputContainsNOCACHE |
---|
39 | */ |
---|
40 | var $_dontCacheWhenTheOutputContainsNOCACHE = false; |
---|
41 | |
---|
42 | /** |
---|
43 | * Don't cache the method call when its result is false |
---|
44 | * |
---|
45 | * @var boolean $_dontCacheWhenTheResultIsFalse |
---|
46 | */ |
---|
47 | var $_dontCacheWhenTheResultIsFalse = false; |
---|
48 | |
---|
49 | /** |
---|
50 | * Don't cache the method call when its result is null |
---|
51 | * |
---|
52 | * @var boolean $_dontCacheWhenTheResultIsNull |
---|
53 | */ |
---|
54 | var $_dontCacheWhenTheResultIsNull = false; |
---|
55 | |
---|
56 | /** |
---|
57 | * Debug the Cache_Lite_Function caching process |
---|
58 | * |
---|
59 | * @var boolean $_debugCacheLiteFunction |
---|
60 | */ |
---|
61 | var $_debugCacheLiteFunction = false; |
---|
62 | |
---|
63 | // --- Public methods ---- |
---|
64 | |
---|
65 | /** |
---|
66 | * Constructor |
---|
67 | * |
---|
68 | * $options is an assoc. To have a look at availables options, |
---|
69 | * see the constructor of the Cache_Lite class in 'Cache_Lite.php' |
---|
70 | * |
---|
71 | * Comparing to Cache_Lite constructor, there is another option : |
---|
72 | * $options = array( |
---|
73 | * (...) see Cache_Lite constructor |
---|
74 | * 'debugCacheLiteFunction' => (bool) debug the caching process, |
---|
75 | * 'defaultGroup' => default cache group for function caching (string), |
---|
76 | * 'dontCacheWhenTheOutputContainsNOCACHE' => (bool) don't cache when the function output contains "NOCACHE", |
---|
77 | * 'dontCacheWhenTheResultIsFalse' => (bool) don't cache when the function result is false, |
---|
78 | * 'dontCacheWhenTheResultIsNull' => (bool don't cache when the function result is null |
---|
79 | * ); |
---|
80 | * |
---|
81 | * @param array $options options |
---|
82 | * @access public |
---|
83 | */ |
---|
84 | function Cache_Lite_Function($options = array(NULL)) |
---|
85 | { |
---|
86 | $availableOptions = array('debugCacheLiteFunction', 'defaultGroup', 'dontCacheWhenTheOutputContainsNOCACHE', 'dontCacheWhenTheResultIsFalse', 'dontCacheWhenTheResultIsNull'); |
---|
87 | while (list($name, $value) = each($options)) { |
---|
88 | if (in_array($name, $availableOptions)) { |
---|
89 | $property = '_'.$name; |
---|
90 | $this->$property = $value; |
---|
91 | } |
---|
92 | } |
---|
93 | reset($options); |
---|
94 | $this->Cache_Lite($options); |
---|
95 | } |
---|
96 | |
---|
97 | /** |
---|
98 | * Calls a cacheable function or method (or not if there is already a cache for it) |
---|
99 | * |
---|
100 | * Arguments of this method are read with func_get_args. So it doesn't appear |
---|
101 | * in the function definition. Synopsis : |
---|
102 | * call('functionName', $arg1, $arg2, ...) |
---|
103 | * (arg1, arg2... are arguments of 'functionName') |
---|
104 | * |
---|
105 | * @return mixed result of the function/method |
---|
106 | * @access public |
---|
107 | */ |
---|
108 | function call() |
---|
109 | { |
---|
110 | $arguments = func_get_args(); |
---|
111 | $id = $this->_makeId($arguments); |
---|
112 | $data = $this->get($id, $this->_defaultGroup); |
---|
113 | if ($data !== false) { |
---|
114 | if ($this->_debugCacheLiteFunction) { |
---|
115 | echo "Cache hit !\n"; |
---|
116 | } |
---|
117 | $array = unserialize($data); |
---|
118 | $output = $array['output']; |
---|
119 | $result = $array['result']; |
---|
120 | } else { |
---|
121 | if ($this->_debugCacheLiteFunction) { |
---|
122 | echo "Cache missed !\n"; |
---|
123 | } |
---|
124 | ob_start(); |
---|
125 | ob_implicit_flush(false); |
---|
126 | $target = array_shift($arguments); |
---|
127 | if (is_array($target)) { |
---|
128 | // in this case, $target is for example array($obj, 'method') |
---|
129 | $object = $target[0]; |
---|
130 | $method = $target[1]; |
---|
131 | $result = call_user_func_array(array(&$object, $method), $arguments); |
---|
132 | } else { |
---|
133 | if (strstr($target, '::')) { // classname::staticMethod |
---|
134 | list($class, $method) = explode('::', $target); |
---|
135 | $result = call_user_func_array(array($class, $method), $arguments); |
---|
136 | } else if (strstr($target, '->')) { // object->method |
---|
137 | // use a stupid name ($objet_123456789 because) of problems where the object |
---|
138 | // name is the same as this var name |
---|
139 | list($object_123456789, $method) = explode('->', $target); |
---|
140 | global $$object_123456789; |
---|
141 | $result = call_user_func_array(array($$object_123456789, $method), $arguments); |
---|
142 | } else { // function |
---|
143 | $result = call_user_func_array($target, $arguments); |
---|
144 | } |
---|
145 | } |
---|
146 | $output = ob_get_contents(); |
---|
147 | ob_end_clean(); |
---|
148 | if ($this->_dontCacheWhenTheResultIsFalse) { |
---|
149 | if ((is_bool($result)) && (!($result))) { |
---|
150 | echo($output); |
---|
151 | return $result; |
---|
152 | } |
---|
153 | } |
---|
154 | if ($this->_dontCacheWhenTheResultIsNull) { |
---|
155 | if (is_null($result)) { |
---|
156 | echo($output); |
---|
157 | return $result; |
---|
158 | } |
---|
159 | } |
---|
160 | if ($this->_dontCacheWhenTheOutputContainsNOCACHE) { |
---|
161 | if (strpos($output, 'NOCACHE') > -1) { |
---|
162 | return $result; |
---|
163 | } |
---|
164 | } |
---|
165 | $array['output'] = $output; |
---|
166 | $array['result'] = $result; |
---|
167 | $this->save(serialize($array), $id, $this->_defaultGroup); |
---|
168 | } |
---|
169 | echo($output); |
---|
170 | return $result; |
---|
171 | } |
---|
172 | |
---|
173 | /** |
---|
174 | * Drop a cache file |
---|
175 | * |
---|
176 | * Arguments of this method are read with func_get_args. So it doesn't appear |
---|
177 | * in the function definition. Synopsis : |
---|
178 | * remove('functionName', $arg1, $arg2, ...) |
---|
179 | * (arg1, arg2... are arguments of 'functionName') |
---|
180 | * |
---|
181 | * @return boolean true if no problem |
---|
182 | * @access public |
---|
183 | */ |
---|
184 | function drop() |
---|
185 | { |
---|
186 | $id = $this->_makeId(func_get_args()); |
---|
187 | return $this->remove($id, $this->_defaultGroup); |
---|
188 | } |
---|
189 | |
---|
190 | /** |
---|
191 | * Make an id for the cache |
---|
192 | * |
---|
193 | * @var array result of func_get_args for the call() or the remove() method |
---|
194 | * @return string id |
---|
195 | * @access private |
---|
196 | */ |
---|
197 | function _makeId($arguments) |
---|
198 | { |
---|
199 | $id = serialize($arguments); // Generate a cache id |
---|
200 | if (!$this->_fileNameProtection) { |
---|
201 | $id = md5($id); |
---|
202 | // if fileNameProtection is set to false, then the id has to be hashed |
---|
203 | // because it's a very bad file name in most cases |
---|
204 | } |
---|
205 | return $id; |
---|
206 | } |
---|
207 | |
---|
208 | } |
---|