<?php
/* Please see the README and LICENSE files. */
/**
* This class intercepts user errors from trigger_error and lower system errors.
* It processes the errors.
*/
class System_Error implements System_Component {
////////////////////////////////////////////////////////////////////////////
// START CONFIGURABLE
////////////////////////////////////////////////////////////////////////////
// Pages
protected static $redirect_404 = "/404.php";
protected static $redirect_403 = "/403.php";
// Output
protected static $enable_client = false; // Show errors to users?
protected static $min_show_client = 16384; // Minmum level to display
protected static $backtrace_client = false;
protected static $show_file_client = true;
protected static $show_context_client = false;
protected static $show_line_client = true;
protected static $short_filename_client = true;
// Logging
protected static $enable_log = false; // Write to log?
protected static $min_show_log = E_USER_WARNING;
protected static $backtrace_log = false;
protected static $show_file_log = true;
protected static $show_context_log = false;
protected static $show_line_log = true;
protected static $short_filename_log = false;
////////////////////////////////////////////////////////////////////////////
// STOP CONFIGURABLE
////////////////////////////////////////////////////////////////////////////
private static $pending_action = 0;
const ACT_REDIRECT = 1;
const ACT_DIE = 2;
const E403 = 32768;
const E404 = 65536;
/**
* @see System_Component
*/
public function start() {
set_error_handler(array($this, "handle_error"));
}
/**
* @see System_Component
*/
public function stop(){} // Cannot stop this train
/**
* Replaces the default error handler. Automagically called by some system errors
* and by trigger_error()
*
* @see set_error_handler()
*/
public static function handle_error($errno, $errstr, $errfile, $errline, $errcontext) {
switch($errstr){
case self::E404:
case self::E403:
self::$pending_action = self::ACT_REDIRECT;
break;
}
$parsed = array_merge(self::parse_error($errno),array(
"message"=>$errstr,
"file"=>$errfile,
"line"=>$errline,
"context"=>$errcontext));
if(self::$enable_log && $errno < self::$min_show_log){
self::log_error($parsed);
}
self::do_pending($errstr);
if(self::$enable_client && $errno < self::$min_show_client){
self::output_error($parsed);
}
}
/**
* Convert an error into an array of attributes
*
* @see Error::handler(...)
* @return String[] The attributes
*/
protected static function parse_error($level) {
switch ($level) {
case E_NOTICE:
case E_USER_NOTICE:
$level = "Notice";
$level_color = "#409CED";
break;
case E_WARNING:
case E_USER_WARNING:
$level = "Warning";
$level_color = "#DB8427";
break;
case E_USER_ERROR:
$level = "Error";
$level_color = "#BF3E28";
break;
case E_STRICT:
$level = "Strict Error";
$level_color = "#BF3E28";
break;
default:
$level = "Unknown";
$level_color = "#F5FC23";
break;
}
return array(
"level"=>$level,
"color"=>$level_color);
}
/**
* Does whatever pending action was discovered during error parsing
*
* @param String $errstr The error string
*/
protected static function do_pending($errstr){
if(self::$pending_action == 0){return false;}
switch(self::$pending_action){
case self::ACT_REDIRECT:
switch($errstr){
case self::E404:
header("Location: ".self::$redirect_404);
break;
case self::E403:
header("Location: ".self::$redirect_403);
break;
}
die();
break;
case self::ACT_DIE:
die();
}
}
/**
* Prints an error message to the current page/buffer
*
* @param String[] $message Array with information to print
*/
protected static function output_error($array) {
if(class_exists("Template_File") && class_exists("Template_FileParser") && class_exists("Template_Parser")){
$file = new Template_File("html/error");
if($file->exists()){
$tfp = new Template_FileParser($file);
$tfp->parse($array);
return;
}
}
echo '<span style="font-size:12px;font-weight:normal;display:inline-block;border:2px solid '.$array['color'].';padding:6px;padding-top:3px;padding-left:10px">';
echo '<span style="color:'.$array['color'].';margin-left:-7px;"> <b>'.$array['level'].'</b> </span> '.
(self::$show_file_client ?
(self::$short_filename_client ?
str_replace(__DIR__,"",$array['file']) :
$array['file']
).(self::$show_line_client ?
" [Line: ".$array['line']."]":
""
)."<br/>":
""
);
echo $array['message']."<br/>";
if(self::$show_context_client){
echo("<pre>Context:");
print_r($array['context']);
echo("</pre>");
}
if(self::$backtrace_client){
echo("<pre>Backtrace:");
print_r(debug_backtrace());
echo("</pre>");
}
echo("</span><br/><br/>");
}
/**
* Writes an error entry in a log file
*
* @param String[] $message Array with information to print
*/
protected static function log_error($message) {
# TODO
# Write to file, need a clean, modular, reusable way to do it
}
}
?>