PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/core/Error.php

https://github.com/CodeYellowBV/piwik
PHP | 222 lines | 144 code | 23 blank | 55 comment | 13 complexity | c3d78ad96b3f09169a4a972066f69d75 MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik;
  10. require_once PIWIK_INCLUDE_PATH . '/core/Log.php';
  11. /**
  12. * Holds PHP error information (non-exception errors). Also contains log formatting logic
  13. * for PHP errors and Piwik's error handler function.
  14. */
  15. class Error
  16. {
  17. /**
  18. * The backtrace string to use when testing.
  19. *
  20. * @var string
  21. */
  22. public static $debugBacktraceForTests = null;
  23. /**
  24. * The error number. See http://php.net/manual/en/errorfunc.constants.php#errorfunc.constants.errorlevels
  25. *
  26. * @var int
  27. */
  28. public $errno;
  29. /**
  30. * The error message.
  31. *
  32. * @var string
  33. */
  34. public $errstr;
  35. /**
  36. * The file in which the error occurred.
  37. *
  38. * @var string
  39. */
  40. public $errfile;
  41. /**
  42. * The line number on which the error occurred.
  43. *
  44. * @var int
  45. */
  46. public $errline;
  47. /**
  48. * The error backtrace.
  49. *
  50. * @var string
  51. */
  52. public $backtrace;
  53. /**
  54. * Constructor.
  55. *
  56. * @param int $errno
  57. * @param string $errstr
  58. * @param string $errfile
  59. * @param int $errline
  60. * @param string $backtrace
  61. */
  62. public function __construct($errno, $errstr, $errfile, $errline, $backtrace)
  63. {
  64. $this->errno = $errno;
  65. $this->errstr = $errstr;
  66. $this->errfile = $errfile;
  67. $this->errline = $errline;
  68. $this->backtrace = $backtrace;
  69. }
  70. public function getErrNoString()
  71. {
  72. switch ($this->errno) {
  73. case E_ERROR:
  74. return "Error";
  75. case E_WARNING:
  76. return "Warning";
  77. case E_PARSE:
  78. return "Parse Error";
  79. case E_NOTICE:
  80. return "Notice";
  81. case E_CORE_ERROR:
  82. return "Core Error";
  83. case E_CORE_WARNING:
  84. return "Core Warning";
  85. case E_COMPILE_ERROR:
  86. return "Compile Error";
  87. case E_COMPILE_WARNING:
  88. return "Compile Warning";
  89. case E_USER_ERROR:
  90. return "User Error";
  91. case E_USER_WARNING:
  92. return "User Warning";
  93. case E_USER_NOTICE:
  94. return "User Notice";
  95. case E_STRICT:
  96. return "Strict Notice";
  97. case E_RECOVERABLE_ERROR:
  98. return "Recoverable Error";
  99. case E_DEPRECATED:
  100. return "Deprecated";
  101. case E_USER_DEPRECATED:
  102. return "User Deprecated";
  103. default:
  104. return "Unknown error ({$this->errno})";
  105. }
  106. }
  107. public static function formatFileAndDBLogMessage(&$message, $level, $tag, $datetime, $log)
  108. {
  109. if ($message instanceof Error) {
  110. $message = $message->errfile . '(' . $message->errline . '): ' . $message->getErrNoString()
  111. . ' - ' . $message->errstr . "\n" . $message->backtrace;
  112. $message = $log->formatMessage($level, $tag, $datetime, $message);
  113. }
  114. }
  115. public static function formatScreenMessage(&$message, $level, $tag, $datetime, $log)
  116. {
  117. if ($message instanceof Error) {
  118. $errno = $message->errno & error_reporting();
  119. // problem when using error_reporting with the @ silent fail operator
  120. // it gives an errno 0, and in this case the objective is to NOT display anything on the screen!
  121. // is there any other case where the errno is zero at this point?
  122. if ($errno == 0) {
  123. $message = false;
  124. return;
  125. }
  126. if (!Common::isPhpCliMode()) {
  127. @header('Content-Type: text/html; charset=utf-8');
  128. }
  129. $htmlString = '';
  130. $htmlString .= "\n<div style='word-wrap: break-word; border: 3px solid red; padding:4px; width:70%; background-color:#FFFF96;'>
  131. <strong>There is an error. Please report the message (Piwik " . (class_exists('Piwik\Version') ? Version::VERSION : '') . ")
  132. and full backtrace in the <a href='?module=Proxy&action=redirect&url=http://forum.piwik.org' target='_blank'>Piwik forums</a> (please do a Search first as it might have been reported already!).<br /><br/>
  133. ";
  134. $htmlString .= $message->getErrNoString();
  135. $htmlString .= ":</strong> <em>{$message->errstr}</em> in <strong>{$message->errfile}</strong>";
  136. $htmlString .= " on line <strong>{$message->errline}</strong>\n";
  137. $htmlString .= "<br /><br />Backtrace --&gt;<div style=\"font-family:Courier;font-size:10pt\"><br />\n";
  138. $htmlString .= str_replace("\n", "<br />\n", $message->backtrace);
  139. $htmlString .= "</div><br />";
  140. $htmlString .= "\n </pre></div><br />";
  141. $message = $htmlString;
  142. }
  143. }
  144. public static function setErrorHandler()
  145. {
  146. Piwik::addAction('Log.formatFileMessage', array('\\Piwik\\Error', 'formatFileAndDBLogMessage'));
  147. Piwik::addAction('Log.formatDatabaseMessage', array('\\Piwik\\Error', 'formatFileAndDBLogMessage'));
  148. Piwik::addAction('Log.formatScreenMessage', array('\\Piwik\\Error', 'formatScreenMessage'));
  149. set_error_handler(array('\\Piwik\\Error', 'errorHandler'));
  150. }
  151. public static function errorHandler($errno, $errstr, $errfile, $errline)
  152. {
  153. // if the error has been suppressed by the @ we don't handle the error
  154. if (error_reporting() == 0) {
  155. return;
  156. }
  157. $backtrace = '';
  158. if (empty(self::$debugBacktraceForTests)) {
  159. $bt = @debug_backtrace();
  160. if ($bt !== null && isset($bt[0])) {
  161. foreach ($bt as $i => $debug) {
  162. $backtrace .= "#$i "
  163. . (isset($debug['class']) ? $debug['class'] : '')
  164. . (isset($debug['type']) ? $debug['type'] : '')
  165. . (isset($debug['function']) ? $debug['function'] : '')
  166. . '(...) called at ['
  167. . (isset($debug['file']) ? $debug['file'] : '') . ':'
  168. . (isset($debug['line']) ? $debug['line'] : '') . ']' . "\n";
  169. }
  170. }
  171. } else {
  172. $backtrace = self::$debugBacktraceForTests;
  173. }
  174. $error = new Error($errno, $errstr, $errfile, $errline, $backtrace);
  175. Log::error($error);
  176. switch ($errno) {
  177. case E_ERROR:
  178. case E_PARSE:
  179. case E_CORE_ERROR:
  180. case E_CORE_WARNING:
  181. case E_COMPILE_ERROR:
  182. case E_COMPILE_WARNING:
  183. case E_USER_ERROR:
  184. exit;
  185. break;
  186. case E_WARNING:
  187. case E_NOTICE:
  188. case E_USER_WARNING:
  189. case E_USER_NOTICE:
  190. case E_STRICT:
  191. case E_RECOVERABLE_ERROR:
  192. case E_DEPRECATED:
  193. case E_USER_DEPRECATED:
  194. default:
  195. // do not exit
  196. break;
  197. }
  198. }
  199. }