27use Wikimedia\WrappedString;
28use Wikimedia\WrappedStringList;
47 protected static $log = [];
86 public static function setup() {
113 public static function init() {
114 self::$enabled =
true;
123 self::$enabled =
false;
134 if ( self::$enabled ) {
145 public static function log( $str ) {
146 if ( !self::$enabled ) {
149 if ( !is_string( $str ) ) {
150 $str = print_r( $str,
true );
153 'msg' => htmlspecialchars( $str ),
174 self::$deprecationWarnings = [];
188 public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE, $log =
'auto' ) {
195 if (
$log ===
'debug' ) {
199 $callerDescription = self::getCallerDescription( $callerOffset );
202 self::formatCallerDescription( $msg, $callerDescription ),
206 if ( self::$enabled ) {
208 'msg' => htmlspecialchars( $msg ),
210 'caller' => $callerDescription[
'func'],
229 public static function deprecated( $function, $version =
false,
230 $component =
false, $callerOffset = 2
233 $component = $component ?:
'MediaWiki';
234 $msg =
"Use of $function was deprecated in $component $version.";
236 $msg =
"Use of $function is deprecated.";
238 self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 );
264 $component =
false, $callerOffset = 2
266 $reflectionMethod =
new ReflectionMethod( $instance, $method );
267 $declaringClass = $reflectionMethod->getDeclaringClass()->getName();
269 if ( $declaringClass === $class ) {
275 $component = $component ?:
'MediaWiki';
276 $msg =
"$declaringClass overrides $method which was deprecated in $component $version.";
277 self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 );
312 $component =
false, $callerOffset = 2
314 if ( $callerOffset ===
false ) {
318 $callerDescription = self::getCallerDescription( $callerOffset );
319 $callerFunc = $callerDescription[
'func'];
320 $rawMsg = self::formatCallerDescription( $msg, $callerDescription );
326 if ( isset( self::$deprecationWarnings[$msg][$callerFunc] ) ) {
328 } elseif ( isset( self::$deprecationWarnings[$msg] ) ) {
329 if ( self::$enabled ) {
336 self::$deprecationWarnings[$msg][$callerFunc] =
true;
341 $component = $component ?:
'MediaWiki';
343 # Strip -* off the end of $version so that branches can use the
344 # format #.##-branchname to avoid issues if the branch is merged into
345 # a version of MediaWiki later than what it was branched from
346 $comparableVersion = preg_replace(
'/-.*$/',
'', $version );
348 # If the comparableVersion is larger than our release limit then
349 # skip the warning message for the deprecation
356 self::sendRawDeprecated(
376 foreach ( self::$deprecationFilters as $filter => $callback ) {
377 if ( preg_match( $filter, $msg ) ) {
378 if ( is_callable( $callback ) ) {
386 trigger_error( $msg, E_USER_DEPRECATED );
389 if ( self::$enabled ) {
390 $logMsg = htmlspecialchars( $msg ) .
391 Html::rawElement(
'div', [
'class' =>
'mw-debug-backtrace' ],
392 Html::element(
'span', [],
'Backtrace:' ) .
wfBacktrace()
397 'type' =>
'deprecated',
398 'caller' => $callerFunc,
411 string $regex, ?callable $callback =
null
413 if ( !defined(
'MW_PHPUNIT_TEST' ) && !defined(
'MW_PARSER_TEST' ) ) {
414 throw new LogicException( __METHOD__ .
' can only be used in tests' );
416 self::$deprecationFilters[$regex] = $callback;
423 self::$deprecationFilters = [];
433 private static function getCallerDescription( $callerOffset ) {
436 if ( isset( $callers[$callerOffset] ) ) {
437 $callerfile = $callers[$callerOffset];
438 if ( isset( $callerfile[
'file'] ) && isset( $callerfile[
'line'] ) ) {
439 $file = $callerfile[
'file'] .
' at line ' . $callerfile[
'line'];
441 $file =
'(internal function)';
444 $file =
'(unknown location)';
447 if ( isset( $callers[$callerOffset + 1] ) ) {
448 $callerfunc = $callers[$callerOffset + 1];
450 if ( isset( $callerfunc[
'class'] ) ) {
451 $func .= $callerfunc[
'class'] .
'::';
453 if ( isset( $callerfunc[
'function'] ) ) {
454 $func .= $callerfunc[
'function'];
460 return [
'file' =>
$file,
'func' => $func ];
470 private static function formatCallerDescription( $msg, $caller ) {
472 return $msg .
' [Called from ' . $caller[
'func'] .
' in ' . $caller[
'file'] .
']';
489 preg_match(
'/(.*) \[Called from ([^ ]+) in ([^ ]+) at line (\d+)\]$/', $msg, $match );
492 'message' =>
"{$match[1]} [Called from {$match[2]}]",
510 private static function sendMessage( $msg, $group, $level ) {
511 if ( $level !==
false ) {
512 trigger_error( $msg, $level );
526 public static function debugMsg( $str, $context = [] ) {
532 if ( isset( $context[
'prefix'] ) ) {
533 $prefix = $context[
'prefix'];
534 } elseif ( isset( $context[
'channel'] ) && $context[
'channel'] !==
'wfDebug' ) {
535 $prefix =
"[{$context['channel']}] ";
537 if ( isset( $context[
'seconds_elapsed'] ) && isset( $context[
'memory_used'] ) ) {
538 $prefix .=
"{$context['seconds_elapsed']} {$context['memory_used']} ";
540 $str = LegacyLogger::interpolate( $str, $context );
541 $str = $prefix . $str;
543 self::$debug[] = rtrim( UtfNormal\Validator::cleanUp( $str ) );
557 public static function query( $sql, $function, $runTime, $dbhost ) {
558 if ( !self::$enabled ) {
566 [\xC0-\xC1] # Invalid UTF-8 Bytes
567 | [\xF5-\xFF] # Invalid UTF-8 Bytes
568 | \xE0[\x80-\x9F] # Overlong encoding of prior code point
569 | \xF0[\x80-\x8F] # Overlong encoding of prior code point
570 | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
571 | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
572 | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
573 | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
574 | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]
575 | [\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
576 | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
577 | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
578 | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
585 $sql = UtfNormal\Validator::cleanUp( $sql );
588 'sql' =>
"$dbhost: $sql",
589 'function' => $function,
603 $files = get_included_files();
605 foreach ( $files as
$file ) {
606 $size = filesize(
$file );
609 'size' => $context->
getLanguage()->formatSize( $size ),
628 if ( self::$enabled ) {
629 self::log(
'MWDebug output complete' );
630 $debugInfo = self::getDebugInfo( $context );
634 $html[] = ResourceLoader::makeInlineScript(
635 ResourceLoader::makeConfigSetScript( [
'debugInfo' => $debugInfo ] )
640 $html[] =
'<!-- Debug output:';
641 foreach ( self::$debug as $line ) {
642 $html[] = htmlspecialchars( $line, ENT_NOQUOTES );
647 return WrappedString::join(
"\n", $html );
663 $html[] = Html::openElement(
'div', [
'id' =>
'mw-html-debug-log' ] );
664 $html[] =
"<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">";
666 foreach ( self::$debug as $line ) {
667 $display = nl2br( htmlspecialchars( trim( $line ) ) );
669 $html[] =
"<li><code>$display</code></li>";
675 return WrappedString::join(
"\n", $html );
685 if ( !self::$enabled ) {
691 $obContents = ob_get_contents();
693 $obContentArray = explode(
'<br />', $obContents );
694 foreach ( $obContentArray as $obContent ) {
695 if ( trim( $obContent ) ) {
696 self::debugMsg( Sanitizer::stripAllTags( $obContent ) );
701 self::log(
'MWDebug output complete' );
702 $debugInfo = self::getDebugInfo( $context );
704 ApiResult::setIndexedTagName( $debugInfo,
'debuginfo' );
705 ApiResult::setIndexedTagName( $debugInfo[
'log'],
'line' );
706 ApiResult::setIndexedTagName( $debugInfo[
'debugLog'],
'msg' );
707 ApiResult::setIndexedTagName( $debugInfo[
'queries'],
'query' );
708 ApiResult::setIndexedTagName( $debugInfo[
'includes'],
'queries' );
709 $result->
addValue(
null,
'debuginfo', $debugInfo );
719 if ( !self::$enabled ) {
725 $branch = GitInfo::currentBranch();
726 if ( GitInfo::isSHA1( $branch ) ) {
734 'phpEngine' =>
'PHP',
735 'phpVersion' => PHP_VERSION,
736 'gitRevision' => GitInfo::headSHA1(),
737 'gitBranch' => $branch,
738 'gitViewUrl' => GitInfo::headViewUrl(),
739 'time' => $request->getElapsedTime(),
741 'debugLog' => self::$debug,
742 'queries' => self::$query,
744 'method' => $request->getMethod(),
745 'url' => $request->getRequestURL(),
746 'headers' => $request->getAllHeaders(),
747 'params' => $request->getValues(),
749 'memory' => $context->
getLanguage()->formatSize( memory_get_usage() ),
750 'memoryPeak' => $context->
getLanguage()->formatSize( memory_get_peak_usage() ),
751 'includes' => self::getFilesIncluded( $context ),
const MW_VERSION
The running version of MediaWiki.
if(MW_ENTRY_POINT==='index') global $wgCommandLineMode
wfBacktrace( $raw=null)
Get a debug backtrace as a string.
wfGetCaller( $level=2)
Get the name of the function which called this function wfGetCaller( 1 ) is the function with the wfG...
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfDebugBacktrace( $limit=0)
Safety wrapper for debug_backtrace().
if(!defined('MW_SETUP_CALLBACK'))
This class represents the result of the API operations.
addValue( $path, $name, $value, $flags=0)
Add value to the output data at the given path.
static warning( $msg, $callerOffset=1, $level=E_USER_NOTICE, $log='auto')
Adds a warning entry to the log.
static getFilesIncluded(IContextSource $context)
Returns a list of files included, along with their size.
static array $deprecationFilters
Keys are regexes, values are optional callbacks to call if the filter is hit.
static bool $enabled
Is the debugger enabled?
static filterDeprecationForTest(string $regex, ?callable $callback=null)
Deprecation messages matching the supplied regex will be suppressed.
static addModules(OutputPage $out)
Add ResourceLoader modules to the OutputPage object if debugging is enabled.
static parseCallerDescription( $msg)
Append a caller description to an error message.
static appendDebugInfoToApiResult(IContextSource $context, ApiResult $result)
Append the debug info to given ApiResult.
static array $deprecationWarnings
Array of functions that have already been warned, formatted function-caller to prevent a buttload of ...
static clearLog()
Clears internal log array and deprecation tracking.
static sendRawDeprecated( $msg, $sendToLog=true, $callerFunc='')
Send a raw deprecation message to the log and the debug toolbar, without filtering of duplicate messa...
static deinit()
Disable the debugger.
static query( $sql, $function, $runTime, $dbhost)
Begins profiling on a database query.
static getLog()
Returns internal log array.
static array $debug
Debug messages from wfDebug().
static log( $str)
Adds a line to the log.
static detectDeprecatedOverride( $instance, $class, $method, $version=false, $component=false, $callerOffset=2)
Show a warning if $method declared in $class is overridden in $instance.
static getDebugInfo(IContextSource $context)
Returns the HTML to add to the page for the toolbar.
static debugMsg( $str, $context=[])
This is a method to pass messages from wfDebug to the pretty debugger.
static clearDeprecationFilters()
Clear all deprecation filters.
static array $log
Log lines.
static deprecated( $function, $version=false, $component=false, $callerOffset=2)
Show a warning that $function is deprecated.
static array $query
SQL statements of the database queries.
static getHTMLDebugLog()
Generate debug log in HTML for displaying at the bottom of the main content area.
static init()
Enabled the debugger and load resource module.
static deprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
static getDebugHTML(IContextSource $context)
Returns the HTML to add to the page for the toolbar.
This is one of the Core classes and should be read at least once by any new developers.
addModules( $modules)
Load one or more ResourceLoader modules on this page.
$wgUseCdn
Config variable stub for the UseCdn setting, for use by phpdoc and IDEs.
$wgDeprecationReleaseLimit
Config variable stub for the DeprecationReleaseLimit setting, for use by phpdoc and IDEs.
$wgDebugComments
Config variable stub for the DebugComments setting, for use by phpdoc and IDEs.
$wgShowDebug
Config variable stub for the ShowDebug setting, for use by phpdoc and IDEs.
$wgDebugToolbar
Config variable stub for the DebugToolbar setting, for use by phpdoc and IDEs.
$wgDevelopmentWarnings
Config variable stub for the DevelopmentWarnings setting, for use by phpdoc and IDEs.
$wgUseFileCache
Config variable stub for the UseFileCache setting, for use by phpdoc and IDEs.
Interface for objects which can provide a MediaWiki context on request.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.