44 private $forceGlobalDetach =
false;
46 private $movePages =
true;
48 private $suppressRedirect =
false;
50 private $derived =
false;
52 private readonly LoggerInterface $logger;
86 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
87 $this->logger = LoggerFactory::getInstance(
'RenameUser' );
94 ] as $possibleOption ) {
95 if ( isset( $renameOptions[ $possibleOption ] ) ) {
96 $this->$possibleOption = $renameOptions[ $possibleOption ];
100 $this->performer = $performer;
101 $this->target = $target;
102 $this->oldName = $oldName;
103 $this->newName = $newName;
104 $this->reason = $reason;
114 private function check():
Status {
118 $expectedName = $this->oldName;
119 if ( $this->derived && $this->userFactory->isUserTableShared() ) {
120 $expectedName = $this->newName;
122 if ( $this->target->getName() !== $expectedName ) {
123 return Status::newFatal(
'renameuser-error-unexpected-name' );
127 $newRigor = $this->derived ? UserFactory::RIGOR_NONE : UserFactory::RIGOR_CREATABLE;
128 $oldUser = $this->userFactory->newFromName( $this->oldName, UserFactory::RIGOR_NONE );
129 $newUser = $this->userFactory->newFromName( $this->newName, $newRigor );
131 return Status::newFatal(
'renameusererrorinvalid', $this->oldName );
134 return Status::newFatal(
'renameusererrorinvalid', $this->newName );
136 $currentUser = $this->derived ? $newUser : $oldUser;
137 if ( !$currentUser->isRegistered() ) {
138 return Status::newFatal(
'renameusererrordoesnotexist', $currentUser->getName() );
140 if ( !$this->derived && $newUser->isRegistered() ) {
141 return Status::newFatal(
'renameusererrorexists', $this->newName );
145 if ( $this->userNameUtils->isTemp( $this->oldName ) ) {
146 return Status::newFatal(
'renameuser-error-temp-user', $this->oldName );
149 $this->userNameUtils->isTemp( $this->newName ) ||
150 $this->userNameUtils->isTempReserved( $this->newName )
152 return Status::newFatal(
'renameuser-error-temp-user-reserved', $this->newName );
156 $centralIdLookup = $this->centralIdLookupFactory->getNonLocalLookup();
157 $userCentralAttached = $centralIdLookup && $centralIdLookup->isAttached( $this->target );
158 if ( !$this->forceGlobalDetach && $userCentralAttached ) {
159 return Status::newFatal(
'renameuser-error-global-detaching' );
162 return Status::newGood();
170 $status = $this->check();
171 if ( !$status->isOK() ) {
175 $user = $this->target;
176 $performer = $this->performer;
177 $oldName = $this->oldName;
178 $newName = $this->newName;
181 'reason' => $this->reason,
182 'derived' => $this->derived,
193 $status->merge( $rename->renameUser() );
194 if ( !$status->isOK() ) {
199 if ( $performer->getId() === $user->getId() ) {
200 $performer->setName( $newName );
201 $this->performer->setName( $newName );
205 $status->merge( $this->moveUserPages() );
215 if ( $this->movePages && $this->permissionManager->userHasRight( $this->performer,
'move' ) ) {
216 $suppressRedirect = $this->suppressRedirect
217 && $this->permissionManager->userHasRight( $this->performer,
'suppressredirect' );
218 $oldTitle = $this->titleFactory->makeTitle(
NS_USER, $this->oldName );
219 $newTitle = $this->titleFactory->makeTitle(
NS_USER, $this->newName );
221 $status = $this->movePagesAndSubPages( $this->performer, $oldTitle, $newTitle, $suppressRedirect );
222 if ( !$status->isOK() ) {
226 $oldTalkTitle = $oldTitle->getTalkPageIfDefined();
227 $newTalkTitle = $newTitle->getTalkPageIfDefined();
228 if ( $oldTalkTitle && $newTalkTitle ) {
229 $status = $this->movePagesAndSubPages(
235 if ( !$status->isOK() ) {
240 return Status::newGood();
243 private function movePagesAndSubPages(
244 User $performer, Title $oldTitle, Title $newTitle,
bool $suppressRedirect
246 $status = Status::newGood();
248 $movePage = $this->movePageFactory->newMovePage(
252 $movePage->setMaximumMovedPages( -1 );
253 $logMessage = RequestContext::getMain()->msg(
254 'renameuser-move-log',
255 $oldTitle->getText(),
257 )->inContentLanguage()->text();
259 if ( $oldTitle->exists() ) {
260 $status->merge( $movePage->moveIfAllowed( $performer, $logMessage, !$suppressRedirect ) );
261 if ( !$status->isGood() ) {
266 $batchStatus = $movePage->moveSubpagesIfAllowed( $performer, $logMessage, !$suppressRedirect );
267 foreach ( $batchStatus->getValue() as $titleText => $moveStatus ) {
268 $status->merge( $moveStatus );
284 if ( $this->derived ) {
285 throw new LogicException(
"Can't rename globally with a command created with newDerivedRenameUser()" );
287 $status = $this->renameLocal();
288 if ( !$status->isGood() ) {
293 if ( $this->userFactory->isUserTableShared() ) {
294 foreach ( $this->options->get( MainConfigNames::LocalDatabases ) as $database ) {
295 if ( $database == WikiMap::getCurrentWikiDbDomain()->getId() ) {
298 $status->merge( $this->enqueueRemoteRename( $database ) );
313 private function enqueueRemoteRename(
string $database ): Status {
315 'oldname' => $this->oldName,
316 'newname' => $this->newName,
317 'uid' => $this->target->getId(),
318 'performer' => $this->performer->getId(),
319 'reason' => $this->reason,
320 'movePages' => $this->movePages,
321 'suppressRedirect' => $this->suppressRedirect,
323 $oldTitle = $this->titleFactory->makeTitle(
NS_USER, $this->oldName );
324 $this->logger->info(
"Enqueuing a rename job for domain {$database}" );
325 $job =
new JobSpecification(
'renameUserDerived', $jobParams, [], $oldTitle );
326 $this->jobQueueGroupFactory->makeJobQueueGroup( $database )->push(
$job );
327 return Status::newGood();
340 if ( !$this->derived && $this->userFactory->isUserTableShared() ) {
341 return $this->renameGlobal();
343 return $this->renameLocal();
357 if ( !$this->permissionManager->userHasRight( $this->performer,
'renameuser' ) ) {
358 return Status::newFatal(
'renameuser-error-local-rights' );
362 $centralIdLookup = $this->centralIdLookupFactory->getNonLocalLookup();
363 $userCentralAttached = $centralIdLookup && $centralIdLookup->isAttached( $this->target );
364 if ( ( $this->userFactory->isUserTableShared() || $userCentralAttached )
365 && !$this->permissionManager->userHasRight( $this->performer,
'renameuser-global' ) ) {
366 return Status::newFatal(
'renameuser-error-global-rights' );
369 return $this->renameUnsafe();