<?php
namespace Fury\Modules\ErrorHandler;
/**
* Class: ErrorHandler
* @author Eugene Sukhodolskiy <eugene.sukhodolskiy@gmail.com>
* @version 0.1
* Date: 19.07.2022
*/
class ErrorHandler{
/**
* With all errs in source view
*/
private Array $errs_src;
/**
* What errors need to be displayed and logined
*/
private Array $important_errors;
public function __construct(){
$this -> important_errors = FCONF["error_handler"]["important_errors"];
if(!FCONF["debug"]){
error_reporting(-1);
}else{
error_reporting(0);
}
$this -> set_err_handler();
}
/**
* Set custom error handler
*/
public function set_err_handler(){
set_error_handler([$this, "error_handler"], E_ALL);
register_shutdown_function([$this, "fatal_error_handler"]);
// set_exception_handler([$this, "exception_handler"]);
}
// FIXME
public function exception_handler(\Exception $e) {
$this -> error_handler(
$e -> getCode(),
$e -> getMessage(),
$e -> getFile(),
$e -> getLine()
);
}
/**
* Set custom FATAL error handler
*/
public function fatal_error_handler(){
$error = error_get_last();
if ($error){
$this -> view_fatal_error($error["type"], $error["message"], $error["file"], $error["line"]);
}
}
/**
* Handle of error
*/
public function error_handler(Int $errno, String $errstr, String $errfile, Int $errline){
$err_type = $this -> get_err_type($errno);
if(!$this -> error_is_important($err_type)){
return true;
}
$this -> view_fatal_error($errno, $errstr, $errfile, $errline);
return true;
}
/**
* Get type of error
*/
private function get_err_type(Int $errno){
$errors = array(
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
E_PARSE => "E_PARSE",
E_NOTICE => "E_NOTICE",
E_CORE_ERROR => "E_CORE_ERROR",
E_CORE_WARNING => "E_CORE_WARNING",
E_COMPILE_ERROR => "E_COMPILE_ERROR",
E_COMPILE_WARNING => "E_COMPILE_WARNING",
E_USER_ERROR => "E_USER_ERROR",
E_USER_WARNING => "E_USER_WARNING",
E_USER_NOTICE => "E_USER_NOTICE",
E_STRICT => "E_STRICT",
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
E_DEPRECATED => "E_DEPRECATED",
E_USER_DEPRECATED => "E_USER_DEPRECATED",
);
return isset($errors[$errno]) ? $errors[$errno] : "EXCEPTION";
}
/**
* Get lines with errors from file
*/
public function get_prog_code(String $errfile, Int $errline) {
$file = explode("\n", file_get_contents($errfile));
$code = [];
for($i = $errline - 8; $i < $errline + 6; $i++){
if(!isset($file[$i])) continue;
if(trim($file[$i]) == "") continue;
$code[$i + 1] = str_replace("\t", " ", htmlspecialchars($file[$i]));
}
return $code;
}
protected function error_is_important(String $errtype){
foreach($this -> important_errors as $important_error){
if($errtype == $important_error){
return true;
}
}
return false;
}
/**
* show styles and html code for fatal error
*/
public function view_fatal_error(Int $errno, String $errstr, String $errfile, Int $errline){
http_response_code(500);
if(!FCONF["debug"]) return false;
$err_type = $this -> get_err_type($errno);
$code = $this -> get_prog_code($errfile, $errline);
$errstr = str_replace(["\\", "\n", "\r", "\t", "\""], ["\", "", "", "", "'"], str_replace("`", "'", $errstr));
$code = str_replace(["\\", "\n"], ["\", ""], str_replace("`", "'", $code));
$this -> show_err_page(compact("errno", "err_type", "errstr", "errfile", "errline", "code"));
}
protected function show_err_page(Array $data) {
$json_data = json_encode($data);
echo "<title></title>";
echo '<link rel="stylesheet" type="text/css" href="/SHServ/Resources/css/server-error-handler.css">';
echo "<div class='simple-err-disp'><b>{$data["err_type"]}</b>: {$data["errstr"]}<br>{$data["errfile"]} In line <b>{$data["errline"]}</b></div>";
echo "<script>const eh_err = `{$json_data}`;</script>";
echo '<script src="/SHServ/Resources/js/dist/server-error-handler.js"></script>';
echo "<div class='error-handler'></div>";
die();
}
}