source: branches/version-2_12-dev/data/module/Cache/Lite/Function.php @ 22587

Revision 22587, 7.0 KB checked in by pineray, 11 years ago (diff)

#2167 汎用のキャッシュ機能

Line 
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
18require_once('Cache/Lite.php');
19
20class 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}
Note: See TracBrowser for help on using the repository browser.