Location: PHPKode > projects > Pygalle > admin/log.php
<?php
/**
 * @package		Pygalle
 * @copyright	Copyright (C) 2008 Erik Finnegan. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * @author 		hide@address.com
 * Joomla! and Pygalle EVE Corporate Intranet are free software.
 * This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

jimport('joomla.error.log');

define( '_PY_LEVEL_TRACE', 4);
define( '_PY_LEVEL_DEBUG', 3);
define( '_PY_LEVEL_INFO', 3);
define( '_PY_LEVEL_WARN', 2);
define( '_PY_LEVEL_ERROR', 1);

class PyLog extends JLog {

	function & getInstance( $logLevel=null, $logFilename="pygalle_debug.log") {
		static $instances;

		$config =& JFactory::getConfig();
		$path = $config->getValue('config.log_path');
		jimport('joomla.filesystem.path');
		$path = JPath :: clean($path . DS . $logFilename);
		$sig = md5($path);

		if (!isset ($instances)) {
			$instances = array ();
		}
		
		if ( $logLevel === null) {
			$params = JComponentHelper::getParams( 'com_pygalle');
			if ( $params) {
				$logLevel = $params->get( 'log_level', _PY_LEVEL_TRACE);
				$logLevel = min( _PY_LEVEL_TRACE, max( _PY_LEVEL_ERROR, $logLevel));
			} else {
				$logLevel = _PY_LEVEL_TRACE;
			}
		}
		
		if (empty ($instances[$sig])) {
			$instances[$sig] = new PyLog($path, array( '_level' => $logLevel));
		}

		return $instances[$sig];
	}

	function setOptions( $options) {
		if (parent::setOptions( $options)) {
			//FIXME remove 'format' value from array
		}
		$this->setProperties( $options);
	}

	private function log( $level) {
		if ($level <= $this->_level) {

			$args = @func_get_args();
			// throw away the $level argument
			$args = array_slice( $args, 1);
			$args = $args[0];
			if ( count($args) == 0) {
				$args[] = 'touch';
			}
			
			// make a prefix of either calling class->method name or executing file and the previous call
			$prefix = '';
			$stack = debug_backtrace();
			if ( isset($stack[2]['class'])) {
				$prefix = $stack[2]['class'].$stack[2]['type'].$stack[2]['function']; 
			} else {
				$currentFile = $stack[1]['file'];
				$pathDelimeter = strrpos( $currentFile, DS);
				if ( !$pathDelimeter) $pathDelimeter = -1;
				$prefix .= substr( $currentFile, $pathDelimeter + 1);
				// retrieve calling object/file from stack trace
				$stackDepth = count( $stack);
				$i = 3;
				// iterate through stack until object found
				do {
					$lastCall = $stack[$i];
					$i++;
				} while ( empty( $lastCall['class']) && $i < $stackDepth);
				$class = $lastCall['class'];
				$prefix .= " (";
				$prefix .= ($class.$lastCall['type'].$lastCall['function']);
				$prefix .= ')'; 
			}
			// trunkate and pad prefix to 55 chars
			$prefix = substr( str_pad( $prefix, 40, ' ', STR_PAD_LEFT), 0, 55 );
			
			// create output for log arguments
			foreach( $args as $output) {
				$message = $prefix."\t".$this->printRecursive($output);
				$this->addEntry( array( 'level' => $level, 'comment' => $message));
			}
		}

	}

	/**
	 * Log all parameters with priority _PY_LEVEL_TRACE
	 *
	 * @param mixed arg List of arguments
	 */
	function trace() {
		$args = func_get_args();
		$this->log( _PY_LEVEL_TRACE, $args);
	}

	/**
	 * Log all parameters with priority _PY_LEVEL_DEBUG
	 *
	 * @param mixed arg List of arguments
	 */
	function debug() {
		$args = func_get_args();
		$this->log( _PY_LEVEL_DEBUG, $args);
	}

	/**
	 * Log all parameters with priority _PY_LEVEL_ERROR
	 *
	 * @param mixed arg List of arguments
	 */
	function error() {
		$args = func_get_args();
		$this->log( _PY_LEVEL_ERROR, $args);
	}

	/**
	 * Log all parameters with priority _PY_LEVEL_INFO
	 *
	 * @param mixed arg List of arguments
	 */
	function info() {
		$args = func_get_args();
		$this->log( _PY_LEVEL_INFO, $args);
	}

	function is_tracing () {
		return $this->_level == _PY_LEVEL_TRACE;
	}

	/**
	 * Creates a string representation of the object given.
	 * Depth should not be specified when calling the function. It is used internally to
	 * end recursion.
	 *
	 * @param object $object
	 * @param int $depth
	 * @return String
	 * @static
	 */
	static function printRecursive( $object, $depth=4) {
		// ripcord
		if ( !$depth) return gettype( $object);
		
		$returnVal = '';
		if ( $object instanceof JDatabase || $object instanceof JDatabaseMySQL) {
			$returnVal = "Current database state... \n"."last query: ".$object->getQuery()."\nresult rows: ".@$object->getNumRows()."\nError (if any): ".$object->getErrorMsg();
		
		} else if ( $object instanceof RuntimeException || $object instanceof JException) {
			$returnVal = '('.$object->getCode().') '.$object->getMessage();
		
		} else if ( $object instanceof JDate) {
			$returnVal = " <JDate> [" . $object->toMySQL() . ", " . $object->toUnix() . "]";
			
		} else if ( is_object( $object)) {
			$returnVal = " <" . get_class( $object) . "> [\n";
			foreach ( $vars = get_object_vars( $object) as $k => $v) {
				$returnVal .= $k . ' => '.PyLog::printRecursive($v, $depth - 1)."\n";
			}
			$returnVal .= "]";
			$returnVal .= "\n" ;
		} else if ( is_array( $object)) {
			$returnVal .= " <Array> {\n";
			foreach ( $object as $k => $v) {
				$returnVal .= $k . ' => '.PyLog::printRecursive($v, $depth - 1)."\n";
			}
			$returnVal .= "}";
			$returnVal .= "\n";
		} else if ( $object === false) {
			$returnVal = 'false';
		} else if ( $object === true) {
			$returnVal = 'true';
		} else if ( $object === null) {
			$returnVal = 'null';
		} else {
			$returnVal = $object;
		}
		return $returnVal;
	}

	function outputIsComplex( $output) {
		return is_object( $output) || is_array( $output) || is_a( $output, 'JDatabase');
	}
	
	function printStackTrace() {

		$this->trace( $this->_buildStackTrace());
	}
	
	private static function _buildStackTrace() {
		
		$stack = debug_backtrace();
		$output = '';
		for ( $i = 1; $i < 10 && $stack[$i] != null; $i++) {
			$lastCall = $stack[$i];

			$class = $lastCall['class'];
			if ( $class) {
				$prefix = $class.$lastCall['type'].$lastCall['function']; 
			} else {
				$pathDelimeter = strrpos( $lastCall['file'], DS);
				if ( !$pathDelimeter) $pathDelimeter = -1;
				$prefix = substr( $lastCall['file'], $pathDelimeter + 1);
			}
			$output .= $prefix;
			$output .= PyLog::printRecursive( $lastCall, 2);
			$output .= "\n";
		}
		return $output;
	}
}
Return current item: Pygalle