Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
MigrateInitialAccounts
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 2
20
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace MediaWiki\Extension\CentralAuth\Maintenance;
4
5use Maintenance;
6use MWCryptRand;
7
8class MigrateInitialAccounts extends Maintenance {
9
10    public function __construct() {
11        parent::__construct();
12        $this->requireExtension( 'CentralAuth' );
13        $this->addDescription( "Globalize all user accounts, assuming all default config options.\n" .
14            "This script is intended to only be used during MediaWiki installation." );
15    }
16
17    public function execute() {
18        if ( !defined( 'MEDIAWIKI_INSTALL' ) ) {
19            $this->fatalError( "This script is intended to only be used during MediaWiki installation." );
20        }
21
22        // Assume that CentralAuth database is the same as the local wiki's database.
23        $dbw = $this->getPrimaryDB();
24
25        // Assume that no global users exist, and all local users can be migrated.
26        // Assume that there are very few users, so we don't need batching.
27        $users = $dbw->newSelectQueryBuilder()
28            ->from( 'user' )
29            ->select( [
30                'user_id',
31                'user_email',
32                'user_name',
33                'user_email_authenticated',
34                'user_password',
35                'user_registration',
36            ] )
37            ->caller( __METHOD__ )
38            ->fetchResultSet();
39
40        // We're in the installer, so none of the CentralAuth code except for this script is loaded,
41        // therefore we can't rely on any of our services or default values of config options.
42        // Migrate the users manually using custom database queries.
43
44        foreach ( $users as $user ) {
45            $dbw->doAtomicSection( __METHOD__, static function ( $dbw, $fname ) use ( $user ) {
46                global $wgDBname;
47
48                // Unlike migratePass0/1, we don't need to store anything into globalnames and localnames,
49                // these tables are only used for incomplete migrations and we're doing a complete one.
50
51                // See CentralAuthUser::storeGlobalData()
52                $dbw->newInsertQueryBuilder()
53                    ->insertInto( 'globaluser' )
54                    ->row( [
55                        'gu_name' => $user->user_name,
56                        'gu_home_db' => $wgDBname,
57                        'gu_email' => $user->user_email,
58                        'gu_email_authenticated' => $user->user_email_authenticated,
59                        'gu_password' => $user->user_password,
60                        'gu_locked' => 0,
61                        'gu_hidden_level' => 0,
62                        'gu_registration' => $user->user_registration,
63                        'gu_auth_token' => MWCryptRand::generateHex( 32 ),
64                    ] )
65                    ->caller( $fname )
66                    ->execute();
67                $gu_id = $dbw->insertId();
68
69                // See CentralAuthUser::attach()
70                $dbw->newInsertQueryBuilder()
71                    ->insertInto( 'localuser' )
72                    ->row( [
73                        'lu_wiki' => $wgDBname,
74                        'lu_name' => $user->user_name,
75                        'lu_attached_timestamp' => $user->user_registration,
76                        'lu_attached_method' => 'new',
77                        'lu_local_id' => $user->user_id,
78                        'lu_global_id' => $gu_id,
79                    ] )
80                    ->caller( $fname )
81                    ->execute();
82
83                // We don't handle AntiSpoof integration here, because it's complicated, and the
84                // AntiSpoof extension doesn't handle the initial accounts either.
85            } );
86        }
87
88        $count = count( $users );
89        $this->output( "Globalized $count accounts\n" );
90        return true;
91    }
92}