<?php

namespace loyalsoft;

/**
 * 错误处理模块, 主要是捕获框架运行中的异常信息, 并记录到日志中.
 * @version
 *          1.0.0 功能整理独立成为一个文件. 2017年8月8日 09:04:36. by --gwang
 * @author gwang (mail@wanggangzero.cn)
 * @copyright ? 2017-8-8, SJZ LoyalSoft Corporation & gwang. All rights reserved.
 */
class ErrHandler {

    /**
     * 自定义错误处理方法
     * @param int $errno
     * @param string $errstr
     * @param string $errfile
     * @param int $errline
     * @return boolean 此错误,是否继续由其他模块处理(冒泡), true: 停止, false: 继续
     */
    static function error_handler($errno, $errstr, $errfile, $errline) {
        $msg = CommUtil::str2UTF8($errstr) . " in " . CommUtil::str2UTF8($errfile) . ":" . $errline;
        CLog::err($msg . PHP_EOL . DebugHelper::get_call_stack(10), 'Error Handler:');
        return TRUE;                                                            # 不再继续错误处理的冒泡过程::则代码得以继续执行
//        if ($errno == E_USER_ERROR && !(php_sapi_name() === 'cli')) {           # 如果是用户自定义错误，直接返回resp, 这种情况的话,可以刷下数据
//            CLog::flush();                                                      # 最后再将快速日志刷到文件
//            Err($errno);                                                        # 直接返回错误响应
//        }
    }

    /**
     * 程序运行结束时调用
     */
    static function shutdown_function() {
        $lasterror = error_get_last();
        if ($lasterror) {                                                       # 如果是异常结束, 记录日志
            $msg = CommUtil::str2UTF8(var_export($lasterror, true));
            CLog::err($msg, 'Shutdown Handler:');
        } else {
//            CLog::err("just normal exiting", 'Shutdown Handler:');            # 正常结束运行
        }
        CLog::flush();                                                          # 最后再将快速日志刷到文件(如果有数据的话)
    }

    /**
     *  自定义异常处理函数, 将捕获的异常信息写入日志
     * @param \Exception $exception
     */
    static function appException($exception) {
        $msg = CommUtil::str2UTF8($exception->getMessage())
                . '  in ' . CommUtil::str2UTF8($exception->getFile())
                . ":" . $exception->getLine();
        CLog::err($msg . PHP_EOL . DebugHelper::get_call_stack(10), 'Exception Handler:');
        CLog::flush();                                                          # 最后再将快速日志刷到文件,因为后续逻辑执行就中断了
    }

    /**
     * 依据全局变量决定是否开启错误handler并设置Err捕获级别
     */
    static function AutoHookShutdownExceptionHandler() {
        if (defined('DEBUGING') && DEBUGING) {                                  # 调试模式,启用所有的php错误报告
            error_reporting(E_ALL);                                             # E_ALL : 开启所有错误和警告
            register_shutdown_function(array(__CLASS__, 'shutdown_function'));  # 插入运行结束时处理代码
            set_error_handler(array(__CLASS__, 'error_handler'));               # 插入自定义错误处理代码
            set_exception_handler(array(__CLASS__, 'appException'));            # 插入自定义异常处理代码
        } else {
            error_reporting(0);                                                 # 非调试模式关闭所有的错误报告
        }
    }

}

// 越早启用捕获的错误信息也就越全面
ErrHandler::AutoHookShutdownExceptionHandler();                                 # 初始化框架错误捕获机制