Location: PHPKode > projects > SvnDashboard > 1.1.3.140/phpLib/modules/Logger.mod.php
<?php

//=============================================================================
//
// Description:
// 	The logger module offers methods making log entries. The module supports
//	several modes  that affect whether  the log is created in non-persistent
//	memory, persistent memory, a flat-file, or in a database.
//
// Classes:
// 	ErrorHandler
//		Functions:
//			__construct( )
//			__destruct( )
//
// Change-Log:
//	2008-10-31 - Bob Jackman:	Added Comments/Code Documentation
//
//	2008-11-04 - Bob Jackman:	Added support for multiple modes of operation.
//							There  is  currently  a  segmentation  fault  when in
//							LOGGER_MODE_FLAT mode and the logfile has reached its
//							configured maxEntries limit.
//							Database support is still pending.
//
//	2008-11-05 - Bob Jackman:	Redefined Mode Constants. Introduced Default Constants.
//							Adjusted code accordingly.
//
//	2008-11-06 - Bob Jackman:	Moved create/kill functions into separate GOD file.
//							Adjusted MOD file accordingly.
//
//=============================================================================





//====================  Global Constant Initialization
if (!defined('LOGGER_MODE_MEM'))			{ define('LOGGER_MODE_MEM', 1); }
if (!defined('LOGGER_MODE_MEM_STATEFUL'))	{ define('LOGGER_MODE_MEM_STATEFUL', 1); }
if (!defined('LOGGER_MODE_MEM_STATELESS'))	{ define('LOGGER_MODE_MEM_STATELESS', 2); }
if (!defined('LOGGER_MODE_FLAT'))			{ define('LOGGER_MODE_FLAT', 4); }
if (!defined('LOGGER_MODE_DATABASE'))		{ define('LOGGER_MODE_DATABASE', 8); }
if (!defined('LOGGER_MODE_MEM_FLAT'))		{ define('LOGGER_MODE_MEM_FLAT', 6); }
if (!defined('LOGGER_MODE_MEM_DATABASE'))	{ define('LOGGER_MODE_MEM_DATABASE', 10); }
if (!defined('LOGGER_DEFAULT_MODE'))		{ define('LOGGER_DEFAULT_MODE', LOGGER_MODE_MEM_STATEFUL); }
if (!defined('LOGGER_DEFAULT_FLAT_PATH'))	{ define('LOGGER_DEFAULT_FLAT_PATH', './log.log'); }
if (!defined('LOGGER_DEFAULT_MAX_ENTRIES'))	{ define('LOGGER_DEFAULT_MAX_ENTRIES', 500); }
if (!defined('LOGGER_DEFAULT_ERROR_LOGGING')){ define('LOGGER_DEFAULT_ERROR_LOGGING', false); }

//====================  Module Implementation
class Logger extends Module
{
	//=============================================================================
     // Class: Logger
     // Author: Bob Jackman
     // Date: 2008-10-29
     //
     // Description:	Methods for making and reading log entries in memory,
     //				database, or on disk
     //
     // Dependencies:
     // 	None
     //===========================================================================

     private $_mode;			// mode in which the logger operates (memory, database, flat-file, etc)
     private $_log;				// log entries (if logging in memory mode)
     private $_logPath;			// path to log file (if logging in flat mode)
     private $_errorLogging;		// level of errors to automatically log (similar to PHP's error_reporting directive)
     private $_maxEntries;		// maximum log entries to keep. old entries are shifted off to make room for new ones

     function __construct(EventData $preCreate = null, EventData $postCreate = null, EventData $preDestroy = null, EventData $postDestroy = null, ModuleLoader $loader = null)
     {
     	//=============================================================================
		// Function: __construct
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description: Initialize the logger module
		//
		// Params:
		// 	$preCreate {EventData} Optional:	EventData object to pass to the
		//								preCreate GOD event. If not passed, the
		//								GOD event will not be fired.
		//	$postCreate {EventData} Optional:	EventData object to pass to the
		//								postCreate GOD event. If not passed,
		//								the GOD event will not be fired.
		//	$preDestroy {EventData} Optional:	EventData object to pass to the
		//								preDestroy GOD event. If not passed,
		//								the GOD event will not be fired.
		//	$postDestroy {EventData} Optional:	EventData object to pass to the
		//								postDestroy GOD event. If not passed,
		//								the GOD event will not be fired.
		//	$loader {ModuleLoader} Optional:	Reference to the ModuleLoader object
		//								that owns this module
		//	$onFail {String} Optional:		[w|warn|warning|e|error|fatal|die]
		//								Action to take if the module fails to
		//								load for any reason (unresolved
		//								dependencies). Defaults to fatal.
		//
		// Returns: {none}
		//==================================

		parent::__construct($preCreate, $postCreate, $preDestroy, $postDestroy, $loader);

		//====================  Set Default Configuration Options
		if ($this->_errorLogging === null) // -- not already set
		{
			$this->setErrorLogging(LOGGER_DEFAULT_ERROR_LOGGING);
		}

		if ($this->_mode === null) // -- not already set
		{
			$this->setMode(LOGGER_DEFAULT_MODE);
		}

		if ($this->_logPath === null) // -- not already set
		{
			$this->setPath(LOGGER_DEFAULT_FLAT_PATH);
		}

		if ($this->_maxEntries === null) // -- not already set
		{
			$this->setMaxEntries(LOGGER_DEFAULT_MAX_ENTRIES);
		}

	    	//====================  Register Module Events
	    	$this->registerEvents();

     	//====================  Log Initialization Logic
     	if ($this->_mode == LOGGER_MODE_FLAT) // -- flat only mode
     	{
     		// don't clear log
     		// writes are done at time of log entry
     		// file loading is not neccessary
     	}
     	elseif ($this->_mode == LOGGER_MODE_DATABASE) // -- database only mode
     	{
     		// don't clear log
     		// writes are done at time of log entry
     		// database log loading is not neccessary
     	}
     	elseif ($this->_mode == LOGGER_MODE_MEM_FLAT) // -- flat AND memory mode
     	{
     		// don't clear log
     		// writes are done on destruct
     		// load file into memory
     		$this->_log = $this->loadFlatLog();
     	}
     	elseif ($this->_mode == LOGGER_MODE_MEM_DATABASE) // -- database AND memory mode
     	{
     		// don't clear log
     		// writes are done on destruct
     		// load database log into memory
     		$this->_log = $this->loadDatabaseLog();
     	}
     	else // -- memory only mode (stateful or stateless)
     	{
     		// clear log
     		// no file write is ever done
     		// no file/db load is possible
     		$this->clearLog();
     	}

		//====================  Log Startup
		new LogEntry('** Logger Started', 'Logger', 'Primary Functions', null, $this);
     }

     public function __destruct()
     {
     	//=============================================================================
		// Function: __destruct
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Destruct the logger module
		//
		// Params:
		// 	None
		//
		// Returns: {none}
		//=============================================================================

		//====================  Initialize Variables
		$killArgs = func_get_args();

		//====================  Log Shutdown
		new LogEntry('** Logger Shut Down', 'Logger', 'Primary Functions', null, $this);

		//====================  Save Log
		if ($this->_mode == LOGGER_MODE_MEM_DATABASE) // -- db log and memory log
     	{
     		// this only happens if mode is db AND memory (persistent or non-persistent) mode
     		// otherwise, a db write happens at the time of logging
     		$this->writeDbLog();
     	}
     	elseif ($this->_mode == LOGGER_MODE_MEM_FLAT) // -- flat file and memory log
     	{
     		// this only happens if mode is flat file AND memory (persistent or non-persistent) mode
     		// otherwise, a flat file write happens at the time of logging
     		$this->writeFlatLog();
     	}

     	parent::__destruct();
     }

     // --

     public function addEntry(LogEntry $logEntry, $append = true)
     {
     	//=============================================================================
		// Function: addEntry
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description: Add an entry to the log
		//
		// Params:
		// 	$logEntry {LogEntry} Required:	LogEntry object containing log message,
		//								timestamp, and other pertinent info
		//	$append {bool} Optional:			Whether to append to log, or flush and
		//								start over. If not passed, new entry is
		//								appended.
		//
		// Returns: {none}
		//=============================================================================

		//====================  Clear Log Contents
     	if (!$append) // -- don't append
     	{
     		$this->clearLog();
     	}

		//====================  Add Log Entry
		$logArray = $this->getLog();
     	if ($this->getMaxEntries() >= 0) // -- max entries is positive value
     	{
     		$isFull = (sizeof($logArray) >= $this->getMaxEntries() ? true : false);
     	}
     	else // -- max entries is negative value (unlimited entries)
     	{
     		$isFull = false;
     	}

     	$errorLevel = $logEntry->getErrorLevel();
     	if (($errorLevel == -1) || (($errorLevel & $this->_errorLogging) != 0)) // -- based on reporting level, log this entry
     	{
	     	if ($this->_mode  == LOGGER_MODE_DATABASE) // -- db log
	     	{
				// to do: check for full log before writing

     			//====================  Write Entry to Database
     			$this->writeDbLog($logEntry);
     		}
	     	elseif ($this->_mode == LOGGER_MODE_FLAT) // -- flat log
	     	{
	     		if ($isFull) // -- log is full
	     		{
	     		  	$remove = (sizeof($logArray) - $this->getMaxEntries()) + 1;
	     			array_splice($logArray, 0, $remove);
	     		}

	     		$logArray[] = $logEntry;

	     		//====================  Write Entry to File
	     		$this->writeFlatLog($logArray);
	     	}
	     	else // -- mem log
	     	{
	     		if ($isFull) // -- log is full
		     	{
		     		array_shift($this->_log);
		     	}

	     		//====================  Add Event to Memory
	     		array_push($this->_log, $logEntry);
	     	}

	     	//====================  Determine if Events Should be Fired
	     	$fireEvents = true;
	     	$stack = debug_backtrace();
	     	array_shift($stack); // -- remove this logger object from stack
	     	foreach ($stack as $level) // -- loop through current stack
	     	{
	     		if (isset($level['class']) && $level['class'] == get_class($this)) // -- logger is making the log entry
	     		{
	     			$fireEvents = false;
	     		}
	     	}

	     	//====================  Fire onLogEntry Event
     		$this->registerEvents(); // -- attempt to register appropriate events

    			$eventData = new EventData('log');
			$eventData->setAttribute('timestamp', microtime(true));
			$eventData->setCaller($this);
			$eventData->setAttribute('description', 'Log Entry');
			$eventData->setAttribute('logEntry', $logEntry);
    			$this->fireEvent(onLogEntry, $eventData);
	     }
     }

     public function clearLog()
     {
     	//=============================================================================
		// Function: clearLog
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Clear all existing log contents (do not remove flat-files
		//				or database tables)
		//
		// Params:
		// 	None
		//
		// Returns: {void}
		//
		//==================================

		//====================  Clear Log Entries
     	if ($this->_mode == LOGGER_MODE_DATABASE) // -- db mode
     	{
     		//====================  Clear Database Log
     		// to do: clear db log
     	}
     	elseif ($this->_mode == LOGGER_MODE_FLAT) // -- flat mode
     	{
     		//====================  Clear Log File
			$logFile = fopen($this->_logPath, 'w');
			fwrite($logFile, null);
			fclose($logFile);
     	}
     	else // -- mem log
     	{
     		//====================  Clear Log Memory
     		$this->_log = array();
     	}
     }

	public function getErrorLogging()
	{
		//=============================================================================
		// Function: getErrorLogging
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the current errorlogging level
		//
		// Params:
		// 	None
		//
		// Returns: {int}
		//=============================================================================

		//====================  Return ErrorLogging Value
		return $this->_errorLogging;
	}

	public function getLog()
	{
		//=============================================================================
		// Function: getLog
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description: Get the current log entries
		//
		// Params:
		// 	None
		//
		// Returns: {array}
		//=============================================================================

		//====================  Return Log Entries
		if ($this->_mode == LOGGER_MODE_DATABASE) // -- db log
     	{
     		// to do: get db log entries
     	}
     	elseif ($this->_mode == LOGGER_MODE_FLAT) // -- flat log
     	{
			return $this->loadFlatLog();
     	}
		else // -- mem log
     	{
     		return $this->_log;
     	}
	}

	public function getLogCount()
	{
		//=============================================================================
		// Function: getLogCount
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the current number of log entries
		//
		// Params:
		// 	None
		//
		// Returns: {int}
		//=============================================================================

		//====================  Return Log Count
		return sizeof($this->getLog());
	}

	public function getMaxEntries()
	{
		//=============================================================================
		// Function: getMaxEntries
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the currently configured maximum entries value
		//
		// Params:
		// 	None
		//
		// Returns: {int}
		//=============================================================================

		//====================  Return maxEntries
		return $this->_maxEntries;
	}

     public function getMode()
     {
     	//=============================================================================
		// Function: getMode
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description: Get the current logging mode
		//
		// Params:
		// 	None
		//
		// Returns: {int}
		//=============================================================================

		//====================  Return Logging Mode
     	return $this->_mode;
     }

     public function setErrorLogging($errorLogging)
     {
     	//=============================================================================
		// Function: setErrorLogging
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Set the level of errors to automatically log
		//
		// Params:
		// 	$errorLogging {int} Required:		Level of errors to automatically log
		//
		// Returns: {void}
		//=============================================================================

		//====================  Set Error Logging Level
     	$this->_errorLogging = $errorLogging;
     }

     public function setMaxEntries($maxEntries)
     {
     	//=============================================================================
		// Function: setMaxEntries
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Set the maximum number of log entries to keep
		//
		// Params:
		// 	$maxEntries {int} Required:	Maximum number of log entries to keep
		//
		// Returns: {int}
		//=============================================================================

		//====================  Set Maximum Log Entries
     	$this->_maxEntries = $maxEntries;
     }

     private function setMode($mode)
     {
     	//=============================================================================
		// Function: setMode
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description: Set the operation mode for the logger
		//
		// Params:
		//	$mode {int} Optional:	Determines the mode of logging
		//							* Non-Persistent Memory Log
		//							* Persistent Memory Only
		//							* Flat-File
		//							* Database
		//							* Memory + Flat File
		//							* Memory + Database
		//						If not passed, mode defaults to
		//						LOGGER_DEFAULT_MODE
		//
		// Returns: {void}
		//=============================================================================

		//====================  Validate Requested Mode
     	$validModes = array('LOGGER_MODE_MEM' => LOGGER_MODE_MEM,
						'LOGGER_MODE_MEM_STATEFUL' => LOGGER_MODE_MEM_STATEFUL,
						'LOGGER_MODE_MEM_STATELESS' => LOGGER_MODE_MEM_STATELESS,
						'LOGGER_MODE_FLAT' => LOGGER_MODE_FLAT,
						'LOGGER_MODE_DATABASE' => LOGGER_MODE_DATABASE,
						'LOGGER_MODE_MEM_FLAT' => LOGGER_MODE_MEM_FLAT,
						'LOGGER_MODE_MEM_DATABASE' => LOGGER_MODE_MEM_DATABASE
						);

     	if (!isset($validModes[$mode]) && !in_array($mode, $validModes)) // -- not a valid mode
     	{
     		if (empty($this->_mode)) // -- mode is not already set
     		{
     			trigger_error('Invalid Logger Mode \''.$mode.'\': Default Used', E_USER_WARNING);
     			$mode = LOGGER_DEFAULT_MODE;
     		}
     		else // -- mode has already been set
     		{
     			trigger_error('Invalid Logger Mode \''.$mode.'\': Reverted to previous mode', E_USER_WARNING);
     			return false;
     		}
     	}
     	elseif (isset($validModes[$mode])) // -- mode is a valid string
    		{
    			$mode = constant($mode);
    		}

     	//====================  Set Mode
     	$this->_mode = $mode;
     }

     public function setPath($path)
     {
     	//=============================================================================
		// Function: setPath
		// Author: Bob Jackman
		// Date: 2008-11-04
		//
		// Description:	Set the path to the flat log file
		//
		// Params:
		// 	$path {$string} Required:	Valid path to flat file in which to keep log.
		//							If file does not exist, it will be created.
		//
		// Returns: {bool}	True on success, False on failure
		//=============================================================================

		//====================  Validate Path
		$pathParts = pathinfo($path);
		if (empty($pathParts['filename'])) // -- no filename in path
		{
			trigger_error('Logger Path specifies no filename. Failed to set path.', E_USER_WARNING);
			return false;
		}
		else // -- filename specified
		{
			if (realpath($path)) // -- path exists
			{
				if ($this->_logPath !== false && $this->_logPath !== null) // -- path has already been set
				{
					if ($this->_mode == LOGGER_MODE_FLAT) // -- flat mode only
					{
						trigger_error('Changing path when writing of flat log has already started. Previous Log entries will not follow path change.', E_USER_WARNING);
					}
					elseif ($this->_mode == LOGGER_MODE_FLAT) // -- db mode only
					{
						// to do;
					}
				}

				$resolvedPath = realpath($path);
				$this->_logPath = $resolvedPath;

				return true;
			}
			else // -- path does not exist
			{
				$dir = realpath($pathParts['dirname']);

				if (is_dir($dir)) // -- dir exists
				{
					//====================  Attempt to Create File
					$logFile = @fopen($path, 'w');
					if ($logFile) // -- creation successful
					{
						$resolvedPath = realpath($path);
						$this->_logPath = $resolvedPath;
					}
					else // -- creation failed
					{
						trigger_error('Logger file does not exist. Creation Failed: \''.$dir.'/'.$pathParts['basename'].'\'', E_USER_WARNING);
					}
				}
				else // -- bad directory
				{
					trigger_error('Logger path \''.$pathParts['dirname'].'\' does not exist.', E_USER_WARNING);
				}

				return false;
			}
		}
     }

     // --

     private function loadFlatLog($path = false)
     {
     	//=============================================================================
		// Function: loadFlatLog
		// Author: Bob Jackman
		// Date: 2008-11-04
		//
		// Description: Load the log from a flat file
		//
		// Params:
		// 	$path {$string} Optional:	Valid path to flat file in which to keep log.
		//							If not passed, currently configured path is used.
		//
		// Returns: {bool}	True on success, False on failure
		//=============================================================================

		//====================  Validate Path
     	if ($path === false) // -- path not passed
     	{
     		$path = $this->_logPath;
     	}

		if (file_exists($path)) // -- path exists
		{
			//====================  Load File Contents
			$logText = file_get_contents($this->_logPath);

			//====================  Split Into Array
			$rawArray = explode("\n", $logText);

			//====================  Trim Empty Elements
			$rawArray = arrayTrim($rawArray);

			//====================  Extract Data and Create LogEntry Objects
			$log = array();
			foreach ($rawArray as $text) // -- loop through each log entry
			{
				//====================  Extract Data
				preg_match('/^(.*?):\s+(.*?)\s+\((.*?)\)\W+(.*?)\s*\[([-\d]+)\]$/', $text, $matches);

				//====================  Create Timestamp
				preg_match_all('/(\d+)|(\w+)/', $matches[1], $time);
				$time = $time[0];
				$time = mktime($time[3], $time[4], $time[5], $time[0], $time[1], $time[2], (stristr($time[6], 'dt') ? 1 : 0));

				//====================  Create LogEntry Object
				$entry = new LogEntry($matches[4], $matches[2], $matches[3], $matches[5]);
				$entry->setTimestamp($time);

				$log[] = $entry;
			}

			return $log;
		}
		else // -- path does not exist
		{
			return false;
		}
     }

     private function registerEvents()
     {
     	//=============================================================================
		// Function: registerEvents
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Register Logger Events such as onLogEntry and onLogCommit
		//
		// Params:
		// 	None
		//
		// Returns: {void}
		//=============================================================================

		//====================  Register Events
    		$this->registerEvent('onLogEntry');
    		$this->registerEvent('onLogCommit');
     }

     private function writeDbLog($entry = false)
     {
     	// to do.
     }

     private function writeFlatLog($entry = false)
     {
     	//=============================================================================
		// Function: writeFlatLog
		// Author: Bob Jackman
		// Date: 2008-11-04
		//
		// Description:	Write Log Entry(ies) to a flat file
		//
		// Params:
		// 	None
		//
		// Returns: {bool}	True on Success, false on failure
		//=============================================================================

		//====================  Prepare File Contents
		$string = '';
     	if ($entry === false || is_array($entry)) // -- no entry was passed or entry is an array
	     {
	     	//====================  Convert ALL Memory Log Entries to Strings
	     	if ($entry === false) // -- no entry was passed
	     	{
	     		$entry = $this->_log;
	     	}

	     	$i = 0;
     		foreach ($entry as $e) // -- loop through all passed entries
     		{
     			if (stristr(get_class($e), 'logentry')) // -- this element is a LogEntry Object
     			{
     				if ($i !== 0) // -- this is not the first line
					{
						$string .= "\n";
					}

					$string .= sprintf('%s: %s (%s) - %s [%d]', date('m-d-Y G:i:s T', $e->getTimestamp()), $e->getCategory(), $e->getSubCategory(), $e->getMessage(), $e->getErrorLevel());

					$i++;
				}
     		}
	     }
	     else // -- an entry was passed
	     {
	     	if (is_object($entry) && stristr(get_class($entry), 'logentry')) // -- passed entry was a LogEntry Object
	     	{
	     		$string = "\n".sprintf('%s: %s (%s) - %s [%d]', date('m-d-Y G:i:s T', $entry->getTimestamp()), $entry->getCategory(), $entry->getSubCategory(), $entry->getMessage(), $entry->getErrorLevel());
	     	}
	     	elseif (isset($this->_log[$entry])) // -- passed entry was a valid Log Array Index
	     	{
	     		$entry = $this->_log[$entry];
	     		$string = "\n".sprintf('%s: %s (%s) - %s [%d]', date('m-d-Y G:i:s T', $entry->getTimestamp()), $entry->getCategory(), $entry->getSubCategory(), $entry->getMessage(), $entry->getErrorLevel());
	     	}
	     	else // -- passed entry is not usable
	     	{
	     		return false;
	     	}
	     }

	     if (realpath($this->_logPath) !== false) // -- path is valid
	     {
	     	$path = $this->_logPath;
	     }
	     else // -- path is not valid
	     {
	     	$path = LOGGER_DEFAULT_FLAT_PATH;

	     	if (realpath($path) !== false) // -- default path is valid
	     	{
	     		trigger_error('Configured Logger Path does not exist. Using Default (\''.$path.'\').', E_USER_WARNING);
	     	}
	     	else // -- default path is not valid
	     	{
	     		trigger_error('Configured Logger Path does not exist (\''.$this->_logPath.'\'). Default Path is also invalid (\''.$path.'\').', E_USER_WARNING);
	     	}
	     }

		//====================  Write String(s) to File
		if (realpath($path) !== false) // -- path is valid
		{
			if ($this->_mode == LOGGER_MODE_FLAT) // -- flat file mode
			{
				$append = false;
			}
			else // -- non-flat file mode
			{
				$append = FILE_APPEND;
			}

			//====================  Ouput to File
			file_put_contents($this->_logPath, $string, $append);

			return true;
		}
		else // -- path is invalid
		{
			return false;
		}
     }
}

class LogEntry
{
	//=============================================================================
     // Class: LogEntry
     // Author: Bob Jackman
     // Date: 2008-10-29
     //
     // Description:	Object for holding log data
     //
     // Dependencies:
     //    None
     //=============================================================================

     private $timestamp;		// timestamp at which this object was created
     private $category;		// category of this log entry
     private $subCategory;	// subcategory of this log entry
     private $message;		// log message of this log entry
     private $errorLevel;	// error level of this entry (-1 means unconditionally log this entry)

     public function __construct($message, $category = null, $subCategory = null, $errorLevel = null, $logger = false)
     {
     	//=============================================================================
		// Function: __construct
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Construct the logger module
		//
		// Params:
		// 	$message {string} Required:		Message to add to log
		//	$category {string} Optional:		Category of this entry
		//	$subcategory {string} Optional:	Subcategory of this entry
		//	$errorLevel {int} Optional:		Error Level of this entry (null or -1 means log unconditionally)
		//	$logger {Logger} Optional:		The logger module to which to submit this entry
		//								If passed, this entry is automatically submitted to the logger
		//								If not passed, this entry is created, but it is up to the programmer
		//								to submit it to the logger module.
		//
		// Returns: {LogEntry}
		//=============================================================================

		//====================  Initialize Variables
     	$this->setTimestamp();
     	$this->setMessage($message);

     	if ($errorLevel === null) // -- errorLevel was not passed
     	{
     		$errorLevel = -1;
     	}
     	$this->setErrorLevel($errorLevel);

     	if ($category !== null) // -- category was passed
     	{
     		$this->setCategory($category);
     	}

     	if ($subCategory !== null) // -- subcategory was passed
     	{
     		$this->setSubCategory($subCategory);
     	}

     	//====================  Record Entry
     	if (stristr(get_class($logger), 'logger')) // -- logger object was passed
     	{
     		$logger->addEntry($this);
     	}
     }

	public function __destruct()
	{
		//=============================================================================
		// Function: __destruct
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Desctruct the log entry object
		//
		// Returns: {void}
		//=============================================================================

		//====================  Unset Object Variables
		$properties = get_class_vars(get_class($this));
		foreach ($properties as $property => $value)
		{
			unset($this->$property);
		}
	}

	// --

	public function setCategory($category)
	{
		//=============================================================================
		// Function: setCategory
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description: Set the category of this entry
		//
		// Params:
		// 	$category {string} Required:	The category of this entry
		//
		// Returns: {void}
		//=============================================================================

		//====================  Set Category
		$this->category = $category;
	}

	public function setErrorLevel($level = -1)
	{
		//=============================================================================
		// Function: setErrorLevel
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Set the errorLevel of this entry
		//
		// Params:
		// 	$level {int} Required:	The error level of this entry
		//
		// Returns: {void}
		//=============================================================================

		//====================  Set Error Level
		$this->errorLevel = $level;
	}

	public function setMessage($message)
	{
		//=============================================================================
		// Function: setMessage
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Set the message of this entry
		//
		// Params:
		// 	$message {string} Required:	The message of this entry
		//
		// Returns: {void}
		//=============================================================================

		//====================  Set Message
		$this->message = $message;
	}

	public function setSubCategory($subCategory)
	{
		//=============================================================================
		// Function: setSubCategory
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Set the subcategory of this entry
		//
		// Params:
		// 	$subCategory {string} Required:	The subcategory of this entry
		//
		// Returns: {void}
		//=============================================================================

		//====================  Set Sub-Category
		$this->subCategory = $subCategory;
	}

	public function setTimestamp($timestamp = false)
	{
		//=============================================================================
		// Function: setTimestamp
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Set the timestamp of this entry
		//
		// Params:
		// 	$timestamp {int} Optional:	The timestamp of this entry
		//							If not supplied, the current system time is used
		//
		// Returns: {void}
		//=============================================================================

		//====================  Condition Passed Value
		if ($timestamp === false)
		{
			$timestamp = microtime(true);
		}

		//====================  Set Timestamp
		$this->timestamp = $timestamp;
	}

	public function getCategory()
	{
		//=============================================================================
		// Function: getCategory
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the current category of this entry
		//
		// Params:
		// 	None
		//
		// Returns: {string}
		//=============================================================================

		//====================  Return Category Value
		return $this->category;
	}

	public function getErrorLevel()
	{
		//=============================================================================
		// Function: getErrorLevel
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the current error level of this entry
		//
		// Params:
		// 	None
		//
		// Returns: {int}
		//=============================================================================

		//====================  Return ErrorLevel Value
		return $this->errorLevel;
	}

	public function getMessage()
	{
		//=============================================================================
		// Function: getMessage
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the current message of this entry
		//
		// Params:
		// 	none
		//
		// Returns: {string}
		//=============================================================================

		//====================  Return Message Value
		return $this->message;
	}

	public function getTimestamp()
	{
		//=============================================================================
		// Function: getTimestamp
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the creation timestamp of this entry
		//
		// Params:
		// 	none
		//
		// Returns: {int}
		//=============================================================================

		//====================  Return Timestamp Value
		return $this->timestamp;
	}

	public function getSubCategory()
	{
		//=============================================================================
		// Function: getSubCategory
		// Author: Bob Jackman
		// Date: 2008-10-31
		//
		// Description:	Get the current subcategory of this entry
		//
		// Params:
		// 	None
		//
		// Returns: {string}
		//=============================================================================

		//====================  Get Sub-Category
		return $this->subCategory;
	}
}

?>
Return current item: SvnDashboard