/library/Zend/Cache/Frontend/Function.php
PHP | 179 lines | 87 code | 15 blank | 77 comment | 12 complexity | 82cde971206fba9e320bfbcfc6484bf3 MD5 | raw file
Possible License(s): AGPL-1.0
1<?php
2/**
3 * Zend Framework
4 *
5 * LICENSE
6 *
7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
14 *
15 * @category Zend
16 * @package Zend_Cache
17 * @subpackage Zend_Cache_Frontend
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Function.php 24594 2012-01-05 21:27:01Z matthew $
21 */
22
23
24/**
25 * @see Zend_Cache_Core
26 */
27require_once 'Zend/Cache/Core.php';
28
29
30/**
31 * @package Zend_Cache
32 * @subpackage Zend_Cache_Frontend
33 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
34 * @license http://framework.zend.com/license/new-bsd New BSD License
35 */
36class Zend_Cache_Frontend_Function extends Zend_Cache_Core
37{
38 /**
39 * This frontend specific options
40 *
41 * ====> (boolean) cache_by_default :
42 * - if true, function calls will be cached by default
43 *
44 * ====> (array) cached_functions :
45 * - an array of function names which will be cached (even if cache_by_default = false)
46 *
47 * ====> (array) non_cached_functions :
48 * - an array of function names which won't be cached (even if cache_by_default = true)
49 *
50 * @var array options
51 */
52 protected $_specificOptions = array(
53 'cache_by_default' => true,
54 'cached_functions' => array(),
55 'non_cached_functions' => array()
56 );
57
58 /**
59 * Constructor
60 *
61 * @param array $options Associative array of options
62 * @return void
63 */
64 public function __construct(array $options = array())
65 {
66 while (list($name, $value) = each($options)) {
67 $this->setOption($name, $value);
68 }
69 $this->setOption('automatic_serialization', true);
70 }
71
72 /**
73 * Main method : call the specified function or get the result from cache
74 *
75 * @param callback $callback A valid callback
76 * @param array $parameters Function parameters
77 * @param array $tags Cache tags
78 * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
79 * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
80 * @return mixed Result
81 */
82 public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
83 {
84 if (!is_callable($callback, true, $name)) {
85 Zend_Cache::throwException('Invalid callback');
86 }
87
88 $cacheBool1 = $this->_specificOptions['cache_by_default'];
89 $cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']);
90 $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']);
91 $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
92 if (!$cache) {
93 // Caching of this callback is disabled
94 return call_user_func_array($callback, $parameters);
95 }
96
97 $id = $this->_makeId($callback, $parameters);
98 if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) {
99 // A cache is available
100 $output = $rs[0];
101 $return = $rs[1];
102 } else {
103 // A cache is not available (or not valid for this frontend)
104 ob_start();
105 ob_implicit_flush(false);
106 $return = call_user_func_array($callback, $parameters);
107 $output = ob_get_clean();
108 $data = array($output, $return);
109 $this->save($data, $id, $tags, $specificLifetime, $priority);
110 }
111
112 echo $output;
113 return $return;
114 }
115
116 /**
117 * ZF-9970
118 *
119 * @deprecated
120 */
121 private function _makeId($callback, array $args)
122 {
123 return $this->makeId($callback, $args);
124 }
125
126 /**
127 * Make a cache id from the function name and parameters
128 *
129 * @param callback $callback A valid callback
130 * @param array $args Function parameters
131 * @throws Zend_Cache_Exception
132 * @return string Cache id
133 */
134 public function makeId($callback, array $args = array())
135 {
136 if (!is_callable($callback, true, $name)) {
137 Zend_Cache::throwException('Invalid callback');
138 }
139
140 // functions, methods and classnames are case-insensitive
141 $name = strtolower($name);
142
143 // generate a unique id for object callbacks
144 if (is_object($callback)) { // Closures & __invoke
145 $object = $callback;
146 } elseif (isset($callback[0])) { // array($object, 'method')
147 $object = $callback[0];
148 }
149 if (isset($object)) {
150 try {
151 $tmp = @serialize($callback);
152 } catch (Exception $e) {
153 Zend_Cache::throwException($e->getMessage());
154 }
155 if (!$tmp) {
156 $lastErr = error_get_last();
157 Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}");
158 }
159 $name.= '__' . $tmp;
160 }
161
162 // generate a unique id for arguments
163 $argsStr = '';
164 if ($args) {
165 try {
166 $argsStr = @serialize(array_values($args));
167 } catch (Exception $e) {
168 Zend_Cache::throwException($e->getMessage());
169 }
170 if (!$argsStr) {
171 $lastErr = error_get_last();
172 throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}");
173 }
174 }
175
176 return md5($name . $argsStr);
177 }
178
179}