00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00088 class t3lib_timeTrack {
00089 var $starttime = 0;
00090
00091 var $LR = 1;
00092 var $printConf=array(
00093 'showParentKeys' => 1,
00094 'contentLength' => 10000,
00095 'contentLength_FILE' => 400,
00096 'flag_tree' => 1,
00097 'flag_messages' => 1,
00098 'flag_queries' => 0,
00099 'flag_content' => 0,
00100 'allTime' => 0,
00101 'keyLgd' => 40,
00102 'factor' => 10,
00103 'col' => '#D9D5C9',
00104 'highlight_col' => '#FF9933'
00105 );
00106
00107 var $wrapError = array();
00108 var $wrapIcon = array();
00109 var $uniqueCounter = 0;
00110 var $tsStack = array(array());
00111 var $tsStackLevel = 0;
00112 var $tsStackLevelMax = array();
00113 var $tsStackLog = array();
00114 var $tsStackPointer = 0;
00115 var $currentHashPointer = array();
00116
00117 var $highlightLongerThan = 0;
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00137 function start() {
00138 $this->wrapError = array(
00139 0 => array('',''),
00140 1 => array('<strong>','</strong>'),
00141 2 => array('<strong style="color:#ff6600;">','</strong>'),
00142 3 => array('<strong style="color:#ff0000;">','</strong>')
00143 );
00144
00145 $this->wrapIcon = array(
00146 0 => '',
00147 1 => '<img src="'.TYPO3_mainDir.'gfx/icon_note.gif" width="18" height="16" align="absmiddle" alt="" />',
00148 2 => '<img src="'.TYPO3_mainDir.'gfx/icon_warning.gif" width="18" height="16" align="absmiddle" alt="" />',
00149 3 => '<img src="'.TYPO3_mainDir.'gfx/icon_fatalerror.gif" width="18" height="16" align="absmiddle" alt="" />'
00150 );
00151
00152 $this->starttime = 0;
00153 $this->starttime = $this->mtime();
00154 }
00155
00164 function push($tslabel, $value='') {
00165 array_push($this->tsStack[$this->tsStackPointer], $tslabel);
00166 array_push($this->currentHashPointer, 'timetracker_'.$this->uniqueCounter++);
00167
00168 $this->tsStackLevel++;
00169 $this->tsStackLevelMax[] = $this->tsStackLevel;
00170
00171
00172 $k = end($this->currentHashPointer);
00173 $this->tsStackLog[$k] = array(
00174 'level' => $this->tsStackLevel,
00175 'tsStack' => $this->tsStack,
00176 'value' => $value,
00177 'starttime' => microtime(),
00178 'stackPointer' => $this->tsStackPointer
00179 );
00180 }
00181
00189 function pull($content='') {
00190 $k = end($this->currentHashPointer);
00191 $this->tsStackLog[$k]['endtime'] = microtime();
00192 $this->tsStackLog[$k]['content'] = $content;
00193
00194 $this->tsStackLevel--;
00195 array_pop($this->tsStack[$this->tsStackPointer]);
00196 array_pop($this->currentHashPointer);
00197 }
00198
00207 function setTSlogMessage($content,$num=0) {
00208 end($this->currentHashPointer);
00209 $k = current($this->currentHashPointer);
00210
00211 if (strlen($content)>30) {
00212 $placeholder = '<br /><img src="'.TYPO3_mainDir.'clear.gif" width="300" height="1" alt="" />';
00213 }
00214 $this->tsStackLog[$k]['message'][] = $this->wrapIcon[$num].$this->wrapError[$num][0].htmlspecialchars($content).$this->wrapError[$num][1].$placeholder;
00215 }
00216
00224 function setTSselectQuery($query,$msg) {
00225 end($this->currentHashPointer);
00226 $k = current($this->currentHashPointer);
00227
00228 $this->tsStackLog[$k]['selectQuery'][] = array('query'=>$query,'msg'=>$msg);
00229 }
00230
00237 function incStackPointer() {
00238 $this->tsStackPointer++;
00239 $this->tsStack[$this->tsStackPointer]=array();
00240 }
00241
00248 function decStackPointer() {
00249 unset($this->tsStack[$this->tsStackPointer]);
00250 $this->tsStackPointer--;
00251 }
00252
00258 function mtime() {
00259 return $this->convertMicrotime(microtime())-$this->starttime;
00260 }
00261
00268 function convertMicrotime($microtime) {
00269 $parts = explode(' ',$microtime);
00270 return round(($parts[0]+$parts[1])*1000);
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00301 function printTSlog() {
00302
00303 $preEndtime = 0;
00304 foreach($this->tsStackLog as $uniqueId=>$data) {
00305 $this->tsStackLog[$uniqueId]['endtime'] = $this->convertMicrotime($this->tsStackLog[$uniqueId]['endtime'])-$this->starttime;
00306 $this->tsStackLog[$uniqueId]['starttime'] = $this->convertMicrotime($this->tsStackLog[$uniqueId]['starttime'])-$this->starttime;
00307 $this->tsStackLog[$uniqueId]['deltatime'] = $this->tsStackLog[$uniqueId]['endtime']-$this->tsStackLog[$uniqueId]['starttime'];
00308 $this->tsStackLog[$uniqueId]['key'] = implode($this->tsStackLog[$uniqueId]['stackPointer']?'.':'/', end($data['tsStack']));
00309 $preEndtime = $this->tsStackLog[$uniqueId]['endtime'];
00310 }
00311
00312
00313 $arr = array();
00314 reset($this->tsStackLog);
00315 while(list($uniqueId,$data)=each($this->tsStackLog)) {
00316 $this->createHierarchyArray($arr,$data['level'], $uniqueId);
00317 }
00318
00319 $this->tsStackLog[$arr['0.'][0]]['content'] = $this->fixContent($arr['0.']['0.'], $this->tsStackLog[$arr['0.'][0]]['content'], '', 0, $arr['0.'][0]);
00320
00321
00322 reset($this->tsStackLog);
00323
00324 $outputArr = array();
00325 $outputArr[] = $this->fw('TypoScript Key');
00326 $outputArr[] = $this->fw('Value');
00327
00328 if ($this->printConf['allTime']) {
00329 $outputArr[] = $this->fw('Time');
00330 $outputArr[] = $this->fw('Own');
00331 $outputArr[] = $this->fw('Sub');
00332 $outputArr[] = $this->fw('Total');
00333 } else {
00334 $outputArr[] = $this->fw('Own');
00335 }
00336
00337 $outputArr[] = $this->fw('Details');
00338
00339 $out = '';
00340 foreach ($outputArr as $row) {
00341 $out.= '
00342 <th style="text-align:center; background:#ABBBB4;"><strong>'.$row.'</strong></th>';
00343 }
00344 $out = '<tr>'.$out.'</tr>';
00345
00346 $flag_tree = $this->printConf['flag_tree'];
00347 $flag_messages = $this->printConf['flag_messages'];
00348 $flag_content = $this->printConf['flag_content'];
00349 $flag_queries = $this->printConf['flag_queries'];
00350 $keyLgd = $this->printConf['keyLgd'];
00351 $factor = $this->printConf['factor'];
00352 $col = $this->printConf['col'];
00353 $highlight_col = $this->printConf['highlight_col'];
00354
00355 $c=0;
00356 while(list($uniqueId,$data)=each($this->tsStackLog)) {
00357 $bgColor = ' background-color:'.($c%2 ? t3lib_div::modifyHTMLColor($col,$factor,$factor,$factor) : $col).';';
00358 if ($this->highlightLongerThan && intval($data['owntime']) > intval($this->highlightLongerThan)) {
00359 $bgColor = ' background-color:'.$highlight_col.';';
00360 }
00361
00362 $item = '';
00363 if (!$c) {
00364 $data['icons'] = '';
00365 $data['key'] = 'Script Start';
00366 $data['value'] = '';
00367 }
00368
00369
00370
00371 $keyLabel = '';
00372 if (!$flag_tree && $data['stackPointer']) {
00373 $temp = array();
00374 reset($data['tsStack']);
00375 while(list($k,$v)=each($data['tsStack'])) {
00376 $temp[] = t3lib_div::fixed_lgd_pre(implode($v,$k?'.':'/'),$keyLgd);
00377 }
00378 array_pop($temp);
00379 $temp = array_reverse($temp);
00380 array_pop($temp);
00381 if (count($temp)) {
00382 $keyLabel = '<br /><span style="color:#999999;">'.implode($temp,'<br />').'</span>';
00383 }
00384 }
00385 if ($flag_tree) {
00386 $tmp = t3lib_div::trimExplode('.',$data['key'],1);
00387 $theLabel = end($tmp);
00388 } else {
00389 $theLabel = $data['key'];
00390 }
00391 $theLabel = t3lib_div::fixed_lgd_pre($theLabel, $keyLgd);
00392 $theLabel = $data['stackPointer'] ? '<span style="color:maroon;">'.$theLabel.'</span>' : $theLabel;
00393 $keyLabel = $theLabel.$keyLabel;
00394 $item.= '<td valign="top" style="text-align:left; white-space:nowrap; padding-left:2px;'.$bgColor.'">'.($flag_tree?$data['icons']:'').$this->fw($keyLabel).'</td>';
00395
00396
00397 $keyValue = $data['value'];
00398 $item.= '<td valign="top" style="text-align:left; white-space:nowrap;'.$bgColor.'">'.$this->fw(htmlspecialchars($keyValue)).'</td>';
00399
00400 if ($this->printConf['allTime']) {
00401 $item.= '<td valign="top" style="text-align:right; white-space:nowrap;'.$bgColor.'"> '.$this->fw($data['starttime']).'</td>';
00402 $item.= '<td valign="top" style="text-align:right; white-space:nowrap;'.$bgColor.'"> '.$this->fw($data['owntime']).'</td>';
00403 $item.= '<td valign="top" style="text-align:left; white-space:nowrap;'.$bgColor.'"> '.$this->fw($data['subtime'] ? '+'.$data['subtime'] : '').'</td>';
00404 $item.= '<td valign="top" style="text-align:left; white-space:nowrap;'.$bgColor.'"> '.$this->fw($data['subtime'] ? '='.$data['deltatime'] : '').'</td>';
00405 } else {
00406 $item.= '<td valign="top" style="text-align:right; white-space:nowrap;'.$bgColor.'"> '.$this->fw($data['owntime']).'</td>';
00407 }
00408
00409
00410
00411 $msgArr = array();
00412 $msg = '';
00413 if ($flag_messages && is_array($data['message'])) {
00414 reset($data['message']);
00415 while(list(,$v)=each($data['message'])) {
00416 $msgArr[] = nl2br($v);
00417 }
00418 }
00419 if ($flag_queries && is_array($data['selectQuery'])) {
00420 reset($data['selectQuery']);
00421 while(list(,$v)=each($data['selectQuery'])) {
00422 $res = $GLOBALS['TYPO3_DB']->sql_query('EXPLAIN '.$v['query']);
00423 $v['mysql_error'] = $GLOBALS['TYPO3_DB']->sql_error();
00424 if (!$GLOBALS['TYPO3_DB']->sql_error()) {
00425 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00426 $v['explain'][]=$row;
00427 }
00428 }
00429 $msgArr[] = t3lib_div::view_array($v);
00430 }
00431 }
00432 if ($flag_content && strcmp($data['content'],'')) {
00433 $maxlen = 120;
00434 if (preg_match_all('/(\S{'.$maxlen.',})/', $data['content'], $reg)) {
00435 foreach ($reg[1] as $key=>$match) {
00436 $match = preg_replace('/(.{'.$maxlen.'})/', '$1 ', $match);
00437 $data['content'] = str_replace($reg[0][$key], $match, $data['content']);
00438 }
00439 }
00440 $msgArr[] = '<span style="color:#000066;">'.nl2br($data['content']).'</span>';
00441 }
00442 if (count($msgArr)) {
00443 $msg = implode($msgArr,'<hr />');
00444 }
00445 $item.= '<td valign="top" style="text-align:left;'.$bgColor.'">'.$this->fw($msg).'</td>';
00446 $out.= '<tr>'.$item.'</tr>';
00447 $c++;
00448 }
00449 $out = '<table border="0" cellpadding="0" cellspacing="0" summary="">'.$out.'</table>';
00450 return $out;
00451 }
00452
00463 function fixContent(&$arr, $content, $depthData='', $first=0, $vKey='') {
00464 $ac=0;
00465 $c=0;
00466
00467 reset($arr);
00468 while(list($k,$v)=each($arr)) {
00469 if (t3lib_div::testInt($k)) {
00470 $ac++;
00471 }
00472 }
00473
00474 $subtime=0;
00475 reset($arr);
00476 while(list($k,$v)=each($arr)) {
00477 if (t3lib_div::testInt($k)) {
00478 $c++;
00479
00480 $deeper = is_array($arr[$k.'.']) ? 1 : 0;
00481 $PM = 'join';
00482 $LN = ($ac==$c)?'blank':'line';
00483 $BTM = ($ac==$c)?'bottom':'';
00484 $PM = is_array($arr[$k.'.']) ? ($deeper ? 'minus':'plus') : 'join';
00485 $this->tsStackLog[$v]['icons'] = $depthData.($first?'':'<img src="'.TYPO3_mainDir.'gfx/ol/'.$PM.$BTM.'.gif" width="18" height="16" align="top" border="0" alt="" />');
00486
00487 if (strlen($this->tsStackLog[$v]['content'])) {
00488 $content = str_replace($this->tsStackLog[$v]['content'],$v, $content);
00489 }
00490 if (is_array($arr[$k.'.'])) {
00491 $this->tsStackLog[$v]['content'] = $this->fixContent($arr[$k.'.'], $this->tsStackLog[$v]['content'], $depthData.($first?'':'<img src="'.TYPO3_mainDir.'gfx/ol/'.$LN.'.gif" width="18" height="16" align="top" border="0" alt="" />'), 0, $v);
00492 } else {
00493 $this->tsStackLog[$v]['content'] = $this->fixCLen($this->tsStackLog[$v]['content'], $this->tsStackLog[$v]['value']);
00494 $this->tsStackLog[$v]['subtime'] = '';
00495 $this->tsStackLog[$v]['owntime'] = $this->tsStackLog[$v]['deltatime'];
00496 }
00497 $subtime+= $this->tsStackLog[$v]['deltatime'];
00498 }
00499 }
00500
00501 if (isset($this->tsStackLog[$vKey])) {
00502 $this->tsStackLog[$vKey]['subtime'] = $subtime;
00503 $this->tsStackLog[$vKey]['owntime'] = $this->tsStackLog[$vKey]['deltatime']-$subtime;
00504 }
00505 $content=$this->fixCLen($content, $this->tsStackLog[$vKey]['value']);
00506
00507
00508 reset($arr);
00509 while(list($k,$v)=each($arr)) {
00510 if (t3lib_div::testInt($k)) {
00511 if (strlen($this->tsStackLog[$v]['content'])) {
00512 $content = str_replace($v, '<strong style="color:red;">['.$this->tsStackLog[$v]['key'].']</strong>', $content);
00513 }
00514 }
00515 }
00516
00517 return $content;
00518 }
00519
00527 function fixCLen($c,$v) {
00528 $len = $v=='FILE'?$this->printConf['contentLength_FILE']:$this->printConf['contentLength'];
00529 if (strlen($c)>$len) {
00530 $c = '<span style="color:green;">'.htmlspecialchars(t3lib_div::fixed_lgd($c,$len)).'</span>';
00531 } else {
00532 $c = htmlspecialchars($c);
00533 }
00534 return $c;
00535 }
00536
00543 function fw($str) {
00544 return '<span style="font-family:Verdana,Arial,Helvetica,sans-serif; font-size:0.6em; color:black; vertical-align:top;">'.$str.' </span>';
00545 }
00546
00557 function createHierarchyArray(&$arr,$pointer,$uniqueId) {
00558 if (!is_array($arr)) {
00559 $arr = array();
00560 }
00561 if ($pointer>0) {
00562 end($arr);
00563 $k = key($arr);
00564 $this->createHierarchyArray($arr[intval($k).'.'],$pointer-1,$uniqueId);
00565 } else {
00566 $arr[] = $uniqueId;
00567 }
00568 }
00569
00579 function debug_typo3PrintError($header,$text,$js,$baseUrl='') {
00580 if ($js) {
00581 echo "alert('".t3lib_div::slashJS($header."\n".$text)."');";
00582 } else {
00583 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
00584 "http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd">
00585 <?xml version="1.0" encoding="utf-8"?>
00586 <html>
00587 <head>
00588 '.($baseUrl ? '<base href="'.htmlspecialchars($baseUrl).'" />' : '').'
00589 <title>Error!</title>
00590 <style type="text/css"><!--
00591 body { font-family:Verdana,Arial,Helvetica,sans-serif; font-size: 90%; text-align: center; background-color: #ffffff; }
00592 h1 { font-size: 1.2em; margin: 0 0 1em 0; }
00593 p { margin: 0; text-align: left; }
00594 img { border: 0; margin: 10px 0; }
00595 div.center div { margin: 0 auto; }
00596 .errorBox { width: 400px; padding: 0.5em; border: 1px solid black; background-color: #F4F0E8; }
00597 --></style>
00598 </head>
00599 <body>
00600 <div class="center">
00601 <img src="'.TYPO3_mainDir.'gfx/typo3logo.gif" width="123" height="34" alt="" />
00602 <div class="errorBox">
00603 <h1>'.$header.'</h1>
00604 <p>'.$text.'</p>
00605 </div>
00606 </div>
00607 </body>
00608 </html>';
00609 }
00610 }
00611 }
00612
00613
00614
00615 ?>