141 $this->hookRunner =
new HookRunner( $services->getHookContainer() );
142 $this->dbProvider = $services->getConnectionProvider();
143 $this->userFactory = $services->getUserFactory();
144 $this->jobQueueGroup = $services->getJobQueueGroup();
145 $this->titleFactory = $services->getTitleFactory();
146 $this->logger = LoggerFactory::getInstance(
'Renameuser' );
148 $config = $services->getMainConfig();
154 $this->renamer = $renamer;
155 $this->checkIfUserExists =
true;
157 if ( isset( $options[
'checkIfUserExists'] ) ) {
158 $this->checkIfUserExists = $options[
'checkIfUserExists'];
161 if ( isset( $options[
'debugPrefix'] ) ) {
162 $this->debugPrefix = $options[
'debugPrefix'];
165 if ( isset( $options[
'reason'] ) ) {
166 $this->reason = $options[
'reason'];
169 if ( isset( $options[
'derived'] ) ) {
170 $this->derived = $options[
'derived'];
174 $this->tablesJob = [];
176 $this->hookRunner->onRenameUserSQL( $this );
201 $dbw = $this->dbProvider->getPrimaryDatabase();
202 $atomicId = $dbw->startAtomic( __METHOD__, $dbw::ATOMIC_CANCELABLE );
204 $this->hookRunner->onRenameUserPreRename( $this->uid, $this->old, $this->
new );
207 if ( $this->checkIfUserExists ) {
210 $userRenamed = $this->derived && self::isTableShared(
'user' );
211 $currentName = $userRenamed ? $this->new :
$this->old;
212 if ( !$this->lockUserAndGetId( $currentName ) ) {
213 $this->
debug(
"User $currentName does not exist, bailing out" );
214 $dbw->cancelAtomic( __METHOD__, $atomicId );
216 return Status::newFatal(
'renameusererrordoesnotexist', $this->
new );
221 $contribs = $this->userFactory->newFromId( $this->uid )->getEditCount();
225 $this->
debug(
"Starting rename of {$this->old} to {$this->new}" );
226 if ( !$this->derived ) {
227 $this->
debug(
"Rename of {$this->old} to {$this->new} will update shared tables" );
229 if ( $this->shouldUpdate(
'user' ) ) {
230 $this->
debug(
"Updating user table for {$this->old} to {$this->new}" );
231 $dbw->newUpdateQueryBuilder()
233 ->set( [
'user_name' => $this->
new,
'user_touched' => $dbw->timestamp() ] )
234 ->where( [
'user_name' => $this->old,
'user_id' => $this->uid ] )
235 ->caller( __METHOD__ )->execute();
237 $this->
debug(
"Skipping user table for rename from {$this->old} to {$this->new}" );
239 if ( $this->shouldUpdate(
'actor' ) ) {
240 $this->
debug(
"Updating actor table for {$this->old} to {$this->new}" );
241 $dbw->newUpdateQueryBuilder()
243 ->set( [
'actor_name' => $this->
new ] )
244 ->where( [
'actor_name' => $this->old,
'actor_user' => $this->uid ] )
245 ->caller( __METHOD__ )->execute();
247 $this->
debug(
"Skipping actor table for rename from {$this->old} to {$this->new}" );
251 if ( $this->renamer->getId() === $this->uid ) {
252 $this->renamer->setName( $this->
new );
257 $user = $this->userFactory->newFromId( $this->uid );
259 $user->load( IDBAccessObject::READ_LATEST );
260 SessionManager::singleton()->invalidateSessionsForUser( $user );
263 $user->invalidateCache();
266 if ( $this->shouldUpdate(
'block_target' ) ) {
267 $this->
debug(
"Updating block_target table for {$this->old} to {$this->new}" );
268 $dbw->newUpdateQueryBuilder()
269 ->update(
'block_target' )
270 ->set( [
'bt_user_text' => $this->
new ] )
271 ->where( [
'bt_user' => $this->uid,
'bt_user_text' => $this->old ] )
272 ->caller( __METHOD__ )->execute();
274 $this->
debug(
"Skipping block_target table for rename from {$this->old} to {$this->new}" );
280 $oldTitle = $this->titleFactory->makeTitle(
NS_USER, $this->old );
281 $newTitle = $this->titleFactory->makeTitle(
NS_USER, $this->
new );
286 if ( $this->shouldUpdate(
'logging' ) ) {
287 $this->
debug(
"Updating logging table for {$this->old} to {$this->new}" );
288 $dbw->newUpdateQueryBuilder()
289 ->update(
'logging' )
290 ->set( [
'log_title' => $newTitle->getDBkey() ] )
292 'log_type' => $logTypesOnUser,
294 'log_title' => $oldTitle->getDBkey()
296 ->caller( __METHOD__ )->execute();
298 $this->
debug(
"Skipping logging table for rename from {$this->old} to {$this->new}" );
301 if ( $this->shouldUpdate(
'recentchanges' ) ) {
302 $this->
debug(
"Updating recentchanges table for rename from {$this->old} to {$this->new}" );
303 $dbw->newUpdateQueryBuilder()
304 ->update(
'recentchanges' )
305 ->set( [
'rc_title' => $newTitle->getDBkey() ] )
308 'rc_log_type' => $logTypesOnUser,
310 'rc_title' => $oldTitle->getDBkey()
312 ->caller( __METHOD__ )->execute();
314 $this->
debug(
"Skipping recentchanges table for rename from {$this->old} to {$this->new}" );
318 foreach ( $this->tables as $table => $fieldSet ) {
319 [ $nameCol, $userCol ] = $fieldSet;
320 if ( $this->shouldUpdate( $table ) ) {
321 $this->
debug(
"Updating {$table} table for rename from {$this->old} to {$this->new}" );
322 $dbw->newUpdateQueryBuilder()
324 ->set( [ $nameCol => $this->
new ] )
325 ->where( [ $nameCol => $this->old, $userCol => $this->uid ] )
326 ->caller( __METHOD__ )->execute();
328 $this->
debug(
"Skipping {$table} table for rename from {$this->old} to {$this->new}" );
341 foreach ( $this->tablesJob as $table =>
$params ) {
342 if ( !$this->shouldUpdate( $table ) ) {
343 $this->
debug(
"Skipping {$table} table for rename from {$this->old} to {$this->new}" );
346 $this->
debug(
"Updating {$table} table for rename from {$this->old} to {$this->new}" );
352 $res = $dbw->newSelectQueryBuilder()
353 ->select( [ $timestampC ] )
355 ->where( [ $userTextC => $this->old, $userIDC => $this->uid ] )
356 ->orderBy( $timestampC, SelectQueryBuilder::SORT_ASC )
357 ->caller( __METHOD__ )->fetchResultSet();
360 $jobParams[
'table'] = $table;
361 $jobParams[
'column'] = $userTextC;
362 $jobParams[
'uidColumn'] = $userIDC;
363 $jobParams[
'timestampColumn'] = $timestampC;
368 $jobParams[
'minTimestamp'] =
'0';
369 $jobParams[
'maxTimestamp'] =
'0';
370 $jobParams[
'count'] = 0;
372 if ( isset(
$params[
'uniqueKey'] ) ) {
373 $jobParams[
'uniqueKey'] =
$params[
'uniqueKey'];
377 foreach ( $res as $row ) {
379 if ( $jobParams[
'count'] === 0 ) {
380 $jobParams[
'minTimestamp'] = $row->$timestampC;
384 $jobParams[
'maxTimestamp'] = $row->$timestampC;
386 $jobParams[
'count']++;
388 if ( $jobParams[
'count'] >= $this->updateRowsPerJob ) {
389 $jobs[] =
new JobSpecification(
'renameUserTable', $jobParams, [], $oldTitle );
390 $jobParams[
'minTimestamp'] =
'0';
391 $jobParams[
'maxTimestamp'] =
'0';
392 $jobParams[
'count'] = 0;
396 if ( $jobParams[
'count'] > 0 ) {
397 $jobs[] =
new JobSpecification(
'renameUserTable', $jobParams, [], $oldTitle );
403 $logEntry->setPerformer( $this->renamer );
404 $logEntry->setTarget( $oldTitle );
405 $logEntry->setComment( $this->reason );
406 $logEntry->setParameters( [
407 '4::olduser' => $this->old,
408 '5::newuser' => $this->
new,
409 '6::edits' => $contribs,
410 'derived' => $this->derived
412 $logid = $logEntry->insert();
417 $count = count( $jobs );
419 $this->jobQueueGroup->push( $jobs );
420 $this->
debug(
"Queued $count jobs for rename from {$this->old} to {$this->new}" );
424 $dbw->endAtomic( __METHOD__ );
427 $dbw->onTransactionCommitOrIdle(
428 function () use ( $dbw, $logEntry, $logid, $fname ) {
429 $dbw->startAtomic( $fname );
431 $user = $this->userFactory->newFromId( $this->uid );
432 $user->load( IDBAccessObject::READ_LATEST );
434 $user->saveSettings();
435 $this->hookRunner->onRenameUserComplete( $this->uid, $this->old, $this->
new );
437 $logEntry->publish( $logid );
438 $dbw->endAtomic( $fname );
443 $this->
debug(
"Finished rename from {$this->old} to {$this->new}" );
445 return Status::newGood();