PhpToolCase
Api Documentation Version 0.9.2
PtcDebug.php
Go to the documentation of this file.
1 <?php
2 
3  /**
4  * DEBUGGER & LOGGER CLASS
5  * <br>All class properties and methods are static because it's required
6  * to let them work on script shutdown when FATAL error occurs.
7  * PHP version 5.3
8  * @category Library
9  * @version 0.9.2
10  * @author Irony <carlo@salapc.com>
11  * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
12  * @link http://phptoolcase.com
13  */
14 
15  declare( ticks = 1 ); // used by the watch var , function calls trace and code coverage utilities
16 
17  class PtcDebug
18  {
19  /**
20  * Returns the buffer array
21  * @return the buffer array
22  */
23  public static function getBuffer( ) { return static::$_buffer; }
24  /**
25  * Retrieves the code coverage analysis data stored in the PtcDebug::$_finalCoverageData property
26  */
27  public static function getCoverage( ) { return static::$_finalCoverageData; }
28  /**
29  * Adds style properties to the floating panel styles array
30  * @param string $css some css to add
31  */
32  public static function addCss( $css ){ static::$_panelCss = static::$_panelCss . "\n" . $css; }
33  /**
34  * Checks if the debug "url_key" and "url_pass" are set on the referer url. See @ref check_referer
35  * @return true if "url_key" and "url_pass" are in the referer url, otherwise false
36  */
37  public static function checkReferer( )
38  {
39  if ( @array_key_exists( 'HTTP_REFERER' , @$_SERVER ) )
40  {
41  $query = parse_url( $_SERVER[ 'HTTP_REFERER' ] , PHP_URL_QUERY );
42  $params = array( );
43  parse_str( $query , $params );
44  if ( @$params[ static::$_options[ 'url_key' ] ] == static::$_options[ 'url_pass' ] )
45  {
46  $_GET[ static::$_options[ 'url_key' ] ] = $params[ static::$_options[ 'url_key' ] ];
47  return true;
48  }
49  }
50  return false;
51  }
52  /**
53  * Sets the error handler to be the debug class. good for production with "$dieOnFatal" set to false.
54  * See @ref replaceErrorHandler
55  * @param string $dieOnFatal die if fatal error occurs
56  */
57  public static function setErrorHandler( $dieOnFatal = true )
58  {
59  ini_set( 'display_errors' , false );
60  ini_set( 'html_errors' , false );
61  if ( !@static::$_options[ 'error_reporting' ] )
62  {
63  @static::$_options[ 'error_reporting' ] = static::$_defaultOptions[ 'error_reporting' ];
64  }
65  ini_set( 'error_reporting' , static::$_options[ 'error_reporting' ] );
66  @static::$_options[ 'die_on_error' ] = $dieOnFatal;
67  set_error_handler( array( get_called_class( ) , 'errorHandler' ) );
68  }
69  /**
70  * Loads the debug interface and/or the console class if requested. See @ref dbg_getting_started
71  * @param array $options array of options, see PtcDebug::$ _defaultOptions
72  */
73  public static function load( $options = null )
74  {
75  $now = microtime( true );
76  if ( defined( '_PTCDEBUG_NAMESPACE_' ) ) // check if the debug class is already loaded
77  {
78  $err = array( 'errno' => static::_msgType( E_USER_NOTICE ),
79  'errstr' => 'Debug already loaded!','errfile' => 'trace' );
80  static::_buildBuffer( 'log' , '{errorHandler}' , $err );
81  return;
82  }
83  $called_class = get_called_class( );
84  /* if error handler was called previously */
85  if ( @isset( static::$_options[ 'die_on_error' ] ) )
86  {
87  static::$_defaultOptions[ 'die_on_error' ] = static::$_options[ 'die_on_error' ];
88  }
89  if ( @isset( static::$_options[ 'error_reporting' ] ) )
90  {
91  static::$_defaultOptions[ 'error_reporting' ] = static::$_options[ 'error_reporting' ];
92  }
93  static::$_options = ( is_array( $options ) ) ?
94  array_merge( static::$_defaultOptions , $options ) : static::$_defaultOptions;
95  if ( !$has_access = static::_checkAccess( ) ){ return; } // check access with ips
96  $buffer = 'Debug Info:';
97  if ( static::$_options[ 'check_referer' ] ){ static::checkReferer( ); }// check if referer has debug vars
98  if ( static::$_options[ 'session_start' ] ) // start session on request
99  {
100  if ( session_id( ) === '' ) // check if session is already active
101  {
102  session_start( );
103  $buffer .= '<br>Initialized browser session with session_start( )';
104  }
105  else{ $buffer .= '<br>Session id is ' . session_id( ); }
106  }
107  if ( !@$_SESSION ){ $_SESSION = array( ); }
108  if ( !@$_SESSION[ 'ptcdebug' ] ){ $_SESSION[ 'ptcdebug' ] = array( ); }
109  if ( @$_GET[ static::$_options[ 'url_key' ] ] == static::$_options[ 'url_pass' ] )
110  {
111  $_SESSION[ 'ptcdebug' ][ static::$_options[ 'url_key' ] ] = true;
112  $_SESSION[ 'ptcdebug' ][ 'code_highlighter' ] = true;
113  $_SESSION[ 'ptcdebug' ][ 'search_files' ] = true;
114  //$buffer .= '<br>PtcDebug turned on!';
115  }
116  else if ( @$_GET[ static::$_options[ 'url_key' ] . '_off' ] == static::$_options[ 'url_pass' ] )
117  {
118  $_SESSION[ 'ptcdebug' ][ static::$_options[ 'url_key' ] ] = false;
119  $_SESSION[ 'ptcdebug' ][ 'code_highlighter' ] = false;
120  $_SESSION[ 'ptcdebug' ][ 'search_files' ] = false;
121  }
122  if ( static::_getSessionVars( static::$_options[ 'url_key' ] ) )
123  {
124  static::$_startTime = microtime( true );
125  if ( static::$_options[ 'set_time_limit' ] )
126  {
127  set_time_limit( static::$_options[ 'set_time_limit' ] );
128  }
129  if ( static::$_options[ 'memory_limit' ] )
130  {
131  ini_set( 'memory_limit' , static::$_options[ 'memory_limit' ] );
132  }
133  if ( static::$_options[ 'show_interface' ] || static::$_options[ 'debug_console' ] )
134  {
135  register_shutdown_function( array( $called_class , 'processBuffer' ) );
136  }
137  if ( static::$_options[ 'replace_error_handler' ] ) // replace error handler
138  {
139  static::setErrorHandler( static::$_options[ 'die_on_error' ] );
140  $buffer .= '<br>Error handler has been overridden!';
141  }
142  if ( static::$_options[ 'catch_exceptions' ] ) // set exception handler
143  {
144  set_exception_handler( array( $called_class , 'exceptionHandler' ) );
145  $buffer .= "<br>Exception Handler turned on!";
146  }
147  if ( static::$_options[ 'debug_console' ] ) // try to laod the console class
148  {
149  static::$_consoleStarted = false;
150  $buffer.='<br>Console debug turned on';
151  if ( file_exists( dirname( __FILE__ ) . '/PhpConsole/__autoload.php' ) )
152  {
153  require_once( dirname(__FILE__).'/PhpConsole/__autoload.php' );
154  static::$_consoleStarted = true;
155  \PhpConsole\Helper::register( );
156  $buffer .= ", phpConsole class started!";
157  }
158  else{ $buffer .= ', but could not find phpConsole class!'; }
159  }
160  if ( static::$_options[ 'enable_inspector' ] || static::$_options[ 'code_coverage' ] ||
161  static::$_options[ 'trace_functions' ] )
162  {
163  register_tick_function( array( $called_class , 'tickHandler' ) );
164  //if ( static::$_options[ 'declare_ticks' ] ) { declare( ticks = 1 ); }
165  $buffer .= "<br>Variables inspector enabled!";
166  }
167  if ( static::$_options[ 'code_coverage' ] === 'full' )
168  {
169  static::startCoverage( );
170  $buffer .= "<br>Code coverage analysis for all scripts enabled!";
171  }
172  if ( static::$_options[ 'trace_functions' ] === 'full' )
173  {
174  static::startTrace( );
175  $buffer .= "<br>Function calls tracing for all scripts enabled!";
176  }
177  if ( !static::_getSessionVars( 'show_messages' ) ){ static::_setSessionVars( ); }
178  if ( @$_GET[ 'hidepanels' ] ){ static::_disablePanels( ); }
179  else
180  {
181  static::$_options[ 'show_messages' ] = static::_getSessionVars( 'show_messages' );
182  static::$_options[ 'show_globals' ] = static::_getSessionVars( 'show_globals' );
183  static::$_options[ 'show_sql' ] = static::_getSessionVars( 'show_sql' );
184  static::$_options[ 'show_w3c' ] = static::_getSessionVars( 'show_w3c' );
185  }
186  @define( '_PTCDEBUG_NAMESPACE_' , $called_class );
187  static::$_tickTime = ( ( microtime( true ) - $now ) + static::$_tickTime );
188  static::bufferLog( '' , '<span>' . $buffer . '<span>' , 'Debug Loader' );
189  }
190  }
191  /**
192  * The ticks handler to execute all tickable functions
193  */
194  public static function tickHandler( )
195  {
196  //$now = microtime( true );
197  if ( static::$_codeCoverage || static::$_functionTrace ) { $bt = debug_backtrace( ); }
198  if ( static::$_disableOpcode ) // try to disable opcode cache
199  {
200  static::_disableOpcodeCache( );
201  static::$_disableOpcode = false;
202  }
203  if ( static::$_options[ 'enable_inspector' ] && count( static::$_watchedVars ) )
204  {
205  static::_watchCallback( );
206  }
207  if ( static::$_codeCoverage ) { static::_codeCoverageAnalysis( $bt ); }
208  if ( static::$_functionTrace ) { static::_traceFunctionCalls( $bt ); }
209  //if ( static::$_options[ 'profiler' ] ) { }
210  unset( $bt );
211  // FIXME: the timer goes to minus here
212  //static::$_tickTime = ( ( microtime( true ) - $now ) + static::$_tickTime );
213  }
214  /**
215  * Starts the code coverage analysis utility to find executed lines. See @ref codeCoverage
216  */
217  public static function startCoverage( )
218  {
219  if ( @static::$_options[ 'code_coverage' ] )
220  {
221  if ( static::$_codeCoverage && static::$_options[ 'code_coverage' ] !== 'full' )
222  {
223  static::bufferLog( 'Coverage already started, please use stopCoverage( )
224  before starting a new one!', '' , 'Debugger Notice' );
225  return false;
226  }
227  static::$_codeCoverage = true;
228  }
229  }
230  /**
231  * Stops the code coverage analysis utility. See @ref codeCoverage
232  */
233  public static function stopCoverage( )
234  {
235  if ( static::$_options[ 'code_coverage' ] !== 'full' )
236  {
237  static::$_codeCoverage = false;
238  if( static::$_coverageData )
239  {
240  static::$_finalCoverageData[ ] = static::$_coverageData;
241  static::$_coverageData = null;
242  }
243  }
244  }
245  /**
246  * Starts the function calls trace utility. See @ref traceFunctions
247  */
248  public static function startTrace( )
249  {
250  if ( @static::$_options[ 'trace_functions' ] )
251  {
252  if ( static::$_functionTrace && static::$_options[ 'trace_functions' ] !== 'full' )
253  {
254  static::bufferLog( 'Function calls tracing has been already started, please use stopTrace( )
255  before starting a new one!' , '' , 'Debugger Notice' );
256  return false;
257  }
258  static::$_functionTrace = true;
259  }
260  }
261  /**
262  * Stops the function calls trace utility. See @ref traceFunctions
263  */
264  public static function stopTrace( )
265  {
266  if ( static::$_options[ 'trace_functions' ] !== 'full' )
267  {
268  static::$_functionTrace = false;
269  if ( static::$_traceData )
270  {
271  static::$_finalTraceData[ ] = static::$_traceData;
272  static::$_traceData = null;
273  }
274  }
275  }
276  /**
277  * Excludes functions from the function calls tracing engine
278  * @param array | string $functions the function the exclude by their name
279  */
280  public static function excludeFromTrace( $functions )
281  {
282  $functions = ( is_array( $functions) ) ? $functions : array( $functions );
283  static::$_excludeFromTrace = array_merge( static::$_excludeFromTrace , $functions );
284  }
285  /**
286  * Watches a variable that is in a declare(ticks=n); code block, for changes. See @ref variableInspector
287  * @param string $variableName the name of the variable to watch
288  * @param string $callback a callback function that retrieves the variable
289  */
290  public static function watch( $variableName , $callback = null )
291  {
292  if ( @static::$_options[ 'enable_inspector' ] )
293  {
294  $var = ( $callback ) ? array( 'value' => $callback( ) , 'callback' => $callback ) :
295  static::_findWatchVar( $variableName );
296  static::$_watchedVars[ $variableName ] = $var;
297  $value = ( $callback ) ? call_user_func( $callback ) : static::$_watchedVars[ $variableName ];
298  static::bufferLog( $value , 'Watching variable <span style="font-weight:bold;">$' .
299  $variableName . '</span> = ' , 'Inspector' );
300  }
301  else
302  {
303  $err = array( 'errno' => static::_msgType( E_USER_NOTICE ) , 'errfile' => 'trace' ,
304  'errstr' => 'Please set to true [\'enable_inspector\'] option to be able to watch a variable' );
305  static::_buildBuffer( 'log' , '{errorHandler}' , $err );
306  }
307  }
308  /**
309  * Writes data to the messages panel. See @ref logging_data
310  * @param mixed $string the string to pass
311  * @param mixed $statement some statement if required
312  * @param string $category a category for the messages panel
313  */
314  public static function bufferLog( $string , $statement = null , $category = null )
315  {
316  static::_buildBuffer( 'log' , $string , $statement , $category );
317  }
318  /**
319  * Writes data to the sql panel. See @ref log_sql
320  * @param mixed $string the string to pass
321  * @param mixed $statement some statement if required
322  * @param string $category a category for the sql panel
323  */
324  public static function bufferSql( $string , $statement = null , $category = null )
325  {
326  static::_buildBuffer( 'sql' , $string , $statement , $category );
327  }
328  /**
329  * Monitors the execution of php code, or sql queries based on a reference. See @ref execution_timing
330  * @param string $reference a reference to look for ("$statement")
331  * @param string|numeric $precision sec/ms
332  * @return true if a given reference is found, otherwise false
333  */
334  public static function stopTimer( $reference = null , $precision = 1 )
335  {
336  $now = microtime( true );
337  $last = static::_findReference( $reference , 1 );
338  if ( !$last ){ return false; }
339  $time = ( $now - @$last[ 'data' ][ 'start_time' ] );
340  switch( $precision )
341  {
342  case 0 : // seconds
343  case 'sec' : // seconds
344  static::$_buffer[ $last[ 'key' ] ][ 'time' ] = round( $time , 3 ) . ' sec';
345  break;
346  case 1 : // millisecons
347  case 'ms' : // millisecons
348  default :
349  static::$_buffer[ $last[ 'key' ] ][ 'time' ] = round( $time * 1000 , 3 ) . ' ms';
350  break;
351  }
352  if ( static::$_options[ 'debug_console' ] )
353  {
354  static::$_buffer[ $last[ 'key' ] ][ 'console_time' ] =
355  static::$_buffer[ $last[ 'key' ] ][ 'time' ];
356  }
357  return true;
358  }
359  /**
360  * Convert memory_usage( ) into a readable format
361  * @param float $val The value to convert
362  * @param int $precision the decimal points
363  */
364  public static function convertMemUsage( $val , $precision = 2)
365  {
366  $ram = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
367  return $usage = ( $val ) ? @round( $val / pow( 1024 ,
368  ($i = floor( log( $val , 1024) ) ) ) , $precision ) . $ram[ $i ] : '0 Bytes';
369  }
370  /**
371  * Handles php errors. See @ref replaceErrorHandler
372  * @param string $errno error number (php standards)
373  * @param string $errstr error string
374  * @param string $errfile error file
375  * @param string $errline error line
376  @return true to prevent php default error handler to fire
377  */
378  public static function errorHandler( $errno , $errstr , $errfile , $errline )
379  {
380  if ( error_reporting( ) == 0 ){ return; } // if error has been supressed with an @
381  $err = array( 'errno' => static::_msgType( $errno ) , 'errstr' => $errstr ,
382  'errfile' => $errfile , 'errline' => $errline );
383  static::_buildBuffer( 'log' , '{errorHandler}' , $err );
384  // stop if fatal error occurs
385  if ( static::$_options[ 'die_on_error' ] && static::_msgType( $errno ) == 'Php Error') { die( ); }
386  return true; // don't execute php error handler
387  }
388  /**
389  * Exception handler, catches exceptions that are not in a try/catch block
390  * @param object $exception the exception object
391  */
392  public static function exceptionHandler( $exception )
393  {
394  $err = array( 'errno' => static::_msgType( 'exception' ) , 'errstr' => $exception->getMessage( ) ,
395  'errfile' => $exception->getFile( ) , 'errline' => $exception->getLine( ) );
396  static::_buildBuffer( 'log' , '{errorHandler}' , $err );
397  }
398  /**
399  * Attaches a message to the end of the buffer array to add data based on a reference. See @ref add_to_log
400  * @param string $reference a reference to look for ("$statement")
401  * @param mixed $string the message to show
402  * @param string $statement a new statement if required
403  * @return true if the given reference is found, false otherwise
404  */
405  public static function addToBuffer( $reference , $string , $statement = null )
406  {
407  $raw_buffer = static::_findReference( $reference , 2 );
408  if ( !$raw_buffer ){ return false; }
409  $last = $raw_buffer[ 'data' ];
410  if ( @$string )
411  {
412  $last[ 'var_type' ] = gettype( $string );
413  $last[ 'errstr' ] = $string;
414  }
415  if ( $statement ){ $last[ 'errmsg' ] = $statement; }
416  if ( static::$_options[ 'debug_console' ] )
417  {
418  $last[ 'console_string' ] = ( !@$string ) ? $last[ 'errstr' ] : $string;
419  $last[ 'console_statement' ] = ( !@$statement ) ? $last[ 'errmsg' ] : $statement;
420  }
421  @static::$_buffer[ $raw_buffer[ 'key' ] ] = $last;
422  return true;
423  }
424  /**
425  * Processes the buffer to show the interface and/or the console messages
426  */
427  public static function processBuffer( )
428  {
429  @unregister_tick_function( 'tickHandler' );
430  static::$_countTime = false;
431  if ( static::$_codeCoverage )
432  {
433  $trace_o = static::$_options[ 'code_coverage' ];
434  static::$_options[ 'code_coverage' ] = true;
435  static::stopCoverage( );
436  static::$_options[ 'code_coverage' ] = $trace_o;
437  }
438  if ( static::$_functionTrace )
439  {
440  $trace_o = static::$_options[ 'trace_functions' ];
441  static::$_options[ 'trace_functions' ] = true;
442  static::stopTrace( );
443  static::$_options[ 'trace_functions' ] = $trace_o;
444  }
445  static::$_endTime = microtime( true );
446  if( static::$_consoleStarted ){ static::_debugConsole(); }
447  if( static::$_options[ 'show_interface' ] )
448  {
449  static::_lastError( ); // get last php fatal error
450  $interface = static::_buildInterface( ); // build the interface
451  print $interface;
452  }
453  }
454  /**
455  * Searches files for a string inside a given folder recursively. See @ref search_string
456  * @param string $query the string to lok for
457  * @param string $path a starting path to search recursively
458  * @param int $last check last result
459  * @return an html table with all results
460  */
461  public static function findString( $query , $path = null , $last = 1 )
462  {
463  $path = ( $path ) ? $path : dirname(__FILE__);
464  $real_path = realpath( $path );
465  if ( !$real_path ) // need to trigger error if path is not found
466  {
467  trigger_error( 'The path "' . $path .
468  '" does not exists or is not accessible!' , E_USER_WARNING );
469  return false;
470  }
471  $fp = @opendir( $real_path );
472  if ( !$fp ) // need to trigger error if path is not found
473  {
474  trigger_error( 'The path "' . $path .
475  '" does not exists or is not accessible!' , E_USER_WARNING );
476  return false;
477  }
478  while ( $f = readdir( $fp ) )
479  {
480  if ( preg_match( '#^\.+$#' , $f ) ){ continue; } // ignore symbolic links
481  $file_full_path = $real_path . DIRECTORY_SEPARATOR . $f;
482  if ( is_dir( $file_full_path ) )
483  {
484  @$result .= static::findString( $query , $file_full_path , $last );
485  }
486  else
487  {
488  $file_lines = @file( $file_full_path );
489  if ( $file_lines )
490  {
491  $line_number = 1;
492  foreach ( $file_lines as $line )
493  {
494  $search_count = substr_count( $line , $query );
495  if ( $search_count > 0 ) // we found matches
496  {
497  $line = preg_replace( '|' . $query . '|',
498  '<span style="color:yellow;font-weight:bold;">' . $query .
499  '</span>' , htmlentities( $line ) );
500  @$result .= '<tr>';
501  $result .= '<td style="white-space: nowrap;"># ' . $last . '</td>';
502  $result .= '<td><div style="color:blue;">' . $file_full_path . '</div></td>';
503  $result .= '<td><div style="font-weight:bold;color:black;">' .
504  $line_number . '</div></td>';
505  $result .= '<td><div style="color:darkred;font-weight:bold;"">' . $line . '</div></td>';
506  $result .= '<td><div style="font-weight:bold;color:red;">
507  ' . $search_count . '</div></td>';
508  $result .= '</tr>';
509  $last++;
510  }
511  $line_number++;
512  }}
513  }
514  }
515  return @$result;
516  }
517  /**
518  * File highlighter that opens a popup window inspect source code. See @ref file_inspector
519  * @param string $file the full path for the file
520  * @param string $line the line to be highlighted
521  * @return the html output of the source code
522  */
523  public static function highlightFile( $file , $line = null )
524  {
525  $lines = implode( range( 1 , count( file ( $file ) ) ) , '<br />' );
526  $content = highlight_file( $file , true );
527  if ( $line )
528  {
529  $line = $line - 1;
530  $l = explode( '<br />' , $content );
531  $l[ $line ] = '<div id="line" style="display:inline;background-color:yellow;">' . $l[ $line ] . '</div>';
532  $content = implode( '<br />' , $l );
533  }
534  $html = '
535  <style type="text/css">
536  .num{float:left;color:gray;font-size:13px;
537  font-family:monospace;text-align:right;margin-right:6pt;
538  padding-right:6pt;border-right:1px solid gray;}
539  body{margin:0px;margin-left:5px;}
540  td{vertical-align:top;}code{white-space:nowrap;}
541  </style>
542  <script>
543  window.onload=function()
544  {
545  var SupportDiv = document.getElementById("line");
546  window.scroll(0,findPos(SupportDiv));
547  return false;
548  };
549  function findPos(obj)
550  {
551  var curtop=0;
552  if(obj.offsetParent)
553  {
554  do{
555  curtop+=(obj.offsetTop-40);
556  } while (obj = obj.offsetParent);
557  return [curtop];
558  }
559  };
560  </script>';
561  $html .= "<table><tr><td class=\"num\">\n$lines\n</td>";
562  $html .= "<td>\n$content\n</td></tr></table>";
563  return $html;
564  }
565  /**
566  * Default options for the debug class. See @ref dbg_class_options
567  */
568  protected static $_defaultOptions = array
569  (
570  'url_key' => 'debug' , // the key to pass to the url to turn on debug
571  'url_pass' => 'true' , // the pass to turn on debug
572  'replace_error_handler' => true , // replace default php error handler
573  'error_reporting' => E_ALL , // error reporting flag
574  'catch_exceptions' => true , // sets exception handler to be this class method
575  'check_referer' => false , // check referer for key and pass ( good for ajax debugging )
576  'die_on_error' => true , // die if fatal error occurs ( with this class error handler )
577  'debug_console' => false , // only for Chrome,show messages in console ( phpConsole needed )
578  'allowed_ips' => null , // restrict access with ip's
579  'session_start' => false , // start session for persistent debugging
580  'show_interface' => true , // show the interface ( false to debug in console only )
581  'set_time_limit' => null , // set php execution time limit
582  'memory_limit' => null , // set php memory size
583  'show_messages' => true , // show messages panel
584  'show_globals' => true , // show global variables in vars panel
585  'show_sql' => true , // show sql panel
586  'show_w3c' => true, // show the w3c panel
587  'minified_html' => true , // compress html for a lighter output
588  'trace_depth' => 10 , // maximum depth for the backtrace
589  'max_dump_depth' => 6 , // maximum depth for the dump function
590  'panel_top' => '0px' , // panel top position
591  'panel_right' => '0px' , // panel right position
592  'default_category' => 'General' , // default category for the messages
593  'enable_inspector' => true , // enable variables inspector, use declare(ticks=n); in code block
594  'code_coverage' => true, // enable code coverage analysis, use "full" to start globally
595  'trace_functions' => true, // enable function calls tracing, use "full" to start globally
596  'exclude_categories' => array( 'Event Manager' , 'Autoloader' ) // exclude categories from the output
597  );
598  /**
599  * Array of methods excluded from the backtrace
600  */
601  protected static $_excludeMethods=array( );
602  /**
603  * Code coverage analysis storage
604  */
605  protected static $_coverageData = null;
606  /**
607  * Final data array for the code coveage
608  */
609  protected static $_finalCoverageData = array( );
610  /**
611  * Function calls tracing storage property
612  */
613  protected static $_traceData = null;
614  /**
615  * Final data array for the function calls trace
616  */
617  protected static $_finalTraceData = array( );
618  /**
619  * Array with all options
620  */
621  protected static $_options = array( );
622  /**
623  * The debug buffer
624  */
625  protected static $_buffer = array( );
626  /**
627  * Application start time
628  */
629  protected static $_startTime = null;
630  /**
631  * Application end time
632  */
633  protected static $_endTime = null;
634  /**
635  * Decides if we should send the buffer to the PhpConsole class
636  */
637  protected static $_consoleStarted = false;
638  /**
639  * Array of watched variables declared
640  */
641  protected static $_watchedVars = array();
642  /**
643  * Tick execution time property
644  */
645  protected static $_tickTime = 0;
646  /**
647  * Exclude PtcDebug::$_buildBuffer from execution timing property
648  */
649  protected static $_countTime = true;
650  /**
651  * Code coverage analysis property to start coverage
652  */
653  protected static $_codeCoverage = false;
654  /**
655  * Function calls trace property to start the analysis
656  */
657  protected static $_functionTrace = false;
658  /**
659  * Controlls when to disable opcode cache
660  */
661  protected static $_disableOpcode = true;
662  /**
663  * Exclude functions from the function calls trace array
664  */
665  protected static $_excludeFromTrace = array( );
666  /**
667  * Property that holds the css for the floating panel
668  */
669  protected static $_panelCss = '#ptcDebugPanel{font-family:Arial,sant-serif;
670  position:fixed;top:{PANEL_TOP};right:{PANEL_RIGHT};
671  background:#eee;color:#333;z-index:10000;line-height:1.3em;
672  text-align:left;padding:0px;margin:0px;height:25px;}
673  #ptcDebugPanel ul.tabs li{background-color:#ddd;border-color:#999;margin:0 -3px -1px 0;
674  padding:3px 6px;border-width:1px;list-style:none;display:inline-block;border-style:solid;}
675  #ptcDebugPanel ul.tabs li.active{background-color:#fff;border-bottom-color:transparent;
676  text-decoration:}#ptcDebugPanel ul.tabs li:hover{background-color:#eee;}
677  #ptcDebugPanel ul.tabs li.active:hover{background-color:#fff;}
678  #ptcDebugPanel ul.tabs.merge-up{margin-top:-24px;}
679  #ptcDebugPanel ul.tabs.right{padding:0 0 0 0;text-align:right;}
680  #ptcDebugPanel ul.tabs{border-bottom-color:#999;border-bottom-width:1px;font-size:14px;
681  list-style:none;margin:0;padding:0;z-index:100000;position:relative;
682  background-color:#EEE}#ptcDebugPanel ul.tabs a{color:purple;font-size:10px;
683  text-decoration:none;}#ptcDebugPanel .tabs a:hover{color:red;}
684  #ptcDebugPanel ul.tabs a.active{color:black;background-color:yellow;}
685  .msgTable{padding:0;margin:0;border:1px solid #999;font-family:Arial;
686  font-size:11px;text-align:left;border-collapse:separate;border-spacing:2px;}
687  .msgTable th{margin:0;border:0;padding:3px 5px;vertical-align:top;
688  background-color:#999;color:#EEE;white-space:nowrap;}
689  .msgTable td{margin:0;border:0;padding:3px 3px 3px 3px;vertical-align:top;}
690  .msgTable tr td{background-color:#ddd;color:#333}
691  .msgTable tr.php-notice td{background-color:lightblue;}
692  .msgTable tr.exception td{background-color:greenyellow;}
693  .msgTable tr.php-warning td{background-color:yellow;}
694  .msgTable tr.php-error td{background-color:orange;}
695  .msgTable tr.inspector td{background-color:lightgreen;}
696  .innerTable a.php-notice{color:lightblue;}
697  .innerTable a.exception{color:greenyellow;}.innerTable a.php-warning{color:yellow;}
698  .innerTable a.php-error{color:orange;}.innerTable a.inspector{color:lightgreen;}
699  .innerTable a.general{color:darkgrey;}.innerTable a.show-all{color:red;}
700  #ptcDebugFilterBar{background-color:black;margin-bottom:8px;padding:4px;
701  font-size:13px;}.innerTable{z-index:10000;position:relative;background:#eee;
702  height:300px;padding:30px 10px 0 10px;overflow:auto;clear:both;}
703  .innerTable a{color:dodgerBlue;font-size:bold;text-decoration:none}
704  .innerTable p{font-size:12px;color:#333;text-align:left;line-height:12px;}
705  .innerPanel h1{font-size:16px;font-weight:bold;margin-bottom:20px;
706  padding:0;border:0px;background-color:#EEE;}
707  #ptcDebugPanelTitle{height:25px;float:left;z-index:1000000;position:relative;}
708  #ptcDebugPanelTitle h1{font-size:16px;font-weight:bold;margin-bottom:20px;
709  margin-left:10px;padding:0 0 0 0;border:0px;background-color:#EEE;
710  color:#669;margin-top:5px;;height:20px;}
711  #analysisPanel h2{font-size:14px;font-weight:bold;margin-bottom:20px;
712  padding:0 0 0 0;border:0px;background-color:#EEE;
713  color:#669;margin-top:5px;;height:20px;}
714  .vars-config, .vars-config span{font-weight:bold;}
715  .msgTable pre span, .vars-config span{padding:2px;}
716  .msgTable pre, span, .vars{font-size:11px;line-height:15px;
717  font-family:"andale mono","monotype.com","courier new",courier,monospace;}
718  .msgTable pre,.msgTable span{font-weight:bold;}
719  #varsPanel a{text-decoration:none;font-size:14px;font-weight:bold;color:#669;
720  line-height:25px;}.count_vars{font-size:11px;color:purple;padding:0;margin:0;}
721  .fixed{width:1%;white-space:nowrap;}.fixed1{width:5%;white-space:nowrap;}
722  #ptcDebugStatusBar{height:2px;background-color:#999;}' ;
723  /**
724  * Sends the buffer to the PhpConsole class. See @ref ajax_env
725  */
726  protected static function _debugConsole()
727  {
728  $handler = \PhpConsole\Handler::getInstance( );
729  $handler->setHandleErrors( false );
730  $handler->setHandleExceptions( false );
731  $handler->start( );
732  foreach ( static::$_buffer as $k => $arr )
733  {
734  if ( @$arr[ 'console_string' ] || @$arr[ 'console_statement' ] )
735  {
736  if ( !@$arr )
737  {
738  $php_trace = static::_debugTrace( 1 );
739  $arr=array( 'errline' => $php_trace[ 'line' ] , 'errfile' => $php_trace[ 'file' ] );
740  }
741  $statement = ( @$arr[ 'console_statement' ] ) ?
742  strip_tags( preg_replace( "=<br */?>=i" , "\n" ,
743  @$arr[ 'console_statement' ] ) ) : null;
744  $statement .= ( @$arr[ 'console_time' ] ) ? ' [time: ' . $arr[ 'console_time' ] . ']' : '';
745  $console_type = '[' . @end( @explode( '/' , $arr[ 'errfile' ][ 0 ] ) ) . ':';
746  $console_type .= $arr[ 'errline' ][ 0 ] . ']';
747  $key=(@$arr['type']=='log') ? 'messages' : 'sql';
748  if(static::$_options['show_'.$key])
749  {
750  if ( 'error' === $arr['console_statement'] )
751  {
752  $handler->handleError( $arr[ 'console_category' ] , $arr[ 'errstr' ] ,
753  $arr[ 'errfile' ][ 0 ] , $arr[ 'errline' ][ 0 ] , null , 2 );
754  }
755  else
756  {
757  \PC::debug( $console_type , $arr[ 'console_category' ] . '.file' );
758  if ( $statement )
759  {
760  \PC::debug( $statement , $arr[ 'console_category' ] . '.message' );
761  }
762  if ( @$arr[ 'console_string' ] )
763  {
764  \PC::debug( $arr[ 'console_string' ] , $arr[ 'console_category' ] . '.result' );
765  }
766  if ( @$arr[ 'errfile' ] )
767  {
768  unset( $arr[ 'errfile' ][ 0 ] );
769  if ( !empty( $arr[ 'errfile' ] ) )
770  {
771  \PC::debug( $arr[ 'errfile' ] , $arr[ 'console_category' ] . '.trace' );
772  }
773  }
774  //\PC::debug( $arr , $arr[ 'console_category' ] . '[full]' );
775  }
776  }
777  }
778  }
779  if ( !static::$_options[ 'show_interface' ] )
780  {
781  static::_buildCoverageData( );
782  static::_buildTraceData( );
783  }
784  $time = ( ( static::$_endTime - static::$_startTime ) - static::$_tickTime );
785  $console_final = 'Seconds: ' . round( $time , 3 ) . ' | Milliseconds: ' . round( $time * 1000 , 3 );
786  \PC::debug( array( @get_included_files( ) ) , static::$_options[ 'default_category' ] . '.includedFiles' );
787  \PC::debug( 'Global Execution Time ' . $console_final , static::$_options[ 'default_category' ] );
788  }
789  /**
790  * Checks if a given ip has access
791  * @param string|array $allowedIps the ip's that are allowed
792  */
793  protected static function _checkAccess($allowedIps=null)
794  {
795  static::$_options['allowed_ips']=(!$allowedIps) ? static::$_options['allowed_ips'] : $allowedIps;
796  if(static::$_options['allowed_ips'])
797  {
798  static::$_options['allowed_ips']=(is_array(static::$_options['allowed_ips'])) ?
799  static::$_options['allowed_ips'] : array(static::$_options['allowed_ips']);
800  if(@in_array(@$_SERVER['REMOTE_ADDR'],static::$_options['allowed_ips'])){ return true; }
801  return false;
802  }
803  return true;
804  }
805  /**
806  * Sets session vars to control which panels will be shown
807  */
808  protected static function _setSessionVars()
809  {
810  $_SESSION[ 'ptcdebug' ]['show_messages']=static::$_options['show_messages'];
811  $_SESSION[ 'ptcdebug' ]['show_globals']=static::$_options['show_globals'];
812  $_SESSION[ 'ptcdebug' ]['show_sql']=static::$_options['show_sql'];
813  $_SESSION[ 'ptcdebug' ]['show_w3c']=static::$_options['show_w3c'];
814  }
815  /**
816  * Controls which panels will be shown with $_GET variable "hidepanels"
817  */
818  protected static function _disablePanels( )
819  {
820  $hide = @explode( ',' , $_GET[ 'hidepanels' ] );
821  if ( !@empty( $hide ) )
822  {
823  $_SESSION[ 'ptcdebug' ][ 'show_messages' ] = true;
824  $_SESSION[ 'ptcdebug' ][ 'show_globals' ] = true;
825  $_SESSION[ 'ptcdebug' ][ 'show_sql' ] = true;
826  $_SESSION[ 'ptcdebug' ][ 'show_w3c' ] = true;
827  foreach ( $hide as $k => $v )
828  {
829  if ( $v == 'msg' || $v == 'all' )
830  {
831  $_SESSION[ 'ptcdebug' ][ 'show_messages' ] = false;
832  }
833  if ( $v == 'globals' || $v == 'all' )
834  {
835  $_SESSION[ 'ptcdebug' ][ 'show_globals' ] = false;
836  }
837  if ( $v == 'sql' || $v == 'all' )
838  {
839  $_SESSION[ 'ptcdebug' ][ 'show_sql' ] = false;
840  }
841  if ( $v == 'w3c' || $v == 'all' )
842  {
843  $_SESSION[ 'ptcdebug' ][ 'show_w3c' ] = false;
844  }
845  }
846  }
847  static::$_options[ 'show_messages' ] = static::_getSessionVars( 'show_messages' );
848  static::$_options[ 'show_globals' ] = static::_getSessionVars( 'show_globals' );
849  static::$_options[ 'show_sql' ] = static::_getSessionVars( 'show_sql' );
850  static::$_options[ 'show_w3c' ] = static::_getSessionVars( 'show_w3c' );
851  }
852  /**
853  * Builds the buffer
854  * @param string $type log/sql
855  * @param mixed $string the string to pass
856  * @param mixed $statement some statement preceding the string
857  * @param string $category a category for the message
858  */
859  protected static function _buildBuffer( $type , $string , $statement = null , $category = null )
860  {
861  if ( @in_array( $category , static::$_options[ 'exclude_categories' ] ) ){ return; }
862  if ( defined( '_PTCDEBUG_NAMESPACE_' ) &&
863  @static::_getSessionVars( static::$_options[ 'url_key' ] ) &&
864  ( static::$_options[ 'show_interface' ] || static::$_options[ 'debug_console' ] ) )
865  {
866  $buffer = array( 'start_time' => microtime( true ) , 'type' => $type );
867  $php_trace = static::_debugTrace( static::$_options[ 'trace_depth' ] );
868  $buffer[ 'errline' ] = @$php_trace[ 'line' ];
869  $buffer[ 'errfile' ] = @$php_trace[ 'file' ];
870  $buffer[ 'function' ] = @$php_trace[ 'function' ];
871  $buffer[ 'class' ] = @$php_trace[ 'class' ];
872  if ( $string === '{errorHandler}' )
873  {
874  $buffer[ 'errno' ] = $statement[ 'errno' ];
875  $buffer[ 'errstr' ] = $statement[ 'errstr' ];
876  if ( $statement[ 'errfile' ] == 'trace' )
877  {
878  $params = @explode( ':' , @str_replace( ':\\' , '{win-patch}' ,
879  @$buffer[ 'errfile' ][ 0 ] ) ); // windows patch
880  @$buffer[ 'errfile' ][ 0 ] = @str_replace( '{win-patch}' , ':\\' , @$params[ 0 ] );
881  }
882  else // if static::errorHandler() called the function
883  {
884  if ( !@is_array( $buffer[ 'errline' ] ) ){ $buffer[ 'errline' ] = array( ); }
885  if ( !@is_array( $buffer[ 'errfile' ] ) ){ $buffer[ 'errfile' ] = array( ); }
886  if ( !@is_array( $buffer[ 'function' ] ) ){ $buffer[ 'function' ] = array( ); }
887  if ( !@is_array( $buffer[ 'class' ] ) ){ $buffer[ 'class' ] = array( ); }
888  @array_unshift( $buffer[ 'errline' ] , $statement[ 'errline' ] );
889  @array_unshift( $buffer[ 'errfile' ] , $statement[ 'errfile' ] );
890  @array_unshift( $buffer[ 'function' ] , '' );
891  @array_unshift( $buffer[ 'class' ] , '' );
892  }
893  if ( static::$_options[ 'debug_console' ] )
894  {
895  //var_dump($buffer );
896  $buffer[ 'console_string' ] = $buffer;
897  $buffer[ 'console_statement' ] = 'error';
898  $buffer[ 'console_category' ] = $statement[ 'errno' ];
899  }
900  }
901  else
902  {
903  $params = @explode( ':' , @str_replace( ':\\' , '{win-patch}' ,
904  @$buffer[ 'errfile' ][ 0 ] ) ); // windows patch
905  @$buffer[ 'errfile' ][ 0 ] = @str_replace( '{win-patch}' , ':\\' , @$params[ 0 ] );
906  $buffer[ 'var_type' ] = gettype( $string );
907  if ( !$category ){ $category = static::$_options[ 'default_category' ]; }
908  $buffer[ 'errno' ] = $category;
909  $buffer[ 'errstr' ] = $string;
910  $buffer[ 'errmsg' ] = $statement;
911  if ( static::$_options[ 'debug_console' ] )
912  {
913  $buffer[ 'console_string' ] = $string;
914  $buffer[ 'console_statement' ] = $statement;
915  $buffer[ 'console_category' ] = $category;
916  }
917  }
918  @static::$_buffer[ ] = $buffer;
919  if ( static::$_countTime )
920  {
921  static::$_tickTime = ( ( microtime( true ) - $buffer[ 'start_time' ] ) + static::$_tickTime );
922  }
923  }
924  }
925  /**
926  * Callback function that checks if a given variable has changed
927  */
928  protected static function _watchCallback( )
929  {
930  if ( count( static::$_watchedVars ) )
931  {
932  foreach ( static::$_watchedVars as $variableName => $variableValue )
933  {
934  if ( is_array( $variableValue ) )
935  {
936  $var = $variableValue[ 'callback' ]( );
937  if ( @$var !== @$variableValue[ 'value' ] )
938  {
939  $info=array
940  (
941  'variable' => '$' . $variableName ,
942  'previous_value' => $variableValue[ 'value' ] ,
943  'new_value' => $var
944  );
945  static::$_watchedVars[ $variableName ] =
946  array( 'value' => $var , 'callback' => $variableValue[ 'callback' ] );
947  }
948  }
949  else
950  {
951  $var = static::_findWatchVar( $variableName );
952  if ( @$var !== @$variableValue )
953  {
954  $info=array
955  (
956  'variable' => '$' . $variableName ,
957  'previous_value' => $variableValue ,
958  'new_value' => $var
959  );
960  static::$_watchedVars[ $variableName ] = $var;
961  }
962  }
963  }
964  if ( @$info )
965  {
966  static::bufferLog( $info ,' Watched variable changed <span style="font-weight:bold;">$'.
967  $variableName . '</span> = ','Inspector');
968  }
969  }
970  }
971  /**
972  * Collect data for code coverage analysis
973  * @param array $backtrace the debug_backtrace( )
974  */
975  protected static function _codeCoverageAnalysis( $backtrace = null)
976  {
977  $backtrace = ( !$backtrace ) ?
978  debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ) : $backtrace;
979  $backtrace = array_reverse( $backtrace );
980  foreach ( $backtrace as $k => $v )
981  {
982  if ( @$v[ 'file' ] == __FILE__ ||
983  @strpos( $v[ 'file' ] , 'runtime-created function' ) ) { continue; }
984  if ( @$v[ 'line' ] && !@array_key_exists( @$v[ 'line' ] ,
985  @static::$_coverageData[ $v[ 'file' ] ] ) )
986  {
987  if ( !@array_key_exists( $v[ 'file' ] , static::$_coverageData ) )
988  {
989  static::$_coverageData[ $v[ 'file' ] ] = array( );
990  }
991  static::$_coverageData[ $v[ 'file' ] ][ $v[ 'line' ] ] = 1;
992  }
993  }
994  }
995  /**
996  * Evaluates the type of variable for output
997  * @param mixed $var the variable to pass
998  * @return the html output with the variable content
999  */
1000  protected static function _formatVar($var)
1001  {
1002  if(is_array($var) || is_object($var)){ $html_string=static::_doDump($var); }
1003  else if(@is_bool($var))
1004  {
1005  $html_string='<span style="color:#92008d;">'.($var==1 ? 'TRUE' : 'FALSE').'</span>';
1006  }
1007  else if(@is_null($var)){ $html_strisng='<span style="color:black;">NULL</span>'; }
1008  else if(@is_float($var)){ $html_string='<span style="color:#10C500;">'.$var.'</span>'; }
1009  else if(is_int($var)){ $html_string='<span style="color:red;">'.$var.'</span>'; }
1010  // could be a string
1011  else{ $html_string='<span>'.static::_cleanBuffer(@print_r($var,true)).'</span>'; }
1012  return @$html_string;
1013  }
1014  /**
1015  * Retrieves the variable to watch from the "$GLOBALS"
1016  * @param string $variableName the name of the variable to find
1017  * @return the watched variable if found, otherwise null
1018  */
1019  protected static function _findWatchVar($variableName)
1020  {
1021  $pieces=preg_split('/(->|\[.*?\])/',$variableName,null,PREG_SPLIT_DELIM_CAPTURE);
1022  $pieces=array_filter($pieces);
1023  $skip_key=null;
1024  $watch='$GLOBALS[\''.$pieces[0].'\']';
1025  foreach($pieces as $k=>$v)
1026  {
1027  if($k>0 && $k!=$skip_key && $v)
1028  {
1029  if($m=preg_match('/->/',$v) && @$pieces[$k+1])
1030  {
1031  $skip_key=($k+1);
1032  $watch=$watch.'->'.$pieces[$k+1];
1033  }
1034  else if($y=preg_match('/\[(.*?)\]/',$v,$match,PREG_OFFSET_CAPTURE))
1035  {
1036  $watch=$watch.$v;
1037  }
1038  }
1039  }
1040  return $var=@eval('return @'.$watch.';');
1041  }
1042  /**
1043  * Finds a value in the buffer based on a reference (the "$statement")
1044  * @param string $reference the reference to look for
1045  * @param numeric $type "1" to time execution, "2" to attach data to a message
1046  * @return the array if the given reference is found in the buffer
1047  */
1048  protected static function _findReference($reference,$type=1)
1049  {
1050  switch($type)
1051  {
1052  case 1:$msg='Could not find reference "'.$reference.'" to time execution!';
1053  break;
1054  case 2:$msg='Could not find reference "'.$reference.'" to add data to!';
1055  break;
1056  }
1057  for($i=0;$i<@count(static::$_buffer);$i++)
1058  {
1059  if($reference==@static::$_buffer[$i]['errmsg'])
1060  {
1061  $last['data']=static::$_buffer[$i];
1062  $last['key']=$i;
1063  }
1064  }
1065  if(!@$last)
1066  {
1067  $err=array('errno'=>static::_msgType(E_USER_WARNING),
1068  'errstr'=>$msg,'errfile'=>'trace');
1069  static::_buildBuffer('log','{errorHandler}',$err);
1070  return false;
1071  }
1072  return $last;
1073  }
1074  /**
1075  * Custom dump to properly format a given variable and make it more friendly to read
1076  * @param mixed $var the string to pass
1077  * @param mixed $varName some statement preceding the variable
1078  * @param string $indent uses "|" as indents by default
1079  * @param string $reference a reference to prevent recursion
1080  * @param int $depth maximun depth
1081  * @return the html output with the variable
1082  */
1083  protected static function _doDump( &$var , $varName = NULL , $indent = NULL , $reference = NULL , $depth = 0 )
1084  {
1085  $span_color='color:grey;';
1086  $do_dump_indent='<span style="color:white;"> | &nbsp;</span>';
1087  $reference=$reference.$varName;
1088  $keyvar='recursion_protection_scheme';
1089  $keyname='referenced_object_name';
1090  if((is_array($var) && isset($var[$keyvar])) || is_object($var) && property_exists($var,$keyvar))
1091  {
1092  if(is_array($var))
1093  {
1094  $real_var=&$var[$keyvar];
1095  $real_name=&$var[$keyname];
1096  $type=ucfirst(gettype($real_var));
1097  $result=$indent.$varName.' <span style="'.$span_color.'">'.$type.
1098  '</span> => **RECURSION** <span style="color:#e87800;">&amp;'.
1099  $real_name.'</span><br>';
1100  }
1101  else // if it's object
1102  {
1103  $real_var=&$var;
1104  $real_name=get_class($var);
1105  //$real_name=$real_name.'->'.$reference;
1106  $type=ucfirst(gettype($real_var));
1107  $varName='<span>'.$varName.'</span>';
1108  $result=$indent.$varName.' => <span style="'.$span_color.'">'.
1109  $type.'</span>(<span style="color:#e87800;">&amp;'.
1110  $real_name.'</span>) **RECURSION** <br>';
1111  }
1112  return $result;
1113  }
1114  else
1115  {
1116  $id="ptc-debug-".rand();
1117  $var=array($keyvar=>$var,$keyname=>$reference);
1118  $avar=&$var[$keyvar];
1119  $type=ucfirst(gettype($avar));
1120  switch($type)
1121  {
1122  case 'String':$type_color='<span style="color:#CF3F33;">';break;
1123  case 'Integer':$type_color='<span style="color:red;">';break;
1124  case 'Double':$type_color='<span style="color:#10C500;">'; $type='Float';break;
1125  case 'Boolean':$type_color='<span style="color:#92008d;">';break;
1126  case 'NULL':$type_color='<span style="color:black;">';break;
1127  default:$type_color='<span>';
1128  }
1129  if(is_array($avar))
1130  {
1131  $count=count($avar);
1132  @$result.=$indent.($varName ? '<span>' . $varName . '</span> => ' : '</span>');
1133  if(!empty($avar))
1134  {
1135  $depth=($depth+1);
1136  $result.='<a href="#" onclick="ptc_show_vars(\''.$id.'\',this);return false;"><span>'.
1137  $type.'('.$count.')&dArr;</span></a>';
1138  $result.='<div style="display:none;" id="'.$id.'">'.$indent.'<span> (</span><br>';
1139  $keys=array_keys($avar);
1140  if ( $depth < static::$_options[ 'max_dump_depth' ] )
1141  {
1142  foreach ( $keys as $name )
1143  {
1144  if ( $name !== 'GLOBALS' ) // avoid globals for recursion nightmares
1145  {
1146  $value = &$avar[ $name ];
1147  $name=static::_cleanBuffer($name);
1148  $result.=static::_doDump($value,'<span style="color:#CF7F18;">[\''.
1149  $name.'\']</span>',$indent.$do_dump_indent,$reference,$depth);
1150  }
1151  }
1152  }
1153  else
1154  {
1155  $result.=$indent.$do_dump_indent.$varName.' <span style="'.
1156  $span_color.'">'.$type=ucfirst(gettype($var[$keyvar])).
1157  '</span> => **MAX DEPTH REACHED** <span style="color:#e87800;">'.
1158  $var[$keyname].'</span><br>';
1159  }
1160  $result.=$indent.'<span> )</span></div><div><!-- --></div>';
1161  }
1162  else{ $result.='<span style="'.$span_color.'">'.$type.'('.$count.')</span></br>'; }
1163  }
1164  else if ( is_object( $avar ) )
1165  {
1166  $rf = @new \ReflectionFunction( $avar );
1167  if ( ( @$rf->getName( ) == '{closure}' ) ) // work with lambda functions first
1168  {
1169  $result .= $indent . ( $varName ? $varName . ' => ' : '');
1170  $result .= '<span>**RUNTIME CREATED FUNCTION** ';
1171  if ( @$rf->getFileName( ) ) { $result .= @$rf->getFileName( ); }
1172  if ( @$rf->getStartLine( ) ) { $result .= ':' . @$rf->getStartLine( ); }
1173  if ( @$rf->getStartLine( ) ) { $result .= '-' . @$rf->getEndline( ); }
1174  $result .= '</span><br>';
1175  }
1176  else
1177  {
1178  @$avar->recursion_protection_scheme = "recursion_protection_scheme";
1179  $depth = ( $depth + 1 );
1180  @$result .= $indent . ( $varName ? $varName . ' => ' : '');
1181  $result .= '<a href="#" onclick="ptc_show_vars(\''.$id.'\',this);return false;">';
1182  $result .= '<span>' . $type . '(' . get_class( $avar ) . ')&dArr;</span></a>'.
1183  '<div style="display:none;" id="' . $id . '">' . $indent . ' <span> ( </span><br>';
1184  if ( $depth < static::$_options[ 'max_dump_depth' ] )
1185  {
1186  // public properties
1187  $class_properties = array( );
1188  foreach ( $avar as $name => $value )
1189  {
1190  $name = static::_cleanBuffer( $name );
1191  $name=is_object($value) ? '<span>'.$name.'</span>' : $name;
1192  $result .= static::_doDump( $value , $name ,$indent .
1193  $do_dump_indent , $reference,$depth );
1194  $class_properties[ ] = $name;
1195  }
1196  // protected/private properties
1197  $class = @new \ReflectionClass( $avar );
1198  $properties = $class->getProperties( );
1199  foreach ( $properties as $property )
1200  {
1201  $name = $property->getName( );
1202  if ( $property->isPrivate( ) ) { $name = $name . ':private'; }
1203  else if ( $property->isProtected( ) ) { $name = $name.':protected'; }
1204  if ( $property->isStatic( ) ) { $name = $name . ':static'; }
1205  $property->setAccessible( true );
1206  $value = $property->getValue( $avar );
1207  if(!in_array($name,$class_properties))
1208  {
1209  $name=static::_cleanBuffer($name);
1210  $name=is_object($value) ? '<span>'.$name.'</span>' : $name;
1211  $result.=static::_doDump($value,$name,$indent.$do_dump_indent,$reference,$depth);
1212  }
1213  }
1214  $methods=$class->getMethods();
1215  if($methods)
1216  {
1217  $class_methods=array();
1218  $z=0;
1219  foreach($methods as $method)
1220  {
1221  $name=$method->getName();
1222  if($method->isPrivate()){ $name=$name.':private'; }
1223  else if($method->isProtected()){ $name=$name.':protected'; }
1224  if($method->isStatic()){ $name=$name.':static'; }
1225  $class_methods[$z]=$name;
1226  $z++;
1227  }
1228  $result.=static::_doDump($class_methods,
1229  '<span style="color:#CF7F18;">[**class_methods:'.get_class($avar).
1230  '**]</span>', $indent.$do_dump_indent,$reference);
1231  }
1232  }
1233  else
1234  {
1235  $result.=$indent.$do_dump_indent.$varName.
1236  ' <span style="'.$span_color.'">'.$type=ucfirst(gettype($var[$keyvar])).
1237  '</span> => **MAX DEPTH REACHED** <span style="color:#e87800;">'.
1238  $var[$keyname].'</span><br>';
1239  }
1240  $result.=$indent.'<span> ) </span></div><div><!-- --></div>';
1241  unset($avar->recursion_protection_scheme);
1242  }
1243  }
1244  else
1245  {
1246  if($varName=="recursion_protection_scheme"){ return; }
1247  @$result .= $indent . '<span>' . $varName . '</span> => <span style="'.$span_color.'">';
1248  if(is_string($avar) && (strlen($avar)>50))
1249  {
1250  $result.='<a href="#" onclick="ptc_show_string(\''.$id.
1251  '\',this);return false;" style="font-weight:bold;">';
1252  }
1253  $result.=$type.'(';
1254  if ( is_bool( $avar ) )
1255  {
1256  $result .= strlen( $avar ) . ')</span> ' . $type_color . ( $avar == 1 ? "TRUE" : "FALSE" ) .
1257  '</span><br>';
1258  }
1259  else if ( is_null( $avar ) ) { $result .= strlen( $avar ) . ')</span> ' . $type_color . 'NULL</span><br>'; }
1260  else if ( is_string( $avar ) )
1261  {
1262  $avar = trim( static::_cleanBuffer( $avar ) );
1263  $string = ( strlen( $avar ) > 50 ) ? substr( $avar , 0 , 47 ) . '...' : $avar;
1264  $string = '<span id="' . $id . '-span">\'' . $string . '\'</span>';
1265  $result .= strlen ( $avar ) . ') ';
1266  $result .= ( strlen( $avar ) > 50 ) ? '&dArr;</span></a>' : '</span>';
1267  $result .= $type_color . $string . '</span>';
1268  if ( strlen( $avar ) > 50 )
1269  {
1270  $result.='<div style="display:none;" id="'.$id.'">'.$type_color.'\''.$avar.'\'</div>';
1271  }
1272  $result .= '<br>';
1273  }
1274  else // could be a float, an integer or undefined
1275  {
1276  //$avar=static::_cleanBuffer($avar);
1277  $result .= @strlen( $avar ) . ')</span> ' . $type_color . $avar . '</span><br>';
1278  }
1279  }
1280  $var = @$var[ $keyvar ];
1281  }
1282  //$var=@$var[$keyvar];
1283  return $result;
1284  }
1285  /**
1286  * Sorts the buffer
1287  * @return the sorted buffer array
1288  */
1289  protected static function _sortBuffer()
1290  {
1291  if(@static::$_buffer)
1292  {
1293  foreach(static::$_buffer as $k=>$arr)
1294  {
1295  $type=$arr['type'];
1296  //unset($arr['type']);
1297  $buffer[$type][]=$arr;
1298  }
1299  return @static::$_buffer=$buffer;
1300  }
1301  }
1302  /**
1303  * Trace php as best as we can
1304  * @param int $depth the maximum trace depth
1305  * @return the trace without the methods in the PtcDebug::$_excludeMethods property
1306  */
1307  protected static function _debugTrace( $depth = NULL )
1308  {
1309  if ( !$depth ) { $depth = static::$_options[ 'trace_depth' ]; }
1310  if ( version_compare( PHP_VERSION, '5.3.6' ) < 0 )
1311  {
1312  $raw_trace = debug_backtrace( false );
1313  }
1314  else { $raw_trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); }
1315  //$this_methods = get_class_methods( get_called_class( ) );
1316  foreach ( $raw_trace as $k => $arr )
1317  {
1318  if((@$arr['class']=='PtcDebug' && (@preg_match("|_|",@$arr['function']) ||
1319  @in_array(@$arr['function'],static::$_excludeMethods))) ||
1320  @preg_match("|__|",@$arr['function'])){ unset($raw_trace[$k]); }
1321  }
1322  if(!empty($raw_trace))
1323  {
1324  $raw_trace=@array_values($raw_trace);
1325  $raw_trace=@array_reverse($raw_trace);
1326  if($depth>count($raw_trace)){ $depth=count($raw_trace); }
1327  for($i=0;$i<$depth;$i++)
1328  {
1329  if(@$raw_trace[$i]['line'] && @$raw_trace[$i]['file'])
1330  {
1331  $php_trace['file'][]=$raw_trace[$i]['file'].':'.$raw_trace[$i]['line'];
1332  $php_trace['line'][]=$raw_trace[$i]['line'];
1333  $php_trace['class'][]=@$raw_trace[$i]['class'];
1334  //$php_trace['function'][]=$raw_trace[$i]['function'];
1335  $php_trace['function'][]=(@$raw_trace[$i]['function']) ?
1336  $raw_trace[$i]['function'].'()' : null;
1337  }
1338  }
1339  unset( $raw_trace );
1340  }
1341  else{ $php_trace=null; }
1342  return @$php_trace;
1343  }
1344  /**
1345  * Gets the fatal error on shutdown
1346  */
1347  protected static function _lastError()
1348  {
1349  if(static::$_options['replace_error_handler'] && $error=error_get_last())
1350  {
1351  $err_type=static::_msgType( $error['type'] );
1352  if($err_type=='Php Error')
1353  {
1354  $err=array('errno'=>$err_type,'errstr'=>$error['message'],
1355  'errfile'=>$error['file'],'errline'=>$error['line']);
1356  static::_buildBuffer('log','{errorHandler}',$err);
1357  }
1358  }
1359  }
1360  /**
1361  * Builds the debug interface
1362  * @return the html with interface
1363  */
1364  protected static function _buildInterface( )
1365  {
1366  static::_sortBuffer( );
1367  $interface = static::_includeJs( ); // include js
1368  $interface .= static::_includeCss( ); // include css
1369  $interface .= '<div id="ptcDebugPanel">';
1370  $interface .= '<div id="ptcDebugPanelTitle" style="display:none;">&nbsp;</div>';
1371  $interface .= static::_buildMenu( ); // top menu
1372  $interface .= static::_buildMsgPanel( 'log' , 'msgPanel' ); // msgs
1373  $interface .= static::_buildMsgPanel( 'sql' , 'sqlPanel' ); // sql
1374  $interface .= static::_buildAnalysisPanel( ); // Analysis
1375  $interface .= static::_buildVarsPanel( ); // vars
1376  $interface .= static::_buildW3cPanel( ); // w3c
1377  $interface .= static::_buildTimerPanel( ); // timer
1378  $interface .= '<div id="ptcDebugStatusBar" style="display:none;">&nbsp;</div>';
1379  $interface .= '</div>';
1380  //$interface = static::_compressHtml( $interface ); // make html lighter
1381  return $interface;
1382  }
1383  /**
1384  * Builds the debug menu
1385  * @return the html menu compressed
1386  */
1387  protected static function _buildMenu( )
1388  {
1389  $ul = '<ul class="tabs right" id="floatingTab">';
1390  //$ul .= '<li><a href="#" onClick="minimize();return false;">>></a></li>';
1391  $num_msg = @count( static::$_buffer[ 'log' ] );
1392  $ul .= '<li>' . static::_menuLinks( 'msgPanel' , 'log & messages ( ' . $num_msg . ' ) ' ,
1393  'messages ( ' . $num_msg . ' ) ' ) . '</li>';
1394  $num_msg = @count( static::$_buffer[ 'sql' ] );
1395  $ul .= '<li>' . static::_menuLinks( 'sqlPanel' , 'mysql query messages ( ' . $num_msg . ' ) ' ,
1396  'sql ( ' . $num_msg . ' ) ' ) . '</li>';
1397  $num_msg = (@count( static::$_finalCoverageData ) + @count( static::$_finalTraceData ) );
1398  $ul .= '<li>' . static::_menuLinks( 'analysisPanel' , 'analysis ( ' . $num_msg . ' ) ' ,
1399  'analysis ( ' . $num_msg . ' ) ' ) . '</li>';
1400  $ul .= '<li>' . static::_menuLinks( 'varsPanel' , 'configuration & environment variables' ,
1401  'vars & config' ) . '</li>';
1402  $ul .= '<li>' . static::_menuLinks( 'w3cPanel' , 'W3C validator' , 'w3c' ) . '</a></li>';
1403  $ul .='<li>' . static::_menuLinks( 'timerPanel' , 'execution time monitor' , 'timer' ) . '</li>';
1404  $ul .= '<li><a href="#" onClick="hideInterface();return false;">X</a></li>';
1405  $ul .= '</ul> ';
1406  return $ul = static::_compressHtml( $ul );
1407  }
1408  /**
1409  * Builds the menu links
1410  * @param string $id the panel id
1411  * @param string $title the panel title
1412  * @param string $text the text for the link
1413  * @return the html anchor tag
1414  */
1415  protected static function _menuLinks( $id , $title , $text )
1416  {
1417  $title = ucwords( $title );
1418  $text = strtoupper( $text );
1419  $return = '<a href="#" onClick="ptc_show_panel(\'' . $id . '\',\'' .
1420  $title . '\',this);return false;">';
1421  return $return .= $text . '</a>';
1422  }
1423  /**
1424  * Checks message types
1425  * @param string|numeric $msg php standards
1426  * @return the message type as a readable string
1427  */
1428  protected static function _msgType( $msg = NULL )
1429  {
1430  switch ( $msg )
1431  {
1432  case @E_NOTICE:
1433  case @E_USER_NOTICE:
1434  case @E_DEPRECATED:
1435  case @E_USER_DEPRECATED:
1436  case @E_STRICT:
1437  return 'Php Notice';
1438  break;
1439  case @E_WARNING:
1440  case @E_USER_WARNING:
1441  case @E_CORE_WARNING:
1442  case @E_COMPILE_WARNING:
1443  return 'Php Warning';
1444  break;
1445  case @E_ERROR:
1446  case @E_PARSE;
1447  case @E_RECOVERABLE_ERROR:
1448  case @E_USER_ERROR:
1449  case @E_CORE_ERROR:
1450  case @E_COMPILE_ERROR:
1451  return 'Php Error';
1452  break;
1453  case 'exception' : return 'Exception';
1454  break;
1455  default: return 'General';
1456  }
1457  }
1458  /**
1459  * Builds the html log and sql tables
1460  * @param string $type sql|log
1461  * @return the html table data
1462  */
1463  protected static function _buildHtmlTable( $type )
1464  {
1465  $div = null;
1466  if ( @static::$_buffer[ $type ] )
1467  {
1468  $categories = array( );
1469  foreach ( static::$_buffer[ $type ] as $k => $arr )
1470  {
1471  if ( @$arr[ 'errno' ] )
1472  {
1473  if ( !array_key_exists( $arr[ 'errno' ] , $categories ) )
1474  {
1475  $categories[ $arr[ 'errno' ] ] = 1;
1476  }
1477  else
1478  {
1479  $categories[ $arr[ 'errno' ] ] = ( $categories[ $arr[ 'errno' ] ] + 1 );
1480  }
1481  }
1482  }
1483  if ( sizeof( $categories ) > 1 )
1484  {
1485  ksort( $categories );
1486  $div .= '<div id="ptcDebugFilterBar"><a href="#" onClick="ptc_filter_categories(\'' .
1487  $type . 'Table\',\'showAll\')" class="show-all">Show All</a> | ';
1488  foreach ( $categories as $k => $v )
1489  {
1490  $cat_id = str_replace( ' ' , '-' , strtolower( $k ) );
1491  $div .= '<a href="#" onClick="ptc_filter_categories(\'' . $type .
1492  'Table\',\'' . $cat_id . '\')" class="' . $cat_id . '">' . $k . "(" . $v . ")</a> | ";
1493  }
1494  $div = substr( $div , 0 , -3 );
1495  $div .= '</div>';
1496  }
1497  $a = 1;
1498  $div .= '<table border="1" style="width:100%" class="msgTable" id="' . $type . 'Table"><tr>';
1499  $div .= '<th>#</th><th>category</th><th>file</th><th>line</th>';
1500  $div .= '<th>class</th><th>function</th>';
1501  if ( $type == 'log' ){ $div .= '<th>type</th>'; }
1502  $div .= '<th>time</th><th>message</th></tr>';
1503  foreach ( static::$_buffer[ $type ] as $k => $arr )
1504  {
1505  $msg_class = @str_replace( ' ' , '-' , $arr[ 'errno' ] );
1506  $div .= '<tr class="' . strtolower( $msg_class ) . '"><td class="fixed"># ' . $a . '</td>';
1507  //$div.='<td style="'.static:: _errorMsgStyle($arr['errno']).'">'.$arr['errno'].'</td>';
1508  $div .= '<td class="fixed"><span style="color:green;">'.@$arr['errno'].'</span></td>';
1509  $div .= '<td class="fixed">';
1510  $div .= @static::_buildTraceLink( @$arr[ 'errfile' ][ 0 ] , @$arr[ 'errline' ][ 0 ] );
1511  $div .= '<span>' . @end( @explode( DIRECTORY_SEPARATOR , $arr[ 'errfile' ][ 0 ] ) ).'</span></a>';
1512  if ( count( @$arr[ 'errfile' ] ) > 1 )
1513  {
1514  $class = 'ptc-debug-class-' . rand( );
1515  $div .= ' <a href="#" onclick="ptc_show_trace(\'' . $class .
1516  '\',this);return false;"><span>' . '&dArr;</span></a>';
1517  }
1518  @array_shift( $arr[ 'errfile' ] );
1519  if ( !empty( $arr[ 'errfile' ] ) )
1520  {
1521  $indent = '<span style="color:black;">| &nbsp;</span>';
1522  foreach ( $arr[ 'errfile' ] as $k => $file )
1523  {
1524  $div .= '<div class="' . $class . '" style="display:none;">';
1525  if ( $file || @$arr[ 'errfile' ][ $k + 1 ] ){ $div .= $indent; }
1526  $params = @explode( ':' , str_replace( ':\\' , '{win-patch}' , $file ) ); // windows patch;
1527  @$params[ 0 ] = @str_replace( '{win-patch}' , ':\\' , @$params[ 0 ] );
1528  $div .= @static::_buildTraceLink( $params[ 0 ] , $params[ 1 ] );
1529  $div .= @end( @explode( DIRECTORY_SEPARATOR , $file ) ) . '</a></div>';
1530  $indent = $indent . '<span style="color:black;">| &nbsp;</span>';
1531  }
1532  }
1533  $div .= '</td>';
1534  $div .= '<td class="fixed">' . @static::_buildTraceTree( @$arr[ 'errline' ] , $class , 'black' ) . '</td>';
1535  $div .= '<td class="fixed">' . @static::_buildTraceTree( @$arr[ 'class' ] , $class , 'purple' ) . '</td>';
1536  $div.='<td class="fixed">' . @static::_buildTraceTree( @$arr[ 'function' ] , $class , 'darkred' ) . '</td>';
1537  if ( $type == 'log' )
1538  {
1539  $div .= '<td class="fixed">';
1540  switch ( @$arr[ 'var_type' ] )
1541  {
1542  case 'boolean' : $color = 'color:#92008d;'; break;
1543  case 'NULL' : $color = 'color:black;'; break;
1544  case 'integer' : $color = 'color:red;'; break;
1545  case 'double' : $color = 'color:#10C500;'; break;
1546  case 'array' : $color = 'color:blue'; break;
1547  case 'object' : $color = 'color:#CF3F33'; break;
1548  //case 'string': $color='color:#CF3F33'; break;
1549  default : $color = '';
1550  }
1551  $div .= '<span style="' . $color . '">' . @$arr[ 'var_type' ] . '</span>';
1552  $div .= '</td>';
1553  }
1554  $div .= ( @$arr[ 'time' ] ) ? '<td class="fixed"><span style="color:blue;font-weight:normal;"">'.
1555  $arr[ 'time' ] . '</span></td>' : '<td class="fixed">&nbsp;</td>';
1556  $errors = array( 'php-warning' , 'php-notice' , 'php-error' , 'exception' );
1557  $err_style = ( !in_array( strtolower( $msg_class ) , $errors ) ) ? 'font-weight:normal;' : 'color:darkred;';
1558  $div .= '<td><span style="' . $err_style . '">';
1559  if ( @$arr[ 'errmsg' ] ){ $div .= @$arr[ 'errmsg' ] . ' '; }
1560  $div .= static::_formatVar( @$arr[ 'errstr' ] );
1561  $div .= '</span></td></tr>';
1562  $a++;
1563  }
1564  $div .= "</table><br>";
1565  }
1566  else{ $div = '<span class="vars">no messages</span>'; }
1567  return $div;
1568  }
1569  /**
1570  * Builds the link for the code highlighter popup
1571  * @param string $file the full path to the file
1572  * @param string $line the line to be highlighted
1573  */
1574  protected static function _buildTraceLink( $file , $line = null )
1575  {
1576  $html = '<a href="#" onclick="';
1577  if ( session_id( ) !== '' && static::_getSessionVars( 'code_highlighter' ) )
1578  {
1579  $js_file = @addslashes( @str_replace( $document_root , '' , $file ) );
1580  $html .= 'ptc_read_code(\'' . addslashes( $file ) . '\',\'' . $line . '\');return false;" title="' . @$file . '">';
1581  }
1582  else
1583  {
1584  $html .= 'return false;"';
1585  $html .= ' title="' . @$file . ' '."\n\n".'** USE SESSION_START(), IF YOU WISH';
1586  $html .= ' TO ACTIVATE THE CODE POPUP HIGHLIGHTER **" style="cursor:text;">';
1587  }
1588  return $html;
1589  }
1590  /**
1591  * Builds the tree for the links in the vars & config panel
1592  * @param mixed $var the variable
1593  * @param string $className a css class
1594  * @param string $styleColor the color for
1595  */
1596  protected static function _buildTraceTree( $var , $className = null , $styleColor = null )
1597  {
1598  $indent = '';
1599  foreach ( $var as $k => $v )
1600  {
1601  if ( $k > 0 )
1602  {
1603  $display = 'display:none;';
1604  $class = ' class="' . $className . '"';
1605  }
1606  @$html .= '<div style="font-weight:bold;color:' . $styleColor . ';' .
1607  @$display . '"' . @$class . '>';
1608 
1609  if ( $v || @$var[ $k + 1 ] ) { $html .= $indent; }
1610 
1611  if( !$v ) { $v = '&nbsp;'; }
1612  $html .= $v . '</div>';
1613  $indent = $indent . '<span style="color:black;">| &nbsp;</span>';
1614  }
1615  return $html;
1616  }
1617  /**
1618  * Builds the log/sql panel
1619  * @param $type log or sql
1620  * @param $panelId ome id for the panel
1621  */
1622  protected static function _buildMsgPanel( $type , $panelId )
1623  {
1624  $div = '<div id="' . $panelId . '" style="display:none;" class="innerTable">';
1625  $key = ( $type == 'log' ) ? 'messages' : 'sql';
1626  if ( !static::$_options[ 'show_' . $key ] )
1627  {
1628  return $div.='<span class="vars">Panel is Disabled</span></div>';
1629  }
1630  $div .= ( @static::$_buffer[ $type ] ) ? static::_buildHtmlTable( $type ) :
1631  '<span class="vars">no messages</span>';
1632  return $div .= '</div>';
1633  }
1634  /**
1635  * Builds the timer panel
1636  */
1637  protected static function _buildTimerPanel( )
1638  {
1639  $time = ( ( static::$_endTime - static::$_startTime ) - static::$_tickTime );
1640  $div = '<div id="timerPanel" style="display:none;" class="innerTable">';
1641  $div .= '<span style="font-weight:bold;">Global Execution Time:</span>';
1642  $div .= '<br>Seconds: ' . round( $time , 3 ) . '<br>Milliseconds: ' .
1643  round( $time * 1000 , 3 );
1644  $div .= '</div>';
1645  return $div = static::_compressHtml( $div );
1646  }
1647  /**
1648  * Builds the Analysis panel for code coverage analysis
1649  */
1650  protected static function _buildAnalysisPanel( )
1651  {
1652  $div = '<div id="analysisPanel" style="display:none;" class="innerTable">';
1653  $div .= '<h2>Code Coverage Analysis</h2>';
1654  $div .= static::_buildCoverageData( );
1655  $div .= '<br><h2>Function Calls Trace</h2>';
1656  $div .= static::_buildTraceData( );
1657  $div .= '<br><h2>Search Files For String</h2>';
1658  if ( session_id( ) === '' )
1659  {
1660  $div .= '<span class="vars">Use session start to search for a string inside files!</span>';
1661  }
1662  else
1663  {
1664  $div .= '<form id="searchStringForm" method="get" ';
1665  $div .= 'onSubmit="ptc_search_string( );return false;">';
1666  $div .= '<span><b>Path: </b>&nbsp;&nbsp;</span>';
1667  $div .= '<input name="ptc_search_path" type="text" value="' .
1668  $_SERVER[ 'DOCUMENT_ROOT' ] . '" size="120"><br>';
1669  $div .= '<span><b>String: </b></span>';
1670  $div .= '<input name="ptc_search_files" type="text" size="120">';
1671  $div .= '<input name="ptc_submit_search" type="submit" value="Search">';
1672  $div .= '</form>';
1673  }
1674  return $div .= '</div>' ;
1675  }
1676  /**
1677  * Builds the html data for the code coverage analysis
1678  */
1679  protected static function _buildCoverageData( )
1680  {
1681  if ( static::$_options[ 'code_coverage' ] )
1682  {
1683  if ( !empty( static::$_finalCoverageData ) )
1684  {
1685  $i = 1;
1686  foreach ( static::$_finalCoverageData as $data )
1687  {
1688  $div .= '<div style="font-weight:bold;"><span><b>Coverage ' . $i;
1689  $div .= ' result:</b></span> &nbsp;&nbsp;' . static::_formatVar( $data ) . '</div>';
1690  if ( static::$_consoleStarted )
1691  {
1692  \PC::debug( $data , static::$_options[ 'default_category' ] .'.coverageResult ' . ( $i ) );
1693  }
1694  $i++;
1695  }
1696  //static::$_finalCoverageData = array( );
1697  }
1698  else{ @$div .= '<span class="vars">no data available</span><br>'; }
1699  }
1700  else
1701  {
1702  $div .= '<span class="vars">';
1703  $div .= 'Code coverage is disabled! To use this feature, ';
1704  $div .= 'set the option [\'code_coverage\'] to \'true\' or \'full\'!';
1705  $div .= '</span><br>';
1706  }
1707  return $div;
1708  }
1709  /**
1710  * Builds the html data for the function calls trace
1711  */
1712  protected static function _buildTraceData( )
1713  {
1714  if ( static::$_options[ 'trace_functions' ] )
1715  {
1716  if ( !empty( static::$_finalTraceData ) )
1717  {
1718  for ( $a = 0; $a < sizeof( static::$_finalTraceData ); $a++ )
1719  {
1720  $data = static::$_finalTraceData[ $a ];
1721  // this is just a patch
1722  $data = array_unique( $data , SORT_REGULAR );
1723  //$data = array_map( 'unserialize' , array_unique( array_map( 'serialize' , $data ) ) );
1724  @$div .= '<span><b>Trace ' . ( $a +1 ) . ' result: ';
1725  $div .= '<a href="#" onclick="ptc_show_trace_table(\'jsLive-' . $a . '\' , this );return false;">';
1726  $div .=sizeof( $data ). ' calls &dArr;</a></b></span>';
1727  $div .= '<table border="1" style="width:100%;display:none" class="msgTable jsLive-' .
1728  $a . '" id="logTable">';
1729  $div .= '<tbody><tr><th>#</th><th>function</th><th>file</th>';
1730  $div .= '<th>line</th><!--<th>memory</th>--><th>called by</th><th>in</th></tr>';
1731  $i = 1;
1732  foreach ( $data as $k => $v )
1733  {
1734  $link = ( @$v[ 'file' ] ) ? static::_buildTraceLink( $v[ 'file' ] , @$v[ 'line' ] )
1735  . $v[ 'file' ] . '</a>' : '';
1736  $args = ( @$v[ 'args' ] ) ? @preg_replace( '/Array/' , '' ,
1737  @static::_formatVar( $v[ 'args' ] ) , 1 ) : '( )';
1738  $called_by_args = ( @$v[ 'called_by_args' ] ) ? @preg_replace( '/Array/' , '' ,
1739  @static::_formatVar( $v[ 'called_by_args' ] ) , 1 ) : '';
1740  if ( !$called_by_args && @$v[ 'called_by' ] ) { @$v[ 'called_by' ] = @$v[ 'called_by' ] . '( )'; }
1741  $in = ( @$v[ 'in' ] ) ? static::_buildTraceLink( $v[ 'in' ] , @$v[ 'on_line' ] ) . $v[ 'in' ] : '';
1742  $in .= ( @$v[ 'on_line' ] ) ? ': '. $v[ 'on_line' ] : '';
1743  $in .=( @$v[ 'in' ] ) ? '</a>' : '';
1744  $div .= '<tr class="general">';
1745  $div .= '<td class="fixed"><div style="color:black;"># '. $i . '</div></td>';
1746  $div .= '<td class="fixed"><div style="color:darkred;font-weight:bold;">';
1747  $div .= $v[ 'function' ] .$args . '</div></td>';
1748  $div .= '<td class="fixed">'.$link.'</td>';
1749  $div .= '<td class="fixed"><div style="color:black;font-weight:bold;">';
1750  $div .= @$v[ 'line' ] .'</div></td>';
1751  //$div .= '<td class="fixed"><div style="color:green;font-weight:bold;">';
1752  //$div .= @static::convertMemUsage( $v[ 'memory' ] ) . '</div></td>';
1753  $div .= '<td class="fixed"><div style="color:purple;font-weight:bold;">';
1754  $div .= @$v[ 'called_by' ] . $called_by_args . '</div></td>';
1755  $div .= '<td class="fixed">' . $in . '</td>';
1756  $div .= '</tr>';
1757  $i++;
1758  }
1759  $div .= '</tbody></table><br>';
1760  if ( static::$_consoleStarted )
1761  {
1762  \PC::debug( $data , static::$_options[ 'default_category' ] .'.traceResult ' . ( $a + 1 ) );
1763  }
1764  }
1765  //static::$_finalTraceData = array( );
1766  }
1767  else { $div .= '<span class="vars">no data available</span><br>'; }
1768  }
1769  else
1770  {
1771  $div .= '<span class="vars">';
1772  $div .= 'Functions calls tracing is disabled! To use this feature, ';
1773  $div .= 'set the option [\'trace_functions\'] to \'true\' or \'full\'!';
1774  $div .= '</span><br>';
1775  }
1776  return $div;
1777  }
1778  /**
1779  * Builds the vars panel
1780  */
1781  protected static function _buildVarsPanel( )
1782  {
1783  $div = '<div id="varsPanel" style="display:none;" class="innerTable">';
1784  $div .= '<a href="#" onClick="ptc_show_vars(\'files\',this)">Files';
1785  $included_files = @get_included_files( );
1786  $div .= '<span class="count_vars">(' . @sizeof( $included_files ) .
1787  ')</span>&dArr;</a><br>';
1788  $div .= '<div id="files" class="vars" style="display:none;line-height:20px;">';
1789  if ( !@empty( $included_files ) )
1790  {
1791  $a = 1;
1792  foreach ( $included_files as $filename )
1793  {
1794  $div .= $a . ' ' . @static::_buildTraceLink( $filename ) . $filename . '</a>';
1795  if ( $_SERVER[ 'SCRIPT_FILENAME' ] == $filename )
1796  {
1797  $div .= ' <span style="font-weight:bold;color:red;">';
1798  $div .= '&laquo; Main File</span>';
1799  }
1800  $div .= "<br>\n";
1801  $a++;
1802  }
1803  }
1804  else { $div .= '<span class="vars">Could not get included files!</span>'; }
1805  $div .= '</div>';
1806  $div .= static::_buildInnerVars( 'options' , 'Configuration' , static::$_options );
1807  $constants = @get_defined_constants( true );
1808  $div .= static::_buildInnerVars( 'constants' , 'Constants' , $constants );
1809  $functions = @get_defined_functions( );
1810  $div .= static::_buildInnerVars( 'functionsInternal' , 'Internal Functions' ,
1811  @$functions[ 'internal' ] );
1812  $div .= static::_buildInnerVars( 'functionsUser' , 'User Functions' , @$functions[ 'user' ] );
1813  $div.=static::_buildInnerVars( 'declared_classes' , 'Declared Classes' ,
1814  $classes = @get_declared_classes( ) );
1815  $div.=static::_buildInnerVars( 'declared_interfaces' , 'Declared Interfaces' ,
1816  $interfaces = @get_declared_interfaces( ) );
1817  $div .= static::_buildInnerVars( 'phpInfo' , 'Php Config' , $php_info = static::_buildPhpInfo( ) );
1818  if ( !static::$_options[ 'show_globals' ] )
1819  {
1820  $div .= '<span class="vars">Global Vars Disabled</span>';
1821  }
1822  else { $div .= static::_buildInnerVars( 'globals' , 'Globals ' , array_reverse( $GLOBALS ) ); }
1823  return $div .= '</div>';
1824  }
1825  /**
1826  * Builds the inner vars div
1827  * @param string $panelId the id of the panel to show/hide
1828  * @param string $linkTitle the title of the link
1829  * @param string $array array of parameters
1830  */
1831  protected static function _buildInnerVars( $panelId , $linkTitle , $array )
1832  {
1833  $div = '<div id="' . $panelId . '" class="vars vars-config" ';
1834  $div .= 'style="line-height:20px;font-size:14px;"><span>' . $linkTitle;
1835  $div .= '</span> '. @static::_doDump( $array );
1836  return $div .= '</div>';
1837  }
1838  /**
1839  * Builds the W3C panel
1840  */
1841  protected static function _buildW3cPanel( )
1842  {
1843  $uri = parse_url( $_SERVER[ 'REQUEST_URI' ] );
1844  if ( @$uri[ 'query' ] )
1845  {
1846  $query = '?';
1847  $parts = explode( '&' , $uri[ 'query' ] );
1848  foreach ( $parts as $k => $v )
1849  {
1850  if ( $v != static::$_options[ 'url_key' ] . '=' . static::$_options[ 'url_pass' ] )
1851  {
1852  $query .= ( $k == 0 ) ? $v : '&' . $v;
1853  }
1854  }
1855  }
1856  $div = '<div id="w3cPanel" style="display:none;" class="innerTable">';
1857  if ( static::$_options[ 'show_w3c' ] )
1858  {
1859  $div .= '<p>Click on the WC3 link to verify the validation or to check errors</p>';
1860  $div .= '<p><a href="http://validator.w3.org/check?uri=' . $_SERVER[ 'HTTP_HOST' ] .
1861  $uri[ 'path' ] . @$query . '" target="_blank">';
1862  $div .= '<img src="http://www.w3.org/Icons/WWW/w3c_home_nb" alt="W3C Validator"></a></p>';
1863  $div .= '<p>Or copy paste the source here ';
1864  $div .= '<a href="http://validator.w3.org/#validate_by_input" target="_blank">';
1865  $div .= 'http://validator.w3.org/#validate_by_input</a></p>';
1866  }
1867  else { $div .= '<span class="vars">Panel is Disabled</span>'; }
1868  $div .= '</div>';
1869  return $div = static::_compressHtml( $div );
1870  }
1871  /**
1872  * Formats phpinfo() function
1873  */
1874  protected static function _buildPhpInfo( )
1875  {
1876  $php_array = static::_phpInfoArray( );
1877  $php_array[ 'version' ] = @phpversion( );
1878  $php_array[ 'os' ] = @php_uname( );
1879  $php_array[ 'extensions' ] = @get_loaded_extensions( );
1880  ksort( $php_array );
1881  return $php_array;
1882  }
1883  /**
1884  * Includes the css for the interface
1885  */
1886  protected static function _includeCss( )
1887  {
1888  return static::_compressHtml( '<style type="text/css">' . str_replace( array( '{PANEL_TOP}' ,
1889  '{PANEL_RIGHT}' ) , array( static::$_options[ 'panel_top' ] ,
1890  static::$_options[ 'panel_right' ] ) , static::$_panelCss ) . '</style>' );
1891  }
1892  /**
1893  * Includes the javascript for the interface
1894  */
1895  protected static function _includeJs( )
1896  {
1897  return static::_compressHtml(
1898  '<script>
1899  var activePanelID=false;
1900  var panels=new Object;panels.msg="msgPanel";panels.vars="varsPanel";
1901  panels.sql="sqlPanel";panels.w3c="w3cPanel";panels.timer="timerPanel";
1902  panels.analysis="analysisPanel";
1903  function ptc_show_panel(elId,panelTitle,el)
1904  {
1905  var floatDivId="ptcDebugPanel";
1906  var tabs=document.getElementById(\'floatingTab\').getElementsByTagName("a");
1907  for(var i=0;i<tabs.length;i++){tabs[i].className="";}
1908  if(document.getElementById(elId).style.display=="none")
1909  {
1910  ptc_reset_panels();
1911  document.getElementById(elId).style.display=\'\';
1912  document.getElementById(\'ptcDebugStatusBar\').style.display=\'\';
1913  document.getElementById(floatDivId).style.width=\'100%\';
1914  el.className="active";activePanelID=elId;ptc_set_title(panelTitle);
1915  }
1916  else
1917  {
1918  document.getElementById(\'ptcDebugPanelTitle\').style.display=\'none\';
1919  ptc_reset_panels();
1920  document.getElementById(floatDivId).style.width=\'\';
1921  }
1922  return false;
1923  };
1924  function ptc_reset_panels()
1925  {
1926  document.getElementById(\'ptcDebugStatusBar\').style.display=\'none\';
1927  for(var i in panels){document.getElementById(panels[i]).style.display=\'none\';}
1928  };
1929  function ptc_set_title(panelTitle)
1930  {
1931  document.getElementById(\'ptcDebugPanelTitle\').style.display=\'\';
1932  document.getElementById(\'ptcDebugPanelTitle\').innerHTML=\'<h1>\'+panelTitle+\'</h1>\';
1933  };
1934  function hideInterface(){document.getElementById(\'ptcDebugPanel\').style.display=\'none\';};
1935  function ptc_show_vars(elId,link)
1936  {
1937  var element=document.getElementById(elId).style;
1938  if(element.display=="none")
1939  {
1940  link.innerHTML=link.innerHTML.replace("\u21d3","\u21d1");
1941  element.display=\'\';
1942  }
1943  else
1944  {
1945  link.innerHTML=link.innerHTML.replace("\u21d1","\u21d3");
1946  element.display=\'none\';
1947  }
1948  };
1949  function ptc_show_string(elId,link)
1950  {
1951  if(document.getElementById(elId).style.display=="none")
1952  {
1953  link.innerHTML=link.innerHTML.replace("\u21d3","\u21d1");
1954  document.getElementById(elId).style.display=\'inline\';
1955  document.getElementById(elId+"-span").style.display=\'none\';
1956  }
1957  else
1958  {
1959  link.innerHTML=link.innerHTML.replace("\u21d1","\u21d3");
1960  document.getElementById(elId+"-span").style.display=\'\';
1961  document.getElementById(elId).style.display=\'none\';
1962  }
1963  };
1964  function ptc_show_trace(className,link)
1965  {
1966  var elements=document.getElementsByClassName(\'\'+className+\'\');
1967  for(i in elements)
1968  {
1969  if(elements[i].hasOwnProperty(\'style\'))
1970  {
1971  if(elements[i].style.display=="none")
1972  {
1973  link.innerHTML=link.innerHTML.replace("\u21d3","\u21d1");
1974  elements[i].style.display=\'\';
1975  }
1976  else
1977  {
1978  link.innerHTML=link.innerHTML.replace("\u21d1","\u21d3");
1979  elements[i].style.display=\'none\';
1980  }
1981  }
1982  }
1983  };
1984  function ptc_read_code(filename,line)
1985  {
1986  var query="http://' . addslashes( $_SERVER[ 'HTTP_HOST' ] ) .
1987  $path = addslashes( str_replace( realpath( $_SERVER[ 'DOCUMENT_ROOT' ] ) ,
1988  '' , realpath( dirname( __FILE__ ) ) ) ) . '/PtcDebug.php?ptc_read_file="+filename;
1989  if(line){query+="&ptc_read_line="+line;}
1990  newwindow=window.open(query,"name","height=350,width=820");
1991  if(window.focus){newwindow.focus()};
1992  return false;
1993  };
1994  function ptc_search_string( )
1995  {
1996  if ( !document.getElementsByName("ptc_search_files")[0].value )
1997  {
1998  alert( "Please type a search string!" );
1999  }
2000  else if ( !document.getElementsByName("ptc_search_path")[0].value )
2001  {
2002  alert( "Please type a search path!" );
2003  }
2004  else
2005  {
2006  var query="http://' . addslashes( $_SERVER[ 'HTTP_HOST' ] ) .
2007  $path = addslashes( str_replace( realpath( $_SERVER[ 'DOCUMENT_ROOT' ] ) ,
2008  '' , realpath( dirname( __FILE__ ) ) ) ) .
2009  '/PtcDebug.php?ptc_search_files="+document.getElementsByName("ptc_search_files")[0].value;
2010  query+="&ptc_search_path="+document.getElementsByName("ptc_search_path")[0].value;
2011  newwindow=window.open(query,"name","height=350,width=1220");
2012  if(window.focus){newwindow.focus()};
2013  }
2014  return false;
2015  };
2016  function ptc_filter_categories( tableId , catId )
2017  {
2018  var table=document.getElementById(tableId);
2019  var trs=table.getElementsByTagName("tr");
2020  if(catId=="showAll"){for(var i=1; i<trs.length; i++){trs[i].style.display="";}}
2021  else
2022  {
2023  for(var i=1; i<trs.length; i++){trs[i].style.display="none";}
2024  var cur_cat=document.getElementsByClassName(catId);
2025  for(var i=0; i<cur_cat.length; ++i){cur_cat[i].style.display="";}
2026  }
2027  };
2028  function ptc_show_trace_table( className , link )
2029  {
2030  var panel = document.getElementsByClassName( className );
2031  if ( panel[ 0 ].style.display == "none" )
2032  {
2033  link.innerHTML=link.innerHTML.replace( "\u21d3" , "\u21d1" );
2034  panel[ 0 ].style.display = "";
2035  }
2036  else
2037  {
2038  link.innerHTML=link.innerHTML.replace( "\u21d1" , "\u21d3" );
2039  panel[ 0 ].style.display = "none";
2040  }
2041  };
2042  window.onload=function( )
2043  {
2044  var div=document.getElementById("ptcDebugStatusBar");
2045  var press=false;
2046  div.onmousedown=function(){press=true;return false;};
2047  this.onmouseover=div.style.cursor="s-resize";
2048  this.onmousemove=function(event)
2049  {
2050  event=event ? event : window.event;
2051  if(press===true && activePanelID)
2052  {
2053  document.getElementById(activePanelID).style.height=(event.clientY-49)+"px";
2054  }
2055  };
2056  this.onmouseup=function(){press=false;};
2057  };
2058  /*function ptc_minimize( )
2059  {
2060  var floatDivId="ptcDebugPanel";resetPanels();
2061  document.getElementById(floatDivId).style.width=\'300px\';
2062  return false;
2063  };*/
2064  </script>' );
2065  }
2066  /**
2067  * Compresses the html before render
2068  * @param string $html some html code
2069  */
2070  protected static function _compressHtml( $html )
2071  {
2072  if ( static::$_options[ 'minified_html' ] )
2073  {
2074  $html = preg_replace( '!/\*[^*]*\*+([^/][^*]*\*+)*/!' , '' , $html ); // remove comments
2075  $html = str_replace( array ( "\r\n" , "\r" , "\n" , "\t" , ' ' , ' ' , ' ' ) , '' , $html ); // tabs,newlines,etc.
2076  }
2077  return $html;
2078  }
2079  /**
2080  * Formats phpinfo() into an array
2081  */
2082  protected static function _phpInfoArray( )
2083  {
2084  ob_start( );
2085  @phpinfo( );
2086  $info_arr = array( );
2087  $info_lines = explode( "\n" , strip_tags( ob_get_clean( ) , "<tr><td><h2>" ) );
2088  $cat= 'General';
2089  $reg_ex = "~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~";
2090  foreach ( $info_lines as $line )
2091  {
2092  preg_match( "~<h2>(.*)</h2>~" , $line , $title) ? $cat = $title[ 1 ] : null; // new cat?
2093  if ( preg_match( "~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~" , $line , $val ) )
2094  {
2095  $info_arr[ $cat ][ $val[ 1 ] ] = $val[ 2 ];
2096  }
2097  else if ( preg_match( $reg_ex , $line , $val ) )
2098  {
2099  $info_arr[ $cat ][ $val[1] ] = array( 'local' => $val[ 2 ] , 'master' => $val[ 3 ] );
2100  }
2101  }
2102  return $info_arr;
2103  }
2104  /**
2105  * Attempts to disable any detetected opcode caches / optimizers
2106  */
2107  protected static function _disableOpcodeCache( )
2108  {
2109  if ( extension_loaded( 'xcache' ) )
2110  {
2111  // will be implemented in 2.0, here for future proofing
2112  @ini_set( 'xcache.optimizer', false );
2113  // xcache seems to do some optimizing, anyway..
2114  }
2115  else if ( extension_loaded( 'apc' ) )
2116  {
2117  @ini_set( 'apc.optimization', 0 ); // removed in apc 3.0.13 (2007-02-24)
2118  apc_clear_cache();
2119  }
2120  else if ( extension_loaded( 'eaccelerator' ) )
2121  {
2122  @ini_set( 'eaccelerator.optimizer', 0 );
2123  if ( function_exists( 'eaccelerator_optimizer' ) )
2124  {
2125  @eaccelerator_optimizer( false );
2126  }
2127  // try setting eaccelerator.optimizer = 0 in a .user.ini or .htaccess file
2128  }
2129  else if (extension_loaded( 'Zend Optimizer+' ) )
2130  {
2131  @ini_set('zend_optimizerplus.optimization_level', 0);
2132  }
2133  }
2134  /**
2135  * Function calls trace engine
2136  * @param array $trace the php debug_backtrace( ) result
2137  */
2138  protected static function _traceFunctionCalls( $trace = null )
2139  {
2140  $depth = 10;
2141  $trace = ( !$trace ) ? debug_backtrace( true ) : $trace;
2142  $i= 1 ;
2143  $methods = get_class_methods( get_called_class( ) );
2144  foreach ( $trace as $k => $v )
2145  {
2146  if ( @$v[ 'class' ] == get_called_class( ) || @in_array( $v[ 'function' ] , $methods ) ||
2147  @in_array( $trace[ $k + 1 ][ 'function' ] , $methods ))
2148  {
2149  continue;
2150  }
2151  if( $depth === $i ){ break; }
2152  $new_array = array
2153  (
2154  //'ns' => $exe_time
2155  //'memory' => memory_get_usage( true ),
2156  'file' => @$v[ 'file' ] ,
2157  'line' => @$v[ 'line' ] ,
2158  'args' => @$v[ 'args' ],
2159  'function' => @$v[ 'class' ] . @$v[ 'type' ] . @$v[ 'function' ] ,
2160  );
2161  if ( @$trace[ $k + 1 ][ 'function' ] || @$trace[ $k + 1 ][ 'class' ] )
2162  {
2163  $new_array[ 'called_by' ] = @$trace[ $k + 1 ][ 'class' ] .
2164  @$trace[ $k + 1 ][ 'type' ] . @$trace[ $k + 1 ][ 'function' ];
2165  $new_array[ 'called_by_args' ] = @$trace[ $k + 1 ][ 'args' ];
2166  $new_array[ 'in' ] = @$trace[ $k + 1 ][ 'file' ];
2167  $new_array[ 'on_line' ] = @$trace[ $k + 1 ][ 'line' ];
2168  }
2169  @static::$_traceData[ ] = array_filter( $new_array );
2170  $i++;
2171  }
2172  unset( $new_array );
2173  unset( $trace );
2174  }
2175  /**
2176  * Removes html entities from the buffer
2177  * @param string $var some string
2178  */
2179  protected static function _cleanBuffer( $var )
2180  {
2181  return ( @is_string( $var ) ) ? @htmlentities( $var ) : $var;
2182  }
2183  /**
2184  * Retrieves the session var for the ptcdebug class
2185  * @param string $var the session var to retrieve
2186  */
2187  protected static function _getSessionVars( $var = null )
2188  {
2189  return ( $var ) ? @$_SESSION[ 'ptcdebug' ][ $var ] : @$_SESSION[ 'ptcdebug' ];
2190  }
2191  /**
2192  * Shows the search popup window with the result
2193  * @param string $string a search string to search for
2194  * @param string $path a start path where to search for a string recursively
2195  */
2196  public static function showSearchPopup( $string , $path = null )
2197  {
2198  $path = ( $path ) ? $path : dirname( __FILE__ );
2199  static::$_options[ 'minified_html' ] = false;
2200  static::$_options[ 'panel_top' ] = '0px';
2201  static::$_options[ 'panel_right' ] = '0px';
2202  $result = static::_includeCss( );
2203  $result .= '<div style="background: #eee;color: #333;height:100%;">';
2204  $result .= '<table class="msgTable" id="searchString" border="1" style="width:100%;">';
2205  $result .= '<tbody><tr><th>#</th><th>file</th><th>line</th>';
2206  $result .= '<th>string</th><th>occurences</th></tr>';
2207  $result .= PtcDebug::findString( $string , $path );
2208  $result = str_replace( $path , '' , $result );
2209  return $result . '</tbody></table></div>';
2210  }
2211  }
2212  /**
2213  * Calls highlight file method to show source code, session_start() must be active for security reasons
2214  */
2215  if ( @$_GET[ 'ptc_read_file' ] )
2216  {
2217  @session_start( );
2218  if ( !@$_SESSION[ 'ptcdebug' ][ 'code_highlighter' ] ) { exit( ); }
2219  echo PtcDebug::highlightFile( $_GET[ 'ptc_read_file' ] , @$_GET[ 'ptc_read_line' ] );
2220  exit( );
2221  }
2222  /**
2223  * Shows a popup with string search results, session_start() must be active for security reasons
2224  */
2225  if ( @$_GET[ 'ptc_search_files' ] )
2226  {
2227  @session_start( );
2228  if ( !@$_SESSION[ 'ptcdebug' ][ 'search_files' ] ) { exit( ); }
2229  echo PtcDebug::showSearchPopup( $_GET[ 'ptc_search_files' ] , @$_GET[ 'ptc_search_path' ] );
2230  exit( );
2231  }
static $_consoleStarted
Decides if we should send the buffer to the PhpConsole class.
Definition: PtcDebug.php:637
static $_codeCoverage
Code coverage analysis property to start coverage.
Definition: PtcDebug.php:653
static convertMemUsage($val, $precision=2)
Convert memory_usage( ) into a readable format.
Definition: PtcDebug.php:364
static stopTimer($reference=null, $precision=1)
Monitors the execution of php code, or sql queries based on a reference.
Definition: PtcDebug.php:334
static _buildW3cPanel()
Builds the W3C panel.
Definition: PtcDebug.php:1841
static _includeJs()
Includes the javascript for the interface.
Definition: PtcDebug.php:1895
static bufferSql($string, $statement=null, $category=null)
Writes data to the sql panel.
Definition: PtcDebug.php:324
static $_defaultOptions
Default options for the debug class.
Definition: PtcDebug.php:568
static _debugConsole()
Sends the buffer to the PhpConsole class.
Definition: PtcDebug.php:726
static getCoverage()
Retrieves the code coverage analysis data stored in the PtcDebug::$_finalCoverageData property...
Definition: PtcDebug.php:27
static showSearchPopup($string, $path=null)
Shows the search popup window with the result.
Definition: PtcDebug.php:2196
static startTrace()
Starts the function calls trace utility.
Definition: PtcDebug.php:248
static _cleanBuffer($var)
Removes html entities from the buffer.
Definition: PtcDebug.php:2179
static stopCoverage()
Stops the code coverage analysis utility.
Definition: PtcDebug.php:233
static _watchCallback()
Callback function that checks if a given variable has changed.
Definition: PtcDebug.php:928
static _disableOpcodeCache()
Attempts to disable any detetected opcode caches / optimizers.
Definition: PtcDebug.php:2107
static getBuffer()
Returns the buffer array.
Definition: PtcDebug.php:23
static _findWatchVar($variableName)
Retrieves the variable to watch from the &quot;$GLOBALS&quot;.
Definition: PtcDebug.php:1019
static $_countTime
Exclude PtcDebug::$_buildBuffer from execution timing property.
Definition: PtcDebug.php:649
static $_buffer
The debug buffer.
Definition: PtcDebug.php:625
static processBuffer()
Processes the buffer to show the interface and/or the console messages.
Definition: PtcDebug.php:427
static addToBuffer($reference, $string, $statement=null)
Attaches a message to the end of the buffer array to add data based on a reference.
Definition: PtcDebug.php:405
static _codeCoverageAnalysis($backtrace=null)
Collect data for code coverage analysis.
Definition: PtcDebug.php:975
static _setSessionVars()
Sets session vars to control which panels will be shown.
Definition: PtcDebug.php:808
static $_finalTraceData
Final data array for the function calls trace.
Definition: PtcDebug.php:617
static findString($query, $path=null, $last=1)
Searches files for a string inside a given folder recursively.
Definition: PtcDebug.php:461
static addCss($css)
Adds style properties to the floating panel styles array.
Definition: PtcDebug.php:32
static $_watchedVars
Array of watched variables declared.
Definition: PtcDebug.php:641
static $_traceData
Function calls tracing storage property.
Definition: PtcDebug.php:613
static $_finalCoverageData
Final data array for the code coveage.
Definition: PtcDebug.php:609
static _phpInfoArray()
Formats phpinfo() into an array.
Definition: PtcDebug.php:2082
static highlightFile($file, $line=null)
File highlighter that opens a popup window inspect source code.
Definition: PtcDebug.php:523
static startCoverage()
Starts the code coverage analysis utility to find executed lines.
Definition: PtcDebug.php:217
static _traceFunctionCalls($trace=null)
Function calls trace engine.
Definition: PtcDebug.php:2138
static errorHandler($errno, $errstr, $errfile, $errline)
Handles php errors.
Definition: PtcDebug.php:378
static _compressHtml($html)
Compresses the html before render.
Definition: PtcDebug.php:2070
static _buildInnerVars($panelId, $linkTitle, $array)
Builds the inner vars div.
Definition: PtcDebug.php:1831
static bufferLog($string, $statement=null, $category=null)
Writes data to the messages panel.
Definition: PtcDebug.php:314
static $_endTime
Application end time.
Definition: PtcDebug.php:633
static _checkAccess($allowedIps=null)
Checks if a given ip has access.
Definition: PtcDebug.php:793
static setErrorHandler($dieOnFatal=true)
Sets the error handler to be the debug class.
Definition: PtcDebug.php:57
static tickHandler()
The ticks handler to execute all tickable functions.
Definition: PtcDebug.php:194
static checkReferer()
Checks if the debug &quot;url_key&quot; and &quot;url_pass&quot; are set on the referer url.
Definition: PtcDebug.php:37
static $_startTime
Application start time.
Definition: PtcDebug.php:629
static $_excludeFromTrace
Exclude functions from the function calls trace array.
Definition: PtcDebug.php:665
static exceptionHandler($exception)
Exception handler, catches exceptions that are not in a try/catch block.
Definition: PtcDebug.php:392
static watch($variableName, $callback=null)
Watches a variable that is in a declare(ticks=n); code block, for changes.
Definition: PtcDebug.php:290
static excludeFromTrace($functions)
Excludes functions from the function calls tracing engine.
Definition: PtcDebug.php:280
static $_panelCss
Property that holds the css for the floating panel.
Definition: PtcDebug.php:669
static load($options=null)
Loads the debug interface and/or the console class if requested.
Definition: PtcDebug.php:73
static $_options
Array with all options.
Definition: PtcDebug.php:621
static _disablePanels()
Controls which panels will be shown with $_GET variable &quot;hidepanels&quot;.
Definition: PtcDebug.php:818
static $_functionTrace
Function calls trace property to start the analysis.
Definition: PtcDebug.php:657
static _buildBuffer($type, $string, $statement=null, $category=null)
Builds the buffer.
Definition: PtcDebug.php:859
static $_coverageData
Code coverage analysis storage.
Definition: PtcDebug.php:605
static _formatVar($var)
Evaluates the type of variable for output.
Definition: PtcDebug.php:1000
static _buildPhpInfo()
Formats phpinfo() function.
Definition: PtcDebug.php:1874
static _includeCss()
Includes the css for the interface.
Definition: PtcDebug.php:1886
static $_excludeMethods
Array of methods excluded from the backtrace.
Definition: PtcDebug.php:601
static $_tickTime
Tick execution time property.
Definition: PtcDebug.php:645
static _getSessionVars($var=null)
Retrieves the session var for the ptcdebug class.
Definition: PtcDebug.php:2187
static stopTrace()
Stops the function calls trace utility.
Definition: PtcDebug.php:264
static $_disableOpcode
Controlls when to disable opcode cache.
Definition: PtcDebug.php:661