mirror of
				https://github.com/e107inc/e107.git
				synced 2025-10-24 19:26:21 +02:00 
			
		
		
		
	Issue #6 global LAN_META_DESCRIPTION and LAN_META_TITLE added and replacements made throughout.
		
			
				
	
	
		
			433 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			433 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /*
 | |
|  * e107 website system
 | |
|  *
 | |
|  * Copyright (C) 2008-2010 e107 Inc (e107.org)
 | |
|  * Released under the terms and conditions of the
 | |
|  * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 | |
|  *
 | |
|  * Cache handler
 | |
|  *
 | |
|  * $URL$
 | |
|  * $Id$
 | |
| */
 | |
| 
 | |
| if (!defined('e107_INIT')) { exit; }
 | |
| 
 | |
| define('CACHE_PREFIX','<?php exit; ?>');
 | |
| 
 | |
| /**
 | |
|  * Class to cache data as files, improving site speed and throughput.
 | |
|  * FIXME - pref independant cache handler, cache drivers
 | |
|  *
 | |
|  * @package     e107
 | |
|  * @subpackage	e107_handlers
 | |
|  * @version     $Id$
 | |
|  * @author      e107 Inc
 | |
|  */
 | |
| class ecache {
 | |
| 
 | |
| 	public $CachePageMD5;
 | |
| 	public $CachenqMD5;
 | |
| 	public $UserCacheActive;			// Checkable flag - TRUE if user cache enabled
 | |
| 	public $SystemCacheActive;			// Checkable flag - TRUE if system cache enabled
 | |
| 	private $lastError;
 | |
| 	private $lastFile;
 | |
| 
 | |
| 	const CACHE_PREFIX = '<?php exit; ?>';
 | |
| 
 | |
| 	function __construct()
 | |
| 	{
 | |
| 		//$this->UserCacheActive = e107::getPref('cachestatus');
 | |
| 		//$this->SystemCacheActive = e107::getPref('syscachestatus');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set the MD5 Hash
 | |
| 	 */
 | |
| 	public function setMD5($text, $hash=true)
 | |
| 	{
 | |
| 		if($text === null)
 | |
| 		{
 | |
| 			$this->CachePageMD5 = md5(e_BASE.e_LANGUAGE.THEME.USERCLASS_LIST.defset('e_QUERY').filemtime(THEME.'theme.php'));
 | |
| 			return $this;
 | |
| 		}
 | |
| 
 | |
| 		$this->CachePageMD5 = ($hash === true) ? md5($text) : $text;
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function getMD5()
 | |
| 	{
 | |
| 		return $this->CachePageMD5;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @param $CacheTag
 | |
| 	 * @param bool $syscache
 | |
| 	 * @return string
 | |
| 	 * @desc Internal class function that returns the filename of a cache file based on the query.
 | |
| 	 * @scope private
 | |
| 	 * If the tag begins 'menu_', e_QUERY is not included in the hash which creates the file name
 | |
| 	 */
 | |
| 	function cache_fname($CacheTag, $syscache = false)
 | |
| 	{
 | |
| 		if(strpos($CacheTag, "nomd5_") === 0) {
 | |
| 			// Add 'nomd5' to indicate we are not calculating an md5
 | |
| 			$CheckTag = '_nomd5';
 | |
| 		}
 | |
| 		elseif (isset($this) && $this instanceof ecache)
 | |
| 		{
 | |
| 			if (defined("THEME"))
 | |
| 			{
 | |
| 				if (strpos($CacheTag, "nq_") === 0)
 | |
| 				{
 | |
| 					// We do not care about e_QUERY, so don't use it in the md5 calculation
 | |
| 					if (!$this->CachenqMD5)
 | |
| 					{
 | |
| 						$this->CachenqMD5 = md5(e_BASE.(defined("ADMIN") && ADMIN == true ? "admin" : "").e_LANGUAGE.THEME.USERCLASS_LIST.filemtime(THEME.'theme.php'));
 | |
| 					}
 | |
| 					// Add 'nq' to indicate we are not using e_QUERY
 | |
| 					$CheckTag = '_nq_'.$this->CachenqMD5;
 | |
| 
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					// It's a page - need the query in the hash
 | |
| 					if (!$this->CachePageMD5)
 | |
| 					{
 | |
| 						$this->CachePageMD5 = md5(e_BASE.e_LANGUAGE.THEME.USERCLASS_LIST.defset('e_QUERY').filemtime(THEME.'theme.php'));
 | |
| 					}
 | |
| 					$CheckTag = '_'.$this->CachePageMD5;
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				// Check if a custom CachePageMD5 is in use in e_module.php.
 | |
| 				$CheckTag = ($this->CachePageMD5) ? "_".$this->CachePageMD5 : "";
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$CheckTag = '';
 | |
| 		}
 | |
| 		$q = ($syscache ? "S_" : "C_").preg_replace("#\W#", "_", $CacheTag);
 | |
| 		
 | |
| 		if($syscache === true)
 | |
| 		{
 | |
| 			$CheckTag = ''; // no MD5 on system cache. XXX To be Checked. 
 | |
| 		}
 | |
| 
 | |
| 		$fname = e_CACHE_CONTENT.$q.$CheckTag.'.cache.php';
 | |
| 		//echo "cache f_name = $fname <br />";
 | |
| 		$this->lastFile = $fname;
 | |
| 		return $fname;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieve Cache data.
 | |
| 	 * @param $CacheTag
 | |
| 	 * @param bool|int $MaximumAge the time in minutes before the cache file 'expires'
 | |
| 	 * @param bool $ForcedCheck check even if cache pref is disabled.
 | |
| 	 * @param bool $syscache set to true when checking sys cache.
 | |
| 	 * @return string
 | |
| 	 * @desc Returns the data from the cache file associated with $query, else it returns false if there is no cache for $query.
 | |
| 	 * @scope public
 | |
| 	 */
 | |
| 	public function retrieve($CacheTag, $MaximumAge = false, $ForcedCheck = false, $syscache = false)
 | |
| 	{
 | |
| 		if(($ForcedCheck != false ) || ($syscache == false && $this->UserCacheActive) || ($syscache == true && $this->SystemCacheActive) && !e107::getParser()->checkHighlighting())
 | |
| 		{
 | |
| 			$cache_file = (isset($this) && $this instanceof ecache ? $this->cache_fname($CacheTag, $syscache) : self::cache_fname($CacheTag, $syscache));
 | |
| 
 | |
| 			if(file_exists($cache_file))
 | |
| 			{
 | |
| 				if ($MaximumAge !== false && (filemtime($cache_file) + ($MaximumAge * 60)) < time()) {
 | |
| 					unlink($cache_file);
 | |
| 					return false;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					$ret = file_get_contents($cache_file);
 | |
| 
 | |
| 					if($ret === false)
 | |
| 					{
 | |
| 						$this->lastError = "Couldn't read ".$cache_file;
 | |
| 					}
 | |
| 
 | |
| 					if (strpos($ret, self::CACHE_PREFIX) === 0)
 | |
| 					{
 | |
| 						$ret = substr($ret, strlen(self::CACHE_PREFIX));
 | |
| 					}
 | |
| 					elseif(strpos($ret, '<?php exit;') === 0)
 | |
| 					{
 | |
| 						$ret = substr($ret, 11);
 | |
| 					}
 | |
| 					elseif(strpos($ret,'<?php') === 0)
 | |
| 					{
 | |
| 						$ret = substr($ret, 5);		// Handle the history for now
 | |
| 					}
 | |
| 
 | |
| 					return $ret;
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				$this->lastError = "Cache file not found: ".$cache_file;
 | |
| 				return false;
 | |
| 			}
 | |
| 		}
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Return the last error encountered during cache processing.
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function getLastError()
 | |
| 	{
 | |
| 		return $this->lastError;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Return the last error encountered during cache processing.
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function getLastFile()
 | |
| 	{
 | |
| 		return $this->lastFile;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @param string $CacheTag
 | |
| 	 * @param bool $MaximumAge the time in minutes before the cache file 'expires'
 | |
| 	 * @param bool $ForcedCheck
 | |
| 	 * @return string
 | |
| 	 * @desc Returns the data from the cache file associated with $query, else it returns false if there is no cache for $query.
 | |
| 	 * @scope public
 | |
| 	 */
 | |
| 	function retrieve_sys($CacheTag, $MaximumAge = false, $ForcedCheck = false)
 | |
| 	{
 | |
| 		if(isset($this) && $this instanceof ecache)
 | |
| 		{
 | |
| 			return $this->retrieve($CacheTag, $MaximumAge, $ForcedCheck, true);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			return self::retrieve($CacheTag, $MaximumAge, $ForcedCheck, true);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 *
 | |
| 	 * @param string $CacheTag - name of tag for future retrieval - should NOT contain an MD5. 
 | |
| 	 * @param string $Data - data to be cached
 | |
| 	 * @param boolean $ForceCache [optional] if TRUE, writes cache even when disabled in admin prefs. 
 | |
| 	 * @param boolean $bRaw [optional] if TRUE, writes data exactly as provided instead of prefacing with php leadin
 | |
| 	 * @param boolean $syscache [optional]
 | |
| 	 * @return void|null
 | |
| 	 */
 | |
| 	public function set($CacheTag, $Data, $ForceCache = false, $bRaw=0, $syscache = false)
 | |
| 	{
 | |
| 		if(defined('E107_INSTALL') && E107_INSTALL === true)
 | |
| 		{
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		if(($ForceCache != false ) || ($syscache == false && $this->UserCacheActive) || ($syscache == true && $this->SystemCacheActive) && !e107::getParser()->checkHighlighting())
 | |
| 		{
 | |
| 			$cache_file = (isset($this) && $this instanceof ecache ? $this->cache_fname($CacheTag, $syscache) : self::cache_fname($CacheTag, $syscache));
 | |
| 			@file_put_contents($cache_file, ($bRaw? $Data : self::CACHE_PREFIX.$Data) );
 | |
| 			@chmod($cache_file, 0755); //Cache should not be world-writeable
 | |
| 			@touch($cache_file);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	* @return void
 | |
| 	* @param string $CacheTag - name of tag for future retrieval - should NOT contain an MD5
 | |
| 	* @param string $Data - data to be cached
 | |
| 	* @param bool   $ForceCache (optional, default false) - if TRUE, writes cache even when disabled
 | |
| 	* @param bool   $bRaw (optional, default false) - if TRUE, writes data exactly as provided instead of prefacing with php leadin
 | |
| 	* @desc Creates / overwrites the cache file for $query, $text is the data to store for $query.
 | |
| 	* @scope public
 | |
| 	*/
 | |
| 	function set_sys($CacheTag, $Data, $ForceCache = false, $bRaw=0)
 | |
| 	{
 | |
| 		if(isset($this) && $this instanceof ecache)
 | |
| 		{
 | |
| 			$this->set($CacheTag, $Data, $ForceCache, $bRaw, true);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			self::set($CacheTag, $Data, $ForceCache, $bRaw, true);			
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Deletes cache files. If $query is set, deletes files named {$CacheTag}*.cache.php, if not it deletes all cache files - (*.cache.php)
 | |
| 	 *
 | |
| 	 * @param string $CacheTag
 | |
| 	 * @param boolean $syscache
 | |
| 	 * @param boolean $related clear also 'nq_' and 'nomd5_' entries
 | |
| 	 * @return bool
 | |
| 	 *
 | |
| 	 */
 | |
| 	public function clear($CacheTag = '', $syscache = false, $related = false)
 | |
| 	{
 | |
| 
 | |
| 		$file = ($CacheTag) ? preg_replace("#\W#", "_", $CacheTag)."*.cache.php" : "*.cache.php";
 | |
| 		e107::getEvent()->triggerAdminEvent('cache_clear', "cachetag=$CacheTag&file=$file&syscache=$syscache");
 | |
| 		e107::getEvent()->trigger('cache_clear', ['tag'=>$CacheTag, 'file'=>$file, 'system'=>$syscache]);
 | |
| 		$ret = self::delete(e_CACHE_CONTENT, $file, $syscache);
 | |
| 
 | |
| 		if($CacheTag && $related) //TODO - too dirty - add it to the $file pattern above
 | |
| 		{
 | |
| 			self::delete(e_CACHE_CONTENT, 'nq_'.$file, $syscache);
 | |
| 			self::delete(e_CACHE_CONTENT, 'nomd5_'.$file, $syscache);
 | |
| 			//ecache::delete(e_CACHE_CONTENT, 'nq_'.$file, $syscache);
 | |
| 			//ecache::delete(e_CACHE_CONTENT, 'nomd5_'.$file, $syscache);
 | |
| 		}
 | |
| 		return $ret;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	* @return bool
 | |
| 	* @param string $CacheTag
 | |
| 	* @desc Deletes cache files. If $query is set, deletes files named {$CacheTag}*.cache.php, if not it deletes all cache files - (*.cache.php)
 | |
| 	*/
 | |
| 	function clear_sys($CacheTag = '', $related = false)
 | |
| 	{
 | |
| 
 | |
| 
 | |
| 		if(isset($this) && $this instanceof ecache)
 | |
| 		{
 | |
| 			return $this->clear($CacheTag, true, $related);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			self::clear($CacheTag, true, $related);
 | |
| 		//	ecache::clear($CacheTag, true, $related);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	* @return bool
 | |
| 	* @param string $dir
 | |
| 	* @param string $pattern
 | |
| 	* @desc Internal class function to allow deletion of cache files using a pattern, default '*.*'
 | |
| 	* @scope private
 | |
| 	*/
 | |
| 	function delete($dir, $pattern = "*.*", $syscache = false) {
 | |
| 		$pattern = ($syscache ? "S_" : "C_").$pattern;
 | |
| 		$pattern = str_replace(array("\*", "\?"), array(".*", "."), preg_quote($pattern));
 | |
| 		if (substr($dir, -1) != "/") {
 | |
| 			$dir .= "/";
 | |
| 		}
 | |
| 		if (is_dir($dir))
 | |
| 		{
 | |
|  			$d = opendir($dir);
 | |
| 			while ($file = readdir($d)) {
 | |
| 				if (is_file($dir.$file) && preg_match("/^{$pattern}$/", $file)) {
 | |
| 					unlink($dir.$file);
 | |
| 				}
 | |
| 			}
 | |
| 			closedir($d);
 | |
| 			return true;
 | |
| 		} else {
 | |
| 			return false;
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	
 | |
| 	/**
 | |
| 	 * Clear Full Cache
 | |
| 	 * @param string $type: content | system| browser | db | image | js | css | library
 | |
| 	 * @example clearAll('db');
 | |
| 	 */
 | |
| 	 
 | |
| 	function clearAll($type,$mask = null)
 | |
| 	{		
 | |
| 		$path = null;
 | |
| 
 | |
| 		$event = e107::getEvent();
 | |
| 
 | |
| 		if($type =='content')
 | |
| 		{
 | |
| 			$this->clear();
 | |
| 			$event->trigger('cache_clear_all', ['type'=>$type,'mask'=>$mask]);
 | |
| 			return;
 | |
| 		}
 | |
| 			
 | |
| 		if($type === 'system')
 | |
| 		{
 | |
| 			$this->clear_sys();
 | |
| 			$event->trigger('cache_clear_all', ['type'=>$type,'mask'=>$mask]);
 | |
| 			return;	
 | |
| 		}
 | |
| 
 | |
| 		if($type === 'browser')
 | |
| 		{
 | |
| 			e107::getConfig()->set('e_jslib_browser_cache', time())->save(false);
 | |
| 			$event->trigger('cache_clear_all', ['type'=>$type,'mask'=>$mask]);
 | |
| 			return;	
 | |
| 		}
 | |
| 
 | |
| 		if($type === 'db')
 | |
| 		{
 | |
| 			$path = e_CACHE_DB;
 | |
| 			$mask = ($mask == null) ? '.*\.php' : $mask;
 | |
| 		}
 | |
| 
 | |
| 		if($type === 'image')
 | |
| 		{
 | |
| 			$path = e_CACHE_IMAGE;
 | |
| 			$mask = ($mask == null) ? '.*(\.cache\.bin|\.jpg|\.jpeg|\.png|\.gif)' : $mask;
 | |
| 		}
 | |
| 
 | |
| 		if($type === 'js')
 | |
| 		{
 | |
| 			$path = e_WEB."cache/";
 | |
| 			$mask = ($mask == null) ? '.*\.js' : $mask;
 | |
| 		}
 | |
| 
 | |
| 		if($type === 'css')
 | |
| 		{
 | |
| 			$path = e_WEB."cache/";
 | |
| 			$mask = ($mask == null) ? '.*\.css' : $mask;
 | |
| 		}
 | |
| 
 | |
| 		if($type === 'library')
 | |
| 		{
 | |
| 			$path = e_CACHE_CONTENT;
 | |
| 			$mask = ($mask == null) ? 'S_Library_.*\.cache\.php' : $mask;
 | |
| 		}
 | |
| 
 | |
| 		if((null == $path) || (null == $mask))
 | |
| 		{
 | |
| 			return;
 | |
| 		}
 | |
| 		
 | |
| 		$fl = e107::getFile(false);
 | |
| 		$fl->mode = 'fname';
 | |
| 		$files = $fl->get_files($path, $mask);
 | |
| 
 | |
| 		if($files)
 | |
| 		{
 | |
| 			foreach ($files as $file)
 | |
| 			{
 | |
| 				unlink($path.$file);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		$event->trigger('cache_clear_all', ['type'=>$type,'mask'=>$mask]);
 | |
| 	}
 | |
| 	
 | |
| }
 |