* Previously, when iterating ResultWrapper with foreach() or a similar
construct, the range of the index was 1..numRows. This has been fixed to be
0..(numRows-1).
+* The ChangePasswordForm hook, deprecated in 1.27, has been removed. Use the
+ AuthChangeFormFields hook or security levels instead.
* …
=== Deprecations in 1.34 ===
$req: AuthenticationRequest object describing the change (and target user)
$status: StatusValue with the result of the action
-'ChangePasswordForm': DEPRECATED since 1.27! Use AuthChangeFormFields or
-security levels. For extensions that need to add a field to the ChangePassword
-form via the Preferences form.
-&$extraFields: An array of arrays that hold fields like would be passed to the
- pretty function.
-
'ChangesListInitRows': Batch process change list rows prior to rendering.
$changesList: ChangesList instance
$rows: The data that will be rendered. May be a \Wikimedia\Rdbms\IResultWrapper
}
/**
- * Set PHP's memory limit to the larger of php.ini or $wgMemoryLimit
+ * Raise PHP's memory limit (if needed).
*
- * @return int Resulting value of the memory limit.
+ * @internal For use by Setup.php
*/
-function wfMemoryLimit() {
- global $wgMemoryLimit;
- $memlimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
- if ( $memlimit != -1 ) {
- $conflimit = wfShorthandToInteger( $wgMemoryLimit );
- if ( $conflimit == -1 ) {
+function wfMemoryLimit( $newLimit ) {
+ $oldLimit = wfShorthandToInteger( ini_get( 'memory_limit' ) );
+ // If the INI config is already unlimited, there is nothing larger
+ if ( $oldLimit != -1 ) {
+ $newLimit = wfShorthandToInteger( $newLimit );
+ if ( $newLimit == -1 ) {
wfDebug( "Removing PHP's memory limit\n" );
Wikimedia\suppressWarnings();
- ini_set( 'memory_limit', $conflimit );
+ ini_set( 'memory_limit', $newLimit );
Wikimedia\restoreWarnings();
- return $conflimit;
- } elseif ( $conflimit > $memlimit ) {
- wfDebug( "Raising PHP's memory limit to $conflimit bytes\n" );
+ } elseif ( $newLimit > $oldLimit ) {
+ wfDebug( "Raising PHP's memory limit to $newLimit bytes\n" );
Wikimedia\suppressWarnings();
- ini_set( 'memory_limit', $conflimit );
+ ini_set( 'memory_limit', $newLimit );
Wikimedia\restoreWarnings();
- return $conflimit;
}
}
- return $memlimit;
}
/**
*/
public function insertRevisionOn( RevisionRecord $rev, IDatabase $dbw ) {
// TODO: pass in a DBTransactionContext instead of a database connection.
- $this->checkDatabaseWikiId( $dbw );
+ $this->checkDatabaseDomain( $dbw );
$slotRoles = $rev->getSlotRoles();
$minor,
User $user
) {
- $this->checkDatabaseWikiId( $dbw );
+ $this->checkDatabaseDomain( $dbw );
$pageId = $title->getArticleID();
* @param IDatabase $db
* @throws MWException
*/
- private function checkDatabaseWikiId( IDatabase $db ) {
- $storeWiki = $this->dbDomain;
- $dbWiki = $db->getDomainID();
-
- if ( $dbWiki === $storeWiki ) {
- return;
- }
-
- $storeWiki = $storeWiki ?: $this->loadBalancer->getLocalDomainID();
- // @FIXME: when would getDomainID() be false here?
- $dbWiki = $dbWiki ?: wfWikiID();
-
- if ( $dbWiki === $storeWiki ) {
- return;
- }
-
- // HACK: counteract encoding imposed by DatabaseDomain
- $storeWiki = str_replace( '?h', '-', $storeWiki );
- $dbWiki = str_replace( '?h', '-', $dbWiki );
-
- if ( $dbWiki === $storeWiki ) {
+ private function checkDatabaseDomain( IDatabase $db ) {
+ $dbDomain = $db->getDomainID();
+ $storeDomain = $this->loadBalancer->resolveDomainID( $this->dbDomain );
+ if ( $dbDomain === $storeDomain ) {
return;
}
- throw new MWException( "RevisionStore for $storeWiki "
- . "cannot be used with a DB connection for $dbWiki" );
+ throw new MWException( "DB connection domain '$dbDomain' does not match '$storeDomain'" );
}
/**
* @return object|false data row as a raw object
*/
private function fetchRevisionRowFromConds( IDatabase $db, $conditions, $flags = 0 ) {
- $this->checkDatabaseWikiId( $db );
+ $this->checkDatabaseDomain( $db );
$revQuery = $this->getQueryInfo( [ 'page', 'user' ] );
$options = [];
* of the corresponding revision.
*/
public function listRevisionSizes( IDatabase $db, array $revIds ) {
- $this->checkDatabaseWikiId( $db );
+ $this->checkDatabaseDomain( $db );
$revLens = [];
if ( !$revIds ) {
* @return int
*/
private function getPreviousRevisionId( IDatabase $db, RevisionRecord $rev ) {
- $this->checkDatabaseWikiId( $db );
+ $this->checkDatabaseDomain( $db );
if ( $rev->getPageId() === null ) {
return 0;
* @return int
*/
public function countRevisionsByPageId( IDatabase $db, $id ) {
- $this->checkDatabaseWikiId( $db );
+ $this->checkDatabaseDomain( $db );
$row = $db->selectRow( 'revision',
[ 'revCount' => 'COUNT(*)' ],
* @return bool True if the given user was the only one to edit since the given timestamp
*/
public function userWasLastToEdit( IDatabase $db, $pageId, $userId, $since ) {
- $this->checkDatabaseWikiId( $db );
+ $this->checkDatabaseDomain( $db );
if ( !$userId ) {
return false;
// Start the autoloader, so that extensions can derive classes from core files
require_once "$IP/includes/AutoLoader.php";
-// Load up some global defines
+// Load global constants
require_once "$IP/includes/Defines.php";
// Load default settings
die( 1 );
}
+/**
+ * Changes to the PHP environment that don't vary on configuration.
+ */
+
// Install a header callback
MediaWiki\HeaderCallback::register();
+// Set the encoding used by reading HTTP input, writing HTTP output.
+// This is also the default for mbstring functions.
+mb_internal_encoding( 'UTF-8' );
+
/**
* Load LocalSettings.php
*/
// Don't let any other extensions load
ExtensionRegistry::getInstance()->finish();
-mb_internal_encoding( 'UTF-8' );
-
// Set the configured locale on all requests for consisteny
putenv( "LC_ALL=$wgShellLocale" );
setlocale( LC_ALL, $wgShellLocale );
$ps_misc = Profiler::instance()->scopedProfileIn( $fname . '-misc' );
// Raise the memory limit if it's too low
-wfMemoryLimit();
+// Note, this makes use of wfDebug, and thus should not be before
+// MWDebug::init() is called.
+wfMemoryLimit( $wgMemoryLimit );
/**
* Set up the timezone, suppressing the pseudo-security warning in PHP 5.1+
* @since 1.20
*/
public function getSubpage( $text ) {
- return self::makeTitleSafe( $this->mNamespace, $this->getText() . '/' . $text );
+ return self::makeTitleSafe(
+ $this->mNamespace,
+ $this->getText() . '/' . $text,
+ '',
+ $this->mInterwiki
+ );
}
/**
--- /dev/null
+# wikimedia/objectcache
+
+## Statistics
+
+Sent to StatsD under MediaWiki's namespace.
+
+### WANObjectCache
+
+The default WANObjectCache provided by MediaWikiServices disables these
+statistics in processes where `$wgCommandLineMode` is true.
+
+#### `wanobjectcache.{kClass}.{cache_action_and_result}`
+
+Call counter from `WANObjectCache::getWithSetCallback()`.
+
+* Type: Counter.
+* Variable `kClass`: The first part of your cache key.
+* Variable `result`: One of:
+ * `"hit.good"`,
+ * `"hit.refresh"`,
+ * `"hit.volatile"`,
+ * `"hit.stale"`,
+ * `"miss.busy"` (or `"renew.busy"`, if the `minAsOf` is used),
+ * `"miss.compute"` (or `"renew.busy"`, if the `minAsOf` is used).
+
+#### `wanobjectcache.{kClass}.regen_set_delay`
+
+Upon cache miss, this measures the time spent in `WANObjectCache::getWithSetCallback()`,
+from the start of the method to right after the new value has been computed by the callback.
+
+This essentially measures the whole method (including retrieval of any old value,
+validation, any locks for `lockTSE`, and the callbacks), except for the time spent
+in sending the value to the backend server.
+
+* Type: Measure (in milliseconds).
+* Variable `kClass`: The first part of your cache key.
+
+#### `wanobjectcache.{kClass}.ck_touch.{result}`
+
+Call counter from `WANObjectCache::touchCheckKey()`.
+
+* Type: Counter.
+* Variable `kClass`: The first part of your cache key.
+* Variable `result`: One of `"ok"` or `"error"`.
+
+#### `wanobjectcache.{kClass}.ck_reset.{result}`
+
+Call counter from `WANObjectCache::resetCheckKey()`.
+
+* Type: Counter.
+* Variable `kClass`: The first part of your cache key.
+* Variable `result`: One of `"ok"` or `"error"`.
+
+#### `wanobjectcache.{kClass}.delete.{result}`
+
+Call counter from `WANObjectCache::delete()`.
+
+* Type: Counter.
+* Variable `kClass`: The first part of your cache key.
+* Variable `result`: One of `"ok"` or `"error"`.
+
+#### `wanobjectcache.{kClass}.cooloff_bounce`
+
+Upon a cache miss, the `WANObjectCache::getWithSetCallback()` method generally
+recomputes the value from the callback, and stores it for re-use.
+
+If regenerating the value costs more than a certain threshold of time (e.g. 50ms),
+then for popular keys it is likely that many web servers will generate and store
+the value simultaneously when the key is entirely absent from the cache. In this case,
+the cool-off feature can be used to protect backend cache servers against network
+congestion. This protection is implemented with a lock and subsequent cool-off period.
+The winner stores their value, while other web server return their value directly.
+
+This counter is incremented whenever a new value was regenerated but not stored.
+
+* Type: Counter.
+* Variable `kClass`: The first part of your cache key.
+
+When the regeneration callback is slow, these scenarios may use the cool-off feature:
+
+* Storing the first interim value for tombstoned keys.
+
+ If a key is currently tombstoned due to a recent `delete()` action, and thus in "hold-off", then
+ the key may not be written to. A mutex lock will let one web server generate the new value and
+ (until the hold-off is over) the generated value will be considered an interim (temporary) value
+ only. Requests that cannot get the lock will use the last stored interim value.
+ If there is no interim value yet, then requests that cannot get the lock may still generate their
+ own value. Here, the cool-off feature is used to decide which requests stores their interim value.
+
+* Storing the first interim value for stale keys.
+
+ If a key is currently in "hold-off" due to a recent `touchCheckKey()` action, then the key may
+ not be written to. A mutex lock will let one web request generate the new value and (until the
+ hold-off is over) such value will be considered an interim (temporary) value only. Requests that
+ lose the lock, will instead return the last stored interim value, or (if it remained in cache) the
+ stale value preserved from before `touchCheckKey()` was called.
+ If there is no stale value and no interim value yet, then multiple requests may need to
+ generate the value simultaneously. In this case, the cool-off feature is used to decide
+ which requests store their interim value.
+
+ The same logic applies when the callback passed to getWithSetCallback() in the "touchedCallback"
+ parameter starts returning an updated timestamp due to a dependency change.
+
+* Storing the first value when `lockTSE` is used.
+
+ When `lockTSE` is in use, and no stale value is found on the backend, and no `busyValue`
+ callback is provided, then multiple requests may generate the value simultaneously;
+ the cool-off is used to decide which requests store their interim value.
use Psr\Log\NullLogger;
use Wikimedia\ScopedCallback;
use Wikimedia\Timestamp\ConvertibleTimestamp;
-use Wikimedia;
+use Wikimedia\AtEase\AtEase;
use BagOStuff;
use HashBagOStuff;
use LogicException;
$fname = false,
callable $inputCallback = null
) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$fp = fopen( $filename, 'r' );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
if ( $fp === false ) {
throw new RuntimeException( "Could not open \"{$filename}\"" );
if ( $this->conn ) {
// Avoid connection leaks for sanity. Normally, resources close at script completion.
// The connection might already be closed in zend/hhvm by now, so suppress warnings.
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$this->closeConnection();
- Wikimedia\restoreWarnings();
- $this->conn = false;
+ AtEase::restoreWarnings();
+ $this->conn = null;
}
}
}
use DateTime;
use DateTimeZone;
-use Wikimedia;
+use Wikimedia\AtEase\AtEase;
use InvalidArgumentException;
use Exception;
use RuntimeException;
* @throws DBUnexpectedError
*/
public function freeResult( $res ) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$ok = $this->mysqlFreeResult( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
if ( !$ok ) {
throw new DBUnexpectedError( $this, "Unable to free MySQL result" );
}
* @throws DBUnexpectedError
*/
public function fetchObject( $res ) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$row = $this->mysqlFetchObject( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
$errno = $this->lastErrno();
// Unfortunately, mysql_fetch_object does not reset the last errno.
* @throws DBUnexpectedError
*/
public function fetchRow( $res ) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$row = $this->mysqlFetchArray( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
$errno = $this->lastErrno();
// Unfortunately, mysql_fetch_array does not reset the last errno.
if ( is_bool( $res ) ) {
$n = 0;
} else {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$n = $this->mysqlNumRows( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
}
// Unfortunately, mysql_num_rows does not reset the last errno.
public function lastError() {
if ( $this->conn ) {
# Even if it's non-zero, it can still be invalid
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$error = $this->mysqlError( $this->conn );
if ( !$error ) {
$error = $this->mysqlError();
}
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
} else {
$error = $this->mysqlError();
}
use Wikimedia\Timestamp\ConvertibleTimestamp;
use Wikimedia\WaitConditionLoop;
-use Wikimedia;
+use Wikimedia\AtEase\AtEase;
use Exception;
/**
}
public function freeResult( $res ) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$ok = pg_free_result( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
if ( !$ok ) {
throw new DBUnexpectedError( $this, "Unable to free Postgres result\n" );
}
}
public function fetchObject( $res ) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$row = pg_fetch_object( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
# @todo FIXME: HACK HACK HACK HACK debug
# @todo hashar: not sure if the following test really trigger if the object
}
public function fetchRow( $res ) {
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$row = pg_fetch_array( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
$conn = $this->getBindingHandle();
if ( pg_last_error( $conn ) ) {
return 0;
}
- Wikimedia\suppressWarnings();
+ AtEase::suppressWarnings();
$n = pg_num_rows( ResultWrapper::unwrap( $res ) );
- Wikimedia\restoreWarnings();
+ AtEase::restoreWarnings();
$conn = $this->getBindingHandle();
if ( pg_last_error( $conn ) ) {
* @deprecated Since 1.28 Use MediaWikiServices::getInstance()->getMainWANObjectCache()
*/
public static function getMainWANInstance() {
+ wfDeprecated( __METHOD__, '1.28' );
return MediaWikiServices::getInstance()->getMainWANObjectCache();
}
* @throws MWException
*/
protected function getDB( $serverIndex ) {
- if ( !isset( $this->conns[$serverIndex] ) ) {
- if ( $serverIndex >= $this->numServers ) {
- throw new MWException( __METHOD__ . ": Invalid server index \"$serverIndex\"" );
- }
+ if ( $serverIndex >= $this->numServers ) {
+ throw new MWException( __METHOD__ . ": Invalid server index \"$serverIndex\"" );
+ }
- # Don't keep timing out trying to connect for each call if the DB is down
- if ( isset( $this->connFailureErrors[$serverIndex] )
- && ( time() - $this->connFailureTimes[$serverIndex] ) < 60
- ) {
- throw $this->connFailureErrors[$serverIndex];
- }
+ # Don't keep timing out trying to connect for each call if the DB is down
+ if (
+ isset( $this->connFailureErrors[$serverIndex] ) &&
+ ( time() - $this->connFailureTimes[$serverIndex] ) < 60
+ ) {
+ throw $this->connFailureErrors[$serverIndex];
+ }
- if ( $this->serverInfos ) {
+ if ( $this->serverInfos ) {
+ if ( !isset( $this->conns[$serverIndex] ) ) {
// Use custom database defined by server connection info
$info = $this->serverInfos[$serverIndex];
$type = $info['type'] ?? 'mysql';
$this->logger->debug( __CLASS__ . ": connecting to $host" );
$db = Database::factory( $type, $info );
$db->clearFlag( DBO_TRX ); // auto-commit mode
+ $this->conns[$serverIndex] = $db;
+ }
+ $db = $this->conns[$serverIndex];
+ } else {
+ // Use the main LB database
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
+ $index = $this->replicaOnly ? DB_REPLICA : DB_MASTER;
+ if ( $lb->getServerType( $lb->getWriterIndex() ) !== 'sqlite' ) {
+ // Keep a separate connection to avoid contention and deadlocks
+ $db = $lb->getConnection( $index, [], false, $lb::CONN_TRX_AUTOCOMMIT );
} else {
- // Use the main LB database
- $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
- $index = $this->replicaOnly ? DB_REPLICA : DB_MASTER;
- if ( $lb->getServerType( $lb->getWriterIndex() ) !== 'sqlite' ) {
- // Keep a separate connection to avoid contention and deadlocks
- $db = $lb->getConnection( $index, [], false, $lb::CONN_TRX_AUTOCOMMIT );
- } else {
- // However, SQLite has the opposite behavior due to DB-level locking.
- // Stock sqlite MediaWiki installs use a separate sqlite cache DB instead.
- $db = $lb->getConnection( $index );
- }
+ // However, SQLite has the opposite behavior due to DB-level locking.
+ // Stock sqlite MediaWiki installs use a separate sqlite cache DB instead.
+ $db = $lb->getConnection( $index );
}
-
- $this->logger->debug( sprintf( "Connection %s will be used for SqlBagOStuff", $db ) );
- $this->conns[$serverIndex] = $db;
}
- return $this->conns[$serverIndex];
+ $this->logger->debug( sprintf( "Connection %s will be used for SqlBagOStuff", $db ) );
+
+ return $db;
}
/**
# Show delete and move logs if there were any such events.
# The logging query can DOS the site when bots/crawlers cause 404 floods,
# so be careful showing this. 404 pages must be cheap as they are hard to cache.
- $cache = $services->getMainObjectStash();
- $key = $cache->makeKey( 'page-recent-delete', md5( $title->getPrefixedText() ) );
+ $dbCache = ObjectCache::getInstance( 'db-replicated' );
+ $key = $dbCache->makeKey( 'page-recent-delete', md5( $title->getPrefixedText() ) );
$loggedIn = $this->getContext()->getUser()->isLoggedIn();
$sessionExists = $this->getContext()->getRequest()->getSession()->isPersistent();
- if ( $loggedIn || $cache->get( $key ) || $sessionExists ) {
+ if ( $loggedIn || $dbCache->get( $key ) || $sessionExists ) {
$logTypes = [ 'delete', 'move', 'protect' ];
$dbr = wfGetDB( DB_REPLICA );
$status->value = $logid;
// Show log excerpt on 404 pages rather than just a link
- $cache = MediaWikiServices::getInstance()->getMainObjectStash();
- $key = $cache->makeKey( 'page-recent-delete', md5( $logTitle->getPrefixedText() ) );
- $cache->set( $key, 1, $cache::TTL_DAY );
+ $dbCache = ObjectCache::getInstance( 'db-replicated' );
+ $key = $dbCache->makeKey( 'page-recent-delete', md5( $logTitle->getPrefixedText() ) );
+ $dbCache->set( $key, 1, $dbCache::TTL_DAY );
}
return $status;
return $params;
}
- public function onAuthChangeFormFields(
- array $requests, array $fieldInfo, array &$formDescriptor, $action
- ) {
- // This method is never called for remove actions.
-
- $extraFields = [];
- Hooks::run( 'ChangePasswordForm', [ &$extraFields ], '1.27' );
- foreach ( $extraFields as $extra ) {
- list( $name, $label, $type, $default ) = $extra;
- $formDescriptor[$name] = [
- 'type' => $type,
- 'name' => $name,
- 'label-message' => $label,
- 'default' => $default,
- ];
-
- }
-
- return parent::onAuthChangeFormFields( $requests, $fieldInfo, $formDescriptor, $action );
- }
-
public function execute( $subPage ) {
$this->setHeaders();
$this->outputHeader();
* @file
* @ingroup Upload
*/
-use MediaWiki\MediaWikiServices;
use MediaWiki\Shell\Shell;
/**
protected $mTempPath;
/** @var TempFSFile|null Wrapper to handle deleting the temp file */
protected $tempFileObj;
-
- protected $mDesiredDestName, $mDestName, $mRemoveTempFile, $mSourceType;
- protected $mTitle = false, $mTitleError = 0;
- protected $mFilteredName, $mFinalExtension;
- protected $mLocalFile, $mStashFile, $mFileSize, $mFileProps;
+ /** @var string|null */
+ protected $mDesiredDestName;
+ /** @var string|null */
+ protected $mDestName;
+ /** @var string|null */
+ protected $mRemoveTempFile;
+ /** @var string|null */
+ protected $mSourceType;
+ /** @var Title|bool */
+ protected $mTitle = false;
+ /** @var int */
+ protected $mTitleError = 0;
+ /** @var string|null */
+ protected $mFilteredName;
+ /** @var string|null */
+ protected $mFinalExtension;
+ /** @var LocalFile */
+ protected $mLocalFile;
+ /** @var UploadStashFile */
+ protected $mStashFile;
+ /** @var int|null */
+ protected $mFileSize;
+ /** @var array|null */
+ protected $mFileProps;
+ /** @var string[] */
protected $mBlackListedExtensions;
- protected $mJavaDetected, $mSVGNSError;
+ /** @var bool|null */
+ protected $mJavaDetected;
+ /** @var string|null */
+ protected $mSVGNSError;
protected static $safeXmlEncodings = [
'UTF-8',
* @todo Replace this with a whitelist filter!
* @param string $element
* @param array $attribs
- * @param array|null $data
+ * @param string|null $data
* @return bool|array
*/
public function checkSvgScriptCallback( $element, $attribs, $data = null ) {
* @return Status[]|bool
*/
public static function getSessionStatus( User $user, $statusKey ) {
- $cache = MediaWikiServices::getInstance()->getMainObjectStash();
- $key = $cache->makeKey( 'uploadstatus', $user->getId() ?: md5( $user->getName() ), $statusKey );
+ $store = self::getUploadSessionStore();
+ $key = self::getUploadSessionKey( $store, $user, $statusKey );
- return $cache->get( $key );
+ return $store->get( $key );
}
/**
*
* The value will be set in cache for 1 day
*
+ * Avoid triggering this method on HTTP GET/HEAD requests
+ *
* @param User $user
* @param string $statusKey
* @param array|bool $value
* @return void
*/
public static function setSessionStatus( User $user, $statusKey, $value ) {
- $cache = MediaWikiServices::getInstance()->getMainObjectStash();
- $key = $cache->makeKey( 'uploadstatus', $user->getId() ?: md5( $user->getName() ), $statusKey );
+ $store = self::getUploadSessionStore();
+ $key = self::getUploadSessionKey( $store, $user, $statusKey );
if ( $value === false ) {
- $cache->delete( $key );
+ $store->delete( $key );
} else {
- $cache->set( $key, $value, $cache::TTL_DAY );
+ $store->set( $key, $value, $store::TTL_DAY );
}
}
+
+ /**
+ * @param BagOStuff $store
+ * @param User $user
+ * @param string $statusKey
+ * @return string
+ */
+ private static function getUploadSessionKey( BagOStuff $store, User $user, $statusKey ) {
+ return $store->makeKey(
+ 'uploadstatus',
+ $user->getId() ?: md5( $user->getName() ),
+ $statusKey
+ );
+ }
+
+ /**
+ * @return BagOStuff
+ */
+ private static function getUploadSessionStore() {
+ return ObjectCache::getInstance( 'db-replicated' );
+ }
}
* @author Michael Dale
*/
class UploadFromChunks extends UploadFromFile {
+ /** @var LocalRepo */
+ private $repo;
+ /** @var UploadStash */
+ public $stash;
+ /** @var User */
+ public $user;
+
protected $mOffset;
protected $mChunkIndex;
protected $mFileKey;
protected $mVirtualTempPath;
- /** @var LocalRepo */
- private $repo;
+
+ /** @noinspection PhpMissingParentConstructorInspection */
/**
* Setup local pointers to stash, repo and user (similar to UploadFromStash)
'〇周后' => '〇周後',
'〇只' => '〇隻',
'〇余' => '〇餘',
+'》里' => '》裡',
'“' => '「',
'”' => '」',
'‘' => '『',
'包准' => '包準',
'包谷' => '包穀',
'包扎' => '包紮',
+'包制' => '包製',
'匏系' => '匏繫',
'北山索面' => '北山索麵',
'北仑河' => '北崙河',
'后安路' => '后安路',
'后平路' => '后平路',
'后庄' => '后庄',
-'后座' => '后座',
'后母戊' => '后母戊',
'后海湾' => '后海灣',
'后海灣' => '后海灣',
'方便面' => '方便麵',
'方向' => '方向',
'方法里' => '方法裡',
+'于吉林' => '於吉林',
'于震中' => '於震中',
'于震前' => '於震前',
'于震后' => '於震後',
'松口镇' => '松口鎮',
'松山庄' => '松山庄',
'松溪县' => '松谿縣',
+'松开始' => '松開始',
'板荡' => '板蕩',
'林宏岳' => '林宏嶽',
'林杰樑' => '林杰樑',
'片里' => '片裡',
'片言只语' => '片言隻語',
'版图里' => '版圖裡',
+'版本里' => '版本裡',
'牙签' => '牙籤',
'牛只' => '牛隻',
'物欲' => '物慾',
'理次发' => '理次髮',
'理发动' => '理發動',
'理发展' => '理發展',
+'理发放' => '理發放',
'理发现' => '理發現',
'理发生' => '理發生',
'理发表' => '理發表',
'空蒙' => '空濛',
'空荡' => '空蕩',
'空荡荡' => '空蕩蕩',
+'空里' => '空裡',
'空钟' => '空鐘',
'空余' => '空餘',
'窒欲' => '窒慾',
'制成' => '製成',
'制毒' => '製毒',
'制法' => '製法',
+'制汉字' => '製漢字',
'制浆' => '製漿',
'制片' => '製片',
'制版' => '製版',
'托交' => '託交',
'托付' => '託付',
'托克逊' => '託克遜',
-'托儿' => '託兒',
'托古讽今' => '託古諷今',
'托名' => '託名',
'托命' => '託命',
'这只比' => '這只比',
'这只用' => '這只用',
'这只能' => '這只能',
+'这只要' => '這只要',
'这只限' => '這只限',
'这只需' => '這只需',
'这只须' => '這只須',
'那只比' => '那只比',
'那只用' => '那只用',
'那只能' => '那只能',
+'那只要' => '那只要',
'那只限' => '那只限',
'那只需' => '那只需',
'那只须' => '那只須',
'厘革' => '釐革',
'金仆姑' => '金僕姑',
'金城里' => '金城里',
+'金发放' => '金發放',
'金范' => '金範',
'金圣叹' => '金聖歎',
'金表情' => '金表情',
'闯荡' => '闖蕩',
'闯炼' => '闖鍊',
'关系' => '關係',
+'关注:' => '關注:',
+'關注:' => '關注:',
'关系列' => '關系列',
'关系所' => '關系所',
'关系科' => '關系科',
'島' => '岛',
'峽' => '峡',
'崍' => '崃',
-'崑' => '昆',
'崗' => '岗',
'崙' => '仑',
'崢' => '峥',
'昇汞' => '升汞',
'陞用' => '升用',
'陞補' => '升补',
+'昇起' => '升起',
'陞遷' => '升迁',
'昇降' => '升降',
'卓著' => '卓著',
'旋乾转坤' => '旋乾转坤',
'無言不讎' => '无言不雠',
'曠若發矇' => '旷若发矇',
+'崑崙' => '昆仑',
+'崑岡' => '昆冈',
+'崑劇' => '昆剧',
+'崑山' => '昆山',
+'崑嵛' => '昆嵛',
+'崑承湖' => '昆承湖',
+'崑曲' => '昆曲',
+'崑腔' => '昆腔',
+'崑蘇' => '昆苏',
+'崑調' => '昆调',
'易·乾' => '易·乾',
'易經·乾' => '易经·乾',
'易经·乾' => '易经·乾',
'瀋液' => '渖液',
'满拚自尽' => '满拚自尽',
'滿拚自盡' => '满拚自尽',
+'靈崑' => '灵昆',
'薰習' => '熏习',
'薰心' => '熏心',
'薰沐' => '熏沐',
'老么' => '老幺',
'肉乾乾' => '肉干干',
'肘手鍊足' => '肘手链足',
+'蘇崑' => '苏昆',
'甦醒' => '苏醒',
'苧烯' => '苧烯',
'薴烯' => '苧烯',
'蔡孝乾' => '蔡孝乾',
'蔡絛' => '蔡絛',
'行餘' => '行馀',
+'西崑' => '西昆',
'覆蓋' => '覆盖',
'見微知著' => '见微知著',
'見著' => '见著',
'局域网' => '區域網',
'局域网络' => '區域網路',
'十杆' => '十桿',
-'特立尼达和托巴哥' => '千里達托貝哥',
-'特立尼達和多巴哥' => '千里達托貝哥',
+'特立尼达和托巴哥' => '千里達及托巴哥',
+'特立尼達和多巴哥' => '千里達及托巴哥',
'不列颠哥伦比亚省' => '卑詩省',
'南朝鲜' => '南韓',
'卡斯特罗' => '卡斯楚',
'塞维利亚' => '塞維亞',
'西維爾' => '塞維亞',
'塞黑' => '塞蒙',
+'塔希提' => '大溪地',
'共和联邦' => '大英國協',
'英联邦' => '大英國協',
'英聯邦' => '大英國協',
'尼日尔' => '尼日',
'尼日爾' => '尼日',
'雅马哈' => '山葉',
-'巴厘岛' => '峇里島',
+'巴厘' => '峇里',
'特朗普' => '川普',
'机床' => '工具機',
'機床' => '工具機',
'萌島' => '曼島',
'马恩岛' => '曼島',
'木杆' => '木桿',
+'尾班車' => '末班車',
'列奥纳多' => '李奧納多',
'杜塞尔多夫' => '杜塞道夫',
'杜塞爾多夫' => '杜塞道夫',
'圣基茨和尼维斯' => '聖克里斯多福及尼維斯',
'聖吉斯納域斯' => '聖克里斯多福及尼維斯',
'聖佐治' => '聖喬治',
+'圣多美和普林西比' => '聖多美普林西比',
+'聖多美和普林西比' => '聖多美普林西比',
'圣文森特和格林纳丁斯' => '聖文森及格瑞那丁',
'聖文森特和格林納丁斯' => '聖文森及格瑞那丁',
'圣赫勒拿' => '聖赫倫那',
'扎伊爾' => '薩伊',
'素檀' => '蘇丹',
'苏里南' => '蘇利南',
+'蘇里南' => '蘇利南',
'浮罗交怡' => '蘭卡威',
'浮羅交怡' => '蘭卡威',
'劳拉' => '蘿拉',
'香煙' => '香菸',
'馬里共和國' => '馬利共和國',
'马里共和国' => '馬利共和國',
+'馬拉維' => '馬拉威',
'马拉维' => '馬拉威',
'馬勒當拿' => '馬拉度納',
'马拉多纳' => '馬拉度納',
'IP地址' => 'IP位址',
'·威尔士' => '·威爾士',
'·威爾士' => '·威爾士',
+'》里' => '》裏',
'一地里' => '一地裏',
'三十六著' => '三十六着',
'三極體' => '三極管',
'夢著述' => '夢著述',
'夢著錄' => '夢著錄',
'梦里' => '夢裏',
+'塔希提' => '大溪地',
'天里' => '天裏',
'宇航员' => '太空人',
'夾著' => '夾着',
'山里的' => '山裏的',
'甘比亞' => '岡比亞',
'岸裡' => '岸裡',
-'巴厘岛' => '峇里島',
+'巴厘' => '峇里',
'工作台' => '工作枱',
'已占' => '已佔',
'巴塞罗那' => '巴塞隆拿',
'爭著錄' => '爭著錄',
'墙里' => '牆裏',
'版图里' => '版圖裏',
+'版本里' => '版本裏',
'版权信息' => '版權資訊',
-'千里達托貝哥' => '特立尼達和多巴哥',
+'千里達及托巴哥' => '特立尼達和多巴哥',
'牽著' => '牽着',
'牽著作' => '牽著作',
'牽著名' => '牽著名',
'空著者' => '空著者',
'空著述' => '空著述',
'空著錄' => '空著錄',
+'空里' => '空裏',
'太空梭' => '穿梭機',
'航天飞机' => '穿梭機',
'穿著' => '穿着',
'聖喬治' => '聖佐治',
'圣基茨和尼维斯' => '聖吉斯納域斯',
'聖克里斯多福及尼維斯' => '聖吉斯納域斯',
+'聖多美普林西比' => '聖多美和普林西比',
'聖文森及格瑞那丁' => '聖文森特和格林納丁斯',
'聖露西亞' => '聖盧西亞',
'聖馬利諾' => '聖馬力諾',
'藏著者' => '藏著者',
'藏著述' => '藏著述',
'藏著錄' => '藏著錄',
+'蘇利南' => '蘇里南',
'蘊涵著' => '蘊涵着',
'蘸著' => '蘸着',
'蘸著作' => '蘸著作',
'馬拉度納' => '馬勒當拿',
'马拉多纳' => '馬勒當拿',
'马拉特·萨芬' => '馬拉特·沙芬',
+'馬拉威' => '馬拉維',
'馬斯垂克' => '馬斯特里赫特',
'馬爾地夫' => '馬爾代夫',
'馬利共和國' => '馬里共和國',
'駕著者' => '駕著者',
'駕著述' => '駕著述',
'駕著錄' => '駕著錄',
+'駛著' => '駛着',
'騎著' => '騎着',
'騎著作' => '騎著作',
'騎著名' => '騎著名',
'騙著者' => '騙著者',
'騙著述' => '騙著述',
'騙著錄' => '騙著錄',
-'驶著' => '驶着',
'体里' => '體裏',
'高畫質' => '高清',
'高著' => '高着',
'全球資訊網' => '万维网',
'三十六著' => '三十六着',
'三極體' => '三极管',
+'上落客' => '上下客',
'下著' => '下着',
'下著作' => '下著作',
'下著名' => '下著名',
'下著稱' => '下著称',
'下著者' => '下著者',
'下著述' => '下著述',
+'落車' => '下车',
'卑詩省' => '不列颠哥伦比亚省',
'不著' => '不着',
'不著書' => '不著书',
'聖露西亞' => '圣卢西亚',
'聖克里斯多福及尼維斯' => '圣基茨和尼维斯',
'聖吉斯納域斯' => '圣基茨和尼维斯',
+'聖多美普林西比' => '圣多美和普林西比',
'聖文森及格瑞那丁' => '圣文森特和格林纳丁斯',
'聖馬利諾' => '圣马力诺',
'蓋亞那' => '圭亚那',
'朝著稱' => '朝著称',
'朝著者' => '朝著者',
'朝著述' => '朝著述',
+'尾班車' => '末班车',
'賓·拉登' => '本·拉登',
'本份' => '本分',
'賓拉登' => '本拉登',
'牽著述' => '牵著述',
'千里達' => '特立尼达',
'千里達及托巴哥' => '特立尼达和多巴哥',
-'千里達托貝哥' => '特立尼达和托巴哥',
'德蕾莎·梅伊' => '特蕾莎·梅',
'文翠珊' => '特蕾莎·梅',
'狗隻' => '犬只',
索羅門群島 所罗门群岛
汶萊 文莱
史瓦濟蘭 斯威士兰
+史瓦帝尼 斯威士兰
斯洛維尼亞 斯洛文尼亚
紐西蘭 新西兰
格瑞那達 格林纳达
波士尼亞與赫塞哥維納 波斯尼亚和黑塞哥维那
辛巴威 津巴布韦
宏都拉斯 洪都拉斯
-千里達托貝哥 特立尼达和托巴哥
萬那杜 瓦努阿图
溫納圖 瓦努阿图
葛摩 科摩罗
電視影集 电视系列剧
原子筆 圆珠笔
智慧卡 智能卡
+尾班車 末班车
+落車 下车
+上落客 上下客
鐵達尼號 泰坦尼克号
轉殖 克隆
空中巴士 空中客车
卑詩省 不列颠哥伦比亚省
丹帕沙 登巴萨
峇里 巴厘
-史瓦帝尼 斯威士兰
皮特肯 皮特凯恩
安地卡 安提瓜
撒拉威阿拉伯 阿拉伯撒哈拉
格瑞那丁 格林纳丁斯
普立茲獎 普利策奖
富比士 福布斯
+聖多美普林西比 圣多美和普林西比
公寓里 公寓裏
窝里斗 窩裏鬥
镇里 鎮裏
+》里 》裏
+空里 空裏
+版本里 版本裏
苑裡 苑裡
霄裡 霄裡
岸裡 岸裡
寫著 寫着
遇著 遇着
殺著 殺着
-驶è\91\97 驶着
+é§\9bè\91\97 é§\9b着
著筆 着筆
著鞭 着鞭
著法 着法
厄瓜多尔 厄瓜多爾
厄瓜多爾 厄瓜多爾
厄瓜多 厄瓜多爾
+馬拉威 馬拉維
百慕大 百慕達
厄利垂亞 厄立特里亞
吉布地 吉布堤
索羅門群島 所羅門群島
文莱 汶萊
史瓦濟蘭 斯威士蘭
+史瓦帝尼 斯威士蘭
斯洛維尼亞 斯洛文尼亞
紐西蘭 新西蘭
格瑞那達 格林納達
沙烏地阿拉伯 沙特阿拉伯
辛巴威 津巴布韋
宏都拉斯 洪都拉斯
-千里達托貝哥 特立尼達和多巴哥
+千里達及托巴哥 特立尼達和多巴哥
萬那杜 瓦努阿圖
葛摩 科摩羅
寮國 老撾
北朝鲜 北韓
寮語 老撾語
寮人民民主共和國 老撾人民民主共和國
+蘇利南 蘇里南
莱特湾 雷伊泰灣
萊特灣 雷伊泰灣
蘭卡威 浮羅交怡
帕拉林匹克 殘疾人奧林匹克
不列颠哥伦比亚省 卑詩省
丹帕沙 登巴薩
-巴厘岛 峇里島
-史瓦帝尼 斯威士蘭
+巴厘 峇里
皮特凯恩 皮特肯
安地卡 安提瓜
撒拉威阿拉伯 阿拉伯撒哈拉
疯牛病 瘋牛症
狂牛症 瘋牛症
普利策奖 普立茲獎
+聖多美普林西比 聖多美和普林西比
+塔希提 大溪地
剖釐 剖厘
一釐 一厘
昇平 升平
+昇起 升起
飛昇 飞升
提昇 提升
高昇 高升
滿拚自盡 满拚自尽
拚生尽死 拚生尽死
拚生盡死 拚生尽死
+崑劇 昆剧
+崑山 昆山
+崑岡 昆冈
+崑崙 昆仑
+崑嵛 昆嵛
+崑曲 昆曲
+崑腔 昆腔
+崑蘇 昆苏
+崑調 昆调
+蘇崑 苏昆
+西崑 西昆
+靈崑 灵昆
+崑承湖 昆承湖
所罗门群岛 索羅門群島
所羅門群島 索羅門群島
文莱 汶萊
-斯威士兰 史瓦濟蘭
-斯威士蘭 史瓦濟蘭
+斯威士兰 史瓦帝尼
+斯威士蘭 史瓦帝尼
斯洛文尼亚 斯洛維尼亞
斯洛文尼亞 斯洛維尼亞
新西兰 紐西蘭
津巴布韦 辛巴威
津巴布韋 辛巴威
洪都拉斯 宏都拉斯
-特立尼达和托巴哥 千里達托貝哥
-特立尼達和多巴哥 千里達托貝哥
+特立尼达和托巴哥 千里達及托巴哥
+特立尼達和多巴哥 千里達及托巴哥
瑙鲁 諾魯
瑙魯 諾魯
瓦努阿图 萬那杜
内罗毕 奈洛比
內羅畢 奈洛比
苏里南 蘇利南
+蘇里南 蘇利南
莫桑比克 莫三比克
莱索托 賴索托
萊索托 賴索托
金沙薩 金夏沙
达累斯萨拉姆 三蘭港
马拉维 馬拉威
+馬拉維 馬拉威
留尼汪 留尼旺
布隆方丹 布隆泉
厄瓜多 厄瓜多
东南亚国家联盟 東南亞國家協會
東南亞國家聯盟 東南亞國家協會
哥特式 哥德式
+尾班車 末班車
落車 下車
上落客 上下客
集装箱 貨櫃
不列颠哥伦比亚省 卑詩省
登巴萨 丹帕沙
登巴薩 丹帕沙
-巴厘岛 峇里島
-斯威士兰 史瓦帝尼
-斯威士蘭 史瓦帝尼
+巴厘 峇里
皮特凯恩 皮特肯
安提瓜 安地卡
阿拉伯撒哈拉 撒拉威阿拉伯
格林納丁斯 格瑞那丁
空中客车 空中巴士
普利策奖 普立茲獎
+圣多美和普林西比 聖多美普林西比
+聖多美和普林西比 聖多美普林西比
+塔希提 大溪地
黄岩县 黃巖縣
黄岩区 黃巖區
北仑河 北崙河
+昆剧 崑劇
+昆山 崑山
+昆冈 崑岡
+昆仑 崑崙
昆嵛 崑嵛
-昆承湖 崑承湖
+昆曲 崑曲
+昆腔 崑腔
+昆苏 崑蘇
+昆调 崑調
+苏昆 蘇崑
+西昆 西崑
灵昆 靈崑
+昆承湖 崑承湖
龙岩 龍巖
扑冬 撲鼕
冬冬鼓 鼕鼕鼓
U+05C6D屭|U+05C43屃|
U+05C85岅|U+05742坂|
U+05CDD峝|U+05CD2峒|
-U+05D11崑|U+06606昆|
U+05D19崙|U+04ED1仑|
U+05D57嵗|U+05C81岁|
U+05D7D嵽|U+2BD87𫶇|
這只比
這只限
這只應
+這只要
這只不過
這只包括
那只能
那只比
那只限
那只應
+那只要
那只不過
那只包括
多只能
黑奴籲天錄
林郁方
讚歌
-崑山
-崑曲
-崑腔
-崑調
-崑劇
-崑蘇
-蘇崑
一干家中
星期後
依依不捨
于禁
于敏中
註:# 不作“注:”
+關注:
劃為# 不作“划為”
一個# 避免“個裡”的錯誤
兩個
殿裡
隊裡
詞裡
+》裡
+空裡
+版本裡
裏白 #植物常用名
烏蘇里 #分詞用
夸脫
于丹
于冕
于吉
+於吉林
于堅
于姓
于氏
米瀋
拾瀋
姦污
-託兒
同人誌
文學誌
衝着
燉製
煮製
熬製
+包製
+製漢字 #和製漢字等
遏制 #以下分詞用
管制
抑制
胎發生
結發育
結發表
+金發放
+理發放
古人有云
昔人有云
云敞
哈囉喂
松口鎮
岩松了
+松開始
沙瑯
琺瑯
菜餚
關系統
關系所
關系科
-崑崙
-崑山
-崑劇
-崑曲
-崑腔
-崑蘇
-崑調
-崑岡
-西崑
-蘇崑
銹病
嚐糞
public static function applyInitialConfig() {
global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType, $wgMainWANCache;
global $wgMainStash;
+ global $wgObjectCaches;
global $wgLanguageConverterCacheType, $wgUseDatabaseMessages;
global $wgLocaltimezone, $wgLocalisationCacheConf;
global $wgSearchType;
$wgLanguageConverterCacheType = 'hash';
// Uses db-replicated in DefaultSettings
$wgMainStash = 'hash';
+ // Use hash instead of db
+ $wgObjectCaches['db-replicated'] = $wgObjectCaches['hash'];
// Use memory job queue
$wgJobTypeConf = [
'default' => [ 'class' => JobQueueMemory::class, 'order' => 'fifo' ],
// Wipe WANObjectCache process cache, which is invalidated by article insertion
// due to T144706
- ObjectCache::getMainWANInstance()->clearProcessCache();
+ MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
$this->executeSetupSnippets( $teardown );
}
/**
* @dataProvider provideDomainCheck
- * @covers \MediaWiki\Revision\RevisionStore::checkDatabaseWikiId
+ * @covers \MediaWiki\Revision\RevisionStore::checkDatabaseDomain
*/
public function testDomainCheck( $wikiId, $dbName, $dbPrefix ) {
$this->setMwGlobals(
<?php
+use MediaWiki\Interwiki\InterwikiLookup;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\MediaWikiServices;
use Wikimedia\TestingAccessWrapper;
];
}
+ public function provideSubpage() {
+ // NOTE: avoid constructing Title objects in the provider, since it may access the database.
+ return [
+ [ 'Foo', 'x', new TitleValue( NS_MAIN, 'Foo/x' ) ],
+ [ 'Foo#bar', 'x', new TitleValue( NS_MAIN, 'Foo/x' ) ],
+ [ 'User:Foo', 'x', new TitleValue( NS_USER, 'Foo/x' ) ],
+ [ 'wiki:User:Foo', 'x', new TitleValue( NS_MAIN, 'User:Foo/x', '', 'wiki' ) ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideSubpage
+ * @covers Title::getSubpage
+ */
+ public function testSubpage( $title, $sub, LinkTarget $expected ) {
+ $interwikiLookup = $this->getMock( InterwikiLookup::class );
+ $interwikiLookup->expects( $this->any() )
+ ->method( 'isValidInterwiki' )
+ ->willReturnCallback(
+ function ( $prefix ) {
+ return $prefix == 'wiki';
+ }
+ );
+
+ $this->setService( 'InterwikiLookup', $interwikiLookup );
+
+ $title = Title::newFromText( $title );
+ $expected = Title::newFromLinkTarget( $expected );
+ $actual = $title->getSubpage( $sub );
+
+ // NOTE: convert to string for comparison
+ $this->assertSame( $expected->getPrefixedText(), $actual->getPrefixedText(), 'text form' );
+ $this->assertTrue( $expected->equals( $actual ), 'Title equality' );
+ }
+
public static function provideNewFromTitleValue() {
return [
[ new TitleValue( NS_MAIN, 'Foo' ) ],
new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
] );
- ObjectCache::getMainWANInstance()->clearProcessCache();
+ MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
$result = $this->doListWatchlistRawRequest( [
'wrowner' => $otherUser->getName(),
'wrtoken' => '1234567890',
}
public function testGetLinkClasses() {
- $wanCache = ObjectCache::getMainWANInstance();
- $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
- $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+ $services = MediaWikiServices::getInstance();
+ $wanCache = $services->getMainWANObjectCache();
+ $titleFormatter = $services->getTitleFormatter();
+ $nsInfo = $services->getNamespaceInfo();
$linkCache = new LinkCache( $titleFormatter, $wanCache, $nsInfo );
$foobarTitle = new TitleValue( NS_MAIN, 'FooBar' );
$redirectTitle = new TitleValue( NS_MAIN, 'Redirect' );
$this->db->delete( 'actor', [ 'actor_user' => $id ], __METHOD__ );
User::purge( $domain, $id );
// Because WANObjectCache->delete() stupidly doesn't delete from the process cache.
- ObjectCache::getMainWANInstance()->clearProcessCache();
+
+ MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
$user = User::newFromId( $id );
$this->assertFalse( $user->getActorId() > 0, 'No Actor ID by default if none in database' );