MediaWiki  master
GlobalFunctions.php
Go to the documentation of this file.
1 <?php
23 if ( !defined( 'MEDIAWIKI' ) ) {
24  die( "This file is part of MediaWiki, it is not a valid entry point" );
25 }
26 
32 use Wikimedia\AtEase\AtEase;
34 use Wikimedia\RequestTimeout\RequestTimeout;
35 use Wikimedia\WrappedString;
36 
47 function wfLoadExtension( $ext, $path = null ) {
48  if ( !$path ) {
49  global $wgExtensionDirectory;
50  $path = "$wgExtensionDirectory/$ext/extension.json";
51  }
53 }
54 
68 function wfLoadExtensions( array $exts ) {
69  global $wgExtensionDirectory;
70  $registry = ExtensionRegistry::getInstance();
71  foreach ( $exts as $ext ) {
72  $registry->queue( "$wgExtensionDirectory/$ext/extension.json" );
73  }
74 }
75 
84 function wfLoadSkin( $skin, $path = null ) {
85  if ( !$path ) {
86  global $wgStyleDirectory;
87  $path = "$wgStyleDirectory/$skin/skin.json";
88  }
90 }
91 
99 function wfLoadSkins( array $skins ) {
100  global $wgStyleDirectory;
101  $registry = ExtensionRegistry::getInstance();
102  foreach ( $skins as $skin ) {
103  $registry->queue( "$wgStyleDirectory/$skin/skin.json" );
104  }
105 }
106 
113 function wfArrayDiff2( $a, $b ) {
114  return array_udiff( $a, $b, 'wfArrayDiff2_cmp' );
115 }
116 
122 function wfArrayDiff2_cmp( $a, $b ) {
123  if ( is_string( $a ) && is_string( $b ) ) {
124  return strcmp( $a, $b );
125  } elseif ( count( $a ) !== count( $b ) ) {
126  return count( $a ) <=> count( $b );
127  } else {
128  reset( $a );
129  reset( $b );
130  while ( key( $a ) !== null && key( $b ) !== null ) {
131  $valueA = current( $a );
132  $valueB = current( $b );
133  $cmp = strcmp( $valueA, $valueB );
134  if ( $cmp !== 0 ) {
135  return $cmp;
136  }
137  next( $a );
138  next( $b );
139  }
140  return 0;
141  }
142 }
143 
154 function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
155  wfDeprecated( __FUNCTION__, '1.36' );
156 
157  if ( $changed === null ) {
158  throw new MWException( 'GlobalFunctions::wfAppendToArrayIfNotDefault got null' );
159  }
160  if ( $default[$key] !== $value ) {
161  $changed[$key] = $value;
162  }
163 }
164 
184 function wfMergeErrorArrays( ...$args ) {
185  $out = [];
186  foreach ( $args as $errors ) {
187  foreach ( $errors as $params ) {
188  $originalParams = $params;
189  if ( $params[0] instanceof MessageSpecifier ) {
190  $msg = $params[0];
191  $params = array_merge( [ $msg->getKey() ], $msg->getParams() );
192  }
193  # @todo FIXME: Sometimes get nested arrays for $params,
194  # which leads to E_NOTICEs
195  $spec = implode( "\t", $params );
196  $out[$spec] = $originalParams;
197  }
198  }
199  return array_values( $out );
200 }
201 
210 function wfArrayInsertAfter( array $array, array $insert, $after ) {
211  // Find the offset of the element to insert after.
212  $keys = array_keys( $array );
213  $offsetByKey = array_flip( $keys );
214 
215  $offset = $offsetByKey[$after];
216 
217  // Insert at the specified offset
218  $before = array_slice( $array, 0, $offset + 1, true );
219  $after = array_slice( $array, $offset + 1, count( $array ) - $offset, true );
220 
221  $output = $before + $insert + $after;
222 
223  return $output;
224 }
225 
234 function wfObjectToArray( $objOrArray, $recursive = true ) {
235  $array = [];
236  if ( is_object( $objOrArray ) ) {
237  $objOrArray = get_object_vars( $objOrArray );
238  }
239  foreach ( $objOrArray as $key => $value ) {
240  if ( $recursive && ( is_object( $value ) || is_array( $value ) ) ) {
241  $value = wfObjectToArray( $value );
242  }
243 
244  $array[$key] = $value;
245  }
246 
247  return $array;
248 }
249 
260 function wfRandom() {
261  // The maximum random value is "only" 2^31-1, so get two random
262  // values to reduce the chance of dupes
263  $max = mt_getrandmax() + 1;
264  $rand = number_format( ( mt_rand() * $max + mt_rand() ) / $max / $max, 12, '.', '' );
265  return $rand;
266 }
267 
278 function wfRandomString( $length = 32 ) {
279  $str = '';
280  for ( $n = 0; $n < $length; $n += 7 ) {
281  $str .= sprintf( '%07x', mt_rand() & 0xfffffff );
282  }
283  return substr( $str, 0, $length );
284 }
285 
313 function wfUrlencode( $s ) {
314  static $needle;
315 
316  if ( $s === null ) {
317  // Reset $needle for testing.
318  $needle = null;
319  return '';
320  }
321 
322  if ( $needle === null ) {
323  $needle = [ '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F', '%7E' ];
324  if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
325  ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
326  ) {
327  $needle[] = '%3A';
328  }
329  }
330 
331  $s = urlencode( $s );
332  $s = str_ireplace(
333  $needle,
334  [ ';', '@', '$', '!', '*', '(', ')', ',', '/', '~', ':' ],
335  $s
336  );
337 
338  return $s;
339 }
340 
351 function wfArrayToCgi( $array1, $array2 = null, $prefix = '' ) {
352  if ( $array2 !== null ) {
353  $array1 += $array2;
354  }
355 
356  $cgi = '';
357  foreach ( $array1 as $key => $value ) {
358  if ( $value !== null && $value !== false ) {
359  if ( $cgi != '' ) {
360  $cgi .= '&';
361  }
362  if ( $prefix !== '' ) {
363  $key = $prefix . "[$key]";
364  }
365  if ( is_array( $value ) ) {
366  $firstTime = true;
367  foreach ( $value as $k => $v ) {
368  $cgi .= $firstTime ? '' : '&';
369  if ( is_array( $v ) ) {
370  $cgi .= wfArrayToCgi( $v, null, $key . "[$k]" );
371  } else {
372  $cgi .= urlencode( $key . "[$k]" ) . '=' . urlencode( $v );
373  }
374  $firstTime = false;
375  }
376  } else {
377  if ( is_object( $value ) ) {
378  $value = $value->__toString();
379  }
380  $cgi .= urlencode( $key ) . '=' . urlencode( $value );
381  }
382  }
383  }
384  return $cgi;
385 }
386 
396 function wfCgiToArray( $query ) {
397  if ( isset( $query[0] ) && $query[0] == '?' ) {
398  $query = substr( $query, 1 );
399  }
400  $bits = explode( '&', $query );
401  $ret = [];
402  foreach ( $bits as $bit ) {
403  if ( $bit === '' ) {
404  continue;
405  }
406  if ( strpos( $bit, '=' ) === false ) {
407  // Pieces like &qwerty become 'qwerty' => '' (at least this is what php does)
408  $key = $bit;
409  $value = '';
410  } else {
411  list( $key, $value ) = explode( '=', $bit );
412  }
413  $key = urldecode( $key );
414  $value = urldecode( $value );
415  if ( strpos( $key, '[' ) !== false ) {
416  $keys = array_reverse( explode( '[', $key ) );
417  $key = array_pop( $keys );
418  $temp = $value;
419  foreach ( $keys as $k ) {
420  $k = substr( $k, 0, -1 );
421  $temp = [ $k => $temp ];
422  }
423  if ( isset( $ret[$key] ) ) {
424  $ret[$key] = array_merge( $ret[$key], $temp );
425  } else {
426  $ret[$key] = $temp;
427  }
428  } else {
429  $ret[$key] = $value;
430  }
431  }
432  return $ret;
433 }
434 
443 function wfAppendQuery( $url, $query ) {
444  if ( is_array( $query ) ) {
445  $query = wfArrayToCgi( $query );
446  }
447  if ( $query != '' ) {
448  // Remove the fragment, if there is one
449  $fragment = false;
450  $hashPos = strpos( $url, '#' );
451  if ( $hashPos !== false ) {
452  $fragment = substr( $url, $hashPos );
453  $url = substr( $url, 0, $hashPos );
454  }
455 
456  // Add parameter
457  if ( strpos( $url, '?' ) === false ) {
458  $url .= '?';
459  } else {
460  $url .= '&';
461  }
462  $url .= $query;
463 
464  // Put the fragment back
465  if ( $fragment !== false ) {
466  $url .= $fragment;
467  }
468  }
469  return $url;
470 }
471 
495 function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
497  $wgHttpsPort;
498  if ( $defaultProto === PROTO_CANONICAL ) {
499  $serverUrl = $wgCanonicalServer;
500  } elseif ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
501  // Make $wgInternalServer fall back to $wgServer if not set
502  $serverUrl = $wgInternalServer;
503  } else {
504  $serverUrl = $wgServer;
505  if ( $defaultProto === PROTO_CURRENT ) {
506  $defaultProto = $wgRequest->getProtocol() . '://';
507  }
508  }
509 
510  // Analyze $serverUrl to obtain its protocol
511  $bits = wfParseUrl( $serverUrl );
512  $serverHasProto = $bits && $bits['scheme'] != '';
513 
514  if ( $defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL ) {
515  if ( $serverHasProto ) {
516  $defaultProto = $bits['scheme'] . '://';
517  } else {
518  // $wgCanonicalServer or $wgInternalServer doesn't have a protocol.
519  // This really isn't supposed to happen. Fall back to HTTP in this
520  // ridiculous case.
521  $defaultProto = PROTO_HTTP;
522  }
523  }
524 
525  $defaultProtoWithoutSlashes = $defaultProto !== null ? substr( $defaultProto, 0, -2 ) : '';
526 
527  if ( substr( $url, 0, 2 ) == '//' ) {
528  $url = $defaultProtoWithoutSlashes . $url;
529  } elseif ( substr( $url, 0, 1 ) == '/' ) {
530  // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes,
531  // otherwise leave it alone.
532  if ( $serverHasProto ) {
533  $url = $serverUrl . $url;
534  } else {
535  // If an HTTPS URL is synthesized from a protocol-relative $wgServer, allow the
536  // user to override the port number (T67184)
537  if ( $defaultProto === PROTO_HTTPS && $wgHttpsPort != 443 ) {
538  if ( isset( $bits['port'] ) ) {
539  throw new Exception( 'A protocol-relative $wgServer may not contain a port number' );
540  }
541  $url = $defaultProtoWithoutSlashes . $serverUrl . ':' . $wgHttpsPort . $url;
542  } else {
543  $url = $defaultProtoWithoutSlashes . $serverUrl . $url;
544  }
545  }
546  }
547 
548  $bits = wfParseUrl( $url );
549 
550  if ( $bits && isset( $bits['path'] ) ) {
551  $bits['path'] = wfRemoveDotSegments( $bits['path'] );
552  return wfAssembleUrl( $bits );
553  } elseif ( $bits ) {
554  # No path to expand
555  return $url;
556  } elseif ( substr( $url, 0, 1 ) != '/' ) {
557  # URL is a relative path
558  return wfRemoveDotSegments( $url );
559  }
560 
561  # Expanded URL is not valid.
562  return false;
563 }
564 
573 function wfGetServerUrl( $proto ) {
574  $url = wfExpandUrl( '/', $proto );
575  return substr( $url, 0, -1 );
576 }
577 
591 function wfAssembleUrl( $urlParts ) {
592  $result = '';
593 
594  if ( isset( $urlParts['delimiter'] ) ) {
595  if ( isset( $urlParts['scheme'] ) ) {
596  $result .= $urlParts['scheme'];
597  }
598 
599  $result .= $urlParts['delimiter'];
600  }
601 
602  if ( isset( $urlParts['host'] ) ) {
603  if ( isset( $urlParts['user'] ) ) {
604  $result .= $urlParts['user'];
605  if ( isset( $urlParts['pass'] ) ) {
606  $result .= ':' . $urlParts['pass'];
607  }
608  $result .= '@';
609  }
610 
611  $result .= $urlParts['host'];
612 
613  if ( isset( $urlParts['port'] ) ) {
614  $result .= ':' . $urlParts['port'];
615  }
616  }
617 
618  if ( isset( $urlParts['path'] ) ) {
619  $result .= $urlParts['path'];
620  }
621 
622  if ( isset( $urlParts['query'] ) && $urlParts['query'] !== '' ) {
623  $result .= '?' . $urlParts['query'];
624  }
625 
626  if ( isset( $urlParts['fragment'] ) ) {
627  $result .= '#' . $urlParts['fragment'];
628  }
629 
630  return $result;
631 }
632 
645 function wfRemoveDotSegments( $urlPath ) {
646  $output = '';
647  $inputOffset = 0;
648  $inputLength = strlen( $urlPath );
649 
650  while ( $inputOffset < $inputLength ) {
651  $prefixLengthOne = substr( $urlPath, $inputOffset, 1 );
652  $prefixLengthTwo = substr( $urlPath, $inputOffset, 2 );
653  $prefixLengthThree = substr( $urlPath, $inputOffset, 3 );
654  $prefixLengthFour = substr( $urlPath, $inputOffset, 4 );
655  $trimOutput = false;
656 
657  if ( $prefixLengthTwo == './' ) {
658  # Step A, remove leading "./"
659  $inputOffset += 2;
660  } elseif ( $prefixLengthThree == '../' ) {
661  # Step A, remove leading "../"
662  $inputOffset += 3;
663  } elseif ( ( $prefixLengthTwo == '/.' ) && ( $inputOffset + 2 == $inputLength ) ) {
664  # Step B, replace leading "/.$" with "/"
665  $inputOffset += 1;
666  $urlPath[$inputOffset] = '/';
667  } elseif ( $prefixLengthThree == '/./' ) {
668  # Step B, replace leading "/./" with "/"
669  $inputOffset += 2;
670  } elseif ( $prefixLengthThree == '/..' && ( $inputOffset + 3 == $inputLength ) ) {
671  # Step C, replace leading "/..$" with "/" and
672  # remove last path component in output
673  $inputOffset += 2;
674  $urlPath[$inputOffset] = '/';
675  $trimOutput = true;
676  } elseif ( $prefixLengthFour == '/../' ) {
677  # Step C, replace leading "/../" with "/" and
678  # remove last path component in output
679  $inputOffset += 3;
680  $trimOutput = true;
681  } elseif ( ( $prefixLengthOne == '.' ) && ( $inputOffset + 1 == $inputLength ) ) {
682  # Step D, remove "^.$"
683  $inputOffset += 1;
684  } elseif ( ( $prefixLengthTwo == '..' ) && ( $inputOffset + 2 == $inputLength ) ) {
685  # Step D, remove "^..$"
686  $inputOffset += 2;
687  } else {
688  # Step E, move leading path segment to output
689  if ( $prefixLengthOne == '/' ) {
690  $slashPos = strpos( $urlPath, '/', $inputOffset + 1 );
691  } else {
692  $slashPos = strpos( $urlPath, '/', $inputOffset );
693  }
694  if ( $slashPos === false ) {
695  $output .= substr( $urlPath, $inputOffset );
696  $inputOffset = $inputLength;
697  } else {
698  $output .= substr( $urlPath, $inputOffset, $slashPos - $inputOffset );
699  $inputOffset += $slashPos - $inputOffset;
700  }
701  }
702 
703  if ( $trimOutput ) {
704  $slashPos = strrpos( $output, '/' );
705  if ( $slashPos === false ) {
706  $output = '';
707  } else {
708  $output = substr( $output, 0, $slashPos );
709  }
710  }
711  }
712 
713  return $output;
714 }
715 
723 function wfUrlProtocols( $includeProtocolRelative = true ) {
724  global $wgUrlProtocols;
725 
726  // Cache return values separately based on $includeProtocolRelative
727  static $withProtRel = null, $withoutProtRel = null;
728  $cachedValue = $includeProtocolRelative ? $withProtRel : $withoutProtRel;
729  if ( $cachedValue !== null ) {
730  return $cachedValue;
731  }
732 
733  // Support old-style $wgUrlProtocols strings, for backwards compatibility
734  // with LocalSettings files from 1.5
735  if ( is_array( $wgUrlProtocols ) ) {
736  $protocols = [];
737  foreach ( $wgUrlProtocols as $protocol ) {
738  // Filter out '//' if !$includeProtocolRelative
739  if ( $includeProtocolRelative || $protocol !== '//' ) {
740  $protocols[] = preg_quote( $protocol, '/' );
741  }
742  }
743 
744  $retval = implode( '|', $protocols );
745  } else {
746  // Ignore $includeProtocolRelative in this case
747  // This case exists for pre-1.6 compatibility, and we can safely assume
748  // that '//' won't appear in a pre-1.6 config because protocol-relative
749  // URLs weren't supported until 1.18
750  $retval = $wgUrlProtocols;
751  }
752 
753  // Cache return value
754  if ( $includeProtocolRelative ) {
755  $withProtRel = $retval;
756  } else {
757  $withoutProtRel = $retval;
758  }
759  return $retval;
760 }
761 
769  return wfUrlProtocols( false );
770 }
771 
797 function wfParseUrl( $url ) {
798  global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
799 
800  // Protocol-relative URLs are handled really badly by parse_url(). It's so
801  // bad that the easiest way to handle them is to just prepend 'http:' and
802  // strip the protocol out later.
803  $wasRelative = substr( $url, 0, 2 ) == '//';
804  if ( $wasRelative ) {
805  $url = "http:$url";
806  }
807  $bits = parse_url( $url );
808  // parse_url() returns an array without scheme for some invalid URLs, e.g.
809  // parse_url("%0Ahttp://example.com") == [ 'host' => '%0Ahttp', 'path' => 'example.com' ]
810  if ( !$bits || !isset( $bits['scheme'] ) ) {
811  return false;
812  }
813 
814  // parse_url() incorrectly handles schemes case-sensitively. Convert it to lowercase.
815  $bits['scheme'] = strtolower( $bits['scheme'] );
816 
817  // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
818  if ( in_array( $bits['scheme'] . '://', $wgUrlProtocols ) ) {
819  $bits['delimiter'] = '://';
820  } elseif ( in_array( $bits['scheme'] . ':', $wgUrlProtocols ) ) {
821  $bits['delimiter'] = ':';
822  // parse_url detects for news: and mailto: the host part of an url as path
823  // We have to correct this wrong detection
824  if ( isset( $bits['path'] ) ) {
825  $bits['host'] = $bits['path'];
826  $bits['path'] = '';
827  }
828  } else {
829  return false;
830  }
831 
832  /* Provide an empty host for eg. file:/// urls (see T30627) */
833  if ( !isset( $bits['host'] ) ) {
834  $bits['host'] = '';
835 
836  // See T47069
837  if ( isset( $bits['path'] ) ) {
838  /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
839  if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
840  $bits['path'] = '/' . $bits['path'];
841  }
842  } else {
843  $bits['path'] = '';
844  }
845  }
846 
847  // If the URL was protocol-relative, fix scheme and delimiter
848  if ( $wasRelative ) {
849  $bits['scheme'] = '';
850  $bits['delimiter'] = '//';
851  }
852  return $bits;
853 }
854 
865 function wfExpandIRI( $url ) {
866  return preg_replace_callback(
867  '/((?:%[89A-F][0-9A-F])+)/i',
868  static function ( array $matches ) {
869  return urldecode( $matches[1] );
870  },
871  wfExpandUrl( $url )
872  );
873 }
874 
881 function wfMatchesDomainList( $url, $domains ) {
882  $bits = wfParseUrl( $url );
883  if ( is_array( $bits ) && isset( $bits['host'] ) ) {
884  $host = '.' . $bits['host'];
885  foreach ( (array)$domains as $domain ) {
886  $domain = '.' . $domain;
887  if ( substr( $host, -strlen( $domain ) ) === $domain ) {
888  return true;
889  }
890  }
891  }
892  return false;
893 }
894 
915 function wfDebug( $text, $dest = 'all', array $context = [] ) {
917 
918  if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
919  return;
920  }
921 
922  $text = trim( $text );
923 
924  if ( $wgDebugLogPrefix !== '' ) {
925  $context['prefix'] = $wgDebugLogPrefix;
926  }
927  $context['private'] = ( $dest === false || $dest === 'private' );
928 
929  $logger = LoggerFactory::getInstance( 'wfDebug' );
930  $logger->debug( $text, $context );
931 }
932 
937 function wfIsDebugRawPage() {
938  static $cache;
939  if ( $cache !== null ) {
940  return $cache;
941  }
942  // Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
943  // phpcs:ignore MediaWiki.Usage.SuperGlobalsUsage.SuperGlobals
944  if ( ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' )
945  || MW_ENTRY_POINT === 'load'
946  ) {
947  $cache = true;
948  } else {
949  $cache = false;
950  }
951  return $cache;
952 }
953 
960 function wfDebugMem( $exact = false ) {
961  wfDeprecated( __FUNCTION__, '1.36' );
962  $mem = memory_get_usage();
963  if ( !$exact ) {
964  $mem = floor( $mem / 1024 ) . ' KiB';
965  } else {
966  $mem .= ' B';
967  }
968  wfDebug( "Memory usage: $mem" );
969 }
970 
996 function wfDebugLog(
997  $logGroup, $text, $dest = 'all', array $context = []
998 ) {
999  $text = trim( $text );
1000 
1001  $logger = LoggerFactory::getInstance( $logGroup );
1002  $context['private'] = ( $dest === false || $dest === 'private' );
1003  $logger->info( $text, $context );
1004 }
1005 
1014 function wfLogDBError( $text, array $context = [] ) {
1015  $logger = LoggerFactory::getInstance( 'wfLogDBError' );
1016  $logger->error( trim( $text ), $context );
1017 }
1018 
1034 function wfDeprecated( $function, $version = false, $component = false, $callerOffset = 2 ) {
1035  if ( is_string( $version ) || $version === false ) {
1036  MWDebug::deprecated( $function, $version, $component, $callerOffset + 1 );
1037  } else {
1038  throw new InvalidArgumentException(
1039  "MediaWiki version must either be a string or false. " .
1040  "Example valid version: '1.33'"
1041  );
1042  }
1043 }
1044 
1066 function wfDeprecatedMsg( $msg, $version = false, $component = false, $callerOffset = 2 ) {
1067  MWDebug::deprecatedMsg( $msg, $version, $component,
1068  $callerOffset === false ? false : $callerOffset + 1 );
1069 }
1070 
1081 function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
1082  MWDebug::warning( $msg, $callerOffset + 1, $level, 'auto' );
1083 }
1084 
1094 function wfLogWarning( $msg, $callerOffset = 1, $level = E_USER_WARNING ) {
1095  MWDebug::warning( $msg, $callerOffset + 1, $level, 'production' );
1096 }
1097 
1103  $context = RequestContext::getMain();
1104 
1105  $profiler = Profiler::instance();
1106  $profiler->setContext( $context );
1107  $profiler->logData();
1108 
1109  // Send out any buffered statsd metrics as needed
1111  MediaWikiServices::getInstance()->getStatsdDataFactory(),
1112  $context->getConfig()
1113  );
1114 }
1115 
1125 function wfIncrStats( $key, $count = 1 ) {
1126  $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
1127  $stats->updateCount( $key, $count );
1128 }
1129 
1135 function wfReadOnly() {
1136  return MediaWikiServices::getInstance()->getReadOnlyMode()
1137  ->isReadOnly();
1138 }
1139 
1148 function wfReadOnlyReason() {
1149  return MediaWikiServices::getInstance()->getReadOnlyMode()
1150  ->getReason();
1151 }
1152 
1161  wfDeprecated( __FUNCTION__, '1.36' );
1162  return MediaWikiServices::getInstance()->getConfiguredReadOnlyMode()
1163  ->getReason();
1164 }
1165 
1181 function wfGetLangObj( $langcode = false ) {
1182  # Identify which language to get or create a language object for.
1183  # Using is_object here due to Stub objects.
1184  if ( is_object( $langcode ) ) {
1185  # Great, we already have the object (hopefully)!
1186  return $langcode;
1187  }
1188 
1189  global $wgLanguageCode;
1190  $services = MediaWikiServices::getInstance();
1191  if ( $langcode === true || $langcode === $wgLanguageCode ) {
1192  # $langcode is the language code of the wikis content language object.
1193  # or it is a boolean and value is true
1194  return $services->getContentLanguage();
1195  }
1196 
1197  global $wgLang;
1198  if ( $langcode === false || $langcode === $wgLang->getCode() ) {
1199  # $langcode is the language code of user language object.
1200  # or it was a boolean and value is false
1201  return $wgLang;
1202  }
1203 
1204  $validCodes = array_keys( $services->getLanguageNameUtils()->getLanguageNames() );
1205  if ( in_array( $langcode, $validCodes ) ) {
1206  # $langcode corresponds to a valid language.
1207  return $services->getLanguageFactory()->getLanguage( $langcode );
1208  }
1209 
1210  # $langcode is a string, but not a valid language code; use content language.
1211  wfDebug( "Invalid language code passed to wfGetLangObj, falling back to content language." );
1212  return $services->getContentLanguage();
1213 }
1214 
1231 function wfMessage( $key, ...$params ) {
1232  $message = new Message( $key );
1233 
1234  // We call Message::params() to reduce code duplication
1235  if ( $params ) {
1236  $message->params( ...$params );
1237  }
1238 
1239  return $message;
1240 }
1241 
1254 function wfMessageFallback( ...$keys ) {
1255  return Message::newFallbackSequence( ...$keys );
1256 }
1257 
1266 function wfMsgReplaceArgs( $message, $args ) {
1267  # Fix windows line-endings
1268  # Some messages are split with explode("\n", $msg)
1269  $message = str_replace( "\r", '', $message );
1270 
1271  // Replace arguments
1272  if ( is_array( $args ) && $args ) {
1273  if ( is_array( $args[0] ) ) {
1274  $args = array_values( $args[0] );
1275  }
1276  $replacementKeys = [];
1277  foreach ( $args as $n => $param ) {
1278  $replacementKeys['$' . ( $n + 1 )] = $param;
1279  }
1280  $message = strtr( $message, $replacementKeys );
1281  }
1282 
1283  return $message;
1284 }
1285 
1294 function wfHostname() {
1295  // Hostname overriding
1296  global $wgOverrideHostname;
1297  if ( $wgOverrideHostname !== false ) {
1298  return $wgOverrideHostname;
1299  }
1300 
1301  return php_uname( 'n' ) ?: 'unknown';
1302 }
1303 
1314 function wfReportTime( $nonce = null ) {
1315  global $wgShowHostnames;
1316 
1317  $elapsed = ( microtime( true ) - $_SERVER['REQUEST_TIME_FLOAT'] );
1318  // seconds to milliseconds
1319  $responseTime = round( $elapsed * 1000 );
1320  $reportVars = [ 'wgBackendResponseTime' => $responseTime ];
1321  if ( $wgShowHostnames ) {
1322  $reportVars['wgHostname'] = wfHostname();
1323  }
1324 
1325  return (
1327  ResourceLoader::makeConfigSetScript( $reportVars ),
1328  $nonce
1329  )
1330  );
1331 }
1332 
1343 function wfDebugBacktrace( $limit = 0 ) {
1344  static $disabled = null;
1345 
1346  if ( $disabled === null ) {
1347  $disabled = !function_exists( 'debug_backtrace' );
1348  if ( $disabled ) {
1349  wfDebug( "debug_backtrace() is disabled" );
1350  }
1351  }
1352  if ( $disabled ) {
1353  return [];
1354  }
1355 
1356  if ( $limit ) {
1357  return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit + 1 ), 1 );
1358  } else {
1359  return array_slice( debug_backtrace(), 1 );
1360  }
1361 }
1362 
1371 function wfBacktrace( $raw = null ) {
1372  global $wgCommandLineMode;
1373 
1374  if ( $raw === null ) {
1375  $raw = $wgCommandLineMode;
1376  }
1377 
1378  if ( $raw ) {
1379  $frameFormat = "%s line %s calls %s()\n";
1380  $traceFormat = "%s";
1381  } else {
1382  $frameFormat = "<li>%s line %s calls %s()</li>\n";
1383  $traceFormat = "<ul>\n%s</ul>\n";
1384  }
1385 
1386  $frames = array_map( static function ( $frame ) use ( $frameFormat ) {
1387  $file = !empty( $frame['file'] ) ? basename( $frame['file'] ) : '-';
1388  $line = $frame['line'] ?? '-';
1389  $call = $frame['function'];
1390  if ( !empty( $frame['class'] ) ) {
1391  $call = $frame['class'] . $frame['type'] . $call;
1392  }
1393  return sprintf( $frameFormat, $file, $line, $call );
1394  }, wfDebugBacktrace() );
1395 
1396  return sprintf( $traceFormat, implode( '', $frames ) );
1397 }
1398 
1408 function wfGetCaller( $level = 2 ) {
1409  $backtrace = wfDebugBacktrace( $level + 1 );
1410  if ( isset( $backtrace[$level] ) ) {
1411  return wfFormatStackFrame( $backtrace[$level] );
1412  } else {
1413  return 'unknown';
1414  }
1415 }
1416 
1424 function wfGetAllCallers( $limit = 3 ) {
1425  $trace = array_reverse( wfDebugBacktrace() );
1426  if ( !$limit || $limit > count( $trace ) - 1 ) {
1427  $limit = count( $trace ) - 1;
1428  }
1429  $trace = array_slice( $trace, -$limit - 1, $limit );
1430  return implode( '/', array_map( 'wfFormatStackFrame', $trace ) );
1431 }
1432 
1439 function wfFormatStackFrame( $frame ) {
1440  if ( !isset( $frame['function'] ) ) {
1441  return 'NO_FUNCTION_GIVEN';
1442  }
1443  return isset( $frame['class'] ) && isset( $frame['type'] ) ?
1444  $frame['class'] . $frame['type'] . $frame['function'] :
1445  $frame['function'];
1446 }
1447 
1448 /* Some generic result counters, pulled out of SearchEngine */
1449 
1457 function wfShowingResults( $offset, $limit ) {
1458  return wfMessage( 'showingresults' )->numParams( $limit, $offset + 1 )->parse();
1459 }
1460 
1470 function wfClientAcceptsGzip( $force = false ) {
1471  static $result = null;
1472  if ( $result === null || $force ) {
1473  $result = false;
1474  if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
1475  # @todo FIXME: We may want to blacklist some broken browsers
1476  $m = [];
1477  if ( preg_match(
1478  '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
1479  $_SERVER['HTTP_ACCEPT_ENCODING'],
1480  $m
1481  )
1482  ) {
1483  if ( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) {
1484  $result = false;
1485  return $result;
1486  }
1487  wfDebug( "wfClientAcceptsGzip: client accepts gzip." );
1488  $result = true;
1489  }
1490  }
1491  }
1492  return $result;
1493 }
1494 
1505 function wfEscapeWikiText( $text ) {
1506  global $wgEnableMagicLinks;
1507  static $repl = null, $repl2 = null;
1508  if ( $repl === null || defined( 'MW_PARSER_TEST' ) || defined( 'MW_PHPUNIT_TEST' ) ) {
1509  // Tests depend upon being able to change $wgEnableMagicLinks, so don't cache
1510  // in those situations
1511  $repl = [
1512  '"' => '&#34;', '&' => '&#38;', "'" => '&#39;', '<' => '&#60;',
1513  '=' => '&#61;', '>' => '&#62;', '[' => '&#91;', ']' => '&#93;',
1514  '{' => '&#123;', '|' => '&#124;', '}' => '&#125;', ';' => '&#59;',
1515  "\n#" => "\n&#35;", "\r#" => "\r&#35;",
1516  "\n*" => "\n&#42;", "\r*" => "\r&#42;",
1517  "\n:" => "\n&#58;", "\r:" => "\r&#58;",
1518  "\n " => "\n&#32;", "\r " => "\r&#32;",
1519  "\n\n" => "\n&#10;", "\r\n" => "&#13;\n",
1520  "\n\r" => "\n&#13;", "\r\r" => "\r&#13;",
1521  "\n\t" => "\n&#9;", "\r\t" => "\r&#9;", // "\n\t\n" is treated like "\n\n"
1522  "\n----" => "\n&#45;---", "\r----" => "\r&#45;---",
1523  '__' => '_&#95;', '://' => '&#58;//',
1524  ];
1525 
1526  $magicLinks = array_keys( array_filter( $wgEnableMagicLinks ) );
1527  // We have to catch everything "\s" matches in PCRE
1528  foreach ( $magicLinks as $magic ) {
1529  $repl["$magic "] = "$magic&#32;";
1530  $repl["$magic\t"] = "$magic&#9;";
1531  $repl["$magic\r"] = "$magic&#13;";
1532  $repl["$magic\n"] = "$magic&#10;";
1533  $repl["$magic\f"] = "$magic&#12;";
1534  }
1535 
1536  // And handle protocols that don't use "://"
1537  global $wgUrlProtocols;
1538  $repl2 = [];
1539  foreach ( $wgUrlProtocols as $prot ) {
1540  if ( substr( $prot, -1 ) === ':' ) {
1541  $repl2[] = preg_quote( substr( $prot, 0, -1 ), '/' );
1542  }
1543  }
1544  $repl2 = $repl2 ? '/\b(' . implode( '|', $repl2 ) . '):/i' : '/^(?!)/';
1545  }
1546  $text = substr( strtr( "\n$text", $repl ), 1 );
1547  $text = preg_replace( $repl2, '$1&#58;', $text );
1548  return $text;
1549 }
1550 
1561 function wfSetVar( &$dest, $source, $force = false ) {
1562  $temp = $dest;
1563  if ( $source !== null || $force ) {
1564  $dest = $source;
1565  }
1566  return $temp;
1567 }
1568 
1578 function wfSetBit( &$dest, $bit, $state = true ) {
1579  $temp = (bool)( $dest & $bit );
1580  if ( $state !== null ) {
1581  if ( $state ) {
1582  $dest |= $bit;
1583  } else {
1584  $dest &= ~$bit;
1585  }
1586  }
1587  return $temp;
1588 }
1589 
1596 function wfVarDump( $var ) {
1597  global $wgOut;
1598  $s = str_replace( "\n", "<br />\n", var_export( $var, true ) . "\n" );
1599  if ( headers_sent() || !isset( $wgOut ) || !is_object( $wgOut ) ) {
1600  print $s;
1601  } else {
1602  $wgOut->addHTML( $s );
1603  }
1604 }
1605 
1613 function wfHttpError( $code, $label, $desc ) {
1614  global $wgOut;
1615  HttpStatus::header( $code );
1616  if ( $wgOut ) {
1617  $wgOut->disable();
1618  $wgOut->sendCacheControl();
1619  }
1620 
1622  header( 'Content-type: text/html; charset=utf-8' );
1623  ob_start();
1624  print '<!DOCTYPE html>' .
1625  '<html><head><title>' .
1626  htmlspecialchars( $label ) .
1627  '</title></head><body><h1>' .
1628  htmlspecialchars( $label ) .
1629  '</h1><p>' .
1630  nl2br( htmlspecialchars( $desc ) ) .
1631  "</p></body></html>\n";
1632  header( 'Content-Length: ' . ob_get_length() );
1633  ob_end_flush();
1634 }
1635 
1653 function wfResetOutputBuffers( $resetGzipEncoding = true ) {
1654  if ( $resetGzipEncoding ) {
1655  // Suppress Content-Encoding and Content-Length
1656  // headers from OutputHandler::handle.
1659  }
1660  while ( $status = ob_get_status() ) {
1661  if ( isset( $status['flags'] ) ) {
1662  $flags = PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_REMOVABLE;
1663  $deleteable = ( $status['flags'] & $flags ) === $flags;
1664  } elseif ( isset( $status['del'] ) ) {
1665  $deleteable = $status['del'];
1666  } else {
1667  // Guess that any PHP-internal setting can't be removed.
1668  $deleteable = $status['type'] !== 0; /* PHP_OUTPUT_HANDLER_INTERNAL */
1669  }
1670  if ( !$deleteable ) {
1671  // Give up, and hope the result doesn't break
1672  // output behavior.
1673  break;
1674  }
1675  if ( $status['name'] === 'MediaWikiIntegrationTestCase::wfResetOutputBuffersBarrier' ) {
1676  // Unit testing barrier to prevent this function from breaking PHPUnit.
1677  break;
1678  }
1679  if ( !ob_end_clean() ) {
1680  // Could not remove output buffer handler; abort now
1681  // to avoid getting in some kind of infinite loop.
1682  break;
1683  }
1684  if ( $resetGzipEncoding && $status['name'] == 'ob_gzhandler' ) {
1685  // Reset the 'Content-Encoding' field set by this handler
1686  // so we can start fresh.
1687  header_remove( 'Content-Encoding' );
1688  break;
1689  }
1690  }
1691 }
1692 
1708  wfDeprecated( __FUNCTION__, '1.36' );
1709  wfResetOutputBuffers( false );
1710 }
1711 
1721 function wfAcceptToPrefs( $accept, $def = '*/*' ) {
1722  wfDeprecated( __FUNCTION__, '1.36' );
1723  # No arg means accept anything (per HTTP spec)
1724  if ( !$accept ) {
1725  return [ $def => 1.0 ];
1726  }
1727 
1728  $prefs = [];
1729 
1730  $parts = explode( ',', $accept );
1731 
1732  foreach ( $parts as $part ) {
1733  # @todo FIXME: Doesn't deal with params like 'text/html; level=1'
1734  $values = explode( ';', trim( $part ) );
1735  $match = [];
1736  if ( count( $values ) == 1 ) {
1737  $prefs[$values[0]] = 1.0;
1738  } elseif ( preg_match( '/q\s*=\s*(\d*\.\d+)/', $values[1], $match ) ) {
1739  $prefs[$values[0]] = floatval( $match[1] );
1740  }
1741  }
1742 
1743  return $prefs;
1744 }
1745 
1758 function mimeTypeMatch( $type, $avail ) {
1759  if ( array_key_exists( $type, $avail ) ) {
1760  return $type;
1761  } else {
1762  $mainType = explode( '/', $type )[0];
1763  if ( array_key_exists( "$mainType/*", $avail ) ) {
1764  return "$mainType/*";
1765  } elseif ( array_key_exists( '*/*', $avail ) ) {
1766  return '*/*';
1767  } else {
1768  return null;
1769  }
1770  }
1771 }
1772 
1787 function wfNegotiateType( $cprefs, $sprefs ) {
1788  wfDeprecated( __FUNCTION__, '1.36' );
1789  $combine = [];
1790 
1791  foreach ( array_keys( $sprefs ) as $type ) {
1792  $subType = explode( '/', $type )[1];
1793  if ( $subType != '*' ) {
1794  $ckey = mimeTypeMatch( $type, $cprefs );
1795  if ( $ckey ) {
1796  $combine[$type] = $sprefs[$type] * $cprefs[$ckey];
1797  }
1798  }
1799  }
1800 
1801  foreach ( array_keys( $cprefs ) as $type ) {
1802  $subType = explode( '/', $type )[1];
1803  if ( $subType != '*' && !array_key_exists( $type, $sprefs ) ) {
1804  $skey = mimeTypeMatch( $type, $sprefs );
1805  if ( $skey ) {
1806  $combine[$type] = $sprefs[$skey] * $cprefs[$type];
1807  }
1808  }
1809  }
1810 
1811  $bestq = 0;
1812  $besttype = null;
1813 
1814  foreach ( array_keys( $combine ) as $type ) {
1815  if ( $combine[$type] > $bestq ) {
1816  $besttype = $type;
1817  $bestq = $combine[$type];
1818  }
1819  }
1820 
1821  return $besttype;
1822 }
1823 
1832 function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
1833  $ret = MWTimestamp::convert( $outputtype, $ts );
1834  if ( $ret === false ) {
1835  wfDebug( "wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts" );
1836  }
1837  return $ret;
1838 }
1839 
1848 function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
1849  if ( $ts === null ) {
1850  return null;
1851  } else {
1852  return wfTimestamp( $outputtype, $ts );
1853  }
1854 }
1855 
1861 function wfTimestampNow() {
1862  return MWTimestamp::now( TS_MW );
1863 }
1864 
1870 function wfIsWindows() {
1871  return PHP_OS_FAMILY === 'Windows';
1872 }
1873 
1880 function wfIsCLI() {
1881  return PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg';
1882 }
1883 
1895 function wfTempDir() {
1896  global $wgTmpDirectory;
1897 
1898  if ( $wgTmpDirectory !== false ) {
1899  return $wgTmpDirectory;
1900  }
1901 
1903 }
1904 
1914 function wfMkdirParents( $dir, $mode = null, $caller = null ) {
1915  global $wgDirectoryMode;
1916 
1917  if ( FileBackend::isStoragePath( $dir ) ) { // sanity
1918  throw new MWException( __FUNCTION__ . " given storage path '$dir'." );
1919  }
1920 
1921  if ( $caller !== null ) {
1922  wfDebug( "$caller: called wfMkdirParents($dir)" );
1923  }
1924 
1925  if ( strval( $dir ) === '' || is_dir( $dir ) ) {
1926  return true;
1927  }
1928 
1929  $dir = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $dir );
1930 
1931  if ( $mode === null ) {
1932  $mode = $wgDirectoryMode;
1933  }
1934 
1935  // Turn off the normal warning, we're doing our own below
1936  AtEase::suppressWarnings();
1937  $ok = mkdir( $dir, $mode, true ); // PHP5 <3
1938  AtEase::restoreWarnings();
1939 
1940  if ( !$ok ) {
1941  // directory may have been created on another request since we last checked
1942  if ( is_dir( $dir ) ) {
1943  return true;
1944  }
1945 
1946  // PHP doesn't report the path in its warning message, so add our own to aid in diagnosis.
1947  wfLogWarning( sprintf( "failed to mkdir \"%s\" mode 0%o", $dir, $mode ) );
1948  }
1949  return $ok;
1950 }
1951 
1957 function wfRecursiveRemoveDir( $dir ) {
1958  wfDebug( __FUNCTION__ . "( $dir )" );
1959  // taken from https://www.php.net/manual/en/function.rmdir.php#98622
1960  if ( is_dir( $dir ) ) {
1961  $objects = scandir( $dir );
1962  foreach ( $objects as $object ) {
1963  if ( $object != "." && $object != ".." ) {
1964  if ( filetype( $dir . '/' . $object ) == "dir" ) {
1965  wfRecursiveRemoveDir( $dir . '/' . $object );
1966  } else {
1967  unlink( $dir . '/' . $object );
1968  }
1969  }
1970  }
1971  reset( $objects );
1972  rmdir( $dir );
1973  }
1974 }
1975 
1982 function wfPercent( $nr, int $acc = 2, bool $round = true ) {
1983  $accForFormat = $acc >= 0 ? $acc : 0;
1984  $ret = sprintf( "%.${accForFormat}f", $nr );
1985  return $round ? round( (float)$ret, $acc ) . '%' : "$ret%";
1986 }
1987 
2011 function wfIniGetBool( $setting ) {
2012  return wfStringToBool( ini_get( $setting ) );
2013 }
2014 
2027 function wfStringToBool( $val ) {
2028  $val = strtolower( $val );
2029  // 'on' and 'true' can't have whitespace around them, but '1' can.
2030  return $val == 'on'
2031  || $val == 'true'
2032  || $val == 'yes'
2033  || preg_match( "/^\s*[+-]?0*[1-9]/", $val ); // approx C atoi() function
2034 }
2035 
2048 function wfEscapeShellArg( ...$args ) {
2049  return Shell::escape( ...$args );
2050 }
2051 
2076 function wfShellExec( $cmd, &$retval = null, $environ = [],
2077  $limits = [], $options = []
2078 ) {
2079  if ( Shell::isDisabled() ) {
2080  $retval = 1;
2081  // Backwards compatibility be upon us...
2082  return 'Unable to run external programs, proc_open() is disabled.';
2083  }
2084 
2085  if ( is_array( $cmd ) ) {
2086  $cmd = Shell::escape( $cmd );
2087  }
2088 
2089  $includeStderr = isset( $options['duplicateStderr'] ) && $options['duplicateStderr'];
2090  $profileMethod = $options['profileMethod'] ?? wfGetCaller();
2091 
2092  try {
2093  $result = Shell::command( [] )
2094  ->unsafeParams( (array)$cmd )
2095  ->environment( $environ )
2096  ->limits( $limits )
2097  ->includeStderr( $includeStderr )
2098  ->profileMethod( $profileMethod )
2099  // For b/c
2100  ->restrict( Shell::RESTRICT_NONE )
2101  ->execute();
2102  } catch ( ProcOpenError $ex ) {
2103  $retval = -1;
2104  return '';
2105  }
2106 
2107  $retval = $result->getExitCode();
2108 
2109  return $result->getStdout();
2110 }
2111 
2129 function wfShellExecWithStderr( $cmd, &$retval = null, $environ = [], $limits = [] ) {
2130  return wfShellExec( $cmd, $retval, $environ, $limits,
2131  [ 'duplicateStderr' => true, 'profileMethod' => wfGetCaller() ] );
2132 }
2133 
2149 function wfShellWikiCmd( $script, array $parameters = [], array $options = [] ) {
2150  global $wgPhpCli;
2151  // Give site config file a chance to run the script in a wrapper.
2152  // The caller may likely want to call wfBasename() on $script.
2153  Hooks::runner()->onWfShellWikiCmd( $script, $parameters, $options );
2154  $cmd = [ $options['php'] ?? $wgPhpCli ];
2155  if ( isset( $options['wrapper'] ) ) {
2156  $cmd[] = $options['wrapper'];
2157  }
2158  $cmd[] = $script;
2159  // Escape each parameter for shell
2160  return Shell::escape( array_merge( $cmd, $parameters ) );
2161 }
2162 
2174 function wfMerge( $old, $mine, $yours, &$result, &$mergeAttemptResult = null ) {
2175  global $wgDiff3;
2176 
2177  # This check may also protect against code injection in
2178  # case of broken installations.
2179  AtEase::suppressWarnings();
2180  $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
2181  AtEase::restoreWarnings();
2182 
2183  if ( !$haveDiff3 ) {
2184  wfDebug( "diff3 not found" );
2185  return false;
2186  }
2187 
2188  # Make temporary files
2189  $td = wfTempDir();
2190  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
2191  $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
2192  $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
2193 
2194  # NOTE: diff3 issues a warning to stderr if any of the files does not end with
2195  # a newline character. To avoid this, we normalize the trailing whitespace before
2196  # creating the diff.
2197 
2198  fwrite( $oldtextFile, rtrim( $old ) . "\n" );
2199  fclose( $oldtextFile );
2200  fwrite( $mytextFile, rtrim( $mine ) . "\n" );
2201  fclose( $mytextFile );
2202  fwrite( $yourtextFile, rtrim( $yours ) . "\n" );
2203  fclose( $yourtextFile );
2204 
2205  # Check for a conflict
2206  $cmd = Shell::escape( $wgDiff3, '-a', '--overlap-only', $mytextName,
2207  $oldtextName, $yourtextName );
2208  $handle = popen( $cmd, 'r' );
2209 
2210  $mergeAttemptResult = '';
2211  do {
2212  $data = fread( $handle, 8192 );
2213  if ( strlen( $data ) == 0 ) {
2214  break;
2215  }
2216  $mergeAttemptResult .= $data;
2217  } while ( true );
2218  pclose( $handle );
2219 
2220  $conflict = $mergeAttemptResult !== '';
2221 
2222  # Merge differences
2223  $cmd = Shell::escape( $wgDiff3, '-a', '-e', '--merge', $mytextName,
2224  $oldtextName, $yourtextName );
2225  $handle = popen( $cmd, 'r' );
2226  $result = '';
2227  do {
2228  $data = fread( $handle, 8192 );
2229  if ( strlen( $data ) == 0 ) {
2230  break;
2231  }
2232  $result .= $data;
2233  } while ( true );
2234  pclose( $handle );
2235  unlink( $mytextName );
2236  unlink( $oldtextName );
2237  unlink( $yourtextName );
2238 
2239  if ( $result === '' && $old !== '' && !$conflict ) {
2240  wfDebug( "Unexpected null result from diff3. Command: $cmd" );
2241  $conflict = true;
2242  }
2243  return !$conflict;
2244 }
2245 
2257 function wfDiff( $before, $after, $params = '-u' ) {
2258  wfDeprecated( __FUNCTION__, '1.25' );
2259  if ( $before == $after ) {
2260  return '';
2261  }
2262 
2263  global $wgDiff;
2264  AtEase::suppressWarnings();
2265  $haveDiff = $wgDiff && file_exists( $wgDiff );
2266  AtEase::restoreWarnings();
2267 
2268  # This check may also protect against code injection in
2269  # case of broken installations.
2270  if ( !$haveDiff ) {
2271  wfDebug( "diff executable not found" );
2272  $diffs = new Diff( explode( "\n", $before ), explode( "\n", $after ) );
2273  $format = new UnifiedDiffFormatter();
2274  return $format->format( $diffs );
2275  }
2276 
2277  # Make temporary files
2278  $td = wfTempDir();
2279  $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
2280  $newtextFile = fopen( $newtextName = tempnam( $td, 'merge-your-' ), 'w' );
2281 
2282  fwrite( $oldtextFile, $before );
2283  fclose( $oldtextFile );
2284  fwrite( $newtextFile, $after );
2285  fclose( $newtextFile );
2286 
2287  // Get the diff of the two files
2288  $cmd = "$wgDiff " . $params . ' ' . Shell::escape( $oldtextName, $newtextName );
2289 
2290  $h = popen( $cmd, 'r' );
2291  if ( !$h ) {
2292  unlink( $oldtextName );
2293  unlink( $newtextName );
2294  throw new Exception( __FUNCTION__ . '(): popen() failed' );
2295  }
2296 
2297  $diff = '';
2298 
2299  do {
2300  $data = fread( $h, 8192 );
2301  if ( strlen( $data ) == 0 ) {
2302  break;
2303  }
2304  $diff .= $data;
2305  } while ( true );
2306 
2307  // Clean up
2308  pclose( $h );
2309  unlink( $oldtextName );
2310  unlink( $newtextName );
2311 
2312  // Kill the --- and +++ lines. They're not useful.
2313  $diff_lines = explode( "\n", $diff );
2314  if ( isset( $diff_lines[0] ) && strpos( $diff_lines[0], '---' ) === 0 ) {
2315  unset( $diff_lines[0] );
2316  }
2317  if ( isset( $diff_lines[1] ) && strpos( $diff_lines[1], '+++' ) === 0 ) {
2318  unset( $diff_lines[1] );
2319  }
2320 
2321  $diff = implode( "\n", $diff_lines );
2322 
2323  return $diff;
2324 }
2325 
2338 function wfBaseName( $path, $suffix = '' ) {
2339  if ( $suffix == '' ) {
2340  $encSuffix = '';
2341  } else {
2342  $encSuffix = '(?:' . preg_quote( $suffix, '#' ) . ')?';
2343  }
2344 
2345  $matches = [];
2346  if ( preg_match( "#([^/\\\\]*?){$encSuffix}[/\\\\]*$#", $path, $matches ) ) {
2347  return $matches[1];
2348  } else {
2349  return '';
2350  }
2351 }
2352 
2362 function wfRelativePath( $path, $from ) {
2363  // Normalize mixed input on Windows...
2364  $path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
2365  $from = str_replace( '/', DIRECTORY_SEPARATOR, $from );
2366 
2367  // Trim trailing slashes -- fix for drive root
2368  $path = rtrim( $path, DIRECTORY_SEPARATOR );
2369  $from = rtrim( $from, DIRECTORY_SEPARATOR );
2370 
2371  $pieces = explode( DIRECTORY_SEPARATOR, dirname( $path ) );
2372  $against = explode( DIRECTORY_SEPARATOR, $from );
2373 
2374  if ( $pieces[0] !== $against[0] ) {
2375  // Non-matching Windows drive letters?
2376  // Return a full path.
2377  return $path;
2378  }
2379 
2380  // Trim off common prefix
2381  while ( count( $pieces ) && count( $against )
2382  && $pieces[0] == $against[0] ) {
2383  array_shift( $pieces );
2384  array_shift( $against );
2385  }
2386 
2387  // relative dots to bump us to the parent
2388  while ( count( $against ) ) {
2389  array_unshift( $pieces, '..' );
2390  array_shift( $against );
2391  }
2392 
2393  $pieces[] = wfBaseName( $path );
2394 
2395  return implode( DIRECTORY_SEPARATOR, $pieces );
2396 }
2397 
2405 function wfGetPrecompiledData( $name ) {
2406  wfDeprecated( __FUNCTION__, '1.36' );
2407  global $IP;
2408 
2409  $file = "$IP/serialized/$name";
2410  if ( file_exists( $file ) ) {
2411  $blob = file_get_contents( $file );
2412  if ( $blob ) {
2413  return unserialize( $blob );
2414  }
2415  }
2416  return false;
2417 }
2418 
2426 function wfWikiID() {
2427  global $wgDBprefix, $wgDBname;
2428 
2429  if ( $wgDBprefix ) {
2430  return "$wgDBname-$wgDBprefix";
2431  } else {
2432  return $wgDBname;
2433  }
2434 }
2435 
2467 function wfGetDB( $db, $groups = [], $wiki = false ) {
2468  return wfGetLB( $wiki )->getMaintenanceConnectionRef( $db, $groups, $wiki );
2469 }
2470 
2480 function wfGetLB( $wiki = false ) {
2481  if ( $wiki === false ) {
2482  return MediaWikiServices::getInstance()->getDBLoadBalancer();
2483  } else {
2484  $factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
2485  return $factory->getMainLB( $wiki );
2486  }
2487 }
2488 
2496 function wfFindFile( $title, $options = [] ) {
2497  return MediaWikiServices::getInstance()->getRepoGroup()->findFile( $title, $options );
2498 }
2499 
2508 function wfLocalFile( $title ) {
2509  return MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()->newFile( $title );
2510 }
2511 
2519  global $wgMiserMode;
2520  return $wgMiserMode
2521  || ( SiteStats::pages() > 100000
2522  && SiteStats::edits() > 1000000
2523  && SiteStats::users() > 10000 );
2524 }
2525 
2534 function wfScript( $script = 'index' ) {
2536  if ( $script === 'index' ) {
2537  return $wgScript;
2538  } elseif ( $script === 'load' ) {
2539  return $wgLoadScript;
2540  } else {
2541  return "{$wgScriptPath}/{$script}.php";
2542  }
2543 }
2544 
2551 function wfGetScriptUrl() {
2552  wfDeprecated( __FUNCTION__, '1.35' );
2553  if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
2554  /* as it was called, minus the query string.
2555  *
2556  * Some sites use Apache rewrite rules to handle subdomains,
2557  * and have PHP set up in a weird way that causes PHP_SELF
2558  * to contain the rewritten URL instead of the one that the
2559  * outside world sees.
2560  *
2561  * If in this mode, use SCRIPT_URL instead, which mod_rewrite
2562  * provides containing the "before" URL.
2563  */
2564  return $_SERVER['SCRIPT_NAME'];
2565  } else {
2566  return $_SERVER['URL'];
2567  }
2568 }
2569 
2577 function wfBoolToStr( $value ) {
2578  return $value ? 'true' : 'false';
2579 }
2580 
2586 function wfGetNull() {
2587  return wfIsWindows() ? 'NUL' : '/dev/null';
2588 }
2589 
2598 function wfStripIllegalFilenameChars( $name ) {
2599  global $wgIllegalFileChars;
2600  $illegalFileChars = $wgIllegalFileChars ? "|[" . $wgIllegalFileChars . "]" : '';
2601  $name = preg_replace(
2602  "/[^" . Title::legalChars() . "]" . $illegalFileChars . "/",
2603  '-',
2604  $name
2605  );
2606  // $wgIllegalFileChars may not include '/' and '\', so we still need to do this
2607  $name = wfBaseName( $name );
2608  return $name;
2609 }
2610 
2617 function wfMemoryLimit( $newLimit ) {
2618  $oldLimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
2619  // If the INI config is already unlimited, there is nothing larger
2620  if ( $oldLimit != -1 ) {
2621  $newLimit = wfShorthandToInteger( $newLimit );
2622  if ( $newLimit == -1 ) {
2623  wfDebug( "Removing PHP's memory limit" );
2624  Wikimedia\suppressWarnings();
2625  ini_set( 'memory_limit', $newLimit );
2626  Wikimedia\restoreWarnings();
2627  } elseif ( $newLimit > $oldLimit ) {
2628  wfDebug( "Raising PHP's memory limit to $newLimit bytes" );
2629  Wikimedia\suppressWarnings();
2630  ini_set( 'memory_limit', $newLimit );
2631  Wikimedia\restoreWarnings();
2632  }
2633  }
2634 }
2635 
2644 
2645  $timeout = RequestTimeout::singleton();
2646  $timeLimit = $timeout->getWallTimeLimit();
2647  if ( $timeLimit !== INF ) {
2648  // RequestTimeout library is active
2649  if ( $wgTransactionalTimeLimit > $timeLimit ) {
2650  $timeout->setWallTimeLimit( $wgTransactionalTimeLimit );
2651  }
2652  } else {
2653  // Fallback case, likely $wgRequestTimeLimit === null
2654  $timeLimit = (int)ini_get( 'max_execution_time' );
2655  // Note that CLI scripts use 0
2656  if ( $timeLimit > 0 && $wgTransactionalTimeLimit > $timeLimit ) {
2657  $timeout->setWallTimeLimit( $wgTransactionalTimeLimit );
2658  }
2659  }
2660  ignore_user_abort( true ); // ignore client disconnects
2661 
2662  return $timeLimit;
2663 }
2664 
2672 function wfShorthandToInteger( $string = '', $default = -1 ) {
2673  $string = trim( $string );
2674  if ( $string === '' ) {
2675  return $default;
2676  }
2677  $last = $string[strlen( $string ) - 1];
2678  $val = intval( $string );
2679  switch ( $last ) {
2680  case 'g':
2681  case 'G':
2682  $val *= 1024;
2683  // break intentionally missing
2684  case 'm':
2685  case 'M':
2686  $val *= 1024;
2687  // break intentionally missing
2688  case 'k':
2689  case 'K':
2690  $val *= 1024;
2691  }
2692 
2693  return $val;
2694 }
2695 
2703 function wfGetCache( $cacheType ) {
2704  return ObjectCache::getInstance( $cacheType );
2705 }
2706 
2713 function wfGetMainCache() {
2715 }
2716 
2731 function wfUnpack( $format, $data, $length = false ) {
2732  if ( $length !== false ) {
2733  $realLen = strlen( $data );
2734  if ( $realLen < $length ) {
2735  throw new MWException( "Tried to use wfUnpack on a "
2736  . "string of length $realLen, but needed one "
2737  . "of at least length $length."
2738  );
2739  }
2740  }
2741 
2742  Wikimedia\suppressWarnings();
2743  $result = unpack( $format, $data );
2744  Wikimedia\restoreWarnings();
2745 
2746  if ( $result === false ) {
2747  // If it cannot extract the packed data.
2748  throw new MWException( "unpack could not unpack binary data" );
2749  }
2750  return $result;
2751 }
2752 
2760 function wfCanIPUseHTTPS( $ip ) {
2761  $canDo = true;
2762  Hooks::runner()->onCanIPUseHTTPS( $ip, $canDo );
2763  return (bool)$canDo;
2764 }
2765 
2773 function wfIsInfinity( $str ) {
2774  // The INFINITY_VALS are hardcoded elsewhere in MediaWiki (e.g. mediawiki.special.block.js).
2775  return in_array( $str, ExpiryDef::INFINITY_VALS );
2776 }
2777 
2792 function wfThumbIsStandard( File $file, array $params ) {
2794 
2795  $multipliers = [ 1 ];
2796  if ( $wgResponsiveImages ) {
2797  // These available sizes are hardcoded currently elsewhere in MediaWiki.
2798  // @see Linker::processResponsiveImages
2799  $multipliers[] = 1.5;
2800  $multipliers[] = 2;
2801  }
2802 
2803  $handler = $file->getHandler();
2804  if ( !$handler || !isset( $params['width'] ) ) {
2805  return false;
2806  }
2807 
2808  $basicParams = [];
2809  if ( isset( $params['page'] ) ) {
2810  $basicParams['page'] = $params['page'];
2811  }
2812 
2813  $thumbLimits = [];
2814  $imageLimits = [];
2815  // Expand limits to account for multipliers
2816  foreach ( $multipliers as $multiplier ) {
2817  $thumbLimits = array_merge( $thumbLimits, array_map(
2818  static function ( $width ) use ( $multiplier ) {
2819  return round( $width * $multiplier );
2820  }, $wgThumbLimits )
2821  );
2822  $imageLimits = array_merge( $imageLimits, array_map(
2823  static function ( $pair ) use ( $multiplier ) {
2824  return [
2825  round( $pair[0] * $multiplier ),
2826  round( $pair[1] * $multiplier ),
2827  ];
2828  }, $wgImageLimits )
2829  );
2830  }
2831 
2832  // Check if the width matches one of $wgThumbLimits
2833  if ( in_array( $params['width'], $thumbLimits ) ) {
2834  $normalParams = $basicParams + [ 'width' => $params['width'] ];
2835  // Append any default values to the map (e.g. "lossy", "lossless", ...)
2836  $handler->normaliseParams( $file, $normalParams );
2837  } else {
2838  // If not, then check if the width matchs one of $wgImageLimits
2839  $match = false;
2840  foreach ( $imageLimits as $pair ) {
2841  $normalParams = $basicParams + [ 'width' => $pair[0], 'height' => $pair[1] ];
2842  // Decide whether the thumbnail should be scaled on width or height.
2843  // Also append any default values to the map (e.g. "lossy", "lossless", ...)
2844  $handler->normaliseParams( $file, $normalParams );
2845  // Check if this standard thumbnail size maps to the given width
2846  if ( $normalParams['width'] == $params['width'] ) {
2847  $match = true;
2848  break;
2849  }
2850  }
2851  if ( !$match ) {
2852  return false; // not standard for description pages
2853  }
2854  }
2855 
2856  // Check that the given values for non-page, non-width, params are just defaults
2857  foreach ( $params as $key => $value ) {
2858  if ( !isset( $normalParams[$key] ) || $normalParams[$key] != $value ) {
2859  return false;
2860  }
2861  }
2862 
2863  return true;
2864 }
2865 
2878 function wfArrayPlus2d( array $baseArray, array $newValues ) {
2879  // First merge items that are in both arrays
2880  foreach ( $baseArray as $name => &$groupVal ) {
2881  if ( isset( $newValues[$name] ) ) {
2882  $groupVal += $newValues[$name];
2883  }
2884  }
2885  // Now add items that didn't exist yet
2886  $baseArray += $newValues;
2887 
2888  return $baseArray;
2889 }
2890 
2900 function wfGetRusage() {
2901  wfDeprecated( __FUNCTION__, '1.35' );
2902  return getrusage( 0 /* RUSAGE_SELF */ );
2903 }
$wgPhpCli
$wgPhpCli
Executable path of the PHP cli binary.
Definition: DefaultSettings.php:8881
wfArrayInsertAfter
wfArrayInsertAfter(array $array, array $insert, $after)
Insert array into another array after the specified KEY
Definition: GlobalFunctions.php:210
MediaWiki\Shell\Shell
Executes shell commands.
Definition: Shell.php:45
wfMergeErrorArrays
wfMergeErrorArrays(... $args)
Merge arrays in the style of PermissionManager::getPermissionErrors, with duplicate removal e....
Definition: GlobalFunctions.php:184
wfResetOutputBuffers
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
Definition: GlobalFunctions.php:1653
wfMessageFallback
wfMessageFallback(... $keys)
This function accepts multiple message keys and returns a message instance for the first message whic...
Definition: GlobalFunctions.php:1254
$wgThumbLimits
$wgThumbLimits
Adjust thumbnails on image pages according to a user setting.
Definition: DefaultSettings.php:1612
wfCanIPUseHTTPS
wfCanIPUseHTTPS( $ip)
Determine whether the client at a given source IP is likely to be able to access the wiki via HTTPS.
Definition: GlobalFunctions.php:2760
ResourceLoader\makeConfigSetScript
static makeConfigSetScript(array $configuration)
Return JS code which will set the MediaWiki configuration array to the given value.
Definition: ResourceLoader.php:1671
ObjectCache\getLocalClusterInstance
static getLocalClusterInstance()
Get the main cluster-local cache object.
Definition: ObjectCache.php:272
SiteStats\users
static users()
Definition: SiteStats.php:121
MediaWiki\emitBufferedStatsdData
static emitBufferedStatsdData(IBufferingStatsdDataFactory $stats, Config $config)
Send out any buffered statsd data according to sampling rules.
Definition: MediaWiki.php:1117
MediaWiki\ProcOpenError
@newable
Definition: ProcOpenError.php:28
wfDiff
wfDiff( $before, $after, $params='-u')
Returns unified plain-text diff of two texts.
Definition: GlobalFunctions.php:2257
$wgResponsiveImages
$wgResponsiveImages
Generate and use thumbnails suitable for screens with 1.5 and 2.0 pixel densities.
Definition: DefaultSettings.php:1730
PROTO_HTTPS
const PROTO_HTTPS
Definition: Defines.php:204
$wgDebugRawPage
$wgDebugRawPage
If true, log debugging data from action=raw and load.php.
Definition: DefaultSettings.php:6676
wfThumbIsStandard
wfThumbIsStandard(File $file, array $params)
Returns true if these thumbnail parameters match one that MediaWiki requests from file description pa...
Definition: GlobalFunctions.php:2792
$wgTmpDirectory
$wgTmpDirectory
The local filesystem path to a temporary directory.
Definition: DefaultSettings.php:452
wfArrayPlus2d
wfArrayPlus2d(array $baseArray, array $newValues)
Merges two (possibly) 2 dimensional arrays into the target array ($baseArray).
Definition: GlobalFunctions.php:2878
$wgDBname
$wgDBname
Current wiki database name.
Definition: DefaultSettings.php:2036
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:69
wfMkdirParents
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
Definition: GlobalFunctions.php:1914
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:173
$wgDiff3
$wgDiff3
Path to the GNU diff3 utility.
Definition: DefaultSettings.php:7170
wfMerge
wfMerge( $old, $mine, $yours, &$result, &$mergeAttemptResult=null)
wfMerge attempts to merge differences between three texts.
Definition: GlobalFunctions.php:2174
wfDebugBacktrace
wfDebugBacktrace( $limit=0)
Safety wrapper for debug_backtrace().
Definition: GlobalFunctions.php:1343
wfSetVar
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...
Definition: GlobalFunctions.php:1561
wfGetLB
wfGetLB( $wiki=false)
Get a load balancer object.
Definition: GlobalFunctions.php:2480
wfFormatStackFrame
wfFormatStackFrame( $frame)
Return a string representation of frame.
Definition: GlobalFunctions.php:1439
ResourceLoader\makeInlineScript
static makeInlineScript( $script, $nonce=null)
Make an HTML script that runs given JS code after startup and base modules.
Definition: ResourceLoader.php:1644
wfRemoveDotSegments
wfRemoveDotSegments( $urlPath)
Remove all dot-segments in the provided URL path.
Definition: GlobalFunctions.php:645
$wgScript
$wgScript
The URL path to index.php.
Definition: DefaultSettings.php:204
wfSetBit
wfSetBit(&$dest, $bit, $state=true)
As for wfSetVar except setting a bit.
Definition: GlobalFunctions.php:1578
wfNegotiateType
wfNegotiateType( $cprefs, $sprefs)
Returns the 'best' match between a client's requested internet media types and the server's list of a...
Definition: GlobalFunctions.php:1787
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1832
SiteStats\pages
static pages()
Definition: SiteStats.php:112
wfUnpack
wfUnpack( $format, $data, $length=false)
Wrapper around php's unpack.
Definition: GlobalFunctions.php:2731
wfConfiguredReadOnlyReason
wfConfiguredReadOnlyReason()
Get the value of $wgReadOnly or the contents of $wgReadOnlyFile.
Definition: GlobalFunctions.php:1160
MessageSpecifier
Definition: MessageSpecifier.php:24
$wgShowHostnames
$wgShowHostnames
Expose backend server host names through the API and various HTML comments.
Definition: DefaultSettings.php:6868
wfMemoryLimit
wfMemoryLimit( $newLimit)
Raise PHP's memory limit (if needed).
Definition: GlobalFunctions.php:2617
wfObjectToArray
wfObjectToArray( $objOrArray, $recursive=true)
Recursively converts the parameter (an object) to an array with the same data.
Definition: GlobalFunctions.php:234
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:313
wfArrayDiff2_cmp
wfArrayDiff2_cmp( $a, $b)
Definition: GlobalFunctions.php:122
wfGetScriptUrl
wfGetScriptUrl()
Get the script URL.
Definition: GlobalFunctions.php:2551
$wgDiff
$wgDiff
Path to the GNU diff utility.
Definition: DefaultSettings.php:7175
wfBaseName
wfBaseName( $path, $suffix='')
Return the final portion of a pathname.
Definition: GlobalFunctions.php:2338
wfQueriesMustScale
wfQueriesMustScale()
Should low-performance queries be disabled?
Definition: GlobalFunctions.php:2518
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
wfHostname
wfHostname()
Get host name of the current machine, for use in error reporting.
Definition: GlobalFunctions.php:1294
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1135
wfMsgReplaceArgs
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
Definition: GlobalFunctions.php:1266
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1231
wfLogWarning
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
Definition: GlobalFunctions.php:1094
wfStringToBool
wfStringToBool( $val)
Convert string value to boolean, when the following are interpreted as true:
Definition: GlobalFunctions.php:2027
$wgTransactionalTimeLimit
$wgTransactionalTimeLimit
The request time limit for "slow" write requests that should not be interrupted due to the risk of da...
Definition: DefaultSettings.php:2436
$wgDebugLogPrefix
$wgDebugLogPrefix
Prefix for debug log lines.
Definition: DefaultSettings.php:6662
wfExpandIRI
wfExpandIRI( $url)
Take a URL, make sure it's expanded to fully qualified, and replace any encoded non-ASCII Unicode cha...
Definition: GlobalFunctions.php:865
$wgLang
$wgLang
Definition: Setup.php:782
wfDebugLog
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Definition: GlobalFunctions.php:996
$wgDBprefix
$wgDBprefix
Current wiki database table name prefix.
Definition: DefaultSettings.php:2056
wfShellWikiCmd
wfShellWikiCmd( $script, array $parameters=[], array $options=[])
Generate a shell-escaped command line string to run a MediaWiki cli script.
Definition: GlobalFunctions.php:2149
wfBoolToStr
wfBoolToStr( $value)
Convenience function converts boolean values into "true" or "false" (string) values.
Definition: GlobalFunctions.php:2577
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:443
ExtensionRegistry\getInstance
static getInstance()
Definition: ExtensionRegistry.php:136
Wikimedia\ParamValidator\TypeDef\ExpiryDef
Type definition for expiry timestamps.
Definition: ExpiryDef.php:17
wfParseUrl
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
Definition: GlobalFunctions.php:797
File
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition: File.php:63
wfReportTime
wfReportTime( $nonce=null)
Returns a script tag that stores the amount of time it took MediaWiki to handle the request in millis...
Definition: GlobalFunctions.php:1314
wfDeprecatedMsg
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: GlobalFunctions.php:1066
wfGetMainCache
wfGetMainCache()
Get the main cache object.
Definition: GlobalFunctions.php:2713
MWException
MediaWiki exception.
Definition: MWException.php:29
wfStripIllegalFilenameChars
wfStripIllegalFilenameChars( $name)
Replace all invalid characters with '-'.
Definition: GlobalFunctions.php:2598
wfGetRusage
wfGetRusage()
Get system resource usage of current request context.
Definition: GlobalFunctions.php:2900
mimeTypeMatch
mimeTypeMatch( $type, $avail)
Checks if a given MIME type matches any of the keys in the given array.
Definition: GlobalFunctions.php:1758
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1034
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2534
wfArrayDiff2
wfArrayDiff2( $a, $b)
Like array_diff( $a, $b ) except that it works with two-dimensional arrays.
Definition: GlobalFunctions.php:113
wfIncrStats
wfIncrStats( $key, $count=1)
Increment a statistics counter.
Definition: GlobalFunctions.php:1125
FileBackend\isStoragePath
static isStoragePath( $path)
Check if a given path is a "mwstore://" path.
Definition: FileBackend.php:1528
$blob
$blob
Definition: testCompression.php:70
wfTransactionalTimeLimit
wfTransactionalTimeLimit()
Raise the request time limit to $wgTransactionalTimeLimit.
Definition: GlobalFunctions.php:2642
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2467
wfUrlProtocolsWithoutProtRel
wfUrlProtocolsWithoutProtRel()
Like wfUrlProtocols(), but excludes '//' from the protocol list.
Definition: GlobalFunctions.php:768
$wgCommandLineMode
global $wgCommandLineMode
Definition: DevelopmentSettings.php:29
$matches
$matches
Definition: NoLocalSettings.php:24
$wgLoadScript
$wgLoadScript
The URL path to load.php.
Definition: DefaultSettings.php:212
wfTimestampOrNull
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
Definition: GlobalFunctions.php:1848
ObjectCache\getInstance
static getInstance( $id)
Get a cached instance of the specified type of cache object.
Definition: ObjectCache.php:74
$args
if( $line===false) $args
Definition: mcc.php:124
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1181
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:396
wfLoadSkins
wfLoadSkins(array $skins)
Load multiple skins at once.
Definition: GlobalFunctions.php:99
$title
$title
Definition: testCompression.php:38
MWDebug\deprecated
static deprecated( $function, $version=false, $component=false, $callerOffset=2)
Show a warning that $function is deprecated.
Definition: MWDebug.php:221
wfGetCache
wfGetCache( $cacheType)
Get a specific cache object.
Definition: GlobalFunctions.php:2703
$wgEnableMagicLinks
$wgEnableMagicLinks
Enable the magic links feature of automatically turning ISBN xxx, PMID xxx, RFC xxx into links.
Definition: DefaultSettings.php:4841
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1861
PROTO_CANONICAL
const PROTO_CANONICAL
Definition: Defines.php:207
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:915
wfPercent
wfPercent( $nr, int $acc=2, bool $round=true)
Definition: GlobalFunctions.php:1982
wfAcceptToPrefs
wfAcceptToPrefs( $accept, $def=' */*')
Converts an Accept-* header into an array mapping string values to quality factors.
Definition: GlobalFunctions.php:1721
$wgCanonicalServer
$wgCanonicalServer
Canonical URL of the server, to use in IRC feeds and notification e-mails.
Definition: DefaultSettings.php:117
wfIsDebugRawPage
wfIsDebugRawPage()
Returns true if debug logging should be suppressed if $wgDebugRawPage = false.
Definition: GlobalFunctions.php:937
UnifiedDiffFormatter
A formatter that outputs unified diffs @newable.
Definition: UnifiedDiffFormatter.php:32
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:206
wfUrlProtocols
wfUrlProtocols( $includeProtocolRelative=true)
Returns a regular expression of url protocols.
Definition: GlobalFunctions.php:723
wfLoadExtensions
wfLoadExtensions(array $exts)
Load multiple extensions at once.
Definition: GlobalFunctions.php:68
wfWikiID
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
Definition: GlobalFunctions.php:2426
$s
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
Definition: mergeMessageFileList.php:206
wfClearOutputBuffers
wfClearOutputBuffers()
More legible than passing a 'false' parameter to wfResetOutputBuffers():
Definition: GlobalFunctions.php:1707
wfClientAcceptsGzip
wfClientAcceptsGzip( $force=false)
Whether the client accept gzip encoding.
Definition: GlobalFunctions.php:1470
$wgUrlProtocols
$wgUrlProtocols
URL schemes that should be recognized as valid by wfParseUrl().
Definition: DefaultSettings.php:4671
$wgExtensionDirectory
$wgExtensionDirectory
Filesystem extensions directory.
Definition: DefaultSettings.php:248
wfIsCLI
wfIsCLI()
Check if we are running from the commandline.
Definition: GlobalFunctions.php:1880
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:1870
$wgServer
$wgServer
URL of the server.
Definition: DefaultSettings.php:108
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:172
$line
$line
Definition: mcc.php:119
$wgLanguageCode
$wgLanguageCode
Site language code.
Definition: DefaultSettings.php:3196
wfIsInfinity
wfIsInfinity( $str)
Determine input string is represents as infinity.
Definition: GlobalFunctions.php:2773
wfDebugMem
wfDebugMem( $exact=false)
Send a line giving PHP memory usage.
Definition: GlobalFunctions.php:960
$wgDirectoryMode
$wgDirectoryMode
Default value for chmoding of new directories.
Definition: DefaultSettings.php:1722
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1505
wfAppendToArrayIfNotDefault
wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed)
Appends to second array if $value differs from that in $default.
Definition: GlobalFunctions.php:154
$wgDisableOutputCompression
$wgDisableOutputCompression
Disable output compression (enabled by default if zlib is available)
Definition: DefaultSettings.php:3641
wfVarDump
wfVarDump( $var)
A wrapper around the PHP function var_export().
Definition: GlobalFunctions.php:1596
$wgIllegalFileChars
$wgIllegalFileChars
Additional characters that are not allowed in filenames.
Definition: DefaultSettings.php:529
wfGetNull
wfGetNull()
Get a platform-independent path to the null file, e.g.
Definition: GlobalFunctions.php:2586
TempFSFile\getUsableTempDirectory
static getUsableTempDirectory()
Definition: TempFSFile.php:80
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:476
wfIniGetBool
wfIniGetBool( $setting)
Safety wrapper around ini_get() for boolean settings.
Definition: GlobalFunctions.php:2011
$wgOverrideHostname
$wgOverrideHostname
Override server hostname detection with a hardcoded value.
Definition: DefaultSettings.php:6875
PROTO_INTERNAL
const PROTO_INTERNAL
Definition: Defines.php:208
wfFindFile
wfFindFile( $title, $options=[])
Find a file.
Definition: GlobalFunctions.php:2496
wfGetAllCallers
wfGetAllCallers( $limit=3)
Return a string consisting of callers in the stack.
Definition: GlobalFunctions.php:1424
wfLoadExtension
wfLoadExtension( $ext, $path=null)
Load an extension.
Definition: GlobalFunctions.php:47
unserialize
unserialize( $serialized)
Definition: ApiMessageTrait.php:146
wfLoadSkin
wfLoadSkin( $skin, $path=null)
Load a skin.
Definition: GlobalFunctions.php:84
wfShorthandToInteger
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:2672
$wgImageLimits
$wgImageLimits
Limit images on image description pages to a user-selectable limit.
Definition: DefaultSettings.php:1599
wfRandom
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
Definition: GlobalFunctions.php:260
wfTempDir
wfTempDir()
Tries to get the system directory for temporary files.
Definition: GlobalFunctions.php:1895
$wgMiserMode
$wgMiserMode
Disable database-intensive features.
Definition: DefaultSettings.php:2458
wfHttpError
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
Definition: GlobalFunctions.php:1613
wfReadOnlyReason
wfReadOnlyReason()
Check if the site is in read-only mode and return the message if so.
Definition: GlobalFunctions.php:1148
wfMatchesDomainList
wfMatchesDomainList( $url, $domains)
Check whether a given URL has a domain that occurs in a given set of domains.
Definition: GlobalFunctions.php:881
$cache
$cache
Definition: mcc.php:33
HttpStatus\header
static header( $code)
Output an HTTP status code header.
Definition: HttpStatus.php:96
wfGetPrecompiledData
wfGetPrecompiledData( $name)
Get an object from the precompiled serialized directory.
Definition: GlobalFunctions.php:2405
wfRecursiveRemoveDir
wfRecursiveRemoveDir( $dir)
Remove a directory and all its content.
Definition: GlobalFunctions.php:1957
$wgHttpsPort
$wgHttpsPort
For installations where the canonical server is HTTP but HTTPS is optionally supported,...
Definition: DefaultSettings.php:145
$path
$path
Definition: NoLocalSettings.php:25
Message
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition: Message.php:161
$keys
$keys
Definition: testCompression.php:72
wfBacktrace
wfBacktrace( $raw=null)
Get a debug backtrace as a string.
Definition: GlobalFunctions.php:1371
wfEscapeShellArg
wfEscapeShellArg(... $args)
Version of escapeshellarg() that works better on Windows.
Definition: GlobalFunctions.php:2048
$source
$source
Definition: mwdoc-filter.php:34
wfAssembleUrl
wfAssembleUrl( $urlParts)
This function will reassemble a URL parsed with wfParseURL.
Definition: GlobalFunctions.php:591
$ext
if(!is_readable( $file)) $ext
Definition: router.php:48
wfRelativePath
wfRelativePath( $path, $from)
Generate a relative path name to the given file.
Definition: GlobalFunctions.php:2362
wfWarn
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
Definition: GlobalFunctions.php:1081
Title\legalChars
static legalChars()
Get a regex character class describing the legal characters in a link.
Definition: Title.php:737
$wgRequest
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:651
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
MWDebug\warning
static warning( $msg, $callerOffset=1, $level=E_USER_NOTICE, $log='auto')
Adds a warning entry to the log.
Definition: MWDebug.php:180
$wgOut
$wgOut
Definition: Setup.php:787
wfGetServerUrl
wfGetServerUrl( $proto)
Get the wiki's "server", i.e.
Definition: GlobalFunctions.php:573
$wgScriptPath
$wgScriptPath
The path we should point to.
Definition: DefaultSettings.php:176
$IP
$IP
Definition: WebStart.php:49
wfLocalFile
wfLocalFile( $title)
Get an object referring to a locally registered file.
Definition: GlobalFunctions.php:2508
Message\newFallbackSequence
static newFallbackSequence(... $keys)
Factory function accepting multiple message keys and returning a message instance for the first messa...
Definition: Message.php:458
wfShowingResults
wfShowingResults( $offset, $limit)
Definition: GlobalFunctions.php:1457
wfGetCaller
wfGetCaller( $level=2)
Get the name of the function which called this function wfGetCaller( 1 ) is the function with the wfG...
Definition: GlobalFunctions.php:1408
$wgStyleDirectory
$wgStyleDirectory
Filesystem stylesheets directory.
Definition: DefaultSettings.php:255
wfLogDBError
wfLogDBError( $text, array $context=[])
Log for database errors.
Definition: GlobalFunctions.php:1014
SiteStats\edits
static edits()
Definition: SiteStats.php:94
MWDebug\deprecatedMsg
static deprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: MWDebug.php:304
MW_ENTRY_POINT
const MW_ENTRY_POINT
Definition: api.php:41
$wgInternalServer
$wgInternalServer
Internal server name as known to CDN, if different.
Definition: DefaultSettings.php:3003
PROTO_HTTP
const PROTO_HTTP
Definition: Defines.php:203
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:495
wfShellExecWithStderr
wfShellExecWithStderr( $cmd, &$retval=null, $environ=[], $limits=[])
Execute a shell command, returning both stdout and stderr.
Definition: GlobalFunctions.php:2129
MediaWiki\HeaderCallback\warnIfHeadersSent
static warnIfHeadersSent()
Log a warning message if headers have already been sent.
Definition: HeaderCallback.php:83
wfLogProfilingData
wfLogProfilingData()
Definition: GlobalFunctions.php:1102
Diff
Class representing a 'diff' between two sequences of strings.
Definition: Diff.php:32
wfShellExec
wfShellExec( $cmd, &$retval=null, $environ=[], $limits=[], $options=[])
Execute a shell command, with time and memory limits mirrored from the PHP configuration if supported...
Definition: GlobalFunctions.php:2076
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Definition: GlobalFunctions.php:351
wfRandomString
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
Definition: GlobalFunctions.php:278
$type
$type
Definition: testCompression.php:52