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