Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 96 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
FlowFixUserIp | |
0.00% |
0 / 90 |
|
0.00% |
0 / 5 |
210 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
doDBUpdates | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 | |||
updateTreeRevision | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
30 | |||
updateRevision | |
0.00% |
0 / 35 |
|
0.00% |
0 / 1 |
30 | |||
getUpdateKey | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Flow\Maintenance; |
4 | |
5 | use Flow\Container; |
6 | use Flow\Data\ManagerGroup; |
7 | use Flow\DbFactory; |
8 | use Flow\Model\Header; |
9 | use Flow\Model\PostRevision; |
10 | use Flow\Model\PostSummary; |
11 | use Flow\Model\UUID; |
12 | use MediaWiki\Maintenance\LoggedUpdateMaintenance; |
13 | use Wikimedia\Rdbms\IDatabase; |
14 | |
15 | $IP = getenv( 'MW_INSTALL_PATH' ); |
16 | if ( $IP === false ) { |
17 | $IP = __DIR__ . '/../../..'; |
18 | } |
19 | |
20 | require_once "$IP/maintenance/Maintenance.php"; |
21 | |
22 | /** |
23 | * Sets *_user_ip to null when *_user_id is > 0 |
24 | * |
25 | * @ingroup Maintenance |
26 | */ |
27 | class FlowFixUserIp extends LoggedUpdateMaintenance { |
28 | /** |
29 | * The number of entries completed |
30 | * |
31 | * @var int |
32 | */ |
33 | private $completeCount = 0; |
34 | |
35 | /** |
36 | * @var ManagerGroup |
37 | */ |
38 | protected $storage; |
39 | |
40 | private const TYPES = [ |
41 | 'post' => PostRevision::class, |
42 | 'header' => Header::class, |
43 | 'post-summary' => PostSummary::class, |
44 | ]; |
45 | |
46 | public function __construct() { |
47 | parent::__construct(); |
48 | |
49 | $this->setBatchSize( 300 ); |
50 | $this->requireExtension( 'Flow' ); |
51 | } |
52 | |
53 | protected function doDBUpdates() { |
54 | $this->storage = $storage = Container::get( 'storage' ); |
55 | /** @var DbFactory $dbf */ |
56 | $dbf = Container::get( 'db.factory' ); |
57 | $dbw = $dbf->getDB( DB_PRIMARY ); |
58 | $fname = __METHOD__; |
59 | |
60 | $runUpdate = function ( $callback ) use ( $dbw, $storage, $fname ) { |
61 | $continue = "\0"; |
62 | do { |
63 | $this->beginTransaction( $dbw, $fname ); |
64 | $continue = $callback( $dbw, $continue ); |
65 | $this->commitTransaction( $dbw, $fname ); |
66 | $storage->clear(); |
67 | } while ( $continue !== null ); |
68 | }; |
69 | |
70 | $runUpdate( [ $this, 'updateTreeRevision' ] ); |
71 | foreach ( [ 'rev_user', 'rev_mod_user', 'rev_edit_user' ] as $prefix ) { |
72 | $runUpdate( function ( $dbw, $continue ) use ( $prefix ) { |
73 | return $this->updateRevision( $prefix, $dbw, $continue ); |
74 | } ); |
75 | } |
76 | |
77 | return true; |
78 | } |
79 | |
80 | public function updateTreeRevision( IDatabase $dbw, $continue = null ) { |
81 | $rows = $dbw->newSelectQueryBuilder() |
82 | ->select( [ 'tree_rev_id' ] ) |
83 | ->from( 'flow_tree_revision' ) |
84 | ->where( [ |
85 | $dbw->expr( 'tree_rev_id', '>', $continue ), |
86 | $dbw->expr( 'tree_orig_user_ip', '!=', null ), |
87 | $dbw->expr( 'tree_orig_user_id', '>', 0 ), |
88 | ] ) |
89 | ->caller( __METHOD__ ) |
90 | ->limit( $this->getBatchSize() ) |
91 | ->orderBy( 'tree_rev_id' ) |
92 | ->fetchResultSet(); |
93 | |
94 | $om = Container::get( 'storage' )->getStorage( 'PostRevision' ); |
95 | $objs = $ids = []; |
96 | foreach ( $rows as $row ) { |
97 | $id = UUID::create( $row->tree_rev_id ); |
98 | $found = $om->get( $id ); |
99 | if ( $found ) { |
100 | $ids[] = $row->tree_rev_id; |
101 | $objs[] = $found; |
102 | } else { |
103 | $this->error( __METHOD__ . ': Failed loading Flow\Model\PostRevision: ' . $id->getAlphadecimal() ); |
104 | } |
105 | } |
106 | if ( !$ids ) { |
107 | return null; |
108 | } |
109 | $dbw->newUpdateQueryBuilder() |
110 | ->update( 'flow_tree_revision' ) |
111 | ->set( [ 'tree_orig_user_ip' => null ] ) |
112 | ->where( [ 'tree_rev_id' => $ids ] ) |
113 | ->caller( __METHOD__ ) |
114 | ->execute(); |
115 | foreach ( $objs as $obj ) { |
116 | $om->cachePurge( $obj ); |
117 | } |
118 | |
119 | $this->completeCount += count( $ids ); |
120 | |
121 | return end( $ids ); |
122 | } |
123 | |
124 | public function updateRevision( $columnPrefix, IDatabase $dbw, $continue = null ) { |
125 | $rows = $dbw->newSelectQueryBuilder() |
126 | ->select( [ 'rev_id', 'rev_type' ] ) |
127 | ->from( 'flow_revision' ) |
128 | ->where( [ |
129 | $dbw->expr( 'rev_id', '>', $continue ), |
130 | $dbw->expr( "{$columnPrefix}_id", '>', 0 ), |
131 | $dbw->expr( "{$columnPrefix}_ip", '!=', null ), |
132 | ] ) |
133 | ->caller( __METHOD__ ) |
134 | ->limit( $this->getBatchSize() ) |
135 | ->orderBy( 'rev_id' ) |
136 | ->fetchResultSet(); |
137 | |
138 | $ids = $objs = []; |
139 | foreach ( $rows as $row ) { |
140 | $id = UUID::create( $row->rev_id ); |
141 | $type = self::TYPES[$row->rev_type]; |
142 | $om = $this->storage->getStorage( $type ); |
143 | $obj = $om->get( $id ); |
144 | if ( $obj ) { |
145 | $om->merge( $obj ); |
146 | $ids[] = $row->rev_id; |
147 | $objs[] = $obj; |
148 | } else { |
149 | $this->error( __METHOD__ . ": Failed loading $type: " . $id->getAlphadecimal() ); |
150 | } |
151 | } |
152 | if ( !$ids ) { |
153 | return null; |
154 | } |
155 | |
156 | $dbw->newUpdateQueryBuilder() |
157 | ->update( 'flow_revision' ) |
158 | ->set( [ "{$columnPrefix}_ip" => null ] ) |
159 | ->where( [ 'rev_id' => $ids ] ) |
160 | ->caller( __METHOD__ ) |
161 | ->execute(); |
162 | |
163 | foreach ( $objs as $obj ) { |
164 | $this->storage->cachePurge( $obj ); |
165 | } |
166 | |
167 | $this->completeCount += count( $ids ); |
168 | |
169 | return end( $ids ); |
170 | } |
171 | |
172 | /** |
173 | * Get the update key name to go in the update log table |
174 | * |
175 | * @return string |
176 | */ |
177 | protected function getUpdateKey() { |
178 | return 'FlowFixUserIp'; |
179 | } |
180 | } |
181 | |
182 | $maintClass = FlowFixUserIp::class; |
183 | require_once RUN_MAINTENANCE_IF_MAIN; |