Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00088 class t3lib_timeTrack { 00089 var $starttime = 0; // Is loaded with the millisecond time when this object is created 00090 00091 var $LR = 1; // Log Rendering flag. If set, ->push() and ->pull() is called from the cObj->cObjGetSingle(). This determines whether or not the TypoScript parsing activity is logged. But it also slows down the rendering 00092 var $printConf=array( 00093 'showParentKeys' => 1, 00094 'contentLength' => 10000, // Determines max lenght of displayed content before it gets cropped. 00095 'contentLength_FILE' => 400, // Determines max lenght of displayed content FROM FILE cObjects before it gets cropped. Reason is that most FILE cObjects are huge and often used as template-code. 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 ); 00105 00106 var $wrapError =array( 00107 0 => array('',''), 00108 1 => array('<b>','</b>'), 00109 2 => array('<b><font color="#ff6600">','</font></b>'), 00110 3 => array('<b><font color="#ff0000">','</font></b>') 00111 ); 00112 var $wrapIcon =array( 00113 0 => '', 00114 1 => '<img src="typo3/gfx/icon_note.gif" width="18" height="16" align="absmiddle" alt="" />', 00115 2 => '<img src="typo3/gfx/icon_warning.gif" width="18" height="16" align="absmiddle" alt="" />', 00116 3 => '<img src="typo3/gfx/icon_fatalerror.gif" width="18" height="16" align="absmiddle" alt="" />' 00117 ); 00118 00119 var $uniqueCounter=0; 00120 var $tsStack = array(array()); 00121 var $tsStackLevel = 0; 00122 var $tsStackLevelMax=array(); 00123 var $tsStackLog = array(); 00124 var $tsStackPointer=0; 00125 var $currentHashPointer=array(); 00126 00127 00128 00129 00130 00131 00132 /******************************************* 00133 * 00134 * Logging parsing times in the scripts 00135 * 00136 *******************************************/ 00137 00144 function start() { 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 // setTSlog 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 $this->tsStackLog[$k]['message'][] = $this->wrapIcon[$num].$this->wrapError[$num][0].htmlspecialchars($content).$this->wrapError[$num][1]; 00212 } 00213 00221 function setTSselectQuery($query,$msg) { 00222 end($this->currentHashPointer); 00223 $k = current($this->currentHashPointer); 00224 00225 $this->tsStackLog[$k]['selectQuery'][] = array('query'=>$query,'msg'=>$msg); 00226 } 00227 00234 function incStackPointer() { 00235 $this->tsStackPointer++; 00236 $this->tsStack[$this->tsStackPointer]=array(); 00237 } 00238 00245 function decStackPointer() { 00246 unset($this->tsStack[$this->tsStackPointer]); 00247 $this->tsStackPointer--; 00248 } 00249 00255 function mtime() { 00256 return $this->convertMicrotime(microtime())-$this->starttime; 00257 } 00258 00265 function convertMicrotime($microtime) { 00266 $parts = explode(' ',$microtime); 00267 return round(($parts[0]+$parts[1])*1000); 00268 } 00269 00270 00271 00272 00273 00274 00275 00276 00277 00278 00279 00280 00281 00282 00283 00284 00285 00286 /******************************************* 00287 * 00288 * Printing the parsing time information (for Admin Panel) 00289 * 00290 *******************************************/ 00291 00298 function printTSlog() { 00299 // Calculate times and keys for the tsStackLog 00300 $preEndtime=0; 00301 foreach($this->tsStackLog as $uniqueId=>$data) { 00302 $this->tsStackLog[$uniqueId]['endtime'] = $this->convertMicrotime($this->tsStackLog[$uniqueId]['endtime'])-$this->starttime; 00303 $this->tsStackLog[$uniqueId]['starttime'] = $this->convertMicrotime($this->tsStackLog[$uniqueId]['starttime'])-$this->starttime; 00304 $this->tsStackLog[$uniqueId]['deltatime'] = $this->tsStackLog[$uniqueId]['endtime']-$this->tsStackLog[$uniqueId]['starttime']; 00305 $this->tsStackLog[$uniqueId]['key'] = implode($this->tsStackLog[$uniqueId]['stackPointer']?'.':'/', end($data['tsStack'])); 00306 $preEndtime = $this->tsStackLog[$uniqueId]['endtime']; 00307 } 00308 00309 // Create hierarchical array of keys pointing to the stack 00310 $arr = array(); 00311 reset($this->tsStackLog); 00312 while(list($uniqueId,$data)=each($this->tsStackLog)) { 00313 $this->createHierarchyArray($arr,$data['level'], $uniqueId); 00314 } 00315 // Parsing the registeret content and create icon-html for the tree 00316 $this->tsStackLog[$arr['0.'][0]]['content'] = $this->fixContent($arr['0.']['0.'], $this->tsStackLog[$arr['0.'][0]]['content'], '', 0, $arr['0.'][0]); 00317 00318 // Displaying the tree: 00319 reset($this->tsStackLog); 00320 $out='<tr> 00321 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('TypoScript Key').'</b></td> 00322 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Value').'</b></td>'; 00323 if ($this->printConf['allTime']) { 00324 $out.=' 00325 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Time').'</b></td> 00326 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Own').'</b></td> 00327 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Sub').'</b></td> 00328 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Total').'</b></td>'; 00329 } else { 00330 $out.=' 00331 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Own').'</b></td>'; 00332 } 00333 00334 $out.=' 00335 <td bgcolor="#ABBBB4" align="center"><b>'.$this->fw('Details').'</b></td> 00336 </tr>'; 00337 00338 00339 00340 $flag_tree=$this->printConf['flag_tree']; 00341 $flag_messages=$this->printConf['flag_messages']; 00342 $flag_content=$this->printConf['flag_content']; 00343 $flag_queries=$this->printConf['flag_queries']; 00344 $keyLgd=$this->printConf['keyLgd']; 00345 $factor=$this->printConf['factor']; 00346 $col=$this->printConf['col']; 00347 00348 $c=0; 00349 while(list($uniqueId,$data)=each($this->tsStackLog)) { 00350 $bgColor = ' bgcolor="'.($c%2 ? t3lib_div::modifyHTMLColor($col,$factor,$factor,$factor) : $col).'"'; 00351 $item=''; 00352 if (!$c) { // If first... 00353 $data['icons']=''; 00354 $data['key']= 'Script Start'; 00355 $data['value'] = ''; 00356 } 00357 00358 00359 // key label: 00360 $keyLabel=''; 00361 if (!$flag_tree && $data['stackPointer']) { 00362 $temp=array(); 00363 reset($data['tsStack']); 00364 while(list($k,$v)=each($data['tsStack'])) { 00365 $temp[]=t3lib_div::fixed_lgd_pre(implode($v,$k?'.':'/'),$keyLgd); 00366 } 00367 array_pop($temp); 00368 $temp = array_reverse($temp); 00369 array_pop($temp); 00370 if (count($temp)) { 00371 $keyLabel='<br /><font color="#999999">'.implode($temp,'<br />').'</font>'; 00372 } 00373 } 00374 if ($flag_tree) { 00375 $tmp = t3lib_div::trimExplode('.',$data['key'],1); 00376 $theLabel = end($tmp); 00377 } else { 00378 $theLabel = $data['key']; 00379 } 00380 $theLabel = t3lib_div::fixed_lgd_pre($theLabel, $keyLgd); 00381 $theLabel = $data['stackPointer'] ? '<font color="maroon">'.$theLabel.'</font>' : $theLabel; 00382 $keyLabel=$theLabel.$keyLabel; 00383 $item.='<td valign="top" nowrap="nowrap"'.$bgColor.'>'.($flag_tree?$data['icons']:'').$this->fw($keyLabel).'</td>'; 00384 00385 // key value: 00386 $keyValue=$data['value']; 00387 $item.='<td valign="top" nowrap="nowrap"'.$bgColor.'>'.$this->fw(htmlspecialchars($keyValue)).'</td>'; 00388 00389 if ($this->printConf['allTime']) { 00390 // deltatime: 00391 $item.='<td valign="top" align="right" nowrap="nowrap"'.$bgColor.'>'.$this->fw($data['starttime']).'</td>'; 00392 $item.='<td valign="top" align="right" nowrap="nowrap"'.$bgColor.'>'.$this->fw($data['owntime']).'</td>'; 00393 $item.='<td valign="top" align="right" nowrap="nowrap"'.$bgColor.'>'.$this->fw($data['subtime'] ? '+'.$data['subtime'] : '').'</td>'; 00394 $item.='<td valign="top" align="right" nowrap="nowrap"'.$bgColor.'>'.$this->fw($data['subtime'] ? '='.$data['deltatime'] : '').'</td>'; 00395 } else { 00396 // deltatime: 00397 $item.='<td valign="top" align="right" nowrap="nowrap"'.$bgColor.'>'.$this->fw($data['owntime']).'</td>'; 00398 } 00399 00400 00401 // messages: 00402 $msgArr=array(); 00403 $msg=''; 00404 if ($flag_messages && is_array($data['message'])) { 00405 reset($data['message']); 00406 while(list(,$v)=each($data['message'])) { 00407 $msgArr[]=nl2br($v); 00408 } 00409 } 00410 if ($flag_queries && is_array($data['selectQuery'])) { 00411 reset($data['selectQuery']); 00412 while(list(,$v)=each($data['selectQuery'])) { 00413 $res = $GLOBALS['TYPO3_DB']->sql_query('EXPLAIN '.$v['query']); 00414 $v['mysql_error'] = $GLOBALS['TYPO3_DB']->sql_error(); 00415 if (!$GLOBALS['TYPO3_DB']->sql_error()) { 00416 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 00417 $v['explain'][]=$row; 00418 } 00419 } 00420 $msgArr[]=t3lib_div::view_array($v); 00421 } 00422 } 00423 if ($flag_content && strcmp($data['content'],'')) { 00424 $msgArr[]='<font color="#000066">'.nl2br($data['content']).'</font>'; 00425 } 00426 if (count($msgArr)) { 00427 $msg=implode($msgArr,'<hr />'); 00428 } 00429 $item.='<td valign="top"'.$bgColor.'>'.$this->fw($msg).'</td>'; 00430 $out.='<tr>'.$item.'</tr>'; 00431 $c++; 00432 } 00433 $out='<table border="0" cellpadding="0" cellspacing="0">'.$out.'</table>'; 00434 return $out; 00435 } 00436 00447 function fixContent(&$arr, $content, $depthData='', $first=0, $vKey='') { 00448 $ac=0; 00449 $c=0; 00450 // First, find number of entries 00451 reset($arr); 00452 while(list($k,$v)=each($arr)) { 00453 if (t3lib_div::testInt($k)) { 00454 $ac++; 00455 } 00456 } 00457 // Traverse through entries 00458 $subtime=0; 00459 reset($arr); 00460 while(list($k,$v)=each($arr)) { 00461 if (t3lib_div::testInt($k)) { 00462 $c++; 00463 00464 $deeper = is_array($arr[$k.'.']) ? 1 : 0; 00465 $PM = 'join'; 00466 $LN = ($ac==$c)?'blank':'line'; 00467 $BTM = ($ac==$c)?'bottom':''; 00468 $PM = is_array($arr[$k.'.']) ? ($deeper ? 'minus':'plus') : 'join'; 00469 $this->tsStackLog[$v]['icons']=$depthData.($first?'':'<img src="'.TYPO3_mainDir.'gfx/ol/'.$PM.$BTM.'.gif" width="18" height="16" align="top" border="0" alt="" />'); 00470 00471 if (strlen($this->tsStackLog[$v]['content'])) { 00472 $content = str_replace($this->tsStackLog[$v]['content'],$v, $content); 00473 } 00474 if (is_array($arr[$k.'.'])) { 00475 $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); 00476 } else { 00477 $this->tsStackLog[$v]['content'] = $this->fixCLen($this->tsStackLog[$v]['content'], $this->tsStackLog[$v]['value']); 00478 $this->tsStackLog[$v]['subtime']=''; 00479 $this->tsStackLog[$v]['owntime']=$this->tsStackLog[$v]['deltatime']; 00480 } 00481 $subtime+=$this->tsStackLog[$v]['deltatime']; 00482 } 00483 } 00484 // Set content with special chars 00485 if (isset($this->tsStackLog[$vKey])) { 00486 $this->tsStackLog[$vKey]['subtime']=$subtime; 00487 $this->tsStackLog[$vKey]['owntime']=$this->tsStackLog[$vKey]['deltatime']-$subtime; 00488 } 00489 $content=$this->fixCLen($content, $this->tsStackLog[$vKey]['value']); 00490 00491 // Traverse array again, this time substitute the unique hash with the red key 00492 reset($arr); 00493 while(list($k,$v)=each($arr)) { 00494 if (t3lib_div::testInt($k)) { 00495 if (strlen($this->tsStackLog[$v]['content'])) { 00496 $content = str_replace($v, '<font color="red"><b>['.$this->tsStackLog[$v]['key'].']</b></font>', $content); 00497 } 00498 } 00499 } 00500 // return the content 00501 return $content; 00502 } 00503 00511 function fixCLen($c,$v) { 00512 $len = $v=='FILE'?$this->printConf['contentLength_FILE']:$this->printConf['contentLength']; 00513 if (strlen($c)>$len) { 00514 $c='<font color="green">'.htmlspecialchars(t3lib_div::fixed_lgd($c,$len)).'</font>'; 00515 } else { 00516 $c=htmlspecialchars($c); 00517 } 00518 return $c; 00519 } 00520 00527 function fw($str) { 00528 return '<font face="verdana" color="black" size="1" style="color:black;">'.$str.' </font>'; 00529 } 00530 00541 function createHierarchyArray(&$arr,$pointer,$uniqueId) { 00542 if (!is_array($arr)) $arr=array(); 00543 if ($pointer>0) { 00544 end($arr); 00545 $k=key($arr); 00546 $this->createHierarchyArray($arr[intval($k).'.'],$pointer-1,$uniqueId); 00547 } else { 00548 $arr[] = $uniqueId; 00549 } 00550 } 00551 00561 function debug_typo3PrintError($header,$text,$js,$baseUrl='') { 00562 if ($js) { 00563 echo"alert('".t3lib_div::slashJS($header."\n".$text)."');"; 00564 } else { 00565 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 00566 "http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd"> 00567 <?xml version="1.0" encoding="utf-8"?> 00568 <html> 00569 <head> 00570 '.($baseUrl ? '<base href="'.htmlspecialchars($baseUrl).'" />' : '').' 00571 <title>Error!</title> 00572 <style type="text/css"><!--/*--><![CDATA[/*><!--*/ 00573 body { font-family: verdana,arial,helvetica; font-size: 90%; text-align: center; background-color: #ffffff; } 00574 h1 { font-size: 1.2em; margin: 0 0 1em 0; } 00575 p { margin: 0; text-align: left; } 00576 img { border: 0; margin: 10px 0; } 00577 div.center div { margin: 0 auto; } 00578 .errorBox { width: 400px; padding: 0.5em; border: 1px solid black; background-color: #F4F0E8; } 00579 /*]]>*/--></style> 00580 </head> 00581 <body> 00582 <div class="center"> 00583 <img src="'.TYPO3_mainDir.'gfx/typo3logo.gif" width="123" height="34" alt="" /> 00584 <div class="errorBox"> 00585 <h1>'.$header.'</h1> 00586 <p>'.$text.'</p> 00587 </div> 00588 </div> 00589 </body> 00590 </html>'; 00591 } 00592 } 00593 } 00594 ?>