]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - maintenance/populateIpChanges.php
MediaWiki 1.30.2 renames
[autoinstalls/mediawiki.git] / maintenance / populateIpChanges.php
1 <?php
2 /**
3  * Find all revisions by logged out users and copy the rev_id,
4  * rev_timestamp, and a hex representation of rev_user_text to the
5  * new ip_changes table. This table is used to efficiently query for
6  * contributions within an IP range.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  * http://www.gnu.org/copyleft/gpl.html
22  *
23  * @file
24  * @ingroup Maintenance
25  */
26
27 require_once __DIR__ . '/Maintenance.php';
28
29 use MediaWiki\MediaWikiServices;
30
31 /**
32  * Maintenance script that will find all rows in the revision table where
33  * rev_user = 0 (user is an IP), and copy relevant fields to ip_changes so
34  * that historical data will be available when querying for IP ranges.
35  *
36  * @ingroup Maintenance
37  */
38 class PopulateIpChanges extends LoggedUpdateMaintenance {
39         public function __construct() {
40                 parent::__construct();
41
42                 $this->addDescription( <<<TEXT
43 This script will find all rows in the revision table where the user is an IP,
44 and copy relevant fields to the ip_changes table. This backfilled data will
45 then be available when querying for IP ranges at Special:Contributions.
46 TEXT
47                 );
48                 $this->addOption( 'rev-id', 'The rev_id to start copying from. Default: 0', false, true );
49                 $this->addOption(
50                         'max-rev-id',
51                         'The rev_id to stop at. Default: result of MAX(rev_id)',
52                         false,
53                         true
54                 );
55                 $this->addOption(
56                         'throttle',
57                         'Wait this many milliseconds after copying each batch of revisions. Default: 0',
58                         false,
59                         true
60                 );
61                 $this->addOption( 'force', 'Run regardless of whether the database says it\'s been run already' );
62         }
63
64         public function doDBUpdates() {
65                 $dbw = $this->getDB( DB_MASTER );
66
67                 if ( !$dbw->tableExists( 'ip_changes' ) ) {
68                         $this->error( 'ip_changes table does not exist', true );
69                 }
70
71                 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
72                 $dbr = $this->getDB( DB_REPLICA, [ 'vslow' ] );
73                 $throttle = intval( $this->getOption( 'throttle', 0 ) );
74                 $maxRevId = intval( $this->getOption( 'max-rev-id', 0 ) );
75                 $start = $this->getOption( 'rev-id', 0 );
76                 $end = $maxRevId > 0
77                         ? $maxRevId
78                         : $dbw->selectField( 'revision', 'MAX(rev_id)', false, __METHOD__ );
79
80                 if ( empty( $end ) ) {
81                         $this->output( "No revisions found, aborting.\n" );
82                         return true;
83                 }
84
85                 $blockStart = $start;
86                 $attempted = 0;
87                 $inserted = 0;
88
89                 $this->output( "Copying IP revisions to ip_changes, from rev_id $start to rev_id $end\n" );
90
91                 while ( $blockStart <= $end ) {
92                         $blockEnd = min( $blockStart + $this->mBatchSize, $end );
93                         $rows = $dbr->select(
94                                 'revision',
95                                 [ 'rev_id', 'rev_timestamp', 'rev_user_text' ],
96                                 [ "rev_id BETWEEN $blockStart AND $blockEnd", 'rev_user' => 0 ],
97                                 __METHOD__
98                         );
99
100                         $numRows = $rows->numRows();
101
102                         if ( !$rows || $numRows === 0 ) {
103                                 $blockStart = $blockEnd + 1;
104                                 continue;
105                         }
106
107                         $this->output( "...checking $numRows revisions for IP edits that need copying, " .
108                                 "between rev_ids $blockStart and $blockEnd\n" );
109
110                         $insertRows = [];
111                         foreach ( $rows as $row ) {
112                                 // Make sure this is really an IP, e.g. not maintenance user or imported revision.
113                                 if ( IP::isValid( $row->rev_user_text ) ) {
114                                         $insertRows[] = [
115                                                 'ipc_rev_id' => $row->rev_id,
116                                                 'ipc_rev_timestamp' => $row->rev_timestamp,
117                                                 'ipc_hex' => IP::toHex( $row->rev_user_text ),
118                                         ];
119
120                                         $attempted++;
121                                 }
122                         }
123
124                         if ( $insertRows ) {
125                                 $dbw->insert( 'ip_changes', $insertRows, __METHOD__, 'IGNORE' );
126
127                                 $inserted += $dbw->affectedRows();
128                         }
129
130                         $lbFactory->waitForReplication();
131                         usleep( $throttle * 1000 );
132
133                         $blockStart = $blockEnd + 1;
134                 }
135
136                 $this->output( "Attempted to insert $attempted IP revisions, $inserted actually done.\n" );
137
138                 return true;
139         }
140
141         protected function getUpdateKey() {
142                 return 'populate ip_changes';
143         }
144 }
145
146 $maintClass = "PopulateIpChanges";
147 require_once RUN_MAINTENANCE_IF_MAIN;