Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.15% covered (success)
98.15%
53 / 54
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
CleanupWatchlistLabelMember
100.00% covered (success)
100.00%
53 / 53
100.00% covered (success)
100.00%
3 / 3
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getUpdateKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 doDBUpdates
100.00% covered (success)
100.00%
49 / 49
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3use MediaWiki\Maintenance\LoggedUpdateMaintenance;
4
5require_once __DIR__ . '/TableCleanup.php';
6
7/**
8 * @ingroup Maintenance
9 */
10class CleanupWatchlistLabelMember extends LoggedUpdateMaintenance {
11
12    public function __construct() {
13        parent::__construct();
14        $this->addDescription( 'Add watchlist labels to talk pages (to match those of the subject pages).' );
15        $this->setBatchSize( 500 );
16    }
17
18    /** @inheritDoc */
19    protected function getUpdateKey() {
20        return __CLASS__;
21    }
22
23    /** @inheritDoc */
24    protected function doDBUpdates() {
25        $dbw = $this->getServiceContainer()->getConnectionProvider()->getPrimaryDatabase();
26        $batchNum = 1;
27        while ( true ) {
28            // Find the missing talk page data for the watchlist_label_member table.
29            $missingLabelMembers = $dbw->newSelectQueryBuilder()
30                ->select( [ 'wlm_subject.wlm_label', 'wl_talk.wl_id', 'wl_talk.wl_namespace' ] )
31                ->distinct()
32                // Select the watchlist
33                ->from( 'watchlist', 'wl_subject' )
34                // Join to the watchlist talk pages (where NS IDs are incremented by one)
35                ->join( 'watchlist', 'wl_talk', [
36                    'wl_subject.wl_user = wl_talk.wl_user',
37                    'wl_subject.wl_namespace + 1 = wl_talk.wl_namespace',
38                    'wl_subject.wl_title = wl_talk.wl_title',
39                    // Making sure it's not the same row.
40                    'wl_subject.wl_id != wl_talk.wl_id',
41                ] )
42                // Determine if the watchlist item (for the subject page) is labelled.
43                ->join( 'watchlist_label_member', 'wlm_subject', [
44                    'wlm_subject.wlm_item = wl_subject.wl_id',
45                ] )
46                // And find the labels for the matching talk page (if any).
47                ->leftJoin( 'watchlist_label_member', 'wlm_talk', [
48                    'wlm_talk.wlm_item = wl_talk.wl_id',
49                    'wlm_talk.wlm_label = wlm_subject.wlm_label',
50                ] )
51                ->where( [
52                    // Exclude the matched talk page rows if they exist.
53                    'wlm_talk.wlm_item IS NULL',
54                    // Ensure that the subject and talk namespaces are valid.
55                    'wl_subject.wl_namespace % 2 = 0',
56                ] )
57                ->limit( $this->getBatchSize() )
58                ->caller( __METHOD__ )
59                ->fetchResultSet();
60            $data = [];
61            foreach ( $missingLabelMembers as $missingLabelMember ) {
62                $data[] = [
63                    'wlm_label' => $missingLabelMember->wlm_label,
64                    'wlm_item' => $missingLabelMember->wl_id,
65                ];
66            }
67            if ( !$data ) {
68                $this->output( $batchNum === 1 ? "Nothing to fix.\n" : "Done.\n" );
69                return true;
70            }
71            $this->output(
72                'Fixing labels on talk pages for ' . count( $data ) . ' watchlist items (batch ' . $batchNum . ").\n"
73            );
74            $batchNum++;
75            $dbw->newInsertQueryBuilder()
76                ->insertInto( 'watchlist_label_member' )
77                ->rows( $data )
78                ->caller( __METHOD__ )
79                ->execute();
80        }
81    }
82}
83
84// @codeCoverageIgnoreStart
85$maintClass = CleanupWatchlistLabelMember::class;
86require_once RUN_MAINTENANCE_IF_MAIN;
87// @codeCoverageIgnoreEnd