1<?php
2// +----------------------------------------------------------------------+
3// | PEAR :: Cache                                                        |
4// +----------------------------------------------------------------------+
5// | Copyright (c) 1997-2003 The PHP Group                                |
6// +----------------------------------------------------------------------+
7// | This source file is subject to version 2.0 of the PHP license,       |
8// | that is bundled with this package in the file LICENSE, and is        |
9// | available at through the world-wide-web at                           |
10// | http://www.php.net/license/2_02.txt.                                 |
11// | If you did not receive a copy of the PHP license and are unable to   |
12// | obtain it through the world-wide-web, please send a note to          |
13// | license@php.net so we can mail you a copy immediately.               |
14// +----------------------------------------------------------------------+
15// | Authors: Sebastian Bergmann <sb@sebastian-bergmann.de>               |
16// +----------------------------------------------------------------------+
17//
18// $Id: Function.php 174777 2004-12-15 09:09:33Z dufuz $
19
20require_once 'Cache.php';
21
22/**
23* Function_Cache
24*
25* Purpose:
26*
27*   Caching the result and output of functions.
28*
29* Example:
30*
31*   require_once 'Cache/Function.php';
32*
33*   class foo {
34*     function bar($test) {
35*       echo "foo::bar($test)<br>";
36*     }
37*   }
38*
39*   class bar {
40*     function foobar($object) {
41*       echo '$'.$object.'->foobar('.$object.')<br>';
42*     }
43*   }
44*
45*   $bar = new bar;
46*
47*   function foobar() {
48*     echo 'foobar()';
49*   }
50*
51*   $cache = new Cache_Function();
52*
53*   $cache->call('foo::bar', 'test');
54*   $cache->call('bar->foobar', 'bar');
55*   $cache->call('foobar');
56*
57* Note:
58*
59*   You cannot cache every function. You should only cache
60*   functions that only depend on their arguments and don't use
61*   global or static variables, don't rely on database queries or
62*   files, and so on.
63*
64* @author       Sebastian Bergmann <sb@sebastian-bergmann.de>
65* @module       Function_Cache
66* @modulegroup  Function_Cache
67* @package      Cache
68* @version      $Revision: 174777 $
69* @access       public
70*/
71class Cache_Function extends Cache
72{
73    var $expires;
74
75    /**
76    * Constructor
77    *
78    * @param    string  Name of container class
79    * @param    array   Array with container class options
80    * @param    integer Number of seconds for which to cache
81    */
82    function Cache_Function($container  = 'file',
83                            $container_options = array('cache_dir'       => '.',
84                                                       'filename_prefix' => 'cache_'
85                                                      ),
86                            $expires = 3600
87                           )
88    {
89      $this->Cache($container, $container_options);
90      $this->expires = $expires;
91    }
92
93    /**
94    * PEAR-Deconstructor
95    * Call deconstructor of parent
96    */
97    function _Cache_Function()
98    {
99        $this->_Cache();
100    }
101
102    /**
103    * Calls a cacheable function or method.
104    *
105    * @return mixed $result
106    * @access public
107    */
108    function call()
109    {
110        // get arguments
111        $arguments = func_get_args();
112
113        // generate cache id
114        $id = md5(serialize($arguments));
115
116        // query cache
117        $cached_object = $this->get($id, 'function_cache');
118
119        if ($cached_object != null) {
120            // cache hit: return cached output and result
121
122            $output = $cached_object[0];
123            $result = $cached_object[1];
124
125        } else {
126            // cache miss: call function, store output and result in cache
127
128            ob_start();
129            $target = array_shift($arguments);
130
131            // classname::staticMethod
132            if (strstr($target, '::')) {
133                list($class, $method) = explode('::', $target);
134
135                $result = call_user_func_array(array($class, $method), $arguments);
136            } elseif (strstr($target, '->')) {
137                // object->method
138                list($object, $method) = explode('->', $target);
139                global $$object;
140
141                $result = call_user_func_array(array($$object, $method), $arguments);
142            } else {
143                // function
144                $result = call_user_func_array($target, $arguments);
145            }
146
147            $output = ob_get_contents();
148            ob_end_clean();
149
150            $this->save($id, array($output, $result), $this->expires, 'function_cache');
151        }
152
153        echo $output;
154        return $result;
155    }
156}
157?>
158