Skip to content

Commit 51cf157

Browse files
author
joseph lenton
committed
JosephLenton#19 nested exceptions support
1 parent db7968e commit 51cf157

File tree

2 files changed

+142
-35
lines changed

2 files changed

+142
-35
lines changed

example/multiple_exceptions.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
require( dirname(__FILE__) . '/../src/php_error.php' );
3+
\php_error\reportErrors();
4+
5+
function a() {
6+
b();
7+
}
8+
9+
function b() {
10+
try {
11+
c();
12+
} catch ( Exception $ex ) {
13+
throw new Exception( "thrown exception", 0, $ex );
14+
}
15+
}
16+
17+
function c() {
18+
d();
19+
}
20+
21+
function d() {
22+
throw new Exception( 'blah' );
23+
}
24+
25+
a( "fooobar fooobar fooobar fooobar fooobar fooobar fooobar fooobar fooobar fooobar", "fooobar", "fooobar", "fooobar", "fooobar", "fooobar", "fooobar", "fooobar" );

src/php_error.php

Lines changed: 117 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090

9191
namespace php_error;
9292

93-
use \php_error\ErrorToExceptionException,
93+
use \php_error\ErrorException,
9494
\php_error\FileLinesSet,
9595
\php_error\ErrorHandler,
9696

@@ -1998,8 +1998,6 @@ private function parseStackTrace( $code, $message, $errLine, $errFile, &$stackTr
19981998
// parse the stack trace, and remove the long urls
19991999
foreach ( $stackTrace as $i => $trace ) {
20002000
if ( $trace ) {
2001-
$trace['info'] = '';
2002-
20032001
if ( isset($trace['line'] ) ) {
20042002
$lineLen = max( $lineLen, strlen($trace['line']) );
20052003
} else {
@@ -2008,21 +2006,13 @@ private function parseStackTrace( $code, $message, $errLine, $errFile, &$stackTr
20082006

20092007
$info = '';
20102008

2011-
if ( $i === 0 ) {
2012-
if ( $altInfo !== null ) {
2013-
$info = $altInfo;
2014-
} else if ( isset($trace['info']) && $trace['info'] !== '' ) {
2015-
$info = ErrorHandler::syntaxHighlight( $trace['info'] );
2016-
} else {
2017-
$contents = $this->getFileContents( $trace['file'] );
2018-
2019-
if ( $contents ) {
2020-
$info = ErrorHandler::syntaxHighlight(
2021-
trim( $contents[$trace['line']-1] )
2022-
);
2023-
}
2024-
}
2025-
} else {
2009+
if ( $i === 0 && $altInfo !== null ) {
2010+
$info = $altInfo;
2011+
} else if (
2012+
isset($trace['class']) ||
2013+
isset($trace['type']) ||
2014+
isset($trace['function'])
2015+
) {
20262016
$args = array();
20272017
if ( isset($trace['args']) ) {
20282018
foreach ( $trace['args'] as $arg ) {
@@ -2036,7 +2026,17 @@ private function parseStackTrace( $code, $message, $errLine, $errFile, &$stackTr
20362026
isset($trace['function']) ? $trace['function'] : null,
20372027
$args
20382028
);
2039-
}
2029+
} else if ( isset($trace['info']) && $trace['info'] !== '' ) {
2030+
$info = ErrorHandler::syntaxHighlight( $trace['info'] );
2031+
} else if ( isset($trace['file']) && !isset($trace['info']) ) {
2032+
$contents = $this->getFileContents( $trace['file'] );
2033+
2034+
if ( $contents ) {
2035+
$info = ErrorHandler::syntaxHighlight(
2036+
trim( $contents[$trace['line']-1] )
2037+
);
2038+
}
2039+
}
20402040

20412041
$trace['info'] = $info;
20422042

@@ -2111,17 +2111,31 @@ private function parseStackTrace( $code, $message, $errLine, $errFile, &$stackTr
21112111
}
21122112

21132113
if ( $highlightI === $i ) {
2114-
$cssClass .= 'highlight';
2114+
$cssClass .= ' highlight';
21152115
} else if ( $highlightI > $i ) {
2116-
$cssClass .= 'pre-highlight';
2116+
$cssClass .= ' pre-highlight';
2117+
}
2118+
2119+
if (
2120+
$i !== 0 &&
2121+
isset($trace['exception']) &&
2122+
$trace['exception']
2123+
) {
2124+
$ex = $trace['exception'];
2125+
2126+
$exHtml = '<tr class="error-stack-trace-exception"><td>' .
2127+
htmlspecialchars( $ex->getMessage() ) .
2128+
'</td></tr>';
2129+
} else {
2130+
$exHtml = '';
21172131
}
21182132

21192133
$data = '';
21202134
if ( isset($trace['file-lines-id']) ) {
21212135
$data = 'data-file-lines-id="' . $trace['file-lines-id'] . '"';
21222136
}
21232137

2124-
$stackTrace[$i] = "<tr class='error-stack-trace-line $cssClass' $data>$stackStr</tr>";
2138+
$stackTrace[$i] = "$exHtml<tr class='error-stack-trace-line $cssClass' $data>$stackStr</tr>";
21252139
}
21262140
}
21272141

@@ -2131,7 +2145,7 @@ private function parseStackTrace( $code, $message, $errLine, $errFile, &$stackTr
21312145
}
21322146
}
21332147

2134-
private function logError( $message, $file, $line, $ex=null, $stack=null ) {
2148+
private function logError( $message, $file, $line, $ex=null ) {
21352149
if ( $ex ) {
21362150
$trace = $ex->getTraceAsString();
21372151
$parts = explode( "\n", $trace );
@@ -2151,7 +2165,7 @@ private function logError( $message, $file, $line, $ex=null, $stack=null ) {
21512165
* so you will get a full stack trace.
21522166
*/
21532167
public function reportClassNotFound( $className ) {
2154-
throw new ErrorToExceptionException( E_ERROR, "Class '$className' not found", __FILE__, __LINE__ );
2168+
throw new ErrorException( "Class '$className' not found", E_ERROR, E_ERROR, __FILE__, __LINE__ );
21552169
}
21562170

21572171
/**
@@ -2163,7 +2177,6 @@ public function reportException( $ex ) {
21632177
$ex->getMessage(),
21642178
$ex->getLine(),
21652179
$ex->getFile(),
2166-
$ex->getTrace(),
21672180
$ex
21682181
);
21692182
}
@@ -2179,9 +2192,9 @@ public function reportException( $ex ) {
21792192
* even when it's disabled with ini. It just does nothing
21802193
* more than that.
21812194
*/
2182-
public function reportError( $code, $message, $errLine, $errFile, $stackTrace=null, $ex=null ) {
2195+
public function reportError( $code, $message, $errLine, $errFile, $ex=null ) {
21832196
if (
2184-
$stackTrace === null &&
2197+
$ex === null &&
21852198
$code === 1 &&
21862199
strpos($message, "Class ") === 0 &&
21872200
strpos($message, "not found") !== false &&
@@ -2196,14 +2209,69 @@ public function reportError( $code, $message, $errLine, $errFile, $stackTrace=nu
21962209
$stackTrace = $ex->getTrace();
21972210
}
21982211

2199-
$this->logError( $message, $errFile, $errLine, $ex, $stackTrace );
2212+
$this->logError( $message, $errFile, $errLine, $ex );
22002213

22012214
global $_php_error_is_ini_enabled;
22022215
if ( $_php_error_is_ini_enabled ) {
22032216
$root = $this->applicationRoot;
22042217

2218+
if ( $ex !== null ) {
2219+
$next = $ex;
2220+
$stackTrace = array();
2221+
$skipStacks = 0;
2222+
2223+
for (
2224+
$next = $ex;
2225+
$next !== null;
2226+
$next = $next->getPrevious()
2227+
) {
2228+
$ex = $next;
2229+
2230+
$stack = $ex->getTrace();
2231+
$file = $ex->getFile();
2232+
$line = $ex->getLine();
2233+
2234+
//if ( count($stackTrace) > 0 ) {
2235+
$stack = array_slice( $stack, 0, count($stack)-count($stackTrace) + 1 );
2236+
//}
2237+
2238+
if ( count($stack) > 0 && (
2239+
!isset($stack[0]['file']) ||
2240+
!isset($stack[0]['line']) ||
2241+
$stack[0]['file'] !== $file ||
2242+
$stack[0]['line'] !== $line
2243+
) ) {
2244+
array_unshift( $stack, array(
2245+
'file' => $file,
2246+
'line' => $line
2247+
) );
2248+
}
2249+
2250+
$stackTrace = array_merge( $stack, $stackTrace );
2251+
if ( count($stackTrace) > 0 ) {
2252+
$stackTrace[0]['exception'] = $ex;
2253+
}
2254+
}
2255+
2256+
$message = $ex->getMessage();
2257+
$errFile = $ex->getFile();
2258+
$errLine = $ex->getLine();
2259+
2260+
$code = method_exists($ex, 'getSeverity') ?
2261+
$ex->getSeverity() :
2262+
$ex->getCode() ;
2263+
}
2264+
22052265
list( $message, $srcErrFile, $srcErrLine, $altInfo ) =
2206-
$this->improveErrorMessage( $ex, $code, $message, $errLine, $errFile, $root, $stackTrace );
2266+
$this->improveErrorMessage(
2267+
$ex,
2268+
$code,
2269+
$message,
2270+
$errLine,
2271+
$errFile,
2272+
$root,
2273+
$stackTrace
2274+
);
22072275

22082276
$errFile = $srcErrFile;
22092277
$errLine = $srcErrLine;
@@ -2398,7 +2466,7 @@ function( $code, $message, $file, $line, $context ) use ( $self, &$catchSurpress
23982466
* When using an @, the error reporting drops to 0.
23992467
*/
24002468
if ( error_reporting() !== 0 || $catchSurpressedErrors ) {
2401-
$ex = new ErrorToExceptionException( $code, $message, $file, $line, $context );
2469+
$ex = new ErrorException( $message, $code, $code, $file, $line );
24022470

24032471
$self->reportException( $ex );
24042472
}
@@ -2467,7 +2535,7 @@ function( $code, $message, $file, $line, $context ) use ( $self, &$catchSurpress
24672535
}
24682536

24692537
if ( $error ) {
2470-
$classException = new ErrorToExceptionException( E_ERROR, "Class '$className' not found", __FILE__, __LINE__ );
2538+
$classException = new ErrorException( "Class '$className' not found", E_ERROR, E_ERROR, __FILE__, __LINE__ );
24712539
}
24722540
}
24732541
} );
@@ -3367,8 +3435,18 @@ function displayHTML( Closure $head, $body=null, $javascript=null ) {
33673435
line-height: 28px;
33683436
cursor: pointer;
33693437
}
3438+
.error-stack-trace-exception {
3439+
color: #b33;
3440+
}
3441+
.error-stack-trace-exception > td {
3442+
padding-top: 18px;
3443+
}
33703444
.error-stack-trace-line {
33713445
float: left;
3446+
}
3447+
.error-stack-trace-line.is-exception {
3448+
margin-top: 18px;
3449+
border-top: 1px solid #422;
33723450
}
33733451
.error-stack-trace-line:first-of-type > td:first-of-type {
33743452
border-top-left-radius: 2px;
@@ -3629,15 +3707,19 @@ function displayHTML( Closure $head, $body=null, $javascript=null ) {
36293707
}
36303708
}
36313709
}
3632-
3710+
36333711
/**
3712+
* This is a carbon copy of \ErrorException.
3713+
* However that is only supported in PHP 5.1 and above,
3714+
* so this allows PHP Error to work in PHP 5.0.
3715+
*
36343716
* A thin class that wraps up an error, into an exception.
36353717
*/
3636-
class ErrorToExceptionException extends Exception
3718+
class ErrorException extends Exception
36373719
{
3638-
public function __construct( $code, $message, $file, $line )
3720+
public function __construct( $message, $code, $severity, $file, $line )
36393721
{
3640-
parent::__construct( $message, $code );
3722+
parent::__construct( $message, $code, null );
36413723

36423724
$this->file = $file;
36433725
$this->line = $line;

0 commit comments

Comments
 (0)