PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/FirePHP/library/FirePHP/Rep/PHP/Error.php

http://firephp.googlecode.com/
PHP | 388 lines | 303 code | 69 blank | 16 comment | 72 complexity | ab60c055daef6f4e032ea0c569ceefe4 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT, Apache-2.0
  1. <?php
  2. class FirePHP_Rep_PHP_Error extends FirePHP_Rep
  3. {
  4. protected $_errorNames = array(
  5. 1 => 'E_ERROR',
  6. 2 => 'E_WARNING',
  7. 4 => 'E_PARSE',
  8. 8 => 'E_NOTICE',
  9. 16 => 'E_CORE_ERROR',
  10. 32 => 'E_CORE_WARNING',
  11. 64 => 'E_COMPILE_ERROR',
  12. 128 => 'E_COMPILE_WARNING',
  13. 256 => 'E_USER_ERROR',
  14. 512 => 'E_USER_WARNING',
  15. 1024 => 'E_USER_NOTICE',
  16. 2048 => 'E_STRICT',
  17. 4096 => 'E_RECOVERABLE_ERROR',
  18. 8192 => 'E_DEPRECATED',
  19. 16384 => 'E_USER_DEPRECATED',
  20. 30719 => 'E_ALL');
  21. protected $_colorizer = null;
  22. /*
  23. $message = array();
  24. $message['errno'] = $errno;
  25. $message['errstr'] = $errstr;
  26. $message['errfile'] = $errfile;
  27. $message['errline'] = $errline;
  28. $message['errcontext'] = $errcontext;
  29. $message['backtrace'] = debug_backtrace();
  30. */
  31. public function toString()
  32. {
  33. $this->_colorizer = new Zend_Tool_Framework_Client_Console_ResponseDecorator_Colorizer();
  34. $string = array();
  35. $string[] = array(array('LINE','bgRed'));
  36. $string[] = array(array($this->_data['errstr'],array('hiWhite','bgRed')),
  37. array('SPACER', 'bgRed'),
  38. array(' | ' . $this->_error2string($this->_data['errno']),'bgRed'));
  39. $string[] = array(array('LINE','bgRed'));
  40. $insertCodeOffset = null;
  41. if(isset($this->_data['backtrace'])) {
  42. $table = new Console_Table(CONSOLE_TABLE_ALIGN_LEFT, '');
  43. $index = 1;
  44. for( $i=0 ; $i<sizeof($this->_data['backtrace']) ; $i++ ) {
  45. $frame = $this->_data['backtrace'][$i];
  46. $row = array();
  47. if($i==0) {
  48. // We are dealing with an exception
  49. if(is_string($this->_data['errno'])) {
  50. $table->addRow(array(' | ' . $this->_normalizeFilePath($this->_data['errfile']),
  51. '@ ' . $this->_data['errline']));
  52. } else
  53. // We are dealing with an error
  54. if($frame['class']=='FirePHP_Error_Handler') {
  55. $i++;
  56. if(!isset($frame['file']) && !isset($frame['line'])) {
  57. $frame = $this->_data['backtrace'][$i];
  58. }
  59. $row[] = ' | ' . $this->_normalizeFilePath($frame['file']);
  60. $row[] = '@ ' . $frame['line'];
  61. } else {
  62. throw new Exception('Could not determine where to insert code!');
  63. }
  64. }
  65. if(!$row) {
  66. if(!isset($frame['file'])) {
  67. // This is a call_user_func*() call frame
  68. if(sizeof($this->_data['backtrace'])>=$i+1) {
  69. $frameNext = $this->_data['backtrace'][$i+1];
  70. $row[] = ' | ' . $this->_normalizeFilePath($frameNext['file']);
  71. $row[] = '@ ' . $frameNext['line'];
  72. $row[] = '- call_user_func*(\''.$frame['class'].'\',\''.$frame['function'].'\')';
  73. $i++;
  74. }
  75. } else {
  76. $row[] = ' | ' . $this->_normalizeFilePath($frame['file']);
  77. $row[] = '@ ' . $frame['line'];
  78. $row[] = '- ' . ((isset($frame['type']))?
  79. $frame['class'] . $frame['type'] . $frame['function']:
  80. $frame['function']) . '('.$this->_renderArgs($frame['args']).')';
  81. }
  82. }
  83. $table->addRow($row);
  84. $index++;
  85. }
  86. $insertCodeOffset = sizeof($string)+1;
  87. foreach( explode("\n", $table->getTable()) as $line ) {
  88. if($line = rtrim($line)) {
  89. $string[] = rtrim($line);
  90. }
  91. }
  92. }
  93. if(isset($this->_data['errfile']) && isset($this->_data['errline'])) {
  94. $code = array();
  95. $code[] = ' |';
  96. $start = $this->_data['errline'] - 5;
  97. if($start<0) {
  98. $start = 0;
  99. }
  100. // TODO: Make number of lines configurable
  101. $end = $start + 10;
  102. $lines = file($this->_data['errfile']);
  103. if($end>=sizeof($lines)) {
  104. $end = sizeof($lines)-1;
  105. }
  106. for( $i=$start ; $i <= $end ; $i++ ) {
  107. $errorLine = ($i+1==$this->_data['errline']);
  108. $lines[$i] = str_replace("\t", ' ', rtrim($lines[$i]));
  109. $code[] = str_pad($i+1,4,' ',STR_PAD_LEFT). (($errorLine)?'|>':'| ') . $lines[$i];
  110. // See if we have annotated arguments on previous lines and insert them
  111. if($errorLine &&
  112. ($vars = FirePHP_Annotator::getVariables())) {
  113. for( $j=sizeof($code)-1 ; $j>=sizeof($code)-4 ; $j-- ) {
  114. if(($pos=strpos($code[$j], 'FirePHP_Annotator::setVariables('))!==false) {
  115. $varLines = array();
  116. $varLines[] = '';
  117. foreach( $vars as $name => $value ) {
  118. $varLines[] = ' :' . str_repeat(' ',$pos-1) . $name . ' = ' . $this->_renderVar($value, 70);
  119. }
  120. $varLines[] = '';
  121. array_splice($code, $j+1, 0, $varLines);
  122. break;
  123. }
  124. }
  125. }
  126. }
  127. $code[] = ' |';
  128. if($insertCodeOffset!==null) {
  129. array_splice($string, $insertCodeOffset, 0, $code);
  130. } else {
  131. array_splice($string, sizeof($string), 0, $code);
  132. }
  133. }
  134. $string[] = array(array('LINE','bgRed'));
  135. $string[] = array('RIGHT', array('Generated by FirePHP: http://www.firephp.org/','cyan'));
  136. $this->_markupOutput($string);
  137. return implode("\n", $string);
  138. }
  139. public function shouldDisplay()
  140. {
  141. if(isset($this->_data['backtrace']) &&
  142. substr($this->_data['backtrace'][0]['file'],-16,16)=='/Zend/Loader.php' &&
  143. (
  144. preg_match_all('/^include\([^)]*\): failed to open stream: No such file or directory$/si', $this->_data['errstr'], $m) ||
  145. preg_match_all('/^include\(\): Failed opening \'[^\']*\' for inclusion \([^)]*\)$/si', $this->_data['errstr'], $m)
  146. )
  147. ) {
  148. return false;
  149. }
  150. return true;
  151. }
  152. protected function _markupOutput(&$string)
  153. {
  154. $lines = array();
  155. $maxLength = 0;
  156. for( $i=0 ; $i<sizeof($string) ; $i++ ) {
  157. $maxLength = max($maxLength, $this->_lineLength($string[$i]));
  158. }
  159. $border = array('|', 'bgRed');
  160. for( $i=0 ; $i<sizeof($string) ; $i++ ) {
  161. if(is_array($string[$i])) {
  162. if(sizeof($string[$i])==1 &&
  163. (extract($this->_normalizeSegment($string[$i][0]))) &&
  164. $part=='LINE') {
  165. if($i==0 || $i+1==sizeof($string)) {
  166. $string[$i] = $this->_markupLine(array(array(str_repeat('-', $maxLength+4), $color)));
  167. } else {
  168. $string[$i] = $this->_markupLine(array($border, $this->_markupLine(array(array(str_repeat('-', $maxLength+2), $color))) , $border));
  169. }
  170. } else
  171. if(sizeof($string[$i])==2 && $string[$i][0]=='RIGHT') {
  172. $string[$i] = $this->_markupLine(array($border, ' ', str_repeat(' ', $maxLength-$this->_lineLength($string[$i])) .
  173. $this->_markupLine(array($string[$i][1])), ' ' , $border));
  174. } else {
  175. for( $j=0 ; $j<sizeof($string[$i]) ; $j++ ) {
  176. $part = $string[$i][$j];
  177. if((is_string($part) && $part=='SPACER') ||
  178. (is_array($part) && $part[0]=='SPACER')) {
  179. $before = array_slice($string[$i], 0, $j);
  180. $after = array_slice($string[$i], $j+1);
  181. extract($this->_normalizeSegment($part));
  182. $padLength = $maxLength - $this->_lineLength($before) - $this->_lineLength($after);
  183. if($padLength<0) {
  184. $padLength = 0;
  185. }
  186. $string[$i] = $this->_markupLine(array($border, $this->_markupLine(array(array(' ',$color))), $this->_markupLine($before) .
  187. $this->_markupLine(array(array(str_repeat(' ', $padLength), $color))) .
  188. $this->_markupLine($after) , $this->_markupLine(array(array(' ',$color))), $border));
  189. }
  190. }
  191. }
  192. } else {
  193. $string[$i] = $this->_markupLine(array($border,' ', str_pad($string[$i], $maxLength, ' ', STR_PAD_RIGHT), ' ' , $border));
  194. }
  195. }
  196. }
  197. protected function _markupLine($line)
  198. {
  199. if(is_string($line)) {
  200. return $line;
  201. } else
  202. if(is_array($line)) {
  203. for( $i=0 ; $i<sizeof($line) ; $i++ ) {
  204. extract($this->_normalizeSegment($line[$i]));
  205. if($color!==null) {
  206. $line[$i] = $this->_colorizer->decorate($part, $color);
  207. }
  208. }
  209. return join($line);
  210. }
  211. }
  212. protected function _normalizeSegment($segment) {
  213. if(is_string($segment)) {
  214. return array('part'=>$segment, 'color'=> null);
  215. } else {
  216. return array('part'=>$segment[0], 'color'=> $segment[1]);
  217. }
  218. }
  219. protected function _lineLength($line)
  220. {
  221. if(is_string($line)) {
  222. return strlen($line);
  223. } else
  224. if(is_array($line)) {
  225. $length = 0;
  226. foreach( $line as $part ) {
  227. if(is_string($part)) {
  228. if(!in_array($part, array('LINE', 'RIGHT', 'SPACER'))) {
  229. $length += strlen($part);
  230. }
  231. } else
  232. if(is_array($part)) {
  233. if(!in_array($part[0], array('LINE', 'RIGHT', 'SPACER'))) {
  234. $length += strlen($part[0]);
  235. }
  236. }
  237. }
  238. return $length;
  239. }
  240. }
  241. protected function _renderArgs($args)
  242. {
  243. if(!$args) {
  244. return '';
  245. }
  246. $string = array();
  247. foreach( $args as $arg ) {
  248. $string[] = $this->_renderVar($arg);
  249. }
  250. return implode(',', $string);
  251. }
  252. protected function _renderVar($var, $length=20)
  253. {
  254. if(is_null($var)) {
  255. return 'NULL';
  256. } else
  257. if(is_bool($var)) {
  258. return ($var)?'TRUE':'FALSE';
  259. } else
  260. if(is_int($var) || is_float($var) || is_double($var)) {
  261. return $this->_trimString((string)$var, $length);
  262. } else
  263. if(is_object($var)) {
  264. return $this->_trimString(get_class($var), $length);
  265. } else
  266. if(is_array($var)) {
  267. return $this->_trimString(serialize($var), $length);
  268. } else
  269. if(is_resource($var)) {
  270. return $this->_trimString($var);
  271. } else
  272. if(is_string($var)) {
  273. return '\'' . $this->_trimString($var, $length) . '\'';
  274. } else {
  275. return '\'' . $this->_trimString($var, $length) . '\'';
  276. }
  277. }
  278. protected function _trimString($string, $length=20)
  279. {
  280. if(strlen($string)<=$length+3) {
  281. return $string;
  282. }
  283. return substr($string, 0, $length) . '...';
  284. }
  285. protected function _normalizeFilePath($path)
  286. {
  287. foreach( explode(PATH_SEPARATOR, get_include_path()) as $include_path ) {
  288. // For now we shorten paths based on the include paths
  289. // TODO: Provide an option not to shorten paths
  290. if( substr($path, 0, strlen($include_path)) == $include_path ) {
  291. return '..' . substr($path, strlen($include_path));
  292. }
  293. }
  294. return $path;
  295. }
  296. protected function _error2string($errorLevels)
  297. {
  298. return implode(' | ', $this->_error2array($errorLevels));
  299. }
  300. protected function _error2array($errorLevels)
  301. {
  302. $names = array();
  303. if(is_string($errorLevels)) {
  304. $names[] = $errorLevels;
  305. } else {
  306. if( ( $errorLevels & E_ALL ) == E_ALL)
  307. {
  308. $levels[] = 'E_ALL';
  309. $errorLevels &= ~E_ALL;
  310. }
  311. foreach( $this->_errorNames as $level => $name) {
  312. if( ($errorLevels & $level) == $level ) {
  313. $names[] = $name;
  314. }
  315. }
  316. }
  317. return $names;
  318. }
  319. }