From 13495b462f6a618530f0f6af71fb6fad6bafed91 Mon Sep 17 00:00:00 2001 From: xue <> Date: Fri, 2 Mar 2007 21:05:38 +0000 Subject: Improved error display. --- framework/Exceptions/TErrorHandler.php | 99 ++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 23 deletions(-) (limited to 'framework/Exceptions/TErrorHandler.php') diff --git a/framework/Exceptions/TErrorHandler.php b/framework/Exceptions/TErrorHandler.php index 14c824c9..869ccb00 100644 --- a/framework/Exceptions/TErrorHandler.php +++ b/framework/Exceptions/TErrorHandler.php @@ -207,39 +207,34 @@ class TErrorHandler extends TModule */ protected function displayException($exception) { - $fileName=$exception->getFile(); - $errorLine=$exception->getLine(); - if($exception instanceof TPhpErrorException) + + if($exception instanceof TTemplateException) { - // if PHP exception, we want to show the 2nd stack level context - // because the 1st stack level is of little use (it's in error handler) - $trace=$exception->getTrace(); - if(isset($trace[1]) && isset($trace[1]['file']) && isset($trace[1]['line'])) - { - $fileName=$trace[1]['file']; - $errorLine=$trace[1]['line']; - } + $fileName=$exception->getTemplateFile(); + $lines=empty($fileName)?explode("\n",$exception->getTemplateSource()):@file($fileName); + $source=$this->getSourceCode($lines,$exception->getLineNumber()); + if($fileName==='') + $fileName='---embedded template---'; + $errorLine=$exception->getLineNumber(); } - $lines=file($fileName); - - $beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0; - $endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines); - - $source=''; - for($i=$beginLine;$i<$endLine;++$i) + else { - if($i===$errorLine-1) + if(($trace=$this->getExactTrace($exception))!==null) { - $line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); - $source.="
".$line."
"; + $fileName=$trace['file']; + $errorLine=$trace['line']; } else - $source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); + { + $fileName=$exception->getFile(); + $errorLine=$exception->getLine(); + } + $source=$this->getSourceCode(@file($fileName),$errorLine); } $tokens=array( '%%ErrorType%%' => get_class($exception), - '%%ErrorMessage%%' => htmlspecialchars($exception->getMessage()), + '%%ErrorMessage%%' => $this->addLink(htmlspecialchars($exception->getMessage())), '%%SourceFile%%' => htmlspecialchars($fileName).' ('.$errorLine.')', '%%SourceCode%%' => $source, '%%StackTrace%%' => htmlspecialchars($exception->getTraceAsString()), @@ -254,6 +249,64 @@ class TErrorHandler extends TModule die("Unable to open exception template file '$exceptionFile'."); echo strtr($content,$tokens); } + + private function getExactTrace($exception) + { + $trace=$exception->getTrace(); + $result=null; + // if PHP exception, we want to show the 2nd stack level context + // because the 1st stack level is of little use (it's in error handler) + if($exception instanceof TPhpErrorException) + $result=$trace[1]; + else if($exception instanceof TInvalidOperationException) + { + // in case of getter or setter error, find out the exact file and row + if(($result=$this->getPropertyAccessTrace($trace,'__get'))===null) + $result=$this->getPropertyAccessTrace($trace,'__set'); + } + if($result!==null && strpos($result['file'],': eval()\'d code')!==false) + return null; + + return $result; + } + + private function getPropertyAccessTrace($trace,$pattern) + { + $result=null; + foreach($trace as $t) + { + if(isset($t['function']) && $t['function']===$pattern) + $result=$t; + else + break; + } + return $result; + } + + private function getSourceCode($lines,$errorLine) + { + $beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0; + $endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines); + + $source=''; + for($i=$beginLine;$i<$endLine;++$i) + { + if($i===$errorLine-1) + { + $line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); + $source.="
".$line."
"; + } + else + $source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); + } + return $source; + } + + private function addLink($message) + { + $baseUrl='http://www.pradosoft.com/docs/classdoc'; + return preg_replace('/(T[A-Z]\w+)/',"\${1}",$message); + } } ?> \ No newline at end of file -- cgit v1.2.3