|
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-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
20 * @version $Id: Class.php 23051 2010-10-07 17:01:21Z mabe $ |
|
21 */ |
|
22 |
|
23 /** |
|
24 * @see Zend_Cache_Core |
|
25 */ |
|
26 require_once 'Zend/Cache/Core.php'; |
|
27 |
|
28 |
|
29 /** |
|
30 * @package Zend_Cache |
|
31 * @subpackage Zend_Cache_Frontend |
|
32 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
33 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
34 */ |
|
35 class Zend_Cache_Frontend_Class extends Zend_Cache_Core |
|
36 { |
|
37 /** |
|
38 * Available options |
|
39 * |
|
40 * ====> (mixed) cached_entity : |
|
41 * - if set to a class name, we will cache an abstract class and will use only static calls |
|
42 * - if set to an object, we will cache this object methods |
|
43 * |
|
44 * ====> (boolean) cache_by_default : |
|
45 * - if true, method calls will be cached by default |
|
46 * |
|
47 * ====> (array) cached_methods : |
|
48 * - an array of method names which will be cached (even if cache_by_default = false) |
|
49 * |
|
50 * ====> (array) non_cached_methods : |
|
51 * - an array of method names which won't be cached (even if cache_by_default = true) |
|
52 * |
|
53 * @var array available options |
|
54 */ |
|
55 protected $_specificOptions = array( |
|
56 'cached_entity' => null, |
|
57 'cache_by_default' => true, |
|
58 'cached_methods' => array(), |
|
59 'non_cached_methods' => array() |
|
60 ); |
|
61 |
|
62 /** |
|
63 * Tags array |
|
64 * |
|
65 * @var array |
|
66 */ |
|
67 private $_tags = array(); |
|
68 |
|
69 /** |
|
70 * SpecificLifetime value |
|
71 * |
|
72 * false => no specific life time |
|
73 * |
|
74 * @var int |
|
75 */ |
|
76 private $_specificLifetime = false; |
|
77 |
|
78 /** |
|
79 * The cached object or the name of the cached abstract class |
|
80 * |
|
81 * @var mixed |
|
82 */ |
|
83 private $_cachedEntity = null; |
|
84 |
|
85 /** |
|
86 * The class name of the cached object or cached abstract class |
|
87 * |
|
88 * Used to differentiate between different classes with the same method calls. |
|
89 * |
|
90 * @var string |
|
91 */ |
|
92 private $_cachedEntityLabel = ''; |
|
93 |
|
94 /** |
|
95 * Priority (used by some particular backends) |
|
96 * |
|
97 * @var int |
|
98 */ |
|
99 private $_priority = 8; |
|
100 |
|
101 /** |
|
102 * Constructor |
|
103 * |
|
104 * @param array $options Associative array of options |
|
105 * @throws Zend_Cache_Exception |
|
106 * @return void |
|
107 */ |
|
108 public function __construct(array $options = array()) |
|
109 { |
|
110 while (list($name, $value) = each($options)) { |
|
111 $this->setOption($name, $value); |
|
112 } |
|
113 if ($this->_specificOptions['cached_entity'] === null) { |
|
114 Zend_Cache::throwException('cached_entity must be set !'); |
|
115 } |
|
116 $this->setCachedEntity($this->_specificOptions['cached_entity']); |
|
117 $this->setOption('automatic_serialization', true); |
|
118 } |
|
119 |
|
120 /** |
|
121 * Set a specific life time |
|
122 * |
|
123 * @param int $specificLifetime |
|
124 * @return void |
|
125 */ |
|
126 public function setSpecificLifetime($specificLifetime = false) |
|
127 { |
|
128 $this->_specificLifetime = $specificLifetime; |
|
129 } |
|
130 |
|
131 /** |
|
132 * Set the priority (used by some particular backends) |
|
133 * |
|
134 * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) |
|
135 */ |
|
136 public function setPriority($priority) |
|
137 { |
|
138 $this->_priority = $priority; |
|
139 } |
|
140 |
|
141 /** |
|
142 * Public frontend to set an option |
|
143 * |
|
144 * Just a wrapper to get a specific behaviour for cached_entity |
|
145 * |
|
146 * @param string $name Name of the option |
|
147 * @param mixed $value Value of the option |
|
148 * @throws Zend_Cache_Exception |
|
149 * @return void |
|
150 */ |
|
151 public function setOption($name, $value) |
|
152 { |
|
153 if ($name == 'cached_entity') { |
|
154 $this->setCachedEntity($value); |
|
155 } else { |
|
156 parent::setOption($name, $value); |
|
157 } |
|
158 } |
|
159 |
|
160 /** |
|
161 * Specific method to set the cachedEntity |
|
162 * |
|
163 * if set to a class name, we will cache an abstract class and will use only static calls |
|
164 * if set to an object, we will cache this object methods |
|
165 * |
|
166 * @param mixed $cachedEntity |
|
167 */ |
|
168 public function setCachedEntity($cachedEntity) |
|
169 { |
|
170 if (!is_string($cachedEntity) && !is_object($cachedEntity)) { |
|
171 Zend_Cache::throwException('cached_entity must be an object or a class name'); |
|
172 } |
|
173 $this->_cachedEntity = $cachedEntity; |
|
174 $this->_specificOptions['cached_entity'] = $cachedEntity; |
|
175 if (is_string($this->_cachedEntity)){ |
|
176 $this->_cachedEntityLabel = $this->_cachedEntity; |
|
177 } else { |
|
178 $ro = new ReflectionObject($this->_cachedEntity); |
|
179 $this->_cachedEntityLabel = $ro->getName(); |
|
180 } |
|
181 } |
|
182 |
|
183 /** |
|
184 * Set the cache array |
|
185 * |
|
186 * @param array $tags |
|
187 * @return void |
|
188 */ |
|
189 public function setTagsArray($tags = array()) |
|
190 { |
|
191 $this->_tags = $tags; |
|
192 } |
|
193 |
|
194 /** |
|
195 * Main method : call the specified method or get the result from cache |
|
196 * |
|
197 * @param string $name Method name |
|
198 * @param array $parameters Method parameters |
|
199 * @return mixed Result |
|
200 */ |
|
201 public function __call($name, $parameters) |
|
202 { |
|
203 $cacheBool1 = $this->_specificOptions['cache_by_default']; |
|
204 $cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']); |
|
205 $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']); |
|
206 $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3)); |
|
207 if (!$cache) { |
|
208 // We do not have not cache |
|
209 return call_user_func_array(array($this->_cachedEntity, $name), $parameters); |
|
210 } |
|
211 |
|
212 $id = $this->_makeId($name, $parameters); |
|
213 if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1]) ) { |
|
214 // A cache is available |
|
215 $output = $rs[0]; |
|
216 $return = $rs[1]; |
|
217 } else { |
|
218 // A cache is not available (or not valid for this frontend) |
|
219 ob_start(); |
|
220 ob_implicit_flush(false); |
|
221 |
|
222 try { |
|
223 $return = call_user_func_array(array($this->_cachedEntity, $name), $parameters); |
|
224 $output = ob_get_clean(); |
|
225 $data = array($output, $return); |
|
226 $this->save($data, $id, $this->_tags, $this->_specificLifetime, $this->_priority); |
|
227 } catch (Exception $e) { |
|
228 ob_end_clean(); |
|
229 throw $e; |
|
230 } |
|
231 } |
|
232 |
|
233 echo $output; |
|
234 return $return; |
|
235 } |
|
236 |
|
237 /** |
|
238 * ZF-9970 |
|
239 * |
|
240 * @deprecated |
|
241 */ |
|
242 private function _makeId($name, $args) |
|
243 { |
|
244 return $this->makeId($name, $args); |
|
245 } |
|
246 |
|
247 /** |
|
248 * Make a cache id from the method name and parameters |
|
249 * |
|
250 * @param string $name Method name |
|
251 * @param array $args Method parameters |
|
252 * @return string Cache id |
|
253 */ |
|
254 public function makeId($name, array $args = array()) |
|
255 { |
|
256 return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($args)); |
|
257 } |
|
258 |
|
259 } |