25use Wikimedia\WrappedString;
26use Wikimedia\WrappedStringList;
42 protected static $log = [];
81 public static function setup() {
108 public static function init() {
109 self::$enabled =
true;
118 self::$enabled =
false;
129 if ( self::$enabled ) {
140 public static function log( $str ) {
141 if ( !self::$enabled ) {
144 if ( !is_string( $str ) ) {
145 $str = print_r( $str,
true );
148 'msg' => htmlspecialchars( $str ),
169 self::$deprecationWarnings = [];
183 public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE, $log =
'auto' ) {
190 if (
$log ===
'debug' ) {
194 $callerDescription = self::getCallerDescription( $callerOffset );
197 self::formatCallerDescription( $msg, $callerDescription ),
201 if ( self::$enabled ) {
203 'msg' => htmlspecialchars( $msg ),
205 'caller' => $callerDescription[
'func'],
224 public static function deprecated( $function, $version =
false,
225 $component =
false, $callerOffset = 2
228 $component = $component ?:
'MediaWiki';
229 $msg =
"Use of $function was deprecated in $component $version.";
231 $msg =
"Use of $function is deprecated.";
233 self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 );
259 $component =
false, $callerOffset = 2
261 $reflectionMethod =
new ReflectionMethod( $instance, $method );
262 $declaringClass = $reflectionMethod->getDeclaringClass()->getName();
264 if ( $declaringClass === $class ) {
270 $component = $component ?:
'MediaWiki';
271 $msg =
"$declaringClass overrides $method which was deprecated in $component $version.";
272 self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 );
307 $component =
false, $callerOffset = 2
309 if ( $callerOffset ===
false ) {
313 $callerDescription = self::getCallerDescription( $callerOffset );
314 $callerFunc = $callerDescription[
'func'];
315 $rawMsg = self::formatCallerDescription( $msg, $callerDescription );
321 if ( isset( self::$deprecationWarnings[$msg][$callerFunc] ) ) {
323 } elseif ( isset( self::$deprecationWarnings[$msg] ) ) {
324 if ( self::$enabled ) {
331 self::$deprecationWarnings[$msg][$callerFunc] =
true;
336 $component = $component ?:
'MediaWiki';
338 # Strip -* off the end of $version so that branches can use the
339 # format #.##-branchname to avoid issues if the branch is merged into
340 # a version of MediaWiki later than what it was branched from
341 $comparableVersion = preg_replace(
'/-.*$/',
'', $version );
343 # If the comparableVersion is larger than our release limit then
344 # skip the warning message for the deprecation
351 self::sendRawDeprecated(
371 foreach ( self::$deprecationFilters as $filter => $callback ) {
372 if ( preg_match( $filter, $msg ) ) {
373 if ( is_callable( $callback ) ) {
381 trigger_error( $msg, E_USER_DEPRECATED );
384 if ( self::$enabled ) {
385 $logMsg = htmlspecialchars( $msg ) .
386 Html::rawElement(
'div', [
'class' =>
'mw-debug-backtrace' ],
387 Html::element(
'span', [],
'Backtrace:' ) .
wfBacktrace()
392 'type' =>
'deprecated',
393 'caller' => $callerFunc,
406 string $regex, ?callable $callback =
null
408 if ( !defined(
'MW_PHPUNIT_TEST' ) && !defined(
'MW_PARSER_TEST' ) ) {
409 throw new RuntimeException( __METHOD__ .
' can only be used in tests' );
411 self::$deprecationFilters[$regex] = $callback;
418 self::$deprecationFilters = [];
428 private static function getCallerDescription( $callerOffset ) {
431 if ( isset( $callers[$callerOffset] ) ) {
432 $callerfile = $callers[$callerOffset];
433 if ( isset( $callerfile[
'file'] ) && isset( $callerfile[
'line'] ) ) {
434 $file = $callerfile[
'file'] .
' at line ' . $callerfile[
'line'];
436 $file =
'(internal function)';
439 $file =
'(unknown location)';
442 if ( isset( $callers[$callerOffset + 1] ) ) {
443 $callerfunc = $callers[$callerOffset + 1];
445 if ( isset( $callerfunc[
'class'] ) ) {
446 $func .= $callerfunc[
'class'] .
'::';
448 if ( isset( $callerfunc[
'function'] ) ) {
449 $func .= $callerfunc[
'function'];
455 return [
'file' =>
$file,
'func' => $func ];
465 private static function formatCallerDescription( $msg, $caller ) {
467 return $msg .
' [Called from ' . $caller[
'func'] .
' in ' . $caller[
'file'] .
']';
484 preg_match(
'/(.*) \[Called from ([^ ]+) in ([^ ]+) at line (\d+)\]$/', $msg, $match );
487 'message' =>
"{$match[1]} [Called from {$match[2]}]",
505 private static function sendMessage( $msg, $group, $level ) {
506 if ( $level !==
false ) {
507 trigger_error( $msg, $level );
521 public static function debugMsg( $str, $context = [] ) {
527 if ( isset( $context[
'prefix'] ) ) {
528 $prefix = $context[
'prefix'];
529 } elseif ( isset( $context[
'channel'] ) && $context[
'channel'] !==
'wfDebug' ) {
530 $prefix =
"[{$context['channel']}] ";
532 if ( isset( $context[
'seconds_elapsed'] ) && isset( $context[
'memory_used'] ) ) {
533 $prefix .=
"{$context['seconds_elapsed']} {$context['memory_used']} ";
535 $str = LegacyLogger::interpolate( $str, $context );
536 $str = $prefix . $str;
538 self::$debug[] = rtrim( UtfNormal\Validator::cleanUp( $str ) );
552 public static function query( $sql, $function, $runTime, $dbhost ) {
553 if ( !self::$enabled ) {
561 [\xC0-\xC1] # Invalid UTF-8 Bytes
562 | [\xF5-\xFF] # Invalid UTF-8 Bytes
563 | \xE0[\x80-\x9F] # Overlong encoding of prior code point
564 | \xF0[\x80-\x8F] # Overlong encoding of prior code point
565 | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
566 | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
567 | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
568 | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
569 | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]
570 | [\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
571 | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
572 | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
573 | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
580 $sql = UtfNormal\Validator::cleanUp( $sql );
583 'sql' =>
"$dbhost: $sql",
584 'function' => $function,
598 $files = get_included_files();
600 foreach ( $files as
$file ) {
601 $size = filesize(
$file );
604 'size' => $context->
getLanguage()->formatSize( $size ),
623 if ( self::$enabled ) {
624 self::log(
'MWDebug output complete' );
625 $debugInfo = self::getDebugInfo( $context );
629 $html[] = ResourceLoader::makeInlineScript(
630 ResourceLoader::makeConfigSetScript( [
'debugInfo' => $debugInfo ] ),
631 $context->
getOutput()->getCSP()->getNonce()
636 $html[] =
'<!-- Debug output:';
637 foreach ( self::$debug as
$line ) {
638 $html[] = htmlspecialchars(
$line, ENT_NOQUOTES );
643 return WrappedString::join(
"\n", $html );
659 $html[] = Html::openElement(
'div', [
'id' =>
'mw-html-debug-log' ] );
660 $html[] =
"<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">";
662 foreach ( self::$debug as
$line ) {
663 $display = nl2br( htmlspecialchars( trim(
$line ) ) );
665 $html[] =
"<li><code>$display</code></li>";
671 return WrappedString::join(
"\n", $html );
681 if ( !self::$enabled ) {
687 $obContents = ob_get_contents();
689 $obContentArray = explode(
'<br />', $obContents );
690 foreach ( $obContentArray as $obContent ) {
691 if ( trim( $obContent ) ) {
692 self::debugMsg( Sanitizer::stripAllTags( $obContent ) );
697 self::log(
'MWDebug output complete' );
698 $debugInfo = self::getDebugInfo( $context );
700 ApiResult::setIndexedTagName( $debugInfo,
'debuginfo' );
701 ApiResult::setIndexedTagName( $debugInfo[
'log'],
'line' );
702 ApiResult::setIndexedTagName( $debugInfo[
'debugLog'],
'msg' );
703 ApiResult::setIndexedTagName( $debugInfo[
'queries'],
'query' );
704 ApiResult::setIndexedTagName( $debugInfo[
'includes'],
'queries' );
705 $result->
addValue(
null,
'debuginfo', $debugInfo );
715 if ( !self::$enabled ) {
730 'phpEngine' =>
'PHP',
731 'phpVersion' => PHP_VERSION,
733 'gitBranch' => $branch,
735 'time' => $request->getElapsedTime(),
738 'queries' => self::$query,
740 'method' => $request->getMethod(),
741 'url' => $request->getRequestURL(),
742 'headers' => $request->getAllHeaders(),
743 'params' => $request->getValues(),
745 'memory' => $context->
getLanguage()->formatSize( memory_get_usage() ),
746 'memoryPeak' => $context->
getLanguage()->formatSize( memory_get_peak_usage() ),
747 'includes' => self::getFilesIncluded( $context ),
const MW_VERSION
The running version of MediaWiki.
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'))
The persistent session ID (if any) loaded at startup.
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 isSHA1( $str)
Check if a string looks like a hex encoded SHA1 hash.
New debugger system that outputs a toolbar on page view.
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 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.