Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 80
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
PopulateLocalAndGlobalIds
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 2
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 68
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2$IP = getenv( 'MW_INSTALL_PATH' );
3if ( $IP === false ) {
4    $IP = __DIR__ . '/../../..';
5}
6require_once "$IP/maintenance/Maintenance.php";
7
8use MediaWiki\Extension\CentralAuth\CentralAuthServices;
9use MediaWiki\WikiMap\WikiMap;
10use Wikimedia\Rdbms\SelectQueryBuilder;
11
12class PopulateLocalAndGlobalIds extends Maintenance {
13
14    public function __construct() {
15        parent::__construct();
16        $this->requireExtension( 'CentralAuth' );
17        $this->addDescription(
18            "Populate the localuser.lu_local_id and localuser.lu_global_id fields"
19        );
20        $this->setBatchSize( 1000 );
21    }
22
23    public function execute() {
24        $databaseManager = CentralAuthServices::getDatabaseManager();
25        $dbr = $databaseManager->getCentralReplicaDB();
26        $dbw = $databaseManager->getCentralPrimaryDB();
27        $lastGlobalId = -1;
28
29        // Skip people in global rename queue
30        $wiki = WikiMap::getCurrentWikiId();
31        $globalRenames = $dbr->newSelectQueryBuilder()
32            ->select( 'ru_oldname' )
33            ->from( 'renameuser_status' )
34            ->caller( __METHOD__ )
35            ->fetchFieldValues();
36
37        $ldbr = $databaseManager->getLocalDB( DB_REPLICA, $wiki );
38
39        $this->output( "Populating fields for wiki $wiki... \n" );
40        do {
41            $rows = $dbr->newSelectQueryBuilder()
42                ->select( [ 'lu_name', 'gu_id' ] )
43                ->from( 'localuser' )
44                ->join( 'globaluser', null, 'gu_name = lu_name' )
45                ->where( [
46                    // Start from where we left off in last batch
47                    $dbr->expr( 'gu_id', '>=', $lastGlobalId ),
48                    'lu_wiki' => $wiki,
49                    // Only pick records not already populated
50                    'lu_local_id' => null
51                ] )
52                ->orderBy( 'gu_id', SelectQueryBuilder::SORT_ASC )
53                ->limit( $this->mBatchSize )
54                ->caller( __METHOD__ )
55                ->fetchResultSet();
56
57            $numRows = $rows->numRows();
58
59            $globalUidToLocalName = [];
60            foreach ( $rows as $row ) {
61                if ( in_array( $row->lu_name, $globalRenames ) ) {
62                    $this->output(
63                        "User " . $row->lu_name . " not migrated (pending rename)\n"
64                    );
65                    continue;
66                }
67                $globalUidToLocalName[$row->gu_id] = $row->lu_name;
68            }
69            if ( !$globalUidToLocalName ) {
70                continue;
71            }
72
73            $localNameToUid = [];
74            $localIds = $ldbr->newSelectQueryBuilder()
75                ->select( [ 'user_id', 'user_name' ] )
76                ->from( 'user' )
77                ->where( [ 'user_name' => array_values( $globalUidToLocalName ) ] )
78                ->caller( __METHOD__ )
79                ->fetchResultSet();
80
81            foreach ( $localIds as $lid ) {
82                $localNameToUid[$lid->user_name] = $lid->user_id;
83            }
84            $updated = 0;
85            foreach ( $globalUidToLocalName as $gid => $uname ) {
86                // Save progress so we know where to start our next batch
87                $lastGlobalId = $gid;
88                $dbw->newUpdateQueryBuilder()
89                    ->update( 'localuser' )
90                    ->set( [
91                        'lu_local_id' => $localNameToUid[$uname],
92                        'lu_global_id' => $gid
93                    ] )
94                    ->where( [ 'lu_name' => $uname, 'lu_wiki' => $wiki ] )
95                    ->caller( __METHOD__ )
96                    ->execute();
97                if ( !$dbw->affectedRows() ) {
98                    $this->output(
99                        "Update failed for global user $lastGlobalId for wiki $wiki \n"
100                    );
101                } else {
102                    // Count number of records actually updated
103                    $updated++;
104                }
105            }
106            $this->output(
107                "Updated $updated records. Last user: $lastGlobalId; Wiki: $wiki \n"
108            );
109            $databaseManager->waitForReplication();
110        } while ( $numRows >= $this->mBatchSize );
111        $this->output( "Completed $wiki \n" );
112    }
113
114}
115
116$maintClass = PopulateLocalAndGlobalIds::class;
117require_once RUN_MAINTENANCE_IF_MAIN;