<?php
/**
* class oLogger
* @author : johan <hide@address.com>
* @version : 2006-04-20
*/
class oLogger {
/**
* const sLogDir
* path to the logs
*/
const sLogDir ='logs';
/**
* private array aLogs
* array to store each log line
*/
private $aLogs = array (
'PAGE' => '',
'DATE' => '',
'QUERY' => '',
'TYPE' => ''
);
/**
* private array aLevels
* array to store the query types
*/
private $aLevels = array (
0 => 'UNKNOWN',
1 => 'SELECT',
2 => 'UPDATE',
3 => 'INSERT',
4 => 'DELETE'
);
/**
* public array aDir
* array to store all the log folders and log files
*/
public $aDir = array ();
/**
* private object oXml
* a simple_xml object
*/
private $oXml = null;
/**
* public function __construct
* the constructor
* initailizes the simple_xml object if needed
* @param (string) file : the xml log file from which will be set the simple_xml object property
*/
public function __construct ($file = '') {
if (!empty ($file)) {
$this -> oXml = simplexml_load_file(self::sLogDir.'/'.$file);
}
}
/**
* public function init
* initializes the logger
* gets the sql query, the user id, current date, filename, query type, and builds the aLogs array with all of that
* @param (string) sSql : the sql query we want to log
* @param (int) destId : the user id (depends on your system)
*/
public function init ($sSql, $destId) {
$page = $_SERVER['PHP_SELF'];
$this -> checkDir ($destId);
$date = date ('H:i:s');
$file = date ('Ymd').'.xml';
$sSql = trim (preg_replace ('@(\s)+@', ' ', $sSql));
$aSql = explode (' ', $sSql);
if (false === ($level = array_search ($aSql[0], $this -> aLevels))) {
$level = 0;
}
$this -> aLogs = array (
'PAGE' => $page,
'DATE' => $date,
'QUERY' => $sSql,
'TYPE' => $this -> aLevels[$level]
);
$this -> logIt ($file, $destId);
}
/**
* private function checkDir
* used to check if a log folder exists for a given user id. If not, creates it.
* @param (int) id : the user id
*/
private function checkDir ($id) {
if (!file_exists (self::sLogDir.'/'.$id)) {
mkdir (self::sLogDir.'/'.$id);
}
}
/**
* private function logIt
* build the xml from the aLogs array, and saves it into the given file
* if the given file already exists, it appends the new xml to the existing one
* @param (string) file : the filename in which the xml log will be written
* @param (int) destId : the user id (depends on your system)
*/
private function logIt ($file, $destId) {
if (file_exists (self::sLogDir.'/'.$destId.'/'.$file)) {
$docXml = DOMDocument::load (self::sLogDir.'/'.$destId.'/'.$file);
$root = $docXml -> documentElement;
} else {
$docXml = new DOMDocument('1.0', 'iso-8859-1');
$root = $docXml -> createElement ('logs');
$root = $docXml -> appendChild ($root);
}
$log = $docXml -> createElement ('log');
$log = $root -> appendChild ($log);
foreach ($this -> aLogs as $clef => $val) {
$xmlClef = $docXml -> createElement ($clef);
$xmlClef = $log -> appendChild ($xmlClef);
$xmlVal = $docXml -> createTextNode ($val);
$xmlVal = $xmlClef -> appendChild ($xmlVal);
}
$docXml -> save (self::sLogDir.'/'.$destId.'/'.$file);
$this -> aLogs = array ();
}
/**
* public function getaDir
* builds the aDir array, in which are stored all the log folders and log files
* @param (bool) ordID : if set to true, orders the array by users id ASC
*/
public function getaDir ($ordID = false) {
$aDestLogs = scandir (self::sLogDir);
$aDestLogs = array_splice ($aDestLogs, 2);
if (true === $ordID) {
sort ($aDestLogs, SORT_NUMERIC);
}
if (!empty ($aDestLogs)) {
foreach ($aDestLogs as $v) {
$aFiles = scandir (self::sLogDir.'/'.$v);
$aFiles = array_splice ($aFiles, 2);
$this -> aDir[$v] = $aFiles;
}
} else {
$this -> aDir = array ();
}
}
/**
* public function getList
* builds an array from the oXml simple_xml object with all the values it contains in the $type xml element (the available types are the aLogs array keys)
* used for the logs UI : with this method, I can display only the UPDATE, or the INSERT, or only a given page on the logged website...
* @param (string) type : the type on wihch we want to filter. Must be a valid aLogs key.
*/
public function getList ($type) {
if (!array_key_exists ($type, $this -> aLogs)) {
trigger_error ('Type '.$type.' non reconnu', E_USER_ERROR);
}
$oTypes = $this -> oXml -> xpath ('log/'.$type);
$aType = array_unique ($oTypes);
return $aType;
}
/**
* public function getDetail
* transforms the xml in a log file to html. Could unfortunately not use the XSLTProcessor, because my server did not implement it :-(
* the html can, be changed, of course. The javascript is a javascript function used to get a filter, if needed.
* @param (bool) ord : if set to true, we reverse the xml; as the xml is logged chronologically, we will reverse the dates.
* @param (string) type : if not empty, we filter on that type.
* @param (string) page : if not empty, we filter on that page.
*/
public function getDetail ($ord = false, $type = '', $page = '') {
$sXml = '';
$oLignes = $this -> oXml -> xpath ('log');
if (true === $ord) {
$oLignes = array_reverse ($oLignes);
}
$iCpt = 0;
foreach ($oLignes as $log) {
if (!empty ($type) && $log -> TYPE != $type) {
continue;
}
if (!empty ($page) && $log -> PAGE != $page) {
continue;
}
$sColor = ($iCpt%2) ? 'ct1' : 'ct2';
$sXml .= <<<HTML
<tr>
<td class="$sColor">{$log -> DATE}</td>
<td class="$sColor"><a href="javascript:filtrePage('{$log -> PAGE}');">{$log -> PAGE}</a></td>
<td class="$sColor"><a href="javascript:filtreType('{$log -> TYPE}');">{$log -> TYPE}</a></td>
<td class="$sColor">{$log -> QUERY}</td>
</tr>
HTML;
$iCpt ++;
}
return $sXml;
}
}
?>