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_Custom extends Smarty_CacheResource
17: {
18: /**
19: * fetch cached content and its modification time from data source
20: *
21: * @param string $id unique cache content identifier
22: * @param string $name template name
23: * @param string $cache_id cache id
24: * @param string $compile_id compile id
25: * @param string $content cached content
26: * @param integer $mtime cache modification timestamp (epoch)
27: *
28: * @return void
29: */
30: abstract protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime);
31:
32: /**
33: * Fetch cached content's modification timestamp from data source
34: * {@internal implementing this method is optional.
35: * Only implement it if modification times can be accessed faster than loading the complete cached content.}}
36: *
37: * @param string $id unique cache content identifier
38: * @param string $name template name
39: * @param string $cache_id cache id
40: * @param string $compile_id compile id
41: *
42: * @return integer|boolean timestamp (epoch) the template was modified, or false if not found
43: */
44: protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
45: {
46: return null;
47: }
48:
49: /**
50: * Save content to cache
51: *
52: * @param string $id unique cache content identifier
53: * @param string $name template name
54: * @param string $cache_id cache id
55: * @param string $compile_id compile id
56: * @param integer|null $exp_time seconds till expiration or null
57: * @param string $content content to cache
58: *
59: * @return boolean success
60: */
61: abstract protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content);
62:
63: /**
64: * Delete content from cache
65: *
66: * @param string $name template name
67: * @param string $cache_id cache id
68: * @param string $compile_id compile id
69: * @param integer|null $exp_time seconds till expiration time in seconds or null
70: *
71: * @return integer number of deleted caches
72: */
73: abstract protected function delete($name, $cache_id, $compile_id, $exp_time);
74:
75: /**
76: * populate Cached Object with meta data from Resource
77: *
78: * @param Smarty_Template_Cached $cached cached object
79: * @param Smarty_Internal_Template $_template template object
80: *
81: * @return void
82: */
83: public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
84: {
85: $_cache_id = isset($cached->cache_id) ? preg_replace('![^\w\|]+!', '_', $cached->cache_id) : null;
86: $_compile_id = isset($cached->compile_id) ? preg_replace('![^\w\|]+!', '_', $cached->compile_id) : null;
87:
88: $cached->filepath = sha1($cached->source->filepath . $_cache_id . $_compile_id);
89: $this->populateTimestamp($cached);
90: }
91:
92: /**
93: * populate Cached Object with timestamp and exists from Resource
94: *
95: * @param Smarty_Template_Cached $cached
96: *
97: * @return void
98: */
99: public function populateTimestamp(Smarty_Template_Cached $cached)
100: {
101: $mtime = $this->fetchTimestamp($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id);
102: if ($mtime !== null) {
103: $cached->timestamp = $mtime;
104: $cached->exists = !!$cached->timestamp;
105:
106: return;
107: }
108: $timestamp = null;
109: $this->fetch($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id, $cached->content, $timestamp);
110: $cached->timestamp = isset($timestamp) ? $timestamp : false;
111: $cached->exists = !!$cached->timestamp;
112: }
113:
114: /**
115: * Read the cached template and process the header
116: *
117: * @param Smarty_Internal_Template $_template template object
118: * @param Smarty_Template_Cached $cached cached object
119: *
120: * @return boolean true or false if the cached content does not exist
121: */
122: public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null)
123: {
124: if (!$cached) {
125: $cached = $_template->cached;
126: }
127: $content = $cached->content ? $cached->content : null;
128: $timestamp = $cached->timestamp ? $cached->timestamp : null;
129: if ($content === null || !$timestamp) {
130: $this->fetch(
131: $_template->cached->filepath,
132: $_template->source->name,
133: $_template->cache_id,
134: $_template->compile_id,
135: $content,
136: $timestamp
137: );
138: }
139: if (isset($content)) {
140: /** @var Smarty_Internal_Template $_smarty_tpl
141: * used in evaluated code
142: */
143: $_smarty_tpl = $_template;
144: eval("?>" . $content);
145:
146: return true;
147: }
148:
149: return false;
150: }
151:
152: /**
153: * Write the rendered template output to cache
154: *
155: * @param Smarty_Internal_Template $_template template object
156: * @param string $content content to cache
157: *
158: * @return boolean success
159: */
160: public function writeCachedContent(Smarty_Internal_Template $_template, $content)
161: {
162: return $this->save(
163: $_template->cached->filepath,
164: $_template->source->name,
165: $_template->cache_id,
166: $_template->compile_id,
167: $_template->properties['cache_lifetime'],
168: $content
169: );
170: }
171:
172: /**
173: * Empty cache
174: *
175: * @param Smarty $smarty Smarty object
176: * @param integer $exp_time expiration time (number of seconds, not timestamp)
177: *
178: * @return integer number of cache files deleted
179: */
180: public function clearAll(Smarty $smarty, $exp_time = null)
181: {
182: $this->cache = array();
183:
184: return $this->delete(null, null, null, $exp_time);
185: }
186:
187: /**
188: * Empty cache for a specific template
189: *
190: * @param Smarty $smarty Smarty object
191: * @param string $resource_name template name
192: * @param string $cache_id cache id
193: * @param string $compile_id compile id
194: * @param integer $exp_time expiration time (number of seconds, not timestamp)
195: *
196: * @return integer number of cache files deleted
197: */
198: public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
199: {
200: $this->cache = array();
201: $cache_name = null;
202:
203: if (isset($resource_name)) {
204: $_save_stat = $smarty->caching;
205: $smarty->caching = true;
206: $tpl = new $smarty->template_class($resource_name, $smarty);
207: $smarty->caching = $_save_stat;
208:
209: if ($tpl->source->exists) {
210: $cache_name = $tpl->source->name;
211: } else {
212: return 0;
213: }
214: // remove from template cache
215: if ($smarty->allow_ambiguous_resources) {
216: $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id;
217: } else {
218: $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id;
219: }
220: if (isset($_templateId[150])) {
221: $_templateId = sha1($_templateId);
222: }
223: unset($smarty->template_objects[$_templateId]);
224: // template object no longer needed
225: unset($tpl);
226: }
227:
228: return $this->delete($cache_name, $cache_id, $compile_id, $exp_time);
229: }
230:
231: /**
232: * Check is cache is locked for this template
233: *
234: * @param Smarty $smarty Smarty object
235: * @param Smarty_Template_Cached $cached cached object
236: *
237: * @return boolean true or false if cache is locked
238: */
239: public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
240: {
241: $id = $cached->filepath;
242: $name = $cached->source->name . '.lock';
243:
244: $mtime = $this->fetchTimestamp($id, $name, null, null);
245: if ($mtime === null) {
246: $this->fetch($id, $name, null, null, $content, $mtime);
247: }
248:
249: return $mtime && time() - $mtime < $smarty->locking_timeout;
250: }
251:
252: /**
253: * Lock cache for this template
254: *
255: * @param Smarty $smarty Smarty object
256: * @param Smarty_Template_Cached $cached cached object
257: *
258: * @return bool|void
259: */
260: public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
261: {
262: $cached->is_locked = true;
263:
264: $id = $cached->filepath;
265: $name = $cached->source->name . '.lock';
266: $this->save($id, $name, null, null, $smarty->locking_timeout, '');
267: }
268:
269: /**
270: * Unlock cache for this template
271: *
272: * @param Smarty $smarty Smarty object
273: * @param Smarty_Template_Cached $cached cached object
274: *
275: * @return bool|void
276: */
277: public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
278: {
279: $cached->is_locked = false;
280:
281: $name = $cached->source->name . '.lock';
282: $this->delete($name, null, null, null);
283: }
284: }
285: