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 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
MigrateInitialAccountsTask
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 4
42
0.00% covered (danger)
0.00%
0 / 1
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDescription
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDependencies
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace MediaWiki\Extension\CentralAuth;
4
5use MediaWiki\Status\Status;
6use MWCryptRand;
7
8class MigrateInitialAccountsTask extends \MediaWiki\Installer\Task\Task {
9
10    /**
11     * @return string
12     */
13    public function getName() {
14        return 'centralauth-migrate-accounts';
15    }
16
17    /**
18     * @return string
19     */
20    public function getDescription() {
21        return '[CentralAuth] Globalizing initial user';
22    }
23
24    /**
25     * @return string[]
26     */
27    public function getDependencies() {
28        return [ 'created-user-names', 'extension-tables', 'services' ];
29    }
30
31    public function execute(): Status {
32        $services = $this->getServices();
33        $dbw = $services->getConnectionProvider()->getPrimaryDatabase( 'virtual-centralauth' );
34
35        $names = $this->getContext()->getProvision( 'created-user-names' );
36        if ( !$names ) {
37            return Status::newGood();
38        }
39
40        // Assume that there are very few users, so we don't need batching.
41        $users = $dbw->newSelectQueryBuilder()
42            ->from( 'user' )
43            ->select( [
44                'user_id',
45                'user_email',
46                'user_name',
47                'user_email_authenticated',
48                'user_password',
49                'user_registration',
50            ] )
51            ->where( [ 'user_name' => $names ] )
52            ->caller( __METHOD__ )
53            ->fetchResultSet();
54
55        // We're in the installer, so none of the CentralAuth code except for this script is loaded,
56        // therefore we can't rely on any of our services or default values of config options.
57        // Migrate the users manually using custom database queries.
58
59        foreach ( $users as $user ) {
60            $dbw->doAtomicSection( __METHOD__, static function ( $dbw, $fname ) use ( $user ) {
61                global $wgDBname;
62
63                // Unlike migratePass0/1, we don't need to store anything into globalnames and localnames,
64                // these tables are only used for incomplete migrations and we're doing a complete one.
65
66                // See CentralAuthUser::storeGlobalData()
67                $dbw->newInsertQueryBuilder()
68                    ->insertInto( 'globaluser' )
69                    ->row( [
70                        'gu_name' => $user->user_name,
71                        'gu_home_db' => $wgDBname,
72                        'gu_email' => $user->user_email,
73                        'gu_email_authenticated' => $user->user_email_authenticated,
74                        'gu_password' => $user->user_password,
75                        'gu_locked' => 0,
76                        'gu_hidden_level' => 0,
77                        'gu_registration' => $user->user_registration,
78                        'gu_auth_token' => MWCryptRand::generateHex( 32 ),
79                    ] )
80                    ->caller( $fname )
81                    ->execute();
82                $gu_id = $dbw->insertId();
83
84                // See CentralAuthUser::attach()
85                $dbw->newInsertQueryBuilder()
86                    ->insertInto( 'localuser' )
87                    ->row( [
88                        'lu_wiki' => $wgDBname,
89                        'lu_name' => $user->user_name,
90                        'lu_attached_timestamp' => $user->user_registration,
91                        'lu_attached_method' => 'new',
92                        'lu_local_id' => $user->user_id,
93                        'lu_global_id' => $gu_id,
94                    ] )
95                    ->caller( $fname )
96                    ->execute();
97
98                // We don't handle AntiSpoof integration here, because it's complicated, and the
99                // AntiSpoof extension doesn't handle the initial accounts either.
100            } );
101        }
102
103        return Status::newGood();
104    }
105}