| [ Index ] |
|
Code source de eZ Publish 3.9.0 |
1 <?php 2 // 3 // Definition of eZDebug class 4 // 5 // Created on: <12-Feb-2002 11:00:54 bf> 6 // 7 // SOFTWARE NAME: eZ publish 8 // SOFTWARE RELEASE: 3.9.0 9 // BUILD VERSION: 17785 10 // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS 11 // SOFTWARE LICENSE: GNU General Public License v2.0 12 // NOTICE: > 13 // This program is free software; you can redistribute it and/or 14 // modify it under the terms of version 2.0 of the GNU General 15 // Public License as published by the Free Software Foundation. 16 // 17 // This program is distributed in the hope that it will be useful, 18 // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of version 2.0 of the GNU General 23 // Public License along with this program; if not, write to the Free 24 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 25 // MA 02110-1301, USA. 26 // 27 // 28 29 /*! \defgroup eZUtils Utility classes */ 30 31 /*! 32 \class eZDebug ezdebug.php 33 \ingroup eZUtils 34 \brief Advanced debug/log system 35 36 The eZ debug library is used to handle debug information. It 37 can display information on screen and/or write it to log files. 38 39 You can enable on-screen debug information for specific IP addresses. 40 41 Timing points can be placed in the code to time the different sections of code. 42 43 Each debug message can be turned on/off by using the showTypes() function. 44 45 PHP error messages can also be shown using setHandleType(). 46 47 \code 48 include_once( "lib/ezutils/classes/ezdebug.php" ); 49 50 // write a temporary debug message 51 eZDebug::writeDebug( "Test" ); 52 53 // write a notice 54 eZDebug::writeNotice( "Image found" ); 55 56 // write a warning 57 eZDebug::writeWarning( "Image not found, using default" ); 58 59 // write an error 60 eZDebug::writeError( "Object not found, bailing.." ); 61 62 // add a timing points 63 eZDebug::addTimingPoint( "Module Found" ); 64 65 //.... code 66 67 eZDebug::addTimingPoint( "Module loading" ); 68 69 // print the results on screen. 70 eZDebug::printReport(); 71 72 \endcode 73 */ 74 75 include_once ( "lib/ezutils/classes/ezsys.php" ); 76 77 define( "EZ_LEVEL_NOTICE", 1 ); 78 define( "EZ_LEVEL_WARNING", 2 ); 79 define( "EZ_LEVEL_ERROR", 3 ); 80 define( "EZ_LEVEL_TIMING_POINT", 4 ); 81 define( "EZ_LEVEL_DEBUG", 5 ); 82 83 define( "EZ_SHOW_NOTICE", 1 << (EZ_LEVEL_NOTICE - 1) ); 84 define( "EZ_SHOW_WARNING", 1 << (EZ_LEVEL_WARNING - 1) ); 85 define( "EZ_SHOW_ERROR", 1 << (EZ_LEVEL_ERROR - 1) ); 86 define( "EZ_SHOW_TIMING_POINT", 1 << (EZ_LEVEL_TIMING_POINT - 1) ); 87 define( "EZ_SHOW_DEBUG", 1 << (EZ_LEVEL_DEBUG - 1) ); 88 define( "EZ_SHOW_ALL", EZ_SHOW_NOTICE | EZ_SHOW_WARNING | EZ_SHOW_ERROR | EZ_SHOW_TIMING_POINT | EZ_SHOW_DEBUG ); 89 90 define( "EZ_HANDLE_NONE", 0 ); 91 define( "EZ_HANDLE_FROM_PHP", 1 ); 92 define( "EZ_HANDLE_TO_PHP", 2 ); 93 94 define( "EZ_OUTPUT_MESSAGE_SCREEN", 1 ); 95 define( "EZ_OUTPUT_MESSAGE_STORE", 2 ); 96 97 define( "EZ_DEBUG_MAX_LOGFILE_SIZE", 200*1024 ); 98 define( "EZ_DEBUG_MAX_LOGROTATE_FILES", 3 ); 99 100 define( "EZ_DEBUG_XDEBUG_SIGNATURE", '--XDEBUG--' ); 101 102 class eZDebug 103 { 104 /*! 105 Creates a new debug object. 106 */ 107 function eZDebug( ) 108 { 109 $this->TmpTimePoints = array( EZ_LEVEL_NOTICE => array(), 110 EZ_LEVEL_WARNING => array(), 111 EZ_LEVEL_ERROR => array(), 112 EZ_LEVEL_DEBUG => array() ); 113 114 $this->OutputFormat = array( EZ_LEVEL_NOTICE => array( "color" => "green", 115 'style' => 'notice', 116 'xhtml-identifier' => 'ezdebug-first-notice', 117 "name" => "Notice" ), 118 EZ_LEVEL_WARNING => array( "color" => "orange", 119 'style' => 'warning', 120 'xhtml-identifier' => 'ezdebug-first-warning', 121 "name" => "Warning" ), 122 EZ_LEVEL_ERROR => array( "color" => "red", 123 'style' => 'error', 124 'xhtml-identifier' => 'ezdebug-first-error', 125 "name" => "Error" ), 126 EZ_LEVEL_DEBUG => array( "color" => "brown", 127 'style' => 'debug', 128 'xhtml-identifier' => 'ezdebug-first-debug', 129 "name" => "Debug" ), 130 EZ_LEVEL_TIMING_POINT => array( "color" => "blue", 131 'style' => 'timing', 132 'xhtml-identifier' => 'ezdebug-first-timing-point', 133 "name" => "Timing" ) ); 134 $this->LogFiles = array( EZ_LEVEL_NOTICE => array( "var/log/", 135 "notice.log" ), 136 EZ_LEVEL_WARNING => array( "var/log/", 137 "warning.log" ), 138 EZ_LEVEL_ERROR => array( "var/log/", 139 "error.log" ), 140 EZ_LEVEL_DEBUG => array( "var/log/", 141 "debug.log" ) ); 142 $this->MessageTypes = array( EZ_LEVEL_NOTICE, 143 EZ_LEVEL_WARNING, 144 EZ_LEVEL_ERROR, 145 EZ_LEVEL_TIMING_POINT, 146 EZ_LEVEL_DEBUG ); 147 $this->MessageNames = array( EZ_LEVEL_NOTICE => 'Notice', 148 EZ_LEVEL_WARNING => 'Warning', 149 EZ_LEVEL_ERROR => 'Error', 150 EZ_LEVEL_TIMING_POINT => 'TimingPoint', 151 EZ_LEVEL_DEBUG => 'Debug' ); 152 $this->LogFileEnabled = array( EZ_LEVEL_NOTICE => true, 153 EZ_LEVEL_WARNING => true, 154 EZ_LEVEL_ERROR => true, 155 EZ_LEVEL_TIMING_POINT => true, 156 EZ_LEVEL_DEBUG => true ); 157 $this->AlwaysLog = array( EZ_LEVEL_NOTICE => false, 158 EZ_LEVEL_WARNING => false, 159 EZ_LEVEL_ERROR => true, // Error is on by default, due to its importance 160 EZ_LEVEL_TIMING_POINT => false, 161 EZ_LEVEL_DEBUG => false ); 162 $this->GlobalLogFileEnabled = true; 163 if ( isset( $GLOBALS['eZDebugLogFileEnabled'] ) ) 164 { 165 $this->GlobalLogFileEnabled = $GLOBALS['eZDebugLogFileEnabled']; 166 } 167 $this->ShowTypes = EZ_SHOW_ALL; 168 $this->HandleType = EZ_HANDLE_NONE; 169 $this->OldHandler = false; 170 $this->UseCSS = false; 171 $this->MessageOutput = EZ_OUTPUT_MESSAGE_STORE; 172 $this->ScriptStart = eZDebug::timeToFloat( microtime() ); 173 $this->TimeAccumulatorList = array(); 174 $this->TimeAccumulatorGroupList = array(); 175 $this->OverrideList = array(); 176 $this->topReportsList = array(); 177 $this->bottomReportsList = array(); 178 } 179 180 function reset() 181 { 182 $this->DebugStrings = array(); 183 $this->TmpTimePoints = array( EZ_LEVEL_NOTICE => array(), 184 EZ_LEVEL_WARNING => array(), 185 EZ_LEVEL_ERROR => array(), 186 EZ_LEVEL_DEBUG => array() ); 187 $this->TimeAccumulatorList = array(); 188 $this->TimeAccumulatorGroupList = array(); 189 $this->topReportsList = array(); 190 $this->bottomReportsList = array(); 191 } 192 193 /*! 194 \return the name of the message type. 195 */ 196 function messageName( $messageType ) 197 { 198 if ( isset( $this ) and 199 get_class( $this ) == "ezdebug" ) 200 $instance =& $this; 201 else 202 $instance =& eZDebug::instance(); 203 return $instance->MessageNames[$messageType]; 204 } 205 206 /*! 207 Will return the current eZDebug object. If no object exists one will 208 be created. 209 */ 210 function &instance( ) 211 { 212 $impl =& $GLOBALS["eZDebugGlobalInstance"]; 213 214 $class = get_class( $impl ); 215 if ( $class != "ezdebug" ) 216 { 217 $impl = new eZDebug(); 218 } 219 return $impl; 220 } 221 222 /*! 223 \static 224 Returns true if the message type $type can be shown. 225 */ 226 function showMessage( $type ) 227 { 228 $debug =& eZDebug::instance(); 229 return $debug->ShowTypes & $type; 230 } 231 232 /*! 233 \return \c true if the debug level \a $level should always log to file. 234 */ 235 function alwaysLogMessage( $level ) 236 { 237 if ( isset( $this ) and 238 get_class( $this ) == "ezdebug" ) 239 $instance =& $this; 240 else 241 $instance =& eZDebug::instance(); 242 243 // If there is a global setting for this get the value 244 // and unset it globally 245 if ( isset( $GLOBALS['eZDebugAlwaysLog'] ) ) 246 { 247 $instance->AlwaysLog = $GLOBALS['eZDebugAlwaysLog'] + $instance->AlwaysLog; 248 unset( $GLOBALS['eZDebugAlwaysLog'] ); 249 } 250 251 if ( !isset( $instance->AlwaysLog[$level] ) ) 252 return false; 253 return $instance->AlwaysLog[$level]; 254 } 255 256 /*! 257 Determines how PHP errors are handled. If $type is EZ_HANDLE_TO_PHP all error messages 258 is sent to PHP using trigger_error(), if $type is EZ_HANDLE_FROM_PHP all error messages 259 from PHP is fetched using a custom error handler and output as a usual eZDebug message. 260 If $type is EZ_HANDLE_NONE there is no error exchange between PHP and eZDebug. 261 */ 262 function setHandleType( $type ) 263 { 264 if ( isset( $this ) and 265 get_class( $this ) == "ezdebug" ) 266 $instance =& $this; 267 else 268 $instance =& eZDebug::instance(); 269 if ( $type != EZ_HANDLE_TO_PHP and 270 $type != EZ_HANDLE_FROM_PHP ) 271 $type = EZ_HANDLE_NONE; 272 if ( extension_loaded( 'xdebug' ) and 273 $type == EZ_HANDLE_FROM_PHP ) 274 $type = EZ_HANDLE_NONE; 275 if ( $type == $instance->HandleType ) 276 return $instance->HandleType; 277 278 if ( $instance->HandleType == EZ_HANDLE_FROM_PHP ) 279 restore_error_handler(); 280 switch ( $type ) 281 { 282 case EZ_HANDLE_FROM_PHP: 283 { 284 set_error_handler( "eZDebugErrorHandler" ); 285 } break; 286 287 case EZ_HANDLE_TO_PHP: 288 { 289 restore_error_handler(); 290 } break; 291 292 case EZ_HANDLE_NONE: 293 { 294 } 295 } 296 $oldHandleType = $instance->HandleType; 297 $instance->HandleType = $type; 298 return $oldHandleType; 299 } 300 301 /*! 302 \static 303 Sets types to be shown to $types and returns the old show types. 304 If $types is not supplied the current value is returned and no change is done. 305 $types is one or more of EZ_SHOW_NOTICE, EZ_SHOW_WARNING, EZ_SHOW_ERROR, EZ_SHOW_TIMING_POINT 306 or'ed together. 307 */ 308 function showTypes( $types = false ) 309 { 310 if ( isset( $this ) and 311 get_class( $this ) == "ezdebug" ) 312 $instance =& $this; 313 else 314 $instance =& eZDebug::instance(); 315 if ( $types === false ) 316 return $instance->ShowTypes; 317 $old_types = $instance->ShowTypes; 318 $instance->ShowTypes = $types; 319 return $old_types; 320 } 321 322 /*! 323 Handles PHP errors, creates notice, warning and error messages for 324 the various PHP error types. 325 */ 326 function errorHandler( $errno, $errstr, $errfile, $errline ) 327 { 328 if ( error_reporting() == 0 ) // @ error-control operator is used 329 return; 330 if ( !eZDebug::isDebugEnabled() ) 331 return; 332 $str = "$errstr in $errfile on line $errline"; 333 $errnames =& $GLOBALS["eZDebugPHPErrorNames"]; 334 if ( !is_array( $errnames ) ) 335 { 336 $errnames = array( E_ERROR => "E_ERROR", 337 E_PARSE => "E_PARSE", 338 E_CORE_ERROR => "E_CORE_ERROR", 339 E_COMPILE_ERROR => "E_COMPILE_ERROR", 340 E_USER_ERROR => "E_USER_ERROR", 341 E_WARNING => "E_WARNING", 342 E_CORE_WARNING => "E_CORE_WARNING", 343 E_COMPILE_WARNING => "E_COMPILE_WARNING", 344 E_USER_WARNING => "E_USER_WARNING", 345 E_NOTICE => "E_NOTICE", 346 E_USER_NOTICE => "E_USER_NOTICE" ); 347 } 348 $errname = "unknown"; 349 if ( isset( $errnames[$errno] ) ) 350 $errname = $errnames[$errno]; 351 switch ( $errno ) 352 { 353 case E_ERROR: 354 case E_PARSE: 355 case E_CORE_ERROR: 356 case E_COMPILE_ERROR: 357 case E_USER_ERROR: 358 { 359 eZDebug::writeError( $str, "PHP" ); 360 } break; 361 362 case E_WARNING: 363 case E_CORE_WARNING: 364 case E_COMPILE_WARNING: 365 case E_USER_WARNING: 366 case E_NOTICE: 367 { 368 eZDebug::writeWarning( $str, "PHP" ); 369 } break; 370 371 case E_USER_NOTICE: 372 { 373 eZDebug::writeNotice( $str, "PHP" ); 374 } break; 375 } 376 } 377 378 /*! 379 \static 380 Writes a debug notice. 381 382 The global variable \c 'eZDebugNotice' will be set to \c true if the notice is added. 383 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 384 \param $backgroundClass A string defining the class to use in the HTML debug output. 385 */ 386 function writeNotice( $string, $label = "", $backgroundClass = "" ) 387 { 388 $alwaysLog = eZDebug::alwaysLogMessage( EZ_LEVEL_NOTICE ); 389 $enabled = eZDebug::isDebugEnabled(); 390 if ( !$alwaysLog and !$enabled ) 391 return; 392 393 $show = eZDebug::showMessage( EZ_SHOW_NOTICE ); 394 if ( !$alwaysLog and !$show ) 395 return; 396 397 if ( is_object( $string ) || is_array( $string ) ) 398 $string = eZDebug::dumpVariable( $string ); 399 400 $GLOBALS['eZDebugNotice'] = true; 401 if ( !isset( $GLOBALS['eZDebugNoticeCount'] ) ) 402 $GLOBALS['eZDebugNoticeCount'] = 0; 403 ++$GLOBALS['eZDebugNoticeCount']; 404 405 $debug =& eZDebug::instance(); 406 if ( $debug->HandleType == EZ_HANDLE_TO_PHP ) 407 { 408 // If we get here only because of $alwaysLog we should not trigger a PHP error 409 if ( $enabled and $show ) 410 { 411 if ( $label ) 412 $string = "$label: $string"; 413 trigger_error( $string, E_USER_NOTICE ); 414 } 415 } 416 else 417 { 418 $debug->write( $string, EZ_LEVEL_NOTICE, $label, $backgroundClass, $alwaysLog ); 419 } 420 } 421 422 /*! 423 \static 424 Writes a debug warning. 425 426 The global variable \c 'eZDebugWarning' will be set to \c true if the notice is added. 427 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 428 */ 429 function writeWarning( $string, $label = "", $backgroundClass = "" ) 430 { 431 $alwaysLog = eZDebug::alwaysLogMessage( EZ_LEVEL_WARNING ); 432 $enabled = eZDebug::isDebugEnabled(); 433 if ( !$alwaysLog and !$enabled ) 434 return; 435 436 $show = eZDebug::showMessage( EZ_SHOW_WARNING ); 437 if ( !$alwaysLog and !$show ) 438 return; 439 440 if ( is_object( $string ) || is_array( $string ) ) 441 $string = eZDebug::dumpVariable( $string ); 442 443 $GLOBALS['eZDebugWarning'] = true; 444 if ( !isset( $GLOBALS['eZDebugWarningCount'] ) ) 445 $GLOBALS['eZDebugWarningCount'] = 0; 446 ++$GLOBALS['eZDebugWarningCount']; 447 448 $debug =& eZDebug::instance(); 449 if ( $debug->HandleType == EZ_HANDLE_TO_PHP ) 450 { 451 // If we get here only because of $alwaysLog we should not trigger a PHP error 452 if ( $enabled and $show ) 453 { 454 if ( $label ) 455 $string = "$label: $string"; 456 trigger_error( $string, E_USER_WARNING ); 457 } 458 } 459 else 460 { 461 $debug->write( $string, EZ_LEVEL_WARNING, $label, $backgroundClass, $alwaysLog ); 462 } 463 } 464 465 /*! 466 \static 467 Writes a debug error. 468 469 The global variable \c 'eZDebugError' will be set to \c true if the notice is added. 470 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 471 */ 472 function writeError( $string, $label = "", $backgroundClass = "" ) 473 { 474 $alwaysLog = eZDebug::alwaysLogMessage( EZ_LEVEL_ERROR ); 475 $enabled = eZDebug::isDebugEnabled(); 476 if ( !$alwaysLog and !$enabled ) 477 return; 478 479 $show = eZDebug::showMessage( EZ_SHOW_ERROR ); 480 if ( !$alwaysLog and !$show ) 481 return; 482 483 if ( is_object( $string ) || is_array( $string ) ) 484 $string = eZDebug::dumpVariable( $string ); 485 486 $GLOBALS['eZDebugError'] = true; 487 if ( !isset( $GLOBALS['eZDebugErrorCount'] ) ) 488 $GLOBALS['eZDebugErrorCount'] = 0; 489 ++$GLOBALS['eZDebugErrorCount']; 490 491 $debug =& eZDebug::instance(); 492 if ( $debug->HandleType == EZ_HANDLE_TO_PHP ) 493 { 494 // If we get here only because of $alwaysLog we should not trigger a PHP error 495 if ( $enabled and $show ) 496 { 497 if ( $label ) 498 $string = "$label: $string"; 499 trigger_error( $string, E_USER_ERROR ); 500 } 501 } 502 else 503 { 504 $debug->write( $string, EZ_LEVEL_ERROR, $label, $backgroundClass, $alwaysLog ); 505 } 506 } 507 508 /*! 509 \static 510 Writes a debug message. 511 512 The global variable \c 'eZDebugDebug' will be set to \c true if the notice is added. 513 \param $label This label will be associated with the notice, e.g. to say where the notice came from. 514 */ 515 function writeDebug( $string, $label = "", $backgroundClass = "" ) 516 { 517 $alwaysLog = eZDebug::alwaysLogMessage( EZ_LEVEL_DEBUG ); 518 $enabled = eZDebug::isDebugEnabled(); 519 if ( !$alwaysLog and !$enabled ) 520 return; 521 522 $show = eZDebug::showMessage( EZ_SHOW_DEBUG ); 523 if ( !$alwaysLog and !$show ) 524 return; 525 526 if ( is_object( $string ) || is_array( $string ) ) 527 $string = eZDebug::dumpVariable( $string ); 528 529 $GLOBALS['eZDebugDebug'] = true; 530 if ( !isset( $GLOBALS['eZDebugDebugCount'] ) ) 531 $GLOBALS['eZDebugDebugCount'] = 0; 532 ++$GLOBALS['eZDebugDebugCount']; 533 534 $debug =& eZDebug::instance(); 535 if ( $debug->HandleType == EZ_HANDLE_TO_PHP ) 536 { 537 // If we get here only because of $alwaysLog we should not trigger a PHP error 538 if ( $enabled and $show ) 539 { 540 if ( $label ) 541 $string = "$label: $string"; 542 trigger_error( $string, E_USER_NOTICE ); 543 } 544 } 545 else 546 { 547 $debug->write( $string, EZ_LEVEL_DEBUG, $label, $backgroundClass, $alwaysLog ); 548 } 549 } 550 551 /*! 552 \static 553 \private 554 Dumps the variables contents using the var_dump function 555 */ 556 function dumpVariable( $var ) 557 { 558 // If we have var_export (PHP >= 4.2.0) we use the instead 559 // provides better output, doesn't require output buffering 560 // and doesn't get mangled by Xdebug 561 562 // dl: we should always use 'var_dump' since 'var_export' is 563 // unable to handle recursion properly. 564 //if ( function_exists( 'var_export' ) ) 565 // return var_export( $var, true ); 566 567 ob_start(); 568 var_dump( $var ); 569 $variableContents = ''; 570 if ( extension_loaded( 'xdebug' ) ) 571 $variableContents = EZ_DEBUG_XDEBUG_SIGNATURE; 572 $variableContents .= ob_get_contents(); 573 ob_end_clean(); 574 return $variableContents; 575 } 576 577 /*! 578 Enables/disables the use of external CSS. If false a <style> tag is output 579 before the debug list. Default is to use internal css. 580 */ 581 function setUseExternalCSS( $use ) 582 { 583 if ( isset( $this ) and 584 get_class( $this ) == "ezdebug" ) 585 $instance =& $this; 586 else 587 $instance =& eZDebug::instance(); 588 $instance->UseCSS = $use; 589 } 590 591 /*! 592 Determines the way messages are output, the \a $output parameter 593 is EZ_OUTPUT_MESSAGE_SCREEN and EZ_OUTPUT_MESSAGE_STORE ored together. 594 */ 595 function setMessageOutput( $output ) 596 { 597 if ( isset( $this ) and 598 get_class( $this ) == "ezdebug" ) 599 $instance =& $this; 600 else 601 $instance =& eZDebug::instance(); 602 $instance->MessageOutput = $output; 603 } 604 605 /*! 606 */ 607 function setStoreLog( $store ) 608 { 609 if ( isset( $this ) and 610 get_class( $this ) == "ezdebug" ) 611 $instance =& $this; 612 else 613 $instance =& eZDebug::instance(); 614 $instance->StoreLog = $store; 615 } 616 617 /*! 618 Adds a new timing point for the benchmark report. 619 */ 620 function addTimingPoint( $description = "" ) 621 { 622 if ( !eZDebug::isDebugEnabled() ) 623 return; 624 if ( !eZDebug::showMessage( EZ_SHOW_TIMING_POINT ) ) 625 return; 626 $debug =& eZDebug::instance(); 627 628 $time = microtime(); 629 $usedMemory = 0; 630 if ( function_exists( "memory_get_usage" ) ) 631 $usedMemory = memory_get_usage(); 632 $tp = array( "Time" => $time, 633 "Description" => $description, 634 "MemoryUsage" => $usedMemory ); 635 $debug->TimePoints[] = $tp; 636 $desc = "Timing Point: $description"; 637 foreach ( array( EZ_LEVEL_NOTICE, EZ_LEVEL_WARNING, EZ_LEVEL_ERROR, EZ_LEVEL_DEBUG ) as $lvl ) 638 { 639 if ( isset( $debug->TmpTimePoints[$lvl] ) ) 640 $debug->TmpTimePoints[$lvl] = array(); 641 if ( $debug->TmpTimePoints[$lvl] === false and 642 $debug->isLogFileEnabled( $lvl ) ) 643 { 644 $files =& $debug->logFiles(); 645 $file = $files[$lvl]; 646 $debug->writeFile( $file, $desc, $lvl ); 647 } 648 else 649 array_push( $debug->TmpTimePoints[$lvl], $tp ); 650 } 651 $debug->write( $description, EZ_LEVEL_TIMING_POINT ); 652 } 653 654 /*! 655 \private 656 Writes a debug log message. 657 */ 658 function write( $string, $verbosityLevel = EZ_LEVEL_NOTICE, $label = "", $backgroundClass = "", $alwaysLog = false ) 659 { 660 $enabled = eZDebug::isDebugEnabled(); 661 if ( !$alwaysLog and !$enabled ) 662 return; 663 switch ( $verbosityLevel ) 664 { 665 case EZ_LEVEL_NOTICE: 666 case EZ_LEVEL_WARNING: 667 case EZ_LEVEL_ERROR: 668 case EZ_LEVEL_DEBUG: 669 case EZ_LEVEL_TIMING_POINT: 670 break; 671 672 default: 673 $verbosityLevel = EZ_LEVEL_ERROR; 674 break; 675 } 676 if ( $this->MessageOutput & EZ_OUTPUT_MESSAGE_SCREEN and $enabled ) 677 { 678 print( "$verbosityLevel: $string ($label)\n" ); 679 } 680 $files =& $this->logFiles(); 681 $fileName = false; 682 if ( isset( $files[$verbosityLevel] ) ) 683 $fileName = $files[$verbosityLevel]; 684 if ( $this->MessageOutput & EZ_OUTPUT_MESSAGE_STORE or $alwaysLog ) 685 { 686 if ( ! eZDebug::isLogOnlyEnabled() and $enabled ) 687 { 688 $ip = eZSys::serverVariable( 'REMOTE_ADDR', true ); 689 if ( !$ip ) 690 $ip = eZSys::serverVariable( 'HOSTNAME', true ); 691 $this->DebugStrings[] = array( "Level" => $verbosityLevel, 692 "IP" => $ip, 693 "Time" => time(), 694 "Label" => $label, 695 "String" => $string, 696 "BackgroundClass" => $backgroundClass ); 697 } 698 699 if ( $fileName !== false ) 700 { 701 $timePoints = $this->TmpTimePoints[$verbosityLevel]; 702 if ( is_array( $timePoints ) ) 703 { 704 if ( $this->isLogFileEnabled( $verbosityLevel ) ) 705 { 706 foreach ( $timePoints as $tp ) 707 { 708 $desc = "Timing Point: " . $tp["Description"]; 709 if ( $this->isLogFileEnabled( $verbosityLevel ) ) 710 { 711 $this->writeFile( $fileName, $desc, $verbosityLevel, $alwaysLog ); 712 } 713 } 714 } 715 $this->TmpTimePoints[$verbosityLevel] = false; 716 } 717 if ( $this->isLogFileEnabled( $verbosityLevel ) ) 718 { 719 $string = "$label:\n$string"; 720 $this->writeFile( $fileName, $string, $verbosityLevel, $alwaysLog ); 721 } 722 } 723 } 724 } 725 726 /*! 727 \static 728 \return the maxium size for a log file in bytes. 729 */ 730 function maxLogSize() 731 { 732 $maxLogSize =& $GLOBALS['eZDebugMaxLogSize']; 733 if ( isset( $maxLogSize ) ) 734 return $maxLogSize; 735 return EZ_DEBUG_MAX_LOGFILE_SIZE; 736 } 737 738 /*! 739 \static 740 Sets the maxium size for a log file to \a $size. 741 */ 742 function setMaxLogSize( $size ) 743 { 744 $GLOBALS['eZDebugMaxLogSize'] = $size; 745 } 746 747 /*! 748 \static 749 \return the maxium number of logrotate files to keep. 750 */ 751 function maxLogrotateFiles() 752 { 753 $maxLogrotateFiles =& $GLOBALS['eZDebugMaxLogrotateFiles']; 754 if ( isset( $maxLogrotateFiles ) ) 755 return $maxLogrotateFiles; 756 return EZ_DEBUG_MAX_LOGROTATE_FILES; 757 } 758 759 /*! 760 \static 761 Sets the maxium number of logrotate files to keep to \a $files. 762 */ 763 function setLogrotateFiles( $files ) 764 { 765 $GLOBALS['eZDebugMaxLogrotateFiles'] = $filse; 766 } 767 768 /*! 769 \static 770 Rotates logfiles so the current logfile is backed up, 771 old rotate logfiles are rotated once more and those that 772 exceed maxLogrotateFiles() will be removed. 773 Rotated files will get the extension .1, .2 etc. 774 */ 775 function rotateLog( $fileName ) 776 { 777 $maxLogrotateFiles = eZDebug::maxLogrotateFiles(); 778 for ( $i = $maxLogrotateFiles; $i > 0; --$i ) 779 { 780 $logRotateName = $fileName . '.' . $i; 781 if ( @file_exists( $logRotateName ) ) 782 { 783 if ( $i == $maxLogrotateFiles ) 784 { 785 @unlink( $logRotateName ); 786 // print( "@unlink( $logRotateName )<br/>" ); 787 } 788 else 789 { 790 $newLogRotateName = $fileName . '.' . ($i + 1); 791 @rename( $logRotateName, $newLogRotateName ); 792 // print( "@rename( $logRotateName, $newLogRotateName )<br/>" ); 793 } 794 } 795 } 796 if ( @file_exists( $fileName ) ) 797 { 798 $newLogRotateName = $fileName . '.' . 1; 799 @rename( $fileName, $newLogRotateName ); 800 // print( "@rename( $fileName, $newLogRotateName )<br/>" ); 801 return true; 802 } 803 return false; 804 } 805 806 /*! 807 \private 808 Writes the log message $string to the file $fileName. 809 */ 810 function writeFile( &$logFileData, &$string, $verbosityLevel, $alwaysLog = false ) 811 { 812 $enabled = eZDebug::isDebugEnabled(); 813 if ( !$alwaysLog and !$enabled ) 814 return; 815 if ( !$alwaysLog and !$this->isLogFileEnabled( $verbosityLevel ) ) 816 return; 817 $oldHandleType = eZDebug::setHandleType( EZ_HANDLE_TO_PHP ); 818 $logDir = $logFileData[0]; 819 $logName = $logFileData[1]; 820 $fileName = $logDir . $logName; 821 if ( !file_exists( $logDir ) ) 822 { 823 include_once ( 'lib/ezfile/classes/ezdir.php' ); 824 eZDir::mkdir( $logDir, 0775, true ); 825 } 826 $oldumask = @umask( 0 ); 827 $fileExisted = @file_exists( $fileName ); 828 if ( $fileExisted and 829 filesize( $fileName ) > eZDebug::maxLogSize() ) 830 { 831 if ( eZDebug::rotateLog( $fileName ) ) 832 $fileExisted = false; 833 } 834 $logFile = @fopen( $fileName, "a" ); 835 if ( $logFile ) 836 { 837 $time = strftime( "%b %d %Y %H:%M:%S", strtotime( "now" ) ); 838 $ip = eZSys::serverVariable( 'REMOTE_ADDR', true ); 839 if ( !$ip ) 840 $ip = eZSys::serverVariable( 'HOSTNAME', true ); 841 $notice = "[ " . $time . " ] [" . $ip . "] " . $string . "\n"; 842 @fwrite( $logFile, $notice ); 843 @fclose( $logFile ); 844 if ( !$fileExisted ) 845 @chmod( $fileName, 0664 ); 846 @umask( $oldumask ); 847 } 848 else 849 { 850 @umask( $oldumask ); 851 $logEnabled = $this->isLogFileEnabled( $verbosityLevel ); 852 $this->setLogFileEnabled( false, $verbosityLevel ); 853 if ( $verbosityLevel != EZ_LEVEL_ERROR or 854 $logEnabled ) 855 { 856 eZDebug::setHandleType( $oldHandleType ); 857 $this->writeError( "Cannot open log file '$fileName' for writing\n" . 858 "The web server must be allowed to modify the file.\n" . 859 "File logging for '$fileName' is disabled." , 'eZDebug::writeFile' ); 860 } 861 } 862 eZDebug::setHandleType( $oldHandleType ); 863 } 864 865 /*! 866 \static 867 Enables or disables logging to file for a given message type. 868 If \a $types is not supplied it will do the operation for all types. 869 */ 870 function setLogFileEnabled( $enabled, $types = false ) 871 { 872 if ( isset( $this ) and 873 get_class( $this ) == "ezdebug" ) 874 $instance =& $this; 875 else 876 $instance =& eZDebug::instance(); 877 if ( $types === false ) 878 $types = $instance->messageTypes(); 879 if ( !is_array( $types ) ) 880 $types = array( $types ); 881 foreach ( $types as $type ) 882 { 883 $instance->LogFileEnabled[$type] = $enabled; 884 } 885 } 886 887 /*! 888 \return true if the message type \a $type has logging to file enabled. 889 \sa isGlobalLogFileEnabled, setIsLogFileEnabled 890 */ 891 function isLogFileEnabled( $type ) 892 { 893 if ( !$this->isGlobalLogFileEnabled() ) 894 return false; 895 return $this->LogFileEnabled[$type]; 896 } 897 898 /*! 899 \return true if the message type \a $type has logging to file enabled. 900 \sa isLogFileEnabled, setIsGlobalLogFileEnabled 901 */ 902 function isGlobalLogFileEnabled() 903 { 904 return $this->GlobalLogFileEnabled; 905 } 906 907 /*! 908 Sets whether the logfile \a $type is enabled or disabled to \a $enabled. 909 \sa isLogFileEnabled 910 */ 911 function setIsLogFileEnabled( $type, $enabled ) 912 { 913 $this->LogFileEnabled[$type] = $enabled; 914 } 915 916 /*! 917 Sets whether logfiles are enabled or disabled globally. Sets the value to \a $enabled. 918 \sa isLogFileEnabled, isGlobalLogFileEnabled 919 */ 920 function setIsGlobalLogFileEnabled( $enabled ) 921 { 922 $this->GlobalLogFileEnabled = $enabled; 923 } 924 925 /*! 926 Sets whether debug output should be logged only 927 */ 928 function setLogOnly( $enabled ) 929 { 930 $GLOBALS['eZDebugLogOnly'] = $enabled; 931 } 932 933 /*! 934 \return an array with the available message types. 935 */ 936 function messageTypes() 937 { 938 return $this->MessageTypes; 939 } 940 941 /*! 942 Returns an associative array of all the log files used by this class 943 where each key is the debug level (EZ_LEVEL_NOTICE, EZ_LEVEL_WARNING or EZ_LEVEL_ERROR or EZ_LEVEL_DEBUG). 944 */ 945 function &logFiles() 946 { 947 return $this->LogFiles; 948 } 949 950 /*! 951 \static 952 \return true if debug should be enabled. 953 \note Will return false until the real settings has been updated with updateSettings() 954 */ 955 function isDebugEnabled() 956 { 957 if ( isset( $GLOBALS['eZDebugEnabled'] ) ) 958 { 959 return $GLOBALS['eZDebugEnabled']; 960 } 961 962 return false; 963 } 964 965 /*! 966 \static 967 \return true if there should only be logging of debug strings to file. 968 \note Will return false until the real settings has been updated with updateSettings() 969 */ 970 function isLogOnlyEnabled() 971 { 972 if ( isset( $GLOBALS['eZDebugLogOnly'] ) ) 973 { 974 return $GLOBALS['eZDebugLogOnly']; 975 } 976 977 return false; 978 } 979 980 /*! 981 \static 982 Determine if an ipaddress is in a network. E.G. 120.120.120.120 in 120.120.0.0/24. 983 \return true or false. 984 */ 985 function isIPInNet( $ipaddress, $network, $mask = 24 ) 986 { 987 $lnet = ip2long( $network ); 988 $lip = ip2long( $ipaddress ); 989 $binnet = str_pad( decbin( $lnet ), 32, "0", "STR_PAD_LEFT" ); 990 $firstpart = substr($binnet,0,$mask); 991 $binip = str_pad( decbin( $lip ), 32, "0", "STR_PAD_LEFT" ); 992 $firstip = substr( $binip, 0, $mask ); 993 return( strcmp( $firstpart, $firstip ) == 0 ); 994 } 995 996 /*! 997 \static 998 Updates the settings for debug handling with the settings array \a $settings. 999 The array must contain the following keys. 1000 - debug-enabled - boolean which controls debug handling 1001 - debug-by-ip - boolean which controls IP controlled debugging 1002 - debug-ip-list - array of IPs which gets debug 1003 - debug-by-user - boolean which controls userID controlled debugging 1004 - debug-user-list - array of UserIDs which gets debug 1005 */ 1006 function updateSettings( $settings ) 1007 { 1008 // Make sure errors are handled by PHP when we read, including our own debug output. 1009 $oldHandleType = eZDebug::setHandleType( EZ_HANDLE_TO_PHP ); 1010 1011 $debugEnabled =& $GLOBALS['eZDebugEnabled']; 1012 if ( isset( $settings['debug-log-files-enabled'] ) ) 1013 { 1014 $GLOBALS['eZDebugLogFileEnabled'] = $settings['debug-log-files-enabled']; 1015 if ( isset( $GLOBALS["eZDebugGlobalInstance"] ) ) 1016 $GLOBALS["eZDebugGlobalInstance"]->GlobalLogFileEnabled = $settings['debug-log-files-enabled']; 1017 } 1018 1019 if ( isset( $settings['debug-styles'] ) ) 1020 { 1021 $GLOBALS['eZDebugStyles'] = $settings['debug-styles']; 1022 } 1023 1024 if ( isset( $settings['always-log'] ) and 1025 is_array( $settings['always-log'] ) ) 1026 { 1027 $GLOBALS['eZDebugAlwaysLog'] = $settings['always-log']; 1028 } 1029 1030 if ( isset( $settings['log-only'] ) ) 1031 { 1032 $GLOBALS['eZDebugLogOnly'] = ( $settings['log-only'] == 'enabled' ); 1033 } 1034 1035 $notDebugByIP = true; 1036 $debugEnabled = $settings['debug-enabled']; 1037 if ( $settings['debug-enabled'] and 1038 $settings['debug-by-ip'] ) 1039 { 1040 $ipAddress = eZSys::serverVariable( 'REMOTE_ADDR', true ); 1041 if ( $ipAddress ) 1042 { 1043 $debugEnabled = false; 1044 foreach( $settings['debug-ip-list'] as $itemToMatch ) 1045 { 1046 if ( preg_match("/^(([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+))(\/([0-9]+)$|$)/", $itemToMatch, $matches ) ) 1047 { 1048 if ( $matches[6] ) 1049 { 1050 if ( eZDebug::isIPInNet( $ipAddress, $matches[1], $matches[7])) 1051 { 1052 $debugEnabled = true; 1053 $notDebugByIP = false; 1054 break; 1055 } 1056 } 1057 else 1058 { 1059 if ( $matches[1] == $ipAddress ) 1060 { 1061 $debugEnabled = true; 1062 $notDebugByIP = false; 1063 break; 1064 } 1065 } 1066 } 1067 } 1068 } 1069 else 1070 { 1071 $debugEnabled = ( 1072 in_array( 'commandline', $settings['debug-ip-list'] ) && 1073 ( php_sapi_name() == 'cli' ) 1074 ); 1075 } 1076 } 1077 if ( $settings['debug-enabled'] and 1078 isset( $settings['debug-by-user'] ) and 1079 $settings['debug-by-user'] and 1080 $notDebugByIP ) 1081 { 1082 $debugUserIDList = $settings['debug-user-list'] ? $settings['debug-user-list'] : array(); 1083 $GLOBALS['eZDebugUserIDList'] = $debugUserIDList; 1084 // We enable the debug temporarily. 1085 // In checkDebugByUser() will be last(final) check for debug by user id. 1086 $debugEnabled = true; 1087 } 1088 1089 eZDebug::setHandleType( $oldHandleType ); 1090 } 1091 1092 /*! 1093 \static 1094 Final checking for debug by user id. 1095 Checks if we should enable debug. 1096 */ 1097 function checkDebugByUser() 1098 { 1099 $debugUserIDList = isset( $GLOBALS['eZDebugUserIDList'] ) ? $GLOBALS['eZDebugUserIDList'] : false; 1100 1101 if ( $debugUserIDList === false ) 1102 return false; 1103 1104 $debugEnabled =& $GLOBALS['eZDebugEnabled']; 1105 if ( count( $debugUserIDList ) == 0 ) 1106 { 1107 // We should set previous value. 1108 $debugEnabled = false; 1109 return false; 1110 } 1111 1112 if ( include_once ( "kernel/classes/datatypes/ezuser/ezuser.php" ) ) 1113 $currentUserID = eZUser::currentUserID(); 1114 1115 $debugEnabled = $currentUserID ? in_array( $currentUserID, $debugUserIDList ) : $debugEnabled; 1116 1117 unset( $GLOBALS['eZDebugUserIDList'] ); 1118 } 1119 1120 /*! 1121 \static 1122 Prints the debug report 1123 */ 1124 function printReport( $newWindow = false, $as_html = true, $returnReport = false, 1125 $allowedDebugLevels = false, $useAccumulators = true, $useTiming = true, $useIncludedFiles = false ) 1126 { 1127 if ( !eZDebug::isDebugEnabled() ) 1128 return null; 1129 1130 $debug =& eZDebug::instance(); 1131 $report = $debug->printReportInternal( $as_html, $returnReport & $newWindow, $allowedDebugLevels, $useAccumulators, $useTiming, $useIncludedFiles ); 1132 1133 if ( $newWindow == true ) 1134 { 1135 $debugFilePath = eZDir::path( array( eZSys::varDirectory(), 'cache', 'debug.html' ) ); 1136 print( " 1137 <SCRIPT LANGUAGE='JavaScript'> 1138 <!-- hide this script from old browsers 1139 1140 function showDebug() 1141 { 1142 var debugWindow; 1143 1144 if (navigator.appName == \"Microsoft Internet Explorer\") 1145 { 1146 //Microsoft Internet Explorer 1147 debugWindow = window.open( '/$debugFilePath', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40'); 1148 debugWindow.document.close(); 1149 debugWindow.location.reload(); 1150 } 1151 else if (navigator.appName == \"Opera\") 1152 { 1153 //Opera 1154 debugWindow = window.open( '', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40'); 1155 debugWindow.location.href=\"/$debugFilePath\"; 1156 debugWindow.navigate(\"/$debugFilePath\"); 1157 } 1158 else 1159 { 1160 //Mozilla, Firefox, etc. 1161 debugWindow = window.open( '', 'ezdebug', 'width=500,height=550,status,scrollbars,resizable,screenX=0,screenY=20,left=20,top=40'); 1162 debugWindow.document.location.href=\"/$debugFilePath\"; 1163 }; 1164 } 1165 1166 showDebug(); 1167 1168 // done hiding from old browsers --> 1169 </SCRIPT> 1170 " ); 1171 $header = "<html><head><title>eZ debug</title></head><body>"; 1172 $footer = "</body></html>"; 1173 $fp = fopen( $debugFilePath, "w+" ); 1174 1175 fwrite( $fp, $header ); 1176 fwrite( $fp, $report ); 1177 fwrite( $fp, $footer ); 1178 fclose( $fp ); 1179 } 1180 else 1181 { 1182 if ( $returnReport ) 1183 return $report; 1184 } 1185 return null; 1186 } 1187 1188 /*! 1189 \private 1190 Returns the microtime as a float value. $mtime must be in microtime() format. 1191 */ 1192 function timeToFloat( $mtime ) 1193 { 1194 $tTime = explode( " ", $mtime ); 1195 ereg( "0\.([0-9]+)", "" . $tTime[0], $t1 ); 1196 $time = $tTime[1] . "." . $t1[1]; 1197 return $time; 1198 } 1199 1200 /*! 1201 Sets the time of the start of the script ot \a $mtime. 1202 If \a $mtime is not supplied it gets the current \c microtime(). 1203 This is used to calculate total execution time and percentages. 1204 */ 1205 function setScriptStart( $mtime = false ) 1206 { 1207 if ( $mtime == false ) 1208 $mtime = microtime(); 1209 $time = eZDebug::timeToFloat( microtime() ); 1210 $debug =& eZDebug::instance(); 1211 $debug->ScriptStart = $time; 1212 } 1213 1214 /*! 1215 Creates an accumulator group with key \a $key and group name \a $name. 1216 If \a $name is not supplied name is taken from \a $key. 1217 */ 1218 function createAccumulatorGroup( $key, $name = false ) 1219 { 1220 if ( !eZDebug::isDebugEnabled() ) 1221 return; 1222 if ( $name == '' or 1223 $name === false ) 1224 $name = $key; 1225 $debug =& eZDebug::instance(); 1226 if ( !array_key_exists( $key, $debug->TimeAccumulatorList ) ) 1227 $debug->TimeAccumulatorList[$key] = array( 'name' => $name, 'time' => 0, 'count' => 0, 'is_group' => true, 'in_group' => false ); 1228 if ( !array_key_exists( $key, $debug->TimeAccumulatorGroupList ) ) 1229 $debug->TimeAccumulatorGroupList[$key] = array(); 1230 } 1231 1232 /*! 1233 Creates a new accumulator entry if one does not already exist and initializes with default data. 1234 If \a $name is not supplied name is taken from \a $key. 1235 If \a $inGroup is supplied it will place the accumulator under the specified group. 1236 */ 1237 function createAccumulator( $key, $inGroup = false, $name = false ) 1238 { 1239 if ( !eZDebug::isDebugEnabled() ) 1240 return; 1241 if ( $name == '' or 1242 $name === false ) 1243 $name = $key; 1244 $debug =& eZDebug::instance(); 1245 $isGroup = false; 1246 if ( array_key_exists( $key, $debug->TimeAccumulatorList ) and 1247 array_key_exists( $key, $debug->TimeAccumulatorGroupList ) ) 1248 $isGroup = true; 1249 $debug->TimeAccumulatorList[$key] = array( 'name' => $name, 'time' => 0, 'count' => 0, 'is_group' => $isGroup, 'in_group' => $inGroup ); 1250 if ( $inGroup !== false ) 1251 { 1252 $groupKeys = array(); 1253 if ( array_key_exists( $inGroup, $debug->TimeAccumulatorGroupList ) ) 1254 $groupKeys = $debug->TimeAccumulatorGroupList[$inGroup]; 1255 $debug->TimeAccumulatorGroupList[$inGroup] = array_unique( array_merge( $groupKeys, array( $key ) ) ); 1256 if ( array_key_exists( $inGroup, $debug->TimeAccumulatorList ) ) 1257 $debug->TimeAccumulatorList[$inGroup]['is_group'] = true; 1258 } 1259 } 1260 1261 /*! 1262 Starts an time count for the accumulator \a $key. 1263 You can also specify a name which will be displayed. 1264 */ 1265 function accumulatorStart( $key, $inGroup = false, $name = false, $recursive = false ) 1266 { 1267 if ( !eZDebug::isDebugEnabled() ) 1268 return; 1269 $debug =& eZDebug::instance(); 1270 $key = $key === false ? 'Default Debug-Accumulator' : $key; 1271 if ( ! array_key_exists( $key, $debug->TimeAccumulatorList ) ) 1272 { 1273 $debug->createAccumulator( $key, $inGroup, $name ); 1274 } 1275 1276 $accumulator =& $debug->TimeAccumulatorList[$key]; 1277 if ( $recursive ) 1278 { 1279 if ( isset( $accumulator['recursive_counter'] ) ) 1280 { 1281 $accumulator['recursive_counter']++; 1282 return; 1283 } 1284 $accumulator['recursive_counter'] = 0; 1285 } 1286 $accumulator['temp_time'] = $debug->timeToFloat( microtime() ); 1287 } 1288 1289 /*! 1290 Stops a previous time count and adds the total time to the accumulator \a $key. 1291 */ 1292 function accumulatorStop( $key, $recursive = false ) 1293 { 1294 if ( !eZDebug::isDebugEnabled() ) 1295 return; 1296 $debug =& eZDebug::instance(); 1297 $stopTime = $debug->timeToFloat( microtime() ); 1298 $key = $key === false ? 'Default Debug-Accumulator' : $key; 1299 if ( ! array_key_exists( $key, $debug->TimeAccumulatorList ) ) 1300 { 1301 eZDebug::writeWarning( 'Accumulator $key does not exists, run eZDebug::accumulatorStart first', 'eZDebug::accumulatorStop' ); 1302 return; 1303 } 1304 $accumulator =& $debug->TimeAccumulatorList[$key]; 1305 if ( $recursive ) 1306 { 1307 if ( isset( $accumulator['recursive_counter'] ) ) 1308 { 1309 if ( $accumulator['recursive_counter'] > 0 ) 1310 { 1311 $accumulator['recursive_counter']--; 1312 return; 1313 } 1314 } 1315 } 1316 $diffTime = $stopTime - $accumulator['temp_time']; 1317 $accumulator['time'] = $accumulator['time'] + $diffTime; 1318 ++$accumulator['count']; 1319 } 1320 1321 1322 /*! 1323 \private 1324 Prints a full debug report with notice, warnings, errors and a timing report. 1325 */ 1326 function printReportInternal( $as_html = true, $returnReport = true, $allowedDebugLevels = false, 1327 $useAccumulators = true, $useTiming = true, $useIncludedFiles = false ) 1328 { 1329 $styles = array( 'warning' => false, 1330 'warning-end' => false, 1331 'error' => false, 1332 'error-end' => false, 1333 'debug' => false, 1334 'debug-end' => false, 1335 'notice' => false, 1336 'notice-end' => false, 1337 'timing' => false, 1338 'timing-end' => false, 1339 'mark' => false, 1340 'mark-end' => false, 1341 'emphasize' => false, 1342 'emphasize-end' => false, 1343 'bold' => false, 1344 'bold-end' => false ); 1345 if ( isset( $GLOBALS['eZDebugStyles'] ) ) 1346 $styles = $GLOBALS['eZDebugStyles']; 1347 if ( !$allowedDebugLevels ) 1348 $allowedDebugLevels = array( EZ_LEVEL_NOTICE, EZ_LEVEL_WARNING, EZ_LEVEL_ERROR, 1349 EZ_LEVEL_DEBUG, EZ_LEVEL_TIMING_POINT ); 1350 $endTime = microtime(); 1351 1352 if ( $returnReport ) 1353 { 1354 ob_start(); 1355 } 1356 1357 if ( $as_html ) 1358 { 1359 echo "<table style='border: 1px dashed black;' bgcolor=\"#fefefe\">"; 1360 echo "<tr><th><h1>eZ debug</h1></th></tr>"; 1361 1362 echo "<tr><td>"; 1363 1364 if ( !$this->UseCSS ) 1365 { 1366 echo "<STYLE TYPE='text/css'> 1367 <!-- 1368 td.debugheader 1369 \{ 1370 background-color : #eeeeee; 1371 border-top : 1px solid #444488; 1372 border-bottom : 1px solid #444488; 1373 font-size : 65%; 1374 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 1375 \} 1376 1377 pre.debugtransaction 1378 \{ 1379 background-color : #f8f6d8; 1380 \} 1381 1382 td.timingpoint1 1383 \{ 1384 background-color : #ffffff; 1385 border-top : 1px solid #444488; 1386 font-size : 65%; 1387 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 1388 \} 1389 1390 td.timingpoint2 1391 \{ 1392 background-color : #eeeeee; 1393 border-top : 1px solid #444488; 1394 font-size : 65%; 1395 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 1396 \} 1397 1398 --> 1399 </STYLE>"; 1400 } 1401 echo "<table style='border: 1px lightgray;' cellspacing='0'>"; 1402 } 1403 1404 $this->printTopReportsList(); 1405 1406 $hasLevel = array( EZ_LEVEL_NOTICE => false, 1407 EZ_LEVEL_WARNING => false, 1408 EZ_LEVEL_ERROR => false, 1409 EZ_LEVEL_TIMING_POINT => false, 1410 EZ_LEVEL_DEBUG => false ); 1411 1412 foreach ( $this->DebugStrings as $debug ) 1413 { 1414 if ( !in_array( $debug['Level'], $allowedDebugLevels ) ) 1415 continue; 1416 $time = strftime ("%b %d %Y %H:%M:%S", strtotime( "now" ) ); 1417 1418 $outputData = $this->OutputFormat[$debug["Level"]]; 1419 if ( is_array( $outputData ) ) 1420 { 1421 $identifierText = ''; 1422 if ( !$hasLevel[$debug['Level']] ) 1423 { 1424 $hasLevel[$debug['Level']] = true; 1425 $identifierText = 'id="' . $outputData['xhtml-identifier'] . '"'; 1426 } 1427 $color = $outputData["color"]; 1428 $name = $outputData["name"]; 1429 $label = $debug["Label"]; 1430 $bgclass = $debug["BackgroundClass"]; 1431 $pre = ($bgclass != '' ? " class='$bgclass'" : ''); 1432 if ( $as_html ) 1433 { 1434 $label = htmlspecialchars( $label ); 1435 1436 $contents = ''; 1437 if ( extension_loaded( 'xdebug' ) && ( strncmp( EZ_DEBUG_XDEBUG_SIGNATURE, $debug['String'], strlen( EZ_DEBUG_XDEBUG_SIGNATURE ) ) === 0 ) ) 1438 $contents = substr( $debug['String'], strlen( EZ_DEBUG_XDEBUG_SIGNATURE ) ); 1439 else 1440 $contents = htmlspecialchars( $debug['String'] ); 1441 1442 echo "<tr><td class='debugheader' valign='top'$identifierText><b><font color=\"$color\">$name:</font> $label</b></td> 1443 <td class='debugheader' valign='top'>$time</td></tr> 1444 <tr><td colspan='2'><pre$pre>" . $contents . "</pre></td></tr>"; 1445 } 1446 else 1447 { 1448 echo $styles[$outputData['style']] . "$name:" . $styles[$outputData['style'].'-end'] . " "; 1449 echo $styles['bold'] . "($label)" . $styles['bold-end'] . "\n" . $debug["String"] . "\n\n"; 1450 } 1451 } 1452 flush(); 1453 } 1454 if ( $as_html ) 1455 { 1456 echo "</table>"; 1457 1458 echo "<h2>Timing points:</h2>"; 1459 echo "<table style='border: 1px dashed black;' cellspacing='0'><tr><th>Checkpoint</th><th>Elapsed</th><th>Rel. Elapsed</th><th>Memory</th><th>Rel. Memory</th></tr>"; 1460 } 1461 $startTime = false; 1462 $elapsed = 0.00; 1463 $relElapsed = 0.00; 1464 if ( $useTiming ) 1465 { 1466 for ( $i = 0; $i < count( $this->TimePoints ); ++$i ) 1467 { 1468 $point = $this->TimePoints[$i]; 1469 $nextPoint = false; 1470 if ( isset( $this->TimePoints[$i + 1] ) ) 1471 $nextPoint = $this->TimePoints[$i + 1]; 1472 $time = $this->timeToFloat( $point["Time"] ); 1473 $nextTime = false; 1474 if ( $nextPoint !== false ) 1475 $nextTime = $this->timeToFloat( $nextPoint["Time"] ); 1476 if ( $startTime === false ) 1477 $startTime = $time; 1478 $elapsed = $time - $startTime; 1479 $relElapsed = $nextTime - $time; 1480 1481 $memory = $point["MemoryUsage"]; 1482 $nextMemory = 0; 1483 // Calculate relative memory usage 1484 if ( $nextPoint !== false ) 1485 { 1486 $nextMemory = $nextPoint["MemoryUsage"]; 1487 $relMemory = $nextMemory - $memory; 1488 } 1489 1490 // Convert memeory usage to human readable 1491 $memory = number_format( $memory / 1024, $this->TimingAccuracy ) . "KB"; 1492 $relMemory = number_format( $relMemory / 1024, $this->TimingAccuracy ) . "KB"; 1493 1494 if ( $i % 2 == 0 ) 1495 $class = "timingpoint1"; 1496 else 1497 $class = "timingpoint2"; 1498 1499 if ( $as_html ) 1500 { 1501 echo "<tr><td class='$class'>" . $point["Description"] . "</td><td class='$class'>" . 1502 number_format( ( $elapsed ), $this->TimingAccuracy ) . " sec</td><td class='$class'>". 1503 ( empty( $nextPoint ) ? " " : number_format( ( $relElapsed ), $this->TimingAccuracy ) . " sec" ) . "</td>" 1504 . "<td class='$class'>" . $memory . "</td><td class='$class'>". $relMemory . "</td></tr>"; 1505 } 1506 else 1507 { 1508 echo $point["Description"] . ' ' . 1509 number_format( ( $elapsed ), $this->TimingAccuracy ) . " sec". 1510 ( empty( $nextPoint ) ? "" : number_format( ( $relElapsed ), $this->TimingAccuracy ) . " sec" ) . "\n"; 1511 } 1512 } 1513 1514 if ( count( $this->TimePoints ) > 0 ) 1515 { 1516 $tTime = explode( " ", $endTime ); 1517 ereg( "0\.([0-9]+)", "" . $tTime[0], $t1 ); 1518 $endTime = $tTime[1] . "." . $t1[1]; 1519 1520 $totalElapsed = $endTime - $startTime; 1521 1522 if ( $as_html ) 1523 { 1524 echo "<tr><td><b>Total runtime:</b></td><td><b>" . 1525 number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec</b></td><td></td></tr>"; 1526 } 1527 else 1528 { 1529 echo "Total runtime: " . 1530 number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec\n"; 1531 } 1532 } 1533 else 1534 { 1535 if ( $as_html ) 1536 echo "<tr><td> No timing points defined</td><td>"; 1537 else 1538 echo "No timing points defined\n"; 1539 } 1540 if ( function_exists('xdebug_peak_memory_usage') ) 1541 { 1542 $peakMemory = xdebug_peak_memory_usage(); 1543 if ( $as_html ) 1544 echo "<tr><td><b>Peak memory usage:</b></td><td><b>" . 1545 number_format( $peakMemory / 1024, $this->TimingAccuracy ) . "KB</b></td></tr>"; 1546 else 1547 echo "Peak memory usage: " . 1548 number_format( $peakMemory / 1024, $this->TimingAccuracy ) . "KB\n"; 1549 } 1550 } 1551 if ( $as_html ) 1552 { 1553 echo "</table>"; 1554 } 1555 1556 if ( $useIncludedFiles ) 1557 { 1558 if ( $as_html ) 1559 echo "<h2>Included files:</h2><table style='border: 1px dashed black;' cellspacing='0'><tr><th>File</th></tr>"; 1560 else 1561 echo $styles['emphasize'] . "Includes" . $styles['emphasize-end'] . "\n"; 1562 $phpFiles = get_included_files(); 1563 $j = 0; 1564 $currentPathReg = preg_quote( realpath( "." ) ); 1565 foreach ( $phpFiles as $phpFile ) 1566 { 1567 if ( preg_match( "#^$currentPathReg/(.+)$#", $phpFile, $matches ) ) 1568 $phpFile = $matches[1]; 1569 if ( $as_html ) 1570 { 1571 if ( $j % 2 == 0 ) 1572 $class = "timingpoint1"; 1573 else 1574 $class = "timingpoint2"; 1575 ++$j; 1576 echo "<tr><td class=\"$class\">$phpFile</td></tr>"; 1577 } 1578 else 1579 { 1580 echo "$phpFile\n"; 1581 } 1582 } 1583 if ( $as_html ) 1584 echo "</table>"; 1585 } 1586 1587 if ( $as_html ) 1588 { 1589 echo "<h2>Time accumulators:</h2>"; 1590 echo "<table style='border: 1px dashed black;' cellspacing='0'><tr><th> Accumulator</th><th> Elapsed</th><th> Percent</th><th> Count</th><th> Average</th></tr>"; 1591 $i = 0; 1592 } 1593 1594 $scriptEndTime = eZDebug::timeToFloat( microtime() ); 1595 $totalElapsed = $scriptEndTime - $this->ScriptStart; 1596 $timeList = $this->TimeAccumulatorList; 1597 $groups = $this->TimeAccumulatorGroupList; 1598 $groupList = array(); 1599 foreach ( $groups as $groupKey => $keyList ) 1600 { 1601 if ( count( $keyList ) == 0 and 1602 !array_key_exists( $groupKey, $timeList ) ) 1603 continue; 1604 $groupList[$groupKey] = array( 'name' => $groupKey ); 1605 if ( array_key_exists( $groupKey, $timeList ) ) 1606 { 1607 if ( $timeList[$groupKey]['time'] != 0 ) 1608 $groupList[$groupKey]['time_data'] = $timeList[$groupKey]; 1609 $groupList[$groupKey]['name'] = $timeList[$groupKey]['name']; 1610 unset( $timeList[$groupKey] ); 1611 } 1612 $groupChildren = array(); 1613 foreach ( $keyList as $timeKey ) 1614 { 1615 if ( array_key_exists( $timeKey, $timeList ) ) 1616 { 1617 $groupChildren[] = $timeList[$timeKey]; 1618 unset( $timeList[$timeKey] ); 1619 } 1620 } 1621 $groupList[$groupKey]['children'] = $groupChildren; 1622 } 1623 if ( count( $timeList ) > 0 ) 1624 { 1625 $groupList['general'] = array( 'name' => 'General', 1626 'children' => $timeList ); 1627 } 1628 1629 if ( $useAccumulators ) 1630 { 1631 $j = 0; 1632 foreach ( $groupList as $group ) 1633 { 1634 if ( $j % 2 == 0 ) 1635 $class = "timingpoint1"; 1636 else 1637 $class = "timingpoint2"; 1638 ++$j; 1639 $groupName = $group['name']; 1640 $groupChildren = $group['children']; 1641 if ( count( $groupChildren ) == 0 and 1642 !array_key_exists( 'time_data', $group ) ) 1643 continue; 1644 if ( $as_html ) 1645 echo "<tr><td class='$class'><b>$groupName</b></td>"; 1646 else 1647 echo "Group " . $styles['mark'] . "$groupName:" . $styles['mark-end'] . " "; 1648 if ( array_key_exists( 'time_data', $group ) ) 1649 { 1650 $groupData = $group['time_data']; 1651 $groupElapsed = number_format( ( $groupData['time'] ), $this->TimingAccuracy ); 1652 $groupPercent = number_format( ( $groupData['time'] * 100.0 ) / $totalElapsed, 1 ); 1653 $groupCount = $groupData['count']; 1654 $groupAverage = number_format( ( $groupData['time'] / $groupData['count'] ), $this->TimingAccuracy ); 1655 if ( $as_html ) 1656 { 1657 echo ( "<td class=\"$class\">$groupElapsed sec</td>". 1658 "<td class=\"$class\" align=\"right\"> $groupPercent%</td>". 1659 "<td class=\"$class\" align=\"right\"> $groupCount</td>". 1660 "<td class=\"$class\" align=\"right\"> $groupAverage sec</td>" ); 1661 } 1662 else 1663 { 1664 echo $styles['emphasize'] . "$groupElapsed" . $styles['emphasize-end'] . " sec ($groupPercent%), $groupAverage avg sec ($groupCount)"; 1665 } 1666 } 1667 else if ( $as_html ) 1668 { 1669 echo ( "<td class=\"$class\"></td>". 1670 "<td class=\"$class\"></td>". 1671 "<td class=\"$class\"></td>". 1672 "<td class=\"$class\"></td>" ); 1673 } 1674 if ( $as_html ) 1675 echo "</tr>"; 1676 else 1677 echo "\n"; 1678 1679 $i = 0; 1680 foreach ( $groupChildren as $child ) 1681 { 1682 $childName = $child['name']; 1683 $childElapsed = number_format( ( $child['time'] ), $this->TimingAccuracy ); 1684 $childPercent = number_format( ( $child['time'] * 100.0 ) / $totalElapsed, $this->PercentAccuracy ); 1685 $childCount = $child['count']; 1686 $childAverage = 0.0; 1687 if ( $childCount > 0 ) 1688 { 1689 $childAverage = $child['time'] / $childCount; 1690 } 1691 $childAverage = number_format( $childAverage, $this->PercentAccuracy ); 1692 1693 if ( $as_html ) 1694 { 1695 if ( $i % 2 == 0 ) 1696 $class = "timingpoint1"; 1697 else 1698 $class = "timingpoint2"; 1699 ++$i; 1700 1701 echo ( "<tr>" . 1702 "<td class=\"$class\">$childName</td>" . 1703 "<td class=\"$class\">$childElapsed sec</td>" . 1704 "<td class=\"$class\" align=\"right\">$childPercent%</td>" . 1705 "<td class=\"$class\" align=\"right\">$childCount</td>" . 1706 "<td class=\"$class\" align=\"right\">$childAverage sec</td>" . 1707 "</tr>" ); 1708 } 1709 else 1710 { 1711 echo "$childName: " . $styles['emphasize'] . $childElapsed . $styles['emphasize-end'] . " sec ($childPercent%), $childAverage avg sec ($childCount)\n"; 1712 } 1713 } 1714 } 1715 } 1716 if ( $as_html ) 1717 { 1718 echo "<tr><td><b>Total script time:</b></td><td><b>" . number_format( ( $totalElapsed ), $this->TimingAccuracy ) . " sec</b></td><td></td></tr>"; 1719 } 1720 else 1721 { 1722 echo "\nTotal script time: " . $styles['emphasize'] . number_format( ( $totalElapsed ), $this->TimingAccuracy ) . $styles['emphasize-end'] . " sec\n"; 1723 } 1724 1725 if ( $as_html ) 1726 { 1727 echo "</table>"; 1728 } 1729 1730 $this->printBottomReportsList(); 1731 1732 if ( $as_html ) 1733 { 1734 echo "</td></tr></table>"; 1735 } 1736 1737 if ( $returnReport ) 1738 { 1739 $returnText = ob_get_contents(); 1740 ob_end_clean(); 1741 return $returnText; 1742 } 1743 else 1744 { 1745 return NULL; 1746 } 1747 } 1748 1749 /*! 1750 Appends report to 'top' reports list. 1751 */ 1752 function appendTopReport( $reportName, &$reportContent ) 1753 { 1754 $debug =& eZDebug::instance(); 1755 $debug->topReportsList[$reportName] =& $reportContent; 1756 } 1757 1758 /*! 1759 Prints all 'top' reports 1760 */ 1761 function printTopReportsList() 1762 { 1763 $debug =& eZDebug::instance(); 1764 $reportNames = array_keys( $debug->topReportsList ); 1765 foreach ( $reportNames as $reportName ) 1766 { 1767 $reportContent =& $debug->topReportsList[$reportName]; 1768 echo $reportContent; 1769 } 1770 } 1771 1772 /*! 1773 Appends report to 'bottom' reports list. 1774 */ 1775 function appendBottomReport( $reportName, &$reportContent ) 1776 { 1777 $debug =& eZDebug::instance(); 1778 $debug->bottomReportsList[$reportName] =& $reportContent; 1779 } 1780 1781 /*! 1782 Prints all 'bottom' reports 1783 */ 1784 function printBottomReportsList() 1785 { 1786 $debug =& eZDebug::instance(); 1787 $reportNames = array_keys( $debug->bottomReportsList ); 1788 foreach ( $reportNames as $reportName ) 1789 { 1790 $reportContent =& $debug->bottomReportsList[$reportName]; 1791 echo $reportContent; 1792 } 1793 } 1794 1795 /// \privatesection 1796 /// String array containing the debug information 1797 var $DebugStrings = array(); 1798 1799 /// Array which contains the time points 1800 var $TimePoints = array(); 1801 1802 /// Array which contains the temporary time points 1803 var $TmpTimePoints; 1804 1805 /// Array wich contains time accumulators 1806 var $TimeAccumulatorList = array(); 1807 1808 /// Determines which debug messages should be shown 1809 var $ShowTypes; 1810 1811 /// Determines what to do with php errors, ignore, fetch or output 1812 var $HandleType; 1813 1814 /// An array of the outputformats for the different debug levels 1815 var $OutputFormat; 1816 1817 /// An array of logfiles used by the debug class with each key being the debug level 1818 var $LogFiles; 1819 1820 /// How many places behing . should be displayed when showing times 1821 var $TimingAccuracy = 4; 1822 1823 /// How many places behing . should be displayed when showing percentages 1824 var $PercentAccuracy = 4; 1825 1826 /// Whether to use external CSS or output own CSS. True if external is to be used. 1827 var $UseCSS; 1828 1829 /// Determines how messages are output (screen/log) 1830 var $MessageOutput; 1831 1832 /// A list of message types 1833 var $MessageTypes; 1834 1835 /// A map with message types and whether they should do file logging. 1836 var $LogFileEnabled; 1837 1838 /// Controls whether logfiles are used at all. 1839 var $GlobalLogFileEnabled; 1840 1841 /// The time when the script was started 1842 var $ScriptStart; 1843 1844 /// A list of override directories 1845 var $OverrideList; 1846 1847 /// A list of debug reports that appears at the bottom of debug output 1848 var $bottomReportsList; 1849 1850 /// A list of debug reports that appears at the top of debug output 1851 var $topReportsList; 1852 } 1853 1854 /*! 1855 Helper function for eZDebug, called whenever a PHP error occurs. 1856 The error is then handled by the eZDebug class. 1857 */ 1858 1859 function eZDebugErrorHandler( $errno, $errstr, $errfile, $errline ) 1860 { 1861 if ( $GLOBALS['eZDebugRecursionFlag'] ) 1862 { 1863 print( "Fatal debug error: A recursion in debug error handler was detected, aborting debug message.<br/>" ); 1864 $GLOBALS['eZDebugRecursionFlag'] = false; 1865 return; 1866 } 1867 if ( preg_match( "/variable(.*?)reference/", $errstr ) ) 1868 return; 1869 $GLOBALS['eZDebugRecursionFlag'] = true; 1870 $debug =& eZDebug::instance(); 1871 $debug->errorHandler( $errno, $errstr, $errfile, $errline ); 1872 $GLOBALS['eZDebugRecursionFlag'] = false; 1873 } 1874 $GLOBALS['eZDebugRecursionFlag'] = false; 1875 1876 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sat Feb 24 10:30:04 2007 | par Balluche grâce à PHPXref 0.7 |