Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
4
 
5
// LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
6
 
7
/**
8
* +-----------------------------------------------------------------------------+
9
* | Copyright (c) 2004 Sérgio Gonçalves Carvalho                                |
10
* +-----------------------------------------------------------------------------+
11
* | This file is part of XML_RPC2.                                              |
12
* |                                                                             |
13
* | XML_RPC2 is free software; you can redistribute it and/or modify            |
14
* | it under the terms of the GNU Lesser General Public License as published by |
15
* | the Free Software Foundation; either version 2.1 of the License, or         |
16
* | (at your option) any later version.                                         |
17
* |                                                                             |
18
* | XML_RPC2 is distributed in the hope that it will be useful,                 |
19
* | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
20
* | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
21
* | GNU Lesser General Public License for more details.                         |
22
* |                                                                             |
23
* | You should have received a copy of the GNU Lesser General Public License    |
24
* | along with XML_RPC2; if not, write to the Free Software                     |
25
* | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
26
* | 02111-1307 USA                                                              |
27
* +-----------------------------------------------------------------------------+
28
* | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
29
* +-----------------------------------------------------------------------------+
30
*
31
* @category   XML
32
* @package    XML_RPC2
33
* @author     Fabien MARTY <fab@php.net>
34
* @copyright  2005-2006 Fabien MARTY
35
* @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
36
* @version    CVS: $Id: CachedClient.php 209835 2006-03-21 20:38:18Z fab $
37
* @link       http://pear.php.net/package/XML_RPC2
38
*/
39
 
40
// }}}
41
 
42
// dependencies {{{
43
require_once('Cache/Lite.php');
44
require_once('XML/RPC2/Exception.php');
45
// }}}
46
 
47
/**
48
 * XML_RPC "cached client" class.
49
 *
50
 * @category   XML
51
 * @package    XML_RPC2
52
 * @author     Fabien MARTY <fab@php.net>
53
 * @copyright  2005-2006 Fabien MARTY
54
 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
55
 * @link       http://pear.php.net/package/XML_RPC2
56
 */
57
class XML_RPC2_CachedClient {
58
 
59
    // {{{ properties
60
 
61
    /**
62
     * Associative array of options for XML_RPC2_Client
63
     *
64
     * @var array
65
     */
66
    private $_options;
67
 
68
    /**
69
     * uri Field (holds the uri for the XML_RPC server)
70
     *
71
     * @var array
72
     */
73
    private $_uri;
74
 
75
    /**
76
     * Holds the debug flag
77
     *
78
     * @var boolean
79
     */
80
    private $_debug = false;
81
 
82
    /**
83
     * Cache_Lite options array
84
     *
85
     * @var array
86
     */
87
    private $_cacheOptions = array();
88
 
89
    /**
90
     * Cached methods array (usefull only if cache is off by default)
91
     *
92
     * example1 : array('method1ToCache', 'method2ToCache', ...)
93
     * example2 (with specific cache lifetime) :
94
     * array('method1ToCache' => 3600, 'method2ToCache' => 60, ...)
95
     * NB : a lifetime value of -1 means "no cache for this method"
96
     *
97
     * @var array
98
     */
99
    private $_cachedMethods = array();
100
 
101
    /**
102
     * Non-Cached methods array (usefull only if cache is on by default)
103
     *
104
     * example : array('method1ToCache', 'method2ToCache', ...)
105
     *
106
     * @var array
107
     */
108
    private $_notCachedMethods = array();
109
 
110
    /**
111
     * cache by default
112
     *
113
     * @var boolean
114
     */
115
    private $_cacheByDefault = true;
116
 
117
    /**
118
     * Cache_Lite object
119
     *
120
     * @var object
121
     */
122
    private $_cacheObject = null;
123
 
124
    /**
125
     * XML_RPC2_Client object (if needed, dynamically built)
126
     *
127
     * @var object
128
     */
129
    private $_clientObject = null;
130
 
131
    /**
132
     * Default cache group for XML_RPC client caching
133
     *
134
     * @var string
135
     */
136
    private $_defaultCacheGroup = 'xml_rpc2_client';
137
 
138
    /**
139
     * "cache debug" flag (for debugging the caching process)
140
     *
141
     * @var boolean
142
     */
143
    private $_cacheDebug = false;
144
 
145
    // }}}
146
    // {{{ constructor
147
 
148
    /**
149
     * Constructor
150
     *
151
     * TODO : documentations about cache options
152
     *
153
     * @param string URI for the XML-RPC server
154
     * @param array (optional) Associative array of options
155
     */
156
    protected function __construct($uri, $options = array())
157
    {
158
        if (isset($options['cacheOptions'])) {
159
            $array = $options['cacheOptions'];
160
            if (isset($array['defaultCacheGroup'])) {
161
                $this->_defaultCacheGroup = $array['defaultCacheGroup'];
162
                unset($array['defaultCacheGroup']); // this is a "non standard" option for Cache_Lite
163
            }
164
            if (isset($array['cachedMethods'])) {
165
                $this->_cachedMethods = $array['cachedMethods'];
166
                unset($array['cachedMethods']); // this is a "non standard" option for Cache_Lite
167
            }
168
            if (isset($array['notCachedMethods'])) {
169
                $this->_notCachedMethods = $array['notCachedMethods'];
170
                unset($array['notCachedMethods']); // this is a "non standard" option for Cache_Lite
171
            }
172
            if (isset($array['cacheByDefault'])) {
173
                $this->_cacheByDefault = $array['cacheByDefault'];
174
                unset($array['CacheByDefault']); // this is a "non standard" option for Cache_Lite
175
            }
176
            $array['automaticSerialization'] = false; // datas are already serialized in this class
177
            if (!isset($array['lifetime'])) {
178
                $array['lifetime'] = 3600; // we need a default lifetime
179
            }
180
            unset($options['cacheOptions']); // this is a "non standard" option for XML/RPC2/Client
181
        } else { // no cache options ?
182
            $array = array(
183
                'lifetime' => 3600,               // we need a default lifetime
184
                'automaticSerialization' => false // datas are already serialized in this class
185
            );
186
        }
187
        if (isset($options['cacheDebug'])) {
188
            $this->_cacheDebug = $options['cacheDebug'];
189
            unset($options['cacheDebug']); // this a "non standard" option for XML/RPC2/Client
190
        }
191
        $this->_cacheOptions = $array;
192
        $this->_cacheObject = new Cache_Lite($this->_cacheOptions);
193
        $this->_options = $options;
194
        $this->_uri = $uri;
195
    }
196
 
197
    // }}}
198
    // {{{ create()
199
 
200
    /**
201
     * "Emulated Factory" method to get the same API than XML_RPC2_Client class
202
     *
203
     * Here, simply returns a new instance of XML_RPC2_CachedClient class
204
     *
205
     * @param string URI for the XML-RPC server
206
     * @param string (optional)  Prefix to prepend on all called functions (defaults to '')
207
     * @param string (optional)  Proxy server URI (defaults to no proxy)
208
     *
209
     */
210
    public static function create($uri, $options = array())
211
    {
212
        return new XML_RPC2_CachedClient($uri, $options);
213
    }
214
 
215
    // }}}
216
    // {{{ __call()
217
 
218
    /**
219
     * __call Catchall
220
     *
221
     * Encapsulate all the class logic :
222
     * - determine if the cache has to be used (or not) for the called method
223
     * - see if a cache is available for this call
224
     * - if no cache available, really do the call and store the result for next time
225
     *
226
     * @param   string      Method name
227
     * @param   array       Parameters
228
     * @return  mixed       The call result, already decoded into native types
229
     */
230
    public function __call($methodName, $parameters)
231
    {
232
        if (!isset($this->_cacheObject)) {
233
            $this->_cacheObject = new Cache_Lite($this->_cacheOptions);
234
        }
235
        if (in_array($methodName, $this->_notCachedMethods)) {
236
            // if the called method is listed in _notCachedMethods => no cache
237
            if ($this->_cacheDebug) {
238
                print "CACHE DEBUG : the called method is listed in _notCachedMethods => no cache !\n";
239
            }
240
            return $this->_workWithoutCache___($methodName, $parameters);
241
        }
242
        if (!($this->_cacheByDefault)) {
243
            if ((!(isset($this->_cachedMethods[$methodName]))) and (!(in_array($methodName, $this->_cachedMethods)))) {
244
                // if cache is not on by default and if the called method is not described in _cachedMethods array
245
                // => no cache
246
                if ($this->_cacheDebug) {
247
                    print "CACHE DEBUG : cache is not on by default and the called method is not listed in _cachedMethods => no cache !\n";
248
                }
249
                return $this->_workWithoutCache___($methodName, $parameters);
250
            }
251
        }
252
        if (isset($this->_cachedMethods[$methodName])) {
253
            if ($this->_cachedMethods[$methodName] == -1) {
254
                // if a method is described with a lifetime value of -1 => no cache
255
                if ($this->_cacheDebug) {
256
                    print "CACHE DEBUG : called method has a -1 lifetime value => no cache !\n";
257
                }
258
                return $this->_workWithoutCache___($methodName, $parameters);
259
            }
260
            // if a method is described with a specific (and <> -1) lifetime
261
            // => we fix this new lifetime
262
            $this->_cacheObject->setLifetime($this->_cachedMethods[$methodName]);
263
        } else {
264
            // there is no specific lifetime, let's use the default one
265
            $this->_cacheObject->setLifetime($this->_cacheOptions['lifetime']);
266
        }
267
        $cacheId = $this->_makeCacheId___($methodName, $parameters);
268
        $data = $this->_cacheObject->get($cacheId, $this->_defaultCacheGroup);
269
        if (is_string($data)) {
270
            // cache is hit !
271
            if ($this->_cacheDebug) {
272
                print "CACHE DEBUG : cache is hit !\n";
273
            }
274
            return unserialize($data);
275
        }
276
        // the cache is not hit, let's call the "real" XML_RPC client
277
        if ($this->_cacheDebug) {
278
            print "CACHE DEBUG : cache is not hit !\n";
279
        }
280
        $result = $this->_workWithoutCache___($methodName, $parameters);
281
        $this->_cacheObject->save(serialize($result)); // save in cache for next time...
282
        return $result;
283
    }
284
 
285
    // }}}
286
    // {{{ _workWithoutCache___()
287
 
288
    /**
289
     * Do the real call if no cache available
290
     *
291
     * NB : The '___' at the end of the method name is to avoid collisions with
292
     * XMLRPC __call()
293
     *
294
     * @param   string      Method name
295
     * @param   array       Parameters
296
     * @return  mixed       The call result, already decoded into native types
297
     */
298
    private function _workWithoutCache___($methodName, $parameters)
299
    {
300
        if (!(isset($this->_clientObject))) {
301
            // If the XML_RPC2_Client object is not available, let's build it
302
            require_once('XML/RPC2/Client.php');
303
            $this->_clientObject = XML_RPC2_Client::create($this->_uri, $this->_options);
304
        }
305
        // the real function call...
306
        return call_user_func_array(array($this->_clientObject, $methodName), $parameters);
307
    }
308
 
309
    // }}}
310
    // {{{ _makeCacheId___()
311
 
312
    /**
313
     * make a cache id depending on method called (and corresponding parameters) but depending on "environnement" setting too
314
     *
315
     * NB : The '___' at the end of the method name is to avoid collisions with
316
     * XMLRPC __call()
317
     *
318
     * @param string $methodName called method
319
     * @param array $parameters parameters of the called method
320
     * @return string cache id
321
     */
322
    private function _makeCacheId___($methodName, $parameters)
323
    {
324
        return md5($methodName . serialize($parameters) . serialize($this->_uri) . serialize($this->_options));
325
    }
326
 
327
    // }}}
328
    // {{{ dropCacheFile___()
329
 
330
    /**
331
     * Drop the cache file corresponding to the given method call
332
     *
333
     * NB : The '___' at the end of the method name is to avoid collisions with
334
     * XMLRPC __call()
335
     *
336
     * @param string $methodName called method
337
     * @param array $parameters parameters of the called method
338
     */
339
    public function dropCacheFile___($methodName, $parameters)
340
    {
341
        $id = $this->_makeCacheId___($methodName, $parameters);
342
        $this->_cacheObject->remove($id, $this->_defaultCacheGroup);
343
    }
344
 
345
    // }}}
346
    // {{{ clean___()
347
 
348
    /**
349
     * Clean all the cache
350
     *
351
     * NB : The '___' at the end of the method name is to avoid collisions with
352
     * XMLRPC __call()
353
     */
354
    public function clean___()
355
    {
356
        $this->_cacheObject->clean($this->_defaultCacheGroup, 'ingroup');
357
    }
358
 
359
}
360
 
361
?>