xref: /dokuwiki/inc/ErrorHandler.php (revision 642e976cb685105e1684f43a5d99c79f258029f4)
1*642e976cSAndreas Gohr<?php
2*642e976cSAndreas Gohr
3*642e976cSAndreas Gohrnamespace dokuwiki;
4*642e976cSAndreas Gohr
5*642e976cSAndreas Gohrclass ErrorHandler
6*642e976cSAndreas Gohr{
7*642e976cSAndreas Gohr
8*642e976cSAndreas Gohr    /**
9*642e976cSAndreas Gohr     * Register the default error handling
10*642e976cSAndreas Gohr     */
11*642e976cSAndreas Gohr    public static function register()
12*642e976cSAndreas Gohr    {
13*642e976cSAndreas Gohr        set_error_handler([ErrorHandler::class, 'errorConverter']);
14*642e976cSAndreas Gohr        if (!defined('DOKU_UNITTEST')) {
15*642e976cSAndreas Gohr            set_exception_handler([ErrorHandler::class, 'fatalException']);
16*642e976cSAndreas Gohr        }
17*642e976cSAndreas Gohr    }
18*642e976cSAndreas Gohr
19*642e976cSAndreas Gohr    /**
20*642e976cSAndreas Gohr     * Default Exception handler to show a nice user message before dieing
21*642e976cSAndreas Gohr     *
22*642e976cSAndreas Gohr     * The exception is logged to the error log
23*642e976cSAndreas Gohr     *
24*642e976cSAndreas Gohr     * @param \Throwable $e
25*642e976cSAndreas Gohr     */
26*642e976cSAndreas Gohr    public static function fatalException($e)
27*642e976cSAndreas Gohr    {
28*642e976cSAndreas Gohr        $title = hsc(get_class($e) . ': ' . $e->getMessage());
29*642e976cSAndreas Gohr        $msg = 'An unforeseen error has occured. This is most likely a bug somewhere.';
30*642e976cSAndreas Gohr        $logged = self::logException($e)
31*642e976cSAndreas Gohr            ? 'More info has been written to the DokuWiki _error.log'
32*642e976cSAndreas Gohr            : $e->getFile() . ':' . $e->getLine();
33*642e976cSAndreas Gohr
34*642e976cSAndreas Gohr        echo <<<EOT
35*642e976cSAndreas Gohr<!DOCTYPE html>
36*642e976cSAndreas Gohr<html>
37*642e976cSAndreas Gohr<head><title>$title</title></head>
38*642e976cSAndreas Gohr<body style="font-family: Arial, sans-serif">
39*642e976cSAndreas Gohr    <div style="width:60%; margin: auto; background-color: #fcc;
40*642e976cSAndreas Gohr                border: 1px solid #faa; padding: 0.5em 1em;">
41*642e976cSAndreas Gohr        <h1 style="font-size: 120%">$title</h1>
42*642e976cSAndreas Gohr        <p>$msg</p>
43*642e976cSAndreas Gohr        <p>$logged</p>
44*642e976cSAndreas Gohr    </div>
45*642e976cSAndreas Gohr</body>
46*642e976cSAndreas Gohr</html>
47*642e976cSAndreas GohrEOT;
48*642e976cSAndreas Gohr    }
49*642e976cSAndreas Gohr
50*642e976cSAndreas Gohr    /**
51*642e976cSAndreas Gohr     * Convenience method to display an error message for the given Exception
52*642e976cSAndreas Gohr     *
53*642e976cSAndreas Gohr     * @param \Throwable $e
54*642e976cSAndreas Gohr     * @param string $intro
55*642e976cSAndreas Gohr     */
56*642e976cSAndreas Gohr    public static function showExceptionMsg($e, $intro = 'Error!')
57*642e976cSAndreas Gohr    {
58*642e976cSAndreas Gohr        $msg = $intro . get_class($e) . ': ' . $e->getMessage();
59*642e976cSAndreas Gohr        self::logException($e);
60*642e976cSAndreas Gohr        msg(hsc($msg), -1);
61*642e976cSAndreas Gohr    }
62*642e976cSAndreas Gohr
63*642e976cSAndreas Gohr    /**
64*642e976cSAndreas Gohr     * Default error handler to convert old school warnings, notices, etc to exceptions
65*642e976cSAndreas Gohr     *
66*642e976cSAndreas Gohr     * You should not need to call this directly!
67*642e976cSAndreas Gohr     *
68*642e976cSAndreas Gohr     * @param int $errno
69*642e976cSAndreas Gohr     * @param string $errstr
70*642e976cSAndreas Gohr     * @param string $errfile
71*642e976cSAndreas Gohr     * @param int $errline
72*642e976cSAndreas Gohr     * @return bool
73*642e976cSAndreas Gohr     * @throws \ErrorException
74*642e976cSAndreas Gohr     */
75*642e976cSAndreas Gohr    public static function errorConverter($errno, $errstr, $errfile, $errline)
76*642e976cSAndreas Gohr    {
77*642e976cSAndreas Gohr        if (!(error_reporting() & $errno)) {
78*642e976cSAndreas Gohr            // This error code is not included in error_reporting, so let it fall
79*642e976cSAndreas Gohr            // through to the standard PHP error handler
80*642e976cSAndreas Gohr            return false;
81*642e976cSAndreas Gohr        }
82*642e976cSAndreas Gohr        throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
83*642e976cSAndreas Gohr    }
84*642e976cSAndreas Gohr
85*642e976cSAndreas Gohr    /**
86*642e976cSAndreas Gohr     * Log the given exception to the error log
87*642e976cSAndreas Gohr     *
88*642e976cSAndreas Gohr     * @param \Throwable $e
89*642e976cSAndreas Gohr     * @return bool false if the logging failed
90*642e976cSAndreas Gohr     */
91*642e976cSAndreas Gohr    public static function logException($e)
92*642e976cSAndreas Gohr    {
93*642e976cSAndreas Gohr        global $conf;
94*642e976cSAndreas Gohr
95*642e976cSAndreas Gohr        $log = join("\t", [gmdate('c'), get_class($e), $e->getFile() . ':' . $e->getLine(), $e->getMessage()]) . "\n";
96*642e976cSAndreas Gohr        return io_saveFile($conf['cachedir'] . '/_error.log', $log, true);
97*642e976cSAndreas Gohr    }
98*642e976cSAndreas Gohr}
99