| 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 <[email protected]> |
|---|
| 15 | * @author Fabien MARTY <[email protected]> |
|---|
| 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 | } |
|---|