Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 72
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
PopulateCucActor
0.00% covered (danger)
0.00%
0 / 66
0.00% covered (danger)
0.00%
0 / 3
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 getUpdateKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doDBUpdates
0.00% covered (danger)
0.00%
0 / 56
0.00% covered (danger)
0.00%
0 / 1
42
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 * @file
19 */
20
21namespace MediaWiki\CheckUser\Maintenance;
22
23use LoggedUpdateMaintenance;
24use MediaWiki\MediaWikiServices;
25
26$IP = getenv( 'MW_INSTALL_PATH' );
27if ( $IP === false ) {
28    $IP = __DIR__ . '/../../..';
29}
30require_once "$IP/maintenance/Maintenance.php";
31
32/**
33 * Maintenance script for filling up cuc_actor.
34 *
35 * @author Zabe
36 */
37class PopulateCucActor extends LoggedUpdateMaintenance {
38
39    public function __construct() {
40        parent::__construct();
41        $this->requireExtension( 'CheckUser' );
42        $this->addDescription( 'Populate the cuc_actor column.' );
43        $this->addOption(
44            'sleep',
45            'Sleep time (in seconds) between every batch. Default: 0',
46            false,
47            true
48        );
49    }
50
51    /**
52     * @inheritDoc
53     */
54    protected function getUpdateKey() {
55        return 'PopulateCucActor';
56    }
57
58    /**
59     * @inheritDoc
60     */
61    protected function doDBUpdates() {
62        $services = MediaWikiServices::getInstance();
63        $actorStore = $services->getActorStore();
64        $mainLb = $services->getDBLoadBalancerFactory()->getMainLB();
65        $dbr = $mainLb->getConnection( DB_REPLICA, 'vslow' );
66        $dbw = $mainLb->getMaintenanceConnectionRef( DB_PRIMARY );
67        $batchSize = $this->getBatchSize();
68
69        $prevId = (int)$dbr->newSelectQueryBuilder()
70            ->field( 'MIN(cuc_id)' )
71            ->table( 'cu_changes' )
72            ->caller( __METHOD__ )
73            ->fetchField();
74        $curId = $prevId + $batchSize;
75        $maxId = (int)$dbr->newSelectQueryBuilder()
76            ->field( 'MAX(cuc_id)' )
77            ->table( 'cu_changes' )
78            ->caller( __METHOD__ )
79            ->fetchField();
80
81        if ( !$maxId ) {
82            $this->output( "The cu_changes table seems to be empty.\n" );
83            return true;
84        }
85
86        if ( !$dbw->fieldExists( 'cu_changes', 'cuc_user' ) ) {
87            $this->output( "cuc_user and cuc_user_text have already been dropped.\n" );
88            return true;
89        }
90
91        $diff = $maxId - $prevId;
92        $failed = 0;
93        $sleep = (int)$this->getOption( 'sleep', 0 );
94
95        do {
96            $res = $dbr->newSelectQueryBuilder()
97                ->fields( [ 'cuc_id', 'cuc_user_text' ] )
98                ->table( 'cu_changes' )
99                ->conds( [
100                    'cuc_actor' => 0,
101                    $dbr->expr( 'cuc_id', '>=', $prevId ),
102                    $dbr->expr( 'cuc_id', '<=', $curId ),
103                ] )
104                ->caller( __METHOD__ )
105                ->fetchResultSet();
106
107            foreach ( $res as $row ) {
108                $actor = $actorStore->findActorIdByName( $row->cuc_user_text, $dbr );
109
110                if ( !$actor ) {
111                    $failed++;
112                    continue;
113                }
114
115                $dbw->newUpdateQueryBuilder()
116                    ->update( 'cu_changes' )
117                    ->set( [ 'cuc_actor' => $actor ] )
118                    ->where( [ 'cuc_id' => $row->cuc_id ] )
119                    ->caller( __METHOD__ )
120                    ->execute();
121            }
122
123            $this->waitForReplication();
124
125            if ( $sleep > 0 ) {
126                sleep( $sleep );
127            }
128
129            $this->output( "Processed $batchSize rows out of $diff.\n" );
130
131            $prevId = $curId;
132            $curId += $batchSize;
133        } while ( $prevId <= $maxId );
134
135        $this->output( "Done. Migration failed for $failed row(s).\n" );
136        return true;
137    }
138}
139
140$maintClass = PopulateCucActor::class;
141require_once RUN_MAINTENANCE_IF_MAIN;