Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 91 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
RenameUser | |
0.00% |
0 / 88 |
|
0.00% |
0 / 4 |
462 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
initServices | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 50 |
|
0.00% |
0 / 1 |
210 | |||
movePageAndSubpages | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
30 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @ingroup Maintenance |
19 | * @author Martin Urbanec <martin.urbanec@wikimedia.cz> |
20 | */ |
21 | |
22 | require_once __DIR__ . '/Maintenance.php'; |
23 | |
24 | use MediaWiki\Page\MovePageFactory; |
25 | use MediaWiki\RenameUser\RenameuserSQL; |
26 | use MediaWiki\Title\Title; |
27 | use MediaWiki\User\CentralId\CentralIdLookup; |
28 | use MediaWiki\User\User; |
29 | use MediaWiki\User\UserFactory; |
30 | |
31 | class RenameUser extends Maintenance { |
32 | /** @var UserFactory */ |
33 | private $userFactory; |
34 | |
35 | /** @var CentralIdLookup|null */ |
36 | private $centralLookup; |
37 | |
38 | /** @var MovePageFactory */ |
39 | private $movePageFactory; |
40 | |
41 | public function __construct() { |
42 | parent::__construct(); |
43 | |
44 | $this->addDescription( 'Rename a user' ); |
45 | $this->addArg( 'old-name', 'Current username of the to-be-renamed user' ); |
46 | $this->addArg( 'new-name', 'New username of the to-be-renamed user' ); |
47 | $this->addOption( 'performer', 'Performer of the rename action', false, true ); |
48 | $this->addOption( 'reason', 'Reason of the rename', false, true ); |
49 | $this->addOption( 'force-global-detach', |
50 | 'Rename the local user even if it is attached to a global account' ); |
51 | $this->addOption( 'suppress-redirect', 'Don\'t create redirects when moving pages' ); |
52 | $this->addOption( 'skip-page-moves', 'Don\'t move associated user pages' ); |
53 | } |
54 | |
55 | private function initServices() { |
56 | $services = $this->getServiceContainer(); |
57 | $this->userFactory = $services->getUserFactory(); |
58 | $this->centralLookup = $services->getCentralIdLookupFactory()->getNonLocalLookup(); |
59 | $this->movePageFactory = $services->getMovePageFactory(); |
60 | } |
61 | |
62 | public function execute() { |
63 | $this->initServices(); |
64 | |
65 | $oldName = $this->getArg( 'old-name' ); |
66 | $newName = $this->getArg( 'new-name' ); |
67 | |
68 | $oldUser = $this->userFactory->newFromName( $oldName ); |
69 | if ( !$oldUser ) { |
70 | $this->fatalError( 'The specified old username is invalid' ); |
71 | } |
72 | |
73 | if ( !$oldUser->isRegistered() ) { |
74 | $this->fatalError( 'The user does not exist' ); |
75 | } |
76 | |
77 | if ( !$this->getOption( 'force-global-detach' ) |
78 | && $this->centralLookup |
79 | && $this->centralLookup->isAttached( $oldUser ) |
80 | ) { |
81 | $this->fatalError( 'The user is globally attached. Use CentralAuth to rename this account.' ); |
82 | } |
83 | |
84 | $newUser = $this->userFactory->newFromName( $newName, UserFactory::RIGOR_CREATABLE ); |
85 | if ( !$newUser ) { |
86 | $this->fatalError( 'The specified new username is invalid' ); |
87 | } elseif ( $newUser->isRegistered() ) { |
88 | $this->fatalError( 'New username must be free' ); |
89 | } |
90 | |
91 | if ( $this->getOption( 'performer' ) === null ) { |
92 | $performer = User::newSystemUser( User::MAINTENANCE_SCRIPT_USER, [ 'steal' => true ] ); |
93 | } else { |
94 | $performer = $this->userFactory->newFromName( $this->getOption( 'performer' ) ); |
95 | } |
96 | |
97 | if ( !( $performer instanceof User ) || !$performer->isRegistered() ) { |
98 | $this->fatalError( 'Performer does not exist.' ); |
99 | } |
100 | |
101 | $renamer = new RenameuserSQL( |
102 | $oldUser->getName(), |
103 | $newUser->getName(), |
104 | $oldUser->getId(), |
105 | $performer, |
106 | [ |
107 | 'reason' => $this->getOption( 'reason' ) |
108 | ] |
109 | ); |
110 | |
111 | if ( !$renamer->rename() ) { |
112 | $this->fatalError( 'Renaming failed.' ); |
113 | } else { |
114 | $this->output( "{$oldUser->getName()} was successfully renamed to {$newUser->getName()}.\n" ); |
115 | } |
116 | |
117 | $numRenames = 0; |
118 | if ( !$this->getOption( 'skip-page-moves' ) ) { |
119 | $numRenames += $this->movePageAndSubpages( |
120 | $performer, |
121 | $oldUser->getUserPage(), |
122 | $newUser->getUserPage(), |
123 | 'user' |
124 | ); |
125 | $numRenames += $this->movePageAndSubpages( |
126 | $performer, |
127 | $oldUser->getTalkPage(), |
128 | $newUser->getTalkPage(), |
129 | 'user talk', |
130 | ); |
131 | } |
132 | if ( $numRenames > 0 ) { |
133 | $this->output( "$numRenames user page(s) renamed\n" ); |
134 | } |
135 | } |
136 | |
137 | private function movePageAndSubpages( User $performer, Title $oldTitle, Title $newTitle, $kind ) { |
138 | $movePage = $this->movePageFactory->newMovePage( |
139 | $oldTitle, |
140 | $newTitle, |
141 | ); |
142 | $movePage->setMaximumMovedPages( -1 ); |
143 | $logMessage = wfMessage( |
144 | 'renameuser-move-log', $oldTitle->getText(), $newTitle->getText() |
145 | )->inContentLanguage()->text(); |
146 | $createRedirect = !$this->getOption( 'suppress-redirect' ); |
147 | |
148 | $numRenames = 0; |
149 | if ( $oldTitle->exists() ) { |
150 | $status = $movePage->move( $performer, $logMessage, $createRedirect ); |
151 | if ( $status->isGood() ) { |
152 | $numRenames++; |
153 | } else { |
154 | $this->output( "Failed to rename $kind page: " . |
155 | $status->getWikiText( false, false, 'en' ) . |
156 | "\n" ); |
157 | } |
158 | } |
159 | |
160 | $batchStatus = $movePage->moveSubpages( $performer, $logMessage, $createRedirect ); |
161 | foreach ( $batchStatus->getValue() as $titleText => $status ) { |
162 | if ( $status->isGood() ) { |
163 | $numRenames++; |
164 | } else { |
165 | $this->output( "Failed to rename $kind subpage \"$titleText\": " . |
166 | $status->getWikiText( false, false, 'en' ) . "\n" ); |
167 | } |
168 | } |
169 | return $numRenames; |
170 | } |
171 | } |
172 | |
173 | $maintClass = RenameUser::class; |
174 | require_once RUN_MAINTENANCE_IF_MAIN; |