<?php

/**
 * phpCodeSite - GNU Public Licence
 * http://www.phpedit.net/products/phpCodeSite/
 * 
 * @author Sébastien Hordeaux <marms@phpedit.net> 
 * @author Martin Bialasinski <martin@internet-treff.uni-koeln.de> 
 *
 * @version 1.01
 */

/**
 * @todo Turn it into a global object instead of XX functions.
 * @todo Build a client App which will receive trace infos (=> fsockopen, ... instead of echo).
 */

class PhpCodeSite {
	/**
	 * Indention level
	 * 
	 * @var integer 
	 * @access private 
	 */
	var $Step = 0;

	/**
	 * Debug enabled?
	 * 
	 * @var boolean 
	 * @access private 
	 */
	var $Enabled = true;

	/**
	 * Buffer output?
	 * 
	 * @var boolean 
	 * @access private 
	 */
	var $Buffered = true;
	
	/**
	 * Should the buffer be output with 
	 *
	 */
	var $HtmlOutput = true;

	/**
	 * Buffered output
	 * 
	 * @var boolean 
	 * @access private 
	 */
	var $Output = "";

	/**
	 * Counter for checkpoints
	 * 
	 * @var array 
	 * @access private 
	 */
	var $Checkpoint = array();

	/**
	 * Constructor
	 * 
	 * @access protected 
	 */
	function PhpCodeSite($enable = true, $buffered = true, $html = true){
		$this->Step = 0;
		$this->Enabled = $enable;
		$this->Buffered = $buffered;
	}

	/**
	 * Add a level to the reported items
	 * 
	 * @access private 
	 */
	function IncStep(){
		$this->Step++;
	}

	/**
	 * Remove a level to the reported items
	 * 
	 * @access private 
	 */
	function DecStep(){
		if($this->Step > 0){
			$this->Step--;
		}
	}

	/**
	 * Log an item
	 * 
	 * @access private 
	 */
	function Log($msg){
		for($i = 0; $i < $this->Step; $i++)
		$this->WriteIndent();
		$this->Write($msg);
	}

	/**
	 * Write data to the target output
	 * 
	 * @param string $str String to write
	 * @access private 
	 */
	function Write($str){
		if($this->Enabled){ 
			// Scheint keine Ausgabe zu machen?
			// OutputDebugString($str);
			if ($this->Buffered){
				$this->Output .= $str;
			}else{
				print $str;
			}
		}
	}

	/**
	 * Write an EOL
	 * 
	 * @access private 
	 */
	function WriteEOL(){
		$this->Write("\n");
	}

	/**
	 * Write an indent block
	 * 
	 * @access private 
	 */
	function WriteIndent(){
		$this->Write("|   ");
	}

	/**
	 * Render a variable into the log
	 * param mixed $var Variable to render
	 * 
	 * @access private 
	 */
	function RenderVar($var){
		switch(gettype($var)){
			case "boolean":
				$this->Write($var?"TRUE":"FALSE");
				break;
			case "integer":
			case "double":
				$this->Write($var);
				break;
			case "string":
				$this->Write("\"" . htmlentities($var) . "\"");
				break;
			case "array":
				$this->WriteArray($var);
				break;
			case "object": 
				// $this->WriteEOL();
				// $this->SendObject($var, "");
				$this->Write("Object(" . get_class($var) . ")");
				break;
			case "NULL":
				$this->Write("NULL");
				break;
			default:
				$this->Write("[Unknown type]");
		}
	}

	/**
	 * Write an array into the Log
	 * 
	 * @param array $array Array to write
	 * @access private 
	 */
	function WriteArray($array){
		$this->Write('<span class="debug_array">Array(</span>');
		if(count($array) > 0){
			$this->WriteEOL();
		}
		$this->IncStep();
		while(list($key, $value) = each($array)){
			$this->Log("");
			$this->RenderVar($key);
			$this->Write(" => ");
			$this->RenderVar($value);
			$this->WriteEOL();
		}
		if(count($array) > 0){
			$this->Log('<span class="debug_array">)</span>');
		}else{
			$this->Write(")");
		}
		$this->DecStep();
	}

	/**
	 * Switch between Enabled/Disabled mode
	 * 
	 * @param boolean $state Neuer Status des Loggers
	 * @access public 
	 */
	function SetEnabled($state){
		$this->Enabled = $state;
		$this->Write($this->Enabled ? "<pre>" : "</pre>");
		flush();
	}

	/**
	 * Beginning a new function/method
	 * 
	 * @param string $methodName Name of the function/method
	 * @access public 
	 */
	function EnterMethod($methodName){
		$this->Log('--> '.$methodName);
		$this->WriteEOL();
		$this->IncStep();
	}

	/**
	 * Exit a function/method
	 * 
	 * @param string $methodName Name of the function/method
	 * @access public 
	 */
	function ExitMethod($methodName){
		$this->DecStep();
		$this->Log('<-- '.$methodName);
		$this->WriteEOL();
	}

	/**
	 * Log a note
	 * 
	 * @param string $note Text to write to log
	 * @access public 
	 */
	function SendNote($note){
		$this->Log('[N] '.$note);
		$this->WriteEOL();
	}

	/**
	 * Send a simple message
	 * 
	 * @param string $msg Text to write to log
	 * @access public 
	 */
	function SendMessage($msg){
		$this->Log('[M] '.$msg);
		$this->WriteEOL();
	}

	/**
	 * Log an error
	 * 
	 * @param string $msg Text to write to log
	 * @access public 
	 */
	function SendError($msg){
		$this->Log('[E] '.$msg);
		$this->WriteEOL();
	}

	/**
	 * Log a sql query
	 * 
	 * @param string $query Query to log
	 * @access public 
	 */
	function SendSQL($query){
		$this->Log('[SQL] '.$query);
		$this->WriteEOL();
	}

	/**
	 * Log a variable
	 * 
	 * @param string $value Variable to log
	 * @param string $varName Name of the variable
	 * @access public 
	 */
	function SendVar($value, $varName = ""){
		$this->Log("[L] ");
		if(!empty($varName))
			$this->Write($varName.' = ');
		$this->RenderVar($value);
		$this->WriteEOL();
	}

	/**
	 * Log an object with its properties
	 * 
	 * @param object $object Object to log
	 * @param string $objectName Name of the object
	 * @param boolean $showMethods Log methodnames in object
	 * @access public 
	 */
	function SendObject($object, $objectName = "", $showMethods =
		false){
		$className = get_class($object); 
		// parent class
		$parentCaption = get_parent_class($object);
		if(!empty($parentCaption)){
			$parentCaption = " extends " . $parentCaption;
		}
		$this->Log("|| \$" . $objectName . " = class " . $className . $parentCaption . "{");
		$this->WriteEOL(); 
		// class variables
		$oVars = get_object_vars($object);
		if(is_array($oVars)){
			while(list($varName, $varValue) = each($oVars)){
				$this->Log("||   var \$$varName = ");
				$this->RenderVar($varValue);
				$this->Write(";");
				$this->WriteEOL();
			}
		} 
		// class method
		if($showMethods){
			$oMethods = get_class_methods($className);
			if(is_array($oMethods))
				while(list(, $method) = each($oMethods)){
				$this->Log("||   function $method(){}");
				$this->WriteEOL();
			}
		}else{
			$this->Log("||   [Methods Skipped]");
			$this->WriteEOL();
		}

		$this->Log("|| }");
		$this->WriteEOL();
	}

	/**
	 * Write seperator line
	 * 
	 * @access public 
	 */
	function AddSeparator(){
		$this->Write("----------------------------------------------------------");
		$this->WriteEOL();
	}

	/**
	 * Write an checkpoint to the log
	 * Ex:
	 *               $debug->Checkpoint(__FILE__, __LINE__); or
	 * $debug->Checkpoint();
	 * 
	 * @param string $file Name of file
	 * @param integer $line Linenumber
	 * @access public 
	 */
	function Checkpoint($file = "", $line = 0){
		if(empty($file)){
			$ID = "";
		}else{
			$ID = " [$file - $line]";
		} 
		// Count reaching the checkpoint
		if(!isset($this->Checkpoint[$ID])){
			$this->Checkpoint[$ID] = 0;
		}
		$this->Checkpoint[$ID]++;
		$this->Log("[C] Checkpoint$ID (" . $this->Checkpoint[$ID] . ")");
		$this->WriteEOL();
	}

	/**
	 * Log all global variables
	 * 
	 * @access public 
	 */
	function DisplayInputData(){
		global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS,
		$HTTP_SERVER_VARS, $HTTP_ENV_VARS, $HTTP_SESSION_VARS;
		$this->AddSeparator();
		$this->SendVar($_GET, "_GET");
		$this->SendVar($_POST, "_POST");
		$this->SendVar($_COOKIE, "_COOKIE");
		if (isset($_SESSION)){
			$this->SendVar($_SESSION, "_SESSION");
		} 
		// Uncomment if you want to see all...
		// $this->SendVar($HTTP_SERVER_VARS, "HTTP_SERVER_VARS");
		// $this->SendVar($HTTP_ENV_VARS, "HTTP_ENV_VARS");
		// $this->SendVar($GLOBALS, "GLOBALS");
		$this->AddSeparator();
	}
	
	/** 
	 * Flushes the output buffer
	 *
	 * @access public
	 */
	function FlushBuffer()
	{
		$this->Output = "";
	}

	/**
	 * Print the content of the output buffer
	 * 
	 * @access public 
	 * @return void 
	 */
	function PrintBuffer(){
		if ($this->Output != ""){
			print "<pre>\n" . $this->Output . "\n</pre>\n";
		}
	}

	/**
	 * Return the content of the output buffer
	 * 
	 * @access public 
	 * @return void 
	 */
	function GetBuffer(){
		if ($this->Output != ""){
			return "<pre>\n" . $this->Output . "\n</pre>\n";
		}else{
			return "";
		}
	}
}

?>
