1: <?php
2: /**
3: * Smarty Internal Plugin CacheResource File
4: *
5: * @package Smarty
6: * @subpackage Cacher
7: * @author Uwe Tews
8: * @author Rodney Rehm
9: */
10:
11: /**
12: * This class does contain all necessary methods for the HTML cache on file system
13: * Implements the file system as resource for the HTML cache Version ussing nocache inserts.
14: *
15: * @package Smarty
16: * @subpackage Cacher
17: */
18: class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
19: {
20: /**
21: * populate Cached Object with meta data from Resource
22: *
23: * @param Smarty_Template_Cached $cached cached object
24: * @param Smarty_Internal_Template $_template template object
25: *
26: * @return void
27: */
28: public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
29: {
30: $source = &$_template->source;
31: $smarty = &$_template->smarty;
32: $_compile_dir_sep = $smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
33: $_filepath = sha1($source->uid . $smarty->_joined_template_dir);
34: $cached->filepath = $smarty->getCacheDir();
35: if (isset($_template->cache_id)) {
36: $cached->filepath .= preg_replace(
37: array(
38: '![^\w|]+!',
39: '![|]+!'
40: ),
41: array(
42: '_',
43: $_compile_dir_sep
44: ),
45: $_template->cache_id
46: ) . $_compile_dir_sep;
47: }
48: if (isset($_template->compile_id)) {
49: $cached->filepath .= preg_replace('![^\w]+!', '_', $_template->compile_id) . $_compile_dir_sep;
50: }
51: // if use_sub_dirs, break file into directories
52: if ($smarty->use_sub_dirs) {
53: $cached->filepath .= $_filepath[ 0 ] . $_filepath[ 1 ] . DIRECTORY_SEPARATOR . $_filepath[ 2 ] .
54: $_filepath[ 3 ] .
55: DIRECTORY_SEPARATOR .
56: $_filepath[ 4 ] . $_filepath[ 5 ] . DIRECTORY_SEPARATOR;
57: }
58: $cached->filepath .= $_filepath;
59: $basename = $source->handler->getBasename($source);
60: if (!empty($basename)) {
61: $cached->filepath .= '.' . $basename;
62: }
63: if ($smarty->cache_locking) {
64: $cached->lock_id = $cached->filepath . '.lock';
65: }
66: $cached->filepath .= '.php';
67: $cached->timestamp = $cached->exists = is_file($cached->filepath);
68: if ($cached->exists) {
69: $cached->timestamp = filemtime($cached->filepath);
70: }
71: }
72:
73: /**
74: * populate Cached Object with timestamp and exists from Resource
75: *
76: * @param Smarty_Template_Cached $cached cached object
77: *
78: * @return void
79: */
80: public function populateTimestamp(Smarty_Template_Cached $cached)
81: {
82: $cached->timestamp = $cached->exists = is_file($cached->filepath);
83: if ($cached->exists) {
84: $cached->timestamp = filemtime($cached->filepath);
85: }
86: }
87:
88: /**
89: * Read the cached template and process its header
90: *
91: * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template
92: * @param Smarty_Template_Cached $cached cached object
93: * @param bool $update flag if called because cache update
94: *
95: * @return boolean true or false if the cached content does not exist
96: */
97: public function process(
98: Smarty_Internal_Template $_smarty_tpl,
99: Smarty_Template_Cached $cached = null,
100: $update = false
101: ) {
102: $_smarty_tpl->cached->valid = false;
103: if ($update && defined('HHVM_VERSION')) {
104: eval('?>' . file_get_contents($_smarty_tpl->cached->filepath));
105: return true;
106: } else {
107: return @include $_smarty_tpl->cached->filepath;
108: }
109: }
110:
111: /**
112: * Write the rendered template output to cache
113: *
114: * @param Smarty_Internal_Template $_template template object
115: * @param string $content content to cache
116: *
117: * @return bool success
118: * @throws \SmartyException
119: */
120: public function writeCachedContent(Smarty_Internal_Template $_template, $content)
121: {
122: if ($_template->smarty->ext->_writeFile->writeFile(
123: $_template->cached->filepath,
124: $content,
125: $_template->smarty
126: ) === true
127: ) {
128: if (function_exists('opcache_invalidate')
129: && (!function_exists('ini_get') || strlen(ini_get('opcache.restrict_api'))) < 1
130: ) {
131: opcache_invalidate($_template->cached->filepath, true);
132: } elseif (function_exists('apc_compile_file')) {
133: apc_compile_file($_template->cached->filepath);
134: }
135: $cached = $_template->cached;
136: $cached->timestamp = $cached->exists = is_file($cached->filepath);
137: if ($cached->exists) {
138: $cached->timestamp = filemtime($cached->filepath);
139: return true;
140: }
141: }
142: return false;
143: }
144:
145: /**
146: * Read cached template from cache
147: *
148: * @param Smarty_Internal_Template $_template template object
149: *
150: * @return string content
151: */
152: public function readCachedContent(Smarty_Internal_Template $_template)
153: {
154: if (is_file($_template->cached->filepath)) {
155: return file_get_contents($_template->cached->filepath);
156: }
157: return false;
158: }
159:
160: /**
161: * Empty cache
162: *
163: * @param Smarty $smarty
164: * @param integer $exp_time expiration time (number of seconds, not timestamp)
165: *
166: * @return integer number of cache files deleted
167: */
168: public function clearAll(Smarty $smarty, $exp_time = null)
169: {
170: return $smarty->ext->_cacheResourceFile->clear($smarty, null, null, null, $exp_time);
171: }
172:
173: /**
174: * Empty cache for a specific template
175: *
176: * @param Smarty $smarty
177: * @param string $resource_name template name
178: * @param string $cache_id cache id
179: * @param string $compile_id compile id
180: * @param integer $exp_time expiration time (number of seconds, not timestamp)
181: *
182: * @return integer number of cache files deleted
183: */
184: public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
185: {
186: return $smarty->ext->_cacheResourceFile->clear($smarty, $resource_name, $cache_id, $compile_id, $exp_time);
187: }
188:
189: /**
190: * Check is cache is locked for this template
191: *
192: * @param Smarty $smarty Smarty object
193: * @param Smarty_Template_Cached $cached cached object
194: *
195: * @return boolean true or false if cache is locked
196: */
197: public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
198: {
199: if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
200: clearstatcache(true, $cached->lock_id);
201: } else {
202: clearstatcache();
203: }
204: if (is_file($cached->lock_id)) {
205: $t = filemtime($cached->lock_id);
206: return $t && (time() - $t < $smarty->locking_timeout);
207: } else {
208: return false;
209: }
210: }
211:
212: /**
213: * Lock cache for this template
214: *
215: * @param Smarty $smarty Smarty object
216: * @param Smarty_Template_Cached $cached cached object
217: *
218: * @return bool|void
219: */
220: public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
221: {
222: $cached->is_locked = true;
223: touch($cached->lock_id);
224: }
225:
226: /**
227: * Unlock cache for this template
228: *
229: * @param Smarty $smarty Smarty object
230: * @param Smarty_Template_Cached $cached cached object
231: *
232: * @return bool|void
233: */
234: public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
235: {
236: $cached->is_locked = false;
237: @unlink($cached->lock_id);
238: }
239: }
240: