errno = $errno;
$this->errstr = $errstr;
$this->errfile = $errfile;
$this->errline = $errline;
$this->backtrace = $backtrace;
}
public function getErrNoString()
{
switch ($this->errno) {
case E_ERROR:
return "Error";
case E_WARNING:
return "Warning";
case E_PARSE:
return "Parse Error";
case E_NOTICE:
return "Notice";
case E_CORE_ERROR:
return "Core Error";
case E_CORE_WARNING:
return "Core Warning";
case E_COMPILE_ERROR:
return "Compile Error";
case E_COMPILE_WARNING:
return "Compile Warning";
case E_USER_ERROR:
return "User Error";
case E_USER_WARNING:
return "User Warning";
case E_USER_NOTICE:
return "User Notice";
case E_STRICT:
return "Strict Notice";
case E_RECOVERABLE_ERROR:
return "Recoverable Error";
case E_DEPRECATED:
return "Deprecated";
case E_USER_DEPRECATED:
return "User Deprecated";
default:
return "Unknown error ({$this->errno})";
}
}
public static function formatFileAndDBLogMessage(&$message, $level, $tag, $datetime, $log)
{
if ($message instanceof Error) {
$message = $message->errfile . '(' . $message->errline . '): ' . $message->getErrNoString()
. ' - ' . $message->errstr . "\n" . $message->backtrace;
$message = $log->formatMessage($level, $tag, $datetime, $message);
}
}
public static function formatScreenMessage(&$message, $level, $tag, $datetime, $log)
{
if ($message instanceof Error) {
$errno = $message->errno & error_reporting();
// problem when using error_reporting with the @ silent fail operator
// it gives an errno 0, and in this case the objective is to NOT display anything on the screen!
// is there any other case where the errno is zero at this point?
if ($errno == 0) {
$message = false;
return;
}
if (!Common::isPhpCliMode()) {
@header('Content-Type: text/html; charset=utf-8');
}
$htmlString = '';
$htmlString .= "\n
There is an error. Please report the message (Piwik " . (class_exists('Piwik\Version') ? Version::VERSION : '') . ")
and full backtrace in the Piwik forums (please do a Search first as it might have been reported already!).
";
$htmlString .= $message->getErrNoString();
$htmlString .= ": {$message->errstr} in
{$message->errfile}";
$htmlString .= " on line
{$message->errline}\n";
$htmlString .= "
Backtrace -->
\n";
$htmlString .= str_replace("\n", "
\n", $message->backtrace);
$htmlString .= "
";
$htmlString .= "\n
";
$message = $htmlString;
}
}
public static function setErrorHandler()
{
Piwik::addAction('Log.formatFileMessage', array('\\Piwik\\Error', 'formatFileAndDBLogMessage'));
Piwik::addAction('Log.formatDatabaseMessage', array('\\Piwik\\Error', 'formatFileAndDBLogMessage'));
Piwik::addAction('Log.formatScreenMessage', array('\\Piwik\\Error', 'formatScreenMessage'));
set_error_handler(array('\\Piwik\\Error', 'errorHandler'));
}
public static function errorHandler($errno, $errstr, $errfile, $errline)
{
// if the error has been suppressed by the @ we don't handle the error
if (error_reporting() == 0) {
return;
}
$backtrace = '';
if (empty(self::$debugBacktraceForTests)) {
$bt = @debug_backtrace();
if ($bt !== null && isset($bt[0])) {
foreach ($bt as $i => $debug) {
$backtrace .= "#$i "
. (isset($debug['class']) ? $debug['class'] : '')
. (isset($debug['type']) ? $debug['type'] : '')
. (isset($debug['function']) ? $debug['function'] : '')
. '(...) called at ['
. (isset($debug['file']) ? $debug['file'] : '') . ':'
. (isset($debug['line']) ? $debug['line'] : '') . ']' . "\n";
}
}
} else {
$backtrace = self::$debugBacktraceForTests;
}
$error = new Error($errno, $errstr, $errfile, $errline, $backtrace);
Log::error($error);
switch ($errno) {
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_CORE_WARNING:
case E_COMPILE_ERROR:
case E_COMPILE_WARNING:
case E_USER_ERROR:
exit;
break;
case E_WARNING:
case E_NOTICE:
case E_USER_WARNING:
case E_USER_NOTICE:
case E_STRICT:
case E_RECOVERABLE_ERROR:
case E_DEPRECATED:
case E_USER_DEPRECATED:
default:
// do not exit
break;
}
}
}