''); // Track output buffer level at each time mark var $aMarkNotes = array(); // Other notes can be added and output... var $aTimeMarks = array(); // Overall time markers var $curTimeMark = 'Start'; var $nTimeMarks = 0; // Provide an array index for time marks. Stablizes 'current' function var $aGoodQueries = array(); var $aBadQueries = array(); var $scbbcodes = array(); var $scbcount; var $deprecated_funcs = array(); var $aLog = array(); // Generalized debug log (only seen during debug) var $aIncList = array(); // Included files function __construct() { } /** * Set the active status of the debug logging. * When set to false, called methods within the class will by bypassed for better performance. * @param $var */ public function active($var) { $this->active = (bool) $var; } /** * Return a list of all registered time markers. * @return array */ public function getTimeMarkers() { return $this->aTimeMarks; } /** * Return a list of currently logged items * @return array */ public function getLog() { return $this->aLog; } /** * @return void */ function e107_db_debug() { global $eTimingStart; $this->aTimeMarks[0] = array( 'Index' => 0, 'What' => 'Start', '%Time' => 0, '%DB Time' => 0, '%DB Count' => 0, 'Time' => ($eTimingStart), 'DB Time' => 0, 'DB Count' => 0, 'Memory' => 0 ); register_shutdown_function('e107_debug_shutdown'); } // // Add your new Show function here so it will display in debug output! // /** * @return void */ function Show_All() { $this->ShowIf('Debug Log', $this->Show_Log()); $this->ShowIf('Traffic Counters', e107::getSingleton('e107_traffic')->Display()); $this->ShowIf('Time Analysis', $this->Show_Performance()); $this->ShowIf('SQL Analysis', $this->Show_SQL_Details()); $this->ShowIf('Shortcodes / BBCode', $this->Show_SC_BB()); $this->ShowIf('Paths', $this->Show_PATH()); $this->ShowIf('Deprecated Methods/Functions', $this->Show_DEPRECATED()); if(E107_DBG_INCLUDES) { $this->aIncList = get_included_files(); } $this->ShowIf('Included Files: ' . count($this->aIncList), $this->Show_Includes()); } /** * @param $title * @param $str * @return void */ function ShowIf($title, $str) { if(!empty($str)) { //e107::getRender()->setStyle('debug'); echo "

" . $title . "

"; echo $str; //e107::getRender()->tablerender($title, $str); } } /** * @param $sMarker * @return void */ function Mark_Time($sMarker) { $this->logTime($sMarker); } /** * Replacement for $sql->db_Mark_Time() * @param string $sMarker - a descriptive marker for the log * @return null */ public function logTime($sMarker) { if(!$this->active) { return null; } $timeNow = microtime(); $nMarks = ++$this->nTimeMarks; // file_put_contents(e_LOG."debugClass.log",$nMarks."\t". $sMarker."\n", FILE_APPEND); if(!strlen($sMarker)) { $sMarker = "Mark not set"; } $srch = array('[', ']'); $repl = array("", ""); $this->aTimeMarks[$nMarks] = array( 'Index' => ($this->nTimeMarks), 'What' => str_replace($srch, $repl, $sMarker), '%Time' => 0, '%DB Time' => 0, '%DB Count' => 0, 'Time' => $timeNow, 'DB Time' => 0, 'DB Count' => 0, 'Memory' => ((function_exists("memory_get_usage")) ? memory_get_usage() : 0) ); $this->aOBMarks[$nMarks] = ob_get_level() . '(' . ob_get_length() . ')'; $this->curTimeMark = $sMarker; // Add any desired notes to $aMarkNotes[$nMarks]... e.g. //global $eTimingStart; //$this->aMarkNotes[$nMarks] .= "verify start: ".$eTimingStart."
"; } /** * @param $query * @param $rli * @param $origQryRes * @param $aTrace * @param $mytime * @param $curtable * @return null */ function Mark_Query($query, $rli, $origQryRes, $aTrace, $mytime, $curtable) { if(!$this->active) { return null; } // global $sql; $sql = e107::getDb($rli); // Explain the query, if possible... list($qtype, $args) = explode(" ", ltrim($query), 2); unset($args); $nFields = 0; $bExplained = false; $ExplainText = ''; // Note the subtle bracket in the second comparison! Also, strcasecmp() returns zero on match if(!strcasecmp($qtype, 'SELECT') || !strcasecmp($qtype, '(SELECT')) { // It's a SELECT statement - explain it // $rli should always be set by caller // $sQryRes = (is_null($rli) ? mysql_query("EXPLAIN {$query}") : mysql_query("EXPLAIN {$query}", $rli)); $sQryRes = $sql->gen("EXPLAIN {$query}"); if($sQryRes) // There's something to explain { //$nFields = mysql_num_fields($sQryRes); $nFields = $sql->columnCount(); // mysql_num_fields($sQryRes); $bExplained = true; } } else { // Don't run 'EXPLAIN' on other queries $sQryRes = $origQryRes; // Return from original query could be TRUE or a link resource if success } // Record Basic query info $sCallingFile = varset($aTrace[2]['file']); $sCallingLine = varset($aTrace[2]['line']); $t = &$this->aSQLdetails[$sql->db_QueryCount()]; $t['marker'] = $this->curTimeMark; $t['caller'] = "$sCallingFile($sCallingLine)"; $t['query'] = $query; $t['ok'] = ($sQryRes !== false); $t['error'] = $sQryRes ? '' : $sql->getLastErrorText(); // mysql_error(); $t['nFields'] = $nFields; $t['time'] = $mytime; if($bExplained) { $bRowHeaders = false; // while ($row = @mysql_fetch_assoc($sQryRes)) while($row = $sql->fetch()) { if(!$bRowHeaders) { $bRowHeaders = true; $t['explain'] = "" . implode("", array_keys($row)) . "\n"; } $t['explain'] .= "" . implode(" ", array_values($row)) . " \n"; } } else { $t['explain'] = $ExplainText; } $this->aTimeMarks[$this->nTimeMarks]['DB Time'] += $mytime; $this->aTimeMarks[$this->nTimeMarks]['DB Count']++; if(array_key_exists($curtable, $this->aDBbyTable)) { $this->aDBbyTable[$curtable]['DB Time'] += $mytime; $this->aDBbyTable[$curtable]['DB Count']++; } else { $this->aDBbyTable[$curtable]['Table'] = $curtable; $this->aDBbyTable[$curtable]['%DB Time'] = 0; // placeholder $this->aDBbyTable[$curtable]['%DB Count'] = 0; // placeholder $this->aDBbyTable[$curtable]['DB Time'] = $mytime; $this->aDBbyTable[$curtable]['DB Count'] = 1; } return null; } /** * @param $force * @return false|string */ function Show_SQL_Details($force = false) { global $sql; // // Show stats from aSQLdetails array // if(!E107_DBG_SQLQUERIES && !E107_DBG_SQLDETAILS && ($force === false)) { return false; } $text = ''; $nQueries = $sql->db_QueryCount(); if(!$nQueries) { return $text; } // // ALWAYS summarize query errors // $badCount = 0; $okCount = 0; foreach($this->aSQLdetails as $cQuery) { if($cQuery['ok'] == 1) { $okCount++; } else { $badCount++; } } if($badCount) { $text .= "\n\n"; $text .= "\n"; $text .= "\n"; foreach($this->aSQLdetails as $idx => $cQuery) { if(!$cQuery['ok']) { $text .= "\n\n"; } } $text .= "\n
$badCount Query Errors!
IndexQuery / Error
{$idx}  " . $cQuery['query'] . "
" . $cQuery['error'] . "

\n"; } // // Optionally list good queries // if($okCount && E107_DBG_SQLDETAILS) { $text .= "\n\n"; $text .= "\n"; $text .= "\n \n "; $count = 0; foreach($this->aSQLdetails as $idx => $cQuery) { if($count > 500) { $text .= ""; // NO LAN - debug only. break; } if($cQuery['ok']) { $text .= "\n"; $count++; } } $text .= "\n
" . $this->countLabel($okCount) . " Good Queries
IndexQtimeQuery
 (msec) 
Too many queries. Ending...
{$idx}  " . number_format($cQuery['time'] * 1000.0, 4) . "  " . $cQuery['query'] . '
[' . $cQuery['marker'] . " - " . $cQuery['caller'] . "]

\n"; } // // Optionally list query details // if(E107_DBG_SQLDETAILS) { $count = 0; foreach($this->aSQLdetails as $idx => $cQuery) { $text .= "\n\n"; $text .= "\n"; if(isset($cQuery['explain'])) { $text .= $cQuery['explain']; } if(strlen($cQuery['error'])) { $text .= "\n\n"; } $text .= "'; $text .= '
" . $idx . ") Query: [" . $cQuery['marker'] . " - " . $cQuery['caller'] . "]
" . $cQuery['query'] . "
Error in query:
" . $cQuery['error'] . "
Query time: " . number_format($cQuery['time'] * 1000.0, 4) . ' (ms)

' . "\n"; if($count > 500) { $text .= "
Too many queries. Ending...
"; // NO LAN - debug only. break; } $count++; } } return $text; } /** * @param $amount * @return string */ function countLabel($amount) { $inc = ''; if($amount < 30) { $inc = 'label-success'; } elseif($amount < 50) { $inc = 'label-warning'; } elseif($amount > 49) { $inc = 'label-danger label-important'; } return "" . $amount . ""; } /** * @param $log * @return void */ function save($log) { e107::getMessage()->addDebug("Saving a log"); $titles = array_keys($this->aTimeMarks[0]); $text = implode("\t\t\t", $titles) . "\n\n"; foreach($this->aTimeMarks as $item) { $item['What'] = str_pad($item['What'], 50, " ", STR_PAD_RIGHT); $text .= implode("\t\t\t", $item) . "\n"; } file_put_contents($log, $text, FILE_APPEND); } /** * @param $label * @param $value * @param $thresholdHigh * @return mixed|string */ private function highlight($label, $value = 0, $thresholdHigh = 0) { if($value > $thresholdHigh) { return "" . $label . ""; } if($value == 0) { return "" . $label . ""; } return $label; } /** * @return string */ function Show_Performance() { // // Stats by Time Marker // global $db_time; global $sql; global $eTimingStart, $eTimingStop; $this->Mark_Time('Stop'); if(!E107_DBG_TIMEDETAILS) { return ''; } $totTime = e107::getSingleton('e107_traffic')->TimeDelta($eTimingStart, $eTimingStop); $text = "\n\n"; $bRowHeaders = false; reset($this->aTimeMarks); $aSum = $this->aTimeMarks[0]; // create a template from the 'real' array $aSum['Index'] = ''; $aSum['What'] = 'Total'; $aSum['Time'] = 0; $aSum['DB Time'] = 0; $aSum['DB Count'] = 0; $aSum['Memory'] = 0; // Calculate Memory Usage per entry. $prevMem = 0; foreach($this->aTimeMarks as $k => $v) { $prevKey = $k - 1; if(!empty($prevKey)) { $this->aTimeMarks[$prevKey]['Memory Used'] = (intval($v['Memory']) - $prevMem); } $prevMem = intval($v['Memory']); } $obj = new ArrayObject($this->aTimeMarks); $it = $obj->getIterator(); $head = ''; // while(list($tKey, $tMarker) = each($this->aTimeMarks)) foreach ($it as $tKey=>$tMarker) { if(!$bRowHeaders) { // First time: emit headers $bRowHeaders = true; $head = "\n"; $aUnits = $tMarker; foreach($aUnits as $key => $val) { switch($key) { case 'DB Time': case 'Time': $aUnits[$key] = '(msec)'; break; default: $aUnits[$key] = ''; break; } } $aUnits['OB Lev'] = 'lev(buf bytes)'; $aUnits['Memory'] = '(kb)'; $aUnits['Memory Used'] = '(kb)'; $head .= "\n"; $text .= $head; } // $tMem = ($tMarker['Memory'] - $aSum['Memory']); $tMem = ($tMarker['Memory']); // if($tMem < 0) // Quick Fix for negative numbers. // { // $tMem = 0.0000000001; // } $tMarker['Memory'] = ($tMem ? number_format($tMem / 1024.0, 1) : '?'); // display if known $tUsage = $tMarker['Memory Used']; $tMarker['Memory Used'] = number_format($tUsage / 1024.0, 1); $tMarker['Memory Used'] = $this->highlight($tMarker['Memory Used'], $tUsage, 400000); /* if($tUsage > 400000) // Highlight high memory usage. { $tMarker['Memory Used'] = "".$tMarker['Memory Used'].""; }*/ $aSum['Memory'] = $tMem; if($tMarker['What'] === 'Stop') { $tMarker['Time'] = ' '; $tMarker['%Time'] = ' '; $tMarker['%DB Count'] = ' '; $tMarker['%DB Time'] = ' '; $tMarker['DB Time'] = ' '; $tMarker['OB Lev'] = $this->aOBMarks[$tKey]; $tMarker['DB Count'] = ' '; } else { // Convert from start time to delta time, i.e. from now to next entry // $nextMarker = current($this->aTimeMarks); $it->next(); $nextMarker = $it->current(); $it->seek($tKey - 1); // go back one position. $aNextT = $nextMarker['Time']; $aThisT = $tMarker['Time']; $thisDelta = e107::getSingleton('e107_traffic')->TimeDelta($aThisT, $aNextT); $aSum['Time'] += $thisDelta; $aSum['DB Time'] += $tMarker['DB Time']; $aSum['DB Count'] += $tMarker['DB Count']; $tMarker['Time'] = number_format($thisDelta * 1000.0, 1); $tMarker['Time'] = $this->highlight($tMarker['Time'], $thisDelta, .2); $tMarker['%Time'] = $totTime ? number_format(100.0 * ($thisDelta / $totTime), 0) : 0; $tMarker['%Time'] = $this->highlight($tMarker['%Time'], $tMarker['%Time'], 20); $tMarker['%DB Count'] = number_format(100.0 * $tMarker['DB Count'] / $sql->db_QueryCount(), 0); $tMarker['%DB Time'] = $db_time ? number_format(100.0 * $tMarker['DB Time'] / $db_time, 0) : 0; // $tMarker['DB Time'] = number_format($tMarker['DB Time'] * 1000.0, 1); $dbTime = number_format($tMarker['DB Time'] * 1000.0, 1); $tMarker['DB Time'] = $this->highlight($dbTime,$dbTime, 10); $tMarker['OB Lev'] = $this->aOBMarks[$tKey]; } $text .= "\n"; if(isset($this->aMarkNotes[$tKey])) { $text .= "\n"; } if($tMarker['What'] === 'Stop') { break; } } $text .= $head; $aSum['%Time'] = $totTime ? number_format(100.0 * ($aSum['Time'] / $totTime), 0) : 0; $aSum['%DB Time'] = $db_time ? number_format(100.0 * ($aSum['DB Time'] / $db_time), 0) : 0; $aSum['%DB Count'] = ($sql->db_QueryCount()) ? number_format(100.0 * ($aSum['DB Count'] / ($sql->db_QueryCount())), 0) : 0; $aSum['Time'] = number_format($aSum['Time'] * 1000.0, 1); $aSum['DB Time'] = number_format($aSum['DB Time'] * 1000.0, 1); $text .= " "; // $text .= "\n"; $text .= "\n
" . implode(" ", array_keys($tMarker)) . " OB Lev 
" . implode(" ", $aUnits) . " 
" . implode(" ", array_values($tMarker)) . " 
 "; $text .= $this->aMarkNotes[$tKey] . "
  Total " . $aSum['%Time'] . " " . $aSum['%DB Time'] . " " . $aSum['%DB Count'] . " " . $aSum['Time'] . " " . $aSum['DB Time'] . " " . $aSum['DB Count'] . " " . number_format($aSum['Memory'] / 1024, 1) . " " . number_format($aSum['Memory'] / 1024, 1) . " " . $tMarker['OB Lev'] . "
".implode(" ", $aSum)."  

\n"; // // Stats by Table // $text .= "\n\n"; $bRowHeaders = false; $aSum = $this->aDBbyTable['core']; // create a template from the 'real' array $aSum['Table'] = 'Total'; $aSum['%DB Time'] = 0; $aSum['%DB Count'] = 0; $aSum['DB Time'] = 0; $aSum['DB Count'] = 0; foreach($this->aDBbyTable as $curTable) { if(!$bRowHeaders) { $bRowHeaders = true; $text .= "\n"; $aUnits = $curTable; foreach($aUnits as $key => $val) { switch($key) { case 'DB Time': $aUnits[$key] = '(msec)'; break; default: $aUnits[$key] = ''; break; } } $text .= "\n"; } $aSum['DB Time'] += $curTable['DB Time']; $aSum['DB Count'] += $curTable['DB Count']; $curTable['%DB Count'] = number_format(100.0 * $curTable['DB Count'] / $sql->db_QueryCount(), 0); $curTable['%DB Time'] = number_format(100.0 * $curTable['DB Time'] / $db_time, 0); $timeLabel = number_format($curTable['DB Time'] * 1000.0, 1); $curTable['DB Time'] = $this->highlight($timeLabel, ($curTable['DB Time'] * 1000), 500); // 500 msec $text .= "\n"; } $aSum['%DB Time'] = $db_time ? number_format(100.0 * ($aSum['DB Time'] / $db_time), 0) : 0; $aSum['%DB Count'] = ($sql->db_QueryCount()) ? number_format(100.0 * ($aSum['DB Count'] / ($sql->db_QueryCount())), 0) : 0; $aSum['DB Time'] = number_format($aSum['DB Time'] * 1000.0, 1); $text .= "\n"; $text .= "\n
" . implode("", array_keys($curTable)) . "
" . implode(" ", $aUnits) . " 
" . implode(" ", array_values($curTable)) . " 
" . implode(" ", array_values($aSum)) . " 

\n"; return $text; } /** * @param $message * @param $file * @param $line * @return void|null */ function logDeprecated($message=null, $file=null, $line=null) { if(!empty($message) || !empty($file)) { $this->deprecated_funcs[] = array( 'func' => $message, 'file' => $file, 'line' => $line ); return null; } $back_trace = debug_backtrace(); // print_r($back_trace); $this->deprecated_funcs[] = array( 'message' => varset($message), 'func' => (isset($back_trace[1]['type']) && ($back_trace[1]['type'] === '::' || $back_trace[1]['type'] === '->') ? $back_trace[1]['class'] . $back_trace[1]['type'] . $back_trace[1]['function'] : $back_trace[1]['function']), 'file' => $back_trace[1]['file'], 'line' => $back_trace[1]['line'] ); } /** * @param $type * @param $code * @param $parm * @param $details * @return false|null */ function logCode($type, $code, $parm, $details) { if(!E107_DBG_BBSC || !$this->active) { return false; } $this->scbbcodes[$this->scbcount]['type'] = $type; $this->scbbcodes[$this->scbcount]['code'] = $code; $this->scbbcodes[$this->scbcount]['parm'] = is_array($parm) ? var_export($parm, true) : (string) $parm; $this->scbbcodes[$this->scbcount]['details'] = $details; $this->scbcount++; return null; } /** * @param $force * @return false|string */ function Show_SC_BB($force = false) { if(!E107_DBG_BBSC && ($force === false)) { return false; } $text = "\n"; $description = array(1 => 'Bbcode', 2 => 'Shortcode', 3 => 'Wrapper', 4 => 'Shortcode Override', -2 => 'Shortcode Failure'); $style = array(1 => 'label-info', 2 => 'label-primary', 3 => 'label-warning', 'label-danger', -2 => 'label-danger'); foreach($this->scbbcodes as $codes) { $type = $codes['type']; $text .= "\n"; } $text .= "
Type Code Parm Details
" . ($description[$type]) . " " . (isset($codes['code']) ? $codes['code'] : " ") . " " . ($codes['parm'] ? $codes['parm'] : " ") . " " . ($codes['details'] ? $codes['details'] : " ") . "
"; return $text; } /** * @param $value * @return bool */ private function includeVar($value) { $prefix = array('ADMIN', 'E_', 'e_', 'E107', 'SITE', 'USER', 'CORE'); foreach($prefix as $c) { if(strpos($value, $c) === 0) { return true; } } return false; } /** * @param $force * @return false|string */ function Show_PATH($force = false) { if(!E107_DBG_PATH && ($force === false)) { return false; } $e107 = e107::getInstance(); $sql = e107::getDb(); $text = "\n"; $inc = array( 'BOOTSTRAP', 'HEADERF', 'FOOTERF', 'FILE_UPLOADS', 'FLOODPROTECT', 'FLOODTIMEOUT', 'FONTAWESOME', 'CHARSET', 'GUESTS_ONLINE', 'MEMBERS_ONLINE', 'PAGE_NAME', 'STANDARDS_MODE', 'TIMEOFFSET', 'TOTAL_ONLINE', 'THEME', 'THEME_ABS', 'THEME_LAYOUT', 'THEME_LEGACY', 'THEME_VERSION', 'THEME_STYLE', 'META_OG', 'META_DESCRIPTION', 'MPREFIX', 'VIEWPORT', 'BODYTAG', 'CSSORDER' ); $userCon = get_defined_constants(true); ksort($userCon['user']); $c = 0; foreach($userCon['user'] as $k => $v) { if(E107_DBG_ALLERRORS || in_array($k, $inc) || $this->includeVar($k)) { $text .= " "; $c++; } } $sess = e107::getSession(); $text .= " "; if($_SERVER['E_DEV'] == 'true') { $text .= " "; foreach($e107 as $key=>$val) { $text .= " "; } } $text .= " "; $regis = e107::getRegistry('_all_'); ksort($regis); $c = 0; foreach($regis as $key=>$val) { $id = "view-registry-".$c; $text .= ""; $c++; } $text .= " "; return $text; } /** * @param $force * @return false|string */ function Show_DEPRECATED($force = false) { if(!E107_DBG_DEPRECATED && ($force === false)) { return false; } $text = " \n"; if(empty($this->deprecated_funcs)) { $text .= ""; } else { // $unique = array_unique($this->deprecated_funcs); foreach($this->deprecated_funcs as $funcs) { $text .= "\n"; } } $text .= "
Info File Line
None Found
{$funcs['func']} ".(is_array($funcs['file']) ? print_a($funcs['file'],true) : $funcs['file'])." {$funcs['line']}
"; return $text; } /** * var_dump to debug log * * @param mixed $message */ function dump($message, $TraceLev = 1) { ob_start(); var_dump($message); $content = ob_get_clean(); $bt = debug_backtrace(); $this->aLog[] = array( 'Message' => $content, 'Function' => (isset($bt[$TraceLev]['type']) && ($bt[$TraceLev]['type'] == '::' || $bt[$TraceLev]['type'] == '->') ? $bt[$TraceLev]['class'] . $bt[$TraceLev]['type'] . $bt[$TraceLev]['function'] . '()' : $bt[$TraceLev]['function']) . '()', 'File' => varset($bt[$TraceLev]['file']), 'Line' => varset($bt[$TraceLev]['line']) ); // $this->aLog[] = array ('Message' => $content, 'Function' => '', 'File' => '', 'Line' => '' ); } /** * @desc Simple debug-level 'console' log * Record a "nice" debug message with * $db_debug->log("message"); * @param string|array $message * @param int $TraceLev * @return bool true on success , false on error */ public function log($message, $TraceLev = 1) { if(!$this->active) { return null; } if(!is_string($message)) { $message = "
" . var_export($message, true) . "
"; } if(!deftrue('E107_DBG_BASIC') && !deftrue('E107_DBG_ALLERRORS') && !deftrue('E107_DBG_SQLDETAILS') && !deftrue('E107_DBG_NOTICES')) { return false; } if($TraceLev) { $bt = debug_backtrace(); $this->aLog[] = array( 'Message' => $message, 'Function' => (isset($bt[$TraceLev]['type']) && ($bt[$TraceLev]['type'] == '::' || $bt[$TraceLev]['type'] == '->') ? $bt[$TraceLev]['class'] . $bt[$TraceLev]['type'] . $bt[$TraceLev]['function'] . '()' : $bt[$TraceLev]['function']) . '()', 'File' => varset($bt[$TraceLev]['file']), 'Line' => varset($bt[$TraceLev]['line']) ); } else { $this->aLog[] = array( 'Message' => $message, 'Function' => '', 'File' => '', 'Line' => '' ); } return true; } /** * @return bool|string */ function Show_Log() { if(empty($this->aLog)) { return false; } // // Dump the debug log // $text = "\n\n"; $bRowHeaders = false; foreach($this->aLog as $curLog) { if(!$bRowHeaders) { $bRowHeaders = true; $text .= "\n"; } $text .= "\n"; } $text .= "
" . implode("", array_keys($curLog)) . "
" . implode(" ", array_values($curLog)) . " 

\n"; return $text; } /** * @param $force * @return false|string */ function Show_Includes($force = false) { if(!E107_DBG_INCLUDES && ($force === false)) { return false; } $text = "\n"; $text .= "\n\n"; $text .= "
" . implode(" 
", $this->aIncList) . " 
\n"; return $text; } } // // Helper functions (not part of the class) // /** * @return void */ function e107_debug_shutdown() { if(e_AJAX_REQUEST) // extra output will break json ajax returns ie. comments { return; } global $error_handler; if(!empty($GLOBALS['E107_CLEAN_EXIT'])) { return; } if(empty($GLOBALS['E107_IN_FOOTER'])) { $ADMIN_DIRECTORY = e107::getFolder('admin'); if(deftrue('ADMIN_AREA')) { $filewanted = realpath(__DIR__) . '/../' . $ADMIN_DIRECTORY . 'footer.php'; require_once($filewanted); } elseif(deftrue('USER_AREA')) { $filewanted = realpath(__DIR__) . '/../' . FOOTERF; require_once($filewanted); } } // // Error while in the footer, or during startup, or during above processing // if(!empty($GLOBALS['E107_CLEAN_EXIT'])) { return; } while(ob_get_level() > 0) { ob_end_flush(); } if(isset($error_handler)) { if($error_handler->return_errors()) { echo "

PHP Errors:


" . $error_handler->return_errors() . "
\n"; echo ""; } } else { echo "e107 Shutdown while no error_handler available!"; echo ""; } }