PHP Classes
Icontem

File: class/odebugger.cls.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Johan Barbier  >  PHP Debugger and Helper  >  class/odebugger.cls.php  
File: class/odebugger.cls.php
Role: Class source
Content type: text/plain
Description: Debugger class
Class: PHP Debugger and Helper
Log errors and check PHP code
 

Contents

Class file image Download
<?php
/**
* CLASS odebugger
*
* @author : johan <barbier_johan@hotmail.com>
*/
class odebugger {

	/**
	* private (string) sAssertion
	* Check if error comes from an essertion or not, if yes, will conatin the filename of the evaluated script
	*/
	private $sAssertion = null;
	/**
	* private (string) sLang
	* localization string
	*/
	private $sLang = 'EN';

	/**
	* private (int) iNbLines
	* Number of lines displayed before and after the line of the error
	*/
	private $iNbLines = 2;

	/**
	* private (array) aOptions
	* Options array
	*/
	private $aOptions = array (
		'REALTIME' => true,
		'LOG_FILE' => true,
		'ERROR' => true,
		'EXCEPTION' => true
		);

	/**
	* private (string) sTemplateHTML
	* HTML template file for the realtime log
	*/
	private $sTemplateHTML = 'default';
	/**
	* private (string) sTemplateCSS
	* CSS template file for the realtime log
	*/
	private $sTemplateCSS = 'default';
	/**
	* private (string) sTemplateHTMLLOG
	* HTML template file for the whole log file
	*/
	private $sTemplateHTMLLOG = 'default_log';
	/**
	* private (string) sTemplateCSSLOG
	* CSS template file for the whole log file
	*/
	private $sTemplateCSSLOG = 'default_log';

	/**
	* private (string) sCurDir
	* Current directory of the script
	*/
	private $sCurDir = '';

	/**
	* private (string) sCurId
	* Current file unique id
	*/
	private $sCurId = '';

	/**
	* private (object) oXMLDOC
	* XML LOG Object (DOMDocument object)
	*/
	private $oXMLDOC = null;
	/**
	* private (object) oXMLROOT
	* XML LOG root Object (DOMDocument object)
	*/
	private $oXMLROOT = null;
	/**
	* private (object) oCurrentNode
	* Current node Object (DOMDocument object)
	*/
	private $oCurrentNode = null;

	/**
	* private (array) aCanBeSet
	* class properties that can be set via odebugger::__set()
	*/
	private $aCanBeSet = array (
		'LINES' => 'iNbLines',
		'REALTIME' => "aOptions['REALTIME']",
		'LOGFILE' => "aOptions['LOG_FILE']",
		'HTML' => 'sTemplateHTML',
		'CSS' => 'sTemplateCSS',
		'HTMLLOG' => 'sTemplateHTMLLOG',
		'CSSLOG' => 'sTemplateCSSLOG',
		'ERROR' => "aOptions['ERROR']",
		'EXCEPTION' => "aOptions['EXCEPTION']"
		);

	/**
	* private (object) oXMLTYPES
	* XML DOMDocument object with the list of error types and their translation
	*/
	private $oXMLTYPES = null;

	/**
	* private (object) oXMLERRORS
	* XML DOMDocument object with the list of errors and their translation
	*/
	private $oXMLERRORS = null;

	/**
	* private (array) aIndex
	* replacement array for the templates
	*/
	private $aIndex = array (
		0 => array (
			'{DATE_TITRE}',
			'{DATE_VALUE}'
			),
		1 => array (
			'{TYPE_TITRE}',
			'{TYPE_VALUE}'
			),
		2 => array (
			'{MSG_TITRE}',
			'{MSG_VALUE}'
			),
		3 => array (
			'{FILE_TITRE}',
			'{FILE_VALUE}'
			),
		4 => array (
			'{LINE_TITRE}',
			'{LINE_VALUE}'
			),
		5 => array (
			'{MEM_TITRE}',
			'{MEM_VALUE}'
			),
		6 => array (
			'{TRANS_TITRE}',
			'{TRANS_VALUE}'
			),
		7 => array (
			'{SUGG_TITRE}',
			'{SUGG_VALUE}'
			),
		8 => array (
			'{CONTEXT_TITRE}',
			'{CONTEXT_VALUE}'
			),
		9 => array (
			'{SOURCE_TITRE}',
			'{SOURCE_VALUE}'
			),
		100 => '{TOTAL_STATS}',
		101 => '{PHP_VERSION}'
		);

	/**
	* public function __construct ()
	* contsructor
	* sets the error_reporting to 0
	* gets the localization dir
	* import all the xml files
	* set the error handler
	* @Param (string) sLang : the localization used
	*/
	public function __construct ($sLang = 'EN') {
		@error_reporting (0);

		$aLnDir = scandir ('xml');
		if (in_array ($sLang, $aLnDir)) {
			$this -> sLang = $sLang;
		}
		$this -> oXMLERRORS = DOMDocument::load ('xml/'.$this -> sLang.'/errors.xml');
		$this -> oXMLTYPES = DOMDocument::load ('xml/'.$this -> sLang.'/types.xml');

		$this -> oXMLDOC = new DOMDocument ('1.0', 'utf-8');
		$root = $this -> oXMLDOC -> createElement ('ERRORLOG');
		$this -> oXMLROOT = $this -> oXMLDOC -> appendChild ($root);
		if (!is_dir ('logs')) {
			@mkdir ('logs', 0744);
		}
		$sTemp = dirname (__FILE__);
		$aTemp = explode ('\\', $sTemp);
		array_pop ($aTemp);
		$this -> sCurDir = implode ('/', $aTemp).'/';
		$this -> sCurId = date ('Ymd').'_'.uniqid();

		set_error_handler (array ($this, 'myErrorHandler'));
		set_exception_handler (array ($this, 'myExceptionHandler'));
	}

	/**
	* public function checkCode ()
	* use the assert () function to get the errors in a given string, or a given file
	* @Param (string) sString : the string with the PHP code to evaluate, or the file to evaluate. Usually, it will come from a file via file_get_contents () for example
	* @Return : false if given parameter is not a string.
	*/
	public function checkCode ($sCode) {
		if (file_exists ($sCode)) {
			$sString = file_get_contents ($sCode);
			$this -> sAssertion = $sCode;
		} elseif (!is_string ($sCode)) {
			return false;
		} else {
			$sString = $sCode;
		}
		$sString = str_replace (array ('<?php', '<?', '?>'), '', $sString);
		assert_options(ASSERT_ACTIVE, 1);
		assert_options(ASSERT_WARNING, 0);
		assert_options(ASSERT_QUIET_EVAL, 1);
		//assert_options (ASSERT_CALLBACK, array ($this, 'myAssertHandler')); Waiting a bit to improve this part
		assert ($sString);
		assert_options(ASSERT_ACTIVE, 0);
	}

	/**
	* public function myAssertHandler ()
	* activate the assertion. Right now, does nothing...and is not used.
	* @Param (string) file : the file from which comes the code
	* @Param (int) line : the error line
	* @Param (string) code : the error code
	* @Return : true
	*/
	public function myAssertHandler ($file, $line, $code){
		return true;
	}

	/**
	* private function checkErrorMessage ()
	* try to find the correct trsnalation and suggestion from a given error message
	* @Param (string) sMsg : the PHP error message
	* @Return (array) aTempArr : array with the translation and the suggestion found
	*/
	private function checkErrorMessage ($sMsg) {
		$iLength = strlen ($sMsg);
		$xpath = new DOMXPath($this -> oXMLERRORS);
		$sQueryLabel = '//error/label';
		$oLabelLists = $xpath -> query ($sQueryLabel);
		$aMsg = explode (' ', $sMsg);
		foreach ($oLabelLists as $oLabel) {
			$aLabel = explode (' ', $oLabel -> nodeValue);
			$aDiff = array_diff ($aLabel, $aMsg);
			if (empty ($aDiff)) {
				$aTempArr['TRANSLATION'] = $oLabel -> nextSibling -> nextSibling -> nodeValue;
				$aTempArr['SUGGESTION'] = $oLabel -> nextSibling -> nextSibling -> nextSibling -> nextSibling -> nodeValue;
				return $aTempArr;
			}
		}
	}

	/**
	* private function checkTypeTrans ()
	* try to find the error type translation
	* @Param (int) cErrno : the PHP constant error type code
	* @Return (string) nodeValue : the translated error type
	*/
	private function checkTypeTrans ($cErrno) {
		$xpath = new DOMXPath($this -> oXMLTYPES);
		$sQueryLevel = '//type/level';
		$oLevelList = $xpath -> query ($sQueryLevel);
		foreach ($oLevelList as $oLevel) {
			if (constant ($oLevel -> nodeValue) === $cErrno) {
				return $oLevel -> nextSibling -> nextSibling -> nodeValue;
			}
		}
	}

	/**
	* public function myExceptionHandler ()
	* the exception handler : builds the XML error log
	* @Param (object) e : the Exception object
	*/
	public function myExceptionHandler ($e) {
		$sErrStr = $e -> getMessage ();
		$iErrLine = $e -> getLine ();
		$sType = 'Exception '.$e -> getCode ();
		if (is_null ($this -> sAssertion)) {
			$sErrFile = $e -> getFile ();
		} else {
			$sErrFile = $this -> sAssertion;
			$this -> sAssertion = null;
		}
		$sVars = $e -> getTraceAsString ();
		$aTempArr = array ('TRANSLATION' => '', 'SUGGESTION' => '');

		$this -> buildLog ($sType, $sErrStr, $sErrFile, $iErrLine, $aTempArr, $sVars);
	}

	/**
	* public function myErrorHandler ()
	* the error handler : builds the XML error log
	* @Param (int) cErrno : the PHP constant error type code
	* @Param (string) sErrStr : the PHP error message
	* @Param (string) sErrFile : the file in which the error has been detected
	* @Param (int) iErrLine : the line of the error
	* @Param (array) mVars : the context
	*/
	public function myErrorHandler ($cErrno, $sErrStr, $sErrFile, $iErrLine, $mVars) {
		$aTempArr = $this -> checkErrorMessage ($sErrStr);
		$sType = $this -> checkTypeTrans ($cErrno);
		$sVars = 'n/a';
		if (!is_null ($this -> sAssertion)) {
			$sErrFile = $this -> sAssertion;
			$this -> sAssertion = null;
		}
		$this -> buildLog ($sType, $sErrStr, $sErrFile, $iErrLine, $aTempArr, $sVars);
	}

	/**
	* private function buildLog ()
	* the error handler : builds the XML error log
	* @Param (string) sType : The type of error/exception
	* @Param (string) sErrStr : the PHP error message
	* @Param (string) sErrFile : the file in which the error has been detected
	* @Param (int) iErrLine : the line of the error
	* @Param (string) sVars : the context
	*/
	private function buildLog ($sType, $sErrStr, $sErrFile, $iErrLine, $aTempArr, $sVars) {
		$iErrLine --;
		if ($iErrLine < 0) {
			$iErrLine = 0;
		}
		$oNewLog = $this -> oXMLDOC -> createElement ('ERROR');
		$dump = $this -> oXMLROOT -> getElementsByTagName('ERROR');
		$iNewId = $dump -> length + 1;
		$oNewLog = $this -> oXMLROOT -> appendChild ($oNewLog);
		$oNewLog -> setAttribute ('xml:id', '_'.$iNewId);

		$aElem[] = $this -> oXMLDOC -> createElement ('DATE', date ('d-m-Y H:i:s'));
		$aElem[] = $this -> oXMLDOC -> createElement ('TYPE', $sType);
		$sErrStr = utf8_encode ($sErrStr);
		$aElem[] = $this -> oXMLDOC -> createElement ('PHP_MESSAGE', $sErrStr);
		$aElem[] = $this -> oXMLDOC -> createElement ('FILE', $sErrFile);
		$aElem[] = $this -> oXMLDOC -> createElement ('LINE', $iErrLine);
		if (function_exists ('memory_get_usage')) {
			$iMemory = @memory_get_usage ();
		} else {
			$iMemory = 'n/a';
		}
		$aElem[] = $this -> oXMLDOC -> createElement ('MEMORY', $iMemory);
		$aElem[] = $this -> oXMLDOC -> createElement ('TRANSLATION', $aTempArr['TRANSLATION']);
		$aElem[] = $this -> oXMLDOC -> createElement ('SUGGESTION', $aTempArr['SUGGESTION']);

		$aElem[] = $this -> oXMLDOC -> createElement ('CONTEXT', $sVars);
		$oSource = $this -> oXMLDOC -> createElement ('SOURCE');
		$aSourceElem = array ();
		foreach ($this -> getLine ($sErrFile, $iErrLine) as $iLine => $sLine) {
			$sLine = utf8_encode ($sLine);
			if ($iLine === ($iErrLine)) {
				$aSourceElem[] = $this -> oXMLDOC -> createElement ('SOURCE_LINE_ERROR', ' /** ERROR AROUND THIS LINE => */ '.$sLine);
			} else {
				$aSourceElem[] = $this -> oXMLDOC -> createElement ('SOURCE_LINE', $sLine);
			}
		}
		foreach ($aSourceElem as $oSourceElem) {
			$oSource -> appendChild ($oSourceElem);
		}
		foreach ($aElem as $oElem) {
			$oNewLog -> appendChild ($oElem);
		}
		$oNewLog -> appendChild ($oSource);
		$this -> oCurrentNode = $oNewLog;
		if (true === $this -> aOptions['REALTIME']) {
			$this -> printMe ();
		}
	}
	/**
	* private function getLine ()
	* method to get the lines around the detected error
	* @Param (string) sErrFile : the file in which the error has been detected
	* @Param (int) iErrLine : the line of the error
	* @Return (array) aSource : array with each line
	*/
	private function getLine ($sErrFile, $iErrLine) {
		$aSource = array ();
		if (file_exists ($sErrFile)) {
			$aLines = file ($sErrFile);
			for ($i = $iErrLine - $this -> iNbLines; $i<= $iErrLine + $this -> iNbLines; $i ++) {
				if (isset ($aLines[$i])) {
					$aSource[$i] = $aLines[$i];
				}
			}
		}
		return $aSource;
	}

	/**
	* public function loadXML ()
	* loads an external error log
	* @Param (string) sFile : the error log file to be loaded
	*/
	public function loadXML ($sFile) {
		if (!file_exists ('logs/'.$sFile)) {
			return false;
		}
		$this -> oXMLDOC -> load ('logs/'.$sFile);
	}

	/**
	* public function showAll ()
	* show the whole current xml log
	*/
	public function showAll () {
		$xpath = new DOMXPath($this -> oXMLDOC);
		$sQuery = '//ERROR';
		$oNodeLists = $xpath -> query ($sQuery);
		foreach ($oNodeLists as $oNodeList) {
			$this -> oCurrentNode = $oNodeList;
			$this -> printMe ();
		}
	}

	/**
	* public function showLog ()
	* show the whole current log in a table, with stats (best used after odebugger::loadXML())
	* @Return (string) sHtml : the generated HTML
	*/
	public function showLog () {
		$sBaseHtml = file_get_contents ('templates/'.$this -> sTemplateHTMLLOG.'.dat');
		$iStartPos = strpos ($sBaseHtml, '<!-- LINES HERE -->');
		$sHtml = substr ($sBaseHtml, 0, $iStartPos);
		$iEndPos = strpos ($sBaseHtml, '<!-- STATS -->');
		$iLength = strlen ($sBaseHtml);
		$sTempHtml = substr ($sBaseHtml, $iStartPos,   - ($iLength - $iEndPos));
		$sTempHtmlTotal = '';
		$xpath = new DOMXPath($this -> oXMLDOC);
		$sQuery = '//ERROR';
		$oNodeLists = $xpath -> query ($sQuery);
		foreach ($oNodeLists as $oNodeList) {
			$this -> oCurrentNode = $oNodeList;
			$sTempHtmlTotal .= $this -> printMeLog ($sTempHtml);
		}
		$sHtml .= $sTempHtmlTotal;
		$sQuery = '//ERROR/TYPE';
		$oNodeLists = $xpath -> query ($sQuery);
		foreach ($oNodeLists as $oNodeList) {
			$aTypes[] = $oNodeList  -> nodeValue;
		}
		$sHtml .= substr ($sBaseHtml, $iEndPos, ($iLength - 1));
		$aCountType = array_count_values ($aTypes);
		$sCountType = '';
		foreach ($aCountType as $kType => $vType) {
			$sCountType .= $kType.' : '.$vType.'<br />';
		}
		$sVersion = @phpversion ();
		$sHtml = str_replace ($this -> aIndex[100], $sCountType, $sHtml);
		$sHtml = str_replace ($this -> aIndex[101], $sVersion , $sHtml);
		return $sHtml;
	}

	/**
	* private function printMe ()
	* display a caught error
	* @Return (string) sHtml : the generated HTML
	*/
	private function printMe () {
		$sHtml = file_get_contents ('templates/'.$this -> sTemplateHTML.'.dat');
		$nodeList = $this -> oCurrentNode -> childNodes;
		$iId = $this -> oCurrentNode -> getAttribute ('id');
		for ($i = 0; $i < $nodeList -> length; $i++) {
			$sName = $nodeList -> item($i) -> nodeName;
			if ($sName === 'SOURCE') {
				$sourceNodeList = $nodeList -> item($i) -> childNodes;
				$sValeur = '';
				for ($j = 0; $j < $sourceNodeList -> length; $j++) {
					$sValeur .= str_replace (array ('<?php', '?>', '<?'), '', $sourceNodeList -> item($j) -> nodeValue);
				}
				$sValeur = highlight_string ('<?php '."\r\n".$sValeur.'?>', true);
			} else {
				$sValeur = $nodeList -> item($i) -> nodeValue;
			}
			$sId = uniqid().'_'.$iId;
			$aReplacement = array ($sName, $sValeur);
			$sHtml = str_replace ($this -> aIndex[$i], $aReplacement, $sHtml);
			$sHtml = str_replace ('{ID}', $sId, $sHtml);
		}
		echo $sHtml;
	}

	/**
	* private function printMeLog ()
	* display a caught error, used by odebugger::showLog()
	* @Return (string) sHtml : the generated HTML
	*/
	private function printMeLog ($sHtml) {
		$nodeList = $this -> oCurrentNode -> childNodes;
		for ($i = 0; $i < $nodeList -> length; $i++) {
			if ($nodeList -> item($i) -> nodeName === 'SOURCE') {
				$sourceNodeList = $nodeList -> item($i) -> childNodes;
				$sValeur = '';
				for ($j = 0; $j < $sourceNodeList -> length; $j++) {
					$sValeur .= str_replace (array ('<?php', '?>', '<?'), '', $sourceNodeList -> item($j) -> nodeValue);
				}
				$sValeur = highlight_string ('<?php '."\r\n".$sValeur.'?>', true);
			} else {
				$sValeur = $nodeList -> item($i) -> nodeValue;
			}
			$sHtml = str_replace ($this -> aIndex[$i][1], $sValeur, $sHtml);
		}
		return $sHtml;
	}

	/**
	* public function saveToFile ()
	* save the current log to a given file
	* @Param (string) sFile : name of the log file
	*/
	public function saveToFile ($sFile = null) {
		if ($sFile === null) {
			$sFile = $this -> sCurId.'_error_log.xml';
		}
		$this -> oXMLDOC -> save ($this -> sCurDir.'logs/'.$sFile);
	}

	/**
	* public function __destruct ()
	* destructor
	* will save the log to a file if the LOG_FILE option is set to true
	*/
	public function __destruct () {
		if (true === $this -> aOptions['LOG_FILE']) {
			$this -> saveToFile ();
		}
	}

	/**
	* public function __set ()
	* allows some properties to be set
	* @Param (string) sProp : name of the property
	* @Param (mixed) mVal : the value to be given to the property
	* @Return (boolean) false if failed, true if succeeded
	*/
	public function __set ($sProp, $mVal) {
		if (false === array_key_exists ($sProp, $this -> aCanBeSet)) {
			return false;
		}
		switch ($sProp) {
			case 'LINES' :
				if (!is_int ($mVal)) {
					return false;
				}
				$this -> iNbLines = $mVal;
				return true;
				break;
			case 'HTML' :
				if (!file_exists ('templates/'.$mVal.'.dat')) {
					return false;
				}
				$this -> sTemplateHTML = $mVal;
				return true;
				break;
			case 'HTMLLOG' :
				if (!file_exists ('templates/'.$mVal.'.dat')) {
					return false;
				}
				$this -> sTemplateHTMLLOG = $mVal;
				return true;
				break;
			case 'CSS' :
				if (!file_exists ('css/'.$mVal.'.dat')) {
					return false;
				}
				$this -> sTemplateCSS = $mVal;
				readfile ('css/'.$mVal.'.dat');
				return true;
				break;
			case 'CSSLOG' :
				if (!file_exists ('css/'.$mVal.'.dat')) {
					return false;
				}
				$this -> sTemplateCSSLOG = $mVal;
				readfile ('css/'.$mVal.'.dat');
				return true;
				break;
			case 'REALTIME' :
				if (!is_bool ($mVal)) {
					return false;
				}
				$this -> aOptions['REALTIME'] = $mVal;
				return true;
				break;
			case 'LOGFILE' :
				if (!is_bool ($mVal)) {
					return false;
				}
				$this -> aOptions['LOG_FILE'] = $mVal;
				return true;
				break;
			case 'ERROR' :
				if (!is_bool ($mVal)) {
					return false;
				}
				$this -> aOptions['ERROR'] = $mVal;
				if (true === $mVal) {
					set_error_handler (array ($this, 'myErrorHandler'));
				} else {
					restore_error_handler ();
				}
				return true;
				break;
			case 'EXCEPTION' :
				if (!is_bool ($mVal)) {
					return false;
				}
				$this -> aOptions['EXCEPTION'] = $mVal;
				if (true === $mVal) {
					set_exception_handler (array ($this, 'myExceptionHandler'));
				} else {
					restore_exception_handler ();
				}
				return true;
				break;
			default:
				return false;
		}
	}

	/**
	* public function __get ()
	* allows some properties to be get
	* @Param (string) sProp : name of the property
	* @Return (boolean) false if failed, value of the property if succeeded
	*/
	public function __get ($sProp) {
		if (false === array_key_exists ($sProp, $this -> aCanBeSet)) {
			return false;
		}
		$sRealProp = $this -> aCanBeSet[$sProp];
		return $this -> $sRealProp;
	}
}
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products