5use Wikimedia\TestingAccessWrapper;
15 'revision_actor_temp',
38 if ( $exceptionMsg !==
null ) {
39 $this->fail(
'Expected exception not thrown' );
41 $this->assertInstanceOf( ActorMigration::class, $m );
42 }
catch ( InvalidArgumentException $ex ) {
43 $this->assertSame( $exceptionMsg, $ex->getMessage() );
49 [ 0,
'$stage must include a write mode' ],
58 'Cannot read the new schema without also writing it'
65 'Cannot read the old schema without also writing it'
85 $result = $m->getJoin( $key );
86 $this->assertEquals( $expect, $result );
91 'Simple table, old' => [
95 'rc_user' =>
'rc_user',
96 'rc_user_text' =>
'rc_user_text',
102 'Simple table, read-old' => [
106 'rc_user' =>
'rc_user',
107 'rc_user_text' =>
'rc_user_text',
108 'rc_actor' =>
'NULL',
113 'Simple table, read-new' => [
115 'tables' => [
'actor_rc_user' =>
'actor' ],
117 'rc_user' =>
'actor_rc_user.actor_user',
118 'rc_user_text' =>
'actor_rc_user.actor_name',
119 'rc_actor' =>
'rc_actor',
122 'actor_rc_user' => [
'JOIN',
'actor_rc_user.actor_id = rc_actor' ],
126 'Simple table, new' => [
128 'tables' => [
'actor_rc_user' =>
'actor' ],
130 'rc_user' =>
'actor_rc_user.actor_user',
131 'rc_user_text' =>
'actor_rc_user.actor_name',
132 'rc_actor' =>
'rc_actor',
135 'actor_rc_user' => [
'JOIN',
'actor_rc_user.actor_id = rc_actor' ],
144 'ipb_by' =>
'ipb_by',
145 'ipb_by_text' =>
'ipb_by_text',
146 'ipb_by_actor' =>
'NULL',
151 'ipblocks, read-old' => [
155 'ipb_by' =>
'ipb_by',
156 'ipb_by_text' =>
'ipb_by_text',
157 'ipb_by_actor' =>
'NULL',
162 'ipblocks, read-new' => [
164 'tables' => [
'actor_ipb_by' =>
'actor' ],
166 'ipb_by' =>
'actor_ipb_by.actor_user',
167 'ipb_by_text' =>
'actor_ipb_by.actor_name',
168 'ipb_by_actor' =>
'ipb_by_actor',
171 'actor_ipb_by' => [
'JOIN',
'actor_ipb_by.actor_id = ipb_by_actor' ],
177 'tables' => [
'actor_ipb_by' =>
'actor' ],
179 'ipb_by' =>
'actor_ipb_by.actor_user',
180 'ipb_by_text' =>
'actor_ipb_by.actor_name',
181 'ipb_by_actor' =>
'ipb_by_actor',
184 'actor_ipb_by' => [
'JOIN',
'actor_ipb_by.actor_id = ipb_by_actor' ],
193 'rev_user' =>
'rev_user',
194 'rev_user_text' =>
'rev_user_text',
195 'rev_actor' =>
'NULL',
200 'Revision, read-old' => [
204 'rev_user' =>
'rev_user',
205 'rev_user_text' =>
'rev_user_text',
206 'rev_actor' =>
'NULL',
211 'Revision, read-new' => [
214 'temp_rev_user' =>
'revision_actor_temp',
215 'actor_rev_user' =>
'actor',
218 'rev_user' =>
'actor_rev_user.actor_user',
219 'rev_user_text' =>
'actor_rev_user.actor_name',
220 'rev_actor' =>
'temp_rev_user.revactor_actor',
223 'temp_rev_user' => [
'JOIN',
'temp_rev_user.revactor_rev = rev_id' ],
224 'actor_rev_user' => [
'JOIN',
'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
231 'temp_rev_user' =>
'revision_actor_temp',
232 'actor_rev_user' =>
'actor',
235 'rev_user' =>
'actor_rev_user.actor_user',
236 'rev_user_text' =>
'actor_rev_user.actor_name',
237 'rev_actor' =>
'temp_rev_user.revactor_actor',
240 'temp_rev_user' => [
'JOIN',
'temp_rev_user.revactor_rev = rev_id' ],
241 'actor_rev_user' => [
'JOIN',
'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
257 $expect[
'conds'] =
'(' . implode(
') OR (', $expect[
'orconds'] ) .
')';
259 if ( count(
$users ) === 1 ) {
264 $result = $m->getWhere( $this->db, $key,
$users, $useId );
265 $this->assertEquals( $expect, $result );
269 $makeUserIdentity =
function ( $id,
$name, $actor ) {
270 $u = $this->getMock( UserIdentity::class );
271 $u->method(
'getId' )->willReturn( $id );
272 $u->method(
'getName' )->willReturn( $name );
273 $u->method(
'getActorId' )->willReturn( $actor );
277 $genericUser = [ $makeUserIdentity( 1,
'User1', 11 ) ];
278 $complicatedUsers = [
279 $makeUserIdentity( 1,
'User1', 11 ),
280 $makeUserIdentity( 2,
'User2', 12 ),
281 $makeUserIdentity( 3,
'User3', 0 ),
282 $makeUserIdentity( 0,
'192.168.12.34', 34 ),
283 $makeUserIdentity( 0,
'192.168.12.35', 0 ),
287 'Simple table, old' => [
290 'orconds' => [
'userid' =>
"rc_user = '1'" ],
294 'Simple table, read-old' => [
297 'orconds' => [
'userid' =>
"rc_user = '1'" ],
301 'Simple table, read-new' => [
304 'orconds' => [
'actor' =>
"rc_actor = '11'" ],
308 'Simple table, new' => [
311 'orconds' => [
'actor' =>
"rc_actor = '11'" ],
319 'orconds' => [
'userid' =>
"ipb_by = '1'" ],
323 'ipblocks, read-old' => [
326 'orconds' => [
'userid' =>
"ipb_by = '1'" ],
330 'ipblocks, read-new' => [
333 'orconds' => [
'actor' =>
"ipb_by_actor = '11'" ],
340 'orconds' => [
'actor' =>
"ipb_by_actor = '11'" ],
348 'orconds' => [
'userid' =>
"rev_user = '1'" ],
352 'Revision, read-old' => [
355 'orconds' => [
'userid' =>
"rev_user = '1'" ],
359 'Revision, read-new' => [
362 'temp_rev_user' =>
'revision_actor_temp',
364 'orconds' => [
'actor' =>
"temp_rev_user.revactor_actor = '11'" ],
366 'temp_rev_user' => [
'JOIN',
'temp_rev_user.revactor_rev = rev_id' ],
373 'temp_rev_user' =>
'revision_actor_temp',
375 'orconds' => [
'actor' =>
"temp_rev_user.revactor_actor = '11'" ],
377 'temp_rev_user' => [
'JOIN',
'temp_rev_user.revactor_rev = rev_id' ],
382 'Multiple users, old' => [
386 'userid' =>
"rc_user IN ('1','2','3') ",
387 'username' =>
"rc_user_text IN ('192.168.12.34','192.168.12.35') "
392 'Multiple users, read-old' => [
396 'userid' =>
"rc_user IN ('1','2','3') ",
397 'username' =>
"rc_user_text IN ('192.168.12.34','192.168.12.35') "
402 'Multiple users, read-new' => [
405 'orconds' => [
'actor' =>
"rc_actor IN ('11','12','34') " ],
409 'Multiple users, new' => [
412 'orconds' => [
'actor' =>
"rc_actor IN ('11','12','34') " ],
417 'Multiple users, no use ID, old' => [
421 'username' =>
"rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
426 'Multiple users, read-old' => [
430 'username' =>
"rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
435 'Multiple users, read-new' => [
438 'orconds' => [
'actor' =>
"rc_actor IN ('11','12','34') " ],
442 'Multiple users, new' => [
445 'orconds' => [
'actor' =>
"rc_actor IN ('11','12','34') " ],
461 $user = $this->getMock( UserIdentity::class );
462 $user->method(
'getId' )->willReturn( $u->getId() );
463 $user->method(
'getName' )->willReturn( $u->getName() );
464 if ( $u->getActorId( $this->db ) ) {
465 $user->method(
'getActorId' )->willReturn( $u->getActorId() );
469 [
'actor_user' => $u->getId(),
'actor_name' => $u->getName() ],
472 $user->method(
'getActorId' )->willReturn( $this->db->insertId() );
505 $nameKey = $key .
'_text';
506 $actorKey = $key ===
'ipb_by' ?
'ipb_by_actor' : substr( $key, 0, -5 ) .
'_actor';
508 foreach ( $stages as $writeStage => $possibleReadStages ) {
509 if ( $key ===
'ipb_by' ) {
510 $extraFields[
'ipb_address'] = __CLASS__ .
"#{$stageNames[$writeStage]}";
514 $usesTemp = $key ===
'rev_user';
517 list( $fields, $callback ) = $w->getInsertValuesWithTempTable( $this->db, $key, $user );
519 $fields = $w->getInsertValues( $this->db, $key, $user );
523 $this->assertSame( $user->getId(), $fields[$key],
524 "old field, stage={$stageNames[$writeStage]}" );
525 $this->assertSame( $user->getName(), $fields[$nameKey],
526 "old field, stage={$stageNames[$writeStage]}" );
528 $this->assertArrayNotHasKey( $key, $fields,
"old field, stage={$stageNames[$writeStage]}" );
529 $this->assertArrayNotHasKey( $nameKey, $fields,
"old field, stage={$stageNames[$writeStage]}" );
532 $this->assertSame( $user->getActorId(), $fields[$actorKey],
533 "new field, stage={$stageNames[$writeStage]}" );
535 $this->assertArrayNotHasKey( $actorKey, $fields,
536 "new field, stage={$stageNames[$writeStage]}" );
539 $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
540 $id = $this->db->insertId();
542 $callback( $id, $extraFields );
545 foreach ( $possibleReadStages as $readStage ) {
548 $queryInfo = $r->getJoin( $key );
549 $row = $this->db->selectRow(
550 [ $table ] + $queryInfo[
'tables'],
551 $queryInfo[
'fields'],
558 $this->assertSame( $user->getId(), (
int)$row->$key,
559 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, id" );
560 $this->assertSame( $user->getName(), $row->$nameKey,
561 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, name" );
564 (int)$row->$actorKey,
565 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, actor"
580 'recentchanges' => [
'recentchanges',
'rc_user',
'rc_id', [
583 'rc_title' =>
'Test',
584 'rc_this_oldid' => 42,
585 'rc_last_oldid' => 41,
586 'rc_source' =>
'test',
588 'ipblocks' => [
'ipblocks',
'ipb_by',
'ipb_id', [
589 'ipb_range_start' =>
'',
590 'ipb_range_end' =>
'',
594 'revision' => [
'revision',
'rev_user',
'rev_id', [
620 $m->getInsertValues( $this->db,
'rev_user', $this->
getTestUser()->getUser() );
631 $m->getInsertValuesWithTempTable( $this->db,
'rc_user', $this->
getTestUser()->getUser() );
639 $wrap = TestingAccessWrapper::newFromClass( ActorMigration::class );
640 $wrap->formerTempTables += [
'rc_user' =>
'1.30' ];
642 $this->
hideDeprecated(
'ActorMigration::getInsertValuesWithTempTable for rc_user' );
644 list( $fields, $callback )
645 = $m->getInsertValuesWithTempTable( $this->db,
'rc_user', $this->
getTestUser()->getUser() );
646 $this->assertTrue( is_callable( $callback ) );
657 list( $fields, $callback )
658 = $m->getInsertValuesWithTempTable( $this->db,
'rev_user', $this->
getTestUser()->getUser() );
670 $userIdentity = $this->getMock( UserIdentity::class );
671 $userIdentity->method(
'getId' )->willReturn( $user->getId() );
672 $userIdentity->method(
'getName' )->willReturn( $user->getName() );
673 $userIdentity->method(
'getActorId' )->willReturn( 0 );
675 list( $cFields, $cCallback ) = MediaWikiServices::getInstance()->getCommentStore()
676 ->insertWithTempTable( $this->db,
'rev_comment',
'' );
678 list( $fields, $callback ) =
679 $m->getInsertValuesWithTempTable( $this->db,
'rev_user', $userIdentity );
684 'rev_timestamp' => $this->db->timestamp(),
686 $this->db->insert(
'revision', $extraFields + $fields, __METHOD__ );
687 $id = $this->db->insertId();
688 $callback( $id, $extraFields );
691 $qi = $m->getJoin(
'rev_user' );
692 $row = $this->db->selectRow(
693 [
'revision' ] + $qi[
'tables'], $qi[
'fields'], [
'rev_id' => $id ], __METHOD__, [], $qi[
'joins']
695 $this->assertSame( $user->getId(), (
int)$row->rev_user );
696 $this->assertSame( $user->getName(), $row->rev_user_text );
697 $this->assertSame( $user->getActorId(), (
int)$row->rev_actor );
700 $fields = $m->getInsertValues( $this->db,
'dummy_user', $userIdentity );
701 $this->assertSame( $user->getId(), $fields[
'dummy_user'] );
702 $this->assertSame( $user->getName(), $fields[
'dummy_user_text'] );
703 $this->assertSame( $user->getActorId(), $fields[
'dummy_actor'] );
707 $m = ActorMigration::newMigration();
708 $this->assertInstanceOf( ActorMigration::class, $m );
709 $this->assertSame( $m, ActorMigration::newMigration() );
720 $this->assertSame( $isAnon, $m->isAnon(
'foo' ) );
721 $this->assertSame( $isNotAnon, $m->isNotAnon(
'foo' ) );
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
static provideConstructor()
makeMigration( $stage)
Create an ActorMigration for a particular stage.
testGetWhere( $stage, $key, $users, $useId, $expect)
provideGetWhere
static provideInsertRoundTrip()
testInsertWithTempTableCallbackMissingFields( $stage)
provideStages
testGetJoin( $stage, $key, $expect)
provideGetJoin
testIsAnon( $stage, $isAnon, $isNotAnon)
provideIsAnon
testConstructor( $stage, $exceptionMsg)
provideConstructor
testInsertWithTempTableDeprecated( $stage)
provideStages
testInsertWithTempTableWrong( $stage)
provideStages
testInsertWrong( $stage)
provideStages
testInsertRoundTrip( $table, $key, $pk, $extraFields)
provideInsertRoundTrip
This class handles the logic for the actor table migration.
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Allows to change the fields on the form that will be generated $name
const SCHEMA_COMPAT_WRITE_BOTH
const SCHEMA_COMPAT_READ_NEW
const SCHEMA_COMPAT_READ_BOTH
const SCHEMA_COMPAT_WRITE_OLD
const SCHEMA_COMPAT_READ_OLD
const SCHEMA_COMPAT_WRITE_NEW