introduce a global error handler
This transfers old style PHP errors into Exceptions and installs a global exception handler. All exceptions caught by this handler are logged to an error log and a meassage is shown to the end user. This should finally get rid of "blank page" bug reports.
This commit is contained in:
parent
04225b4a35
commit
642e976cb6
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace dokuwiki;
|
||||
|
||||
class ErrorHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Register the default error handling
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
set_error_handler([ErrorHandler::class, 'errorConverter']);
|
||||
if (!defined('DOKU_UNITTEST')) {
|
||||
set_exception_handler([ErrorHandler::class, 'fatalException']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Exception handler to show a nice user message before dieing
|
||||
*
|
||||
* The exception is logged to the error log
|
||||
*
|
||||
* @param \Throwable $e
|
||||
*/
|
||||
public static function fatalException($e)
|
||||
{
|
||||
$title = hsc(get_class($e) . ': ' . $e->getMessage());
|
||||
$msg = 'An unforeseen error has occured. This is most likely a bug somewhere.';
|
||||
$logged = self::logException($e)
|
||||
? 'More info has been written to the DokuWiki _error.log'
|
||||
: $e->getFile() . ':' . $e->getLine();
|
||||
|
||||
echo <<<EOT
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>$title</title></head>
|
||||
<body style="font-family: Arial, sans-serif">
|
||||
<div style="width:60%; margin: auto; background-color: #fcc;
|
||||
border: 1px solid #faa; padding: 0.5em 1em;">
|
||||
<h1 style="font-size: 120%">$title</h1>
|
||||
<p>$msg</p>
|
||||
<p>$logged</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
EOT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to display an error message for the given Exception
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param string $intro
|
||||
*/
|
||||
public static function showExceptionMsg($e, $intro = 'Error!')
|
||||
{
|
||||
$msg = $intro . get_class($e) . ': ' . $e->getMessage();
|
||||
self::logException($e);
|
||||
msg(hsc($msg), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default error handler to convert old school warnings, notices, etc to exceptions
|
||||
*
|
||||
* You should not need to call this directly!
|
||||
*
|
||||
* @param int $errno
|
||||
* @param string $errstr
|
||||
* @param string $errfile
|
||||
* @param int $errline
|
||||
* @return bool
|
||||
* @throws \ErrorException
|
||||
*/
|
||||
public static function errorConverter($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
if (!(error_reporting() & $errno)) {
|
||||
// This error code is not included in error_reporting, so let it fall
|
||||
// through to the standard PHP error handler
|
||||
return false;
|
||||
}
|
||||
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given exception to the error log
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return bool false if the logging failed
|
||||
*/
|
||||
public static function logException($e)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$log = join("\t", [gmdate('c'), get_class($e), $e->getFile() . ':' . $e->getLine(), $e->getMessage()]) . "\n";
|
||||
return io_saveFile($conf['cachedir'] . '/_error.log', $log, true);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace dokuwiki\Extension;
|
||||
|
||||
use dokuwiki\ErrorHandler;
|
||||
|
||||
/**
|
||||
* Class to encapsulate access to dokuwiki plugins
|
||||
*
|
||||
|
@ -90,42 +92,48 @@ class PluginController
|
|||
|
||||
$class = $type . '_plugin_' . $name;
|
||||
|
||||
//plugin already loaded?
|
||||
if (!empty($DOKU_PLUGINS[$type][$name])) {
|
||||
if ($new || !$DOKU_PLUGINS[$type][$name]->isSingleton()) {
|
||||
return class_exists($class, true) ? new $class : null;
|
||||
try {
|
||||
//plugin already loaded?
|
||||
if (!empty($DOKU_PLUGINS[$type][$name])) {
|
||||
if ($new || !$DOKU_PLUGINS[$type][$name]->isSingleton()) {
|
||||
|
||||
return class_exists($class, true) ? new $class : null;
|
||||
}
|
||||
|
||||
return $DOKU_PLUGINS[$type][$name];
|
||||
}
|
||||
|
||||
return $DOKU_PLUGINS[$type][$name];
|
||||
}
|
||||
|
||||
//construct class and instantiate
|
||||
if (!class_exists($class, true)) {
|
||||
|
||||
# the plugin might be in the wrong directory
|
||||
$inf = confToHash(DOKU_PLUGIN . "$plugin/plugin.info.txt");
|
||||
if ($inf['base'] && $inf['base'] != $plugin) {
|
||||
msg(
|
||||
sprintf(
|
||||
"Plugin installed incorrectly. Rename plugin directory '%s' to '%s'.",
|
||||
hsc($plugin),
|
||||
hsc(
|
||||
$inf['base']
|
||||
)
|
||||
), -1
|
||||
);
|
||||
} elseif (preg_match('/^' . DOKU_PLUGIN_NAME_REGEX . '$/', $plugin) !== 1) {
|
||||
msg(
|
||||
sprintf(
|
||||
"Plugin name '%s' is not a valid plugin name, only the characters a-z and 0-9 are allowed. " .
|
||||
'Maybe the plugin has been installed in the wrong directory?', hsc($plugin)
|
||||
), -1
|
||||
);
|
||||
//construct class and instantiate
|
||||
if (!class_exists($class, true)) {
|
||||
# the plugin might be in the wrong directory
|
||||
$inf = confToHash(DOKU_PLUGIN . "$plugin/plugin.info.txt");
|
||||
if ($inf['base'] && $inf['base'] != $plugin) {
|
||||
msg(
|
||||
sprintf(
|
||||
"Plugin installed incorrectly. Rename plugin directory '%s' to '%s'.",
|
||||
hsc($plugin),
|
||||
hsc(
|
||||
$inf['base']
|
||||
)
|
||||
), -1
|
||||
);
|
||||
} elseif (preg_match('/^' . DOKU_PLUGIN_NAME_REGEX . '$/', $plugin) !== 1) {
|
||||
msg(
|
||||
sprintf(
|
||||
"Plugin name '%s' is not a valid plugin name, only the characters a-z and 0-9 are allowed. " .
|
||||
'Maybe the plugin has been installed in the wrong directory?', hsc($plugin)
|
||||
), -1
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$DOKU_PLUGINS[$type][$name] = new $class;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
ErrorHandler::showExceptionMsg($e, sprintf('Failed to load plugin %s', $plugin));
|
||||
return null;
|
||||
}
|
||||
|
||||
$DOKU_PLUGINS[$type][$name] = new $class;
|
||||
return $DOKU_PLUGINS[$type][$name];
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,9 @@ if (empty($plugin_controller_class)) $plugin_controller_class = dokuwiki\Extensi
|
|||
require_once(DOKU_INC.'vendor/autoload.php');
|
||||
require_once(DOKU_INC.'inc/load.php');
|
||||
|
||||
// from now on everything is an exception
|
||||
\dokuwiki\ErrorHandler::register();
|
||||
|
||||
// disable gzip if not available
|
||||
define('DOKU_HAS_BZIP', function_exists('bzopen'));
|
||||
define('DOKU_HAS_GZIP', function_exists('gzopen'));
|
||||
|
|
Loading…
Reference in New Issue