<?php

class ErrorHandler
{
  var $Encoding;
  var $ShowError;
  var $UserErrors;
  var $OnError;

  function __construct()
  {
    $this->Encoding = 'utf-8';
    $this->ShowError = false;
    $this->UserErrors = E_ALL;  //E_ERROR | E_WARNING | E_PARSE;
    $this->OnError = array(array($this, 'ShowDefaultError'));
  }

  function Start()
  {
    set_error_handler(array($this, 'ErrorHandler'));
    set_exception_handler(array($this, 'ExceptionHandler'));
  }

  function Stop()
  {
    restore_error_handler();
    restore_exception_handler();
  }

  function ErrorHandler($Number, $Message, $FileName, $LineNumber, $Variables)
  {
    $ErrorType = array
    (
      1 => 'Error',
      2 => 'Warning',
      4 => 'Parsing Error',
      8 => 'Notice',
      16 => 'Core Error',
      32 => 'Core Warning',
      64 => 'Compile Error',
      128 => 'Compile Warning',
      256 => 'User Error',
      512 => 'User Warning',
      1024 => 'User Notice'
    );

    if(($this->UserErrors & $Number))
    {
      // Error was suppressed with the @-operator
      if(0 === error_reporting())
      {
        return false;
      }
      $Backtrace = debug_backtrace();
      $Backtrace[0]['function'] = $Message;
      $Backtrace[0]['args'] = '';
      $Backtrace[0]['file'] = $FileName;
      $Backtrace[0]['line'] = $LineNumber;
      $this->Report($Backtrace);
      //if((E_ERROR | E_PARSE) & $Number)
      die();
    }
  }

  function ExceptionHandler(Exception $Exception)
  {
    $Backtrace = $Exception->getTrace();
    array_unshift($Backtrace, array(
      'function' => $Exception->getMessage(),
      'file' => $Exception->getFile(),
      'line' => $Exception->getLine(),
    ));
    $this->Report($Backtrace);
    die();
  }

  function ShowDefaultError($Message)
  {
    $Output = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>'."\n".
      '<meta http-equiv="Content-Language" content="en">'."\n".
      '<meta http-equiv="Content-Type" content="text/html; charset='.$this->Encoding.'"></head><body>'."\n".
      'An internal error occurred!<br/>'.
      'Administrator will be notified and the problem will be investigated and fixed soon.'.'<br/><br/>';
    if($this->ShowError == true)
      $Output .= '<pre>'.$Message.'</pre><br/>';
    $Output .= '</body></html>';
    echo($Output);
  }

  function Report($Backtrace)
  {
    $Date = date('Y-m-d H:i:s');
    $Error = '# '.$Date."\n";
    foreach($Backtrace as $Item)
    {
      if(!array_key_exists('line', $Item)) $Item['line'] = '';
      if(!array_key_exists('file', $Item)) $Item['file'] = '';

      $Error .= ' '.$Item['file'].'('.$Item['line'].")\t".$Item['function'];
      $Arguments = '';
      if(array_key_exists('args', $Item) and is_array($Item['args']))
        foreach($Item['args'] as $Item)
        {
          if(is_object($Item)) ;
          else if(is_array($Item)) $Arguments .= "'".serialize($Item)."',";
          else $Arguments .= "'".$Item."',";
        }
        if(strlen($Arguments) > 0) $Error .= '('.substr($Arguments, 0, -1).')';
        $Error .= "\n";
    }
    $Error .= "\n";
    
    print_r($this->OnError);

    foreach($this->OnError as $OnError)
      call_user_func($OnError, $Error);
  }
}
