ConLite/cms/includes/class.concache.php

531 Zeilen
16 KiB
PHP
Originalformat Blame Verlauf

<?php
/**
* Project:
* Contenido Content Management System
*
* Description:
* Handles the "PEAR Cache Output" functionality.
*
* @package Frontend
* @subpackage Cache
* @version $Rev: 450 $
* @author Murat Purc <murat@purc.de>
* @copyright four for business AG <www.4fb.de>
* @license http://www.contenido.org/license/LIZENZ.txt
* @link http://www.4fb.de
* @link http://www.contenido.org
*
* $Id: class.concache.php 450 2016-07-20 11:11:12Z oldperl $:
*/
if(!defined('CON_FRAMEWORK')) {
die('Illegal call');
}
class cConCache{
/**
* PEAR Cache Output Object
*
* @var obj $_oPearCache
*/
var $_oPearCache;
/**
* Flag 2 activate caching.
*
* @var bool $_bEnableCaching
*/
var $_bEnableCaching = false;
/**
* Flag for output of debug informations.
*
* @var bool $_bDebug
*/
var $_bDebug = false;
/**
* Flag 2 print html comment including some debug informations.
*
* @var bool $_bHtmlComment
*/
var $_bHtmlComment = false;
/**
* Start time of caching.
*
* @var int $_iStartTime
*/
var $_iStartTime;
/**
* Option array 4 generating cache identifier (e. g. $_GET,$_POST, $_COOKIE, ...).
*
* @var array _aIDOptions
*/
var $_aIDOptions;
/**
* Option array 4 pear caching.
*
* @var array $_aIDOptions
*/
var $_aCacheOptions;
/**
* Handler array 2 store code, beeing executed on some events.
* We have actually two events:
* - 'beforeoutput': code to execute before doing the output
* - 'afteroutput' code to execute after output
*
* @var array $_aEventCode
*/
var $_aEventCode;
/**
* Unique identifier for caching.
*
* @var string $_sID
*/
var $_sID;
/**
* Directory 2 store cached output.
*
* @var string $_sDir
*/
var $_sDir = 'cache/';
/**
* Subdirectory 2 store cached output.
*
* @var string $_sGroup
*/
var $_sGroup = 'default';
/**
* Substring 2 add as prefix to cache-filename.
*
* @var string $_sPrefix
*/
var $_sPrefix = 'cache_';
/**
* Default lifetime of cached files.
*
* @var int $_iLifetime
*/
var $_iLifetime = 3600;
/**
* Used 2 store debug message.
*
* @var string $_sDebugMsg
*/
var $_sDebugMsg = '';
/**
* HTML code template used for debug message.
*
* @var string $_sDebugTpl
*/
var $_sDebugTpl = '<div>%s</div>';
/**
* HTML comment template used for generating some debug infos.
*
* @var string $_sDebugTpl
*/
var $_sHtmlCommentTpl = '
<!--
CACHESTATE: %s
TIME: %s
VALID UNTIL: %s
-->
';
/**
* Constructor of cConCache
*
* @param string $cachedir Directory 2 cache files
* @param string $cachegroup Subdirectory 2 cache files
* @param string $cacheprefix Prefixname 2 add 2 cached files
*/
function cConCache($cachedir=null, $cachegroup=null, $cacheprefix=null){
// wherever you want the cache files
if(!is_null($cachedir)){
$this->_sDir = $cachedir;
}
// subdirectory where you want the cache files
if(!is_null($cachegroup)){
$this->_sGroup = $cachegroup;
}
// optional a filename prefix
if(!is_null($cacheprefix)){
$this->_sPrefix = $cacheprefix;
}
// config options are passed to the cache as an array
$this->_aCacheOptions = array('cache_dir' => $this->_sDir, 'filename_prefix' => $this->_sPrefix);
} // function cConCache()
/**
* Set/Get the flag 2 enable caching.
*
* @param bool $enable True 2 enable chaching or false
* @return mixed Enable flag or void
*/
function enable($enable=null){
if(!is_null($enable) && is_bool($enable)){
$this->_bEnableCaching = $enable;
} else {
return $this->_bEnableCaching;
}
} // function enable()
/**
* Set/Get the flag 2 debug cache object (prints out miss/hit state with execution time).
*
* @param bool $debug True 2 activate debugging or false.
* @return mixed Debug flag or void
*/
function debug($debug){
if(!is_null($debug) && is_bool($debug)){
$this->_bDebug = $debug;
} else {
return $this->_bDebug;
}
} // function debug()
/**
* Set/Get flag 2 print out cache info as html comment.
*
* @param bool $htmlcomment True debugging or false.
* @return void Htmlcomment flag or void
*/
function htmlComment($htmlcomment){
if(!is_null($htmlcomment) && is_bool($htmlcomment)){
$this->_bHtmlComment = $htmlcomment;
} else {
return $this->_bHtmlComment;
}
} // function htmlComment()
/**
* Set/Get caching lifetime in seconds.
*
* @param int $seconds New Lifetime in seconds
* @return mixed Actual lifetime or void
*/
function lifetime($seconds=null){
if ($seconds != null && is_numeric($seconds) && $seconds > 0) {
$this->_iLifetime = $seconds;
} else {
return $this->_iLifetime;
}
} // function lifetime()
/**
* Set/Get template to use on printing the chache info.
*
* @param string $template Template string including the '%s' format definition.
* @return void
*/
function infoTemplate($template){
$this->_sDebugTpl = $template;
} // function infoTemplate()
/**
* Add option 4 caching (e. g. $_GET,$_POST, $_COOKIE, ...). Used 2 generate the id for caching.
*
* @param string $name Name of option
* @param string $option Value of option (any variable)
* @return void
*/
function addOption($name, $option){
$this->_aIDOptions[$name] = $option;
} // function addOption()
/**
* Returns information cache hit/miss and execution time if caching is enabled.
*
* @return string Information about cache if caching is enabled, otherwhise nothing.
*/
function getInfo(){
if(!$this->_bEnableCaching){ return; }
return $this->_sDebugMsg;
} // function getInfo()
/**
* Handles PEAR caching. The script will be terminated by calling die(), if any cached
* content is found.
*
* @param int $iPageStartTime Optional start time, e. g. start time of main script
* @return void
*/
function start($iPageStartTime=null){
if(!$this->_bEnableCaching){ return; }
$this->_iStartTime = $this->_getMicroTime();
// set cache object and unique id
$this->_initPEARCache();
// check if it's cached and start the output buffering if neccessary
if ($content = $this->_oPearCache->start($this->_sID, $this->_sGroup)) {
//raise beforeoutput event
$this->_raiseEvent('beforeoutput');
$iEndTime = $this->_getMicroTime();
if ($this->_bHtmlComment) {
$time = sprintf("%2.4f", $iEndTime - $this->_iStartTime);
$exp = date('Y-m-d H:i:s', $this->_oPearCache->container->expires);
$content .= sprintf($this->_sHtmlCommentTpl, 'HIT', $time.' sec.', $exp);
if ($iPageStartTime != null && is_numeric($iPageStartTime)) {
$content .= '<!-- ['.sprintf("%2.4f", $iEndTime - $iPageStartTime).'] -->';
}
}
if ($this->_bDebug) {
$info = sprintf("HIT: %2.4f sec.", $iEndTime - $this->_iStartTime);
$info = sprintf($this->_sDebugTpl, $info);
$content = str_ireplace('</body>', $info."\n</body>", $content);
}
echo $content;
//raise afteroutput event
$this->_raiseEvent('afteroutput');
die();
}
} // function start()
/**
* Handles ending of PEAR caching.
*
* @return void
*/
function end(){
if (!$this->_bEnableCaching){ return; }
// this might go into your auto_append file. store the data into the cache, default lifetime is set in $this->_iLifetime
$this->_oPearCache->endPrint($this->_iLifetime, __FILE__ . ' ' . filemtime(__FILE__));
if ($this->_bDebug) {
$this->_sDebugMsg .= "\n".sprintf("MISS: %2.4f sec.\n", $this->_getMicroTime() - $this->_iStartTime);
$this->_sDebugMsg = sprintf($this->_sDebugTpl, $this->_sDebugMsg);
}
} // function end()
/**
* Removes any cached content if exists.
* This is nesessary to delete cached articles, if they are changed on backend.
*
* @return void
*/
function removeFromCache(){
// set cache object and unique id
$this->_initPEARCache();
$bExists = $this->_oPearCache->isCached($this->_sID, $this->_sGroup);
if ($bExists) {
$this->_oPearCache->remove($this->_sID, $this->_sGroup);
}
} // function removeFromCache()
/*
* Creates one-time a instance of PEAR cache output object and also the unique id,
* if propery $this->_oPearCache is not set.
*
* @return void
* @access private
*/
function _initPEARCache(){
if (is_object($this->_oPearCache)) {
return;
}
// create a output cache object mode - file storage
cInclude('pear', 'Cache/Output.php');
$this->_oPearCache = new Cache_Output('file', $this->_aCacheOptions);
// generate an ID from whatever might influence the script behavoiur
$this->_sID = $this->_oPearCache->generateID($this->_aIDOptions);
} // function _initPEARCache()
/**
* Raises any defined event code by using eval().
*
* @param string $name Name of event 2 raise
* @return void
* @access private
*/
function _raiseEvent($name){
// check if event exists, get out if not
if (!isset($this->_aEventCode[$name]) && !is_array($this->_aEventCode[$name])) {
return;
}
// loop array and execute each defined php-code
foreach ($this->_aEventCode[$name] as $code) {
eval($code);
}
} // function _raiseEvent()
/**
* Returns microtime (Unix-Timestamp), used to calculate time of execution.
*
* @return float Timestamp
* @access private
*/
function _getMicroTime(){
$mtime = explode(' ', microtime());
$mtime = $mtime[1] + $mtime[0];
return $mtime;
} // function _getMicroTime()
} // class cConCache
/**
* @class cConCacheHandler
* @brief Class cConCacheHandler. This is used to set configuration
* and to manage caching output
* @version 0.9
* @date 07.07.2006
* @author Murat Purc <murat@purc.de>
* @copyright <20> Murat Purc 2006
*/
class cConCacheHandler extends cConCache {
/**
* Constructor of cConCacheHandler.
* Does some checks and sets the configuration of cache object.
*
* @param array $aConf Configuration of caching as follows:
* - $a['excludecontenido'] bool. don't cache output, if we have a contenido variable,
* e. g. on calling frontend preview from backend
* - $a['enable'] bool. activate caching of frontend output
* - $a['debug'] bool. compose debuginfo (hit/miss and execution time of caching)
* - $a['infotemplate'] string. debug information template
* - $a['htmlcomment'] bool. add a html comment including several debug messages to output
* - $a['lifetime'] int. lifetime in seconds 2 cache output
* - $a['cachedir'] string. directory where cached content is 2 store.
* - $a['cachegroup'] string. cache group, will be a subdirectory inside cachedir
* - $a['cacheprefix'] string. add prefix 2 stored filenames
* - $a['idoptions'] array. several variables 2 create a unique id, if the output depends
* on them. e. g. array('uri'=>$_SERVER['REQUEST_URI'],'post'=>$_POST,'get'=>$_GET);
* @param obj $db Reference 2 Contenido database object
* @param int $iCreateCode Flag of createcode state from table con_cat_art
*/
function cConCacheHandler($aConf, &$db, $iCreateCode=null) {
// check if caching is allowed on contenido variable
if ($aConf['excludecontenido'] == true) {
if (isset($GLOBALS['contenido'])) {
// contenido variable exists, set state and get out here
$this->_bEnableCaching = false;
return;
}
}
// set enable state of caching
if (is_bool($aConf['enable'])) {
$this->_bEnableCaching = $aConf['enable'];
}
if ($this->_bEnableCaching == false) {
return;
}
// check if current article shouldn't be cached (by stese)
$sExcludeIdarts = getEffectiveSetting('cache', 'excludeidarts', false);
if ($sExcludeIdarts && strlen($sExcludeIdarts)>0) {
$sExcludeIdarts = preg_replace("/[^0-9,]/", '', $sExcludeIdarts);
$aExcludeIdart = explode(',', $sExcludeIdarts);
if (in_array($GLOBALS['idart'], $aExcludeIdart)) {
$this->_bEnableCaching = false;
return;
}
}
$this->_oDB = $db;
// set caching configuration
parent::cConCache($aConf['cachedir'], $aConf['cachegroup']);
$this->debug($aConf['debug']);
$this->htmlComment($aConf['htmlcomment']);
$this->lifetime($aConf['lifetime']);
$this->infoTemplate($aConf['infotemplate']);
foreach ($aConf['idoptions'] as $name => $var) {
$this->addOption($name, $var);
}
if (is_array($aConf['raiseonevent'])) {
$this->_aEventCode = $aConf['raiseonevent'];
}
// check, if code is to create
$this->_bEnableCaching = !$this->_isCode2Create($iCreateCode);
if ($this->_bEnableCaching == false) {
$this->removeFromCache();
}
} // function cConCacheHandler()
/**
* Checks, if the create code flag is set. Output will be loaded from cache, if no code is 2 create.
* It also checks the state of global variable $force.
*
* @param mixed $iCreateCode State of create code (0 or 1). The state will be loaded from database if value is "null"
* @return bool True if code is to create, otherwhise false.
* @access private
*/
function _isCode2Create($iCreateCode){
if ($this->_bEnableCaching == false) {
return;
}
// check content of global variable $force, get out if is's set to '1'
if (isset($GLOBALS['force']) && is_numeric($GLOBALS['force']) && $GLOBALS['force'] == 1) {
return true;
}
if (is_null($iCreateCode)) {
// check if code is expired
$oApiCatArtColl = new cApiCategoryArticleCollection('idart="'.$GLOBALS['idart'].'" AND idcat="'.$GLOBALS['idcat'].'"');
if ($oApiCatArt = $oApiCatArtColl->next()) {
$iCreateCode = $oApiCatArt->get('createcode');
unset($oApiCatArt);
}
unset($oApiCatArtColl);
}
return ($iCreateCode == 1) ? true : false;
} // function _isCode2Create()
} // class cConCacheHandler
?>