22use Wikimedia\AtEase\AtEase;
29use Wikimedia\RequestTimeout\RequestTimeout;
30use Wikimedia\Timestamp\ConvertibleTimestamp;
45$path =
"$wgExtensionDirectory/$ext/extension.json";
47 ExtensionRegistry::getInstance()->queue(
$path );
65 $registry = ExtensionRegistry::getInstance();
66foreach ( $exts as $ext ) {
67 $registry->queue(
"$wgExtensionDirectory/$ext/extension.json" );
82$path =
"$wgStyleDirectory/$skin/skin.json";
84 ExtensionRegistry::getInstance()->queue(
$path );
96 $registry = ExtensionRegistry::getInstance();
97foreach ( $skins as $skin ) {
98 $registry->queue(
"$wgStyleDirectory/$skin/skin.json" );
115 $comparator =
staticfunction ( $a, $b ):
int {
116if ( is_string( $a ) && is_string( $b ) ) {
117return strcmp( $a, $b );
119if ( !is_array( $a ) && !is_array( $b ) ) {
120thrownew InvalidArgumentException(
121'This function assumes that array elements are all strings or all arrays' 124if ( count( $a ) !== count( $b ) ) {
125return count( $a ) <=> count( $b );
129while ( key( $a ) !==
null && key( $b ) !==
null ) {
130 $valueA = current( $a );
131 $valueB = current( $b );
132 $cmp = strcmp( $valueA, $valueB );
142return array_udiff( $arr1, $arr2, $comparator );
168foreach ( $args as $errors ) {
169foreach ( $errors as $params ) {
170 $originalParams = $params;
172 $params = [ $params[0]->getKey(), ...$params[0]->getParams() ];
174 # @todo FIXME: Sometimes get nested arrays for $params, 175 # which leads to E_NOTICEs 176 $spec = implode(
"\t", $params );
177 $out[$spec] = $originalParams;
180return array_values( $out );
193// Find the offset of the element to insert after. 194 $keys = array_keys( $array );
195 $offsetByKey = array_flip( $keys );
197if ( !\array_key_exists( $after, $offsetByKey ) ) {
200 $offset = $offsetByKey[$after];
202// Insert at the specified offset 203 $before = array_slice( $array, 0, $offset + 1,
true );
204 $after = array_slice( $array, $offset + 1, count( $array ) - $offset,
true );
206 $output = $before + $insert + $after;
221if ( is_object( $objOrArray ) ) {
222 $objOrArray = get_object_vars( $objOrArray );
224foreach ( $objOrArray as $key => $value ) {
225if ( $recursive && ( is_object( $value ) || is_array( $value ) ) ) {
229 $array[$key] = $value;
246// The maximum random value is "only" 2^31-1, so get two random 247// values to reduce the chance of dupes 248 $max = mt_getrandmax() + 1;
249 $rand = number_format( ( mt_rand() * $max + mt_rand() ) / $max / $max, 12,
'.',
'' );
265for ( $n = 0; $n < $length; $n += 7 ) {
266 $str .= sprintf(
'%07x', mt_rand() & 0xfffffff );
268return substr( $str, 0, $length );
302// Reset $needle for testing. 307if ( $needle ===
null ) {
308 $needle = [
'%3B',
'%40',
'%24',
'%21',
'%2A',
'%28',
'%29',
'%2C',
'%2F',
'%7E' ];
309if ( !isset( $_SERVER[
'SERVER_SOFTWARE'] ) ||
310 !str_contains( $_SERVER[
'SERVER_SOFTWARE'],
'Microsoft-IIS/7' )
316 $s = urlencode( $s );
319 [
';',
'@',
'$',
'!',
'*',
'(',
')',
',',
'/',
'~',
':' ],
337if ( $array2 !==
null ) {
342foreach ( $array1 as $key => $value ) {
343if ( $value !==
null && $value !==
false ) {
347if ( $prefix !==
'' ) {
348 $key = $prefix .
"[$key]";
350if ( is_array( $value ) ) {
352foreach ( $value as $k => $v ) {
353 $cgi .= $firstTime ?
'' :
'&';
354if ( is_array( $v ) ) {
357 $cgi .= urlencode( $key .
"[$k]" ) .
'=' . urlencode( $v );
362if ( is_object( $value ) ) {
363 $value = $value->__toString();
365 $cgi .= urlencode( $key ) .
'=' . urlencode( $value );
382if ( isset( $query[0] ) && $query[0] ==
'?' ) {
383 $query = substr( $query, 1 );
385 $bits = explode(
'&', $query );
387foreach ( $bits as $bit ) {
391if ( !str_contains( $bit,
'=' ) ) {
392// Pieces like &qwerty become 'qwerty' => '' (at least this is what php does) 396 [ $key, $value ] = explode(
'=', $bit );
398 $key = urldecode( $key );
399 $value = urldecode( $value );
400if ( str_contains( $key,
'[' ) ) {
401 $keys = array_reverse( explode(
'[', $key ) );
402 $key = array_pop( $keys );
404foreach ( $keys as $k ) {
405 $k = substr( $k, 0, -1 );
406 $temp = [ $k => $temp ];
408if ( isset( $ret[$key] ) && is_array( $ret[$key] ) ) {
409 $ret[$key] = array_merge( $ret[$key], $temp );
429if ( is_array( $query ) ) {
433// Remove the fragment, if there is one 435 $hashPos = strpos(
$url,
'#' );
436if ( $hashPos !==
false ) {
437 $fragment = substr(
$url, $hashPos );
442if ( !str_contains(
$url,
'?' ) ) {
449// Put the fragment back 450if ( $fragment !==
false ) {
466if ( MediaWikiServices::hasInstance() ) {
467 $services = MediaWikiServices::getInstance();
468if ( $services->hasService(
'UrlUtils' ) ) {
469return $services->getUrlUtils();
474// UrlUtils throws if the relevant $wg(|Canonical|Internal) variable is null, but the old 475// implementations implicitly converted it to an empty string (presumably by mistake). 476// Preserve the old behavior for compatibility. 535return UrlUtils::assemble( (array)$urlParts );
549return $includeProtocolRelative ?
wfGetUrlUtils()->validProtocols() :
632functionwfDebug( $text, $dest =
'all', array $context = [] ) {
639 $text = trim( $text );
644 $context[
'private'] = ( $dest ===
false || $dest ===
'private' );
646 $logger = LoggerFactory::getInstance(
'wfDebug' );
647 $logger->debug( $text, $context );
656if ( $cache !==
null ) {
659// Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet 660// phpcs:ignore MediaWiki.Usage.SuperGlobalsUsage.SuperGlobals 661if ( ( isset( $_GET[
'action'] ) && $_GET[
'action'] ==
'raw' )
697 $logGroup, $text, $dest =
'all', array $context = []
699 $text = trim( $text );
701 $logger = LoggerFactory::getInstance( $logGroup );
702 $context[
'private'] = ( $dest ===
false || $dest ===
'private' );
703 $logger->info( $text, $context );
715 $logger = LoggerFactory::getInstance(
'wfLogDBError' );
716 $logger->error( trim( $text ), $context );
735functionwfDeprecated( $function, $version =
false, $component =
false, $callerOffset = 2 ) {
736if ( !is_string( $version ) && $version !==
false ) {
737thrownew InvalidArgumentException(
738"MediaWiki version must either be a string or false. " .
739"Example valid version: '1.33'" 743 MWDebug::deprecated( $function, $version, $component, $callerOffset + 1 );
766functionwfDeprecatedMsg( $msg, $version =
false, $component =
false, $callerOffset = 2 ) {
767 MWDebug::deprecatedMsg( $msg, $version, $component,
768 $callerOffset ===
false ?
false : $callerOffset + 1 );
781functionwfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
782 MWDebug::warning( $msg, $callerOffset + 1, $level,
'auto' );
794functionwfLogWarning( $msg, $callerOffset = 1, $level = E_USER_WARNING ) {
795 MWDebug::warning( $msg, $callerOffset + 1, $level,
'production' );
821if ( is_array( $key ) ) {
822// Fallback keys are not allowed in message specifiers 825 $message = Message::newFromSpecifier( $key );
828// We call Message::params() to reduce code duplication 830 $message->params( ...$params );
849return Message::newFallbackSequence( ...$keys );
861 # Fix windows line-endings 862 # Some messages are split with explode("\n", $msg) 863 $message = str_replace(
"\r",
'', $message );
866if ( is_array( $args ) && $args ) {
867if ( is_array( $args[0] ) ) {
868 $args = array_values( $args[0] );
870 $replacementKeys = [];
871foreach ( $args as $n => $param ) {
872 $replacementKeys[
'$' . ( $n + 1 )] = $param;
874 $message = strtr( $message, $replacementKeys );
889// Hostname overriding 895return php_uname(
'n' ) ?:
'unknown';
909static $disabled =
null;
911if ( $disabled ===
null ) {
912 $disabled = !function_exists(
'debug_backtrace' );
914wfDebug(
"debug_backtrace() is disabled" );
922return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit + 1 ), 1 );
924return array_slice( debug_backtrace(), 1 );
939 $frameFormat =
"%s line %s calls %s()\n";
942 $frameFormat =
"<li>%s line %s calls %s()</li>\n";
943 $traceFormat =
"<ul>\n%s</ul>\n";
946 $frames = array_map(
staticfunction ( $frame ) use ( $frameFormat ) {
947 $file = !empty( $frame[
'file'] ) ? basename( $frame[
'file'] ) :
'-';
948 $line = $frame[
'line'] ??
'-';
949 $call = $frame[
'function'];
950if ( !empty( $frame[
'class'] ) ) {
951 $call = $frame[
'class'] . $frame[
'type'] . $call;
953return sprintf( $frameFormat, $file, $line, $call );
956return sprintf( $traceFormat, implode(
'', $frames ) );
971if ( isset( $backtrace[$level] ) ) {
987if ( !$limit || $limit > count( $trace ) - 1 ) {
988 $limit = count( $trace ) - 1;
990 $trace = array_slice( $trace, -$limit - 1, $limit );
991// Do not use `wfFormatStackFrame( ... )` here for compatibility with PHP <8.1.4 992// https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1160800/comment/92e67687_ab221188/ 993return implode(
'/', array_map(
'wfFormatStackFrame', $trace ) );
1009if ( !isset( $frame[
'function'] ) ) {
1010return'NO_FUNCTION_GIVEN';
1012return isset( $frame[
'class'] ) && isset( $frame[
'type'] ) ?
1013 $frame[
'class'] . $frame[
'type'] . $frame[
'function'] :
1027static $result =
null;
1028if ( $result ===
null || $force ) {
1030if ( isset( $_SERVER[
'HTTP_ACCEPT_ENCODING'] ) ) {
1031 # @todo FIXME: We may want to disallow some broken browsers 1034'/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
1035 $_SERVER[
'HTTP_ACCEPT_ENCODING'],
1039if ( isset( $m[2] ) && ( $m[1] ==
'q' ) && ( $m[2] == 0 ) ) {
1042wfDebug(
"wfClientAcceptsGzip: client accepts gzip." );
1062static $repl =
null, $repl2 =
null, $repl3 =
null, $repl4 =
null;
1063if ( $repl ===
null || defined(
'MW_PHPUNIT_TEST' ) ) {
1064// Tests depend upon being able to change $wgEnableMagicLinks, so don't cache 1065// in those situations 1067'"' =>
'"',
'&' =>
'&',
"'" =>
''',
'<' =>
'<',
1068'=' =>
'=',
'>' =>
'>',
'[' =>
'[',
']' =>
']',
1069'{' =>
'{',
'|' =>
'|',
'}' =>
'}',
1070';' =>
';',
// a token inside language converter brackets 1071'!!' =>
'!!',
// a token inside table context 1072"\n!" =>
"\n!",
"\r!" =>
"\r!",
// a token inside table context 1073"\n#" =>
"\n#",
"\r#" =>
"\r#",
1074"\n*" =>
"\n*",
"\r*" =>
"\r*",
1075"\n:" =>
"\n:",
"\r:" =>
"\r:",
1076"\n " =>
"\n ",
"\r " =>
"\r ",
1077"\n\n" =>
"\n ",
"\r\n" =>
" \n",
1078"\n\r" =>
"\n ",
"\r\r" =>
"\r ",
1079"\n\t" =>
"\n	",
"\r\t" =>
"\r	",
// "\n\t\n" is treated like "\n\n" 1080"\n----" =>
"\n----",
"\r----" =>
"\r----",
1081'__' =>
'__',
'://' =>
'://',
1082// Japanese magic words start w/ wide underscore 1084'~~~' =>
'~~~',
// protect from PST, just to be safe(r) 1088// We have to catch everything "\s" matches in PCRE 1089foreach ( $magicLinks as $magic ) {
1090 $repl[
"$magic "] =
"$magic ";
1091 $repl[
"$magic\t"] =
"$magic	";
1092 $repl[
"$magic\r"] =
"$magic ";
1093 $repl[
"$magic\n"] =
"$magic ";
1094 $repl[
"$magic\f"] =
"$magic";
1096// Additionally escape the following characters at the beginning of the 1097// string, in case they merge to form tokens when spliced into a 1098// string. Tokens like -{ {{ [[ {| etc are already escaped because 1099// the second character is escaped above, but the following tokens 1100// are handled here: |+ |- __FOO__ ~~~ 1101// (Only single-byte characters can go here; multibyte characters 1102// like 'wide underscore' must go into $repl above.) 1104'+' =>
'+',
'-' =>
'-',
'_' =>
'_',
'~' =>
'~',
1106// Similarly, protect the following characters at the end of the 1107// string, which could turn form the start of `__FOO__` or `~~~~` 1108// A trailing newline could also form the unintended start of a 1109// paragraph break if it is glued to a newline in the following 1110// context. Again, only single-byte characters can be protected 1111// here; 'wide underscore' is protected by $repl above. 1113'_' =>
'_',
'~' =>
'~',
1114"\n" =>
" ",
"\r" =>
" ",
1115"\t" =>
"	",
// "\n\t\n" is treated like "\n\n" 1118// And handle protocols that don't use "://" 1122if ( substr( $prot, -1 ) ===
':' ) {
1123 $repl2[] = preg_quote( substr( $prot, 0, -1 ),
'/' );
1126 $repl2 = $repl2 ?
'/\b(' . implode(
'|', $repl2 ) .
'):/i' :
'/^(?!)/';
1128// Tell phan that $repl2, $repl3 and $repl4 will also be non-null here 1129'@phan-var string $repl2';
1130'@phan-var string $repl3';
1131'@phan-var string $repl4';
1132// This will also stringify input in case it's not a string 1133 $text = substr( strtr(
"\n$input", $repl ), 1 );
1137 $first = strtr( $text[0], $repl3 );
// protect first character 1138if ( strlen( $text ) > 1 ) {
1139 $text = $first . substr( $text, 1, -1 ) .
1140 strtr( substr( $text, -1 ), $repl4 );
// protect last character 1142// special case for single-character strings 1143 $text = strtr( $first, $repl4 );
// protect last character 1145 $text = preg_replace( $repl2,
'$1:', $text );
1161if (
$source !==
null || $force ) {
1177 $temp = (bool)( $dest & $bit );
1178if ( $state !==
null ) {
1196 $s = str_replace(
"\n",
"<br />\n", var_export( $var,
true ) .
"\n" );
1197if ( headers_sent() ||
$wgOut ===
null || !is_object(
$wgOut ) ) {
1213 HttpStatus::header( $code );
1216$wgOut->sendCacheControl();
1219 \MediaWiki\Request\HeaderCallback::warnIfHeadersSent();
1220 header(
'Content-type: text/html; charset=utf-8' );
1221 ContentSecurityPolicy::sendRestrictiveHeader();
1223 print
'<!DOCTYPE html>' .
1224'<html><head><title>' .
1225 htmlspecialchars( $label ) .
1226'</title><meta name="color-scheme" content="light dark" /></head><body><h1>' .
1227 htmlspecialchars( $label ) .
1229 nl2br( htmlspecialchars( $desc ) ) .
1230"</p></body></html>\n";
1231 header(
'Content-Length: ' . ob_get_length() );
1256// phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition 1257while ( $status = ob_get_status() ) {
1258if ( isset( $status[
'flags'] ) ) {
1259 $flags = PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_REMOVABLE;
1260 $deleteable = ( $status[
'flags'] & $flags ) === $flags;
1261 } elseif ( isset( $status[
'del'] ) ) {
1262 $deleteable = $status[
'del'];
1264// Guess that any PHP-internal setting can't be removed. 1265 $deleteable = $status[
'type'] !== 0;
/* PHP_OUTPUT_HANDLER_INTERNAL */ 1267if ( !$deleteable ) {
1268// Give up, and hope the result doesn't break 1272if ( $status[
'name'] ===
'MediaWikiIntegrationTestCase::wfResetOutputBuffersBarrier' ) {
1273// Unit testing barrier to prevent this function from breaking PHPUnit. 1276if ( !ob_end_clean() ) {
1277// Could not remove output buffer handler; abort now 1278// to avoid getting in some kind of infinite loop. 1281if ( $resetGzipEncoding && $status[
'name'] ==
'ob_gzhandler' ) {
1282// Reset the 'Content-Encoding' field set by this handler 1283// so we can start fresh. 1284 header_remove(
'Content-Encoding' );
1301 $ret = ConvertibleTimestamp::convert( $outputtype, $ts );
1302if ( $ret ===
false ) {
1303wfDebug(
"wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts" );
1330return ConvertibleTimestamp::now( TS_MW );
1351return TempFSFile::getUsableTempDirectory();
1365if ( FileBackend::isStoragePath( $dir ) ) {
1366thrownew LogicException( __FUNCTION__ .
" given storage path '$dir'." );
1368if ( $caller !==
null ) {
1369wfDebug(
"$caller: called wfMkdirParents($dir)" );
1371if ( strval( $dir ) ===
'' ) {
1375 $dir = str_replace( [
'\\',
'/' ], DIRECTORY_SEPARATOR, $dir );
1378// Turn off the normal warning, we're doing our own below 1379// PHP doesn't include the path in its warning message, so we add our own to aid in diagnosis. 1381// Repeat existence check if creation failed so that we silently recover in case of 1382// a race condition where another request created it since the first check. 1384// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged 1385 $ok = is_dir( $dir ) || @mkdir( $dir, $mode,
true ) || is_dir( $dir );
1387 trigger_error( sprintf(
"failed to mkdir \"%s\" mode 0%o", $dir, $mode ), E_USER_WARNING );
1399// taken from https://www.php.net/manual/en/function.rmdir.php#98622 1400if ( is_dir( $dir ) ) {
1401 $objects = scandir( $dir );
1402foreach ( $objects as $object ) {
1403if ( $object !=
"." && $object !=
".." ) {
1404if ( filetype( $dir .
'/' . $object ) ==
"dir" ) {
1407 unlink( $dir .
'/' . $object );
1422 $accForFormat = $acc >= 0 ? $acc : 0;
1423 $ret = sprintf(
"%.{$accForFormat}f", $nr );
1424return $round ? round( (
float)$ret, $acc ) .
'%' :
"$ret%";
1467 $val = strtolower( $val );
1468// 'on' and 'true' can't have whitespace around them, but '1' can. 1472 || preg_match(
"/^\s*[+-]?0*[1-9]/", $val );
// approx C atoi() function 1489return Shell::escape( ...$args );
1517 $limits = [], $options = []
1519if ( Shell::isDisabled() ) {
1521// Backwards compatibility be upon us... 1522return'Unable to run external programs, proc_open() is disabled.';
1525if ( is_array( $cmd ) ) {
1526 $cmd = Shell::escape( $cmd );
1529 $includeStderr = isset( $options[
'duplicateStderr'] ) && $options[
'duplicateStderr'];
1530 $profileMethod = $options[
'profileMethod'] ??
wfGetCaller();
1533 $result = Shell::command( [] )
1534 ->unsafeParams( (array)$cmd )
1535 ->environment( $environ )
1537 ->includeStderr( $includeStderr )
1538 ->profileMethod( $profileMethod )
1540 ->restrict( Shell::RESTRICT_NONE )
1547 $retval = $result->getExitCode();
1549return $result->getStdout();
1570returnwfShellExec( $cmd, $retval, $environ, $limits,
1571 [
'duplicateStderr' =>
true,
'profileMethod' =>
wfGetCaller() ] );
1591// Give site config file a chance to run the script in a wrapper. 1592// The caller may likely want to call wfBasename() on $script. 1593 (
newHookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
1594 ->onWfShellWikiCmd( $script, $parameters, $options );
1596if ( isset( $options[
'wrapper'] ) ) {
1597 $cmd[] = $options[
'wrapper'];
1600// Escape each parameter for shell 1601return Shell::escape( array_merge( $cmd, $parameters ) );
1624 ?
string &$simplisticMergeAttempt,
1625 ?
string &$mergeLeftovers =
null 1629 # This check may also protect against code injection in 1630 # case of broken installations. 1631 AtEase::suppressWarnings();
1633 AtEase::restoreWarnings();
1640 # Make temporary files 1642 $oldtextFile = fopen( $oldtextName = tempnam( $td,
'merge-old-' ),
'w' );
1643 $mytextFile = fopen( $mytextName = tempnam( $td,
'merge-mine-' ),
'w' );
1644 $yourtextFile = fopen( $yourtextName = tempnam( $td,
'merge-your-' ),
'w' );
1646 # NOTE: diff3 issues a warning to stderr if any of the files does not end with 1647 # a newline character. To avoid this, we normalize the trailing whitespace before 1648 # creating the diff. 1650 fwrite( $oldtextFile, rtrim( $old ) .
"\n" );
1651 fclose( $oldtextFile );
1652 fwrite( $mytextFile, rtrim( $mine ) .
"\n" );
1653 fclose( $mytextFile );
1654 fwrite( $yourtextFile, rtrim( $yours ) .
"\n" );
1655 fclose( $yourtextFile );
1657 # Check for a conflict 1658 $cmd = Shell::escape(
$wgDiff3,
'--text',
'--overlap-only', $mytextName,
1659 $oldtextName, $yourtextName );
1660 $handle = popen( $cmd,
'r' );
1662 $mergeLeftovers =
'';
1664 $data = fread( $handle, 8192 );
1665if ( $data ===
false || $data ===
'' ) {
1668 $mergeLeftovers .= $data;
1672 $conflict = $mergeLeftovers !==
'';
1674 # Merge differences automatically where possible, preferring "my" text for conflicts. 1675 $cmd = Shell::escape(
$wgDiff3,
'--text',
'--ed',
'--merge', $mytextName,
1676 $oldtextName, $yourtextName );
1677 $handle = popen( $cmd,
'r' );
1678 $simplisticMergeAttempt =
'';
1680 $data = fread( $handle, 8192 );
1681if ( $data ===
false || $data ===
'' ) {
1684 $simplisticMergeAttempt .= $data;
1687 unlink( $mytextName );
1688 unlink( $oldtextName );
1689 unlink( $yourtextName );
1691if ( $simplisticMergeAttempt ===
'' && $old !==
'' && !$conflict ) {
1692wfDebug(
"Unexpected null result from diff3. Command: $cmd" );
1711if ( $suffix ==
'' ) {
1714 $encSuffix =
'(?:' . preg_quote( $suffix,
'#' ) .
')?';
1718if ( preg_match(
"#([^/\\\\]*?){$encSuffix}[/\\\\]*$#",
$path,
$matches ) ) {
1735// Normalize mixed input on Windows... 1736$path = str_replace(
'/', DIRECTORY_SEPARATOR,
$path );
1737 $from = str_replace(
'/', DIRECTORY_SEPARATOR, $from );
1739// Trim trailing slashes -- fix for drive root 1741 $from = rtrim( $from, DIRECTORY_SEPARATOR );
1743 $pieces = explode( DIRECTORY_SEPARATOR, dirname(
$path ) );
1744 $against = explode( DIRECTORY_SEPARATOR, $from );
1746if ( $pieces[0] !== $against[0] ) {
1747// Non-matching Windows drive letters? 1748// Return a full path. 1752// Trim off common prefix 1753while ( count( $pieces ) && count( $against )
1754 && $pieces[0] == $against[0] ) {
1755 array_shift( $pieces );
1756 array_shift( $against );
1759// relative dots to bump us to the parent 1760while ( count( $against ) ) {
1761 array_unshift( $pieces,
'..' );
1762 array_shift( $against );
1767return implode( DIRECTORY_SEPARATOR, $pieces );
1781if ( $script ===
'index' ) {
1783 } elseif ( $script ===
'load' ) {
1786return"{$wgScriptPath}/{$script}.php";
1798return $value ?
'true' :
'false';
1821 $name = preg_replace(
1822"/[^" . Title::legalChars() .
"]" . $illegalFileChars .
"/",
1826// $wgIllegalFileChars may not include '/' and '\', so we still need to do this 1839// If the INI config is already unlimited, there is nothing larger 1840if ( $oldLimit != -1 ) {
1842if ( $newLimit == -1 ) {
1843wfDebug(
"Removing PHP's memory limit" );
1844 AtEase::suppressWarnings();
1845 ini_set(
'memory_limit', $newLimit );
1846 AtEase::restoreWarnings();
1847 } elseif ( $newLimit > $oldLimit ) {
1848wfDebug(
"Raising PHP's memory limit to $newLimit bytes" );
1849 AtEase::suppressWarnings();
1850 ini_set(
'memory_limit', $newLimit );
1851 AtEase::restoreWarnings();
1865 $timeout = RequestTimeout::singleton();
1866 $timeLimit = $timeout->getWallTimeLimit();
1867if ( $timeLimit !== INF ) {
1868// RequestTimeout library is active 1873// Fallback case, likely $wgRequestTimeLimit === null 1874 $timeLimit = (int)ini_get(
'max_execution_time' );
1875// Note that CLI scripts use 0 1880 ignore_user_abort(
true );
// ignore client disconnects 1893 $string = trim( $string ??
'' );
1894if ( $string ===
'' ) {
1897 $last = substr( $string, -1 );
1898 $val = intval( $string );
1903// break intentionally missing 1907// break intentionally missing 1924// The INFINITY_VALS are hardcoded elsewhere in MediaWiki (e.g. mediawiki.special.block.js). 1925return in_array( $str, ExpiryDef::INFINITY_VALS );
1945 $multipliers = [ 1 ];
1947// These available sizes are hardcoded currently elsewhere in MediaWiki. 1948// @see Linker::processResponsiveImages 1949 $multipliers[] = 1.5;
1954if ( !$handler || !isset( $params[
'width'] ) ) {
1959if ( isset( $params[
'page'] ) ) {
1960 $basicParams[
'page'] = $params[
'page'];
1965// Expand limits to account for multipliers 1966foreach ( $multipliers as $multiplier ) {
1967 $thumbLimits = array_merge( $thumbLimits, array_map(
1968staticfunction ( $width ) use ( $multiplier ) {
1969return round( $width * $multiplier );
1972 $imageLimits = array_merge( $imageLimits, array_map(
1973staticfunction ( $pair ) use ( $multiplier ) {
1975 round( $pair[0] * $multiplier ),
1976 round( $pair[1] * $multiplier ),
1982// Check if the width matches one of $wgThumbLimits 1983if ( in_array( $params[
'width'], $thumbLimits ) ) {
1984 $normalParams = $basicParams + [
'width' => $params[
'width'] ];
1985// Append any default values to the map (e.g. "lossy", "lossless", ...) 1986 $handler->normaliseParams( $file, $normalParams );
1988// If not, then check if the width matches one of $wgImageLimits 1990foreach ( $imageLimits as $pair ) {
1991 $normalParams = $basicParams + [
'width' => $pair[0],
'height' => $pair[1] ];
1992// Decide whether the thumbnail should be scaled on width or height. 1993// Also append any default values to the map (e.g. "lossy", "lossless", ...) 1994 $handler->normaliseParams( $file, $normalParams );
1995// Check if this standard thumbnail size maps to the given width 1996if ( $normalParams[
'width'] == $params[
'width'] ) {
2002returnfalse;
// not standard for description pages 2006// Check that the given values for non-page, non-width, params are just defaults 2007foreach ( $params as $key => $value ) {
2008if ( !isset( $normalParams[$key] ) || $normalParams[$key] != $value ) {
2029// First merge items that are in both arrays 2030foreach ( $baseArray as $name => &$groupVal ) {
2031if ( isset( $newValues[$name] ) ) {
2032 $groupVal += $newValues[$name];
2035// Now add items that didn't exist yet 2036 $baseArray += $newValues;
wfIsWindows()
Check if the operating system is Windows.
wfThumbIsStandard(File $file, array $params)
Returns true if these thumbnail parameters match one that MediaWiki requests from file description pa...
wfVarDump( $var)
A wrapper around the PHP function var_export().
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
wfTempDir()
Tries to get the system directory for temporary files.
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
wfBaseName( $path, $suffix='')
Return the final portion of a pathname.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfClientAcceptsGzip( $force=false)
Whether the client accept gzip encoding.
wfEscapeShellArg(... $args)
Locale-independent version of escapeshellarg()
wfLogDBError( $text, array $context=[])
Log for database errors.
wfLoadSkins(array $skins)
Load multiple skins at once.
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfUrlProtocolsWithoutProtRel()
Like wfUrlProtocols(), but excludes '//' from the protocol list.
wfRecursiveRemoveDir( $dir)
Remove a directory and all its content.
wfLoadExtension( $ext, $path=null)
Load an extension.
wfMemoryLimit( $newLimit)
Raise PHP's memory limit (if needed).
wfSetBit(&$dest, $bit, $state=true)
As for wfSetVar except setting a bit.
wfIniGetBool( $setting)
Safety wrapper around ini_get() for boolean settings.
wfShorthandToInteger(?string $string='', int $default=-1)
Converts shorthand byte notation to integer form.
wfBacktrace( $raw=null)
Get a debug backtrace as a string.
wfArrayDiff2( $arr1, $arr2)
Like array_diff( $arr1, $arr2 ) except that it works with two-dimensional arrays.
wfGetCaller( $level=2)
Get the name of the function which called this function wfGetCaller( 1 ) is the function with the wfG...
wfMergeErrorArrays(... $args)
Merge arrays in the style of PermissionManager::getPermissionErrors, with duplicate removal e....
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
wfShellExec( $cmd, &$retval=null, $environ=[], $limits=[], $options=[])
Execute a shell command, with time and memory limits mirrored from the PHP configuration if supported...
wfIsDebugRawPage()
Returns true if debug logging should be suppressed if $wgDebugRawPage = false.
wfHostname()
Get host name of the current machine, for use in error reporting.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL using $wgServer (or one of its alternatives).
wfShellWikiCmd( $script, array $parameters=[], array $options=[])
Generate a shell-escaped command line string to run a MediaWiki cli script.
wfPercent( $nr, int $acc=2, bool $round=true)
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
wfShellExecWithStderr( $cmd, &$retval=null, $environ=[], $limits=[])
Execute a shell command, returning both stdout and stderr.
wfGetNull()
Get a platform-independent path to the null file, e.g.
wfRelativePath( $path, $from)
Generate a relative path name to the given file.
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
wfUrlProtocols( $includeProtocolRelative=true)
Returns a partial regular expression of recognized URL protocols, e.g.
wfMessageFallback(... $keys)
This function accepts multiple message keys and returns a message instance for the first message whic...
wfMerge(string $old, string $mine, string $yours, ?string &$simplisticMergeAttempt, ?string &$mergeLeftovers=null)
wfMerge attempts to merge differences between three texts.
wfGetAllCallers( $limit=3)
Return a string consisting of callers in the stack.
wfArrayPlus2d(array $baseArray, array $newValues)
Merges two (possibly) 2 dimensional arrays into the target array ($baseArray).
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
wfTransactionalTimeLimit()
Raise the request time limit to $wgTransactionalTimeLimit.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfObjectToArray( $objOrArray, $recursive=true)
Recursively converts the parameter (an object) to an array with the same data.
wfLoadSkin( $skin, $path=null)
Load a skin.
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
wfStringToBool( $val)
Convert string value to boolean, when the following are interpreted as true:
wfDebugBacktrace( $limit=0)
Safety wrapper for debug_backtrace().
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfStripIllegalFilenameChars( $name)
Replace all invalid characters with '-'.
wfFormatStackFrame( $frame)
Return a string representation of frame.
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
wfScript( $script='index')
Get the URL path to a MediaWiki entry point.
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
wfMatchesDomainList( $url, $domains)
Check whether a given URL has a domain that occurs in a given set of domains.
wfIsInfinity( $str)
Determine input string is represents as infinity.
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfLoadExtensions(array $exts)
Load multiple extensions at once.
wfBoolToStr( $value)
Convenience function converts boolean values into "true" or "false" (string) values.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
wfArrayInsertAfter(array $array, array $insert, $after)
Insert an array into another array after the specified key.
wfAssembleUrl( $urlParts)
This function will reassemble a URL parsed with wfParseURL.
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
if(MW_ENTRY_POINT==='index') if(!defined( 'MW_NO_SESSION') &&MW_ENTRY_POINT !=='cli' $wgOut
Implements some public methods and some protected utility functions which are required by multiple ch...
getHandler()
Get a MediaHandler instance for this file.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Create PSR-3 logger objects.
Service locator for MediaWiki core services.
The Message class deals with fetching and processing of interface message into a variety of formats.
Load JSON files, and uses a Processor to extract information.
Handle sending Content-Security-Policy headers.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
Represents a title within MediaWiki.
A service to expand, parse, and otherwise manipulate URLs.
This class is used to hold the location and do limited manipulation of files stored temporarily (this...
Base class for all file backend classes (including multi-write backends).
Value object representing a message parameter that consists of a list of values.
Type definition for expiry timestamps.
$wgScript
Config variable stub for the Script setting, for use by phpdoc and IDEs.
$wgInternalServer
Config variable stub for the InternalServer setting, for use by phpdoc and IDEs.
$wgThumbLimits
Config variable stub for the ThumbLimits setting, for use by phpdoc and IDEs.
$wgDebugLogPrefix
Config variable stub for the DebugLogPrefix setting, for use by phpdoc and IDEs.
$wgPhpCli
Config variable stub for the PhpCli setting, for use by phpdoc and IDEs.
$wgOverrideHostname
Config variable stub for the OverrideHostname setting, for use by phpdoc and IDEs.
$wgImageLimits
Config variable stub for the ImageLimits setting, for use by phpdoc and IDEs.
$wgTmpDirectory
Config variable stub for the TmpDirectory setting, for use by phpdoc and IDEs.
$wgStyleDirectory
Config variable stub for the StyleDirectory setting, for use by phpdoc and IDEs.
$wgTransactionalTimeLimit
Config variable stub for the TransactionalTimeLimit setting, for use by phpdoc and IDEs.
$wgIllegalFileChars
Config variable stub for the IllegalFileChars setting, for use by phpdoc and IDEs.
$wgDirectoryMode
Config variable stub for the DirectoryMode setting, for use by phpdoc and IDEs.
$wgDiff3
Config variable stub for the Diff3 setting, for use by phpdoc and IDEs.
$wgUrlProtocols
Config variable stub for the UrlProtocols setting, for use by phpdoc and IDEs.
$wgResponsiveImages
Config variable stub for the ResponsiveImages setting, for use by phpdoc and IDEs.
$wgDebugRawPage
Config variable stub for the DebugRawPage setting, for use by phpdoc and IDEs.
$wgEnableMagicLinks
Config variable stub for the EnableMagicLinks setting, for use by phpdoc and IDEs.
$wgScriptPath
Config variable stub for the ScriptPath setting, for use by phpdoc and IDEs.
$wgExtensionDirectory
Config variable stub for the ExtensionDirectory setting, for use by phpdoc and IDEs.
$wgLoadScript
Config variable stub for the LoadScript setting, for use by phpdoc and IDEs.
$wgCanonicalServer
Config variable stub for the CanonicalServer setting, for use by phpdoc and IDEs.
$wgServer
Config variable stub for the Server setting, for use by phpdoc and IDEs.
$wgHttpsPort
Config variable stub for the HttpsPort setting, for use by phpdoc and IDEs.