1 : <?php
2 : /**
3 : * Smarty Internal Plugin
4 : *
5 : * @package Smarty
6 : * @subpackage Cacher
7 : */
8 :
9 : /**
10 : * Cache Handler API
11 : *
12 : * @package Smarty
13 : * @subpackage Cacher
14 : * @author Rodney Rehm
15 : */
16 : abstract class Smarty_CacheResource {
17 : /**
18 : * cache for Smarty_CacheResource instances
19 : * @var array
20 : */
21 : public static $resources = array();
22 :
23 : /**
24 : * resource types provided by the core
25 : * @var array
26 : */
27 : protected static $sysplugins = array(
28 : 'file' => true,
29 : );
30 :
31 : /**
32 : * populate Cached Object with meta data from Resource
33 : *
34 : * @param Smarty_Template_Cached $cached cached object
35 : * @param Smarty_Internal_Template $_template template object
36 : * @return void
37 : */
38 : public abstract function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template);
39 :
40 : /**
41 : * populate Cached Object with timestamp and exists from Resource
42 : *
43 : * @param Smarty_Template_Cached $source cached object
44 : * @return void
45 : */
46 : public abstract function populateTimestamp(Smarty_Template_Cached $cached);
47 :
48 : /**
49 : * Read the cached template and process header
50 : *
51 : * @param Smarty_Internal_Template $_template template object
52 : * @param Smarty_Template_Cached $cached cached object
53 : * @return booelan true or false if the cached content does not exist
54 : */
55 : public abstract function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null);
56 :
57 : /**
58 : * Write the rendered template output to cache
59 : *
60 : * @param Smarty_Internal_Template $_template template object
61 : * @param string $content content to cache
62 : * @return boolean success
63 : */
64 : public abstract function writeCachedContent(Smarty_Internal_Template $_template, $content);
65 :
66 : /**
67 : * Return cached content
68 : *
69 : * @param Smarty_Internal_Template $_template template object
70 : * @param string $content content of cache
71 : */
72 : public function getCachedContent(Smarty_Internal_Template $_template)
73 : {
74 0 : if ($_template->cached->handler->process($_template)) {
75 0 : ob_start();
76 0 : $_template->properties['unifunc']($_template);
77 0 : return ob_get_clean();
78 : }
79 0 : return null;
80 : }
81 :
82 : /**
83 : * Empty cache
84 : *
85 : * @param Smarty $smarty Smarty object
86 : * @param integer $exp_time expiration time (number of seconds, not timestamp)
87 : * @return integer number of cache files deleted
88 : */
89 : public abstract function clearAll(Smarty $smarty, $exp_time=null);
90 :
91 : /**
92 : * Empty cache for a specific template
93 : *
94 : * @param Smarty $smarty Smarty object
95 : * @param string $resource_name template name
96 : * @param string $cache_id cache id
97 : * @param string $compile_id compile id
98 : * @param integer $exp_time expiration time (number of seconds, not timestamp)
99 : * @return integer number of cache files deleted
100 : */
101 : public abstract function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time);
102 :
103 :
104 : public function locked(Smarty $smarty, Smarty_Template_Cached $cached)
105 : {
106 : // theoretically locking_timeout should be checked against time_limit (max_execution_time)
107 0 : $start = microtime(true);
108 0 : $hadLock = null;
109 0 : while ($this->hasLock($smarty, $cached)) {
110 0 : $hadLock = true;
111 0 : if (microtime(true) - $start > $smarty->locking_timeout) {
112 : // abort waiting for lock release
113 0 : return false;
114 : }
115 0 : sleep(1);
116 0 : }
117 0 : return $hadLock;
118 : }
119 :
120 : public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
121 : {
122 : // check if lock exists
123 0 : return false;
124 : }
125 :
126 : public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
127 : {
128 : // create lock
129 0 : return true;
130 : }
131 :
132 : public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
133 : {
134 : // release lock
135 0 : return true;
136 : }
137 :
138 :
139 : /**
140 : * Load Cache Resource Handler
141 : *
142 : * @param Smarty $smarty Smarty object
143 : * @param string $type name of the cache resource
144 : * @return Smarty_CacheResource Cache Resource Handler
145 : */
146 : public static function load(Smarty $smarty, $type = null)
147 : {
148 0 : if (!isset($type)) {
149 0 : $type = $smarty->caching_type;
150 0 : }
151 :
152 : // try smarty's cache
153 0 : if (isset($smarty->_cacheresource_handlers[$type])) {
154 0 : return $smarty->_cacheresource_handlers[$type];
155 : }
156 :
157 : // try registered resource
158 0 : if (isset($smarty->registered_cache_resources[$type])) {
159 : // do not cache these instances as they may vary from instance to instance
160 0 : return $smarty->_cacheresource_handlers[$type] = $smarty->registered_cache_resources[$type];
161 : }
162 : // try sysplugins dir
163 0 : if (isset(self::$sysplugins[$type])) {
164 0 : if (!isset(self::$resources[$type])) {
165 0 : $cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
166 0 : self::$resources[$type] = new $cache_resource_class();
167 0 : }
168 0 : return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
169 : }
170 : // try plugins dir
171 0 : $cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type);
172 0 : if ($smarty->loadPlugin($cache_resource_class)) {
173 0 : if (!isset(self::$resources[$type])) {
174 0 : self::$resources[$type] = new $cache_resource_class();
175 0 : }
176 0 : return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
177 : }
178 : // give up
179 0 : throw new SmartyException("Unable to load cache resource '{$type}'");
180 : }
181 :
182 : /**
183 : * Invalid Loaded Cache Files
184 : *
185 : * @param Smarty $smarty Smarty object
186 : */
187 : public static function invalidLoadedCache(Smarty $smarty)
188 : {
189 0 : foreach ($smarty->template_objects as $tpl) {
190 0 : if (isset($tpl->cached)) {
191 0 : $tpl->cached->valid = false;
192 0 : $tpl->cached->processed = false;
193 0 : }
194 0 : }
195 0 : }
196 : }
197 :
198 : /**
199 : * Smarty Resource Data Object
200 : *
201 : * Cache Data Container for Template Files
202 : *
203 : * @package Smarty
204 : * @subpackage TemplateResources
205 : * @author Rodney Rehm
206 : */
207 : class Smarty_Template_Cached {
208 : /**
209 : * Source Filepath
210 : * @var string
211 : */
212 : public $filepath = false;
213 :
214 : /**
215 : * Source Content
216 : * @var string
217 : */
218 : public $content = null;
219 :
220 : /**
221 : * Source Timestamp
222 : * @var integer
223 : */
224 : public $timestamp = false;
225 :
226 : /**
227 : * Source Existance
228 : * @var boolean
229 : */
230 : public $exists = false;
231 :
232 : /**
233 : * Cache Is Valid
234 : * @var boolean
235 : */
236 : public $valid = false;
237 :
238 : /**
239 : * Cache was processed
240 : * @var boolean
241 : */
242 : public $processed = false;
243 :
244 : /**
245 : * CacheResource Handler
246 : * @var Smarty_CacheResource
247 : */
248 : public $handler = null;
249 :
250 : /**
251 : * Template Compile Id (Smarty_Internal_Template::$compile_id)
252 : * @var string
253 : */
254 : public $compile_id = null;
255 :
256 : /**
257 : * Template Cache Id (Smarty_Internal_Template::$cache_id)
258 : * @var string
259 : */
260 : public $cache_id = null;
261 :
262 : /**
263 : * Id for cache locking
264 : * @var string
265 : */
266 : public $lock_id = null;
267 :
268 : /**
269 : * flag that cache is locked by this instance
270 : * @var bool
271 : */
272 : public $is_locked = false;
273 :
274 : /**
275 : * Source Object
276 : * @var Smarty_Template_Source
277 : */
278 : public $source = null;
279 :
280 : /**
281 : * create Cached Object container
282 : *
283 : * @param Smarty_Internal_Template $_template template object
284 : */
285 : public function __construct(Smarty_Internal_Template $_template)
286 : {
287 0 : $this->compile_id = $_template->compile_id;
288 0 : $this->cache_id = $_template->cache_id;
289 0 : $this->source = $_template->source;
290 0 : $_template->cached = $this;
291 0 : $smarty = $_template->smarty;
292 :
293 : //
294 : // load resource handler
295 : //
296 0 : $this->handler = $handler = Smarty_CacheResource::load($smarty); // Note: prone to circular references
297 :
298 : //
299 : // check if cache is valid
300 : //
301 0 : if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->recompiled) {
302 0 : return;
303 : }
304 0 : while (true) {
305 0 : while (true) {
306 0 : $handler->populate($this, $_template);
307 0 : if ($this->timestamp === false || $smarty->force_compile || $smarty->force_cache) {
308 0 : $this->valid = false;
309 0 : } else {
310 0 : $this->valid = true;
311 : }
312 0 : if ($this->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)) {
313 : // lifetime expired
314 0 : $this->valid = false;
315 0 : }
316 0 : if ($this->valid || !$_template->smarty->cache_locking) {
317 0 : break;
318 : }
319 0 : if (!$this->handler->locked($_template->smarty, $this)) {
320 0 : $this->handler->acquireLock($_template->smarty, $this);
321 0 : break 2;
322 : }
323 0 : }
324 0 : if ($this->valid) {
325 0 : if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) {
326 : // load cache file for the following checks
327 0 : if ($smarty->debugging) {
328 0 : Smarty_Internal_Debug::start_cache($_template);
329 0 : }
330 0 : if($handler->process($_template, $this) === false) {
331 0 : $this->valid = false;
332 0 : } else {
333 0 : $this->processed = true;
334 : }
335 0 : if ($smarty->debugging) {
336 0 : Smarty_Internal_Debug::end_cache($_template);
337 0 : }
338 0 : } else {
339 0 : continue;
340 : }
341 0 : } else {
342 0 : return;
343 : }
344 0 : if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && $_template->properties['cache_lifetime'] >= 0 && (time() > ($_template->cached->timestamp + $_template->properties['cache_lifetime']))) {
345 0 : $this->valid = false;
346 0 : }
347 0 : if (!$this->valid && $_template->smarty->cache_locking) {
348 0 : $this->handler->acquireLock($_template->smarty, $this);
349 0 : return;
350 : } else {
351 0 : return;
352 : }
353 : }
354 0 : }
355 :
356 : /**
357 : * Write this cache object to handler
358 : *
359 : * @param Smarty_Internal_Template $_template template object
360 : * @param string $content content to cache
361 : * @return boolean success
362 : */
363 : public function write(Smarty_Internal_Template $_template, $content)
364 : {
365 0 : if (!$_template->source->recompiled) {
366 0 : if ($this->handler->writeCachedContent($_template, $content)) {
367 0 : $this->timestamp = time();
368 0 : $this->exists = true;
369 0 : $this->valid = true;
370 0 : if ($_template->smarty->cache_locking) {
371 0 : $this->handler->releaseLock($_template->smarty, $this);
372 0 : }
373 0 : return true;
374 : }
375 0 : }
376 0 : return false;
377 : }
378 :
379 : }
|