6 * @copyright (c) 2005 phpBB Group
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
14 if (!defined('IN_PHPBB'))
20 * ACM File Based Caching
25 private $vars = array();
26 private $var_expires = array();
27 private $is_modified = false;
29 public $sql_rowset = array();
30 public $cache_dir = '';
35 function __construct()
37 $this->cache_dir
= PHPBB_ROOT_PATH
. 'cache/';
43 private function load()
45 // grab the global cache
46 if (file_exists($this->cache_dir
. 'data_global.' . PHP_EXT
))
48 @include
($this->cache_dir
. 'data_global.' . PHP_EXT
);
58 public function unload()
62 unset($this->var_expires
);
63 unset($this->sql_rowset
);
65 $this->vars
= array();
66 $this->var_expires
= array();
67 $this->sql_rowset
= array();
71 * Save modified objects
73 private function save()
75 if (!$this->is_modified
)
80 if ($fp = @fopen
($this->cache_dir
. 'data_global.' . PHP_EXT
, 'wb'))
83 fwrite($fp, "<?php\n\$this->vars = unserialize(" . var_export(serialize($this->vars
), true) . ");\n\$this->var_expires = unserialize(" . var_export(serialize($this->var_expires
), true) . ");");
87 if (!function_exists('phpbb_chmod'))
89 include(PHPBB_ROOT_PATH
. 'includes/functions.' . PHP_EXT
);
92 phpbb_chmod($this->cache_dir
. 'data_global.' . PHP_EXT
, phpbb
::CHMOD_WRITE
);
96 // Now, this occurred how often? ... phew, just tell the user then...
97 if (!@is_writable
($this->cache_dir
))
99 trigger_error($this->cache_dir
. ' is NOT writable.', E_USER_ERROR
);
102 trigger_error('Not able to open ' . $this->cache_dir
. 'data_global.' . PHP_EXT
, E_USER_ERROR
);
105 $this->is_modified
= false;
111 public function tidy()
113 $dir = @opendir
($this->cache_dir
);
120 while (($entry = readdir($dir)) !== false)
122 if (!preg_match('/^(sql_|data_(?!global))/', $entry))
128 @include
($this->cache_dir
. $entry);
131 $this->remove_file($this->cache_dir
. $entry);
136 if (file_exists($this->cache_dir
. 'data_global.' . PHP_EXT
))
138 if (!sizeof($this->vars
))
143 foreach ($this->var_expires
as $var_name => $expires)
145 if (time() > $expires)
147 $this->destroy($var_name);
152 set_config('cache_last_gc', time(), true);
156 * Get saved cache object
158 public function get($var_name)
160 if ($var_name[0] === '_')
162 if (!$this->_exists($var_name))
167 @include
($this->cache_dir
. "data{$var_name}." . PHP_EXT
);
168 return (isset($data)) ?
$data : false;
172 return ($this->_exists($var_name)) ?
$this->vars
[$var_name] : false;
177 * Put data into cache
179 function put($var_name, $var, $ttl = 31536000)
181 if ($var_name[0] === '_')
183 if ($fp = @fopen
($this->cache_dir
. "data{$var_name}." . PHP_EXT
, 'wb'))
185 @flock
($fp, LOCK_EX
);
186 fwrite($fp, "<?php\n\$expired = (time() > " . (time() +
$ttl) . ") ? true : false;\nif (\$expired) { return; }\n\$data = " . (sizeof($var) ?
"unserialize(" . var_export(serialize($var), true) . ");" : 'array();'));
187 @flock
($fp, LOCK_UN
);
190 if (!function_exists('phpbb_chmod'))
192 include(PHPBB_ROOT_PATH
. 'includes/functions.' . PHP_EXT
);
195 phpbb_chmod($this->cache_dir
. "data{$var_name}." . PHP_EXT
, phpbb
::CHMOD_WRITE
);
200 $this->vars
[$var_name] = $var;
201 $this->var_expires
[$var_name] = time() +
$ttl;
202 $this->is_modified
= true;
209 public function purge()
211 // Purge all phpbb cache files
212 $dir = @opendir
($this->cache_dir
);
219 while (($entry = readdir($dir)) !== false)
221 if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
226 $this->remove_file($this->cache_dir
. $entry);
231 unset($this->var_expires
);
232 unset($this->sql_rowset
);
234 $this->vars
= array();
235 $this->var_expires
= array();
236 $this->sql_rowset
= array();
238 $this->is_modified
= false;
244 public function destroy($var_name, $table = '')
246 if ($var_name === 'sql' && !empty($table))
248 if (!is_array($table))
250 $table = array($table);
253 $dir = @opendir
($this->cache_dir
);
260 while (($entry = readdir($dir)) !== false)
262 if (strpos($entry, 'sql_') !== 0)
267 // The following method is more failproof than simply assuming the query is on line 3 (which it should be)
268 $check_line = @file_get_contents
($this->cache_dir
. $entry);
270 if (empty($check_line))
275 // Now get the contents between /* and */
276 $check_line = substr($check_line, strpos($check_line, '/* ') +
3, strpos($check_line, ' */') - strpos($check_line, '/* ') - 3);
279 foreach ($table as $check_table)
281 // Better catch partial table names than no table names. ;)
282 if (strpos($check_line, $check_table) !== false)
291 $this->remove_file($this->cache_dir
. $entry);
299 if (!$this->_exists($var_name))
304 if ($var_name[0] === '_')
306 $this->remove_file($this->cache_dir
. 'data' . $var_name . '.' . PHP_EXT
, true);
308 else if (isset($this->vars
[$var_name]))
310 $this->is_modified
= true;
311 unset($this->vars
[$var_name]);
312 unset($this->var_expires
[$var_name]);
314 // We save here to let the following cache hits succeed
320 * Check if a given cache entry exist
322 private function _exists($var_name)
324 if ($var_name[0] === '_')
326 return file_exists($this->cache_dir
. 'data' . $var_name . '.' . PHP_EXT
);
330 if (!sizeof($this->vars
))
335 if (!isset($this->var_expires
[$var_name]))
340 return (time() > $this->var_expires
[$var_name]) ?
false : isset($this->vars
[$var_name]);
345 * Load cached sql query
347 public function sql_load($query)
349 // Remove extra spaces and tabs
350 $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
351 $query_id = sizeof($this->sql_rowset
);
353 if (!file_exists($this->cache_dir
. 'sql_' . md5($query) . '.' . PHP_EXT
))
358 @include
($this->cache_dir
. 'sql_' . md5($query) . '.' . PHP_EXT
);
360 if (!isset($expired))
366 $this->remove_file($this->cache_dir
. 'sql_' . md5($query) . '.' . PHP_EXT
, true);
377 public function sql_save($query, &$query_result, $ttl)
381 // Remove extra spaces and tabs
382 $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
383 $filename = $this->cache_dir
. 'sql_' . md5($query) . '.' . PHP_EXT
;
385 if ($fp = @fopen
($filename, 'wb'))
387 @flock
($fp, LOCK_EX
);
389 $query_id = sizeof($this->sql_rowset
);
390 $this->sql_rowset
[$query_id] = array();
392 while ($row = $db->sql_fetchrow($query_result))
394 $this->sql_rowset
[$query_id][] = $row;
396 $db->sql_freeresult($query_result);
398 $file = "<?php\n/* " . str_replace('*/', '*\/', $query) . " */";
399 $file .= "\n\$expired = (time() > " . (time() +
$ttl) . ") ? true : false;\nif (\$expired) { return; }\n";
401 fwrite($fp, $file . "\$this->sql_rowset[\$query_id] = " . (sizeof($this->sql_rowset
[$query_id]) ?
"unserialize(" . var_export(serialize($this->sql_rowset
[$query_id]), true) . ");" : 'array();'));
402 @flock
($fp, LOCK_UN
);
405 if (!function_exists('phpbb_chmod'))
407 include(PHPBB_ROOT_PATH
. 'includes/functions.' . PHP_EXT
);
410 phpbb_chmod($filename, phpbb
::CHMOD_WRITE
);
412 $query_result = $query_id;
417 * Fetch row from cache (database)
419 public function sql_fetchrow($query_id)
421 list(, $row) = each($this->sql_rowset
[$query_id]);
423 return ($row !== NULL) ?
$row : false;
427 * Fetch a field from the current row of a cached database result (database)
429 public function sql_fetchfield($query_id, $field)
431 $row = current($this->sql_rowset
[$query_id]);
433 return ($row !== false && isset($row[$field])) ?
$row[$field] : false;
437 * Free memory used for a cached database result (database)
439 public function sql_freeresult($query_id)
441 if (!isset($this->sql_rowset
[$query_id]))
446 unset($this->sql_rowset
[$query_id]);
452 * Removes/unlinks file
454 private function remove_file($filename, $check = false)
456 if ($check && !@is_writable
($this->cache_dir
))
458 // E_USER_ERROR - not using language entry - intended.
459 trigger_error('Unable to remove files within ' . $this->cache_dir
. '. Please check directory permissions.', E_USER_ERROR
);
462 return @unlink
($filename);