Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 107
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
FlowSetUserIp
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 6
342
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 doDBUpdates
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
42
 updateWorkflow
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
6
 updateTreeRevision
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
6
 updateRevision
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
42
 getUpdateKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Flow\Maintenance;
4
5use Flow\Container;
6use Flow\DbFactory;
7use LoggedUpdateMaintenance;
8use Wikimedia\Rdbms\IDatabase;
9
10$IP = getenv( 'MW_INSTALL_PATH' );
11if ( $IP === false ) {
12    $IP = __DIR__ . '/../../..';
13}
14
15require_once "$IP/maintenance/Maintenance.php";
16
17/**
18 * Populate the *_user_ip fields within flow. This only updates
19 * the database and not the cache. The model loading layer handles
20 * cached old values.
21 *
22 * @ingroup Maintenance
23 */
24class FlowSetUserIp extends LoggedUpdateMaintenance {
25    /**
26     * The number of entries completed
27     *
28     * @var int
29     */
30    private $completeCount = 0;
31
32    public function __construct() {
33        parent::__construct();
34
35        $this->setBatchSize( 300 );
36        $this->requireExtension( 'Flow' );
37    }
38
39    protected function doDBUpdates() {
40        /** @var DbFactory $dbf */
41        $dbf = Container::get( 'db.factory' );
42        $dbw = $dbf->getDB( DB_PRIMARY );
43        $hasRun = false;
44
45        $runUpdate = static function ( $callback ) use ( $dbf, $dbw, &$hasRun ) {
46            $hasRun = true;
47            $continue = "\0";
48            do {
49                $continue = $callback( $dbw, $continue );
50                $dbf->waitForReplicas();
51            } while ( $continue !== null );
52        };
53
54        // run updates only if we have the required source data
55        if ( $dbw->fieldExists( 'flow_workflow', 'workflow_user_text' ) ) {
56            $runUpdate( [ $this, 'updateWorkflow' ] );
57        }
58        if ( $dbw->fieldExists( 'flow_tree_revision', 'tree_orig_user_text' ) ) {
59            $runUpdate( [ $this, 'updateTreeRevision' ] );
60        }
61        if (
62            $dbw->fieldExists( 'flow_revision', 'rev_user_text' ) &&
63            $dbw->fieldExists( 'flow_revision', 'rev_mod_user_text' ) &&
64            $dbw->fieldExists( 'flow_revision', 'rev_edit_user_text' )
65        ) {
66            $runUpdate( [ $this, 'updateRevision' ] );
67        }
68
69        return true;
70    }
71
72    /**
73     * Refreshes a batch of recentchanges entries
74     *
75     * @param IDatabase $dbw
76     * @param int|null $continue The next batch starting at rc_id
77     * @return int|null Start id for the next batch
78     */
79    public function updateWorkflow( IDatabase $dbw, $continue = null ) {
80        $rows = $dbw->newSelectQueryBuilder()
81            ->select( [ 'workflow_id', 'workflow_user_text' ] )
82            ->from( 'flow_workflow' )
83            ->where( [
84                $dbw->expr( 'workflow_id', '>', $continue ),
85                'workflow_user_ip' => null,
86                'workflow_user_id' => 0,
87            ] )
88            ->limit( $this->getBatchSize() )
89            ->orderBy( 'workflow_id' )
90            ->caller( __METHOD__ )
91            ->fetchResultSet();
92
93        $continue = null;
94
95        foreach ( $rows as $row ) {
96            $continue = $row->workflow_id;
97            $dbw->newUpdateQueryBuilder()
98                ->update( 'flow_workflow' )
99                ->set( [ 'workflow_user_ip' => $row->workflow_user_text ] )
100                ->where( [ 'workflow_id' => $row->workflow_id ] )
101                ->caller( __METHOD__ )
102                ->execute();
103
104            $this->completeCount++;
105        }
106
107        return $continue;
108    }
109
110    public function updateTreeRevision( IDatabase $dbw, $continue = null ) {
111        $rows = $dbw->newSelectQueryBuilder()
112            ->select( [ 'tree_rev_id', 'tree_orig_user_text' ] )
113            ->from( 'flow_tree_revision' )
114            ->where( [
115                $dbw->expr( 'tree_rev_id', '>', $continue ),
116                'tree_orig_user_ip' => null,
117                'tree_orig_user_id' => 0,
118            ] )
119            ->limit( $this->getBatchSize() )
120            ->orderBy( 'tree_rev_id' )
121            ->caller( __METHOD__ )
122            ->fetchResultSet();
123
124        $continue = null;
125        foreach ( $rows as $row ) {
126            $continue = $row->tree_rev_id;
127            $dbw->newUpdateQueryBuilder()
128                ->update( 'flow_tree_revision' )
129                ->set( [ 'tree_orig_user_ip' => $row->tree_orig_user_text ] )
130                ->where( [ 'tree_rev_id' => $row->tree_rev_id ] )
131                ->caller( __METHOD__ )
132                ->execute();
133
134            $this->completeCount++;
135        }
136
137        return $continue;
138    }
139
140    public function updateRevision( IDatabase $dbw, $continue = null ) {
141        $rows = $dbw->newSelectQueryBuilder()
142            ->select( [ 'rev_id', 'rev_user_id', 'rev_user_text', 'rev_mod_user_id',
143                'rev_mod_user_text', 'rev_edit_user_id', 'rev_edit_user_text' ] )
144            ->from( 'flow_revision' )
145            ->where( [
146                $dbw->expr( 'rev_id', '>', $continue ),
147                $dbw->expr( 'rev_user_id', '=', 0 )
148                    ->or( 'rev_mod_user_id', '=', 0 )
149                    ->or( 'rev_edit_user_id', '=', 0 ),
150            ] )
151            ->limit( $this->getBatchSize() )
152            ->orderBy( 'rev_id' )
153            ->caller( __METHOD__ )
154            ->fetchResultSet();
155
156        $continue = null;
157        foreach ( $rows as $row ) {
158            $continue = $row->rev_id;
159            $updates = [];
160
161            if ( $row->rev_user_id == 0 ) {
162                $updates['rev_user_ip'] = $row->rev_user_text;
163            }
164            if ( $row->rev_mod_user_id == 0 ) {
165                $updates['rev_mod_user_ip'] = $row->rev_mod_user_text;
166            }
167            if ( $row->rev_edit_user_id == 0 ) {
168                $updates['rev_edit_user_ip'] = $row->rev_edit_user_text;
169            }
170            if ( $updates ) {
171                $dbw->newUpdateQueryBuilder()
172                    ->update( 'flow_revision' )
173                    ->set( $updates )
174                    ->where( [ 'rev_id' => $row->rev_id ] )
175                    ->caller( __METHOD__ )
176                    ->execute();
177            }
178        }
179
180        return $continue;
181    }
182
183    /**
184     * Get the update key name to go in the update log table
185     *
186     * @return string
187     */
188    protected function getUpdateKey() {
189        return 'FlowSetUserIp';
190    }
191}
192
193$maintClass = FlowSetUserIp::class;
194require_once RUN_MAINTENANCE_IF_MAIN;