Created
June 4, 2009 21:42
-
-
Save cs278/123869 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* | |
* @package acm | |
* @version $Id$ | |
* @copyright (c) 2005, 2009 phpBB Group | |
* @license http://opensource.org/licenses/gpl-license.php GNU Public License | |
* | |
*/ | |
/** | |
* @ignore | |
*/ | |
if (!defined('IN_PHPBB')) | |
{ | |
exit; | |
} | |
define('CACHE_TABLE', $table_prefix . 'cache'); | |
define('PHPBB_ACM_DB_EXISTS', 1); | |
define('PHPBB_ACM_DB_STALE', 2); | |
define('PHPBB_ACM_DB_READY', 4); | |
/* | |
DROP TABLE IF EXISTS phpbb_cache; | |
CREATE TABLE phpbb_cache ( | |
var_name VARCHAR(255) NOT NULL, | |
var_data MEDIUMTEXT NOT NULL, | |
var_expires int(11) NOT NULL, | |
var_global tinyint(1) NOT NULL, | |
PRIMARY KEY (var_name), | |
KEY var_expires (var_expires), | |
KEY var_global (var_global) | |
) CHARACTER SET utf8 COLLATE utf8_bin; | |
*/ | |
/** | |
* ACM for caching in the database | |
* @package acm | |
*/ | |
class acm | |
{ | |
var $cache_dir; | |
var $vars; | |
var $states; | |
var $ttls; | |
function acm() | |
{ | |
global $phpbb_root_path; | |
$this->cache_dir = $phpbb_root_path . 'cache/'; | |
} | |
function load($var_name = '') | |
{ | |
global $db; | |
$this->vars = $this->states = $this->ttls = array(); | |
$sql_extra = ($var_name) ? " OR var_name = '" . $db->sql_escape($var_name) . "'" : ''; | |
$sql = 'SELECT var_name, var_data | |
FROM ' . CACHE_TABLE . ' | |
WHERE var_expires > ' . time() . " | |
AND (var_global = 1$sql_extra)"; | |
$result = $db->sql_query($sql); | |
while ($row = $db->sql_fetchrow($result)) | |
{ | |
$this->vars[$row['var_name']] = $row['var_data']; | |
$this->states[$row['var_name']] = PHPBB_ACM_DB_EXISTS; | |
} | |
$db->sql_freeresult($result); | |
} | |
function unload() | |
{ | |
$this->save(); | |
unset($this->vars); | |
} | |
function purge() | |
{ | |
global $db; | |
// Purge all phpbb cache files | |
$dir = @opendir($this->cache_dir); | |
if (!$dir) | |
{ | |
return; | |
} | |
while (($entry = readdir($dir)) !== false) | |
{ | |
if (strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) | |
{ | |
continue; | |
} | |
$this->remove_file($this->cache_dir . $entry); | |
} | |
closedir($dir); | |
// Quicker than truncate on small tables | |
$sql = 'DELETE FROM ' . CACHE_TABLE; | |
$db->sql_query($sql); | |
foreach ($this->states as $var_name => $void) | |
{ | |
$this->states[$var_name] = 0; | |
} | |
$this->vars = $this->ttls = array(); | |
} | |
function save() | |
{ | |
global $db; | |
$delete = $insert = $update = array(); | |
$time = time(); | |
foreach ($this->states as $var_name => $state) | |
{ | |
if (!($state & PHPBB_ACM_DB_STALE)) | |
{ | |
// Skip anything that is not stale | |
continue; | |
} | |
if (!($state & PHPBB_ACM_DB_READY)) | |
{ | |
// If the var is not ready to use and is stale | |
// it must have been deleted. | |
$delete[] = $var_name; | |
} | |
else | |
{ | |
if ($state & PHPBB_ACM_DB_EXISTS) | |
{ | |
// Ready, existing, and stale must need updating | |
$array = 'update'; | |
} | |
else | |
{ | |
$array = 'insert'; | |
} | |
${$array}[$var_name] = array( | |
'var_name' => $var_name, | |
'var_data' => serialize($this->vars[$var_name]), | |
'var_expires' => $this->ttls[$var_name] + $time, | |
'var_global' => ($var_name[0] == '_' ? false : true), | |
); | |
} | |
} | |
if (empty($delete) && empty($update) && empty($insert)) | |
{ | |
return; | |
} | |
if (!empty($delete) || !empty($update)) | |
{ | |
$sql = 'DELETE FROM ' . CACHE_TABLE . ' | |
WHERE ' . $db->sql_in_set('var_name', array_merge($delete, array_keys($update))); | |
// We only want to update the entries we really want to delete | |
if (function_exists('array_combine')) | |
{ | |
$this->states = array_merge($this->states, array_combine($delete, array_fill(0, sizeof($delete), 0))); | |
} | |
else | |
{ | |
foreach ($delete as $var_name) | |
{ | |
$this->states[$var_name] = 0; | |
} | |
} | |
unset($delete); | |
} | |
if (!empty($insert) || !empty($update)) | |
{ | |
$insert = array_merge($insert, $update); | |
$db->sql_multi_insert(CACHE_TABLE, array_values($insert)); | |
if (function_exists('array_combine')) | |
{ | |
$this->states = array_merge($this->states, array_combine(array_keys($insert), array_fill(0, sizeof($insert), PHPBB_ACM_DB_READY | PHPBB_ACM_DB_EXISTS))); | |
} | |
else | |
{ | |
foreach (array_keys($insert) as $var_name) | |
{ | |
$this->states[$var_name] = PHPBB_ACM_DB_READY | PHPBB_ACM_DB_EXISTS; | |
} | |
} | |
unset($insert, $update); | |
} | |
} | |
function tidy() | |
{ | |
global $db; | |
$sql = 'DELETE FROM ' . CACHE_TABLE . ' | |
WHERE var_expires < ' . time(); | |
$db->sql_query($sql); | |
set_config('cache_last_gc', time(), true); | |
} | |
function get($var_name) | |
{ | |
if (!is_array($this->vars)) | |
{ | |
if ($var_name[0] == '_') | |
{ | |
$this->load($var_name); | |
} | |
else | |
{ | |
$this->load(); | |
} | |
} | |
if ($var_name[0] == '_' && !isset($this->states[$var_name])) | |
{ | |
// Local, not known request it | |
global $db; | |
$sql = 'SELECT var_data | |
FROM ' . CACHE_TABLE . " | |
WHERE var_name = '" . $db->sql_escape($var_name) . "' | |
AND var_expires > " . time(); | |
$result = $db->sql_query($sql); | |
if ($row = $db->sql_fetchrow($result)) | |
{ | |
$this->vars[$var_name] = $row['var_data']; | |
$this->states[$var_name] = PHPBB_ACM_DB_EXISTS; | |
} | |
else | |
{ | |
$this->states[$var_name] = 0; | |
} | |
$db->sql_freeresult($result); | |
} | |
if ($this->_exists($var_name)) | |
{ | |
if (!($this->states[$var_name] & PHPBB_ACM_DB_READY)) | |
{ | |
$this->vars[$var_name] = unserialize($this->vars[$var_name]); | |
$this->states[$var_name] |= PHPBB_ACM_DB_READY; | |
} | |
return $this->vars[$var_name]; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
function put($var_name, $var_data, $ttl = 31536000) | |
{ | |
if (!is_array($this->vars)) | |
{ | |
$this->load(); | |
} | |
if (!isset($this->states[$var_name])) | |
{ | |
$this->states[$var_name] = 0; | |
} | |
$this->vars[$var_name] = $var_data; | |
$this->states[$var_name] |= PHPBB_ACM_DB_READY | PHPBB_ACM_DB_STALE; | |
$this->ttls[$var_name] = $ttl; | |
} | |
function destroy($var_name) | |
{ | |
if ($var_name == 'sql') | |
{ | |
// We don't support SQL caching | |
return; | |
} | |
if (!is_array($this->vars)) | |
{ | |
$this->load(); | |
} | |
unset($this->vars[$var_name]); | |
$this->states[$var_name] = ($this->states[$var_name] ^ PHPBB_ACM_DB_READY) | PHPBB_ACM_DB_STALE; | |
} | |
function _exists($var_name) | |
{ | |
return (isset($this->vars[$var_name])) ? true : false; | |
} | |
/** | |
* Removes/unlinks file | |
*/ | |
function remove_file($filename, $check = false) | |
{ | |
if ($check && !@is_writable($this->cache_dir)) | |
{ | |
// E_USER_ERROR - not using language entry - intended. | |
trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); | |
} | |
return @unlink($filename); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment