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 ),
221 public static function deprecated( $function, $version =
false,
222 $component =
false, $callerOffset = 2
225 $component = $component ?:
'MediaWiki';
226 $msg =
"Use of $function was deprecated in $component $version.";
228 $msg =
"Use of $function is deprecated.";
230 self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 );
256 $component =
false, $callerOffset = 2
258 $reflectionMethod =
new ReflectionMethod( $instance, $method );
259 $declaringClass = $reflectionMethod->getDeclaringClass()->getName();
261 if ( $declaringClass === $class ) {
267 $component = $component ?:
'MediaWiki';
268 $msg =
"$declaringClass overrides $method which was deprecated in $component $version.";
269 self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 );
304 $component =
false, $callerOffset = 2
306 if ( $callerOffset ===
false ) {
310 $callerDescription = self::getCallerDescription( $callerOffset );
311 $callerFunc = $callerDescription[
'func'];
312 $rawMsg = self::formatCallerDescription( $msg, $callerDescription );
318 if ( isset( self::$deprecationWarnings[$msg][$callerFunc] ) ) {
320 } elseif ( isset( self::$deprecationWarnings[$msg] ) ) {
321 if ( self::$enabled ) {
328 self::$deprecationWarnings[$msg][$callerFunc] =
true;
333 $component = $component ?:
'MediaWiki';
335 # Strip -* off the end of $version so that branches can use the
336 # format #.##-branchname to avoid issues if the branch is merged into
337 # a version of MediaWiki later than what it was branched from
338 $comparableVersion = preg_replace(
'/-.*$/',
'', $version );
340 # If the comparableVersion is larger than our release limit then
341 # skip the warning message for the deprecation
348 self::sendRawDeprecated(
368 foreach ( self::$deprecationFilters as $filter => $callback ) {
369 if ( preg_match( $filter, $msg ) ) {
370 if ( is_callable( $callback ) ) {
378 trigger_error( $msg, E_USER_DEPRECATED );
390 string $regex, ?callable $callback =
null
392 if ( !defined(
'MW_PHPUNIT_TEST' ) && !defined(
'MW_PARSER_TEST' ) ) {
393 throw new LogicException( __METHOD__ .
' can only be used in tests' );
395 self::$deprecationFilters[$regex] = $callback;
402 self::$deprecationFilters = [];
412 private static function getCallerDescription( $callerOffset ) {
415 if ( isset( $callers[$callerOffset] ) ) {
416 $callerfile = $callers[$callerOffset];
417 if ( isset( $callerfile[
'file'] ) && isset( $callerfile[
'line'] ) ) {
418 $file = $callerfile[
'file'] .
' at line ' . $callerfile[
'line'];
420 $file =
'(internal function)';
423 $file =
'(unknown location)';
426 if ( isset( $callers[$callerOffset + 1] ) ) {
427 $callerfunc = $callers[$callerOffset + 1];
429 if ( isset( $callerfunc[
'class'] ) ) {
430 $func .= $callerfunc[
'class'] .
'::';
432 if ( isset( $callerfunc[
'function'] ) ) {
433 $func .= $callerfunc[
'function'];
439 return [
'file' =>
$file,
'func' => $func ];
449 private static function formatCallerDescription( $msg, $caller ) {
451 return $msg .
' [Called from ' . $caller[
'func'] .
' in ' . $caller[
'file'] .
']';
468 preg_match(
'/(.*) \[Called from ([^ ]+) in ([^ ]+) at line (\d+)\]$/', $msg, $match );
471 'message' =>
"{$match[1]} [Called from {$match[2]}]",
489 private static function sendMessage( $msg, $group, $level ) {
490 if ( $level !==
false ) {
491 trigger_error( $msg, $level );
507 public static function debugMsg( $str, $context = [] ) {
513 if ( isset( $context[
'prefix'] ) ) {
514 $prefix = $context[
'prefix'];
515 } elseif ( isset( $context[
'channel'] ) && $context[
'channel'] !==
'wfDebug' ) {
516 $prefix =
"[{$context['channel']}] ";
518 if ( isset( $context[
'seconds_elapsed'] ) && isset( $context[
'memory_used'] ) ) {
519 $prefix .=
"{$context['seconds_elapsed']} {$context['memory_used']} ";
521 $str = LegacyLogger::interpolate( $str, $context );
522 $str = $prefix . $str;
524 $str = rtrim( UtfNormal\Validator::cleanUp( $str ) );
525 self::$debug[] = $str;
526 if ( isset( $context[
'channel'] ) && $context[
'channel'] ===
'error' ) {
527 $message = isset( $context[
'exception'] )
528 ? $context[
'exception']->getMessage()
530 $real = self::parseCallerDescription( $message );
533 $message = $real[
'message'];
534 $caller = $real[
'func'];
536 $trace = isset( $context[
'exception'] ) ? $context[
'exception']->getTrace() : [];
537 if ( ( $trace[5][
'function'] ??
null ) ===
'wfDeprecated' ) {
540 } elseif ( ( $trace[1][
'function'] ??
null ) ===
'trigger_error' ) {
547 $frame = $trace[$offset] ?? $trace[0];
548 $caller = ( isset( $frame[
'class'] ) ? $frame[
'class'] .
'::' :
'' )
549 . $frame[
'function'];
553 'msg' => htmlspecialchars( $message ),
571 public static function query( $sql, $function, $runTime, $dbhost ) {
572 if ( !self::$enabled ) {
580 [\xC0-\xC1] # Invalid UTF-8 Bytes
581 | [\xF5-\xFF] # Invalid UTF-8 Bytes
582 | \xE0[\x80-\x9F] # Overlong encoding of prior code point
583 | \xF0[\x80-\x8F] # Overlong encoding of prior code point
584 | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
585 | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
586 | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
587 | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
588 | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]
589 | [\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
590 | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
591 | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
592 | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
599 $sql = UtfNormal\Validator::cleanUp( $sql );
602 'sql' =>
"$dbhost: $sql",
603 'function' => $function,
617 $files = get_included_files();
619 foreach ( $files as
$file ) {
620 $size = filesize(
$file );
623 'size' => $context->
getLanguage()->formatSize( $size ),
642 if ( self::$enabled ) {
643 self::log(
'MWDebug output complete' );
644 $debugInfo = self::getDebugInfo( $context );
648 $html[] = ResourceLoader::makeInlineScript(
649 ResourceLoader::makeConfigSetScript( [
'debugInfo' => $debugInfo ] )
654 $html[] =
'<!-- Debug output:';
655 foreach ( self::$debug as $line ) {
656 $html[] = htmlspecialchars( $line, ENT_NOQUOTES );
661 return WrappedString::join(
"\n", $html );
677 $html[] = Html::openElement(
'div', [
'id' =>
'mw-html-debug-log' ] );
678 $html[] =
"<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">";
680 foreach ( self::$debug as $line ) {
681 $display = nl2br( htmlspecialchars( trim( $line ) ) );
683 $html[] =
"<li><code>$display</code></li>";
689 return WrappedString::join(
"\n", $html );
699 if ( !self::$enabled ) {
705 $obContents = ob_get_contents();
707 $obContentArray = explode(
'<br />', $obContents );
708 foreach ( $obContentArray as $obContent ) {
709 if ( trim( $obContent ) ) {
710 self::debugMsg( Sanitizer::stripAllTags( $obContent ) );
715 self::log(
'MWDebug output complete' );
716 $debugInfo = self::getDebugInfo( $context );
718 ApiResult::setIndexedTagName( $debugInfo,
'debuginfo' );
719 ApiResult::setIndexedTagName( $debugInfo[
'log'],
'line' );
720 ApiResult::setIndexedTagName( $debugInfo[
'debugLog'],
'msg' );
721 ApiResult::setIndexedTagName( $debugInfo[
'queries'],
'query' );
722 ApiResult::setIndexedTagName( $debugInfo[
'includes'],
'queries' );
723 $result->
addValue(
null,
'debuginfo', $debugInfo );
733 if ( !self::$enabled ) {
739 $branch = GitInfo::currentBranch();
740 if ( GitInfo::isSHA1( $branch ) ) {
748 'phpEngine' =>
'PHP',
749 'phpVersion' => PHP_VERSION,
750 'gitRevision' => GitInfo::headSHA1(),
751 'gitBranch' => $branch,
752 'gitViewUrl' => GitInfo::headViewUrl(),
753 'time' => $request->getElapsedTime(),
755 'debugLog' => self::$debug,
756 'queries' => self::$query,
758 'method' => $request->getMethod(),
759 'url' => $request->getRequestURL(),
760 'headers' => $request->getAllHeaders(),
761 'params' => $request->getValues(),
763 'memory' => $context->
getLanguage()->formatSize( memory_get_usage() ),
764 'memoryPeak' => $context->
getLanguage()->formatSize( memory_get_peak_usage() ),
765 'includes' => self::getFilesIncluded( $context ),
const MW_VERSION
The running version of MediaWiki.
if(MW_ENTRY_POINT==='index') global $wgCommandLineMode
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 method receives messages from LoggerFactory, wfDebugLog, and MWExceptionHandler.
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.