Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PopulateFRRevTimestamp
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 4
210
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 populateFRRevTimestamp
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 1
90
 lastPosFile
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * @ingroup Maintenance
4 */
5
6use MediaWiki\WikiMap\WikiMap;
7
8if ( getenv( 'MW_INSTALL_PATH' ) ) {
9    $IP = getenv( 'MW_INSTALL_PATH' );
10} else {
11    $IP = __DIR__ . '/../../..';
12}
13
14require_once "$IP/maintenance/Maintenance.php";
15
16class PopulateFRRevTimestamp extends Maintenance {
17
18    public function __construct() {
19        parent::__construct();
20        $this->addDescription( 'Populates fr_rev_timestamp column in the flaggedrevs table.' );
21        $this->addOption( 'startrev', 'The ID of the starting rev', false, true );
22        $this->setBatchSize( 1000 );
23        $this->requireExtension( 'FlaggedRevs' );
24    }
25
26    /**
27     * @inheritDoc
28     */
29    public function execute() {
30        $startRev = $this->getOption( 'startrev' );
31        if ( $startRev === 'prev' ) {
32            $startRev = file_get_contents( $this->lastPosFile() );
33        }
34        if ( $startRev !== null ) {
35            $startRev = (int)$startRev;
36        }
37        $this->populateFRRevTimestamp( $startRev );
38    }
39
40    /**
41     * @param int|null $start Revision ID
42     */
43    private function populateFRRevTimestamp( $start = null ) {
44        $this->output( "Populating and correcting flaggedrevs columns from $start\n" );
45
46        $db = $this->getPrimaryDB();
47
48        if ( $start === null ) {
49            $start = $db->newSelectQueryBuilder()
50                ->select( 'MIN(fr_rev_id)' )
51                ->from( 'flaggedrevs' )
52                ->caller( __METHOD__ )
53                ->fetchField();
54        }
55        $end = $db->newSelectQueryBuilder()
56            ->select( 'MAX(fr_rev_id)' )
57            ->from( 'flaggedrevs' )
58            ->caller( __METHOD__ )
59            ->fetchField();
60        if ( $start === null || $end === null ) {
61            $this->output( "...flaggedrevs table seems to be empty.\n" );
62            return;
63        }
64        # Do remaining chunk
65        $end += $this->mBatchSize - 1;
66        $blockStart = (int)$start;
67        $blockEnd = (int)$start + $this->mBatchSize - 1;
68        $count = 0;
69        $changed = 0;
70
71        while ( $blockEnd <= $end ) {
72            $this->output( "...doing fr_rev_id from $blockStart to $blockEnd\n" );
73            $res = $db->newSelectQueryBuilder()
74                ->select( [ 'fr_rev_id', 'rev_timestamp', 'ar_timestamp' ] )
75                ->from( 'flaggedrevs' )
76                ->leftJoin( 'revision', null, 'rev_id = fr_rev_id' )
77                ->leftJoin( 'archive', null, 'ar_rev_id = fr_rev_id' ) // non-unique but OK
78                ->where( [
79                    $db->expr( 'fr_rev_id', '>=', $blockStart ),
80                    $db->expr( 'fr_rev_id', '<=', $blockEnd ),
81                    'fr_rev_timestamp' => '',
82                ] )
83                ->caller( __METHOD__ )
84                ->fetchResultSet();
85            $db->begin( __METHOD__ );
86            # Go through and clean up missing items
87            foreach ( $res as $row ) {
88                $timestamp = '';
89                if ( $row->rev_timestamp ) {
90                    $timestamp = $row->rev_timestamp;
91                } elseif ( $row->ar_timestamp ) {
92                    $timestamp = $row->ar_timestamp;
93                }
94                if ( $timestamp != '' ) {
95                    # Update the row...
96                    $db->newUpdateQueryBuilder()
97                        ->update( 'flaggedrevs' )
98                        ->set( [ 'fr_rev_timestamp' => $timestamp ] )
99                        ->where( [ 'fr_rev_id' => $row->fr_rev_id ] )
100                        ->caller( __METHOD__ )
101                        ->execute();
102                    $changed++;
103                }
104                $count++;
105            }
106            $db->commit( __METHOD__ );
107            $blockStart += $this->mBatchSize;
108            $blockEnd += $this->mBatchSize;
109            $this->waitForReplication();
110        }
111        file_put_contents( $this->lastPosFile(), $end );
112        $this->output( "fr_rev_timestamp columns update complete ..." .
113            " {$count} rows [{$changed} changed]\n" );
114    }
115
116    /**
117     * @return string
118     */
119    private function lastPosFile() {
120        return __DIR__ . "/popRevTimestampLast-" . WikiMap::getCurrentWikiId();
121    }
122}
123
124$maintClass = PopulateFRRevTimestamp::class;
125require_once RUN_MAINTENANCE_IF_MAIN;