|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2011 Kasper Skårhøj (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 ***************************************************************/ 00027 /** 00028 * Contains class with time tracking functions 00029 * 00030 * $Id: class.t3lib_timetrack.php 10547 2011-02-22 20:03:57Z lolli $ 00031 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj 00032 * XHTML compliant 00033 * 00034 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00035 */ 00036 /** 00037 * [CLASS/FUNCTION INDEX of SCRIPT] 00038 * 00039 * 00040 * 00041 * 88: class t3lib_timeTrack 00042 * 00043 * SECTION: Logging parsing times in the scripts 00044 * 144: function start() 00045 * 164: function push($tslabel, $value='') 00046 * 189: function pull($content='') 00047 * 207: function setTSlogMessage($content,$num=0) 00048 * 221: function setTSselectQuery($query,$msg) 00049 * 234: function incStackPointer() 00050 * 245: function decStackPointer() 00051 * 255: function mtime() 00052 * 265: function convertMicrotime($microtime) 00053 * 00054 * SECTION: Printing the parsing time information (for Admin Panel) 00055 * 298: function printTSlog() 00056 * 447: function fixContent(&$arr, $content, $depthData='', $first=0, $vKey='') 00057 * 511: function fixCLen($c,$v) 00058 * 527: function fw($str) 00059 * 541: function createHierarchyArray(&$arr,$pointer,$uniqueId) 00060 * 561: function debug_typo3PrintError($header,$text,$js,$baseUrl='') 00061 * 00062 * TOTAL FUNCTIONS: 15 00063 * (This index is automatically created/updated by the extension "extdeveval") 00064 * 00065 */ 00066 00067 00068 /** 00069 * Frontend Timetracking functions 00070 * 00071 * Is used to register how much time is used with operations in TypoScript 00072 * Used by index_ts 00073 * 00074 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00075 * @package TYPO3 00076 * @subpackage t3lib 00077 * @see t3lib_tsfeBeUserAuth, tslib_fe, tslib_cObj, TSpagegen 00078 */ 00079 class t3lib_timeTrack { 00080 var $starttime = 0; // Is loaded with the millisecond time when this object is created 00081 00082 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 00083 var $printConf = array( 00084 'showParentKeys' => 1, 00085 'contentLength' => 10000, // Determines max lenght of displayed content before it gets cropped. 00086 '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. 00087 'flag_tree' => 1, 00088 'flag_messages' => 1, 00089 'flag_queries' => 0, 00090 'flag_content' => 0, 00091 'allTime' => 0, 00092 'keyLgd' => 40, 00093 ); 00094 00095 var $wrapError = array(); 00096 var $wrapIcon = array(); 00097 var $uniqueCounter = 0; 00098 var $tsStack = array(array()); 00099 var $tsStackLevel = 0; 00100 var $tsStackLevelMax = array(); 00101 var $tsStackLog = array(); 00102 var $tsStackPointer = 0; 00103 var $currentHashPointer = array(); 00104 00105 var $highlightLongerThan = 0; // Log entries that take than this number of milliseconds (own time) will be highlighted during log display. Set 0 to disable highlighting. 00106 00107 00108 /******************************************* 00109 * 00110 * Logging parsing times in the scripts 00111 * 00112 *******************************************/ 00113 00114 /** 00115 * Constructor 00116 * Sets the starting time 00117 * 00118 * @return void 00119 */ 00120 public function start() { 00121 $this->wrapError = array( 00122 0 => array('', ''), 00123 1 => array('<strong>', '</strong>'), 00124 2 => array('<strong style="color:#ff6600;">', '</strong>'), 00125 3 => array('<strong style="color:#ff0000;">', '</strong>') 00126 ); 00127 00128 $this->wrapIcon = array( 00129 0 => '', 00130 1 => '<img src="' . TYPO3_mainDir . 'gfx/icon_note.gif" width="18" height="16" align="absmiddle" alt="" />', 00131 2 => '<img src="' . TYPO3_mainDir . 'gfx/icon_warning.gif" width="18" height="16" align="absmiddle" alt="" />', 00132 3 => '<img src="' . TYPO3_mainDir . 'gfx/icon_fatalerror.gif" width="18" height="16" align="absmiddle" alt="" />' 00133 ); 00134 00135 $this->starttime = $this->getMilliseconds(); 00136 } 00137 00138 /** 00139 * Pushes an element to the TypoScript tracking array 00140 * 00141 * @param string Label string for the entry, eg. TypoScript property name 00142 * @param string Additional value(?) 00143 * @return void 00144 * @see tslib_cObj::cObjGetSingle(), pull() 00145 */ 00146 public function push($tslabel, $value = '') { 00147 array_push($this->tsStack[$this->tsStackPointer], $tslabel); 00148 array_push($this->currentHashPointer, 'timetracker_' . $this->uniqueCounter++); 00149 00150 $this->tsStackLevel++; 00151 $this->tsStackLevelMax[] = $this->tsStackLevel; 00152 00153 // setTSlog 00154 $k = end($this->currentHashPointer); 00155 $this->tsStackLog[$k] = array( 00156 'level' => $this->tsStackLevel, 00157 'tsStack' => $this->tsStack, 00158 'value' => $value, 00159 'starttime' => microtime(TRUE), 00160 'stackPointer' => $this->tsStackPointer 00161 ); 00162 } 00163 00164 /** 00165 * Pulls an element from the TypoScript tracking array 00166 * 00167 * @param string The content string generated within the push/pull part. 00168 * @return void 00169 * @see tslib_cObj::cObjGetSingle(), push() 00170 */ 00171 public function pull($content = '') { 00172 $k = end($this->currentHashPointer); 00173 $this->tsStackLog[$k]['endtime'] = microtime(TRUE); 00174 $this->tsStackLog[$k]['content'] = $content; 00175 00176 $this->tsStackLevel--; 00177 array_pop($this->tsStack[$this->tsStackPointer]); 00178 array_pop($this->currentHashPointer); 00179 } 00180 00181 /** 00182 * Logs the TypoScript entry 00183 * 00184 * @param string The message string 00185 * @param integer Message type: 0: information, 1: message, 2: warning, 3: error 00186 * @return void 00187 * @see tslib_cObj::CONTENT() 00188 */ 00189 public function setTSlogMessage($content, $num = 0) { 00190 end($this->currentHashPointer); 00191 $k = current($this->currentHashPointer); 00192 00193 if (strlen($content) > 30) { // Enlarge the "details" column by adding a wide clear.gif 00194 $placeholder = '<br /><img src="' . TYPO3_mainDir . 'clear.gif" width="300" height="1" alt="" />'; 00195 } 00196 $this->tsStackLog[$k]['message'][] = $this->wrapIcon[$num] . $this->wrapError[$num][0] . htmlspecialchars($content) . $this->wrapError[$num][1] . $placeholder; 00197 } 00198 00199 /** 00200 * Set TSselectQuery - for messages in TypoScript debugger. 00201 * 00202 * @param array Query array 00203 * @param string Message/Label to attach 00204 * @return void 00205 */ 00206 public function setTSselectQuery(array $data, $msg = '') { 00207 end($this->currentHashPointer); 00208 $k = current($this->currentHashPointer); 00209 00210 if (strlen($msg)) { 00211 $data['msg'] = $msg; 00212 } 00213 00214 $this->tsStackLog[$k]['selectQuery'][] = $data; 00215 } 00216 00217 /** 00218 * Increases the stack pointer 00219 * 00220 * @return void 00221 * @see decStackPointer(), TSpagegen::renderContent(), tslib_cObj::cObjGetSingle() 00222 */ 00223 public function incStackPointer() { 00224 $this->tsStackPointer++; 00225 $this->tsStack[$this->tsStackPointer] = array(); 00226 } 00227 00228 /** 00229 * Decreases the stack pointer 00230 * 00231 * @return void 00232 * @see incStackPointer(), TSpagegen::renderContent(), tslib_cObj::cObjGetSingle() 00233 */ 00234 public function decStackPointer() { 00235 unset($this->tsStack[$this->tsStackPointer]); 00236 $this->tsStackPointer--; 00237 } 00238 00239 /** 00240 * Gets a microtime value as milliseconds value. 00241 * 00242 * @param float $microtime: The microtime value - if not set the current time is used 00243 * @return integer The microtime value as milliseconds value 00244 */ 00245 public function getMilliseconds($microtime = NULL) { 00246 if (!isset($microtime)) { 00247 $microtime = microtime(TRUE); 00248 } 00249 return round($microtime * 1000); 00250 } 00251 00252 /** 00253 * Gets the difference between a given microtime value and the starting time as milliseconds. 00254 * 00255 * @param float $microtime: The microtime value - if not set the current time is used 00256 * @return integer The difference between a given microtime value and starting time as milliseconds 00257 */ 00258 public function getDifferenceToStarttime($microtime = NULL) { 00259 return ($this->getMilliseconds($microtime) - $this->starttime); 00260 } 00261 00262 00263 /******************************************* 00264 * 00265 * Printing the parsing time information (for Admin Panel) 00266 * 00267 *******************************************/ 00268 00269 /** 00270 * Print TypoScript parsing log 00271 * 00272 * @return string HTML table with the information about parsing times. 00273 * @see t3lib_tsfeBeUserAuth::extGetCategory_tsdebug() 00274 */ 00275 public function printTSlog() { 00276 // Calculate times and keys for the tsStackLog 00277 foreach ($this->tsStackLog as $uniqueId => &$data) { 00278 $data['endtime'] = $this->getDifferenceToStarttime($data['endtime']); 00279 $data['starttime'] = $this->getDifferenceToStarttime($data['starttime']); 00280 $data['deltatime'] = $data['endtime'] - $data['starttime']; 00281 if (is_array($data['tsStack'])) { 00282 $data['key'] = implode($data['stackPointer'] ? '.' : '/', end($data['tsStack'])); 00283 } 00284 } 00285 00286 // Create hierarchical array of keys pointing to the stack 00287 $arr = array(); 00288 foreach ($this->tsStackLog as $uniqueId => $data) { 00289 $this->createHierarchyArray($arr, $data['level'], $uniqueId); 00290 } 00291 // Parsing the registeret content and create icon-html for the tree 00292 $this->tsStackLog[$arr['0.'][0]]['content'] = $this->fixContent($arr['0.']['0.'], $this->tsStackLog[$arr['0.'][0]]['content'], '', 0, $arr['0.'][0]); 00293 00294 // Displaying the tree: 00295 $outputArr = array(); 00296 $outputArr[] = $this->fw('TypoScript Key'); 00297 $outputArr[] = $this->fw('Value'); 00298 00299 if ($this->printConf['allTime']) { 00300 $outputArr[] = $this->fw('Time'); 00301 $outputArr[] = $this->fw('Own'); 00302 $outputArr[] = $this->fw('Sub'); 00303 $outputArr[] = $this->fw('Total'); 00304 } else { 00305 $outputArr[] = $this->fw('Own'); 00306 } 00307 00308 $outputArr[] = $this->fw('Details'); 00309 00310 $out = ''; 00311 foreach ($outputArr as $row) { 00312 $out .= ' 00313 <th><strong>' . $row . '</strong></th>'; 00314 } 00315 $out = '<tr>' . $out . '</tr>'; 00316 00317 $flag_tree = $this->printConf['flag_tree']; 00318 $flag_messages = $this->printConf['flag_messages']; 00319 $flag_content = $this->printConf['flag_content']; 00320 $flag_queries = $this->printConf['flag_queries']; 00321 $keyLgd = $this->printConf['keyLgd']; 00322 $factor = $this->printConf['factor']; 00323 $col = $this->printConf['col']; 00324 $highlight_col = $this->printConf['highlight_col']; 00325 00326 $c = 0; 00327 foreach ($this->tsStackLog as $uniqueId => $data) { 00328 if ($this->highlightLongerThan && intval($data['owntime']) > intval($this->highlightLongerThan)) { 00329 $logRowClass = 'typo3-adminPanel-logRow-highlight'; 00330 } else { 00331 $logRowClass = ($c % 2) ? 'typo3-adminPanel-logRow-odd' : 'typo3-adminPanel-logRow-even'; 00332 } 00333 00334 $item = ''; 00335 if (!$c) { // If first... 00336 $data['icons'] = ''; 00337 $data['key'] = 'Script Start'; 00338 $data['value'] = ''; 00339 } 00340 00341 00342 // key label: 00343 $keyLabel = ''; 00344 if (!$flag_tree && $data['stackPointer']) { 00345 $temp = array(); 00346 foreach ($data['tsStack'] as $k => $v) { 00347 $temp[] = t3lib_div::fixed_lgd_cs(implode($v, $k ? '.' : '/'), -$keyLgd); 00348 } 00349 array_pop($temp); 00350 $temp = array_reverse($temp); 00351 array_pop($temp); 00352 if (count($temp)) { 00353 $keyLabel = '<br /><span style="color:#999999;">' . implode($temp, '<br />') . '</span>'; 00354 } 00355 } 00356 if ($flag_tree) { 00357 $tmp = t3lib_div::trimExplode('.', $data['key'], 1); 00358 $theLabel = end($tmp); 00359 } else { 00360 $theLabel = $data['key']; 00361 } 00362 $theLabel = t3lib_div::fixed_lgd_cs($theLabel, -$keyLgd); 00363 $theLabel = $data['stackPointer'] ? '<span class="stackPointer">' . $theLabel . '</span>' : $theLabel; 00364 $keyLabel = $theLabel . $keyLabel; 00365 $item .= '<td class="' . $logRowClass . '" style="padding-left:2px;">' . ($flag_tree ? $data['icons'] : '') . $this->fw($keyLabel) . '</td>'; 00366 00367 // key value: 00368 $keyValue = $data['value']; 00369 $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime" style="' . $bgColor . '">' . $this->fw(htmlspecialchars($keyValue)) . '</td>'; 00370 00371 if ($this->printConf['allTime']) { 00372 $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime"> ' . $this->fw($data['starttime']) . '</td>'; 00373 $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime"> ' . $this->fw($data['owntime']) . '</td>'; 00374 $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime"> ' . $this->fw($data['subtime'] ? '+' . $data['subtime'] : '') . '</td>'; 00375 $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime"> ' . $this->fw($data['subtime'] ? '=' . $data['deltatime'] : '') . '</td>'; 00376 } else { 00377 $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime"> ' . $this->fw($data['owntime']) . '</td>'; 00378 } 00379 00380 00381 // messages: 00382 $msgArr = array(); 00383 $msg = ''; 00384 if ($flag_messages && is_array($data['message'])) { 00385 foreach ($data['message'] as $v) { 00386 $msgArr[] = nl2br($v); 00387 } 00388 } 00389 if ($flag_queries && is_array($data['selectQuery'])) { 00390 $msgArr[] = t3lib_utility_Debug::viewArray($data['selectQuery']); 00391 } 00392 if ($flag_content && strcmp($data['content'], '')) { 00393 $maxlen = 120; 00394 if (preg_match_all('/(\S{' . $maxlen . ',})/', $data['content'], $reg)) { // Break lines which are too longer than $maxlen chars (can happen if content contains long paths...) 00395 foreach ($reg[1] as $key => $match) { 00396 $match = preg_replace('/(.{' . $maxlen . '})/', '$1 ', $match); 00397 $data['content'] = str_replace($reg[0][$key], $match, $data['content']); 00398 } 00399 } 00400 $msgArr[] = '<span style="color:#000066;">' . nl2br($data['content']) . '</span>'; 00401 } 00402 if (count($msgArr)) { 00403 $msg = implode($msgArr, '<hr />'); 00404 } 00405 $item .= '<td valign="top" class="' . $logRowClass . '" style="text-align:left;">' . $this->fw($msg) . '</td>'; 00406 $out .= '<tr>' . $item . '</tr>'; 00407 $c++; 00408 } 00409 $out = '<table id="typo3-adminPanel-tsLog">' . $out . '</table>'; 00410 return $out; 00411 } 00412 00413 /** 00414 * Recursively generates the content to display 00415 * 00416 * @param array Array which is modified with content. Reference 00417 * @param string Current content string for the level 00418 * @param string Prefixed icons for new PM icons 00419 * @param boolean Set this for the first call from outside. 00420 * @param string Seems to be the previous tsStackLog key 00421 * @return string Returns the $content string generated/modified. Also the $arr array is modified! 00422 */ 00423 protected function fixContent(&$arr, $content, $depthData = '', $first = 0, $vKey = '') { 00424 $ac = 0; 00425 $c = 0; 00426 // First, find number of entries 00427 foreach ($arr as $k => $v) { 00428 if (t3lib_div::testInt($k)) { 00429 $ac++; 00430 } 00431 } 00432 // Traverse through entries 00433 $subtime = 0; 00434 foreach ($arr as $k => $v) { 00435 if (t3lib_div::testInt($k)) { 00436 $c++; 00437 00438 $deeper = is_array($arr[$k . '.']) ? 1 : 0; 00439 $PM = 'join'; 00440 $LN = ($ac == $c) ? 'blank' : 'line'; 00441 $BTM = ($ac == $c) ? 'bottom' : ''; 00442 $PM = is_array($arr[$k . '.']) ? ($deeper ? 'minus' : 'plus') : 'join'; 00443 $this->tsStackLog[$v]['icons'] = $depthData . ($first ? '' : '<img src="' . TYPO3_mainDir . 'gfx/ol/' . $PM . $BTM . '.gif" width="18" height="16" align="top" border="0" alt="" />'); 00444 00445 if (strlen($this->tsStackLog[$v]['content'])) { 00446 $content = str_replace($this->tsStackLog[$v]['content'], $v, $content); 00447 } 00448 if (is_array($arr[$k . '.'])) { 00449 $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); 00450 } else { 00451 $this->tsStackLog[$v]['content'] = $this->fixCLen($this->tsStackLog[$v]['content'], $this->tsStackLog[$v]['value']); 00452 $this->tsStackLog[$v]['subtime'] = ''; 00453 $this->tsStackLog[$v]['owntime'] = $this->tsStackLog[$v]['deltatime']; 00454 } 00455 $subtime += $this->tsStackLog[$v]['deltatime']; 00456 } 00457 } 00458 // Set content with special chars 00459 if (isset($this->tsStackLog[$vKey])) { 00460 $this->tsStackLog[$vKey]['subtime'] = $subtime; 00461 $this->tsStackLog[$vKey]['owntime'] = $this->tsStackLog[$vKey]['deltatime'] - $subtime; 00462 } 00463 $content = $this->fixCLen($content, $this->tsStackLog[$vKey]['value']); 00464 00465 // Traverse array again, this time substitute the unique hash with the red key 00466 foreach ($arr as $k => $v) { 00467 if (t3lib_div::testInt($k)) { 00468 if (strlen($this->tsStackLog[$v]['content'])) { 00469 $content = str_replace($v, '<strong style="color:red;">[' . $this->tsStackLog[$v]['key'] . ']</strong>', $content); 00470 } 00471 } 00472 } 00473 // return the content 00474 return $content; 00475 } 00476 00477 /** 00478 * Wraps the input content string in green colored span-tags IF the length o fthe input string exceeds $this->printConf['contentLength'] (or $this->printConf['contentLength_FILE'] if $v == "FILE" 00479 * 00480 * @param string The content string 00481 * @param string Command: If "FILE" then $this->printConf['contentLength_FILE'] is used for content length comparison, otherwise $this->printConf['contentLength'] 00482 * @return string 00483 */ 00484 protected function fixCLen($c, $v) { 00485 $len = $v == 'FILE' ? $this->printConf['contentLength_FILE'] : $this->printConf['contentLength']; 00486 if (strlen($c) > $len) { 00487 $c = '<span style="color:green;">' . htmlspecialchars(t3lib_div::fixed_lgd_cs($c, $len)) . '</span>'; 00488 } else { 00489 $c = htmlspecialchars($c); 00490 } 00491 return $c; 00492 } 00493 00494 /** 00495 * Wraps input string in a <span> tag with black verdana font 00496 * 00497 * @param string The string to be wrapped 00498 * @return string 00499 */ 00500 protected function fw($str) { 00501 return '<span style="font-family:Verdana,Arial,Helvetica,sans-serif; font-size:10px; color:black; vertical-align:top;">' . $str . ' </span>'; 00502 } 00503 00504 /** 00505 * Helper function for internal data manipulation 00506 * 00507 * @param array Array (passed by reference) and modified 00508 * @param integer Pointer value 00509 * @param string Unique ID string 00510 * @return void 00511 * @access private 00512 * @see printTSlog() 00513 */ 00514 protected function createHierarchyArray(&$arr, $pointer, $uniqueId) { 00515 if (!is_array($arr)) { 00516 $arr = array(); 00517 } 00518 if ($pointer > 0) { 00519 end($arr); 00520 $k = key($arr); 00521 $this->createHierarchyArray($arr[intval($k) . '.'], $pointer - 1, $uniqueId); 00522 } else { 00523 $arr[] = $uniqueId; 00524 } 00525 } 00526 00527 /** 00528 * This prints out a TYPO3 error message. 00529 * 00530 * @param string Header string 00531 * @param string Message string 00532 * @param boolean If set, then this will produce a alert() line for inclusion in JavaScript. 00533 * @param string URL for the <base> tag (if you want it) 00534 * @return string 00535 * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7 - use RuntimeException from now on 00536 */ 00537 public function debug_typo3PrintError($header, $text, $js, $baseUrl = '') { 00538 if ($js) { 00539 $errorMessage = 'alert(\'' . t3lib_div::slashJS($header . '\n' . $text) . '\');'; 00540 } else { 00541 t3lib_div::logDeprecatedFunction(); 00542 $messageObj = t3lib_div::makeInstance('t3lib_message_ErrorPageMessage', $text, $header); 00543 $errorMessage = $messageObj->render(); 00544 } 00545 00546 // Hook to modify error message 00547 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_timetrack.php']['debug_typo3PrintError'])) { 00548 $params = array( 00549 'header' => $header, 00550 'text' => $text, 00551 'js' => $js, 00552 'baseUrl' => $baseUrl, 00553 'errorMessage' => &$errorMessage 00554 ); 00555 $null = NULL; 00556 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_timetrack.php']['debug_typo3PrintError'] as $hookMethod) { 00557 t3lib_div::callUserFunction($hookMethod, $params, $null); 00558 } 00559 } 00560 00561 echo $errorMessage; 00562 } 00563 } 00564 00565 // XCLASSing is not possible for this class 00566 00567 ?>
1.8.0