26 use Wikimedia\WrappedString;
27 use Wikimedia\WrappedStringList;
43 protected static $log = [];
82 public static function setup() {
109 public static function init() {
110 self::$enabled =
true;
119 self::$enabled =
false;
130 if ( self::$enabled ) {
141 public static function log( $str ) {
142 if ( !self::$enabled ) {
145 if ( !is_string( $str ) ) {
146 $str = print_r( $str,
true );
149 'msg' => htmlspecialchars( $str ),
170 self::$deprecationWarnings = [];
184 public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE,
$log =
'auto' ) {
191 if (
$log ===
'debug' ) {
195 $callerDescription = self::getCallerDescription( $callerOffset );
198 self::formatCallerDescription( $msg, $callerDescription ),
202 if ( self::$enabled ) {
204 'msg' => htmlspecialchars( $msg ),
206 'caller' => $callerDescription[
'func'],
225 public static function deprecated( $function, $version =
false,
226 $component =
false, $callerOffset = 2
229 $component = $component ?:
'MediaWiki';
230 $msg =
"Use of $function was deprecated in $component $version.";
232 $msg =
"Use of $function is deprecated.";
260 $component =
false, $callerOffset = 2
262 $reflectionMethod =
new ReflectionMethod( $instance, $method );
263 $declaringClass = $reflectionMethod->getDeclaringClass()->getName();
265 if ( $declaringClass === $class ) {
271 $component = $component ?:
'MediaWiki';
272 $msg =
"$declaringClass overrides $method which was deprecated in $component $version.";
308 $component =
false, $callerOffset = 2
310 if ( $callerOffset ===
false ) {
314 $callerDescription = self::getCallerDescription( $callerOffset );
315 $callerFunc = $callerDescription[
'func'];
316 $rawMsg = self::formatCallerDescription( $msg, $callerDescription );
322 if ( isset( self::$deprecationWarnings[$msg][$callerFunc] ) ) {
324 } elseif ( isset( self::$deprecationWarnings[$msg] ) ) {
325 if ( self::$enabled ) {
332 self::$deprecationWarnings[$msg][$callerFunc] =
true;
337 $component = $component ?:
'MediaWiki';
339 # Strip -* off the end of $version so that branches can use the
340 # format #.##-branchname to avoid issues if the branch is merged into
341 # a version of MediaWiki later than what it was branched from
342 $comparableVersion = preg_replace(
'/-.*$/',
'', $version );
344 # If the comparableVersion is larger than our release limit then
345 # skip the warning message for the deprecation
372 foreach ( self::$deprecationFilters as $filter => $callback ) {
373 if ( preg_match( $filter, $msg ) ) {
374 if ( is_callable( $callback ) ) {
382 trigger_error( $msg, E_USER_DEPRECATED );
385 if ( self::$enabled ) {
386 $logMsg = htmlspecialchars( $msg ) .
387 Html::rawElement(
'div', [
'class' =>
'mw-debug-backtrace' ],
388 Html::element(
'span', [],
'Backtrace:' ) .
wfBacktrace()
393 'type' =>
'deprecated',
394 'caller' => $callerFunc,
407 string $regex, ?callable $callback =
null
409 if ( !defined(
'MW_PHPUNIT_TEST' ) && !defined(
'MW_PARSER_TEST' ) ) {
410 throw new RuntimeException( __METHOD__ .
' can only be used in tests' );
412 self::$deprecationFilters[$regex] = $callback;
419 self::$deprecationFilters = [];
429 private static function getCallerDescription( $callerOffset ) {
432 if ( isset( $callers[$callerOffset] ) ) {
433 $callerfile = $callers[$callerOffset];
434 if ( isset( $callerfile[
'file'] ) && isset( $callerfile[
'line'] ) ) {
435 $file = $callerfile[
'file'] .
' at line ' . $callerfile[
'line'];
437 $file =
'(internal function)';
440 $file =
'(unknown location)';
443 if ( isset( $callers[$callerOffset + 1] ) ) {
444 $callerfunc = $callers[$callerOffset + 1];
446 if ( isset( $callerfunc[
'class'] ) ) {
447 $func .= $callerfunc[
'class'] .
'::';
449 if ( isset( $callerfunc[
'function'] ) ) {
450 $func .= $callerfunc[
'function'];
456 return [
'file' =>
$file,
'func' => $func ];
466 private static function formatCallerDescription( $msg, $caller ) {
468 return $msg .
' [Called from ' . $caller[
'func'] .
' in ' . $caller[
'file'] .
']';
485 preg_match(
'/(.*) \[Called from ([^ ]+) in ([^ ]+) at line (\d+)\]$/', $msg, $match );
488 'message' =>
"{$match[1]} [Called from {$match[2]}]",
506 private static function sendMessage( $msg, $group, $level ) {
507 if ( $level !==
false ) {
508 trigger_error( $msg, $level );
522 public static function debugMsg( $str, $context = [] ) {
528 if ( isset( $context[
'prefix'] ) ) {
529 $prefix = $context[
'prefix'];
530 } elseif ( isset( $context[
'channel'] ) && $context[
'channel'] !==
'wfDebug' ) {
531 $prefix =
"[{$context['channel']}] ";
533 if ( isset( $context[
'seconds_elapsed'] ) && isset( $context[
'memory_used'] ) ) {
534 $prefix .=
"{$context['seconds_elapsed']} {$context['memory_used']} ";
536 $str = LegacyLogger::interpolate( $str, $context );
537 $str = $prefix . $str;
539 self::$debug[] = rtrim( UtfNormal\Validator::cleanUp( $str ) );
553 public static function query( $sql, $function, $runTime, $dbhost ) {
554 if ( !self::$enabled ) {
562 [\xC0-\xC1] # Invalid UTF-8 Bytes
563 | [\xF5-\xFF] # Invalid UTF-8 Bytes
564 | \xE0[\x80-\x9F] # Overlong encoding of prior code point
565 | \xF0[\x80-\x8F] # Overlong encoding of prior code point
566 | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
567 | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
568 | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
569 | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
570 | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]
571 | [\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
572 | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
573 | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
574 | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
581 $sql = UtfNormal\Validator::cleanUp( $sql );
584 'sql' =>
"$dbhost: $sql",
585 'function' => $function,
599 $files = get_included_files();
601 foreach ( $files as
$file ) {
602 $size = filesize(
$file );
605 'size' => $context->
getLanguage()->formatSize( $size ),
624 if ( self::$enabled ) {
625 self::log(
'MWDebug output complete' );
626 $debugInfo = self::getDebugInfo( $context );
630 $html[] = ResourceLoader::makeInlineScript(
631 ResourceLoader::makeConfigSetScript( [
'debugInfo' => $debugInfo ] ),
632 $context->
getOutput()->getCSP()->getNonce()
637 $html[] =
'<!-- Debug output:';
638 foreach ( self::$debug as $line ) {
639 $html[] = htmlspecialchars( $line, ENT_NOQUOTES );
644 return WrappedString::join(
"\n", $html );
660 $html[] = Html::openElement(
'div', [
'id' =>
'mw-html-debug-log' ] );
661 $html[] =
"<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">";
663 foreach ( self::$debug as $line ) {
664 $display = nl2br( htmlspecialchars( trim( $line ) ) );
666 $html[] =
"<li><code>$display</code></li>";
672 return WrappedString::join(
"\n", $html );
682 if ( !self::$enabled ) {
688 $obContents = ob_get_contents();
690 $obContentArray = explode(
'<br />', $obContents );
691 foreach ( $obContentArray as $obContent ) {
692 if ( trim( $obContent ) ) {
698 self::log(
'MWDebug output complete' );
699 $debugInfo = self::getDebugInfo( $context );
706 $result->
addValue(
null,
'debuginfo', $debugInfo );
716 if ( !self::$enabled ) {
731 'phpEngine' =>
'PHP',
732 'phpVersion' => PHP_VERSION,
734 'gitBranch' => $branch,
736 'time' => $request->getElapsedTime(),
738 'debugLog' => self::$debug,
739 'queries' => self::$query,
741 'method' => $request->getMethod(),
742 'url' => $request->getRequestURL(),
743 'headers' => $request->getAllHeaders(),
744 'params' => $request->getValues(),
746 'memory' => $context->
getLanguage()->formatSize( memory_get_usage() ),
747 'memoryPeak' => $context->
getLanguage()->formatSize( memory_get_peak_usage() ),
748 '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'))
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 setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
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 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.
static stripAllTags( $html)
Take a fragment of (potentially invalid) HTML and return a version with any tags removed,...
$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.