Changeset View
Changeset View
Standalone View
Standalone View
branches/5.2.x/core/kernel/utility/debugger.php
Show First 20 Lines • Show All 203 Lines • ▼ Show 20 Line(s) | |||||
* Holds reference to global KernelApplication instance | * Holds reference to global KernelApplication instance | ||||
* | * | ||||
* @var kApplication | * @var kApplication | ||||
* @access private | * @access private | ||||
*/ | */ | ||||
private $Application = null; | private $Application = null; | ||||
/** | /** | ||||
* Set to true if fatal error occurred | * Stores last fatal error hash or 0, when no fatal error happened | ||||
* | * | ||||
* @var bool | * @var integer | ||||
* @access private | |||||
*/ | */ | ||||
private $IsFatalError = false; | private $_fatalErrorHash = 0; | ||||
/** | |||||
* Tells if last error (if any) caught by shutdown function was processed | |||||
* | |||||
* @var bool | |||||
* @access private | |||||
*/ | |||||
private $_lastErrorProcessed = false; | |||||
/** | /** | ||||
* Counts warnings on the page | * Counts warnings on the page | ||||
* | * | ||||
* @var int | * @var int | ||||
* @access public | * @access public | ||||
*/ | */ | ||||
public $WarningCount = 0; | public $WarningCount = 0; | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Line(s) | |||||
public $IncludeLevel = 0; | public $IncludeLevel = 0; | ||||
/** | /** | ||||
* Prevents report generation more then once | * Prevents report generation more then once | ||||
* | * | ||||
* @var bool | * @var bool | ||||
* @access private | * @access private | ||||
*/ | */ | ||||
private $reportDone = false; | private $_inReportPrinting = false; | ||||
/** | /** | ||||
* Transparent spacer image used in case of none spacer image defined via SPACER_URL constant. | * Transparent spacer image used in case of none spacer image defined via SPACER_URL constant. | ||||
* Used while drawing progress bars (memory usage, time usage, etc.) | * Used while drawing progress bars (memory usage, time usage, etc.) | ||||
* | * | ||||
* @var string | * @var string | ||||
* @access private | * @access private | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 1093 Lines • ▼ Show 20 Line(s) | |||||
} | } | ||||
$this->ProfilePoints[$title][$location]++; | $this->ProfilePoints[$title][$location]++; | ||||
} | } | ||||
/** | /** | ||||
* Generates report | * Generates report | ||||
* | * | ||||
* @param bool $returnResult | * @param boolean $return_result Returns or output report contents. | ||||
* @param bool $clean_output_buffer | * @param boolean $clean_output_buffer Clean output buffers before displaying anything. | ||||
* @param boolean $is_shutdown_func Called from shutdown function. | |||||
* | * | ||||
* @return string | * @return string | ||||
* @access public | |||||
*/ | */ | ||||
public function printReport($returnResult = false, $clean_output_buffer = true) | public function printReport($return_result = false, $clean_output_buffer = true, $is_shutdown_func = false) | ||||
{ | { | ||||
if ( $this->reportDone ) { | if ( $this->_inReportPrinting ) { | ||||
// don't print same report twice (in case if shutdown function used + compression + fatal error) | // don't print same report twice (in case if shutdown function used + compression + fatal error) | ||||
return ''; | return ''; | ||||
} | } | ||||
$this->_inReportPrinting = true; | |||||
$last_error = error_get_last(); | $last_error = error_get_last(); | ||||
if ( !is_null($last_error) && !$this->_lastErrorProcessed ) { | if ( !is_null($last_error) && $is_shutdown_func ) { | ||||
$this->_lastErrorProcessed = true; | $this->saveError( | ||||
$this->saveError($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']); | $last_error['type'], | ||||
$last_error['message'], | |||||
$last_error['file'], | |||||
$last_error['line'], | |||||
null, | |||||
$is_shutdown_func | |||||
); | |||||
} | } | ||||
$this->profileFinish('script_runtime'); | $this->profileFinish('script_runtime'); | ||||
$this->breakOutofBuffering(!$returnResult); | $this->_breakOutOfBuffering(!$return_result); | ||||
$debugger_start = memory_get_usage(); | $debugger_start = memory_get_usage(); | ||||
if ( defined('SPACER_URL') ) { | if ( defined('SPACER_URL') ) { | ||||
$this->dummyImage = SPACER_URL; | $this->dummyImage = SPACER_URL; | ||||
} | } | ||||
$this->InitReport(); // set parameters required by AJAX | $this->InitReport(); // set parameters required by AJAX | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Line(s) | |||||
$i++; | $i++; | ||||
} | } | ||||
fclose($fp); | fclose($fp); | ||||
} | } | ||||
if ( $skip_reporting ) { | if ( $skip_reporting ) { | ||||
// let debugger write report and then don't output anything | // let debugger write report and then don't output anything | ||||
$this->reportDone = true; | |||||
return ''; | return ''; | ||||
} | } | ||||
$application =& kApplication::Instance(); | $application =& kApplication::Instance(); | ||||
$dbg_path = str_replace(FULL_PATH, '', $this->tempFolder); | $dbg_path = str_replace(FULL_PATH, '', $this->tempFolder); | ||||
$debugger_params = Array ( | $debugger_params = Array ( | ||||
'RowSeparator' => $this->rowSeparator, | 'RowSeparator' => $this->rowSeparator, | ||||
'ErrorsCount' => (int)$this->getProfilerTotal('error_handling'), | 'ErrorsCount' => (int)$this->getProfilerTotal('error_handling'), | ||||
'IsFatalError' => $this->IsFatalError, | 'IsFatalError' => $this->_fatalErrorHappened(), | ||||
'SQLCount' => (int)$this->getProfilerTotal('sql'), | 'SQLCount' => (int)$this->getProfilerTotal('sql'), | ||||
'SQLTime' => isset($this->ProfilerTotals['sql']) ? sprintf('%.5f', $this->ProfilerTotals['sql']) : 0, | 'SQLTime' => isset($this->ProfilerTotals['sql']) ? sprintf('%.5f', $this->ProfilerTotals['sql']) : 0, | ||||
'ScriptTime' => sprintf('%.5f', $this->ProfilerData['script_runtime']['ends'] - $this->ProfilerData['script_runtime']['begins']), | 'ScriptTime' => sprintf('%.5f', $this->ProfilerData['script_runtime']['ends'] - $this->ProfilerData['script_runtime']['begins']), | ||||
'ScriptMemory' => DebuggerUtil::formatSize($this->getMemoryUsed($debugger_start)), | 'ScriptMemory' => DebuggerUtil::formatSize($this->getMemoryUsed($debugger_start)), | ||||
'Shortcut' => DBG_SHORTCUT, | 'Shortcut' => DBG_SHORTCUT, | ||||
); | ); | ||||
ob_start(); | ob_start(); | ||||
Show All 11 Lines | |||||
$Debugger.DOMViewerURL = '<?php echo constant('DBG_DOMVIEWER'); ?>'; | $Debugger.DOMViewerURL = '<?php echo constant('DBG_DOMVIEWER'); ?>'; | ||||
$Debugger.DebugURL = '<?php echo $this->baseURL.'/debugger_responce.php?sid='.$this->rowSeparator.'&path='.urlencode($dbg_path); ?>'; | $Debugger.DebugURL = '<?php echo $this->baseURL.'/debugger_responce.php?sid='.$this->rowSeparator.'&path='.urlencode($dbg_path); ?>'; | ||||
$Debugger.EventURL = '<?php echo /*is_object($application->Factory) &&*/ $application->InitDone ? $application->HREF('dummy', '', Array ('pass' => 'm', '__NO_REWRITE__' => 1)) : ''; ?>'; | $Debugger.EventURL = '<?php echo /*is_object($application->Factory) &&*/ $application->InitDone ? $application->HREF('dummy', '', Array ('pass' => 'm', '__NO_REWRITE__' => 1)) : ''; ?>'; | ||||
$Debugger.BasePath = '<?php echo $this->basePath; ?>'; | $Debugger.BasePath = '<?php echo $this->basePath; ?>'; | ||||
<?php | <?php | ||||
$is_install = defined('IS_INSTALL') && IS_INSTALL; | $is_install = defined('IS_INSTALL') && IS_INSTALL; | ||||
if ( $this->IsFatalError || (!$is_install && DBG_RAISE_ON_WARNINGS && $this->WarningCount) ) { | if ( $this->_fatalErrorHappened() | ||||
|| (!$is_install && DBG_RAISE_ON_WARNINGS && $this->WarningCount) | |||||
) { | |||||
echo '$Debugger.Toggle();'; | echo '$Debugger.Toggle();'; | ||||
} | } | ||||
if ( DBG_TOOLBAR_BUTTONS ) { | if ( DBG_TOOLBAR_BUTTONS ) { | ||||
echo '$Debugger.AddToolbar("$Debugger");'; | echo '$Debugger.AddToolbar("$Debugger");'; | ||||
} | } | ||||
?> | ?> | ||||
window.focus(); | window.focus(); | ||||
</script> | </script> | ||||
<?php | <?php | ||||
if ( $returnResult ) { | if ( $return_result ) { | ||||
$ret = ob_get_contents(); | $ret = ob_get_contents(); | ||||
if ( $clean_output_buffer ) { | if ( $clean_output_buffer ) { | ||||
ob_end_clean(); | ob_end_clean(); | ||||
} | } | ||||
$ret .= $this->getShortReport($this->getMemoryUsed($debugger_start)); | $ret .= $this->getShortReport($this->getMemoryUsed($debugger_start)); | ||||
$this->reportDone = true; | |||||
return $ret; | return $ret; | ||||
} | } | ||||
else { | else { | ||||
if ( !DebuggerUtil::constOn('DBG_HIDE_FULL_REPORT') ) { | if ( !DebuggerUtil::constOn('DBG_HIDE_FULL_REPORT') ) { | ||||
$this->breakOutofBuffering(); | $this->_breakOutOfBuffering(); | ||||
} | } | ||||
elseif ( $clean_output_buffer ) { | elseif ( $clean_output_buffer ) { | ||||
ob_clean(); | ob_clean(); | ||||
} | } | ||||
echo $this->getShortReport($this->getMemoryUsed($debugger_start)); | |||||
$this->reportDone = true; | echo $this->getShortReport($this->getMemoryUsed($debugger_start)); | ||||
} | } | ||||
return ''; | return ''; | ||||
} | } | ||||
function getMemoryUsed($debugger_start) | function getMemoryUsed($debugger_start) | ||||
{ | { | ||||
if ( !isset($this->ProfilerTotals['error_handling']) ) { | if ( !isset($this->ProfilerTotals['error_handling']) ) { | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Line(s) | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return '<br /><table class="dbg_stats_table"><tr><td style="border-color: #FFFFFF;"><table class="dbg_stats_table" align="left">' . $ret . '</table></td></tr></table>'; | return '<br /><table class="dbg_stats_table"><tr><td style="border-color: #FFFFFF;"><table class="dbg_stats_table" align="left">' . $ret . '</table></td></tr></table>'; | ||||
} | } | ||||
/** | /** | ||||
* User-defined error handler | * Detects if there was a fatal error at some point | ||||
* | * | ||||
* @throws Exception | * @return boolean | ||||
* @param int $errno | */ | ||||
* @param string $errstr | private function _fatalErrorHappened() | ||||
* @param string $errfile | { | ||||
* @param int $errline | return $this->_fatalErrorHash !== 0; | ||||
* @param array $errcontext | } | ||||
* @return bool | |||||
* @access public | /** | ||||
* Creates error hash | |||||
* | |||||
* @param string $errfile File, where error happened. | |||||
* @param integer $errline Line in file, where error happened. | |||||
* | |||||
* @return integer | |||||
*/ | */ | ||||
public function saveError($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ()) | private function _getErrorHash($errfile, $errline) | ||||
{ | { | ||||
return crc32($errfile . ':' . $errline); | |||||
} | |||||
/** | |||||
* User-defined error handler | |||||
* | |||||
* @param integer $errno Error code. | |||||
* @param string $errstr Error message. | |||||
* @param string $errfile Error file. | |||||
* @param integer $errline Error line. | |||||
* @param array $errcontext Error context. | |||||
* @param boolean $is_shutdown_func Called from shutdown function. | |||||
* | |||||
* @return boolean | |||||
* @throws Exception When unknown error code given. | |||||
*/ | |||||
public function saveError( | |||||
$errno, | |||||
$errstr, | |||||
$errfile = null, | |||||
$errline = null, | |||||
array $errcontext = null, | |||||
$is_shutdown_func = false | |||||
) { | |||||
$this->ProfilerData['error_handling']['begins'] = memory_get_usage(); | $this->ProfilerData['error_handling']['begins'] = memory_get_usage(); | ||||
$errorType = $this->getErrorNameByCode($errno); | $errorType = $this->getErrorNameByCode($errno); | ||||
if (!$errorType) { | if (!$errorType) { | ||||
throw new Exception('Unknown error type [' . $errno . ']'); | throw new Exception('Unknown error type [' . $errno . ']'); | ||||
return false; | return false; | ||||
} | } | ||||
elseif ( substr($errorType, 0, 5) == 'Fatal' ) { | elseif ( substr($errorType, 0, 5) == 'Fatal' ) { | ||||
$this->IsFatalError = true; | $this->_fatalErrorHash = $this->_getErrorHash($errfile, $errline); | ||||
$this->appendTrace(4); | $this->appendTrace(4); | ||||
} | } | ||||
$this->expandError($errstr, $errfile, $errline); | $this->expandError($errstr, $errfile, $errline); | ||||
$this->Data[] = Array ( | $this->Data[] = Array ( | ||||
'no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline, | 'no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline, | ||||
'context' => $errcontext, 'debug_type' => 'error' | 'context' => $errcontext, 'debug_type' => 'error' | ||||
); | ); | ||||
$this->ProfilerData['error_handling']['ends'] = memory_get_usage(); | $this->ProfilerData['error_handling']['ends'] = memory_get_usage(); | ||||
$this->profilerAddTotal('error_handling', 'error_handling'); | $this->profilerAddTotal('error_handling', 'error_handling'); | ||||
if ($errorType == 'Warning') { | if ($errorType == 'Warning') { | ||||
$this->WarningCount++; | $this->WarningCount++; | ||||
} | } | ||||
if ( $this->IsFatalError ) { | if ( $this->_fatalErrorHappened() | ||||
// append debugger report to data in buffer & clean buffer afterwards | && $this->_getErrorHash($errfile, $errline) === $this->_fatalErrorHash | ||||
die( $this->breakOutofBuffering(false) . $this->printReport(true) ); | ) { | ||||
// Append debugger report to data in buffer & clean buffer afterwards. | |||||
echo $this->_breakOutOfBuffering(false) . $this->printReport(true); | |||||
if ( !$is_shutdown_func ) { | |||||
exit; | |||||
} | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Adds exception details into debugger but don't cause fatal error | * Adds exception details into debugger but don't cause fatal error | ||||
* | * | ||||
Show All 28 Lines | |||||
* | * | ||||
* @param Exception $exception | * @param Exception $exception | ||||
* @return void | * @return void | ||||
* @access public | * @access public | ||||
*/ | */ | ||||
public function saveException($exception) | public function saveException($exception) | ||||
{ | { | ||||
$this->appendException($exception); | $this->appendException($exception); | ||||
$this->IsFatalError = true; | $this->_fatalErrorHash = $this->_getErrorHash($exception->getFile(), $exception->getLine()); | ||||
// append debugger report to data in buffer & clean buffer afterwards | // Append debugger report to data in buffer & clean buffer afterwards. | ||||
die( $this->breakOutofBuffering(false) . $this->printReport(true) ); | echo $this->_breakOutOfBuffering(false) . $this->printReport(true); | ||||
} | } | ||||
/** | /** | ||||
* Transforms short error messages into long ones | * Transforms short error messages into long ones | ||||
* | * | ||||
* @param string $errstr | * @param string $errstr | ||||
* @param string $errfile | * @param string $errfile | ||||
* @param int $errline | * @param int $errline | ||||
Show All 21 Lines | |||||
/** | /** | ||||
* Break buffering in case if fatal error is happened in the middle | * Break buffering in case if fatal error is happened in the middle | ||||
* | * | ||||
* @param bool $flush | * @param bool $flush | ||||
* @return string | * @return string | ||||
* @access private | * @access private | ||||
*/ | */ | ||||
private function breakOutofBuffering($flush = true) | private function _breakOutOfBuffering($flush = true) | ||||
{ | { | ||||
$buffer_content = Array (); | $buffer_content = Array (); | ||||
while ( ob_get_level() ) { | while ( ob_get_level() ) { | ||||
$buffer_content[] = ob_get_clean(); | $buffer_content[] = ob_get_clean(); | ||||
} | } | ||||
$ret = implode('', array_reverse($buffer_content)); | $ret = implode('', array_reverse($buffer_content)); | ||||
if ( $flush ) { | if ( $flush ) { | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Line(s) | |||||
} | } | ||||
} | } | ||||
if ( !DebuggerUtil::constOn('DBG_ZEND_PRESENT') ) { | if ( !DebuggerUtil::constOn('DBG_ZEND_PRESENT') ) { | ||||
$debugger = new Debugger(); | $debugger = new Debugger(); | ||||
} | } | ||||
if ( DebuggerUtil::constOn('DBG_USE_SHUTDOWN_FUNC') ) { | if ( DebuggerUtil::constOn('DBG_USE_SHUTDOWN_FUNC') ) { | ||||
register_shutdown_function(Array (&$debugger, 'printReport')); | register_shutdown_function(array(&$debugger, 'printReport'), false, true, true); | ||||
} | |||||
} | } | ||||
} | |||||
No newline at end of file |