Index: kernel/utility/debugger.php =================================================================== --- kernel/utility/debugger.php (revision 14844) +++ kernel/utility/debugger.php (working copy) @@ -16,6 +16,9 @@ if( !class_exists('Debugger') ) { + /** + * Contains misc functions, used by debugger (mostly copied from kUtil class) + */ class DebuggerUtil { /** @@ -101,6 +104,14 @@ return $ip_match; } + /** + * Checks, that given ip belongs to given subnet + * + * @param string $network + * @param string $ip + * @return bool + * @access public + */ public static function netMatch($network, $ip) { $network = trim($network); @@ -125,7 +136,7 @@ return ($ip >= $from && $ip <= $to); } elseif (strpos($network, '/') !== false) { - // sigle subnet specified + // single subnet specified $ip_arr = explode('/', $network); if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) { @@ -145,125 +156,204 @@ } } + /** + * Main debugger class, that can be used with any In-Portal (or not) project + */ class Debugger { /** - * Holds reference to global KernelApplication instance - * - * @access public - * @var kApplication - */ - var $Application = null; + * Holds reference to global KernelApplication instance + * + * @var kApplication + * @access private + */ + private $Application = null; /** * Set to true if fatal error occurred * * @var bool + * @access private */ - var $IsFatalError = false; + private $IsFatalError = false; /** * Counts warnings on the page * * @var int + * @access public */ - var $WarningCount = 0; + public $WarningCount = 0; /** * Allows to track compile errors, like "stack-overflow" * * @var bool + * @access private */ - var $_compileError = false; + private $_compileError = false; /** * Debugger data for building report * * @var Array + * @access private */ - var $Data = Array(); + private $Data = Array (); - var $ProfilerData = Array(); - var $ProfilerTotals = Array(); - var $ProfilerTotalCount = Array(); + /** + * Holds information about each profiler record (start/end/description) + * + * @var Array + * @access private + */ + private $ProfilerData = Array (); - var $ProfilePoints = Array(); + /** + * Holds information about total execution time per profiler key (e.g. total sql time) + * + * @var Array + * @access private + */ + private $ProfilerTotals = Array (); /** + * Counts how much each of total types were called (e.g. total error count) + * + * @var Array + * @access private + */ + private $ProfilerTotalCount = Array (); + + /** + * Holds information about all profile points registered + * + * @var Array + * @access private + */ + private $ProfilePoints = Array (); + + /** * Prevent recursion when processing debug_backtrace() function results * * @var Array + * @access private */ - var $RecursionStack = Array(); + private $RecursionStack = Array (); - var $scrollbarWidth = 0; + /** + * Cross browser debugger report scrollbar width detection + * + * @var int + * @access private + */ + private $scrollbarWidth = 0; /** * Long errors are saved here, because trigger_error doesn't support error messages over 1KB in size * * @var Array + * @access private */ - var $longErrors = Array(); + private $longErrors = Array (); - var $IncludesData = Array(); - var $IncludeLevel = 0; + /** + * Remembers how much memory & time was spent on including files + * + * @var Array + * @access public + * @see kUtil::includeOnce + */ + public $IncludesData = Array (); - var $reportDone = false; + /** + * Remembers maximal include deep level + * + * @var int + * @access public + * @see kUtil::includeOnce + */ + public $IncludeLevel = 0; /** - * Transparent spacer image used in case of none spacer image defined via SPACER_URL contant. + * Prevents report generation more then once + * + * @var bool + * @access private + */ + private $reportDone = false; + + /** + * 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.) * * @var string + * @access private */ - var $dummyImage = ''; + private $dummyImage = ''; /** * Temporary files created by debugger will be stored here * * @var string + * @access private */ - var $tempFolder = ''; + private $tempFolder = ''; /** * Debug rows will be separated using this string before writing to debug file * * @var string + * @access private */ - var $rowSeparator = '@@'; + private $rowSeparator = '@@'; /** * Base URL for debugger includes * * @var string + * @access private */ - var $baseURL = ''; + private $baseURL = ''; /** + * Sub-folder, where In-Portal is installed + * + * @var string + * @access private + */ + private $basePath = ''; + + /** * Holds last recorded timestamp (for appendTimestamp) * * @var int + * @access private */ - var $LastMoment; + private $LastMoment; /** * Determines, that current request is AJAX request * * @var bool + * @access private */ - var $_isAjax = false; + private $_isAjax = false; + /** + * Creates instance of debugger + */ public function __construct() { global $start, $dbg_options; // check if user haven't defined DEBUG_MODE contant directly - if (defined('DEBUG_MODE') && DEBUG_MODE) { - die('error: contant DEBUG_MODE defined directly, please use $dbg_options array instead'); + if ( defined('DEBUG_MODE') && DEBUG_MODE ) { + die('error: constant DEBUG_MODE defined directly, please use $dbg_options array instead'); } // check IP before enabling debug mode - $ip_match = DebuggerUtil::ipMatch(isset($dbg_options['DBG_IP']) ? $dbg_options['DBG_IP'] : ''); + $ip_match = DebuggerUtil::ipMatch(isset($dbg_options['DBG_IP']) ? $dbg_options['DBG_IP'] : ''); if ( !$ip_match || (isset($_COOKIE['debug_off']) && $_COOKIE['debug_off']) ) { define('DEBUG_MODE', 0); @@ -277,9 +367,13 @@ $this->LastMoment = $start; error_reporting(E_ALL); - ini_set('display_errors', DebuggerUtil::constOn('DBG_ZEND_PRESENT') ? 0 : 1); // show errors on screen in case if not in Zend Studio debugging - $this->scrollbarWidth = $this->isGecko() ? 22 : 25; // vertical scrollbar width differs in Firefox and other browsers + // show errors on screen in case if not in Zend Studio debugging + ini_set('display_errors', DebuggerUtil::constOn('DBG_ZEND_PRESENT') ? 0 : 1); + + // vertical scrollbar width differs in Firefox and other browsers + $this->scrollbarWidth = $this->isGecko() ? 22 : 25; + $this->appendRequest(); } @@ -356,28 +450,43 @@ } } - function InitReport() + /** + * Performs debugger initialization + * + * @return void + */ + private function InitReport() { if ( !class_exists('kApplication') ) { - return ; + return; } $application =& kApplication::Instance(); // string used to separate debugger records while in file (used in debugger dump filename too) $this->rowSeparator = '@' . (is_object($application->Factory) && $application->InitDone ? $application->GetSID() : 0) . '@'; -// $this->rowSeparator = '@'.rand(0,100000).'@'; +// $this->rowSeparator = '@' . rand(0, 100000) . '@'; // include debugger files from this url $reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/'; $kernel_path = preg_replace($reg_exp, '', KERNEL_PATH, 1); $this->baseURL = PROTOCOL . SERVER_NAME . (defined('PORT') ? ':' . PORT : '') . rtrim(BASE_PATH, '/') . $kernel_path . '/utility/debugger'; + // store debugger cookies at this path + $this->basePath = rtrim(BASE_PATH, '/'); + // save debug output in this folder $this->tempFolder = defined('RESTRICTED') ? RESTRICTED : WRITEABLE . '/cache'; } - function mapLongError($msg) + /** + * Allows to overcome short error message problem in tigger_error function + * + * @param string $msg + * @return int + * @access public + */ + public function mapLongError($msg) { $key = $this->generateID(); $this->longErrors[$key] = $msg; @@ -386,31 +495,39 @@ } /** - * Appends all passed variable values (wihout variable names) to debug output + * Appends all passed variable values (without variable names) to debug output * + * @return void + * @access public */ - function dumpVars() + public function dumpVars() { $dump_mode = 'var_dump'; $dumpVars = func_get_args(); - if ($dumpVars[count($dumpVars) - 1] === 'STRICT') { + if ( $dumpVars[count($dumpVars) - 1] === 'STRICT' ) { $dump_mode = 'strict_var_dump'; array_pop($dumpVars); } foreach ($dumpVars as $varValue) { - $this->Data[] = Array('value' => $varValue, 'debug_type' => $dump_mode); + $this->Data[] = Array ('value' => $varValue, 'debug_type' => $dump_mode); } - } - function prepareHTML($dataIndex) + /** + * Transforms collected data at given index into human-readable HTML to place in debugger report + * + * @param int $dataIndex + * @return string + * @access private + */ + private function prepareHTML($dataIndex) { static $errors_displayed = 0; $Data =& $this->Data[$dataIndex]; - if ($Data['debug_type'] == 'html') { + if ( $Data['debug_type'] == 'html' ) { return $Data['html']; } @@ -419,52 +536,54 @@ $errors_displayed++; $fileLink = $this->getFileLink($Data['file'], $Data['line']); $ret = '' . $this->getErrorNameByCode($Data['no']) . ' (#' . $errors_displayed . '): ' . $Data['str']; - $ret .= ' in '.$fileLink.' on line '.$Data['line'].''; + $ret .= ' in ' . $fileLink . ' on line ' . $Data['line'] . ''; return $ret; break; case 'exception': $fileLink = $this->getFileLink($Data['file'], $Data['line']); - $ret = ''.$Data['exception_class'].': '.$Data['str']; - $ret .= ' in '.$fileLink.' on line '.$Data['line'].''; + $ret = '' . $Data['exception_class'] . ': ' . $Data['str']; + $ret .= ' in ' . $fileLink . ' on line ' . $Data['line'] . ''; return $ret; break; case 'var_dump': - return $this->highlightString( $this->print_r($Data['value'], true) ); + return $this->highlightString($this->print_r($Data['value'], true)); break; case 'strict_var_dump': - return $this->highlightString( var_export($Data['value'], true) ); + return $this->highlightString(var_export($Data['value'], true)); break; case 'trace': ini_set('memory_limit', '500M'); $trace =& $Data['trace']; - $i = 0; $traceCount = count($trace); + $i = 0; + $traceCount = count($trace); $ret = ''; - while ($i < $traceCount) { + + while ( $i < $traceCount ) { $traceRec =& $trace[$i]; - $argsID = 'trace_args_'.$dataIndex.'_'.$i; + $argsID = 'trace_args_' . $dataIndex . '_' . $i; $has_args = isset($traceRec['args']); - if (isset($traceRec['file'])) { - $func_name = isset($traceRec['class']) ? $traceRec['class'].$traceRec['type'].$traceRec['function'] : $traceRec['function']; - $args_link = $has_args ? 'Function' : 'Function'; + if ( isset($traceRec['file']) ) { + $func_name = isset($traceRec['class']) ? $traceRec['class'] . $traceRec['type'] . $traceRec['function'] : $traceRec['function']; + $args_link = $has_args ? 'Function' : 'Function'; - $ret .= $args_link.': '.$this->getFileLink($traceRec['file'], $traceRec['line'], $func_name); - $ret .= ' in '.basename($traceRec['file']).' on line '.$traceRec['line'].'
'; + $ret .= $args_link . ': ' . $this->getFileLink($traceRec['file'], $traceRec['line'], $func_name); + $ret .= ' in ' . basename($traceRec['file']) . ' on line ' . $traceRec['line'] . '
'; } else { $ret .= 'no file information available'; } - if ($has_args) { + if ( $has_args ) { // if parameter value is longer then 200 symbols, then leave only first 50 $args = $this->highlightString($this->print_r($traceRec['args'], true)); - $ret .= ''; + $ret .= ''; } $i++; } @@ -477,47 +596,47 @@ $runtime = ($Data['ends'] - $Data['begins']); // in seconds $totals_key = getArrayValue($Data, 'totalsKey'); - if ($totals_key) { + if ( $totals_key ) { $total_before = $Data['totalsBefore']; $total = $this->ProfilerTotals[$totals_key]; - $div_width = Array(); + $div_width = Array (); $total_width = ($this->getWindowWidth() - 10); $div_width['before'] = round(($total_before / $total) * $total_width); $div_width['current'] = round(($runtime / $total) * $total_width); $div_width['left'] = round((($total - $total_before - $runtime) / $total) * $total_width); $subtitle = array_key_exists('subtitle', $Data) ? ' (' . $Data['subtitle'] . ')' : ''; - $ret = 'Name' . $subtitle . ': '.$Data['description'].'
'; + $ret = 'Name' . $subtitle . ': ' . $Data['description'] . '
'; $additional = isset($Data['additional']) ? $Data['additional'] : Array (); - if (isset($Data['file'])) { - array_unshift($additional, Array('name' => 'File', 'value' => $this->getFileLink($Data['file'], $Data['line'], basename($Data['file']).':'.$Data['line']))); + if ( isset($Data['file']) ) { + array_unshift($additional, Array ('name' => 'File', 'value' => $this->getFileLink($Data['file'], $Data['line'], basename($Data['file']) . ':' . $Data['line']))); } - array_unshift($additional, Array('name' => 'Runtime', 'value' => $runtime.'s')); + array_unshift($additional, Array ('name' => 'Runtime', 'value' => $runtime . 's')); $ret .= '
'; //FF 3.5 needs this! foreach ($additional as $mixed_param) { - $ret .= '['.$mixed_param['name'].': '.$mixed_param['value'].'] '; + $ret .= '[' . $mixed_param['name'] . ': ' . $mixed_param['value'] . '] '; } - /*if (isset($Data['file'])) { - $ret .= '[Runtime: '.$runtime.'s] [File: '.$this->getFileLink($Data['file'], $Data['line'], basename($Data['file']).':'.$Data['line']).']
'; + /*if ( isset($Data['file']) ) { + $ret .= '[Runtime: ' . $runtime . 's] [File: ' . $this->getFileLink($Data['file'], $Data['line'], basename($Data['file']) . ':' . $Data['line']) . ']
'; } else { - $ret .= 'Runtime: '.$runtime.'s
'; + $ret .= 'Runtime: ' . $runtime . 's
'; }*/ $ret .= '
'; - $ret .= '
'; - $ret .= '
'; - $ret .= '
'; + $ret .= '
'; + $ret .= '
'; + $ret .= '
'; return $ret; } else { - return 'Name: '.$Data['description'].'
Runtime: '.$runtime.'s'; + return 'Name: ' . $Data['description'] . '
Runtime: ' . $runtime . 's'; } break; @@ -527,7 +646,13 @@ } } - function getWindowWidth() + /** + * Returns debugger report window width excluding scrollbar + * + * @return int + * @access private + */ + private function getWindowWidth() { return DBG_WINDOW_WIDTH - $this->scrollbarWidth - 8; } @@ -537,18 +662,19 @@ * * @param Object $object * @return bool + * @access private */ - function IsBigObject(&$object) + private function IsBigObject(&$object) { $skip_classes = Array( - defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication', - 'kFactory', - 'kUnitConfigReader', - 'NParser', - ); + defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication', + 'kFactory', + 'kUnitConfigReader', + 'NParser', + ); foreach ($skip_classes as $class_name) { - if (strtolower(get_class($object)) == strtolower($class_name)) { + if ( strtolower(get_class($object)) == strtolower($class_name) ) { return true; } } @@ -563,16 +689,17 @@ * @param bool $return_output return output or print it out * @param int $tab_count offset in tabs * @return string + * @access private */ - function print_r(&$array, $return_output = false, $tab_count = -1) + private function print_r(&$array, $return_output = false, $tab_count = -1) { static $first_line = true; // not an array at all - if (!is_array($array)) { - switch (gettype($array)) { + if ( !is_array($array) ) { + switch ( gettype($array) ) { case 'NULL': - return 'NULL'."\n"; + return 'NULL' . "\n"; break; case 'object': @@ -581,10 +708,10 @@ default: // number or string - if (strlen($array) > 200) { - $array = substr($array, 0, 50).' ...'; + if ( strlen($array) > 200 ) { + $array = substr($array, 0, 50) . ' ...'; } - return $array."\n"; + return $array . "\n"; break; } } @@ -592,7 +719,7 @@ $output = ''; $tab_count++; - $output .= "Array\n".str_repeat(' ', $tab_count)."(\n"; + $output .= "Array\n" . str_repeat(' ', $tab_count) . "(\n"; $tab_count++; $tabsign = $tab_count ? str_repeat(' ', $tab_count) : ''; @@ -600,52 +727,52 @@ $array_keys = array_keys($array); foreach ($array_keys as $key) { - switch (gettype($array[$key])) { + switch ( gettype($array[$key]) ) { case 'array': - $output .= $tabsign.'['.$key.'] = '.$this->print_r($array[$key], true, $tab_count); + $output .= $tabsign . '[' . $key . '] = ' . $this->print_r($array[$key], true, $tab_count); break; case 'boolean': - $output .= $tabsign.'['.$key.'] = '.($array[$key] ? 'true' : 'false')."\n"; + $output .= $tabsign . '[' . $key . '] = ' . ($array[$key] ? 'true' : 'false') . "\n"; break; case 'integer': case 'double': case 'string': - if (strlen($array[$key]) > 200) { - $array[$key] = substr($array[$key], 0, 50).' ...'; + if ( strlen($array[$key]) > 200 ) { + $array[$key] = substr($array[$key], 0, 50) . ' ...'; } - $output .= $tabsign.'['.$key.'] = '.$array[$key]."\n"; + $output .= $tabsign . '[' . $key . '] = ' . $array[$key] . "\n"; break; case 'NULL': - $output .= $tabsign.'['.$key."] = NULL\n"; + $output .= $tabsign . '[' . $key . "] = NULL\n"; break; case 'object': - $output .= $tabsign.'['.$key."] = "; - $output .= "Object (".get_class($array[$key]).") = \n".str_repeat(' ', $tab_count + 1)."(\n"; + $output .= $tabsign . '[' . $key . "] = "; + $output .= "Object (" . get_class($array[$key]) . ") = \n" . str_repeat(' ', $tab_count + 1) . "(\n"; $output .= $this->processObject($array[$key], $tab_count + 2); - $output .= str_repeat(' ', $tab_count + 1).")\n"; + $output .= str_repeat(' ', $tab_count + 1) . ")\n"; break; default: - $output .= $tabsign.'['.$key.'] unknown = '.gettype($array[$key])."\n"; + $output .= $tabsign . '[' . $key . '] unknown = ' . gettype($array[$key]) . "\n"; break; } } $tab_count--; - $output .= str_repeat(' ', $tab_count).")\n"; + $output .= str_repeat(' ', $tab_count) . ")\n"; - if ($first_line) { + if ( $first_line ) { $first_line = false; $output .= "\n"; } $tab_count--; - if ($return_output) { + if ( $return_output ) { return $output; } else { @@ -655,16 +782,24 @@ return true; } - function processObject(&$object, $tab_count) + /** + * Returns string representation of given object (more like print_r, but with recursion prevention check) + * + * @param Object $object + * @param int $tab_count + * @return string + * @access private + */ + private function processObject(&$object, $tab_count) { $object_class = get_class($object); - if (!in_array($object_class, $this->RecursionStack)) { - if ($this->IsBigObject($object)) { - return 'SKIPPED (class: '.$object_class.")\n"; + if ( !in_array($object_class, $this->RecursionStack) ) { + if ( $this->IsBigObject($object) ) { + return 'SKIPPED (class: ' . $object_class . ")\n"; } $attribute_names = get_class_vars($object_class); - if (!$attribute_names) { + if ( !$attribute_names ) { return "NO_ATTRIBUTES\n"; } else { @@ -673,12 +808,12 @@ $tabsign = $tab_count ? str_repeat(' ', $tab_count) : ''; foreach ($attribute_names as $attribute_name => $attribute_value) { - if (is_object($object->$attribute_name)) { + if ( is_object($object->$attribute_name) ) { // it is object - $output .= $tabsign.'['.$attribute_name.'] = '.$this->processObject($object->$attribute_name, $tab_count + 1); + $output .= $tabsign . '[' . $attribute_name . '] = ' . $this->processObject($object->$attribute_name, $tab_count + 1); } else { - $output .= $tabsign.'['.$attribute_name.'] = '.$this->print_r($object->$attribute_name, true, $tab_count); + $output .= $tabsign . '[' . $attribute_name . '] = ' . $this->print_r($object->$attribute_name, true, $tab_count); } } array_pop($this->RecursionStack); @@ -687,7 +822,7 @@ } else { // object [in recursion stack] - return '*** RECURSION *** (class: '.$object_class.")\n"; + return '*** RECURSION *** (class: ' . $object_class . ")\n"; } } @@ -697,23 +832,24 @@ * * @param string $sql * @return string + * @access public */ - function formatSQL($sql) + public function formatSQL($sql) { - $sql = trim( preg_replace('/(\n|\t| )+/is', ' ', $sql) ); + $sql = trim(preg_replace('/(\n|\t| )+/is', ' ', $sql)); // whitespace in the beginning of the regex is to avoid splitting inside words, for exmaple "FROM int_ConfigurationValues" into "FROM intConfiguration\n\tValues" $formatted_sql = preg_replace('/\s(CREATE TABLE|DROP TABLE|SELECT|UPDATE|SET|REPLACE|INSERT|DELETE|VALUES|FROM|LEFT JOIN|INNER JOIN|LIMIT|WHERE|HAVING|GROUP BY|ORDER BY)\s/is', "\n\t$1 ", ' ' . $sql); $formatted_sql = $this->highlightString($formatted_sql); - if (defined('DBG_SQL_EXPLAIN') && DBG_SQL_EXPLAIN) { - if (substr($sql, 0, 6) == 'SELECT') { + if ( defined('DBG_SQL_EXPLAIN') && DBG_SQL_EXPLAIN ) { + if ( substr($sql, 0, 6) == 'SELECT' ) { $formatted_sql .= '
' . 'Explain:

'; $explain_result = $this->Application->Conn->Query('EXPLAIN ' . $sql, null, true); $explain_table = ''; foreach ($explain_result as $explain_row) { - if (!$explain_table) { + if ( !$explain_table ) { // first row -> draw header $explain_table .= '' . implode('', array_keys($explain_row)) . ''; } @@ -727,20 +863,26 @@ return $formatted_sql; } - function highlightString($string) + /** + * Highlights given string using "highlight_string" method + * + * @param string $string + * @return string + */ + private function highlightString($string) { - if (!(defined('DBG_USE_HIGHLIGHT') && DBG_USE_HIGHLIGHT) || $this->_compileError) { + if ( !(defined('DBG_USE_HIGHLIGHT') && DBG_USE_HIGHLIGHT) || $this->_compileError ) { return nl2br($string); } - $string = str_replace( Array('\\', '/') , Array('_no_match_string_', '_n_m_s_'), $string); + $string = str_replace(Array ('\\', '/'), Array ('_no_match_string_', '_n_m_s_'), $string); $this->_compileError = true; // next line is possible cause of compile error - $string = highlight_string('', true); + $string = highlight_string('', true); $this->_compileError = false; - $string = str_replace( Array('_no_match_string_', '_n_m_s_'), Array('\\', '/'), $string); + $string = str_replace(Array ('_no_match_string_', '_n_m_s_'), Array ('\\', '/'), $string); - if (strlen($string) >= 65536) { + if ( strlen($string) >= 65536 ) { // preg_replace will fail, when string is longer, then 65KB return str_replace(Array ('<?php ', '?>'), '', $string); } @@ -752,8 +894,9 @@ * Determine by php type of browser used to show debugger * * @return bool + * @access private */ - function isGecko() + private function isGecko() { // we need isset because we may run scripts from shell with no user_agent at all return isset($_SERVER['HTTP_USER_AGENT']) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'firefox') !== false; @@ -766,20 +909,20 @@ * @param int $lineno line number in file where error is found * @param string $title text to show on file edit link * @return string + * @access public */ - function getFileLink($file, $lineno = 1, $title = '') + public function getFileLink($file, $lineno = 1, $title = '') { - if (!$title) { + if ( !$title ) { $title = str_replace('/', '\\', $this->getLocalFile($file)); } - if ($this->isGecko()) { - return ''.$title.''; + if ( $this->isGecko() ) { + return '' . $title . ''; } else { - return ''.$title.''; + return '' . $title . ''; } - } /** @@ -787,34 +930,39 @@ * * @param string $remoteFile * @return string + * @access private */ - function getLocalFile($remoteFile) + private function getLocalFile($remoteFile) { - return preg_replace('/^'.preg_quote(DOC_ROOT, '/').'/', DBG_LOCAL_BASE_PATH, $remoteFile, 1); + return preg_replace('/^' . preg_quote(DOC_ROOT, '/') . '/', DBG_LOCAL_BASE_PATH, $remoteFile, 1); } /** * Appends call trace till this method call * * @param int $levels_to_shift + * @return void + * @access public */ - function appendTrace($levels_to_shift = 1) + public function appendTrace($levels_to_shift = 1) { $levels_shifted = 0; $trace = debug_backtrace(); - while ($levels_shifted < $levels_to_shift) { + while ( $levels_shifted < $levels_to_shift ) { array_shift($trace); $levels_shifted++; } - $this->Data[] = Array('trace' => $trace, 'debug_type' => 'trace'); + $this->Data[] = Array ('trace' => $trace, 'debug_type' => 'trace'); } /** * Appends call trace till this method call * * @param Exception $exception + * @return void + * @access private */ private function appendExceptionTrace(&$exception) { @@ -822,22 +970,33 @@ $this->Data[] = Array('trace' => $trace, 'debug_type' => 'trace'); } - function appendMemoryUsage($msg, $used = null) + /** + * Adds memory usage statistics + * + * @param string $msg + * @param int $used + * @return void + * @access public + */ + public function appendMemoryUsage($msg, $used = null) { - if (!isset($used)) { + if ( !isset($used) ) { $used = round(memory_get_usage() / 1024); } - $this->appendHTML('Memory usage '.$msg.' '.$used.'Kb'); + + $this->appendHTML('Memory usage ' . $msg . ' ' . $used . 'Kb'); } /** - * Appends HTML code whithout transformations + * Appends HTML code without transformations * * @param string $html + * @return void + * @access public */ - function appendHTML($html) + public function appendHTML($html) { - $this->Data[] = Array('html' => $html, 'debug_type' => 'html'); + $this->Data[] = Array ('html' => $html, 'debug_type' => 'html'); } /** @@ -848,26 +1007,28 @@ * @param string $html * @param string $type = {'append','prepend','replace'} * @return bool + * @access public */ - function setHTMLByIndex($index, $html, $type = 'append') + public function setHTMLByIndex($index, $html, $type = 'append') { - if (!isset($this->Data[$index]) || $this->Data[$index]['debug_type'] != 'html') { + if ( !isset($this->Data[$index]) || $this->Data[$index]['debug_type'] != 'html' ) { return false; } - switch ($type) { + switch ( $type ) { case 'append': - $this->Data[$index]['html'] .= '
'.$html; + $this->Data[$index]['html'] .= '
' . $html; break; case 'prepend': - $this->Data[$index]['html'] = $this->Data[$index]['html'].'
'.$html; + $this->Data[$index]['html'] = $this->Data[$index]['html'] . '
' . $html; break; case 'replace': $this->Data[$index]['html'] = $html; break; } + return true; } @@ -876,32 +1037,48 @@ * end to beginning. * * @param int $debugLineCount + * @return void + * @access private */ - function moveToBegin($debugLineCount) + private function moveToBegin($debugLineCount) { - $lines = array_splice($this->Data,count($this->Data)-$debugLineCount,$debugLineCount); - $this->Data = array_merge($lines,$this->Data); + $lines = array_splice($this->Data, count($this->Data) - $debugLineCount, $debugLineCount); + $this->Data = array_merge($lines, $this->Data); } - function moveAfterRow($new_row, $debugLineCount) + /** + * Moves all debugger report lines after $debugLineCount into $new_row position + * + * @param int $new_row + * @param int $debugLineCount + * @return void + * @access private + */ + private function moveAfterRow($new_row, $debugLineCount) { - $lines = array_splice($this->Data,count($this->Data)-$debugLineCount,$debugLineCount); - $rows_before = array_splice($this->Data,0,$new_row,$lines); - $this->Data = array_merge($rows_before,$this->Data); + $lines = array_splice($this->Data, count($this->Data) - $debugLineCount, $debugLineCount); + $rows_before = array_splice($this->Data, 0, $new_row, $lines); + $this->Data = array_merge($rows_before, $this->Data); } - function appendRequest() + /** + * Appends HTTP REQUEST information to debugger report + * + * @return void + * @access private + */ + private function appendRequest() { - if (isset($_SERVER['SCRIPT_FILENAME'])) { + if ( isset($_SERVER['SCRIPT_FILENAME']) ) { $script = $_SERVER['SCRIPT_FILENAME']; } else { - $script = $_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF']; + $script = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['PHP_SELF']; } - $this->appendHTML('ScriptName: '.$this->getFileLink($script, 1, basename($script)).' ('.dirname($script).')'); - if ($this->_isAjax) { - $this->appendHTML('RequestURI: '.$_SERVER['REQUEST_URI'].' (QS Length:'.strlen($_SERVER['QUERY_STRING']).')'); + $this->appendHTML('ScriptName: ' . $this->getFileLink($script, 1, basename($script)) . ' (' . dirname($script) . ')'); + if ( $this->_isAjax ) { + $this->appendHTML('RequestURI: ' . $_SERVER['REQUEST_URI'] . ' (QS Length:' . strlen($_SERVER['QUERY_STRING']) . ')'); } $tools_html = ' @@ -920,17 +1097,17 @@ $value) { - if(!is_array($value) && trim($value) == '') { - $value = 'no value'; - } - else { - $value = htmlspecialchars($this->print_r($value, true)); - } + if ( !is_array($value) && trim($value) == '' ) { + $value = 'no value'; + } + else { + $value = htmlspecialchars($this->print_r($value, true)); + } - $in_cookie = isset($_COOKIE[$key]); - $src = isset($_GET[$key]) && !$in_cookie ? 'GE' : (isset($_POST[$key]) && !$in_cookie ? 'PO' : ($in_cookie ? 'CO' : '?') ); - echo ''; - } + $in_cookie = isset($_COOKIE[$key]); + $src = isset($_GET[$key]) && !$in_cookie ? 'GE' : (isset($_POST[$key]) && !$in_cookie ? 'PO' : ($in_cookie ? 'CO' : '?')); + echo ''; + } ?>
'.$src.''.$key.''.$value.'
' . $src . '' . $key . '' . $value . '
appendHTML('PHP Session: ['.ini_get('session.name').']'); + if ( isset($_SESSION) && $_SESSION ) { + $this->appendHTML('PHP Session: [' . ini_get('session.name') . ']'); $this->dumpVars($_SESSION); $this->moveToBegin(2); } } - function profileStart($key, $description = null, $timeStamp = null) + /** + * Starts profiling of a given $key + * + * @param string $key + * @param string $description + * @param int $timeStamp + * @return void + * @access public + */ + public function profileStart($key, $description = null, $timeStamp = null) { - if (!isset($timeStamp)) { + if ( !isset($timeStamp) ) { $timeStamp = microtime(true); } - $this->ProfilerData[$key] = Array('begins' => $timeStamp, 'ends' => 5000, 'debuggerRowID' => count($this->Data)); - if (isset($description)) { + $this->ProfilerData[$key] = Array ('begins' => $timeStamp, 'ends' => 5000, 'debuggerRowID' => count($this->Data)); + if ( isset($description) ) { $this->ProfilerData[$key]['description'] = $description; } - if (substr($key, 0, 4) == 'sql_') { + if ( substr($key, 0, 4) == 'sql_' ) { // append place from what was called $trace_results = debug_backtrace(); $trace_count = count($trace_results); $i = 0; - while ($i < $trace_count) { + while ( $i < $trace_count ) { if ( !isset($trace_results[$i]['file']) ) { $i++; continue; } $trace_file = basename($trace_results[$i]['file']); - if ($trace_file != 'db_connection.php' && $trace_file != 'db_load_balancer.php' && $trace_file != 'adodb.inc.php') { + if ( $trace_file != 'db_connection.php' && $trace_file != 'db_load_balancer.php' && $trace_file != 'adodb.inc.php' ) { break; } $i++; @@ -982,7 +1170,7 @@ $this->ProfilerData[$key]['file'] = $trace_results[$i]['file']; $this->ProfilerData[$key]['line'] = $trace_results[$i]['line']; - if (array_key_exists('object', $trace_results[$i + 1]) && isset($trace_results[$i + 1]['object']->Prefix)) { + if ( array_key_exists('object', $trace_results[$i + 1]) && isset($trace_results[$i + 1]['object']->Prefix) ) { $object =& $trace_results[$i + 1]['object']; /* @var $object kBase */ @@ -993,31 +1181,40 @@ unset($trace_results); } - $this->Data[] = Array('profile_key' => $key, 'debug_type' => 'profiler'); + $this->Data[] = Array ('profile_key' => $key, 'debug_type' => 'profiler'); } - function profileFinish($key, $description = null, $timeStamp = null) + /** + * Ends profiling for a given $key + * + * @param string $key + * @param string $description + * @param int $timeStamp + * @return void + * @access public + */ + public function profileFinish($key, $description = null, $timeStamp = null) { - if (!isset($timeStamp)) { + if ( !isset($timeStamp) ) { $timeStamp = microtime(true); } $this->ProfilerData[$key]['ends'] = $timeStamp; - if (isset($description)) { + if ( isset($description) ) { $this->ProfilerData[$key]['description'] = $description; } - if (substr($key, 0, 4) == 'sql_') { + if ( substr($key, 0, 4) == 'sql_' ) { $func_arguments = func_get_args(); $rows_affected = $func_arguments[3]; $additional = Array (); - if ($rows_affected > 0) { + if ( $rows_affected > 0 ) { $additional[] = Array ('name' => 'Affected Rows', 'value' => $rows_affected); - if (isset($func_arguments[4])) { - if (strlen($func_arguments[4]) > 200) { + if ( isset($func_arguments[4]) ) { + if ( strlen($func_arguments[4]) > 200 ) { $func_arguments[4] = substr($func_arguments[4], 0, 50) . ' ...'; } @@ -1025,37 +1222,46 @@ } } - $additional[] = Array ('name' => 'Query Number', 'value' => $func_arguments[5]); + $additional[] = Array ('name' => 'Query Number', 'value' => $func_arguments[5]); - if ($func_arguments[6]) { + if ( $func_arguments[6] ) { $this->profilerAddTotal('cachable_queries', $key); $this->ProfilerData[$key]['subtitle'] = 'cachable'; } - if ($func_arguments[7]) { + if ( $func_arguments[7] ) { $additional[] = Array ('name' => 'Server #', 'value' => $func_arguments[7]); } - if (array_key_exists('prefix_special', $this->ProfilerData[$key])) { - $additional[] = Array ('name' => 'PrefixSpecial', 'value' => $this->ProfilerData[$key]['prefix_special']); + if ( array_key_exists('prefix_special', $this->ProfilerData[$key]) ) { + $additional[] = Array ('name' => 'PrefixSpecial', 'value' => $this->ProfilerData[$key]['prefix_special']); } $this->ProfilerData[$key]['additional'] =& $additional; } } - function profilerAddTotal($total_key, $key = null, $value = null) + /** + * Collects total execution time from profiler record + * + * @param string $total_key + * @param string $key + * @param int $value + * @return void + * @access public + */ + public function profilerAddTotal($total_key, $key = null, $value = null) { - if (!isset($this->ProfilerTotals[$total_key])) { + if ( !isset($this->ProfilerTotals[$total_key]) ) { $this->ProfilerTotals[$total_key] = 0; $this->ProfilerTotalCount[$total_key] = 0; } - if (!isset($value)) { + if ( !isset($value) ) { $value = $this->ProfilerData[$key]['ends'] - $this->ProfilerData[$key]['begins']; } - if (isset($key)) { + if ( isset($key) ) { $this->ProfilerData[$key]['totalsKey'] = $total_key; $this->ProfilerData[$key]['totalsBefore'] = $this->ProfilerTotals[$total_key]; } @@ -1064,58 +1270,80 @@ $this->ProfilerTotalCount[$total_key]++; } - function appendTimestamp($message) + /** + * Traces relative code execution speed between this method calls + * + * @param string $message + * @return void + * @access public + */ + public function appendTimestamp($message) { global $start; + $time = microtime(true); $from_last = $time - $this->LastMoment; $from_start = $time - $start; - $this->appendHTML(sprintf("%s %.5f from last %.5f from start", $message, $from_last, $from_start)); + $this->appendHTML(sprintf("%s %.5f from last %.5f from start", $message, $from_last, $from_start)); $this->LastMoment = $time; } - function generateID() + /** + * Returns unique ID for each method call + * + * @return int + * @access public + */ + public function generateID() { list($usec, $sec) = explode(' ', microtime()); $id_part_1 = substr($usec, 4, 4); - $id_part_2 = mt_rand(1,9); + $id_part_2 = mt_rand(1, 9); $id_part_3 = substr($sec, 6, 4); $digit_one = substr($id_part_1, 0, 1); - if ($digit_one == 0) { - $digit_one = mt_rand(1,9); + + if ( $digit_one == 0 ) { + $digit_one = mt_rand(1, 9); $id_part_1 = preg_replace('/^0/', '', $id_part_1); - $id_part_1=$digit_one.$id_part_1; + $id_part_1 = $digit_one . $id_part_1; } - return $id_part_1.$id_part_2.$id_part_3; + + return $id_part_1 . $id_part_2 . $id_part_3; } - - function getErrorNameByCode($error_code) + /** + * Returns error name based on it's code + * + * @param int $error_code + * @return string + * @access private + */ + private function getErrorNameByCode($error_code) { - $error_map = Array( - 'Fatal Error' => Array(E_USER_ERROR), - 'Warning' => Array(E_WARNING, E_USER_WARNING), - 'Notice' => Array(E_NOTICE, E_USER_NOTICE), - ); + $error_map = Array ( + 'Fatal Error' => Array (E_USER_ERROR), + 'Warning' => Array (E_WARNING, E_USER_WARNING), + 'Notice' => Array (E_NOTICE, E_USER_NOTICE), + ); - if (defined('E_STRICT')) { + if ( defined('E_STRICT') ) { // since PHP 5 - $error_map['PHP5 Strict'] = Array(E_STRICT); + $error_map['PHP5 Strict'] = Array (E_STRICT); } - if (defined('E_RECOVERABLE_ERROR')) { + if ( defined('E_RECOVERABLE_ERROR') ) { // since PHP 5.2 - $error_map['Fatal Error (recoverable)'] = Array(E_RECOVERABLE_ERROR); + $error_map['Fatal Error (recoverable)'] = Array (E_RECOVERABLE_ERROR); } - if (defined('E_DEPRECATED')) { + if ( defined('E_DEPRECATED') ) { // since PHP 5.3 - $error_map['PHP5 Depricated'] = Array(E_DEPRECATED, E_USER_DEPRECATED); + $error_map['PHP5 Depricated'] = Array (E_DEPRECATED, E_USER_DEPRECATED); } foreach ($error_map as $error_name => $error_codes) { - if (in_array($error_code, $error_codes)) { + if ( in_array($error_code, $error_codes) ) { return $error_name; } } @@ -1124,37 +1352,49 @@ } /** - * Returns profile total key (check against unexisting key too) + * Returns profile total key (check against missing key too) * * @param string $key * @return int + * @access private */ - function getProfilerTotal($key) + private function getProfilerTotal($key) { - if (isset($this->ProfilerTotalCount[$key])) { + if ( isset($this->ProfilerTotalCount[$key]) ) { return (int)$this->ProfilerTotalCount[$key]; } + return 0; } - function ProfilePoint($title, $level=1) + /** + * Counts how much calls were made to a place, where this method is called (basic version of profiler) + * + * @param string $title + * @param int $level + * @return void + * @access public + */ + public function ProfilePoint($title, $level = 1) { $trace_results = debug_backtrace(); - $level = min($level,count($trace_results)-1); + $level = min($level, count($trace_results) - 1); do { $point = $trace_results[$level]; - $location = $point['file'].':'.$point['line']; + $location = $point['file'] . ':' . $point['line']; $level++; $has_more = isset($trace_results[$level]); - } while ($has_more && $point['function'] == $trace_results[$level]['function'] ); + } while ( $has_more && $point['function'] == $trace_results[$level]['function'] ); - if (!isset($this->ProfilePoints[$title])) { - $this->ProfilePoints[$title] = array(); + if ( !isset($this->ProfilePoints[$title]) ) { + $this->ProfilePoints[$title] = Array (); } - if (!isset($this->ProfilePoints[$title][$location])) { + + if ( !isset($this->ProfilePoints[$title][$location]) ) { $this->ProfilePoints[$title][$location] = 0; } + $this->ProfilePoints[$title][$location]++; } @@ -1169,7 +1409,7 @@ */ public function printReport($returnResult = false, $clean_output_buffer = true) { - if ($this->reportDone) { + if ( $this->reportDone ) { // don't print same report twice (in case if shutdown function used + compression + fatal error) return ''; } @@ -1179,110 +1419,111 @@ $debugger_start = memory_get_usage(); - if (defined('SPACER_URL')) { + if ( defined('SPACER_URL') ) { $this->dummyImage = SPACER_URL; } $this->InitReport(); // set parameters required by AJAX - // defined here, because user can define this contant while script is running, not event before debugger is started - DebuggerUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 0); - DebuggerUtil::safeDefine('DBG_TOOLBAR_BUTTONS', 1); + // defined here, because user can define this constant while script is running, not event before debugger is started + DebuggerUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 0); + DebuggerUtil::safeDefine('DBG_TOOLBAR_BUTTONS', 1); $this->appendSession(); // show php session if any // ensure, that 1st line of debug output always is this one: - $top_line = '
[Reload Frame] [Hide Debugger] [Clear Debugger][Current Time: '.date('H:i:s').'] [File Size: #DBG_FILESIZE#]
'; + $top_line = '
[Reload Frame] [Hide Debugger] [Clear Debugger][Current Time: ' . date('H:i:s') . '] [File Size: #DBG_FILESIZE#]
'; $this->appendHTML($top_line); $this->moveToBegin(1); - if (count($this->ProfilePoints)>0) { - foreach($this->ProfilePoints as $point => $locations) { + if ( count($this->ProfilePoints) > 0 ) { + foreach ($this->ProfilePoints as $point => $locations) { arsort($this->ProfilePoints[$point]); } $this->appendHTML($this->highlightString($this->print_r($this->ProfilePoints, true))); - /*foreach ($this->ProfilePoints as $point => $locations) { - foreach ($locations as $location => $occurrences) { - - - } - }*/ } - if (DebuggerUtil::constOn('DBG_SQL_PROFILE') && isset($this->ProfilerTotals['sql'])) { + if ( DebuggerUtil::constOn('DBG_SQL_PROFILE') && isset($this->ProfilerTotals['sql']) ) { // sql query profiling was enabled -> show totals - if (array_key_exists('cachable_queries', $this->ProfilerTotalCount)) { + if ( array_key_exists('cachable_queries', $this->ProfilerTotalCount) ) { $append = ' Cachable queries: ' . $this->ProfilerTotalCount['cachable_queries']; } else { $append = ''; } - $this->appendHTML('SQL Total time: '.$this->ProfilerTotals['sql'].' Number of queries: '.$this->ProfilerTotalCount['sql'] . $append); + $this->appendHTML('SQL Total time: ' . $this->ProfilerTotals['sql'] . ' Number of queries: ' . $this->ProfilerTotalCount['sql'] . $append); } - if (DebuggerUtil::constOn('DBG_PROFILE_INCLUDES') && isset($this->ProfilerTotals['includes'])) { + if ( DebuggerUtil::constOn('DBG_PROFILE_INCLUDES') && isset($this->ProfilerTotals['includes']) ) { // included file profiling was enabled -> show totals - $this->appendHTML('Included Files Total time: '.$this->ProfilerTotals['includes'].' Number of includes: '.$this->ProfilerTotalCount['includes']); + $this->appendHTML('Included Files Total time: ' . $this->ProfilerTotals['includes'] . ' Number of includes: ' . $this->ProfilerTotalCount['includes']); } - if (DebuggerUtil::constOn('DBG_PROFILE_MEMORY')) { + if ( DebuggerUtil::constOn('DBG_PROFILE_MEMORY') ) { // detailed memory usage reporting by objects was enabled -> show totals - $this->appendHTML('Memory used by Objects: '.round($this->ProfilerTotals['objects'] / 1024, 2).'Kb'); + $this->appendHTML('Memory used by Objects: ' . round($this->ProfilerTotals['objects'] / 1024, 2) . 'Kb'); } - if (DebuggerUtil::constOn('DBG_INCLUDED_FILES')) { + if ( DebuggerUtil::constOn('DBG_INCLUDED_FILES') ) { $files = get_included_files(); - $this->appendHTML('Included files:'); + $this->appendHTML('Included files:'); foreach ($files as $file) { - $this->appendHTML($this->getFileLink($this->getLocalFile($file)).' ('.round(filesize($file) / 1024, 2).'Kb)'); + $this->appendHTML($this->getFileLink($this->getLocalFile($file)) . ' (' . round(filesize($file) / 1024, 2) . 'Kb)'); } } - if (DebuggerUtil::constOn('DBG_PROFILE_INCLUDES')) { - $this->appendHTML('Included files statistics:'.( DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ? ' (sorted by memory usage)':'')); - $totals = Array( 'mem' => 0, 'time' => 0); - $totals_configs = Array( 'mem' => 0, 'time' => 0); - if (is_array($this->IncludesData['mem'])) { + if ( DebuggerUtil::constOn('DBG_PROFILE_INCLUDES') ) { + $totals = $totals_configs = Array ('mem' => 0, 'time' => 0); + $this->appendHTML('Included files statistics:' . (DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ? ' (sorted by memory usage)' : '')); + + if ( is_array($this->IncludesData['mem']) ) { if ( DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ) { array_multisort($this->IncludesData['mem'], SORT_DESC, $this->IncludesData['file'], $this->IncludesData['time'], $this->IncludesData['level']); } + foreach ($this->IncludesData['file'] as $key => $file_name) { - $this->appendHTML( str_repeat(' -> ', ($this->IncludesData['level'][$key] >= 0 ? $this->IncludesData['level'][$key] : 0)).$file_name.' Mem: '.sprintf("%.4f Kb", $this->IncludesData['mem'][$key]/1024).' Time: '.sprintf("%.4f", $this->IncludesData['time'][$key])); - if ($this->IncludesData['level'][$key] == 0) { + $this->appendHTML(str_repeat(' -> ', ($this->IncludesData['level'][$key] >= 0 ? $this->IncludesData['level'][$key] : 0)) . $file_name . ' Mem: ' . sprintf("%.4f Kb", $this->IncludesData['mem'][$key] / 1024) . ' Time: ' . sprintf("%.4f", $this->IncludesData['time'][$key])); + + if ( $this->IncludesData['level'][$key] == 0 ) { $totals['mem'] += $this->IncludesData['mem'][$key]; $totals['time'] += $this->IncludesData['time'][$key]; } - else if ($this->IncludesData['level'][$key] == -1) { + elseif ( $this->IncludesData['level'][$key] == -1 ) { $totals_configs['mem'] += $this->IncludesData['mem'][$key]; $totals_configs['time'] += $this->IncludesData['time'][$key]; } } - $this->appendHTML('Sub-Total classes: '.' Mem: '.sprintf("%.4f Kb", $totals['mem']/1024).' Time: '.sprintf("%.4f", $totals['time'])); - $this->appendHTML('Sub-Total configs: '.' Mem: '.sprintf("%.4f Kb", $totals_configs['mem']/1024).' Time: '.sprintf("%.4f", $totals_configs['time'])); - $this->appendHTML('Grand Total: '.' Mem: '.sprintf("%.4f Kb", ($totals['mem']+$totals_configs['mem'])/1024).' Time: '.sprintf("%.4f", $totals['time']+$totals_configs['time'])); + + $this->appendHTML('Sub-Total classes: ' . ' Mem: ' . sprintf("%.4f Kb", $totals['mem'] / 1024) . ' Time: ' . sprintf("%.4f", $totals['time'])); + $this->appendHTML('Sub-Total configs: ' . ' Mem: ' . sprintf("%.4f Kb", $totals_configs['mem'] / 1024) . ' Time: ' . sprintf("%.4f", $totals_configs['time'])); + $this->appendHTML('Grand Total: ' . ' Mem: ' . sprintf("%.4f Kb", ($totals['mem'] + $totals_configs['mem']) / 1024) . ' Time: ' . sprintf("%.4f", $totals['time'] + $totals_configs['time'])); } } $skip_reporting = DebuggerUtil::constOn('DBG_SKIP_REPORTING') || DebuggerUtil::constOn('DBG_ZEND_PRESENT'); - if (($this->_isAjax && !DebuggerUtil::constOn('DBG_SKIP_AJAX')) || !$skip_reporting) { - $debug_file = $this->tempFolder.'/debug_'.$this->rowSeparator.'.txt'; - if (file_exists($debug_file)) unlink($debug_file); + if ( ($this->_isAjax && !DebuggerUtil::constOn('DBG_SKIP_AJAX')) || !$skip_reporting ) { + $debug_file = $this->tempFolder . '/debug_' . $this->rowSeparator . '.txt'; + if ( file_exists($debug_file) ) { + unlink($debug_file); + } $i = 0; $fp = fopen($debug_file, 'a'); $lineCount = count($this->Data); - while ($i < $lineCount) { - fwrite($fp, $this->prepareHTML($i).$this->rowSeparator); + + while ( $i < $lineCount ) { + fwrite($fp, $this->prepareHTML($i) . $this->rowSeparator); $i++; } + fclose($fp); } - if ($skip_reporting) { + if ( $skip_reporting ) { // let debugger write report and then don't output anything $this->reportDone = true; return ''; @@ -1308,20 +1549,21 @@ $Debugger.EditorPath = ''; $Debugger.DebugURL = 'baseURL.'/debugger_responce.php?sid='.$this->rowSeparator.'&path='.urlencode($dbg_path); ?>'; $Debugger.EventURL = 'Factory) && $application->InitDone ? $application->HREF('dummy', '', Array ('pass' => 'm', '__NO_REWRITE__' => 1)) : ''; ?>'; + $Debugger.BasePath = 'basePath; ?>'; IsFatalError || (!$is_install && DBG_RAISE_ON_WARNINGS && $this->WarningCount)) { + if ( $this->IsFatalError || (!$is_install && DBG_RAISE_ON_WARNINGS && $this->WarningCount) ) { echo '$Debugger.Toggle();'; } - if (DBG_TOOLBAR_BUTTONS) { + if ( DBG_TOOLBAR_BUTTONS ) { echo '$Debugger.AddToolbar("$Debugger");'; } ?> window.focus(); ProfilerTotals['error_handling'])) { + if ( !isset($this->ProfilerTotals['error_handling']) ) { $memory_used = $debugger_start; $this->ProfilerTotalCount['error_handling'] = 0; } @@ -1329,9 +1571,9 @@ $memory_used = $debugger_start - $this->ProfilerTotals['error_handling']; } - if ($returnResult) { + if ( $returnResult ) { $ret = ob_get_contents(); - if ($clean_output_buffer) { + if ( $clean_output_buffer ) { ob_end_clean(); } $ret .= $this->getShortReport($memory_used); @@ -1340,10 +1582,10 @@ return $ret; } else { - if (!DebuggerUtil::constOn('DBG_HIDE_FULL_REPORT')) { + if ( !DebuggerUtil::constOn('DBG_HIDE_FULL_REPORT') ) { $this->breakOutofBuffering(); } - elseif ($clean_output_buffer) { + elseif ( $clean_output_buffer ) { ob_clean(); } echo $this->getShortReport($memory_used); @@ -1361,11 +1603,11 @@ * @return string * @access private */ - function getShortReport($memory_used) + private function getShortReport($memory_used) { - if (DebuggerUtil::constOn('DBG_TOOLBAR_BUTTONS')) { + if ( DebuggerUtil::constOn('DBG_TOOLBAR_BUTTONS') ) { // we have sql & error count in toolbar, don't duplicate here - $info = Array( + $info = Array ( 'Script Runtime' => 'PROFILE:script_runtime', 'SQL\'s Runtime' => 'PROFILE_T:sql', ); @@ -1381,37 +1623,38 @@ ); } - $ret = 'Application:'.DebuggerUtil::formatSize($memory_used).' ('.$memory_used.')'; + $ret = 'Application:' . DebuggerUtil::formatSize($memory_used) . ' (' . $memory_used . ')'; + foreach ($info as $title => $value_key) { list ($record_type, $record_data) = explode(':', $value_key, 2); - switch ($record_type) { + switch ( $record_type ) { case 'PROFILE': // profiler totals value $Data =& $this->ProfilerData[$record_data]; $profile_time = ($Data['ends'] - $Data['begins']); // in seconds - $ret .= ''.$title.':'.sprintf('%.5f', $profile_time).' s'; + $ret .= '' . $title . ':' . sprintf('%.5f', $profile_time) . ' s'; break; case 'PROFILE_TC': // profile totals record count $record_cell = ''; - if ($record_data == 'error_handling' && $this->ProfilerTotalCount[$record_data] > 0) { + if ( $record_data == 'error_handling' && $this->ProfilerTotalCount[$record_data] > 0 ) { $record_cell = ''; } - $ret .= ''.$record_cell.$title.':'.$record_cell.''.$this->ProfilerTotalCount[$record_data].''; + $ret .= '' . $record_cell . $title . ':' . $record_cell . '' . $this->ProfilerTotalCount[$record_data] . ''; break; case 'PROFILE_T': // profile total $record_cell = ''; $total = array_key_exists($record_data, $this->ProfilerTotals) ? $this->ProfilerTotals[$record_data] : 0; - $ret .= ''.$record_cell.$title.':'.$record_cell.''.sprintf('%.5f', $total).' s'; + $ret .= '' . $record_cell . $title . ':' . $record_cell . '' . sprintf('%.5f', $total) . ' s'; break; case 'SEP': - $ret .= ''; + $ret .= ''; break; } } - return '
'.$ret.'
'; + return '
' . $ret . '
'; } /** @@ -1502,7 +1745,16 @@ die( $this->breakOutofBuffering(false) . $this->printReport(true) ); } - function expandError(&$errstr, &$errfile, &$errline) + /** + * Transforms short error messages into long ones + * + * @param string $errstr + * @param string $errfile + * @param int $errline + * @return void + * @access private + */ + private function expandError(&$errstr, &$errfile, &$errline) { if ( preg_match('/(.*)#([\d]+)$/', $errstr, $rets) ) { // replace short message with long one (due triger_error limitations on message size) @@ -1521,37 +1773,63 @@ } } - function breakOutofBuffering($flush = true) + /** + * Break buffering in case if fatal error is happened in the middle + * + * @param bool $flush + * @return string + * @access private + */ + private function breakOutofBuffering($flush = true) { - $buffer_content = Array(); - while (ob_get_level()) { + $buffer_content = Array (); + while ( ob_get_level() ) { $buffer_content[] = ob_get_clean(); } + $ret = implode('', array_reverse($buffer_content)); - if ($flush) { + if ( $flush ) { echo $ret; flush(); } + return $ret; } - function saveToFile($msg) + /** + * Saves given message to "vb_debug.txt" file in DocumentRoot + * + * @param string $msg + * @return void + * @access public + */ + public function saveToFile($msg) { - $fp = fopen($_SERVER['DOCUMENT_ROOT'].'/vb_debug.txt', 'a'); - fwrite($fp, $msg."\n"); + $fp = fopen($_SERVER['DOCUMENT_ROOT'] . '/vb_debug.txt', 'a'); + fwrite($fp, $msg . "\n"); fclose($fp); } - function printConstants($constants) + /** + * Prints given constant values in a table + * + * @param mixed $constants + * @return void + * @access public + */ + public function printConstants($constants) { - if (!is_array($constants)) { + if ( !is_array($constants) ) { $constants = explode(',', $constants); } - $contant_tpl = '%s%s'; - $ret = ''; + + $constant_tpl = ''; + $ret = '
%s%s
'; + foreach ($constants as $constant_name) { - $ret .= sprintf($contant_tpl, $constant_name, constant($constant_name)); + $ret .= sprintf($constant_tpl, $constant_name, constant($constant_name)); } + $ret .= '
'; $this->appendHTML($ret); } @@ -1589,8 +1867,9 @@ * Returns HTML for tools section * * @return string + * @access private */ - function _getToolsHTML() + private function _getToolsHTML() { $html = ' @@ -1620,8 +1899,9 @@ * Returns HTML for dom viewer section * * @return string + * @access private */ - function _getDomViewerHTML() + private function _getDomViewerHTML() { $html = '
@@ -1641,16 +1921,19 @@ } } - if (!function_exists('memory_get_usage')) { + if ( !function_exists('memory_get_usage') ) { // PHP 4.x and compiled without --enable-memory-limit option - function memory_get_usage(){ return -1; } + function memory_get_usage() + { + return -1; + } } - if (!DebuggerUtil::constOn('DBG_ZEND_PRESENT')) { + if ( !DebuggerUtil::constOn('DBG_ZEND_PRESENT') ) { $debugger = new Debugger(); } - if (DebuggerUtil::constOn('DBG_USE_SHUTDOWN_FUNC')) { - register_shutdown_function( Array(&$debugger, 'printReport') ); + if ( DebuggerUtil::constOn('DBG_USE_SHUTDOWN_FUNC') ) { + register_shutdown_function(Array (&$debugger, 'printReport')); } } \ No newline at end of file Index: kernel/utility/debugger/debugger.js =================================================================== --- kernel/utility/debugger/debugger.js (revision 14826) +++ kernel/utility/debugger/debugger.js (working copy) @@ -140,7 +140,7 @@ var $exdate = new Date(); $exdate.setDate( $exdate.getDate() + 365 ); - document.cookie = 'debug_off=1; expires=' + $exdate.toUTCString() + '; path=/'; + document.cookie = 'debug_off=1; expires=' + $exdate.toUTCString() + '; path=' + this.BasePath + '/'; self.location.reload(); break; }