/fuel/core/classes/error.php

https://github.com/Keilaron/TweetBeagle · PHP · 236 lines · 146 code · 37 blank · 53 comment · 22 complexity · 3cc96ab2f6d4e1fb5769d59143884bb8 MD5 · raw file

  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP5 framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2011 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. class Error {
  14. public static $levels = array(
  15. 0 => 'Error',
  16. E_ERROR => 'Error',
  17. E_WARNING => 'Warning',
  18. E_PARSE => 'Parsing Error',
  19. E_NOTICE => 'Notice',
  20. E_CORE_ERROR => 'Core Error',
  21. E_CORE_WARNING => 'Core Warning',
  22. E_COMPILE_ERROR => 'Compile Error',
  23. E_COMPILE_WARNING => 'Compile Warning',
  24. E_USER_ERROR => 'User Error',
  25. E_USER_WARNING => 'User Warning',
  26. E_USER_NOTICE => 'User Notice',
  27. E_STRICT => 'Runtime Notice'
  28. );
  29. public static $fatal_levels = array(E_PARSE, E_ERROR, E_USER_ERROR, E_COMPILE_ERROR);
  30. public static $count = 0;
  31. public static $non_fatal_cache = array();
  32. /**
  33. * Native PHP shutdown handler
  34. *
  35. * @return string
  36. */
  37. public static function shutdown_handler()
  38. {
  39. $last_error = error_get_last();
  40. // Only show valid fatal errors
  41. if ($last_error AND in_array($last_error['type'], static::$fatal_levels))
  42. {
  43. $severity = static::$levels[$last_error['type']];
  44. logger(Fuel::L_ERROR, $severity.' - '.$last_error['message'].' in '.$last_error['file'].' on line '.$last_error['line']);
  45. if ((\Fuel::$is_cli) || (\Fuel::$env != Fuel::PRODUCTION))
  46. {
  47. static::show_php_error(new \ErrorException($last_error['message'], $last_error['type'], 0, $last_error['file'], $last_error['line']));
  48. }
  49. else
  50. {
  51. static::show_production_error();
  52. }
  53. exit(1);
  54. }
  55. }
  56. /**
  57. * PHP Exception handler
  58. *
  59. * @param Exception $e the exception
  60. * @return bool
  61. */
  62. public static function exception_handler(\Exception $e)
  63. {
  64. $severity = ( ! isset(static::$levels[$e->getCode()])) ? $e->getCode() : static::$levels[$e->getCode()];
  65. logger(Fuel::L_ERROR, $severity.' - '.$e->getMessage().' in '.$e->getFile().' on line '.$e->getLine());
  66. if ((\Fuel::$is_cli) || (\Fuel::$env != Fuel::PRODUCTION))
  67. {
  68. static::show_php_error($e);
  69. }
  70. else
  71. {
  72. static::show_production_error();
  73. }
  74. }
  75. /**
  76. * PHP Error handler
  77. *
  78. * @param int $severity the severity code
  79. * @param string $message the error message
  80. * @param string $filepath the path to the file throwing the error
  81. * @param int $line the line number of the error
  82. * @return bool whether to continue with execution
  83. */
  84. public static function error_handler($severity, $message, $filepath, $line)
  85. {
  86. if (static::$count <= Config::get('errors.throttling', 10))
  87. {
  88. logger(Fuel::L_ERROR, $severity.' - '.$message.' in '.$filepath.' on line '.$line);
  89. if (\Fuel::$env != \Fuel::PRODUCTION and ($severity & error_reporting()) == $severity)
  90. {
  91. static::$count++;
  92. static::show_php_error(new \ErrorException($message, $severity, 0, $filepath, $line));
  93. }
  94. }
  95. elseif (\Fuel::$env != \Fuel::PRODUCTION
  96. and static::$count == (\Config::get('error_throttling', 10) + 1)
  97. and ($severity & error_reporting()) == $severity)
  98. {
  99. static::$count++;
  100. static::notice('Error throttling threshold was reached, no more full error reports are shown.', true);
  101. }
  102. return true;
  103. }
  104. /**
  105. * Shows an error. It will stop script execution if the error code is not
  106. * in the errors.continue_on whitelist.
  107. *
  108. * @param Exception $e the exception to show
  109. * @return void
  110. */
  111. public static function show_php_error(\Exception $e)
  112. {
  113. $fatal = (bool)( ! in_array($e->getCode(), \Config::get('errors.continue_on')));
  114. $data = static::prepare_exception($e, $fatal);
  115. if ($fatal)
  116. {
  117. $data['contents'] = ob_get_contents();
  118. while (ob_get_contents() !== FALSE)
  119. ob_end_clean();
  120. }
  121. else
  122. {
  123. static::$non_fatal_cache[] = $data;
  124. }
  125. if (\Fuel::$is_cli)
  126. {
  127. \Cli::write(\Cli::color($data['severity'].' - '.$data['message'].' in '.\Fuel::clean_path($data['filepath']).' on line '.$data['error_line'], 'red'));
  128. var_dump(debug_backtrace());
  129. return;
  130. }
  131. if ($fatal)
  132. {
  133. $data['non_fatal'] = static::$non_fatal_cache;
  134. exit(\View::factory('errors'.DS.'php_fatal_error', $data, false));
  135. }
  136. echo \View::factory('errors'.DS.'php_error', $data, false);
  137. }
  138. /**
  139. * Shows a small notice error, only when not in production or when forced.
  140. * This is used by several libraries to notify the developer of certain things.
  141. *
  142. * @param string $msg the message to display
  143. * @param bool $always_show whether to force display the notice or not
  144. * @return void
  145. */
  146. public static function notice($msg, $always_show = false)
  147. {
  148. $trace = array_merge(array('file' => '(unknown)', 'line' => '(unknown)'), \Arr::element(debug_backtrace(), 1));
  149. logger(Fuel::L_DEBUG, 'Notice - '.$msg.' in '.$trace['file'].' on line '.$trace['line']);
  150. if (\Fuel::$is_test or ( ! $always_show and (\Fuel::$env == \Fuel::PRODUCTION or \Config::get('errors.notices', true) === false)))
  151. {
  152. return;
  153. }
  154. $data['message'] = $msg;
  155. $data['type'] = 'Notice';
  156. $data['filepath'] = \Fuel::clean_path($trace['file']);
  157. $data['line'] = $trace['line'];
  158. $data['function'] = $trace['function'];
  159. echo \View::factory('errors'.DS.'php_short', $data, false);
  160. }
  161. /**
  162. * Shows the errors/production view and exits. This only gets
  163. * called when an error occurs in production mode.
  164. *
  165. * @return void
  166. */
  167. public static function show_production_error()
  168. {
  169. exit(\View::factory('errors'.DS.'production'));
  170. }
  171. protected static function prepare_exception(\Exception $e, $fatal = true)
  172. {
  173. $data = array();
  174. $data['type'] = get_class($e);
  175. $data['severity'] = $e->getCode();
  176. $data['message'] = $e->getMessage();
  177. $data['filepath'] = $e->getFile();
  178. $data['error_line'] = $e->getLine();
  179. $data['backtrace'] = $e->getTrace();
  180. $data['severity'] = ( ! isset(static::$levels[$data['severity']])) ? $data['severity'] : static::$levels[$data['severity']];
  181. foreach ($data['backtrace'] as $key => $trace)
  182. {
  183. if ( ! isset($trace['file']))
  184. {
  185. unset($data['backtrace'][$key]);
  186. }
  187. elseif ($trace['file'] == COREPATH.'classes/error.php')
  188. {
  189. unset($data['backtrace'][$key]);
  190. }
  191. }
  192. $data['debug_lines'] = \Debug::file_lines($data['filepath'], $data['error_line'], $fatal);
  193. $data['orig_filepath'] = $data['filepath'];
  194. $data['filepath'] = \Fuel::clean_path($data['filepath']);
  195. $data['filepath'] = str_replace("\\", "/", $data['filepath']);
  196. return $data;
  197. }
  198. }
  199. /* End of file error.php */