| Current Path : /var/www/element/data/www/greenpr.ru/bitrix3/modules/main/classes/general/ |
| Current File : /var/www/element/data/www/greenpr.ru/bitrix3/modules/main/classes/general/cache.php |
<?
/*********************************************************************
Caching
*********************************************************************/
class CPHPCache
{
var $_cache;
var $folder;
var $content;
var $vars;
var $TTL;
var $uniq_str;
var $initdir;
var $bStarted = false;
var $bInit = "NO";
function __construct()
{
return $this->CPHPCache();
}
function CPHPCache()
{
static $cache_type = false;
if($cache_type === false)
{
if(defined("BX_CACHE_TYPE"))
$prefered_cache_type = BX_CACHE_TYPE;
else
$prefered_cache_type = "files";
$cache_type = "files";
switch($prefered_cache_type)
{
case "memcache":
if(extension_loaded('memcache') && defined("BX_MEMCACHE_HOST"))
{
include_once($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/main/classes/general/cache_memcache.php");
$obCache = new CPHPCacheMemcache;
if($obCache->IsAvailable())
$cache_type = "memcache";
}
break;
case "eaccelerator":
if(extension_loaded('eaccelerator'))
{
include_once($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/main/classes/general/cache_eaccelerator.php");
$obCache = new CPHPCacheEAccelerator;
if($obCache->IsAvailable())
$cache_type = "eaccelerator";
}
break;
case "apc":
if(extension_loaded('apc'))
{
include_once($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/main/classes/general/cache_apc.php");
$obCache = new CPHPCacheAPC;
if($obCache->IsAvailable())
$cache_type = "apc";
}
break;
}
if($cache_type == "files")
include_once($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/main/classes/general/cache_files.php");
}
switch($cache_type)
{
case "memcache":
$this->_cache = new CPHPCacheMemcache;
break;
case "eaccelerator":
$this->_cache = new CPHPCacheEAccelerator;
break;
case "apc":
$this->_cache = new CPHPCacheAPC;
break;
default:
$this->_cache = new CPHPCacheFiles;
break;
}
}
function GetPath($uniq_str)
{
$un = md5($uniq_str);
return substr($un, 0, 2)."/".$un.".php";
}
function Clean($uniq_str, $initdir = false, $basedir = "cache")
{
$basedir = BX_PERSONAL_ROOT."/".$basedir."/";
$filename = CPHPCache::GetPath($uniq_str);
if(is_object($this->_cache))
return $this->_cache->clean($basedir, $initdir, "/".$filename);
else
{
$obCache = new CPHPCache();
$obCache->Clean($uniq_str, $initdir, $basedir);
}
}
function CleanDir($initdir = false, $basedir = "cache")
{
$basedir = BX_PERSONAL_ROOT."/".$basedir."/";
return $this->_cache->clean($basedir, $initdir);
}
function InitCache($TTL, $uniq_str, $initdir=false, $basedir = "cache")
{
global $APPLICATION, $USER;
if($initdir === false)
$initdir = $APPLICATION->GetCurDir();
$this->basedir = BX_PERSONAL_ROOT."/".$basedir."/";
$this->initdir = $initdir;
$this->filename = "/".CPHPCache::GetPath($uniq_str);
$this->TTL = $TTL;
$this->uniq_str = $uniq_str;
$this->vars = false;
if($TTL<=0)
return false;
if(is_object($USER))
{
if(strtoupper($_GET["clear_cache"])=="Y" && $USER->CanDoOperation('cache_control'))
return false;
if(strtoupper($_GET["clear_cache_session"])=="Y" && $USER->CanDoOperation('cache_control'))
$_SESSION["SESS_CLEAR_CACHE"] = "Y";
elseif(strlen($_GET["clear_cache_session"])>0 && $USER->CanDoOperation('cache_control'))
unset($_SESSION["SESS_CLEAR_CACHE"]);
}
if($_SESSION["SESS_CLEAR_CACHE"] == "Y")
return false;
$arAllVars = array("CONTENT" => "", "VARS" => "");
if(!$this->_cache->read(&$arAllVars, $this->basedir, $this->initdir, $this->filename, $this->TTL))
return false;
$this->content = $arAllVars["CONTENT"];
$this->vars = $arAllVars["VARS"];
return true;
}
function Output()
{
echo $this->content;
}
function GetVars()
{
return $this->vars;
}
function StartDataCache($TTL=false, $uniq_str=false, $initdir=false, $vars=Array(), $basedir = "cache")
{
$narg = func_num_args();
if($narg<=0)
$TTL = $this->TTL;
if($narg<=1)
$uniq_str = $this->uniq_str;
if($narg<=2)
$initdir = $this->initdir;
if($narg<=3)
$vars = $this->vars;
if($this->InitCache($TTL, $uniq_str, $initdir, $basedir))
{
$this->Output();
return false;
}
if($TTL<=0)
return true;
ob_start();
$this->vars = $vars;
$this->bStarted = true;
return true;
}
function AbortDataCache()
{
if(!$this->_cache->bStarted)
return;
$this->_cache->bStarted = false;
ob_end_flush();
}
function EndDataCache($vars=false)
{
if(!$this->bStarted)
return;
$this->bStarted = false;
$arAllVars = array(
"CONTENT" => ob_get_contents(),
"VARS" => ($vars!==false? $vars: $this->vars),
);
$this->_cache->write($arAllVars, $this->basedir, $this->initdir, $this->filename, $this->TTL);
if(strlen(ob_get_contents())>0)
ob_end_flush();
else
ob_end_clean();
}
function IsCacheExpired($path)
{
return $this->_cache->IsCacheExpired($path);
}
}
class CPageCache
{
var $filename;
var $folder;
var $content;
var $TTL;
var $bStarted = false;
var $uniq_str = false;
var $init_dir = false;
function GetPath($uniq_str)
{
$un = md5($uniq_str);
return substr($un, 0, 2)."/".$un.".html";
}
function Clean($uniq_str, $initdir = false, $basedir = "cache")
{
$cache_file = $_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/".$basedir."/".$initdir."/".CPageCache::GetPath($uniq_str);
$res = false;
if (file_exists($cache_file))
{
@chmod($cache_file, BX_FILE_PERMISSIONS);
if(unlink($cache_file))
$res = true;
}
return $res;
}
function InitCache($TTL, $uniq_str, $initdir = false, $basedir = "cache")
{
global $APPLICATION, $USER;
if($initdir === false)
$initdir = $APPLICATION->GetCurDir();
$this->TTL = $TTL;
$this->folder = $_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/".$basedir."/".$initdir."/";
$this->filename = $this->folder.CPageCache::GetPath($uniq_str);
$this->tmp_filename = $this->folder.md5(mt_rand()).".tmp";
$this->init_dir = $initdir;
if($TTL<=0)
return false;
if(is_object($USER))
{
if(strtoupper($_GET["clear_cache"])=="Y" && $USER->CanDoOperation('cache_control'))
return false;
if(strtoupper($_GET["clear_cache_session"])=="Y" && $USER->CanDoOperation('cache_control'))
$_SESSION["SESS_CLEAR_CACHE"] = "Y";
elseif(strlen($_GET["clear_cache_session"])>0 && $USER->CanDoOperation('cache_control'))
unset($_SESSION["SESS_CLEAR_CACHE"]);
}
if($_SESSION["SESS_CLEAR_CACHE"] == "Y")
return false;
if(!file_exists($this->filename))
return false;
if(!($handle = fopen($this->filename, "rb")))
return false;
$fdatacreate = fread($handle, 2);
if($fdatacreate=="BX")
{
$fdatacreate = fread($handle, 12);
$fdateexpire = fread($handle, 12);
}
else
$fdatacreate .= fread($handle, 10);
if(IntVal($fdatacreate)<mktime()-$TTL)
{
fclose($handle);
return false;
}
$this->content = fread($handle, filesize($this->filename)-10);
fclose ($handle);
return true;
}
function Output()
{
echo $this->content;
}
function StartDataCache($TTL, $uniq_str=false, $initdir=false, $basedir = "cache")
{
if($this->InitCache($TTL, $uniq_str, $initdir, $basedir))
{
$this->Output();
return false;
}
if($TTL<=0)
return true;
ob_start();
$this->bStarted = true;
return true;
}
function EndDataCache()
{
if(!$this->bStarted) return;
$this->bStarted = false;
CheckDirPath($this->filename);
if($handle = fopen($this->tmp_filename, "wb+"))
{
$contents = ob_get_contents();
fwrite($handle, "BX".str_pad(mktime(), 12, "0", STR_PAD_LEFT).str_pad(mktime() + IntVal($this->TTL), 12, "0", STR_PAD_LEFT));
fwrite($handle, $contents);
fclose($handle);
if(file_exists($this->filename))
unlink($this->filename);
rename($this->tmp_filename, $this->filename);
}
ob_end_flush();
}
function IsCacheExpired($path)
{
if(!file_exists($path))
return true;
if(!($handle = fopen($path, "rb")))
return false;
$fdatacreate = fread($handle, 2);
if($fdatacreate=="BX")
{
$fdatacreate = fread($handle, 12);
$fdateexpire = fread($handle, 12);
}
else
$fdataexpire = 0;
fclose($handle);
if(IntVal($fdateexpire)<mktime())
return true;
return false;
}
}
function BXClearCache($full=false, $initdir="")
{
if($full !== true && $full !== false && $initdir === "" && is_string($full))
{
$initdir = $full;
$full = true;
}
$res = true;
if($full === true)
{
$obCache = new CPHPCache;
$obCache->CleanDir($initdir, "cache");
}
$path = $_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/cache".$initdir;
if(is_dir($path) && ($handle = opendir($path)))
{
while(($file = readdir($handle)) !== false)
{
if($file == "." || $file == "..") continue;
if(is_dir($path."/".$file))
{
if(!BXClearCache($full, $initdir."/".$file))
$res = false;
else
{
@chmod($path."/".$file, BX_DIR_PERMISSIONS);
if(!rmdir($path."/".$file))
$res = false;
}
}
else
{
$expired = $full;
if(!$expired)
{
if(substr($file, -5)==".html")
$expired = CPageCache::IsCacheExpired($path."/".$file);
elseif(substr($file, -4)==".php")
$expired = CPHPCache::IsCacheExpired($path."/".$file);
else
$res = false;
}
if($expired)
{
@chmod($path."/".$file, BX_FILE_PERMISSIONS);
if(!unlink($path."/".$file))
$res = false;
}
}
}
closedir($handle);
}
return $res;
}
// The main purpose of the class is:
// one read - many uses - optional one write
// of the set of variables
class CCacheManager
{
var $CACHE= array();
var $CACHE_PATH = array();
var $VARS = array();
var $TTL = array();
// Tries to read cached variable value from the file
// Returns true on success
// overwise returns false
function Read($ttl, $uniqid, $table_id=false)
{
global $DB;
if(array_key_exists($uniqid, $this->CACHE))
return true;
else
{
$this->CACHE[$uniqid] = new CPHPCache;
$this->CACHE_PATH[$uniqid] = $DB->type.($table_id===false?"":"/".$table_id);
$this->TTL[$uniqid] = $ttl;
return $this->CACHE[$uniqid]->InitCache($ttl, $uniqid, $this->CACHE_PATH[$uniqid], "managed_cache");
}
}
// This method is used to read the variable value
// from the cache after successfull Read
function Get($uniqid)
{
if(array_key_exists($uniqid, $this->VARS))
return $this->VARS[$uniqid];
elseif(array_key_exists($uniqid, $this->CACHE))
return $this->CACHE[$uniqid]->GetVars();
else
return false;
}
// Sets new value to the variable
function Set($uniqid, $val)
{
if(array_key_exists($uniqid, $this->CACHE))
$this->VARS[$uniqid]=$val;
}
// Marks cache entry as invalid
function Clean($uniqid, $table_id=false)
{
global $DB;
$obCache = new CPHPCache;
$obCache->Clean($uniqid, $DB->type."/".($table_id!==false?$table_id."/":""), "managed_cache");
if(array_key_exists($uniqid, $this->CACHE))
{
unset($this->CACHE[$uniqid]);
unset($this->CACHE_PATH[$uniqid]);
unset($this->VARS[$uniqid]);
}
}
// Marks cache entries associated with the table as invalid
function CleanDir($table_id)
{
global $DB;
$strPath = $DB->type."/".$table_id;
foreach($this->CACHE_PATH as $uniqid=>$Path)
{
if($Path==$strPath)
{
unset($this->CACHE[$uniqid]);
unset($this->CACHE_PATH[$uniqid]);
unset($this->VARS[$uniqid]);
}
}
$obCache = new CPHPCache;
$obCache->CleanDir($DB->type."/".$table_id, "managed_cache");
}
// Clears all managed_cache
function CleanAll()
{
global $DB;
$this->CACHE= array();
$this->CACHE_PATH = array();
$this->VARS = array();
$this->TTL = array();
$obCache = new CPHPCache;
$obCache->CleanDir(false, "managed_cache");
}
// Use it to flush cache to the files.
// Causion: only at the end of all operations!
function _Finalize()
{
global $DB, $CACHE_MANAGER;
$obCache = new CPHPCache;
foreach($CACHE_MANAGER->CACHE as $uniqid=>$val)
{
if(array_key_exists($uniqid, $CACHE_MANAGER->VARS))
{
$obCache->StartDataCache($CACHE_MANAGER->TTL[$uniqid], $uniqid, $CACHE_MANAGER->CACHE_PATH[$uniqid], $CACHE_MANAGER->VARS[$uniqid], "managed_cache");
$obCache->EndDataCache();
}
}
}
}
global $CACHE_MANAGER;
$CACHE_MANAGER = new CCacheManager;
/*****************************************************************************************************/
/************************ CStackCacheManager *******************************************************/
/*****************************************************************************************************/
class CStackCacheManager
{
var $cache = array();
var $cacheLength = array();
var $cacheTTL = array();
var $defaultLength = 10;
var $defaultTTL = 3600;
var $eventHandlerAdded = false;
function SetLength($entity, $length)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
$length = IntVal($length);
if ($length <= 0)
$length = $this->defaultLength;
$this->cacheLength[$entity] = IntVal($length);
}
function SetTTL($entity, $ttl)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
$ttl = IntVal($ttl);
if ($ttl <= 0)
$ttl = $this->defaultTTL;
$this->cacheTTL[$entity] = IntVal($ttl);
}
function Init($entity, $length, $ttl)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
if (!$this->eventHandlerAdded)
{
AddEventHandler("main", "OnEpilog", array("CStackCacheManager", "SaveAll"));
$this->eventHandlerAdded = True;
}
$length = IntVal($length);
if ($length <= 0)
$length = $this->defaultLength;
$ttl = IntVal($ttl);
if ($ttl <= 0)
$ttl = $this->defaultTTL;
if (!array_key_exists($entity, $this->cache))
$this->cache[$entity] = array();
if (!array_key_exists($entity, $this->cacheLength))
$this->cacheLength[$entity] = IntVal($length);
if (!array_key_exists($entity, $this->cacheTTL))
$this->cacheTTL[$entity] = IntVal($ttl);
}
function Load($entity)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
if (!array_key_exists($entity, $this->cache))
$this->Init($entity, $this->defaultLength, $this->defaultTTL);
$objCache = new CPHPCache;
if ($objCache->InitCache($this->cacheTTL[$entity], $entity, $GLOBALS["DB"]->type."/".$entity, "stack_cache"))
$this->cache[$entity] = $objCache->GetVars();
}
//NO ONE SHOULD NEVER EVER USE INTEGER $id HERE
function Clear($entity, $id = False)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
if (!array_key_exists($entity, $this->cache))
$this->Load($entity);
if ($id !== False)
{
if (array_key_exists($id, $this->cache[$entity]))
unset($this->cache[$entity][$id]);
}
else
{
$this->cache[$entity] = array();
$objCache = new CPHPCache;
$objCache->Clean($entity, $GLOBALS["DB"]->type."/".$entity, "stack_cache");
}
}
// Clears all managed_cache
function CleanAll()
{
global $DB;
$this->cache = array();
$this->cacheLength = array();
$this->cacheTTL = array();
$objCache = new CPHPCache;
$objCache->CleanDir(false, "stack_cache");
}
//NO ONE SHOULD NEVER EVER USE INTEGER $id HERE
function Exist($entity, $id)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return False;
if (!array_key_exists($entity, $this->cache))
$this->Load($entity);
if (array_key_exists($id, $this->cache[$entity]))
return True;
else
return False;
}
//NO ONE SHOULD NEVER EVER USE INTEGER $id HERE
function Get($entity, $id)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return False;
if (!array_key_exists($entity, $this->cache))
$this->Load($entity);
if (array_key_exists($id, $this->cache[$entity]))
{
$result = $this->cache[$entity][$id];
unset($this->cache[$entity][$id]);
$this->cache[$entity] = $this->cache[$entity] + array($id => $result);
return $result;
}
else
{
return False;
}
}
//NO ONE SHOULD NEVER EVER USE INTEGER $id HERE
function Set($entity, $id, $value)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
if (!array_key_exists($entity, $this->cache))
$this->Load($entity);
if (array_key_exists($id, $this->cache[$entity]))
{
unset($this->cache[$entity][$id]);
$this->cache[$entity] = $this->cache[$entity] + array($id => $value);
}
else
{
$this->cache[$entity] = $this->cache[$entity] + array($id => $value);
if (count($this->cache[$entity]) > $this->cacheLength[$entity])
array_shift($this->cache[$entity]);
}
}
function Save($entity)
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
$objCache = new CPHPCache;
$objCache->Clean($entity, $GLOBALS["DB"]->type."/".$entity, "stack_cache");
if (array_key_exists($entity, $this->cache))
{
$objCache->StartDataCache($this->cacheTTL[$entity], $entity, $GLOBALS["DB"]->type."/".$entity, $this->cache[$entity], "stack_cache");
$objCache->EndDataCache();
}
}
function SaveAll()
{
if (defined("BITRIX_SKIP_STACK_CACHE") && BITRIX_SKIP_STACK_CACHE)
return;
foreach ($GLOBALS["stackCacheManager"]->cache as $entity => $value)
$GLOBALS["stackCacheManager"]->Save($entity);
}
function MakeIDFromArray($arVals)
{
$id = "id";
sort($arVals);
for ($i = 0; $i < count($arVals); $i++)
$id .= "_".$arVals[$i];
return $id;
}
}
$GLOBALS["stackCacheManager"] = new CStackCacheManager();
?>