Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 109
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 / 103
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 / 22
0.00% covered (danger)
0.00%
0 / 1
6
 updateTreeRevision
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
6
 updateRevision
0.00% covered (danger)
0.00%
0 / 36
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->select(
81            /* table */'flow_workflow',
82            /* select */[ 'workflow_id', 'workflow_user_text' ],
83            /* conds */[
84                'workflow_id > ' . $dbw->addQuotes( $continue ),
85                'workflow_user_ip IS NULL',
86                'workflow_user_id = 0'
87            ],
88            __METHOD__,
89            /* options */[ 'LIMIT' => $this->getBatchSize(), 'ORDER BY' => 'workflow_id' ]
90        );
91
92        $continue = null;
93
94        foreach ( $rows as $row ) {
95            $continue = $row->workflow_id;
96            $dbw->newUpdateQueryBuilder()
97                ->update( 'flow_workflow' )
98                ->set( [ 'workflow_user_ip' => $row->workflow_user_text ] )
99                ->where( [ 'workflow_id' => $row->workflow_id ] )
100                ->caller( __METHOD__ )
101                ->execute();
102
103            $this->completeCount++;
104        }
105
106        return $continue;
107    }
108
109    public function updateTreeRevision( IDatabase $dbw, $continue = null ) {
110        $rows = $dbw->select(
111            /* table */'flow_tree_revision',
112            /* select */[ 'tree_rev_id', 'tree_orig_user_text' ],
113            [
114                'tree_rev_id > ' . $dbw->addQuotes( $continue ),
115                'tree_orig_user_ip IS NULL',
116                'tree_orig_user_id = 0',
117            ],
118            __METHOD__,
119            /* options */[ 'LIMIT' => $this->getBatchSize(), 'ORDER BY' => 'tree_rev_id' ]
120        );
121
122        $continue = null;
123        foreach ( $rows as $row ) {
124            $continue = $row->tree_rev_id;
125            $dbw->newUpdateQueryBuilder()
126                ->update( 'flow_tree_revision' )
127                ->set( [ 'tree_orig_user_ip' => $row->tree_orig_user_text ] )
128                ->where( [ 'tree_rev_id' => $row->tree_rev_id ] )
129                ->caller( __METHOD__ )
130                ->execute();
131
132            $this->completeCount++;
133        }
134
135        return $continue;
136    }
137
138    public function updateRevision( IDatabase $dbw, $continue = null ) {
139        $rows = $dbw->select(
140            /* table */'flow_revision',
141            /* select */[ 'rev_id', 'rev_user_id', 'rev_user_text', 'rev_mod_user_id',
142                'rev_mod_user_text', 'rev_edit_user_id', 'rev_edit_user_text' ],
143            /* conditions */ [
144                'rev_id > ' . $dbw->addQuotes( $continue ),
145                $dbw->makeList(
146                    [
147                        'rev_user_id' => 0,
148                        'rev_mod_user_id' => 0,
149                        'rev_edit_user_id' => 0,
150                    ],
151                    LIST_OR
152                ),
153            ],
154            __METHOD__,
155            /* options */[ 'LIMIT' => $this->getBatchSize(), 'ORDER BY' => 'rev_id' ]
156        );
157
158        $continue = null;
159        foreach ( $rows as $row ) {
160            $continue = $row->rev_id;
161            $updates = [];
162
163            if ( $row->rev_user_id == 0 ) {
164                $updates['rev_user_ip'] = $row->rev_user_text;
165            }
166            if ( $row->rev_mod_user_id == 0 ) {
167                $updates['rev_mod_user_ip'] = $row->rev_mod_user_text;
168            }
169            if ( $row->rev_edit_user_id == 0 ) {
170                $updates['rev_edit_user_ip'] = $row->rev_edit_user_text;
171            }
172            if ( $updates ) {
173                $dbw->newUpdateQueryBuilder()
174                    ->update( 'flow_revision' )
175                    ->set( $updates )
176                    ->where( [ 'rev_id' => $row->rev_id ] )
177                    ->caller( __METHOD__ )
178                    ->execute();
179            }
180        }
181
182        return $continue;
183    }
184
185    /**
186     * Get the update key name to go in the update log table
187     *
188     * @return string
189     */
190    protected function getUpdateKey() {
191        return 'FlowSetUserIp';
192    }
193}
194
195$maintClass = FlowSetUserIp::class;
196require_once RUN_MAINTENANCE_IF_MAIN;