|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZDebug class 00004 // 00005 // Created on: <12-Feb-2002 11:00:54 bf> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.0.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 /*! \defgroup eZUtils Utility classes */ 00032 00033 /*! 00034 \class eZDebug ezdebug.php 00035 \ingroup eZUtils 00036 \brief Advanced debug/log system 00037 00038 The eZ debug library is used to handle debug information. It 00039 can display information on screen and/or write it to log files. 00040 00041 You can enable on-screen debug information for specific IP addresses. 00042 00043 Timing points can be placed in the code to time the different sections of code. 00044 00045 Each debug message can be turned on/off by using the showTypes() function. 00046 00047 PHP error messages can also be shown using setHandleType(). 00048 00049 \code 00050 require_once( "lib/ezutils/classes/ezdebug.php" ); 00051 00052 // write a temporary debug message 00053 eZDebug::writeDebug( "Test" ); 00054 00055 // write a notice 00056 eZDebug::writeNotice( "Image found" ); 00057 00058 // write a warning 00059 eZDebug::writeWarning( "Image not found, using default" ); 00060 00061 // write an error 00062 eZDebug::writeError( "Object not found, bailing.." ); 00063 00064 // add a timing points 00065 eZDebug::addTimingPoint( "Module Found" ); 00066 00067 //.... code 00068 00069 eZDebug::addTimingPoint( "Module loading" ); 00070 00071 // print the results on screen. 00072 eZDebug::printReport(); 00073 00074 \endcode 00075 */ 00076 00077 //include_once( "lib/ezutils/classes/ezsys.php" ); 00078 00079 class eZDebug 00080 { 00081 const LEVEL_NOTICE = 1; 00082 const LEVEL_WARNING = 2; 00083 const LEVEL_ERROR = 3; 00084 const LEVEL_TIMING_POINT = 4; 00085 const LEVEL_DEBUG = 5; 00086 const LEVEL_STRICT = 6; 00087 00088 const SHOW_NOTICE = 1; // 1 << (EZ_LEVEL_NOTICE - 1) 00089 const SHOW_WARNING = 2; // 1 << (EZ_LEVEL_WARNING - 1) 00090 const SHOW_ERROR = 4; // 1 << (EZ_LEVEL_ERROR - 1) 00091 const SHOW_TIMING_POINT = 8; // 1 << (EZ_LEVEL_TIMING_POINT - 1) 00092 const SHOW_DEBUG = 16; // 1 << (EZ_LEVEL_DEBUG - 1) 00093 const SHOW_STRICT = 32; // 1 << (EZ_LEVEL_STRICT - 1) 00094 const SHOW_ALL = 63; // EZ_SHOW_NOTICE | EZ_SHOW_WARNING | EZ_SHOW_ERROR | EZ_SHOW_TIMING_POINT | EZ_SHOW_DEBUG | EZ_SHOW_STRICT 00095 00096 const HANDLE_NONE = 0; 00097 const HANDLE_FROM_PHP = 1; 00098 const HANDLE_TO_PHP = 2; 00099 00100 const OUTPUT_MESSAGE_SCREEN = 1; 00101 const OUTPUT_MESSAGE_STORE = 2; 00102 00103 const MAX_LOGFILE_SIZE = 204800; // 200*1024 00104 const MAX_LOGROTATE_FILES = 3; 00105 00106 const XDEBUG_SIGNATURE = '--XDEBUG--'; 00107 00108 /*! 00109 Creates a new debug object. 00110 */ 00111 function __construct( ) 00112 { 00113 $this->TmpTimePoints = array( self::LEVEL_NOTICE => array(), 00114 self::LEVEL_WARNING => array(), 00115 self::LEVEL_ERROR => array(), 00116 self::LEVEL_DEBUG => array(), 00117 self::LEVEL_STRICT => array() ); 00118 00119 $this->OutputFormat = array( self::LEVEL_NOTICE => array( "color" => "green", 00120 'style' => 'notice', 00121 'xhtml-identifier' => 'ezdebug-first-notice', 00122 "name" => "Notice" ), 00123 self::LEVEL_WARNING => array( "color" => "orange", 00124 'style' => 'warning', 00125 'xhtml-identifier' => 'ezdebug-first-warning', 00126 "name" => "Warning" ), 00127 self::LEVEL_ERROR => array( "color" => "red", 00128 'style' => 'error', 00129 'xhtml-identifier' => 'ezdebug-first-error', 00130 "name" => "Error" ), 00131 self::LEVEL_DEBUG => array( "color" => "brown", 00132 'style' => 'debug', 00133 'xhtml-identifier' => 'ezdebug-first-debug', 00134 "name" => "Debug" ), 00135 self::LEVEL_TIMING_POINT => array( "color" => "blue", 00136 'style' => 'timing', 00137 'xhtml-identifier' => 'ezdebug-first-timing-point', 00138 "name" => "Timing" ), 00139 self::LEVEL_STRICT => array( "color" => "purple", 00140 'style' => 'strict', 00141 'xhtml-identifier' => 'ezdebug-first-strict', 00142 'name' => 'Strict' ) ); 00143 $this->LogFiles = array( self::LEVEL_NOTICE => array( "var/log/", 00144 "notice.log" ), 00145 self::LEVEL_WARNING => array( "var/log/", 00146 "warning.log" ), 00147 self::LEVEL_ERROR => array( "var/log/", 00148 "error.log" ), 00149 self::LEVEL_DEBUG => array( "var/log/", 00150 "debug.log" ), 00151 self::LEVEL_STRICT => array( 'var/log/', 00152 'strict.log' ) ); 00153 $this->MessageTypes = array( self::LEVEL_NOTICE, 00154 self::LEVEL_WARNING, 00155 self::LEVEL_ERROR, 00156 self::LEVEL_TIMING_POINT, 00157 self::LEVEL_DEBUG, 00158 self::LEVEL_STRICT ); 00159 $this->MessageNames = array( self::LEVEL_NOTICE => 'Notice', 00160 self::LEVEL_WARNING => 'Warning', 00161 self::LEVEL_ERROR => 'Error', 00162 self::LEVEL_TIMING_POINT => 'TimingPoint', 00163 self::LEVEL_DEBUG => 'Debug', 00164 self::LEVEL_STRICT => 'Strict' ); 00165 $this->LogFileEnabled = array( self::LEVEL_NOTICE => true, 00166 self::LEVEL_WARNING => true, 00167 self::LEVEL_ERROR => true, 00168 self::LEVEL_TIMING_POINT => true, 00169 self::LEVEL_DEBUG => true, 00170 self::LEVEL_STRICT => true ); 00171 $this->AlwaysLog = array( self::LEVEL_NOTICE => false, 00172 self::LEVEL_WARNING => false, 00173 self::LEVEL_ERROR => true, // Error is on by default, due to its importance 00174 self::LEVEL_TIMING_POINT => false, 00175 self::LEVEL_DEBUG => false, 00176 self::LEVEL_STRICT => false ); 00177 $this->GlobalLogFileEnabled = true; 00178 if ( isset( $GLOBALS['eZDebugLogFileEnabled'] ) ) 00179 { 00180 $this->GlobalLogFileEnabled = $GLOBALS['eZDebugLogFileEnabled']; 00181 } 00182 $this->ShowTypes = self::SHOW_ALL; 00183 $this->HandleType = self::HANDLE_NONE; 00184 $this->OldHandler = false; 00185 $this->UseCSS = false; 00186 $this->MessageOutput = self::OUTPUT_MESSAGE_STORE; 00187 $this->ScriptStart = microtime( true ); 00188 $this->TimeAccumulatorList = array(); 00189 $this->TimeAccumulatorGroupList = array(); 00190 $this->OverrideList = array(); 00191 $this->topReportsList = array(); 00192 $this->bottomReportsList = array(); 00193 } 00194 00195 function reset() 00196 { 00197 $this->DebugStrings = array(); 00198 $this->TmpTimePoints = array( self::LEVEL_NOTICE => array(), 00199 self::LEVEL_WARNING => array(), 00200 self::LEVEL_ERROR => array(), 00201 self::LEVEL_DEBUG => array(), 00202 self::LEVEL_STRICT => array() ); 00203 $this->TimeAccumulatorList = array(); 00204 $this->TimeAccumulatorGroupList = array(); 00205 $this->topReportsList = array(); 00206 $this->bottomReportsList = array(); 00207 } 00208 00209 /*! 00210 \return the name of the message type. 00211 */ 00212 function messageName( $messageType ) 00213 { 00214 return $this->MessageNames[$messageType]; 00215 } 00216 00217 /*! 00218 Will return the current eZDebug object. If no object exists one will 00219 be created. 00220 */ 00221 static function instance( ) 00222 { 00223 if ( empty( $GLOBALS["eZDebugGlobalInstance"] ) ) 00224 { 00225 $GLOBALS["eZDebugGlobalInstance"] = new eZDebug(); 00226 } 00227 return $GLOBALS["eZDebugGlobalInstance"]; 00228 } 00229 00230 /*! 00231 \static 00232 Returns true if the message type $type can be shown. 00233 */ 00234 static function showMessage( $type ) 00235 { 00236 $debug = eZDebug::instance(); 00237 return $debug->ShowTypes & $type; 00238 } 00239 00240 /*! 00241 \return \c true if the debug level \a $level should always log to file. 00242 */ 00243 static function alwaysLogMessage( $level ) 00244 { 00245 $instance = eZDebug::instance(); 00246 // If there is a global setting for this get the value 00247 // and unset it globally 00248 if ( isset( $GLOBALS['eZDebugAlwaysLog'] ) ) 00249 { 00250 $instance->AlwaysLog = $GLOBALS['eZDebugAlwaysLog'] + $instance->AlwaysLog; 00251 unset( $GLOBALS['eZDebugAlwaysLog'] ); 00252 } 00253 00254 if ( !isset( $instance->AlwaysLog[$level] ) ) 00255 { 00256 return false; 00257 } 00258 return $instance->AlwaysLog[$level]; 00259 } 00260 00261 /*! 00262 Determines how PHP errors are handled. If $type is self::HANDLE_TO_PHP all error messages 00263 is sent to PHP using trigger_error(), if $type is self::HANDLE_FROM_PHP all error messages 00264 from PHP is fetched using a custom error handler and output as a usual eZDebug message. 00265 If $type is self::HANDLE_NONE there is no error exchange between PHP and eZDebug. 00266 */ 00267 static function setHandleType( $type ) 00268 { 00269 $instance = eZDebug::instance(); 00270 00271 if ( $type != self::HANDLE_TO_PHP and 00272 $type != self::HANDLE_FROM_PHP ) 00273 $type = self::HANDLE_NONE; 00274 if ( extension_loaded( 'xdebug' ) and 00275 $type == self::HANDLE_FROM_PHP ) 00276 $type = self::HANDLE_NONE; 00277 if ( $type == $instance->HandleType ) 00278 return $instance->HandleType; 00279 00280 if ( $instance->HandleType == self::HANDLE_FROM_PHP ) 00281 restore_error_handler(); 00282 switch ( $type ) 00283 { 00284 case self::HANDLE_FROM_PHP: 00285 { 00286 set_error_handler( "eZDebugErrorHandler" ); 00287 } break; 00288 00289 case self::HANDLE_TO_PHP: 00290 { 00291 restore_error_handler(); 00292 } break; 00293 00294 case self::HANDLE_NONE: 00295 { 00296 } 00297 } 00298 $oldHandleType = $instance->HandleType; 00299 $instance->HandleType = $type; 00300 return $oldHandleType; 00301 } 00302 00303 /*! 00304 \static 00305 Sets types to be shown to $types and returns the old show types. 00306 If $types is not supplied the current value is returned and no change is done. 00307 $types is one or more of self::SHOW_NOTICE, self::SHOW_WARNING, self::SHOW_ERROR, self::SHOW_TIMING_POINT 00308 or'ed together. 00309 */ 00310 static function showTypes( $types = false ) 00311 { 00312 $instance = eZDebug::instance(); 00313 00314 if ( $types === false ) 00315 { 00316 return $instance->ShowTypes; 00317 } 00318 $old_types = $instance->ShowTypes; 00319 $instance->ShowTypes = $types; 00320 return $old_types; 00321 } 00322 00323 /*! 00324 Handles PHP errors, creates notice, warning and error messages for 00325 the various PHP error types. 00326 */ 00327 function errorHandler( $errno, $errstr, $errfile, $errline ) 00328 { 00329 if ( error_reporting() == 0 ) // @ error-control operator is used 00330 return; 00331 if ( !eZDebug::isDebugEnabled() ) 00332 return; 00333 $str = "$errstr in $errfile on line $errline"; 00334 if ( empty( $GLOBALS["eZDebugPHPErrorNames"] ) ) 00335 { 00336 $GLOBALS["eZDebugPHPErrorNames"] = 00337 array( E_ERROR => "E_ERROR", 00338 E_PARSE => "E_PARSE", 00339 E_CORE_ERROR => "E_CORE_ERROR", 00340 E_COMPILE_ERROR => "E_COMPILE_ERROR", 00341 E_USER_ERROR => "E_USER_ERROR", 00342 E_WARNING => "E_WARNING", 00343 E_CORE_WARNING => "E_CORE_WARNING", 00344 E_COMPILE_WARNING => "E_COMPILE_WARNING", 00345 E_USER_WARNING => "E_USER_WARNING", 00346 E_NOTICE => "E_NOTICE", 00347 E_USER_NOTICE => "E_USER_NOTICE", 00348 E_STRICT => "E_STRICT" ); 00349 } 00350 $errname = "unknown"; 00351 if ( isset( $GLOBALS["eZDebugPHPErrorNames"][$errno] ) ) 00352 { 00353 $errname = $GLOBALS["eZDebugPHPErrorNames"][$errno]; 00354 } 00355 switch ( $errno ) 00356 { 00357 case E_ERROR: 00358 case E_PARSE: 00359 case E_CORE_ERROR: 00360 case E_COMPILE_ERROR: 00361 case E_USER_ERROR: 00362 { 00363 $this->writeError( $str, "PHP" ); 00364 } break; 00365 00366 case E_WARNING: 00367 case E_CORE_WARNING: 00368 case E_COMPILE_WARNING: 00369 case E_USER_WARNING: 00370 case E_NOTICE: 00371 { 00372 $this->writeWarning( $str, "PHP" ); 00373 } break; 00374 00375 case E_USER_NOTICE: 00376 { 00377 $this->writeNotice( $str, "PHP" ); 00378 } break; 00379 00380 case E_STRICT: 00381 { 00382 return $this->writeStrict( $str, "PHP" ); 00383 } break; 00384 } 00385 } 00386 00387 /*! 00388 \static 00389 Writes a strict debug message. 00390 00391 The global variable \c 'eZDebugStrict' will be set to \c true if the notice is added. 00392 \param $label This label will be associated with the strict message, e.g. to say where the message came from. 00393 \param $backgroundClass A string defining the class to use in the HTML debug output. 00394 */ 00395 static function writeStrict( $string, $label = "", $backgroundClass = "" ) 00396 { 00397 $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_STRICT ); 00398 $enabled = eZDebug::isDebugEnabled(); 00399 if ( !$alwaysLog and !$enabled ) 00400 return; 00401 00402 $show = eZDebug::showMessage( self::SHOW_STRICT ); 00403 if ( !$alwaysLog and !$show ) 00404 return; 00405 00406 if ( is_object( $string ) || is_array( $string ) ) 00407 $string = eZDebug::dumpVariable( $string ); 00408 00409 $GLOBALS['eZDebugStrict'] = true; 00410 if ( !isset( $GLOBALS['eZDebugStrictCount'] ) ) 00411 $GLOBALS['eZDebugStrictCount'] = 0; 00412 ++$GLOBALS['eZDebugStrictCount']; 00413 00414 $debug = eZDebug::instance(); 00415 if ( $debug->HandleType == self::HANDLE_TO_PHP ) 00416 { 00417 // If we get here only because of $alwaysLog we should not trigger a PHP error 00418 if ( $enabled and $show ) 00419 { 00420 // we can't trigger E_STRICT but we can let the default error handler handle it 00421 // see http://www.php.net/manual/en/function.set-error-handler.php#69218 00422 return false; 00423 } 00424 } 00425 else 00426 { 00427 $debug->write( $string, self::LEVEL_STRICT, $label, $backgroundClass, $alwaysLog ); 00428 return true; 00429 } 00430 } 00431 00432 /*! 00433 \static 00434 Writes a debug notice. 00435 00436 The global variable \c 'eZDebugNotice' will be set to \c true if the notice is added. 00437 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 00438 \param $backgroundClass A string defining the class to use in the HTML debug output. 00439 */ 00440 static function writeNotice( $string, $label = "", $backgroundClass = "" ) 00441 { 00442 $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_NOTICE ); 00443 $enabled = eZDebug::isDebugEnabled(); 00444 if ( !$alwaysLog and !$enabled ) 00445 return; 00446 00447 $show = eZDebug::showMessage( self::SHOW_NOTICE ); 00448 if ( !$alwaysLog and !$show ) 00449 return; 00450 00451 if ( is_object( $string ) || is_array( $string ) ) 00452 $string = eZDebug::dumpVariable( $string ); 00453 00454 $GLOBALS['eZDebugNotice'] = true; 00455 if ( !isset( $GLOBALS['eZDebugNoticeCount'] ) ) 00456 $GLOBALS['eZDebugNoticeCount'] = 0; 00457 ++$GLOBALS['eZDebugNoticeCount']; 00458 00459 $debug = eZDebug::instance(); 00460 if ( $debug->HandleType == self::HANDLE_TO_PHP ) 00461 { 00462 // If we get here only because of $alwaysLog we should not trigger a PHP error 00463 if ( $enabled and $show ) 00464 { 00465 if ( $label ) 00466 $string = "$label: $string"; 00467 trigger_error( $string, E_USER_NOTICE ); 00468 } 00469 } 00470 else 00471 { 00472 $debug->write( $string, self::LEVEL_NOTICE, $label, $backgroundClass, $alwaysLog ); 00473 } 00474 } 00475 00476 /*! 00477 \static 00478 Writes a debug warning. 00479 00480 The global variable \c 'eZDebugWarning' will be set to \c true if the notice is added. 00481 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 00482 */ 00483 static function writeWarning( $string, $label = "", $backgroundClass = "" ) 00484 { 00485 $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_WARNING ); 00486 $enabled = eZDebug::isDebugEnabled(); 00487 if ( !$alwaysLog and !$enabled ) 00488 return; 00489 00490 $show = eZDebug::showMessage( self::SHOW_WARNING ); 00491 if ( !$alwaysLog and !$show ) 00492 return; 00493 00494 if ( is_object( $string ) || is_array( $string ) ) 00495 $string = eZDebug::dumpVariable( $string ); 00496 00497 $GLOBALS['eZDebugWarning'] = true; 00498 if ( !isset( $GLOBALS['eZDebugWarningCount'] ) ) 00499 $GLOBALS['eZDebugWarningCount'] = 0; 00500 ++$GLOBALS['eZDebugWarningCount']; 00501 00502 $debug = eZDebug::instance(); 00503 if ( $debug->HandleType == self::HANDLE_TO_PHP ) 00504 { 00505 // If we get here only because of $alwaysLog we should not trigger a PHP error 00506 if ( $enabled and $show ) 00507 { 00508 if ( $label ) 00509 $string = "$label: $string"; 00510 trigger_error( $string, E_USER_WARNING ); 00511 } 00512 } 00513 else 00514 { 00515 $debug->write( $string, self::LEVEL_WARNING, $label, $backgroundClass, $alwaysLog ); 00516 } 00517 } 00518 00519 /*! 00520 \static 00521 Writes a debug error. 00522 00523 The global variable \c 'eZDebugError' will be set to \c true if the notice is added. 00524 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 00525 */ 00526 static function writeError( $string, $label = "", $backgroundClass = "" ) 00527 { 00528 $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_ERROR ); 00529 $enabled = eZDebug::isDebugEnabled(); 00530 if ( !$alwaysLog and !$enabled ) 00531 return; 00532 00533 $show = eZDebug::showMessage( self::SHOW_ERROR ); 00534 if ( !$alwaysLog and !$show ) 00535 return; 00536 00537 if ( is_object( $string ) || is_array( $string ) ) 00538 $string = eZDebug::dumpVariable( $string ); 00539 00540 $GLOBALS['eZDebugError'] = true; 00541 if ( !isset( $GLOBALS['eZDebugErrorCount'] ) ) 00542 $GLOBALS['eZDebugErrorCount'] = 0; 00543 ++$GLOBALS['eZDebugErrorCount']; 00544 00545 $debug = eZDebug::instance(); 00546 if ( $debug->HandleType == self::HANDLE_TO_PHP ) 00547 { 00548 // If we get here only because of $alwaysLog we should not trigger a PHP error 00549 if ( $enabled and $show ) 00550 { 00551 if ( $label ) 00552 $string = "$label: $string"; 00553 trigger_error( $string, E_USER_ERROR ); 00554 } 00555 } 00556 else 00557 { 00558 $debug->write( $string, self::LEVEL_ERROR, $label, $backgroundClass, $alwaysLog ); 00559 } 00560 } 00561 00562 /*! 00563 \static 00564 Writes a debug message. 00565 00566 The global variable \c 'eZDebugDebug' will be set to \c true if the notice is added. 00567 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 00568 */ 00569 static function writeDebug( $string, $label = "", $backgroundClass = "" ) 00570 { 00571 $alwaysLog = eZDebug::alwaysLogMessage( self::LEVEL_DEBUG ); 00572 $enabled = eZDebug::isDebugEnabled(); 00573 if ( !$alwaysLog and !$enabled ) 00574 return; 00575 00576 $show = eZDebug::showMessage( self::SHOW_DEBUG ); 00577 if ( !$alwaysLog and !$show ) 00578 return; 00579 00580 if ( is_object( $string ) || is_array( $string ) ) 00581 $string = eZDebug::dumpVariable( $string ); 00582 00583 $GLOBALS['eZDebugDebug'] = true; 00584 if ( !isset( $GLOBALS['eZDebugDebugCount'] ) ) 00585 $GLOBALS['eZDebugDebugCount'] = 0; 00586 ++$GLOBALS['eZDebugDebugCount']; 00587 00588 $debug = eZDebug::instance(); 00589 if ( $debug->HandleType == self::HANDLE_TO_PHP ) 00590 { 00591 // If we get here only because of $alwaysLog we should not trigger a PHP error 00592 if ( $enabled and $show ) 00593 { 00594 if ( $label ) 00595 $string = "$label: $string"; 00596 trigger_error( $string, E_USER_NOTICE ); 00597 } 00598 } 00599 else 00600 { 00601 $debug->write( $string, self::LEVEL_DEBUG, $label, $backgroundClass, $alwaysLog ); 00602 } 00603 } 00604 00605 /*! 00606 \static 00607 \private 00608 Dumps the variables contents using the var_dump function 00609 */ 00610 static function dumpVariable( $var ) 00611 { 00612 // If we have var_export (PHP >= 4.2.0) we use the instead 00613 // provides better output, doesn't require output buffering 00614 // and doesn't get mangled by Xdebug 00615 00616 // dl: we should always use 'var_dump' since 'var_export' is 00617 // unable to handle recursion properly. 00618 //if ( function_exists( 'var_export' ) ) 00619 // return var_export( $var, true ); 00620 00621 ob_start(); 00622 var_dump( $var ); 00623 $variableContents = ''; 00624 if ( extension_loaded( 'xdebug' ) ) 00625 $variableContents = self::XDEBUG_SIGNATURE; 00626 $variableContents .= ob_get_contents(); 00627 ob_end_clean(); 00628 return $variableContents; 00629 } 00630 00631 /*! 00632 Enables/disables the use of external CSS. If false a <style> tag is output 00633 before the debug list. Default is to use internal css. 00634 */ 00635 static function setUseExternalCSS( $use ) 00636 { 00637 eZDebug::instance()->UseCSS = $use; 00638 } 00639 00640 /*! 00641 Determines the way messages are output, the \a $output parameter 00642 is self::OUTPUT_MESSAGE_SCREEN and self::OUTPUT_MESSAGE_STORE ored together. 00643 */ 00644 function setMessageOutput( $output ) 00645 { 00646 $this->MessageOutput = $output; 00647 } 00648 00649 /*! 00650 */ 00651 function setStoreLog( $store ) 00652 { 00653 $this->StoreLog = $store; 00654 } 00655 00656 /*! 00657 Adds a new timing point for the benchmark report. 00658 */ 00659 static function addTimingPoint( $description = "" ) 00660 { 00661 if ( !eZDebug::isDebugEnabled() ) 00662 return; 00663 if ( !eZDebug::showMessage( self::SHOW_TIMING_POINT ) ) 00664 return; 00665 $debug = eZDebug::instance(); 00666 00667 $time = microtime( true ); 00668 $usedMemory = 0; 00669 if ( function_exists( "memory_get_usage" ) ) 00670 $usedMemory = memory_get_usage(); 00671 $tp = array( "Time" => $time, 00672 "Description" => $description, 00673 "MemoryUsage" => $usedMemory ); 00674 $debug->TimePoints[] = $tp; 00675 $desc = "Timing Point: $description"; 00676 foreach ( array( self::LEVEL_NOTICE, self::LEVEL_WARNING, self::LEVEL_ERROR, self::LEVEL_DEBUG, self::LEVEL_STRICT ) as $lvl ) 00677 { 00678 if ( isset( $debug->TmpTimePoints[$lvl] ) ) 00679 $debug->TmpTimePoints[$lvl] = array(); 00680 if ( $debug->TmpTimePoints[$lvl] === false and 00681 $debug->isLogFileEnabled( $lvl ) ) 00682 { 00683 $files = $debug->logFiles(); 00684 $file = $files[$lvl]; 00685 $debug->writeFile( $file, $desc, $lvl ); 00686 } 00687 else 00688 array_push( $debug->TmpTimePoints[$lvl], $tp ); 00689 } 00690 $debug->write( $description, self::LEVEL_TIMING_POINT ); 00691 } 00692 00693 /*! 00694 \private 00695 Writes a debug log message. 00696 */ 00697 function write( $string, $verbosityLevel = self::LEVEL_NOTICE, $label = "", $backgroundClass = "", $alwaysLog = false ) 00698 { 00699 $enabled = eZDebug::isDebugEnabled(); 00700 if ( !$alwaysLog and !$enabled ) 00701 return; 00702 switch ( $verbosityLevel ) 00703 { 00704 case self::LEVEL_NOTICE: 00705 case self::LEVEL_WARNING: 00706 case self::LEVEL_ERROR: 00707 case self::LEVEL_DEBUG: 00708 case self::LEVEL_TIMING_POINT: 00709 case self::LEVEL_STRICT: 00710 break; 00711 00712 default: 00713 $verbosityLevel = self::LEVEL_ERROR; 00714 break; 00715 } 00716 if ( $this->MessageOutput & self::OUTPUT_MESSAGE_SCREEN and $enabled ) 00717 { 00718 print( "$verbosityLevel: $string ($label)\n" ); 00719 } 00720 $files = $this->logFiles(); 00721 $fileName = false; 00722 if ( isset( $files[$verbosityLevel] ) ) 00723 $fileName = $files[$verbosityLevel]; 00724 if ( $this->MessageOutput & self::OUTPUT_MESSAGE_STORE or $alwaysLog ) 00725 { 00726 if ( ! eZDebug::isLogOnlyEnabled() and $enabled ) 00727 { 00728 $ip = eZSys::serverVariable( 'REMOTE_ADDR', true ); 00729 if ( !$ip ) 00730 $ip = eZSys::serverVariable( 'HOSTNAME', true ); 00731 $this->DebugStrings[] = array( "Level" => $verbosityLevel, 00732 "IP" => $ip, 00733 "Time" => time(), 00734 "Label" => $label, 00735 "String" => $string, 00736 "BackgroundClass" => $backgroundClass ); 00737 } 00738 00739 if ( $fileName !== false ) 00740 { 00741 $timePoints = $this->TmpTimePoints[$verbosityLevel]; 00742 if ( is_array( $timePoints ) ) 00743 { 00744 if ( $this->isLogFileEnabled( $verbosityLevel ) ) 00745 { 00746 foreach ( $timePoints as $tp ) 00747 { 00748 $desc = "Timing Point: " . $tp["Description"]; 00749 if ( $this->isLogFileEnabled( $verbosityLevel ) ) 00750 { 00751 $this->writeFile( $fileName, $desc, $verbosityLevel, $alwaysLog ); 00752 } 00753 } 00754 } 00755 $this->TmpTimePoints[$verbosityLevel] = false; 00756 } 00757 if ( $this->isLogFileEnabled( $verbosityLevel ) ) 00758 { 00759 $string = "$label:\n$string"; 00760 $this->writeFile( $fileName, $string, $verbosityLevel, $alwaysLog ); 00761 } 00762 } 00763 } 00764 } 00765 00766 /*! 00767 \static 00768 \return the maxium size for a log file in bytes. 00769 */ 00770 static function maxLogSize() 00771 { 00772 if ( isset( $GLOBALS['eZDebugMaxLogSize'] ) ) 00773 { 00774 return $GLOBALS['eZDebugMaxLogSize']; 00775 } 00776 return self::MAX_LOGFILE_SIZE; 00777 } 00778 00779 /*! 00780 \static 00781 Sets the maxium size for a log file to \a $size. 00782 */ 00783 static function setMaxLogSize( $size ) 00784 { 00785 $GLOBALS['eZDebugMaxLogSize'] = $size; 00786 } 00787 00788 /*! 00789 \static 00790 \return the maxium number of logrotate files to keep. 00791 */ 00792 static function maxLogrotateFiles() 00793 { 00794 if ( isset( $GLOBALS['eZDebugMaxLogrotateFiles'] ) ) 00795 { 00796 return $GLOBALS['eZDebugMaxLogrotateFiles']; 00797 } 00798 return self::MAX_LOGROTATE_FILES; 00799 } 00800 00801 /*! 00802 \static 00803 Sets the maxium number of logrotate files to keep to \a $files. 00804 */ 00805 static function setLogrotateFiles( $files ) 00806 { 00807 $GLOBALS['eZDebugMaxLogrotateFiles'] = $files; 00808 } 00809 00810 /*! 00811 \static 00812 Rotates logfiles so the current logfile is backed up, 00813 old rotate logfiles are rotated once more and those that 00814 exceed maxLogrotateFiles() will be removed. 00815 Rotated files will get the extension .1, .2 etc. 00816 */ 00817 static function rotateLog( $fileName ) 00818 { 00819 $maxLogrotateFiles = eZDebug::maxLogrotateFiles(); 00820 for ( $i = $maxLogrotateFiles; $i > 0; --$i ) 00821 { 00822 $logRotateName = $fileName . '.' . $i; 00823 if ( @file_exists( $logRotateName ) ) 00824 { 00825 if ( $i == $maxLogrotateFiles ) 00826 { 00827 @unlink( $logRotateName ); 00828 // print( "@unlink( $logRotateName )<br/>" ); 00829 } 00830 else 00831 { 00832 $newLogRotateName = $fileName . '.' . ($i + 1); 00833 //include_once( 'lib/ezfile/classes/ezfile.php' ); 00834 eZFile::rename( $logRotateName, $newLogRotateName ); 00835 // print( "@rename( $logRotateName, $newLogRotateName )<br/>" ); 00836 } 00837 } 00838 } 00839 if ( @file_exists( $fileName ) ) 00840 { 00841 $newLogRotateName = $fileName . '.' . 1; 00842 //include_once( 'lib/ezfile/classes/ezfile.php' ); 00843 eZFile::rename( $fileName, $newLogRotateName ); 00844 // print( "@rename( $fileName, $newLogRotateName )<br/>" ); 00845 return true; 00846 } 00847 return false; 00848 } 00849 00850 /*! 00851 \private 00852 Writes the log message $string to the file $fileName. 00853 */ 00854 function writeFile( &$logFileData, &$string, $verbosityLevel, $alwaysLog = false ) 00855 { 00856 $enabled = eZDebug::isDebugEnabled(); 00857 if ( !$alwaysLog and !$enabled ) 00858 return; 00859 if ( !$alwaysLog and !$this->isLogFileEnabled( $verbosityLevel ) ) 00860 return; 00861 $oldHandleType = eZDebug::setHandleType( self::HANDLE_TO_PHP ); 00862 $logDir = $logFileData[0]; 00863 $logName = $logFileData[1]; 00864 $fileName = $logDir . $logName; 00865 if ( !file_exists( $logDir ) ) 00866 { 00867 //include_once( 'lib/ezfile/classes/ezdir.php' ); 00868 eZDir::mkdir( $logDir, false, true ); 00869 } 00870 $oldumask = @umask( 0 ); 00871 $fileExisted = @file_exists( $fileName ); 00872 if ( $fileExisted and 00873 filesize( $fileName ) > eZDebug::maxLogSize() ) 00874 { 00875 if ( eZDebug::rotateLog( $fileName ) ) 00876 $fileExisted = false; 00877 } 00878 $logFile = @fopen( $fileName, "a" ); 00879 if ( $logFile ) 00880 { 00881 $time = strftime( "%b %d %Y %H:%M:%S", strtotime( "now" ) ); 00882 $ip = eZSys::serverVariable( 'REMOTE_ADDR', true ); 00883 if ( !$ip ) 00884 $ip = eZSys::serverVariable( 'HOSTNAME', true ); 00885 $notice = "[ " . $time . " ] [" . $ip . "] " . $string . "\n"; 00886 @fwrite( $logFile, $notice ); 00887 @fclose( $logFile ); 00888 if ( !$fileExisted ) 00889 { 00890 $ini = eZINI::instance(); 00891 $permissions = octdec( $ini->variable( 'FileSettings', 'LogFilePermissions' ) ); 00892 @chmod( $fileName, $permissions ); 00893 } 00894 @umask( $oldumask ); 00895 } 00896 else 00897 { 00898 @umask( $oldumask ); 00899 $logEnabled = $this->isLogFileEnabled( $verbosityLevel ); 00900 $this->setLogFileEnabled( false, $verbosityLevel ); 00901 if ( $verbosityLevel != self::LEVEL_ERROR or 00902 $logEnabled ) 00903 { 00904 eZDebug::setHandleType( $oldHandleType ); 00905 $this->writeError( "Cannot open log file '$fileName' for writing\n" . 00906 "The web server must be allowed to modify the file.\n" . 00907 "File logging for '$fileName' is disabled." , 'eZDebug::writeFile' ); 00908 } 00909 } 00910 eZDebug::setHandleType( $oldHandleType ); 00911 } 00912 00913 /*! 00914 \static 00915 Enables or disables logging to file for a given message type. 00916 If \a $types is not supplied it will do the operation for all types. 00917 */ 00918 static function setLogFileEnabled( $enabled, $types = false ) 00919 { 00920 $instance = eZDebug::instance(); 00921 if ( $types === false ) 00922 { 00923 $types = $instance->messageTypes(); 00924 } 00925 if ( !is_array( $types ) ) 00926 { 00927 $types = array( $types ); 00928 } 00929 foreach ( $types as $type ) 00930 { 00931 $instance->LogFileEnabled[$type] = $enabled; 00932 } 00933 } 00934 00935 /*! 00936 \return true if the message type \a $type has logging to file enabled. 00937 \sa isGlobalLogFileEnabled, setIsLogFileEnabled 00938 */ 00939 function isLogFileEnabled( $type ) 00940 { 00941 if ( !$this->isGlobalLogFileEnabled() ) 00942 return false; 00943 return $this->LogFileEnabled[$type]; 00944 } 00945 00946 /*! 00947 \return true if the message type \a $type has logging to file enabled. 00948 \sa isLogFileEnabled, setIsGlobalLogFileEnabled 00949 */ 00950 function isGlobalLogFileEnabled() 00951 { 00952 return $this->GlobalLogFileEnabled; 00953 } 00954 00955 /*! 00956 Sets whether the logfile \a $type is enabled or disabled to \a $enabled. 00957 \sa isLogFileEnabled 00958 */ 00959 function setIsLogFileEnabled( $type, $enabled ) 00960 { 00961 $this->LogFileEnabled[$type] = $enabled; 00962 } 00963 00964 /*! 00965 Sets whether logfiles are enabled or disabled globally. Sets the value to \a $enabled. 00966 \sa isLogFileEnabled, isGlobalLogFileEnabled 00967 */ 00968 function setIsGlobalLogFileEnabled( $enabled ) 00969 { 00970 $this->GlobalLogFileEnabled = $enabled; 00971 } 00972 00973 /*! 00974 Sets whether debug output should be logged only 00975 */ 00976 function setLogOnly( $enabled ) 00977 { 00978 $GLOBALS['eZDebugLogOnly'] = $enabled; 00979 } 00980 00981 /*! 00982 \return an array with the available message types. 00983 */ 00984 function messageTypes() 00985 { 00986 return $this->MessageTypes; 00987 } 00988 00989 /*! 00990 Returns an associative array of all the log files used by this class 00991 where each key is the debug level (self::LEVEL_NOTICE, self::LEVEL_WARNING or self::LEVEL_ERROR or self::LEVEL_DEBUG). 00992 */ 00993 function logFiles() 00994 { 00995 return $this->LogFiles; 00996 } 00997 00998 /*! 00999 \static 01000 \return true if debug should be enabled. 01001 \note Will return false until the real settings has been updated with updateSettings() 01002 */ 01003 static function isDebugEnabled() 01004 { 01005 if ( isset( $GLOBALS['eZDebugEnabled'] ) ) 01006 { 01007 return $GLOBALS['eZDebugEnabled']; 01008 } 01009 01010 return false; 01011 } 01012 01013 /*! 01014 \static 01015 \return true if there should only be logging of debug strings to file. 01016 \note Will return false until the real settings has been updated with updateSettings() 01017 */ 01018 static function isLogOnlyEnabled() 01019 { 01020 if ( isset( $GLOBALS['eZDebugLogOnly'] ) ) 01021 { 01022 return $GLOBALS['eZDebugLogOnly']; 01023 } 01024 01025 return false; 01026 } 01027 01028 /*! 01029 \static 01030 Determine if an ipaddress is in a network. E.G. 120.120.120.120 in 120.120.0.0/24. 01031 \return true or false. 01032 */ 01033 static function isIPInNet( $ipaddress, $network, $mask = 24 ) 01034 { 01035 $lnet = ip2long( $network ); 01036 $lip = ip2long( $ipaddress ); 01037 $binnet = str_pad( decbin( $lnet ), 32, "0", "STR_PAD_LEFT" ); 01038 $firstpart = substr($binnet,0,$mask); 01039 $binip = str_pad( decbin( $lip ), 32, "0", "STR_PAD_LEFT" ); 01040 $firstip = substr( $binip, 0, $mask ); 01041 return( strcmp( $firstpart, $firstip ) == 0 ); 01042 } 01043 01044 /*! 01045 \static 01046 Updates the settings for debug handling with the settings array \a $settings. 01047 The array must contain the following keys. 01048 - debug-enabled - boolean which controls debug handling 01049 - debug-by-ip - boolean which controls IP controlled debugging 01050 - debug-ip-list - array of IPs which gets debug 01051 - debug-by-user - boolean which controls userID controlled debugging 01052 - debug-user-list - array of UserIDs which gets debug 01053 */ 01054 static function updateSettings( $settings ) 01055 { 01056 // Make sure errors are handled by PHP when we read, including our own debug output. 01057 $oldHandleType = eZDebug::setHandleType( self::HANDLE_TO_PHP ); 01058 01059 if ( isset( $settings['debug-log-files-enabled'] ) ) 01060 { 01061 $GLOBALS['eZDebugLogFileEnabled'] = $settings['debug-log-files-enabled']; 01062 if ( isset( $GLOBALS["eZDebugGlobalInstance"] ) ) 01063 $GLOBALS["eZDebugGlobalInstance"]->GlobalLogFileEnabled = $settings['debug-log-files-enabled']; 01064 } 01065 01066 if ( isset( $settings['debug-styles'] ) ) 01067 { 01068 $GLOBALS['eZDebugStyles'] = $settings['debug-styles']; 01069 } 01070 01071 if ( isset( $settings['always-log'] ) and 01072 is_array( $settings['always-log'] ) ) 01073 { 01074 $GLOBALS['eZDebugAlwaysLog'] = $settings['always-log']; 01075 } 01076 01077 if ( isset( $settings['log-only'] ) ) 01078 { 01079 $GLOBALS['eZDebugLogOnly'] = ( $settings['log-only'] == 'enabled' ); 01080 } 01081 01082 $GLOBALS['eZDebugAllowedByIP'] = $settings['debug-by-ip'] ? self::isAllowedByCurrentIP( $settings['debug-ip-list'] ) : true; 01083 01084 // updateSettings is meant to be called before the user session is started 01085 // so we do not take debug-by-user into account yet, but store the debug-user-list in $GLOBALS 01086 // so it can be used in the final check, done by checkDebugByUser() 01087 if ( isset( $settings['debug-by-user'] ) && $settings['debug-by-user'] ) 01088 { 01089 $GLOBALS['eZDebugUserIDList'] = $settings['debug-user-list'] ? $settings['debug-user-list'] : array(); 01090 } 01091 01092 $GLOBALS['eZDebugAllowed'] = $GLOBALS['eZDebugAllowedByIP']; 01093 $GLOBALS['eZDebugEnabled'] = $settings['debug-enabled'] && $GLOBALS['eZDebugAllowedByIP']; 01094 01095 eZDebug::setHandleType( $oldHandleType ); 01096 } 01097 01098 /*! 01099 \static 01100 Final checking for debug by user id. 01101 Checks if we should enable debug. 01102 01103 Returns false if debug-by-user is not active, was already checked before 01104 or if there is no current user. Returns true otherwise. 01105 */ 01106 static function checkDebugByUser() 01107 { 01108 if ( !isset( $GLOBALS['eZDebugUserIDList'] ) || 01109 !is_array( $GLOBALS['eZDebugUserIDList'] ) ) 01110 { 01111 return false; 01112 } 01113 else 01114 { 01115 $currentUserID = eZUser::currentUserID(); 01116 01117 if ( !$currentUserID ) 01118 { 01119 return false; 01120 } 01121 else 01122 { 01123 $GLOBALS['eZDebugAllowedByUser'] = in_array( $currentUserID, $GLOBALS['eZDebugUserIDList'] ); 01124 01125 if ( $GLOBALS['eZDebugAllowed'] ) 01126 { 01127 $GLOBALS['eZDebugAllowed'] = $GLOBALS['eZDebugAllowedByUser']; 01128 } 01129 01130 if ( $GLOBALS['eZDebugEnabled'] ) 01131 { 01132 $GLOBALS['eZDebugEnabled'] = $GLOBALS['eZDebugAllowedByUser']; 01133 } 01134 01135 unset( $GLOBALS['eZDebugUserIDList'] ); 01136 01137 return true; 01138 } 01139 } 01140 } 01141 01142 /*! 01143 \static 01144 Prints the debug report 01145 */ 01146 static function printReport( $newWindow = false, $as_html = true, $returnReport = false, 01147 $allowedDebugLevels = false, $useAccumulators = true, $useTiming = true, $useIncludedFiles = false ) 01148 { 01149 if ( !eZDebug::isDebugEnabled() ) 01150 return null; 01151 01152 $debug = eZDebug::instance(); 01153 $report = $debug->printReportInternal( $as_html, $returnReport & $newWindow, $allowedDebugLevels, $useAccumulators, $useTiming, $useIncludedFiles ); 01154 01155 if ( $newWindow == true ) 01156 { 01157 $debugFilePath = eZDir::path( array( eZSys::varDirectory(), 'cache', 'debug.html' ) ); 01158 $debugFileURL = $debugFilePath; 01159 eZURI::transformURI( $debugFileURL, true ); 01160 print( " 01161 <SCRIPT LANGUAGE='JavaScript'> 01162 <!-- hide this script from old browsers 01163 01164 function showDebug() 01165 { 01166 var debugWindow; 01167 01168 if (navigator.appName == \"Microsoft Internet Explorer\") 01169 { 01170 //Microsoft Internet Explorer 01171 debugWindow = window.open( '$debugFileURL', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40'); 01172 debugWindow.document.close(); 01173 debugWindow.location.reload(); 01174 } 01175 else if (navigator.appName == \"Opera\") 01176 { 01177 //Opera 01178 debugWindow = window.open( '', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40'); 01179 debugWindow.location.href=\"$debugFileURL\"; 01180 debugWindow.navigate(\"$debugFileURL\"); 01181 } 01182 else 01183 { 01184 //Mozilla, Firefox, etc. 01185 debugWindow = window.open( '', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40'); 01186 debugWindow.document.location.href=\"$debugFileURL\"; 01187 }; 01188 } 01189 01190 showDebug(); 01191 01192 // done hiding from old browsers --> 01193 </SCRIPT> 01194 " ); 01195 $header = "<html><head><title>eZ debug</title></head><body>"; 01196 $footer = "</body></html>"; 01197 $fp = fopen( $debugFilePath, "w+" ); 01198 01199 fwrite( $fp, $header ); 01200 fwrite( $fp, $report ); 01201 fwrite( $fp, $footer ); 01202 fclose( $fp ); 01203 } 01204 else 01205 { 01206 if ( $returnReport ) 01207 return $report; 01208 } 01209 return null; 01210 } 01211 01212 /*! 01213 \private 01214 Returns the microtime as a float value. $mtime must be in microtime() format. 01215 */ 01216 static function timeToFloat( $mtime ) 01217 { 01218 $tTime = explode( " ", $mtime ); 01219 ereg( "0\.([0-9]+)", "" . $tTime[0], $t1 ); 01220 $time = $tTime[1] . "." . $t1[1]; 01221 return $time; 01222 } 01223 01224 /*! 01225 Sets the time of the start of the script ot \a $time. 01226 If \a $time is not supplied it gets the current \c microtime( true ). 01227 This is used to calculate total execution time and percentages. 01228 */ 01229 static function setScriptStart( $time = false ) 01230 { 01231 if ( $time == false ) 01232 $time = microtime( true ); 01233 $debug = eZDebug::instance(); 01234 $debug->ScriptStart = $time; 01235 } 01236 01237 /*! 01238 Creates an accumulator group with key \a $key and group name \a $name. 01239 If \a $name is not supplied name is taken from \a $key. 01240 */ 01241 static function createAccumulatorGroup( $key, $name = false ) 01242 { 01243 if ( !eZDebug::isDebugEnabled() ) 01244 return; 01245 if ( $name == '' or 01246 $name === false ) 01247 $name = $key; 01248 $debug = eZDebug::instance(); 01249 if ( !array_key_exists( $key, $debug->TimeAccumulatorList ) ) 01250 $debug->TimeAccumulatorList[$key] = array( 'name' => $name, 'time' => 0, 'count' => 0, 'is_group' => true, 'in_group' => false ); 01251 if ( !array_key_exists( $key, $debug->TimeAccumulatorGroupList ) ) 01252 $debug->TimeAccumulatorGroupList[$key] = array(); 01253 } 01254 01255 /*! 01256 Creates a new accumulator entry if one does not already exist and initializes with default data. 01257 If \a $name is not supplied name is taken from \a $key. 01258 If \a $inGroup is supplied it will place the accumulator under the specified group. 01259 */ 01260 static function createAccumulator( $key, $inGroup = false, $name = false ) 01261 { 01262 if ( !eZDebug::isDebugEnabled() ) 01263 return; 01264 if ( $name == '' or 01265 $name === false ) 01266 $name = $key; 01267 $debug = eZDebug::instance(); 01268 $isGroup = false; 01269 if ( array_key_exists( $key, $debug->TimeAccumulatorList ) and 01270 array_key_exists( $key, $debug->TimeAccumulatorGroupList ) ) 01271 $isGroup = true; 01272 $debug->TimeAccumulatorList[$key] = array( 'name' => $name, 'time' => 0, 'count' => 0, 'is_group' => $isGroup, 'in_group' => $inGroup ); 01273 if ( $inGroup !== false ) 01274 { 01275 $groupKeys = array(); 01276 if ( array_key_exists( $inGroup, $debug->TimeAccumulatorGroupList ) ) 01277 $groupKeys = $debug->TimeAccumulatorGroupList[$inGroup]; 01278 $debug->TimeAccumulatorGroupList[$inGroup] = array_unique( array_merge( $groupKeys, array( $key ) ) ); 01279 if ( array_key_exists( $inGroup, $debug->TimeAccumulatorList ) ) 01280 $debug->TimeAccumulatorList[$inGroup]['is_group'] = true; 01281 } 01282 } 01283 01284 /*! 01285 Starts an time count for the accumulator \a $key. 01286 You can also specify a name which will be displayed. 01287 */ 01288 static function accumulatorStart( $key, $inGroup = false, $name = false, $recursive = false ) 01289 { 01290 if ( !eZDebug::isDebugEnabled() ) 01291 return; 01292 $debug = eZDebug::instance(); 01293 $key = $key === false ? 'Default Debug-Accumulator' : $key; 01294 if ( ! array_key_exists( $key, $debug->TimeAccumulatorList ) ) 01295 { 01296 $debug->createAccumulator( $key, $inGroup, $name ); 01297 } 01298 01299 if ( $recursive ) 01300 { 01301 if ( isset( $debug->TimeAccumulatorList[$key]['recursive_counter'] ) ) 01302 { 01303 $debug->TimeAccumulatorList[$key]['recursive_counter']++; 01304 return; 01305 } 01306 $debug->TimeAccumulatorList[$key]['recursive_counter'] = 0; 01307 } 01308 01309 $debug->TimeAccumulatorList[$key]['temp_time'] = microtime( true ); 01310 } 01311 01312 /*! 01313 Stops a previous time count and adds the total time to the accumulator \a $key. 01314 */ 01315 static function accumulatorStop( $key, $recursive = false ) 01316 { 01317 if ( !eZDebug::isDebugEnabled() ) 01318 return; 01319 $debug = eZDebug::instance(); 01320 $stopTime = microtime( true ); 01321 $key = $key === false ? 'Default Debug-Accumulator' : $key; 01322 if ( ! array_key_exists( $key, $debug->TimeAccumulatorList ) ) 01323 { 01324 eZDebug::writeWarning( "Accumulator '$key' does not exist, run eZDebug::accumulatorStart first", 'eZDebug::accumulatorStop' ); 01325 return; 01326 } 01327 $accumulator = $debug->TimeAccumulatorList[$key]; 01328 if ( $recursive ) 01329 { 01330 if ( isset( $accumulator['recursive_counter'] ) ) 01331 { 01332 if ( $accumulator['recursive_counter'] > 0 ) 01333 { 01334 $accumulator['recursive_counter']--; 01335 return; 01336 } 01337 } 01338 } 01339 $diffTime = $stopTime - $accumulator['temp_time']; 01340 $accumulator['time'] = $accumulator['time'] + $diffTime; 01341 ++$accumulator['count']; 01342 $debug->TimeAccumulatorList[$key] = $accumulator; 01343 } 01344 01345 01346 /*! 01347 \private 01348 Prints a full debug report with notice, warnings, errors and a timing report. 01349 */ 01350 function printReportInternal( $as_html = true, $returnReport = true, $allowedDebugLevels = false, 01351 $useAccumulators = true, $useTiming = true, $useIncludedFiles = false ) 01352 { 01353 $styles = array( 'strict' => false, 01354 'strict-end' => false, 01355 'warning' => false, 01356 'warning-end' => false, 01357 'error' => false, 01358 'error-end' => false, 01359 'debug' => false, 01360 'debug-end' => false, 01361 'notice' => false, 01362 'notice-end' => false, 01363 'timing' => false, 01364 'timing-end' => false, 01365 'mark' => false, 01366 'mark-end' => false, 01367 'emphasize' => false, 01368 'emphasize-end' => false, 01369 'bold' => false, 01370 'bold-end' => false ); 01371 if ( isset( $GLOBALS['eZDebugStyles'] ) ) 01372 $styles = $GLOBALS['eZDebugStyles']; 01373 if ( !$allowedDebugLevels ) 01374 $allowedDebugLevels = array( self::LEVEL_NOTICE, self::LEVEL_WARNING, self::LEVEL_ERROR, 01375 self::LEVEL_DEBUG, self::LEVEL_TIMING_POINT, self::LEVEL_STRICT ); 01376 $endTime = microtime( true ); 01377 01378 if ( $returnReport ) 01379 { 01380 ob_start(); 01381 } 01382 01383 if ( $as_html ) 01384 { 01385 echo "<div id=\"debug\"><table style='border: 1px dashed black; background-color: #fefefe;' summary='Layout table for eZ Publish debug output'>"; 01386 echo "<tr><th><h1>eZ debug</h1></th></tr>"; 01387 01388 echo "<tr><td>"; 01389 01390 if ( !$this->UseCSS ) 01391 { 01392 echo "<STYLE TYPE='text/css'> 01393 <!-- 01394 td.debugheader 01395 { 01396 background-color : #eeeeee; 01397 border-top : 1px solid #444488; 01398 border-bottom : 1px solid #444488; 01399 font-size : 65%; 01400 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 01401 } 01402 01403 pre.debugtransaction 01404 { 01405 background-color : #f8f6d8; 01406 } 01407 01408 td.timingpoint1 01409 { 01410 background-color : #ffffff; 01411 border-top : 1px solid #444488; 01412 font-size : 65%; 01413 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 01414 } 01415 01416 td.timingpoint2 01417 { 01418 background-color : #eeeeee; 01419 border-top : 1px solid #444488; 01420 font-size : 65%; 01421 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 01422 } 01423 01424 --> 01425 </STYLE>"; 01426 } 01427 echo "<table style='border: 1px lightgray;' cellspacing='0' summary='Table for actual debug output, shows notices, warnings and errors.'>"; 01428 } 01429 01430 $this->printTopReportsList(); 01431 01432 $hasLevel = array( self::LEVEL_NOTICE => false, 01433 self::LEVEL_WARNING => false, 01434 self::LEVEL_ERROR => false, 01435 self::LEVEL_TIMING_POINT => false, 01436 self::LEVEL_DEBUG => false, 01437 self::LEVEL_STRICT => false ); 01438 01439 foreach ( $this->DebugStrings as $debug ) 01440 { 01441 if ( !in_array( $debug['Level'], $allowedDebugLevels ) ) 01442 continue; 01443 $time = strftime ("%b %d %Y %H:%M:%S", strtotime( "now" ) ); 01444 01445 $outputData = $this->OutputFormat[$debug["Level"]]; 01446 if ( is_array( $outputData ) ) 01447 { 01448 $identifierText = ''; 01449 if ( !$hasLevel[$debug['Level']] ) 01450 { 01451 $hasLevel[$debug['Level']] = true; 01452 $identifierText = ' id="' . $outputData['xhtml-identifier'] . '"'; 01453 } 01454 $color = $outputData["color"]; 01455 $name = $outputData["name"]; 01456 $label = $debug["Label"]; 01457 $bgclass = $debug["BackgroundClass"]; 01458 $pre = ($bgclass != '' ? " class='$bgclass'" : ''); 01459 if ( $as_html ) 01460 { 01461 $label = htmlspecialchars( $label ); 01462 01463 $contents = ''; 01464 if ( extension_loaded( 'xdebug' ) && ( strncmp( self::XDEBUG_SIGNATURE, $debug['String'], strlen( self::XDEBUG_SIGNATURE ) ) === 0 ) ) 01465 $contents = substr( $debug['String'], strlen( self::XDEBUG_SIGNATURE ) ); 01466 else 01467 $contents = htmlspecialchars( $debug['String'] ); 01468 01469 echo "<tr><td class='debugheader' valign='top'$identifierText><b><span style='color: $color'>$name:</span> $label</b></td> 01470 <td class='debugheader' valign='top'>$time</td></tr> 01471 <tr><td colspan='2'><pre$pre>" . $contents . "</pre></td></tr>"; 01472 } 01473 else 01474 { 01475 echo $styles[$outputData['style']] . "$name:" . $styles[$outputData['style'].'-end'] . " "; 01476 echo $styles['bold'] . "($label)" . $styles['bold-end'] . "\n" . $debug["String"] . "\n\n"; 01477 } 01478 } 01479 flush(); 01480 } 01481 if ( $as_html ) 01482 { 01483 echo "</table>"; 01484 01485 echo "<h2>Timing points:</h2>"; 01486 echo "<table id='timingpoints' style='border: 1px dashed black;' cellspacing='0' summary='Tabel of timingpoint stats.'><tr><th>Checkpoint</th><th>Elapsed</th><th>Rel. Elapsed</th><th>Memory</th><th>Rel. Memory</th></tr>"; 01487 } 01488 $startTime = false; 01489 $elapsed = 0.00; 01490 $relElapsed = 0.00; 01491 if ( $useTiming ) 01492 { 01493 for ( $i = 0; $i < count( $this->TimePoints ); ++$i ) 01494 { 01495 $point = $this->TimePoints[$i]; 01496 $nextPoint = false; 01497 if ( isset( $this->TimePoints[$i + 1] ) ) 01498 $nextPoint = $this->TimePoints[$i + 1]; 01499 $time = $point["Time"]; 01500 $nextTime = false; 01501 if ( $startTime === false ) 01502 $startTime = $time; 01503 $elapsed = $time - $startTime; 01504 01505 $relMemory = 0; 01506 $memory = $point["MemoryUsage"]; 01507 // Calculate relative time and memory usage 01508 if ( $nextPoint !== false ) 01509 { 01510 $nextTime = $nextPoint["Time"]; 01511 $relElapsed = $nextTime - $time; 01512 $relElapsed = number_format( $relElapsed, $this->TimingAccuracy ) . " sec"; 01513 01514 $nextMemory = $nextPoint["MemoryUsage"]; 01515 $relMemory = $nextMemory - $memory; 01516 $relMemory = number_format( $relMemory / 1024, $this->TimingAccuracy ) . " KB"; 01517 } 01518 else 01519 { 01520 $relElapsed = $as_html ? ' ' : ''; 01521 $relMemory = $as_html ? ' ' : ''; 01522 } 01523 01524 // Convert memory usage to human readable 01525 $memory = number_format( $memory / 1024, $this->TimingAccuracy ) . " KB"; 01526 $elapsed = number_format( $elapsed, $this->TimingAccuracy ) . " sec"; 01527 01528 if ( $i % 2 == 0 ) 01529 $class = "timingpoint1"; 01530 else 01531 $class = "timingpoint2"; 01532 01533 if ( $as_html ) 01534 { 01535 echo "<tr><td class='$class'>" . $point["Description"] . "</td> 01536 <td class='$class' align='right'>$elapsed</td><td class='$class' align='right'>$relElapsed</td> 01537 <td class='$class' align='right'>$memory</td><td class='$class' align='right'>$relMemory</td></tr>"; 01538 } 01539 else 01540 { 01541 echo $point["Description"] . ' ' . $elapsed . $relElapsed . "\n"; 01542 } 01543 } 01544 01545 if ( count( $this->TimePoints ) > 0 ) 01546 { 01547 $totalElapsed = $endTime - $startTime; 01548 01549 if ( $as_html ) 01550 { 01551 echo "<tr><td><b>Total runtime:</b></td><td><b>" . 01552 number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec</b></td><td></td></tr>"; 01553 } 01554 else 01555 { 01556 echo "Total runtime: " . 01557 number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec\n"; 01558 } 01559 } 01560 else 01561 { 01562 if ( $as_html ) 01563 echo "<tr><td> No timing points defined</td><td>"; 01564 else 01565 echo "No timing points defined\n"; 01566 } 01567 01568 if ( function_exists( 'memory_get_peak_usage' ) ) 01569 { 01570 $peakMemory = memory_get_peak_usage(); 01571 if ( $as_html ) 01572 { 01573 echo "<tr><td><b>Peak memory usage:</b></td><td><b>" . 01574 number_format( $peakMemory / 1024, $this->TimingAccuracy ) . " KB</b></td></tr>"; 01575 } 01576 else 01577 { 01578 echo "Peak memory usage: " . 01579 number_format( $peakMemory / 1024, $this->TimingAccuracy ) . " KB\n"; 01580 } 01581 } 01582 } 01583 if ( $as_html ) 01584 { 01585 echo "</table>"; 01586 } 01587 01588 if ( $useIncludedFiles ) 01589 { 01590 if ( $as_html ) 01591 echo "<h2>Included files:</h2><table style='border: 1px dashed black;' cellspacing='0' summary='Tabel list of included templates used in the processing of this page.'><tr><th>File</th></tr>"; 01592 else 01593 echo $styles['emphasize'] . "Includes" . $styles['emphasize-end'] . "\n"; 01594 $phpFiles = get_included_files(); 01595 $j = 0; 01596 $currentPathReg = preg_quote( realpath( "." ) ); 01597 foreach ( $phpFiles as $phpFile ) 01598 { 01599 if ( preg_match( "#^$currentPathReg/(.+)$#", $phpFile, $matches ) ) 01600 $phpFile = $matches[1]; 01601 if ( $as_html ) 01602 { 01603 if ( $j % 2 == 0 ) 01604 $class = "timingpoint1"; 01605 else 01606 $class = "timingpoint2"; 01607 ++$j; 01608 echo "<tr><td class=\"$class\">$phpFile</td></tr>"; 01609 } 01610 else 01611 { 01612 echo "$phpFile\n"; 01613 } 01614 } 01615 if ( $as_html ) 01616 echo "</table>"; 01617 } 01618 01619 if ( $as_html ) 01620 { 01621 echo "<h2>Time accumulators:</h2>"; 01622 echo "<table id='timeaccumulators' style='border: 1px dashed black;' cellspacing='0' summary='Table with detailed list of time accumulators'><tr><th> Accumulator</th><th> Elapsed</th><th> Percent</th><th> Count</th><th> Average</th></tr>"; 01623 $i = 0; 01624 } 01625 01626 $scriptEndTime = microtime( true ); 01627 $totalElapsed = $scriptEndTime - $this->ScriptStart; 01628 $timeList = $this->TimeAccumulatorList; 01629 $groups = $this->TimeAccumulatorGroupList; 01630 $groupList = array(); 01631 foreach ( $groups as $groupKey => $keyList ) 01632 { 01633 if ( count( $keyList ) == 0 and 01634 !array_key_exists( $groupKey, $timeList ) ) 01635 continue; 01636 $groupList[$groupKey] = array( 'name' => $groupKey ); 01637 if ( array_key_exists( $groupKey, $timeList ) ) 01638 { 01639 if ( $timeList[$groupKey]['time'] != 0 ) 01640 $groupList[$groupKey]['time_data'] = $timeList[$groupKey]; 01641 $groupList[$groupKey]['name'] = $timeList[$groupKey]['name']; 01642 unset( $timeList[$groupKey] ); 01643 } 01644 $groupChildren = array(); 01645 foreach ( $keyList as $timeKey ) 01646 { 01647 if ( array_key_exists( $timeKey, $timeList ) ) 01648 { 01649 $groupChildren[] = $timeList[$timeKey]; 01650 unset( $timeList[$timeKey] ); 01651 } 01652 } 01653 $groupList[$groupKey]['children'] = $groupChildren; 01654 } 01655 if ( count( $timeList ) > 0 ) 01656 { 01657 $groupList['general'] = array( 'name' => 'General', 01658 'children' => $timeList ); 01659 } 01660 01661 if ( $useAccumulators ) 01662 { 01663 $j = 0; 01664 foreach ( $groupList as $group ) 01665 { 01666 if ( $j % 2 == 0 ) 01667 $class = "timingpoint1"; 01668 else 01669 $class = "timingpoint2"; 01670 ++$j; 01671 $groupName = $group['name']; 01672 $groupChildren = $group['children']; 01673 if ( count( $groupChildren ) == 0 and 01674 !array_key_exists( 'time_data', $group ) ) 01675 continue; 01676 if ( $as_html ) 01677 echo "<tr><td class='$class'><b>$groupName</b></td>"; 01678 else 01679 echo "Group " . $styles['mark'] . "$groupName:" . $styles['mark-end'] . " "; 01680 if ( array_key_exists( 'time_data', $group ) ) 01681 { 01682 $groupData = $group['time_data']; 01683 $groupElapsed = number_format( ( $groupData['time'] ), $this->TimingAccuracy ); 01684 $groupPercent = number_format( ( $groupData['time'] * 100.0 ) / $totalElapsed, 1 ); 01685 $groupCount = $groupData['count']; 01686 $groupAverage = number_format( ( $groupData['time'] / $groupData['count'] ), $this->TimingAccuracy ); 01687 if ( $as_html ) 01688 { 01689 echo ( "<td class=\"$class\">$groupElapsed sec</td>". 01690 "<td class=\"$class\" align=\"right\"> $groupPercent%</td>". 01691 "<td class=\"$class\" align=\"right\"> $groupCount</td>". 01692 "<td class=\"$class\" align=\"right\"> $groupAverage sec</td>" ); 01693 } 01694 else 01695 { 01696 echo $styles['emphasize'] . "$groupElapsed" . $styles['emphasize-end'] . " sec ($groupPercent%), $groupAverage avg sec ($groupCount)"; 01697 } 01698 } 01699 else if ( $as_html ) 01700 { 01701 echo ( "<td class=\"$class\"></td>". 01702 "<td class=\"$class\"></td>". 01703 "<td class=\"$class\"></td>". 01704 "<td class=\"$class\"></td>" ); 01705 } 01706 if ( $as_html ) 01707 echo "</tr>"; 01708 else 01709 echo "\n"; 01710 01711 $i = 0; 01712 foreach ( $groupChildren as $child ) 01713 { 01714 $childName = $child['name']; 01715 $childElapsed = number_format( ( $child['time'] ), $this->TimingAccuracy ); 01716 $childPercent = number_format( ( $child['time'] * 100.0 ) / $totalElapsed, $this->PercentAccuracy ); 01717 $childCount = $child['count']; 01718 $childAverage = 0.0; 01719 if ( $childCount > 0 ) 01720 { 01721 $childAverage = $child['time'] / $childCount; 01722 } 01723 $childAverage = number_format( $childAverage, $this->PercentAccuracy ); 01724 01725 if ( $as_html ) 01726 { 01727 if ( $i % 2 == 0 ) 01728 $class = "timingpoint1"; 01729 else 01730 $class = "timingpoint2"; 01731 ++$i; 01732 01733 echo ( "<tr>" . 01734 "<td class=\"$class\">$childName</td>" . 01735 "<td class=\"$class\">$childElapsed sec</td>" . 01736 "<td class=\"$class\" align=\"right\">$childPercent%</td>" . 01737 "<td class=\"$class\" align=\"right\">$childCount</td>" . 01738 "<td class=\"$class\" align=\"right\">$childAverage sec</td>" . 01739 "</tr>" ); 01740 } 01741 else 01742 { 01743 echo "$childName: " . $styles['emphasize'] . $childElapsed . $styles['emphasize-end'] . " sec ($childPercent%), $childAverage avg sec ($childCount)\n"; 01744 } 01745 } 01746 } 01747 } 01748 if ( $as_html ) 01749 { 01750 echo "<tr><td><b>Total script time:</b></td><td><b>" . number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec</b></td><td></td></tr>"; 01751 } 01752 else 01753 { 01754 echo "\nTotal script time: " . $styles['emphasize'] . number_format( ( $totalElapsed ), $this->TimingAccuracy ) . $styles['emphasize-end'] . " sec\n"; 01755 } 01756 01757 if ( $as_html ) 01758 { 01759 echo "</table>"; 01760 } 01761 01762 $this->printBottomReportsList(); 01763 01764 if ( $as_html ) 01765 { 01766 echo "</td></tr></table></div>"; 01767 } 01768 01769 if ( $returnReport ) 01770 { 01771 $returnText = ob_get_contents(); 01772 ob_end_clean(); 01773 return $returnText; 01774 } 01775 else 01776 { 01777 return NULL; 01778 } 01779 } 01780 01781 /*! 01782 Appends report to 'top' reports list. 01783 */ 01784 static function appendTopReport( $reportName, $reportContent ) 01785 { 01786 $debug = eZDebug::instance(); 01787 $debug->topReportsList[$reportName] = $reportContent; 01788 } 01789 01790 /*! 01791 Prints all 'top' reports 01792 */ 01793 static function printTopReportsList() 01794 { 01795 $debug = eZDebug::instance(); 01796 $reportNames = array_keys( $debug->topReportsList ); 01797 foreach ( $reportNames as $reportName ) 01798 { 01799 echo $debug->topReportsList[$reportName]; 01800 } 01801 } 01802 01803 /*! 01804 Appends report to 'bottom' reports list. 01805 */ 01806 static function appendBottomReport( $reportName, $reportContent ) 01807 { 01808 $debug = eZDebug::instance(); 01809 $debug->bottomReportsList[$reportName] = $reportContent; 01810 } 01811 01812 /*! 01813 Prints all 'bottom' reports 01814 */ 01815 static function printBottomReportsList() 01816 { 01817 $debug = eZDebug::instance(); 01818 $reportNames = array_keys( $debug->bottomReportsList ); 01819 foreach ( $reportNames as $reportName ) 01820 { 01821 echo $debug->bottomReportsList[$reportName]; 01822 } 01823 } 01824 01825 /*! 01826 If debugging is allowed, given the limitations of the DebugByIP and DebugByUser settings. 01827 */ 01828 function isDebugAllowed() 01829 { 01830 01831 } 01832 01833 /*! 01834 If debugging is allowed for the current IP address. 01835 */ 01836 private static function isAllowedByCurrentIP( $allowedIpList ) 01837 { 01838 $ipAddress = eZSys::serverVariable( 'REMOTE_ADDR', true ); 01839 if ( $ipAddress ) 01840 { 01841 foreach( $allowedIpList as $itemToMatch ) 01842 { 01843 if ( preg_match("/^(([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+))(\/([0-9]+)$|$)/", $itemToMatch, $matches ) ) 01844 { 01845 if ( $matches[6] ) 01846 { 01847 if ( self::isIPInNet( $ipAddress, $matches[1], $matches[7] ) ) 01848 { 01849 return true; 01850 } 01851 } 01852 else 01853 { 01854 if ( $matches[1] == $ipAddress ) 01855 { 01856 return true; 01857 } 01858 } 01859 } 01860 } 01861 01862 return false; 01863 } 01864 else 01865 { 01866 return eZSys::isShellExecution() && in_array( 'commandline', $allowedIpList ); 01867 } 01868 } 01869 01870 /// \privatesection 01871 /// String array containing the debug information 01872 public $DebugStrings = array(); 01873 01874 /// Array which contains the time points 01875 public $TimePoints = array(); 01876 01877 /// Array which contains the temporary time points 01878 public $TmpTimePoints; 01879 01880 /// Array wich contains time accumulators 01881 public $TimeAccumulatorList = array(); 01882 01883 /// Determines which debug messages should be shown 01884 public $ShowTypes; 01885 01886 /// Determines what to do with php errors, ignore, fetch or output 01887 public $HandleType; 01888 01889 /// An array of the outputformats for the different debug levels 01890 public $OutputFormat; 01891 01892 /// An array of logfiles used by the debug class with each key being the debug level 01893 public $LogFiles; 01894 01895 /// How many places behing . should be displayed when showing times 01896 public $TimingAccuracy = 4; 01897 01898 /// How many places behing . should be displayed when showing percentages 01899 public $PercentAccuracy = 4; 01900 01901 /// Whether to use external CSS or output own CSS. True if external is to be used. 01902 public $UseCSS; 01903 01904 /// Determines how messages are output (screen/log) 01905 public $MessageOutput; 01906 01907 /// A list of message types 01908 public $MessageTypes; 01909 01910 /// A map with message types and whether they should do file logging. 01911 public $LogFileEnabled; 01912 01913 /// Controls whether logfiles are used at all. 01914 public $GlobalLogFileEnabled; 01915 01916 /// The time when the script was started 01917 public $ScriptStart; 01918 01919 /// A list of override directories 01920 public $OverrideList; 01921 01922 /// A list of debug reports that appears at the bottom of debug output 01923 public $bottomReportsList; 01924 01925 /// A list of debug reports that appears at the top of debug output 01926 public $topReportsList; 01927 } 01928 01929 /*! 01930 Helper function for eZDebug, called whenever a PHP error occurs. 01931 The error is then handled by the eZDebug class. 01932 */ 01933 01934 function eZDebugErrorHandler( $errno, $errstr, $errfile, $errline ) 01935 { 01936 if ( $GLOBALS['eZDebugRecursionFlag'] ) 01937 { 01938 print( "Fatal debug error: A recursion in debug error handler was detected, aborting debug message.<br/>" ); 01939 $GLOBALS['eZDebugRecursionFlag'] = false; 01940 return; 01941 } 01942 01943 $GLOBALS['eZDebugRecursionFlag'] = true; 01944 $debug = eZDebug::instance(); 01945 $result = $debug->errorHandler( $errno, $errstr, $errfile, $errline ); 01946 $GLOBALS['eZDebugRecursionFlag'] = false; 01947 return $result; 01948 } 01949 $GLOBALS['eZDebugRecursionFlag'] = false; 01950 01951 ?>