From: Alexandre Emsenhuber Date: Sat, 25 Aug 2012 11:09:46 +0000 (+0200) Subject: Moved warning stuff into MWDebug class. X-Git-Tag: 1.31.0-rc.0~22568^2 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/comptes/ajouter.php?a=commitdiff_plain;h=5af21595121168fb29c4662f7d00226b3a1fe379;p=lhc%2Fweb%2Fwiklou.git Moved warning stuff into MWDebug class. - Group common code in one instead of doing checks one time in GlobalFunctions.php and another time in Debug.php - Remove the code catching the fact that a warning is due to a deprecation warning, no longer needed - Pass the caller offset from wfDeprecated() to MWDebug::deprecated(); this was breaking deprecation notices for global objects. - Changed PHP error level for deprecation notices (when $wgDevelopmentWarnings is set to true) from E_USER_NOTICE to E_USER_DEPRECATED since we now require PHP 5.3+ - Added E_USER_DEPRECATED to wfSuppressWarnings() and removed the check for the E_DEPRECATED constant being set now that we require PHP 5.3+ - Fixed MWDebugTest by calling wfSuppressWarnings() and wfRestoreWarnings() in setUp() and tearDown() Change-Id: I6810b57c90d384de55a2cf177047767cdb734f79 --- diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 328d429e43..4ff258d2d5 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1082,35 +1082,7 @@ function wfLogDBError( $text ) { * @return null */ function wfDeprecated( $function, $version = false, $component = false, $callerOffset = 2 ) { - static $functionsWarned = array(); - - MWDebug::deprecated( $function, $version, $component ); - - if ( !isset( $functionsWarned[$function] ) ) { - $functionsWarned[$function] = true; - - if ( $version ) { - global $wgDeprecationReleaseLimit; - - if ( $wgDeprecationReleaseLimit && $component === false ) { - # Strip -* off the end of $version so that branches can use the - # format #.##-branchname to avoid issues if the branch is merged into - # a version of MediaWiki later than what it was branched from - $comparableVersion = preg_replace( '/-.*$/', '', $version ); - - # If the comparableVersion is larger than our release limit then - # skip the warning message for the deprecation - if ( version_compare( $wgDeprecationReleaseLimit, $comparableVersion, '<' ) ) { - return; - } - } - - $component = $component === false ? 'MediaWiki' : $component; - wfWarn( "Use of $function was deprecated in $component $version.", $callerOffset ); - } else { - wfWarn( "Use of $function is deprecated.", $callerOffset ); - } - } + MWDebug::deprecated( $function, $version, $component, $callerOffset + 1 ); } /** @@ -1124,34 +1096,7 @@ function wfDeprecated( $function, $version = false, $component = false, $callerO * is true */ function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) { - global $wgDevelopmentWarnings; - - MWDebug::warning( $msg, $callerOffset + 2 ); - - $callers = wfDebugBacktrace(); - if ( isset( $callers[$callerOffset + 1] ) ) { - $callerfunc = $callers[$callerOffset + 1]; - $callerfile = $callers[$callerOffset]; - if ( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ) { - $file = $callerfile['file'] . ' at line ' . $callerfile['line']; - } else { - $file = '(internal function)'; - } - $func = ''; - if ( isset( $callerfunc['class'] ) ) { - $func .= $callerfunc['class'] . '::'; - } - if ( isset( $callerfunc['function'] ) ) { - $func .= $callerfunc['function']; - } - $msg .= " [Called from $func in $file]"; - } - - if ( $wgDevelopmentWarnings ) { - trigger_error( $msg, $level ); - } else { - wfDebug( "$msg\n" ); - } + MWDebug::warning( $msg, $callerOffset + 1, $level ); } /** @@ -2383,11 +2328,7 @@ function wfSuppressWarnings( $end = false ) { } } else { if ( !$suppressCount ) { - // E_DEPRECATED is undefined in PHP 5.2 - if( !defined( 'E_DEPRECATED' ) ) { - define( 'E_DEPRECATED', 8192 ); - } - $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED ) ); + $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED ) ); } ++$suppressCount; } diff --git a/includes/debug/Debug.php b/includes/debug/Debug.php index 0b623e621d..d02bcf53b5 100644 --- a/includes/debug/Debug.php +++ b/includes/debug/Debug.php @@ -133,70 +133,156 @@ class MWDebug { * Adds a warning entry to the log * * @since 1.19 - * @param $msg - * @param int $callerOffset + * @param $msg string + * @param $callerOffset int * @return mixed */ - public static function warning( $msg, $callerOffset = 1 ) { - if ( !self::$enabled ) { - return; - } + public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) { + $callerDescription = self::getCallerDescription( $callerOffset ); - // Check to see if there was already a deprecation notice, so not to - // get a duplicate warning - $logCount = count( self::$log ); - $caller = wfGetCaller( $callerOffset + 1 ); - if ( $logCount ) { - $lastLog = self::$log[ $logCount - 1 ]; - if ( $lastLog['type'] == 'deprecated' && $lastLog['caller'] == $caller ) { - return; - } - } + self::sendWarning( $msg, $callerDescription, $level ); - self::$log[] = array( - 'msg' => htmlspecialchars( $msg ), - 'type' => 'warn', - 'caller' => $caller, - ); + if ( self::$enabled ) { + self::$log[] = array( + 'msg' => htmlspecialchars( $msg ), + 'type' => 'warn', + 'caller' => $callerDescription['func'], + ); + } } /** - * Adds a depreciation entry to the log, along with a backtrace + * Show a warning that $function is deprecated. + * This will send it to the following locations: + * - Debug toolbar, with one item per function and caller, if $wgDebugToolbar + * is set to true. + * - PHP's error log, with level E_USER_DEPRECATED, if $wgDevelopmentWarnings + * is set to true. + * - MediaWiki's debug log, if $wgDevelopmentWarnings is set to false. * * @since 1.19 - * @param $function - * @param $version - * @param $component + * @param $function string: Function that is deprecated. + * @param $version string|bool: Version in which the function was deprecated. + * @param $component string|bool: Component to which the function belongs. + * If false, it is assumbed the function is in MediaWiki core. + * @param $callerOffset integer: How far up the callstack is the original + * caller. 2 = function that called the function that called + * MWDebug::deprecated() (Added in 1.20). * @return mixed */ - public static function deprecated( $function, $version, $component ) { - if ( !self::$enabled ) { - return; - } + public static function deprecated( $function, $version = false, $component = false, $callerOffset = 2 ) { + $callerDescription = self::getCallerDescription( $callerOffset ); + $callerFunc = $callerDescription['func']; - // Chain: This function -> wfDeprecated -> deprecatedFunction -> caller - $caller = wfGetCaller( 4 ); + $sendToLog = true; // Check to see if there already was a warning about this function - $functionString = "$function-$caller"; - if ( in_array( $functionString, self::$deprecationWarnings ) ) { + if ( isset( self::$deprecationWarnings[$function][$callerFunc] ) ) { return; + } elseif ( isset( self::$deprecationWarnings[$function] ) ) { + if ( self::$enabled ) { + $sendToLog = false; + } else { + return; + } } - $version = $version === false ? '(unknown version)' : $version; - $component = $component === false ? 'MediaWiki' : $component; - $msg = htmlspecialchars( "Use of function $function was deprecated in $component $version" ); - $msg .= Html::rawElement( 'div', array( 'class' => 'mw-debug-backtrace' ), - Html::element( 'span', array(), 'Backtrace:' ) - . wfBacktrace() - ); + self::$deprecationWarnings[$function][$callerFunc] = true; - self::$deprecationWarnings[] = $functionString; - self::$log[] = array( - 'msg' => $msg, - 'type' => 'deprecated', - 'caller' => $caller, - ); + if ( $version ) { + global $wgDeprecationReleaseLimit; + if ( $wgDeprecationReleaseLimit && $component === false ) { + # Strip -* off the end of $version so that branches can use the + # format #.##-branchname to avoid issues if the branch is merged into + # a version of MediaWiki later than what it was branched from + $comparableVersion = preg_replace( '/-.*$/', '', $version ); + + # If the comparableVersion is larger than our release limit then + # skip the warning message for the deprecation + if ( version_compare( $wgDeprecationReleaseLimit, $comparableVersion, '<' ) ) { + $sendToLog = false; + } + } + + $component = $component === false ? 'MediaWiki' : $component; + $msg = "Use of $function was deprecated in $component $version."; + } else { + $msg = "Use of $function is deprecated."; + } + + if ( $sendToLog ) { + self::sendWarning( $msg, $callerDescription, E_USER_DEPRECATED ); + } + + if ( self::$enabled ) { + $logMsg = htmlspecialchars( $msg ) . + Html::rawElement( 'div', array( 'class' => 'mw-debug-backtrace' ), + Html::element( 'span', array(), 'Backtrace:' ) . wfBacktrace() + ); + + self::$log[] = array( + 'msg' => $logMsg, + 'type' => 'deprecated', + 'caller' => $callerFunc, + ); + } + } + + /** + * Get an array describing the calling function at a specified offset. + * + * @param $callerOffset integer: How far up the callstack is the original + * caller. 0 = function that called getCallerDescription() + * @return array with two keys: 'file' and 'func' + */ + private static function getCallerDescription( $callerOffset ) { + $callers = wfDebugBacktrace(); + + if ( isset( $callers[$callerOffset] ) ) { + $callerfile = $callers[$callerOffset]; + if ( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ) { + $file = $callerfile['file'] . ' at line ' . $callerfile['line']; + } else { + $file = '(internal function)'; + } + } else { + $file = '(unknown location)'; + } + + if ( isset( $callers[$callerOffset + 1] ) ) { + $callerfunc = $callers[$callerOffset + 1]; + $func = ''; + if ( isset( $callerfunc['class'] ) ) { + $func .= $callerfunc['class'] . '::'; + } + if ( isset( $callerfunc['function'] ) ) { + $func .= $callerfunc['function']; + } + } else { + $func = 'unknown'; + } + + return array( 'file' => $file, 'func' => $func ); + } + + /** + * Send a warning either to the debug log or by triggering an user PHP + * error depending on $wgDevelopmentWarnings. + * + * @param $msg string Message to send + * @param $caller array caller description get from getCallerDescription() + * @param $level error level to use if $wgDevelopmentWarnings is true + */ + private static function sendWarning( $msg, $caller, $level ) { + global $wgDevelopmentWarnings; + + $msg .= ' [Called from ' . $caller['func'] . ' in ' . $caller['file'] . ']'; + + if ( $wgDevelopmentWarnings ) { + trigger_error( $msg, $level ); + } else { + wfDebug( "$msg\n" ); + } } /** diff --git a/tests/phpunit/includes/debug/MWDebugTest.php b/tests/phpunit/includes/debug/MWDebugTest.php index 1627c47358..246b2918cf 100644 --- a/tests/phpunit/includes/debug/MWDebugTest.php +++ b/tests/phpunit/includes/debug/MWDebugTest.php @@ -12,6 +12,11 @@ class MWDebugTest extends MediaWikiTestCase { } /** Clear log before each test */ MWDebug::clearLog(); + wfSuppressWarnings(); + } + + function tearDown() { + wfRestoreWarnings(); } function testAddLog() {