die( "This file is part of MediaWiki, it is not a valid entry point" );
}
+use Liuggio\StatsdClient\StatsdClient;
+use Liuggio\StatsdClient\Sender\SocketSender;
+use MediaWiki\Logger\LoggerFactory;
+
// Hide compatibility functions from Doxygen
/// @cond
/**
* Load an extension
*
- * This is the closest equivalent to:
- * require_once "$IP/extensions/$name/$name.php";
- * as it will process and load the extension immediately.
- *
- * However, batch loading with wfLoadExtensions will
- * be more performant.
+ * This queues an extension to be loaded through
+ * the ExtensionRegistry system.
*
* @param string $name Name of the extension to load
* @param string|null $path Absolute path of where to find the extension.json file
global $IP;
$path = "$IP/extensions/$name/extension.json";
}
- ExtensionRegistry::getInstance()->load( $path );
+ ExtensionRegistry::getInstance()->queue( $path );
}
/**
foreach ( $exts as $ext ) {
$registry->queue( "$IP/extensions/$ext/extension.json" );
}
-
- $registry->loadFromQueue();
}
/**
global $IP;
$path = "$IP/skins/$name/skin.json";
}
- ExtensionRegistry::getInstance()->load( $path );
+ ExtensionRegistry::getInstance()->queue( $path );
}
/**
foreach ( $skins as $skin ) {
$registry->queue( "$IP/skins/$skin/skin.json" );
}
-
- $registry->loadFromQueue();
}
/**
* @since 1.25 support for additional context data
*
* @param string $text
- * @param string|bool $dest Destination of the message:
- * - 'all': both to the log and HTML (debug toolbar or HTML comments)
- * - 'log': only to the log and not in HTML
- * For backward compatibility, it can also take a boolean:
- * - true: same as 'all'
- * - false: same as 'log'
+ * @param string|bool $dest Unused
* @param array $context Additional logging context data
*/
function wfDebug( $text, $dest = 'all', array $context = array() ) {
return;
}
- // Turn $dest into a string if it's a boolean (for b/c)
- if ( $dest === true ) {
- $dest = 'all';
- } elseif ( $dest === false ) {
- $dest = 'log';
- }
-
$text = trim( $text );
// Inline logic from deprecated wfDebugTimer()
);
}
- if ( $dest === 'all' ) {
- $prefix = '';
- if ( $wgDebugTimestamps ) {
- // Prepend elapsed request time and real memory usage with two
- // trailing spaces.
- $prefix = "{$context['seconds_elapsed']} {$context['memory_used']} ";
- }
- MWDebug::debugMsg( "{$prefix}{$text}" );
- }
-
if ( $wgDebugLogPrefix !== '' ) {
$context['prefix'] = $wgDebugLogPrefix;
}
- $logger = MWLoggerFactory::getInstance( 'wfDebug' );
+ $logger = LoggerFactory::getInstance( 'wfDebug' );
$logger->debug( $text, $context );
}
$text = trim( $text );
- if ( $dest === 'all' ) {
- MWDebug::debugMsg( "[{$logGroup}] {$text}\n" );
- }
-
- $logger = MWLoggerFactory::getInstance( $logGroup );
+ $logger = LoggerFactory::getInstance( $logGroup );
$context['private'] = ( $dest === 'private' );
$logger->info( $text, $context );
}
* @param array $context Additional logging context data
*/
function wfLogDBError( $text, array $context = array() ) {
- $logger = MWLoggerFactory::getInstance( 'wfLogDBError' );
+ $logger = LoggerFactory::getInstance( 'wfLogDBError' );
$logger->error( trim( $text ), $context );
}
* @param string $file Filename
* @param array $context Additional logging context data
* @throws MWException
- * @deprecated since 1.25 Use MWLoggerLegacyLogger::emit or UDPTransport
+ * @deprecated since 1.25 Use MediaWiki\Logger\LegacyLogger::emit or UDPTransport
*/
function wfErrorLog( $text, $file, array $context = array() ) {
wfDeprecated( __METHOD__, '1.25' );
- $logger = MWLoggerFactory::getInstance( 'wfErrorLog' );
+ $logger = LoggerFactory::getInstance( 'wfErrorLog' );
$context['destination'] = $file;
$logger->info( trim( $text ), $context );
}
* @todo document
*/
function wfLogProfilingData() {
- global $wgRequestTime, $wgDebugLogGroups, $wgDebugRawPage;
- global $wgProfileLimit, $wgUser, $wgRequest;
+ global $wgDebugLogGroups, $wgDebugRawPage;
- StatCounter::singleton()->flush();
+ $context = RequestContext::getMain();
+ $request = $context->getRequest();
$profiler = Profiler::instance();
+ $profiler->setContext( $context );
+ $profiler->logData();
- # Profiling must actually be enabled...
- if ( $profiler instanceof ProfilerStub ) {
- return;
+ $config = $context->getConfig();
+ if ( $config->has( 'StatsdServer' ) ) {
+ $statsdServer = explode( ':', $config->get( 'StatsdServer' ) );
+ $statsdHost = $statsdServer[0];
+ $statsdPort = isset( $statsdServer[1] ) ? $statsdServer[1] : 8125;
+ $statsdSender = new SocketSender( $statsdHost, $statsdPort );
+ $statsdClient = new StatsdClient( $statsdSender );
+ $statsdClient->send( $context->getStats()->getBuffer() );
}
- // Get total page request time and only show pages that longer than
- // $wgProfileLimit time (default is 0)
- $elapsed = microtime( true ) - $wgRequestTime;
- if ( $elapsed <= $wgProfileLimit ) {
+ # Profiling must actually be enabled...
+ if ( $profiler instanceof ProfilerStub ) {
return;
}
- $profiler->logData();
-
if ( isset( $wgDebugLogGroups['profileoutput'] )
&& $wgDebugLogGroups['profileoutput'] === false
) {
return;
}
- $ctx = array( 'elapsed' => $elapsed );
+ $ctx = array( 'elapsed' => $request->getElapsedTime() );
if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
$ctx['forwarded_for'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
// Don't load $wgUser at this late stage just for statistics purposes
// @todo FIXME: We can detect some anons even if it is not loaded.
// See User::getId()
- if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
- $ctx['anon'] = true;
- } else {
- $ctx['anon'] = false;
- }
+ $user = $context->getUser();
+ $ctx['anon'] = $user->isItemLoaded( 'id' ) && $user->isAnon();
// Command line script uses a FauxRequest object which does not have
// any knowledge about an URL and throw an exception instead.
try {
- $ctx['url'] = urldecode( $wgRequest->getRequestURL() );
+ $ctx['url'] = urldecode( $request->getRequestURL() );
} catch ( Exception $ignored ) {
// no-op
}
$ctx['output'] = $profiler->getOutput();
- $log = MWLoggerFactory::getInstance( 'profileoutput' );
+ $log = LoggerFactory::getInstance( 'profileoutput' );
$log->info( "Elapsed: {elapsed}; URL: <{url}>\n{output}", $ctx );
}
* @return void
*/
function wfIncrStats( $key, $count = 1 ) {
- StatCounter::singleton()->incr( $key, $count );
+ $stats = RequestContext::getMain()->getStats();
+ $stats->updateCount( $key, $count );
}
/**
} else {
$wgReadOnly = false;
}
+ // Callers use this method to be aware that data presented to a user
+ // may be very stale and thus allowing submissions can be problematic.
+ if ( $wgReadOnly === false && wfGetLB()->getLaggedSlaveMode() ) {
+ $wgReadOnly = 'The database has been automatically locked ' .
+ 'while the slave database servers catch up to the master';
+ }
}
return $wgReadOnly;
return defined( 'HHVM_VERSION' );
}
-/**
- * Swap two variables
- *
- * @deprecated since 1.24
- * @param mixed $x
- * @param mixed $y
- */
-function swap( &$x, &$y ) {
- wfDeprecated( __FUNCTION__, '1.24' );
- $z = $x;
- $x = $y;
- $y = $z;
-}
-
/**
* Tries to get the system directory for temporary files. First
* $wgTmpDirectory is checked, and then the TMPDIR, TMP, and TEMP
wfDebug( "$caller: called wfMkdirParents($dir)\n" );
}
- if ( strval( $dir ) === '' || ( file_exists( $dir ) && is_dir( $dir ) ) ) {
+ if ( strval( $dir ) === '' || is_dir( $dir ) ) {
return true;
}
* Also fixes the locale problems on Linux in PHP 5.2.6+ (bug backported to
* earlier distro releases of PHP)
*
- * @param string $args,...
+ * @param string ... strings to escape and glue together, or a single array of strings parameter
* @return string
*/
function wfEscapeShellArg( /*...*/ ) {
wfInitShellLocale();
$args = func_get_args();
+ if ( count( $args ) === 1 && is_array( reset( $args ) ) ) {
+ // If only one argument has been passed, and that argument is an array,
+ // treat it as a list of arguments
+ $args = reset( $args );
+ }
+
$first = true;
$retVal = '';
foreach ( $args as $arg ) {
* @param array $options Array of options:
* - duplicateStderr: Set this to true to duplicate stderr to stdout,
* including errors from limit.sh
+ * - profileMethod: By default this function will profile based on the calling
+ * method. Set this to a string for an alternative method to profile from
*
* @return string Collected stdout as a string
*/
}
$includeStderr = isset( $options['duplicateStderr'] ) && $options['duplicateStderr'];
+ $profileMethod = isset( $options['profileMethod'] ) ? $options['profileMethod'] : wfGetCaller();
wfInitShellLocale();
}
}
if ( is_array( $cmd ) ) {
- // Command line may be given as an array, escape each value and glue them together with a space
- $cmdVals = array();
- foreach ( $cmd as $val ) {
- $cmdVals[] = wfEscapeShellArg( $val );
- }
- $cmd = implode( ' ', $cmdVals );
+ $cmd = wfEscapeShellArg( $cmd );
}
$cmd = $envcmd . $cmd;
$desc[3] = array( 'pipe', 'w' );
}
$pipes = null;
+ $scoped = Profiler::instance()->scopedProfileIn( __FUNCTION__ . '-' . $profileMethod );
$proc = proc_open( $cmd, $desc, $pipes );
if ( !$proc ) {
wfDebugLog( 'exec', "proc_open() failed: $cmd" );
* @return string Collected stdout and stderr as a string
*/
function wfShellExecWithStderr( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
- return wfShellExec( $cmd, $retval, $environ, $limits, array( 'duplicateStderr' => true ) );
+ return wfShellExec( $cmd, $retval, $environ, $limits,
+ array( 'duplicateStderr' => true, 'profileMethod' => wfGetCaller() ) );
}
/**
}
}
-/**
- * Alias to wfShellWikiCmd()
- *
- * @see wfShellWikiCmd()
- */
-function wfShellMaintenanceCmd( $script, array $parameters = array(), array $options = array() ) {
- return wfShellWikiCmd( $script, $parameters, $options );
-}
-
/**
* Generate a shell-escaped command line string to run a MediaWiki cli script.
* Note that $parameters should be a flat array and an option with an argument
}
$cmd[] = $script;
// Escape each parameter for shell
- return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) );
+ return wfEscapeShellArg( array_merge( $cmd, $parameters ) );
}
/**
fclose( $yourtextFile );
# Check for a conflict
- $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
- wfEscapeShellArg( $mytextName ) . ' ' .
- wfEscapeShellArg( $oldtextName ) . ' ' .
- wfEscapeShellArg( $yourtextName );
+ $cmd = wfEscapeShellArg( $wgDiff3, '-a', '--overlap-only', $mytextName,
+ $oldtextName, $yourtextName );
$handle = popen( $cmd, 'r' );
if ( fgets( $handle, 1024 ) ) {
pclose( $handle );
# Merge differences
- $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
- wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
+ $cmd = wfEscapeShellArg( $wgDiff3, '-a', '-e', '--merge', $mytextName,
+ $oldtextName, $yourtextName );
$handle = popen( $cmd, 'r' );
$result = '';
do {
/**
* Returns unified plain-text diff of two texts.
- * Useful for machine processing of diffs.
+ * "Useful" for machine processing of diffs.
+ *
+ * @deprecated since 1.25, use DiffEngine/UnifiedDiffFormatter directly
*
* @param string $before The text before the changes.
* @param string $after The text after the changes.
$cmd = "$wgDiff " . $params . ' ' . wfEscapeShellArg( $oldtextName, $newtextName );
$h = popen( $cmd, 'r' );
+ if ( !$h ) {
+ unlink( $oldtextName );
+ unlink( $newtextName );
+ throw new Exception( __METHOD__ . '(): popen() failed' );
+ }
$diff = '';
* Shortcut for RepoGroup::singleton()->findFile()
*
* @param string $title String or Title object
- * @param array $options Associative array of options:
- * time: requested time for an archived image, or false for the
- * current version. An image object will be returned which was
- * created at the specified time.
- *
- * ignoreRedirect: If true, do not follow file redirects
- *
- * private: If true, return restricted (deleted) files if the current
- * user is allowed to view them. Otherwise, such files will not
- * be found.
- *
- * bypassCache: If true, do not use the process-local cache of File objects
- *
+ * @param array $options Associative array of options (see RepoGroup::findFile)
* @return File|bool File, or false if the file does not exist
*/
function wfFindFile( $title, $options = array() ) {
return ObjectCache::getInstance( $wgParserCacheType );
}
-/**
- * Get the cache object used by the language converter
- *
- * @return BagOStuff
- */
-function wfGetLangConverterCacheStorage() {
- global $wgLanguageConverterCacheType;
- return ObjectCache::getInstance( $wgLanguageConverterCacheType );
-}
-
/**
* Call hook functions defined in $wgHooks
*
return !!$canDo;
}
+/**
+ * Determine input string is represents as infinity
+ *
+ * @param string $str The string to determine
+ * @return bool
+ * @since 1.25
+ */
+function wfIsInfinity( $str ) {
+ $infinityValues = array( 'infinite', 'indefinite', 'infinity', 'never' );
+ return in_array( $str, $infinityValues );
+}
+
/**
* Work out the IP address based on various globals
* For trusted proxies, use the XFF client IP (first of the chain)