PageRenderTime 58ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/system/classes/Exceptions.class.php

http://mortar.googlecode.com/
PHP | 409 lines | 204 code | 52 blank | 153 comment | 36 complexity | 44879cc919353f755de8543e22ecb69c MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * MortarExceptions
  4. *
  5. * While originally developed for Mortar, these exceptions are completely stand alone and are very easy to integrate
  6. * into existing projects. Developers can either call the different exceptions directly or create inheriting exception
  7. * classes for the different objects in their projects. Since this library will include the exception's class name when
  8. * logging or displaying errors the latter method is preferred.
  9. *
  10. * MortarException - 0
  11. * MortarError - E_ERROR
  12. * MortarWarning - E_WARNING
  13. * MortarNotice - E_NOTICE
  14. * MortarDepreciated - E_USER_DEPRECATED
  15. * MortarUserError - E_USER_ERROR
  16. * MortarUserWarning - E_USER_WARNING
  17. * MortarUserNotice - E_USER_NOTICE
  18. *
  19. * @copyright Copyright (c) 2009, Robert Hafner
  20. * @license http://www.opensource.org/licenses/bsd-license.php
  21. */
  22. /*
  23. Copyright (c) 2009, Robert Hafner
  24. All rights reserved.
  25. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
  26. following conditions are met:
  27. * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
  28. disclaimer.
  29. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
  30. following disclaimer in the documentation and/or other materials provided with the distribution.
  31. * Neither the name of the "Mortar" nor the names of its contributors may be used to endorse or promote
  32. products derived from this software without specific prior written permission.
  33. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  34. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  35. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  37. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  38. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  39. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40. */
  41. if(!defined('EXCEPTION_OUTPUT'))
  42. {
  43. /**
  44. * Defines the format which should be used for displaying errors- 'text', 'html' and 'simple' are accepted. This
  45. * can be defined by developers as long as it's done before this file is loaded.
  46. */
  47. define('EXCEPTION_OUTPUT', (defined('STDIN') ? 'text' : 'html'));
  48. }
  49. /**
  50. * MortarException
  51. *
  52. * This class acts as the base for all the other exception classes. It outputs errors and a stack trace when the
  53. * debugging level is high enough. This class itself, while having the display and logging functions built in, is
  54. * designed as a drop in replacement for the Exception class and therefore does not actually log or display anything.
  55. */
  56. class MortarException extends Exception
  57. {
  58. /**
  59. * Each exception inheriting from this class should define this using one of the php error constants (E_ERROR,
  60. * E_WARNING, E_NOTICE, etc) so this class can emulate php actions using the php.ini values.
  61. *
  62. * @var int
  63. */
  64. protected $errorType = 0;
  65. /**
  66. * Initializes the exception and passes itself off to the static function "handleError", using the errorType
  67. * property as the errorLevel for that function. Additionally, if the function "runAction" exists it is called.
  68. *
  69. * @param string $message
  70. * @param int $code This should be left blank or replaced with an error code
  71. */
  72. public function __construct($message = '', $code = 0)
  73. {
  74. parent::__construct($message, $code);
  75. static::handleError($this, $this->errorType);
  76. if(method_exists($this, 'runAction'))
  77. $this->runAction();
  78. }
  79. /**
  80. * Takes in any exception (including those not related to this library) and processes them as an error using the
  81. * errorLevel argument. Various error configuration values are extracted from the php runtime, such as the error
  82. * reporting and logging values, and if it's appropriate the exception is displayed or sent to the php logger.
  83. *
  84. * @param Exception $e
  85. * @param int $errorLevel This should correspond to the various php error constants (E_ERROR, E_WARNING, etc)
  86. */
  87. static public function handleError(Exception $e, $errorLevel = null)
  88. {
  89. if(!isset($errorLevel))
  90. {
  91. $errorLevel = 0; // I could just make this the default argument, but I'd prefer knowing whether something
  92. // was passed or not.
  93. }elseif(!is_numeric($errorLevel)){
  94. $errorLevel = E_ALL | E_STRICT;
  95. }
  96. $error_reporting = error_reporting();
  97. $display_error = ini_get('display_errors');
  98. $display_error = (strtolower($display_error) == 'on' || $display_error == true);
  99. $track_error = ini_get('track_errors');
  100. $track_error = (strtolower($track_error) == 'on' || $track_error == true);
  101. $log_error = ini_get('log_errors');
  102. $log_error = (strtolower($log_error) == 'on' || $log_error == true);
  103. $exception_format = defined('EXCEPTION_OUTPUT') ? strtolower(EXCEPTION_OUTPUT) : 'html';
  104. if($track_error || $log_error || ($display_error && $exception_format == 'simple'))
  105. $errorSimpleText = static::getAsSimpleText($e);
  106. if($track_error == true || strtolower($track_error) == 'on')
  107. {
  108. global $php_errormsg;
  109. $php_errormsg = $errorSimpleText;
  110. }
  111. if($error_reporting & $errorLevel) // boolean &, not conditional &&
  112. {
  113. if($log_error)
  114. static::log($errorSimpleText);
  115. if($display_error)
  116. {
  117. switch($exception_format)
  118. {
  119. case 'text':
  120. echo static::getAsText($e) . PHP_EOL . PHP_EOL;
  121. break;
  122. case 'simple':
  123. echo $errorSimpleText . PHP_EOL . PHP_EOL;
  124. break;
  125. default:
  126. case 'html':
  127. echo static::getAsHtml($e) . PHP_EOL;
  128. break;
  129. }
  130. }
  131. }
  132. }
  133. /**
  134. * Logs the passed string using the php error logging functions. Anything passed here will end up in the PHP log,
  135. * whether that log is run by file, syslog, or anything else.
  136. *
  137. * @param string $logString The string to be logged.
  138. * @return bool Status of log attempt.
  139. */
  140. static public function log($logString)
  141. {
  142. $logString = str_replace(PHP_EOL, ' ', $logString);
  143. $program = defined('PROGRAM') ? '*' . PROGRAM . '* ' : '';
  144. $logText = $program . $logString;
  145. return error_log($logText);
  146. }
  147. /**
  148. * Returns a single line description of the passed exception, suitable for sending to logging functions.
  149. *
  150. * @param Exception $e
  151. * @return string One line description of the passed exception.
  152. */
  153. static public function getAsSimpleText(Exception $e)
  154. {
  155. $file = $e->getFile();
  156. $line = $e->getLine();
  157. $message = $e->getMessage();
  158. $code = $e->getCode();
  159. $errorClass = get_class($e);
  160. $output = $$errorClass . '(' . $code . '): "' . $message;
  161. $output .= '" in file: ' . $file . ':' . $line;
  162. return $output;
  163. }
  164. /**
  165. * Returns an extended description of the exception, typically used for cli output although it can also be used
  166. * inside applications for extended logging.
  167. *
  168. * @param Exception $e
  169. * @return string Extended breakdown of exception, including the stack trace.
  170. */
  171. static public function getAsText(Exception $e)
  172. {
  173. // Add header
  174. $output = PHP_EOL . '*****' . PHP_EOL;;
  175. $file = $e->getFile();
  176. $line = $e->getLine();
  177. $message = $e->getMessage();
  178. $code = $e->getCode();
  179. $errorClass = get_class($e);
  180. $program = defined('PROGRAM') ? PROGRAM . ': ' : '';
  181. $output .= '* ' . $program . $errorClass . '(' . $code . '): ' . $message . PHP_EOL;
  182. $output .= '* in ' . $file . ' on line ' . $line . PHP_EOL;
  183. // Add Call Stack
  184. $stack = array_reverse($e->getTrace());
  185. if(isset($stack[0]))
  186. {
  187. $output .= '*' . PHP_EOL;
  188. $output .= '* Call Stack:' . PHP_EOL;
  189. }
  190. foreach($stack as $index => $line)
  191. {
  192. $function = '';
  193. if(isset($line['class']))
  194. $function = $line['class'] . $line['type'];
  195. $function .= $line['function'];
  196. if(isset($line['args']) && count($line['args']) > 0)
  197. {
  198. $argString = '';
  199. foreach($line['args'] as $argument)
  200. {
  201. $argString .= is_object($argument) ? get_class($argument) : $argument;
  202. $argString .= ', ';
  203. }
  204. $argString = rtrim($argString, ', ');
  205. $function .= '(' . $argString . ')';
  206. }else{
  207. $function .= '()';
  208. }
  209. $output .= '* ' . ($index + 1) . '. ' . $function . PHP_EOL;
  210. if(isset($line['file']) && isset($line['line']))
  211. $output .= '* ' . $line['file'] . ':' . $line['line'] . PHP_EOL;
  212. $output .= '*' . PHP_EOL;
  213. }
  214. return $output . '*****';
  215. }
  216. /**
  217. * Returns an extended description of the exception formatted in html, typically used to output errors by the
  218. * handleError function when display logging is enabled.
  219. *
  220. * @param Exception $e
  221. * @return string Extended breakdown of exception formatted in html.
  222. */
  223. static public function getAsHtml(Exception $e)
  224. {
  225. $file = $e->getFile();
  226. $line = $e->getLine();
  227. $message = $e->getMessage();
  228. $code = $e->getCode();
  229. $errorClass = get_class($e);
  230. $output = "<font size='1'><table class='Core-error' dir='ltr' border='1' cellspacing='0' cellpadding='2'>
  231. <tr><th align='left' bgcolor='#f57900' colspan='4'>( ! ) " . $errorClass . ": {$message} in <br>{$file} on line <i>{$line}</i></th></tr>
  232. <tr>
  233. <td colspan='3' cellspacing='0' cellpadding='0'>
  234. <table class='Core-error' dir='ltr' border='1' cellspacing='0' cellpadding='2' width='100%'>
  235. <th align='left' bgcolor='#e9b96e' colspan='3'>Call Stack</th></tr>
  236. <tr>
  237. <th align='center' bgcolor='#eeeeec'>#</th>
  238. <!--<th align='center' bgcolor='#eeeeec'>Time</th>-->
  239. <th align='left' bgcolor='#eeeeec'>Function</th>
  240. <th align='left' bgcolor='#eeeeec'>Location</th>
  241. </tr>";
  242. $stack = array_reverse($e->getTrace());
  243. $x = 0;
  244. foreach($stack as $traceLine)
  245. {
  246. $x++;
  247. if(is_array($traceLine['args']))
  248. {
  249. $argValueShort = '';
  250. $argString = '';
  251. $argStringLong = '';
  252. $comma = ' ';
  253. foreach($traceLine['args'] as $argName => $argValue)
  254. {
  255. if(is_string($argValue))
  256. {
  257. }elseif(is_object($argValue)){
  258. $argValue = get_class($argValue);
  259. }
  260. if(is_array($argValue))
  261. $argValue = var_export($argValue, true);
  262. $argString .= $comma .( (strlen($argValue) > '8') ? substr($argValue, '0', 6) . '..' : $argValue);
  263. $argStringLong .= $comma . $argValue;
  264. $comma = ', ';
  265. }
  266. $argString = rtrim($argString, ',');
  267. $argStringLong = rtrim($argStringLong, ',');
  268. }else{
  269. $argString = ' ';
  270. }
  271. if((isset($traceLine['file'])))
  272. {
  273. $shortPath = defined('BASE_PATH') ? str_replace(BASE_PATH, '/', $traceLine['file']) : $traceLine['file'];
  274. }else{
  275. $shortPath = 'Global';
  276. $traceLine['file'] = '';
  277. $traceLine['line'] = '';
  278. }
  279. $functionName = '';
  280. if(isset($traceLine['class']))
  281. $functionName .= $traceLine['class'];
  282. if(isset($traceLine['type']))
  283. $functionName .= $traceLine['type'];
  284. $functionName .= $traceLine['function'];
  285. $output .= "<tr>
  286. <td bgcolor='#eeeeec' align='center'>$x</td>
  287. <!--<td bgcolor='#eeeeec' align='center'>Time</td>-->
  288. <td title='{$functionName}({$argStringLong})' bgcolor='#eeeeec'>{$functionName}({$argString})</td>
  289. <td title='{$traceLine['file']}' bgcolor='#eeeeec'>{$shortPath}<b>:</b>{$traceLine['line']}</td>
  290. </tr>";
  291. }
  292. $output .= '</table></font>
  293. </td></tr></table>
  294. <br>';
  295. return $output;
  296. }
  297. }
  298. /**
  299. * MortarError
  300. *
  301. * This class corresponds to the E_ERROR error level in php, meaning that when E_ERROR is enabled by php (whether by the
  302. * php.ini file or a runtime configuration change) then it will check to see if error logging or displaying are also
  303. * activated, and if so will take the appropriate action.
  304. */
  305. class MortarError extends MortarException { protected $errorType = E_ERROR; }
  306. /**
  307. * MortarWarning
  308. *
  309. * This class corresponds to the E_WARNING error level in php, meaning that when E_WARNING is enabled by php (whether by
  310. * the php.ini file or a runtime configuration change) then it will check to see if error logging or displaying are also
  311. * activated, and if so will take the appropriate action.
  312. */
  313. class MortarWarning extends MortarError { protected $errorType = E_WARNING; }
  314. /**
  315. * MortarNotice
  316. *
  317. * This class corresponds to the E_NOTICE error level in php, meaning that when E_NOTICE is enabled by php (whether by
  318. * the php.ini file or a runtime configuration change) then it will check to see if error logging or displaying are also
  319. * activated, and if so will take the appropriate action.
  320. */
  321. class MortarNotice extends MortarError { protected $errorType = E_NOTICE; }
  322. /**
  323. * MortarDepreciated
  324. *
  325. * This class corresponds to the E_USER_DEPRECATED error level in php, meaning that when E_USER_DEPRECATED is enabled by
  326. * php (whether by the php.ini file or a runtime configuration change) then it will check to see if error logging or
  327. * displaying are also activated, and if so will take the appropriate action.
  328. */
  329. class MortarDepreciated extends MortarError { protected $errorType = E_USER_DEPRECATED; }
  330. /**
  331. * MortarUserError
  332. *
  333. * This class corresponds to the E_USER_ERROR error level in php, meaning that when E_USER_ERROR is enabled by php
  334. * (whether by the php.ini file or a runtime configuration change) then it will check to see if error logging or
  335. * displaying are also activated, and if so will take the appropriate action.
  336. */
  337. class MortarUserError extends MortarError { protected $errorType = E_USER_ERROR; }
  338. /**
  339. * MortarError
  340. *
  341. * This class corresponds to the E_USER_WARNING error level in php, meaning that when E_USER_WARNING is enabled by php
  342. * (whether by the php.ini file or a runtime configuration change) then it will check to see if error logging or
  343. * displaying are also activated, and if so will take the appropriate action.
  344. */
  345. class MortarUserWarning extends MortarError { protected $errorType = E_USER_WARNING; }
  346. /**
  347. * MortarUserNotice
  348. *
  349. * This class corresponds to the E_USER_NOTICE error level in php, meaning that when E_USER_NOTICE is enabled by php
  350. * (whether by the php.ini file or a runtime configuration change) then it will check to see if error logging or
  351. * displaying are also activated, and if so will take the appropriate action.
  352. */
  353. class MortarUserNotice extends MortarError { protected $errorType = E_USER_NOTICE; }
  354. ?>