43 private $forceGlobalDetach =
false;
45 private $movePages =
true;
47 private $suppressRedirect =
false;
49 private $derived =
false;
58 private LoggerInterface $logger;
67 private array $localDatabases;
110 $this->centralIdLookupFactory = $centralIdLookupFactory;
111 $this->movePageFactory = $movePageFactory;
112 $this->jobQueueGroupFactory = $jobQueueGroupFactory;
113 $this->userFactory = $userFactory;
114 $this->userNameUtils = $userNameUtils;
115 $this->permissionManager = $permissionManager;
116 $this->titleFactory = $titleFactory;
117 $this->logger = LoggerFactory::getInstance(
'RenameUser' );
124 ] as $possibleOption ) {
125 if ( isset( $renameOptions[ $possibleOption ] ) ) {
126 $this->$possibleOption = $renameOptions[ $possibleOption ];
130 $this->performer = $performer;
131 $this->target = $target;
132 $this->oldName = $oldName;
133 $this->newName = $newName;
134 $this->reason = $reason;
144 private function check():
Status {
148 $expectedName = $this->oldName;
149 if ( $this->derived && $this->userFactory->isUserTableShared() ) {
150 $expectedName = $this->newName;
152 if ( $this->target->getName() !== $expectedName ) {
153 return Status::newFatal(
'renameuser-error-unexpected-name' );
157 $newRigor = $this->derived ? UserFactory::RIGOR_NONE : UserFactory::RIGOR_CREATABLE;
158 $oldUser = $this->userFactory->newFromName( $this->oldName, UserFactory::RIGOR_NONE );
159 $newUser = $this->userFactory->newFromName( $this->newName, $newRigor );
161 return Status::newFatal(
'renameusererrorinvalid', $this->oldName );
164 return Status::newFatal(
'renameusererrorinvalid', $this->newName );
166 $currentUser = $this->derived ? $newUser : $oldUser;
167 if ( !$currentUser->isRegistered() ) {
168 return Status::newFatal(
'renameusererrordoesnotexist', $currentUser->getName() );
170 if ( !$this->derived && $newUser->isRegistered() ) {
171 return Status::newFatal(
'renameusererrorexists', $this->newName );
175 if ( $this->userNameUtils->isTemp( $this->oldName ) ) {
176 return Status::newFatal(
'renameuser-error-temp-user', $this->oldName );
179 $this->userNameUtils->isTemp( $this->newName ) ||
180 $this->userNameUtils->isTempReserved( $this->newName )
182 return Status::newFatal(
'renameuser-error-temp-user-reserved', $this->newName );
186 $centralIdLookup = $this->centralIdLookupFactory->getNonLocalLookup();
187 $userCentralAttached = $centralIdLookup && $centralIdLookup->isAttached( $this->target );
188 if ( !$this->forceGlobalDetach && $userCentralAttached ) {
189 return Status::newFatal(
'renameuser-error-global-detaching' );
192 return Status::newGood();
200 $status = $this->check();
201 if ( !$status->isOK() ) {
205 $user = $this->target;
206 $performer = $this->performer;
207 $oldName = $this->oldName;
208 $newName = $this->newName;
211 'reason' => $this->reason,
212 'derived' => $this->derived,
223 $status->merge( $rename->renameUser() );
224 if ( !$status->isOK() ) {
229 if ( $performer->getId() === $user->getId() ) {
230 $performer->setName( $newName );
231 $this->performer->setName( $newName );
235 $status->merge( $this->moveUserPages() );
245 if ( $this->movePages && $this->permissionManager->userHasRight( $this->performer,
'move' ) ) {
246 $suppressRedirect = $this->suppressRedirect
247 && $this->permissionManager->userHasRight( $this->performer,
'suppressredirect' );
248 $oldTitle = $this->titleFactory->makeTitle(
NS_USER, $this->oldName );
249 $newTitle = $this->titleFactory->makeTitle(
NS_USER, $this->newName );
251 $status = $this->movePagesAndSubPages( $this->performer, $oldTitle, $newTitle, $suppressRedirect );
252 if ( !$status->isOK() ) {
256 $oldTalkTitle = $oldTitle->getTalkPageIfDefined();
257 $newTalkTitle = $newTitle->getTalkPageIfDefined();
258 if ( $oldTalkTitle && $newTalkTitle ) {
259 $status = $this->movePagesAndSubPages(
265 if ( !$status->isOK() ) {
270 return Status::newGood();
273 private function movePagesAndSubPages(
274 User $performer, Title $oldTitle, Title $newTitle,
bool $suppressRedirect
276 $status = Status::newGood();
278 $movePage = $this->movePageFactory->newMovePage(
282 $movePage->setMaximumMovedPages( -1 );
283 $logMessage = RequestContext::getMain()->msg(
284 'renameuser-move-log',
285 $oldTitle->getText(),
287 )->inContentLanguage()->text();
289 if ( $oldTitle->exists() ) {
290 $status->merge( $movePage->moveIfAllowed( $performer, $logMessage, !$suppressRedirect ) );
291 if ( !$status->isGood() ) {
296 $batchStatus = $movePage->moveSubpagesIfAllowed( $performer, $logMessage, !$suppressRedirect );
297 foreach ( $batchStatus->getValue() as $titleText => $moveStatus ) {
298 $status->merge( $moveStatus );
314 if ( $this->derived ) {
315 throw new LogicException(
"Can't rename globally with a command created with newDerivedRenameUser()" );
317 $status = $this->renameLocal();
318 if ( !$status->isGood() ) {
323 if ( $this->userFactory->isUserTableShared() ) {
324 foreach ( $this->localDatabases as $database ) {
325 if ( $database == WikiMap::getCurrentWikiDbDomain()->getId() ) {
328 $status->merge( $this->enqueueRemoteRename( $database ) );
343 private function enqueueRemoteRename(
string $database ): Status {
345 'oldname' => $this->oldName,
346 'newname' => $this->newName,
347 'uid' => $this->target->getId(),
348 'performer' => $this->performer->getId(),
349 'reason' => $this->reason,
350 'movePages' => $this->movePages,
351 'suppressRedirect' => $this->suppressRedirect,
353 $oldTitle = $this->titleFactory->makeTitle(
NS_USER, $this->oldName );
354 $this->logger->info(
"Enqueuing a rename job for domain {$database}" );
355 $job =
new JobSpecification(
'renameUserDerived', $jobParams, [], $oldTitle );
356 $this->jobQueueGroupFactory->makeJobQueueGroup( $database )->push(
$job );
357 return Status::newGood();
370 if ( !$this->derived && $this->userFactory->isUserTableShared() ) {
371 return $this->renameGlobal();
373 return $this->renameLocal();
387 if ( !$this->permissionManager->userHasRight( $this->performer,
'renameuser' ) ) {
388 return Status::newFatal(
'badaccess-groups',
'renameuser' );
392 $centralIdLookup = $this->centralIdLookupFactory->getNonLocalLookup();
393 $userCentralAttached = $centralIdLookup && $centralIdLookup->isAttached( $this->target );
394 if ( ( $this->userFactory->isUserTableShared() || $userCentralAttached )
395 && !$this->permissionManager->userHasRight( $this->performer,
'renameuser-global' ) ) {
396 return Status::newFatal(
'badaccess-groups',
'renameuser-global' );
399 return $this->renameUnsafe();