Use a factory to construct GlobalRenameUserStatus objects

Update the GlobalRenameUserStatus class to use a factory constructor
class like the GlobalRenameUser class already does. This means we can
inject parameters into that class cleanly. All uses in CentralAuth are
updated, I will submit a follow-up for the single use in
WikimediaMaintenance.

The static method getInProgressRenames() is untouched, for now,
although a future patch could move it to GlobalRenameFactory or some
other class where the database can be injected.

Change-Id: I693ced583132ae4e2a9890a0a971b6a14d453c9c
这个提交包含在:
Taavi Väänänen 2024-03-03 12:28:04 +02:00
父节点 4d49b0fa13
当前提交 ca392a20fe
找不到此签名对应的密钥
GPG 密钥 ID: EF242F709F912FBE
共有 10 个文件被更改,包括 118 次插入75 次删除

查看文件

@ -128,7 +128,8 @@
"UserNameUtils",
"UserRegistrationLookup",
"CentralAuth.CentralAuthDatabaseManager",
"CentralAuth.CentralAuthUIService"
"CentralAuth.CentralAuthUIService",
"CentralAuth.GlobalRenameFactory"
]
},
"CentralAutoLogin": {
@ -216,7 +217,8 @@
"class": "MediaWiki\\Extension\\CentralAuth\\Special\\SpecialGlobalRenameProgress",
"services": [
"UserNameUtils",
"CentralAuth.CentralAuthUIService"
"CentralAuth.CentralAuthUIService",
"CentralAuth.GlobalRenameFactory"
]
}
},
@ -355,7 +357,12 @@
"UserNameUtils"
]
},
"globalrenamestatus": "MediaWiki\\Extension\\CentralAuth\\Api\\ApiQueryGlobalRenameStatus"
"globalrenamestatus": {
"class": "MediaWiki\\Extension\\CentralAuth\\Api\\ApiQueryGlobalRenameStatus",
"services": [
"CentralAuth.GlobalRenameFactory"
]
}
},
"APIListModules": {
"globalgroups": {

查看文件

@ -23,6 +23,7 @@ namespace MediaWiki\Extension\CentralAuth\Api;
use ApiQuery;
use ApiQueryBase;
use ApiResult;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameFactory;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameUserStatus;
use Wikimedia\ParamValidator\ParamValidator;
@ -31,9 +32,16 @@ use Wikimedia\ParamValidator\ParamValidator;
*/
class ApiQueryGlobalRenameStatus extends ApiQueryBase {
private GlobalRenameFactory $globalRenameFactory;
/** @inheritDoc */
public function __construct( ApiQuery $queryModule, $moduleName ) {
public function __construct(
ApiQuery $queryModule,
$moduleName,
GlobalRenameFactory $globalRenameFactory
) {
parent::__construct( $queryModule, $moduleName, 'grs' );
$this->globalRenameFactory = $globalRenameFactory;
}
/**
@ -58,7 +66,7 @@ class ApiQueryGlobalRenameStatus extends ApiQueryBase {
* @param string $name Username (old or new)
*/
private function addUser( $name ) {
$statuses = new GlobalRenameUserStatus( $name );
$statuses = $this->globalRenameFactory->newGlobalRenameUserStatus( $name );
$names = $statuses->getNames();
if ( !$names ) {
return;

查看文件

@ -21,6 +21,7 @@
namespace MediaWiki\Extension\CentralAuth;
use MediaWiki\Extension\CentralAuth\GlobalGroup\GlobalGroupLookup;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameFactory;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameRequestStore;
use MediaWiki\Extension\CentralAuth\User\CentralAuthAntiSpoofManager;
use MediaWiki\Extension\CentralAuth\User\CentralAuthForcedLocalCreationService;
@ -127,6 +128,18 @@ class CentralAuthServices {
->get( 'CentralAuth.GlobalGroupLookup' );
}
/**
* @param ContainerInterface|null $services Service container to use. If null, global
* MediaWikiServices::getInstance() will be used instead.
* @return GlobalRenameFactory
*/
public static function getGlobalRenameFactory(
ContainerInterface $services = null
): GlobalRenameFactory {
return ( $services ?: MediaWikiServices::getInstance() )
->get( 'CentralAuth.GlobalRenameFactory' );
}
/**
* @param ContainerInterface|null $services Service container to use. If null, global
* MediaWikiServices::getInstance() will be used instead.

查看文件

@ -89,7 +89,7 @@ class GlobalRenameFactory {
// TODO: this is only used for caching, maybe we can create a Factory service
// for CAUsers and related caching and inject that instead
CentralAuthUser::getInstance( $userNew ),
new GlobalRenameUserStatus( $userNew->getName() ),
$this->newGlobalRenameUserStatus( $userNew->getName() ),
$this->jobQueueGroupFactory,
new GlobalRenameUserDatabaseUpdates( $this->databaseManager ),
new GlobalRenameUserLogger( $performer ),
@ -97,4 +97,10 @@ class GlobalRenameFactory {
);
}
public function newGlobalRenameUserStatus( string $username ): GlobalRenameUserStatus {
return new GlobalRenameUserStatus(
$this->databaseManager,
$username
);
}
}

查看文件

@ -3,13 +3,14 @@
namespace MediaWiki\Extension\CentralAuth\GlobalRename;
use IDBAccessObject;
use MediaWiki\Extension\CentralAuth\CentralAuthDatabaseManager;
use MediaWiki\Extension\CentralAuth\CentralAuthServices;
use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
use MediaWiki\Permissions\Authority;
use MediaWiki\WikiMap\WikiMap;
use Wikimedia\Rdbms\DBQueryError;
use Wikimedia\Rdbms\IDatabase;
use Wikimedia\Rdbms\IExpression;
use Wikimedia\Rdbms\IReadableDatabase;
use Wikimedia\Rdbms\OrExpressionGroup;
/**
@ -22,39 +23,29 @@ use Wikimedia\Rdbms\OrExpressionGroup;
*/
class GlobalRenameUserStatus {
/**
* Either old or new name of the user
*
* @var string
*/
private $name;
private CentralAuthDatabaseManager $databaseManager;
private string $name;
/**
* @param CentralAuthDatabaseManager $databaseManager
* @param string $name Either old or new name of the user
*/
public function __construct( $name ) {
public function __construct(
CentralAuthDatabaseManager $databaseManager,
string $name
) {
$this->databaseManager = $databaseManager;
$this->name = $name;
}
/**
* Get a Database object for the CentralAuth db
*
* @param int $type DB_REPLICA or DB_PRIMARY
*
* @return IDatabase
*/
protected function getDB( $type = DB_REPLICA ) {
return CentralAuthServices::getDatabaseManager()->getCentralDB( $type );
}
/**
* Get the where clause to query rows by either old or new name
*
* @param IDatabase $db
*
* @param IReadableDatabase $db
* @return IExpression
*/
private function getNameWhereClause( IDatabase $db ): IExpression {
private function getNameWhereClause( IReadableDatabase $db ): IExpression {
return $db->expr( 'ru_oldname', '=', $this->name )->or( 'ru_newname', '=', $this->name );
}
@ -66,12 +57,16 @@ class GlobalRenameUserStatus {
* whether it's the old or new name.
*
* @param string|null $wiki Only look for renames on the given wiki.
* @param string|null $usePrimaryDb Set to 'primary' to query the primary db
* @param int $recency IDBAccessObject flags
*
* @return string[] (oldname, newname)
*/
public function getNames( $wiki = null, $usePrimaryDb = null ) {
$db = $this->getDB( $usePrimaryDb === 'primary' ? DB_PRIMARY : DB_REPLICA );
public function getNames( ?string $wiki = null, int $recency = IDBAccessObject::READ_NORMAL ): array {
if ( ( IDBAccessObject::READ_LATEST & $recency ) == IDBAccessObject::READ_LATEST ) {
$db = $this->databaseManager->getCentralPrimaryDB();
} else {
$db = $this->databaseManager->getCentralReplicaDB();
}
$where = [ $this->getNameWhereClause( $db ) ];
@ -83,6 +78,7 @@ class GlobalRenameUserStatus {
->select( [ 'ru_oldname', 'ru_newname' ] )
->from( 'renameuser_status' )
->where( $where )
->recency( $recency )
->caller( __METHOD__ )
->fetchRow();
@ -100,23 +96,22 @@ class GlobalRenameUserStatus {
* Get a user's rename status for all wikis.
* Returns an array ( wiki => status )
*
* @param int $flags IDBAccessObject flags
* @param int $recency IDBAccessObject flags
*
* @return string[]
*/
public function getStatuses( $flags = 0 ) {
if ( ( $flags & IDBAccessObject::READ_LATEST ) == IDBAccessObject::READ_LATEST ) {
$index = DB_PRIMARY;
public function getStatuses( int $recency = IDBAccessObject::READ_NORMAL ): array {
if ( ( IDBAccessObject::READ_LATEST & $recency ) == IDBAccessObject::READ_LATEST ) {
$db = $this->databaseManager->getCentralPrimaryDB();
} else {
$index = DB_REPLICA;
$db = $this->databaseManager->getCentralReplicaDB();
}
$db = $this->getDB( $index );
$res = $db->newSelectQueryBuilder()
->select( [ 'ru_wiki', 'ru_status' ] )
->from( 'renameuser_status' )
->where( [ $this->getNameWhereClause( $db ) ] )
->recency( $flags )
->recency( $recency )
->caller( __METHOD__ )
->fetchResultSet();
@ -131,13 +126,13 @@ class GlobalRenameUserStatus {
/**
* Get a user's rename status for the current wiki.
*
* @param int $flags IDBAccessObject flags
* @param int $recency IDBAccessObject flags
*
* @return string|null Null means no rename pending for this user on the current wiki (possibly
* because it has finished already).
*/
public function getStatus( $flags = 0 ) {
$statuses = $this->getStatuses( $flags );
public function getStatus( int $recency = IDBAccessObject::READ_NORMAL ): ?string {
$statuses = $this->getStatuses( $recency );
return $statuses[WikiMap::getCurrentWikiId()] ?? null;
}
@ -148,7 +143,7 @@ class GlobalRenameUserStatus {
* @param string $status
*/
public function updateStatus( $wiki, $status ) {
$dbw = $this->getDB( DB_PRIMARY );
$dbw = $this->databaseManager->getCentralPrimaryDB();
$fname = __METHOD__;
$dbw->onTransactionPreCommitOrIdle(
@ -169,8 +164,8 @@ class GlobalRenameUserStatus {
*
* @return bool
*/
public function setStatuses( array $rows ) {
$dbw = $this->getDB( DB_PRIMARY );
public function setStatuses( array $rows ): bool {
$dbw = $this->databaseManager->getCentralPrimaryDB();
$dbw->startAtomic( __METHOD__ );
if ( $dbw->getType() === 'mysql' ) {
@ -213,8 +208,8 @@ class GlobalRenameUserStatus {
*
* @param string $wiki
*/
public function done( $wiki ) {
$dbw = $this->getDB( DB_PRIMARY );
public function done( string $wiki ): void {
$dbw = $this->databaseManager->getCentralPrimaryDB();
$fname = __METHOD__;
$dbw->onTransactionPreCommitOrIdle(
@ -235,7 +230,7 @@ class GlobalRenameUserStatus {
* @param Authority $performer User viewing the list, for permissions checks
* @return string[] old username => new username
*/
public static function getInProgressRenames( Authority $performer ) {
public static function getInProgressRenames( Authority $performer ): array {
$dbr = CentralAuthServices::getDatabaseManager()->getCentralReplicaDB();
$qb = $dbr->newSelectQueryBuilder();

查看文件

@ -47,7 +47,10 @@ abstract class LocalRenameJob extends Job {
* @throws Exception
*/
public function run(): bool {
$this->setRenameUserStatus( new GlobalRenameUserStatus( $this->params['to'] ) );
$this->setRenameUserStatus(
CentralAuthServices::getGlobalRenameFactory()
->newGlobalRenameUserStatus( $this->params['to'] )
);
// Bail if it's already done or in progress. Use a locking read to block until the
// transaction adding this job is done, so we can see its changes. This is similar to

查看文件

@ -14,7 +14,7 @@ use MediaWiki\Block\Restriction\PageRestriction;
use MediaWiki\CommentFormatter\CommentFormatter;
use MediaWiki\Extension\CentralAuth\CentralAuthDatabaseManager;
use MediaWiki\Extension\CentralAuth\CentralAuthUIService;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameUserStatus;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameFactory;
use MediaWiki\Extension\CentralAuth\User\CentralAuthGlobalRegistrationProvider;
use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
use MediaWiki\Extension\CentralAuth\Widget\HTMLGlobalUserTextField;
@ -84,6 +84,7 @@ class SpecialCentralAuth extends SpecialPage {
private UserRegistrationLookup $userRegistrationLookup;
private CentralAuthDatabaseManager $databaseManager;
private CentralAuthUIService $uiService;
private GlobalRenameFactory $globalRenameFactory;
/**
* @param CommentFormatter $commentFormatter
@ -95,6 +96,7 @@ class SpecialCentralAuth extends SpecialPage {
* @param UserRegistrationLookup $userRegistrationLookup
* @param CentralAuthDatabaseManager $databaseManager
* @param CentralAuthUIService $uiService
* @param GlobalRenameFactory $globalRenameFactory
*/
public function __construct(
CommentFormatter $commentFormatter,
@ -105,7 +107,8 @@ class SpecialCentralAuth extends SpecialPage {
UserNameUtils $userNameUtils,
UserRegistrationLookup $userRegistrationLookup,
CentralAuthDatabaseManager $databaseManager,
CentralAuthUIService $uiService
CentralAuthUIService $uiService,
GlobalRenameFactory $globalRenameFactory
) {
parent::__construct( 'CentralAuth' );
$this->commentFormatter = $commentFormatter;
@ -117,6 +120,7 @@ class SpecialCentralAuth extends SpecialPage {
$this->userRegistrationLookup = $userRegistrationLookup;
$this->databaseManager = $databaseManager;
$this->uiService = $uiService;
$this->globalRenameFactory = $globalRenameFactory;
}
public function doesWrites() {
@ -263,7 +267,7 @@ class SpecialCentralAuth extends SpecialPage {
private function showRenameInProgressError() {
$this->showError( 'centralauth-admin-rename-in-progress', $this->mUserName );
$renameStatus = new GlobalRenameUserStatus( $this->mUserName );
$renameStatus = $this->globalRenameFactory->newGlobalRenameUserStatus( $this->mUserName );
$names = $renameStatus->getNames();
$this->uiService->showRenameLogExtract( $this->getContext(), $names[1] );
}

查看文件

@ -4,6 +4,7 @@ namespace MediaWiki\Extension\CentralAuth\Special;
use HTMLForm;
use MediaWiki\Extension\CentralAuth\CentralAuthUIService;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameFactory;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameUserStatus;
use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
use MediaWiki\Html\Html;
@ -20,16 +21,22 @@ class SpecialGlobalRenameProgress extends FormSpecialPage {
/** @var CentralAuthUIService */
private $uiService;
private GlobalRenameFactory $globalRenameFactory;
/**
* @var GlobalRenameUserStatus
*/
private $renameuserStatus;
public function __construct( UserNameUtils $userNameUtils, CentralAuthUIService $uiService ) {
public function __construct(
UserNameUtils $userNameUtils,
CentralAuthUIService $uiService,
GlobalRenameFactory $globalRenameFactory
) {
parent::__construct( 'GlobalRenameProgress' );
$this->userNameUtils = $userNameUtils;
$this->uiService = $uiService;
$this->globalRenameFactory = $globalRenameFactory;
}
/** @inheritDoc */
@ -104,7 +111,7 @@ class SpecialGlobalRenameProgress extends FormSpecialPage {
$out = $this->getOutput();
$out->addBacklinkSubtitle( $this->getPageTitle() );
$this->renameuserStatus = new GlobalRenameUserStatus( $name );
$this->renameuserStatus = $this->globalRenameFactory->newGlobalRenameUserStatus( $name );
$names = $this->renameuserStatus->getNames();
if ( !$names ) {
$this->checkCachePurge( $name );

查看文件

@ -36,7 +36,6 @@ use MediaWiki\DAO\WikiAwareEntity;
use MediaWiki\Deferred\DeferredUpdates;
use MediaWiki\Extension\CentralAuth\CentralAuthReadOnlyError;
use MediaWiki\Extension\CentralAuth\CentralAuthServices;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameUserStatus;
use MediaWiki\Extension\CentralAuth\LocalUserNotFoundException;
use MediaWiki\Extension\CentralAuth\RCFeed\CARCFeedFormatter;
use MediaWiki\Extension\CentralAuth\WikiSet;
@ -561,8 +560,12 @@ class CentralAuthUser implements IDBAccessObject {
$queryInfo['joinConds']
);
$renameUserStatus = new GlobalRenameUserStatus( $this->mName );
$renameUser = $renameUserStatus->getNames( null, $fromPrimary ? 'primary' : 'replica' );
$renameUser = CentralAuthServices::getGlobalRenameFactory()
->newGlobalRenameUserStatus( $this->mName )
->getNames(
null,
$fromPrimary ? IDBAccessObject::READ_LATEST : IDBAccessObject::READ_NORMAL
);
$this->loadFromRow( $row, $renameUser, $fromPrimary );
}
@ -2531,19 +2534,16 @@ class CentralAuthUser implements IDBAccessObject {
* Not cached
* @see CentralAuthUser::renameInProgress
* @param string $wiki
* @param int $flags Bitfield of IDBAccessObject::READ_* constants
* @param int $recency Bitfield of IDBAccessObject::READ_* constants
* @return string[]|false
*/
public function renameInProgressOn( $wiki, $flags = 0 ) {
$renameState = new GlobalRenameUserStatus( $this->mName );
// Use primary database as this is being used for various critical things
$names = $renameState->getNames(
$wiki,
( $flags & IDBAccessObject::READ_LATEST ) == IDBAccessObject::READ_LATEST ? 'primary' : 'replica'
);
return $names ?: false;
public function renameInProgressOn( string $wiki, int $recency = IDBAccessObject::READ_NORMAL ) {
return CentralAuthServices::getGlobalRenameFactory()
->newGlobalRenameUserStatus( $this->mName )
->getNames(
$wiki,
$recency
) ?: false;
}
/**

查看文件

@ -1,7 +1,6 @@
<?php
use MediaWiki\Extension\CentralAuth\CentralAuthServices;
use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameUserStatus;
use MediaWiki\Extension\CentralAuth\GlobalRename\LocalRenameJob\LocalRenameUserJob;
use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
use MediaWiki\Extension\CentralAuth\UsersToRename\UsersToRenameDatabaseUpdates;
@ -121,13 +120,14 @@ class ForceRenameUsers extends Maintenance {
}
$this->log( "Renaming $name to {$newCAUser->getName()}." );
$statuses = new GlobalRenameUserStatus( $name );
$success = $statuses->setStatuses( [ [
'ru_wiki' => $wiki,
'ru_oldname' => $name,
'ru_newname' => $newCAUser->getName(),
'ru_status' => 'queued'
] ] );
$success = CentralAuthServices::getGlobalRenameFactory( $services )
->newGlobalRenameUserStatus( $name )
->setStatuses( [ [
'ru_wiki' => $wiki,
'ru_oldname' => $name,
'ru_newname' => $newCAUser->getName(),
'ru_status' => 'queued'
] ] );
if ( !$success ) {
$this->log( "WARNING: Race condition, renameuser_status already set for " .