Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 88 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
MigrateCentralWikiLogs | |
0.00% |
0 / 82 |
|
0.00% |
0 / 2 |
132 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 77 |
|
0.00% |
0 / 1 |
110 |
1 | <?php |
2 | /** |
3 | * This script should be run as part of migrating to a new central OAuth wiki in your |
4 | * cluster. See the notes in migrateCentralWikiLogs.php for the complete process. |
5 | * This script is intended to be run on the new central wiki after the tables have already |
6 | * been migrated. This will fill in the logs from newest to oldest, and tries to do sane |
7 | * things if you need to stop it and restart it later. |
8 | * |
9 | * @ingroup Maintenance |
10 | */ |
11 | if ( getenv( 'MW_INSTALL_PATH' ) ) { |
12 | $IP = getenv( 'MW_INSTALL_PATH' ); |
13 | } else { |
14 | $IP = __DIR__ . '/../../..'; |
15 | } |
16 | |
17 | require_once "$IP/maintenance/Maintenance.php"; |
18 | |
19 | use MediaWiki\Maintenance\Maintenance; |
20 | use MediaWiki\MediaWikiServices; |
21 | use MediaWiki\Title\Title; |
22 | use MediaWiki\WikiMap\WikiMap; |
23 | use Wikimedia\Rdbms\SelectQueryBuilder; |
24 | |
25 | class MigrateCentralWikiLogs extends Maintenance { |
26 | public function __construct() { |
27 | parent::__construct(); |
28 | $this->addDescription( "Import central wiki logs to this wiki" ); |
29 | $this->addOption( 'old', 'Previous central wiki', true, true ); |
30 | $this->setBatchSize( 200 ); |
31 | $this->requireExtension( "OAuth" ); |
32 | } |
33 | |
34 | public function execute() { |
35 | $oldWiki = $this->getOption( 'old' ); |
36 | $targetWiki = WikiMap::getCurrentWikiId(); |
37 | |
38 | $this->output( "Moving OAuth logs from '$oldWiki' to '$targetWiki'\n" ); |
39 | |
40 | // We only read from $oldDb, but we do want to make sure we get the most recent logs. |
41 | $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); |
42 | $oldDb = $lbFactory->getMainLB( $oldWiki )->getConnection( DB_PRIMARY, [], $oldWiki ); |
43 | $targetDb = $lbFactory->getMainLB( $targetWiki ) |
44 | ->getConnection( DB_PRIMARY, [], $targetWiki ); |
45 | |
46 | $targetMinTS = $targetDb->newSelectQueryBuilder() |
47 | ->select( 'MIN(log_timestamp)' ) |
48 | ->from( 'logging' ) |
49 | ->where( [ 'log_type' => 'mwoauthconsumer' ] ) |
50 | ->caller( __METHOD__ ) |
51 | ->fetchField(); |
52 | |
53 | $lastMinTimestamp = null; |
54 | if ( $targetMinTS !== false ) { |
55 | $lastMinTimestamp = $targetMinTS; |
56 | } |
57 | |
58 | $commentStore = MediaWikiServices::getInstance()->getCommentStore(); |
59 | $commentQuery = $commentStore->getJoin( 'log_comment' ); |
60 | |
61 | do { |
62 | $conds = [ 'log_type' => 'mwoauthconsumer' ]; |
63 | |
64 | // This assumes that we don't have more than mBatchSize oauth log entries |
65 | // with the same timestamp. Otherwise this will go into an infinite loop. |
66 | if ( $lastMinTimestamp !== null ) { |
67 | $conds[] = $oldDb->expr( 'log_timestamp', '<', $oldDb->timestamp( $lastMinTimestamp ) ); |
68 | } |
69 | |
70 | $oldLoggs = $oldDb->newSelectQueryBuilder() |
71 | ->select( [ |
72 | 'log_id', 'log_action', 'log_timestamp', 'log_params', 'log_deleted', |
73 | 'actor_id', 'actor_name', 'actor_user' |
74 | ] ) |
75 | ->from( 'logging' ) |
76 | ->join( 'actor', null, 'actor_id=log_actor' ) |
77 | ->where( $conds ) |
78 | ->queryInfo( $commentQuery ) |
79 | ->orderBy( 'log_timestamp', SelectQueryBuilder::SORT_DESC ) |
80 | ->limit( $this->mBatchSize + 1 ) |
81 | ->caller( __METHOD__ ) |
82 | ->fetchResultSet(); |
83 | |
84 | $rowCount = $oldLoggs->numRows(); |
85 | |
86 | if ( $rowCount == $this->mBatchSize + 1 ) { |
87 | $first = $oldLoggs->fetchObject(); |
88 | $oldLoggs->seek( $rowCount - 2 ); |
89 | $last = $oldLoggs->fetchObject(); |
90 | if ( $first->log_timestamp === $last->log_timestamp ) { |
91 | $this->fatalError( "Batch size too low to avoid infinite loop.\n" ); |
92 | } |
93 | $extra = $oldLoggs->fetchObject(); |
94 | if ( $last->log_timestamp === $extra->log_timestamp ) { |
95 | $this->fatalError( "We hit an edge case. Please increase the batch " . |
96 | " size and restart the transfer.\n" ); |
97 | } |
98 | $oldLoggs->rewind(); |
99 | } |
100 | |
101 | $targetDb->begin( __METHOD__ ); |
102 | foreach ( $oldLoggs as $key => $row ) { |
103 | // Skip if this is the extra row we selected |
104 | if ( $key > $this->mBatchSize ) { |
105 | continue; |
106 | } |
107 | |
108 | $lastMinTimestamp = $row->log_timestamp; |
109 | |
110 | $this->output( "Migrating log {$row->log_id}...\n" ); |
111 | if ( !$row->actor_user ) { |
112 | $this->output( |
113 | "Cannot transfer log_id: {$row->log_id}, the log user doesn't exist" |
114 | ); |
115 | continue; |
116 | } |
117 | $logUser = MediaWikiServices::getInstance()->getActorNormalization() |
118 | ->newActorFromRow( $row ); |
119 | $params = LogEntryBase::extractParams( $row->log_params ); |
120 | if ( !isset( $params['4:consumer'] ) ) { |
121 | $this->output( "Cannot transfer log_id: {$row->log_id}, param isn't correct" ); |
122 | continue; |
123 | } |
124 | $logEntry = new ManualLogEntry( 'mwoauthconsumer', $row->log_action ); |
125 | $logEntry->setPerformer( $logUser ); |
126 | $logEntry->setTarget( Title::makeTitleSafe( NS_USER, $row->actor_name ) ); |
127 | $logEntry->setComment( $commentStore->getComment( 'log_comment', $row )->text ); |
128 | $logEntry->setParameters( $params ); |
129 | $logEntry->setRelations( [ |
130 | 'OAuthConsumer' => [ $params['4:consumer'] ] |
131 | ] ); |
132 | // ManualLogEntry::insert() calls $dbw->timestamp on the value |
133 | $logEntry->setTimestamp( $row->log_timestamp ); |
134 | // @TODO: Maybe this will do something some day. Sigh. |
135 | $logEntry->setDeleted( $row->log_deleted ); |
136 | $logEntry->insert( $targetDb ); |
137 | } |
138 | $targetDb->commit( __METHOD__ ); |
139 | |
140 | $this->waitForReplication(); |
141 | |
142 | } while ( $rowCount ); |
143 | } |
144 | |
145 | } |
146 | |
147 | $maintClass = MigrateCentralWikiLogs::class; |
148 | require_once RUN_MAINTENANCE_IF_MAIN; |