BackTraceExplain.php

Go to the documentation of this file.
00001 <?php
00026 class BackTraceExplain
00027 {
00041     const CONTEXT_LINES = 0;
00042 
00053     const SHOW_ARGUMENT_VALUE = false;
00054 
00063     protected static $aFileContent = array();
00064 
00072     protected static $iExplainId = 0;
00073 
00081     protected $iStartLevel = 0;
00082 
00090     protected $oBackTrace = null;
00091 
00099     protected $sScriptFunctionName = "";
00100 
00104     protected function __construct(){}
00105 
00118     protected function fetchArguments()
00119     {
00120         $aArgument = $this->oBackTrace->getArguments();
00121         if ( count( $aArgument ) == 0 )
00122         {
00123             return array();
00124         }
00125         $aReturn = array();
00126         foreach ( $aArgument as $mArgument )
00127         {
00128             switch( gettype( $mArgument ) )
00129             {
00130                 case "array":
00131                     $sSummary = "array( " . count( $mArgument ) . " )";
00132                     break;
00133                 case "boolean":
00134                     $sSummary = $mArgument == true ? "true" : "false";
00135                     break;
00136                 case "double":
00137                 case "integer":
00138                     $sSummary = self::SHOW_ARGUMENT_VALUE == true ? (string) $mArgument : "integer";
00139                     break;
00140                 case "NULL":
00141                     $sSummary = "null";
00142                     break;
00143                 case "object":
00144                     $sSummary = "object( " . htmlentities( get_class( $mArgument ) ) . " )";
00145                     break;
00146                 case "resource":
00147                     $sSummary = "resource( " . htmlentities( strstr( $mArgument, "#" ) . " " . get_resource_type( $mArgument ) ) . " )";
00148                     break;
00149                 case "string":
00150                     if ( self::SHOW_ARGUMENT_VALUE == true )
00151                     {
00152                         if ( strlen( $mArgument ) > 15 )
00153                         {
00154                             $mArgument = substr( $mArgument, 0, 12 ) . "...";
00155                         }
00156                         $sSummary = htmlentities( "\"" . $mArgument . "\"" );
00157                     }
00158                     else
00159                     {
00160                         $sSummary = "string( " . strlen( $mArgument ) . " )";
00161                     }
00162                     break;
00163                 default:
00164                     $sSummary = "unknown type " . htmlentities( gettype( $mArgument ) );
00165                     break;
00166             }
00167             array_push( $aReturn, $sSummary );
00168         }
00169         return $aReturn;
00170     }
00171 
00179     protected function fetchCall()
00180     {
00181         if ( $this->oBackTrace->getScope() == BackTrace::SCOPE_FILE )
00182         {
00183             return "";
00184         }
00185         $iLevel = self::$iExplainId + $this->oBackTrace->getLevel();
00186         $sAnchor = "";
00187         $sArgument = "";
00188         foreach ( $this->fetchArguments() as $sSummary )
00189         {
00190             $sArgument .= ", " . $sSummary;
00191         }
00192         if ( $sArgument != "" )
00193         {
00194             $sArgument = substr( $sArgument, 1 ) . " ";
00195         }
00196         $sClass = $this->oBackTrace->getClass();
00197         $sType = $this->oBackTrace->getType();
00198         $sFunction = $this->oBackTrace->getFunction();
00199         return htmlentities( $sClass . $sType . $sFunction ) . "(" . $sArgument . ")";
00200     }
00201 
00209     protected function fetchLevel()
00210     {
00211         $sLocation = htmlentities( $this->oBackTrace->getFile() ) . " on line " . $this->oBackTrace->getLine();
00212         $sSource = $this->fetchSource();
00213         $sSourceId = "BackTraceExplainSource" . ( self::$iExplainId + $this->oBackTrace->getLevel() );
00214         if ( $sSource != "" )
00215         {
00216             $sLocation =
00217                 "<a href=\"\" onclick=\"this.blur(); " . $this->sScriptFunctionName . "( '" . $sSourceId . "' ); return false;\">" .
00218                     $sLocation .
00219                 "</a>";
00220         }
00221         return
00222             "<div class=\"traceCall\">" .
00223                 $this->fetchCall() .
00224             "</div>" .
00225             "<div class=\"traceLocation\">" .
00226                 $sLocation .
00227             "</div>" .
00228             "<div class=\"traceSource\" id=\"" . $sSourceId . "\">" .
00229                 $sSource .
00230             "</div>";
00231     }
00232 
00247     protected function fetchSource()
00248     {
00249         $sFile = $this->oBackTrace->getFile();
00250         if ( self::CONTEXT_LINES == 0 || file_exists( $sFile ) == false || is_readable( $sFile ) == false )
00251         {
00252             return "";
00253         }
00254         # verifica se existe cache
00255         if ( array_key_exists( $sFile, self::$aFileContent ) == false )
00256         {
00257             self::$aFileContent[$sFile] = substr( highlight_string( file_get_contents( $sFile ), true ), 6, -7 );
00258         }
00259         $sSource = "";
00260         $aLine = explode( "<br />", self::$aFileContent[$sFile] );
00261         $iLine = $this->oBackTrace->getLine();
00262         # define linha inicial e final a ser exibida
00263         if ( self::CONTEXT_LINES < 0 )
00264         {
00265             $iLineStart = 1;
00266             $iLineEnd = count( $aLine );
00267         }
00268         else
00269         {
00270             $fEdge = ( self::CONTEXT_LINES - 1 ) / 3;
00271             $iLineStart = $iLine - ceil( $fEdge * 2 );
00272             $iLineEnd = $iLine + floor( $fEdge );
00273             if ( $iLineStart < 1 )
00274             {
00275                 $iLineEnd += abs( $iLineStart ) + 1;
00276                 $iLineStart = 1;
00277             }
00278             $iSourceLength = count( $aLine );
00279             if ( $iLineEnd > $iSourceLength )
00280             {
00281                 $iLineStart -= $iLineEnd - $iSourceLength;
00282                 if ( $iLineStart < 1 )
00283                 {
00284                     $iLineStart = 1;
00285                 }
00286                 $iLineEnd = $iSourceLength;
00287             }
00288         }
00289         # monta texto de deteção da primeira linha, que precisa de tratamento especial
00290         $sFirstLineDetect = "<span style=\"color: #000000\">\n<span style=\"color: #0000BB\">";
00291         $iFirstLineDetectLength = strlen( $sFirstLineDetect );
00292         # percorre linhas de código
00293         foreach ( $aLine as $iCurrentLine => $sLineContent )
00294         {
00295             # trata linha corrente para contagem iniciar no número 1
00296             $iCurrentLine++;
00297             # verifica se linha deve estar visível
00298             if ( $iCurrentLine < $iLineStart || $iCurrentLine > $iLineEnd )
00299             {
00300                 # remove todo conteúdo que existir entre duas marcações HTML
00301                 $aMatch = array();
00302                 preg_match_all( "(<[^>]+>)", $sLineContent, $aMatch );
00303                 if ( count( $aMatch ) > 0 && is_array( $aMatch[0] ) === true )
00304                 {
00305                     $sLineContent = str_replace( array( "<br/>", "&nbsp;", "\n" ), "", implode( "", $aMatch[0] ) );
00306                 }
00307             }
00308             else
00309             {
00310                 # verifica se é a primeira linha
00311                 if ( substr( $sLineContent, 0, $iFirstLineDetectLength ) === $sFirstLineDetect )
00312                 {
00313                     # retira o prefixo para evitar erros de tratamento do código
00314                     # o prefixo é adiciona de volta a linha ao final do tratamento da linha atual
00315                     $sLineContent = substr( $sLineContent, $iFirstLineDetectLength );
00316                     $sLinePrefix = $sFirstLineDetect;
00317                 }
00318                 else
00319                 {
00320                     $sLinePrefix = "";
00321                 }
00322                 # prepara linha para que ela receba a numeração com uma classe de estilo
00323                 # adiciona uma quebra de linha visível ao final da linha
00324                 $sLineContent = "</span>" . $sLineContent . "<br/>";
00325                 # verifica se linha deve ser destacada
00326                 if ( $iCurrentLine !== $iLine )
00327                 {
00328                     $sClass = "traceNumberLineOff";
00329                 }
00330                 else
00331                 {
00332                     # destaca número da linha
00333                     # adiciona classe de estilo para destaque de todo conteúdo da linha
00334                     $sClass = "traceNumberLineOn";
00335                     $sLineContent = preg_replace( "/>([^<]*)</", "><span class=\"traceLineActive\">$1</span><", $sLineContent );
00336                 }
00337                 $sLineContent =
00338                     $sLinePrefix .
00339                     "<span class=\"" . $sClass . "\">" .
00340                         sprintf( "%0" . strlen( $iLineEnd ) . "d", $iCurrentLine ) .
00341                         $sLineContent;
00342             }
00343             $sSource .= $sLineContent;
00344         }
00345         return $sSource;
00346     }
00347 
00359     public static function perform( BackTrace $oBackTrace = null )
00360     {
00361         if ( $oBackTrace == null )
00362         {
00363             $oBackTrace = new BackTrace();
00364             $oBackTrace->levelDown();
00365         }
00366         $iOriginalLevel = $oBackTrace->getLevel();
00367         $oExplain = new self();
00368         $oExplain->oBackTrace = $oBackTrace;
00369         $oExplain->iStartLevel = $oBackTrace->getLevel();
00370         $oExplain->sScriptFunctionName = "BackTraceExplainFunction" . self::$iExplainId;
00371         $sTrace = "";
00372         do
00373         {
00374             $sTrace .=
00375                 "<li class=\"traceLevel\">" .
00376                     $oExplain->fetchLevel() .
00377                 "</li>";
00378         }
00379         while ( $oBackTrace->levelDown() == true );
00380         self::$iExplainId += $oBackTrace->getLevel() - $iOriginalLevel + 1;
00381         $oBackTrace->setLevel( $iOriginalLevel );
00382         $sDir = dirname( __FILE__ ) . "/resource/";
00383         return
00384             "<style type=\"text/css\">" .
00385                 file_get_contents( $sDir . "style.css" ) .
00386             "</style>" .
00387             "<script type=\"text/javascript\">" .
00388                 str_replace( "_TRACE_FUNCTION_", $oExplain->sScriptFunctionName, file_get_contents( $sDir . "script.js" ) ) .
00389             "</script>" .
00390             "<ol class=\"trace\">" .
00391                 $sTrace .
00392             "</ol>";
00393     }
00394 }

Generated on Thu Feb 3 03:54:59 2011 for CodeToDiagram by  doxygen 1.5.9