139 lines
4.5 KiB
PHP
139 lines
4.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This will initialize strict mode. It is safe to be called multiple times per process
|
|
* eg in the event that a 3rd party lib overrides an error or exception handler.
|
|
*
|
|
* It is called in this file; the parent php file(s) should use require_once and do
|
|
* not need to make any call.
|
|
*/
|
|
function init_strict_mode()
|
|
{
|
|
|
|
// these are safe to call multiple times per process without dups.
|
|
error_reporting(E_ALL | E_STRICT);
|
|
restore_strict_error_handler();
|
|
restore_strict_exception_handler();
|
|
|
|
// register_shutdown_function should only be called once per process to avoid dups.
|
|
static $called = false;
|
|
if (!$called) {
|
|
register_shutdown_function('shutdown_handler');
|
|
$called = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function restores the error handler if it should get overridden
|
|
* eg by a 3rd party lib. Any error handlers that were registered after
|
|
* ours are removed.
|
|
*/
|
|
function restore_strict_error_handler()
|
|
{
|
|
$e_handler_name = function () {
|
|
$name = set_error_handler('restore_strict_error_handler'); // will never be used.
|
|
restore_error_handler();
|
|
|
|
return $name;
|
|
};
|
|
|
|
while (!in_array($e_handler_name(), ['_global_error_handler', null])) {
|
|
restore_error_handler();
|
|
}
|
|
if (!$e_handler_name()) {
|
|
set_error_handler('_global_error_handler');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function restores the exception handler if it should get overridden
|
|
* eg by a 3rd party lib. Any error handlers that were registered after
|
|
* ours are removed.
|
|
*/
|
|
function restore_strict_exception_handler()
|
|
{
|
|
$exc_handler_name = function () {
|
|
$name = set_exception_handler('restore_strict_exception_handler'); // will never be used.
|
|
restore_exception_handler();
|
|
|
|
return $name;
|
|
};
|
|
|
|
while (!in_array($exc_handler_name(), ['_global_exception_handler', null])) {
|
|
restore_exception_handler();
|
|
}
|
|
if (!$exc_handler_name()) {
|
|
set_exception_handler('_global_exception_handler');
|
|
}
|
|
}
|
|
|
|
/***
|
|
* This error handler callback will be called for every type of PHP notice/warning/error.
|
|
*
|
|
* We aspire to write solid code. everything is an exception, even minor warnings.
|
|
*
|
|
* However, we allow the @operator in the code to override.
|
|
*/
|
|
function _global_error_handler($errno, $errstr, $errfile, $errline)
|
|
{
|
|
|
|
/* from php.net
|
|
* error_reporting() settings will have no effect and your error handler will
|
|
* be called regardless - however you are still able to read the current value of
|
|
* error_reporting and act appropriately. Of particular note is that this value will
|
|
* be 0 if the statement that caused the error was prepended by the @ error-control operator.
|
|
*/
|
|
if (!error_reporting()) {
|
|
return;
|
|
}
|
|
|
|
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
|
|
}
|
|
|
|
|
|
/***
|
|
* This exception handler callback will be called for any exceptions that the application code does not catch.
|
|
*/
|
|
function _global_exception_handler($e)
|
|
{
|
|
$msg = sprintf("\nUncaught Exception. code: %s, message: %s\n%s : %s\n\nStack Trace:\n%s\n", $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString());
|
|
while (($e = $e->getPrevious())) {
|
|
$msg .= sprintf("\nPrevious Exception. code: %s, message: %s\n%s : %s\n\nStack Trace:\n%s\n", $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString());
|
|
}
|
|
echo $msg;
|
|
// error_log( $msg );
|
|
strict_mode_mail_admin('Uncaught exception!', $msg);
|
|
echo "\n\nNow exiting. Please report this problem to the software author\n\n";
|
|
exit(1);
|
|
}
|
|
|
|
/**
|
|
* This shutdown handler callback prints a message and sends email on any PHP fatal error.
|
|
*/
|
|
function shutdown_handler()
|
|
{
|
|
$error = error_get_last();
|
|
|
|
$ignore = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_STRICT | E_DEPRECATED | E_USER_DEPRECATED;
|
|
if ($error && ($error['type'] & $ignore) == 0) {
|
|
|
|
// error keys: type, file, line, message
|
|
$msg = "Ouch! Encountered PHP Fatal Error. Shutting down.\n".print_r($error, true);
|
|
echo $msg;
|
|
strict_mode_mail_admin('PHP Fatal Error!', $msg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* email admin if defined.
|
|
*/
|
|
function strict_mode_mail_admin($subject, $msg)
|
|
{
|
|
$subject = sprintf('[%s] [%s] %s [pid: %s]', gethostname(), basename($_SERVER['PHP_SELF']), $subject, getmypid());
|
|
if (defined('ALERTS_MAIL_TO')) {
|
|
mail(ALERTS_MAIL_TO, $subject, $msg);
|
|
} else {
|
|
echo "\nWARNING: ALERTS_MAIL_TO not defined in environment. alert not sent with subject: $subject\n";
|
|
}
|
|
}
|