<?php
use MediaWiki\MediaWikiServices;
+use MediaWiki\Storage\MutableRevisionRecord;
use MediaWiki\Storage\RevisionStore;
use MediaWiki\Storage\IncompleteRevisionException;
use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\SlotRecord;
/**
* RevisionDbTestBase contains test cases for the Revision class that have Database interactions.
]
);
- $this->setMwGlobals( 'wgContentHandlerUseDB', $this->getContentHandlerUseDB() );
- $this->setMwGlobals(
- 'wgMultiContentRevisionSchemaMigrationStage',
- $this->getMcrMigrationStage()
- );
+ $this->setMwGlobals( [
+ 'wgMultiContentRevisionSchemaMigrationStage' => $this->getMcrMigrationStage(),
+ 'wgContentHandlerUseDB' => $this->getContentHandlerUseDB(),
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ] );
$this->overrideMwServices();
}
}
+ /**
+ * @param string $model
+ * @return Title
+ */
+ protected function getMockTitle() {
+ $mock = $this->getMockBuilder( Title::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mock->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( $this->getDefaultWikitextNS() ) );
+ $mock->expects( $this->any() )
+ ->method( 'getPrefixedText' )
+ ->will( $this->returnValue( __CLASS__ ) );
+ $mock->expects( $this->any() )
+ ->method( 'getDBkey' )
+ ->will( $this->returnValue( __CLASS__ ) );
+ $mock->expects( $this->any() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 23 ) );
+
+ return $mock;
+ }
+
abstract protected function getContentHandlerUseDB();
private function makeRevisionWithProps( $props = null ) {
);
}
+ public function provideGetTextId() {
+ yield [ [], null ];
+
+ $slot = new SlotRecord( (object)[
+ 'slot_revision_id' => 42,
+ 'slot_content_id' => 1,
+ 'content_address' => 'tt:789',
+ 'model_name' => CONTENT_MODEL_WIKITEXT,
+ 'role_name' => 'main',
+ 'slot_origin' => 1,
+ ], new WikitextContent( 'Test' ) );
+
+ $rec = new MutableRevisionRecord( $this->testPage->getTitle() );
+ $rec->setId( 42 );
+ $rec->setSlot( $slot );
+
+ yield [ $rec, 789 ];
+ }
+
+ /**
+ * @dataProvider provideGetTextId
+ * @covers Revision::getTextId()
+ */
+ public function testGetTextId( $spec, $expected ) {
+ $rev = new Revision( $spec, 0, $this->testPage->getTitle() );
+ $this->assertSame( $expected, $rev->getTextId() );
+ }
+
}
<?php
+
+use MediaWiki\Storage\MutableRevisionRecord;
+use MediaWiki\Storage\SlotRecord;
use MediaWiki\Tests\Storage\McrSchemaOverride;
/**
return true;
}
+ public function provideGetTextId() {
+ yield [ [], null ];
+
+ $slot = new SlotRecord( (object)[
+ 'slot_revision_id' => 42,
+ 'slot_content_id' => 1,
+ 'content_address' => 'tt:789',
+ 'model_name' => CONTENT_MODEL_WIKITEXT,
+ 'role_name' => 'main',
+ 'slot_origin' => 1,
+ ], new WikitextContent( 'Test' ) );
+
+ $rec = new MutableRevisionRecord( $this->getMockTitle() );
+ $rec->setId( 42 );
+ $rec->setSlot( $slot );
+
+ yield [ $rec, 789 ];
+ }
+
}
<?php
+
+use MediaWiki\Storage\MutableRevisionRecord;
+use MediaWiki\Storage\SlotRecord;
use MediaWiki\Tests\Storage\McrReadNewSchemaOverride;
/**
return true;
}
+ public function provideGetTextId() {
+ yield [ [], null ];
+
+ $slot = new SlotRecord( (object)[
+ 'slot_revision_id' => 42,
+ 'slot_content_id' => 1,
+ 'content_address' => 'tt:789',
+ 'model_name' => CONTENT_MODEL_WIKITEXT,
+ 'role_name' => 'main',
+ 'slot_origin' => 1,
+ ], new WikitextContent( 'Test' ) );
+
+ $rec = new MutableRevisionRecord( $this->getMockTitle() );
+ $rec->setId( 42 );
+ $rec->setSlot( $slot );
+
+ yield [ $rec, 789 ];
+ }
+
}
return true;
}
+ public function provideGetTextId() {
+ yield [ [], null ];
+
+ $row = (object)[
+ 'rev_id' => 7,
+ 'rev_page' => 1, // should match actual page id
+ 'rev_text_id' => 789,
+ 'rev_timestamp' => '20180101000000',
+ 'rev_len' => 7,
+ 'rev_minor_edit' => 0,
+ 'rev_deleted' => 0,
+ 'rev_parent_id' => 0,
+ 'rev_sha1' => 'deadbeef',
+ 'rev_comment' => 'some comment',
+ 'rev_comment_text' => 'some comment',
+ 'rev_comment_data' => '{}',
+ 'rev_user' => 17,
+ 'rev_user_text' => 'some user',
+ ];
+
+ yield [ $row, 789 ];
+ }
+
}
<?php
+
use MediaWiki\Tests\Storage\PreMcrSchemaOverride;
/**
return false;
}
+ public function provideGetTextId() {
+ yield [ [], null ];
+
+ $row = (object)[
+ 'rev_id' => 7,
+ 'rev_page' => 1, // should match actual page id
+ 'rev_text_id' => 789,
+ 'rev_timestamp' => '20180101000000',
+ 'rev_len' => 7,
+ 'rev_minor_edit' => 0,
+ 'rev_deleted' => 0,
+ 'rev_parent_id' => 0,
+ 'rev_sha1' => 'deadbeef',
+ 'rev_comment' => 'some comment',
+ 'rev_comment_text' => 'some comment',
+ 'rev_comment_data' => '{}',
+ 'rev_user' => 17,
+ 'rev_user_text' => 'some user',
+ ];
+
+ yield [ $row, 789 ];
+ }
+
}
<?php
+
use MediaWiki\Tests\Storage\PreMcrSchemaOverride;
/**
return true;
}
+ public function provideGetTextId() {
+ yield [ [], null ];
+
+ $row = (object)[
+ 'rev_id' => 7,
+ 'rev_page' => 1, // should match actual page id
+ 'rev_text_id' => 789,
+ 'rev_timestamp' => '20180101000000',
+ 'rev_len' => 7,
+ 'rev_minor_edit' => 0,
+ 'rev_deleted' => 0,
+ 'rev_parent_id' => 0,
+ 'rev_sha1' => 'deadbeef',
+ 'rev_comment' => 'some comment',
+ 'rev_comment_text' => 'some comment',
+ 'rev_comment_data' => '{}',
+ 'rev_user' => 17,
+ 'rev_user_text' => 'some user',
+ ];
+
+ yield [ $row, 789 ];
+ }
+
}
public function setUp() {
parent::setUp();
- $this->setMwGlobals( 'wgMultiContentRevisionSchemaMigrationStage', MIGRATION_OLD );
+ $this->setMwGlobals(
+ 'wgMultiContentRevisionSchemaMigrationStage',
+ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
+ );
}
public function provideConstructFromArray() {
'content' => new WikitextContent( 'GOAT' ),
'text_id' => 'someid',
],
- new MWException( 'Text already stored in external store (id someid),' )
+ new MWException( 'The text_id field is only available in the pre-MCR schema' )
];
+
yield 'with bad content object (class)' => [
[ 'content' => new stdClass() ],
new MWException( 'content field must contain a Content object' )
[
'rev_id' => '42',
'rev_page' => '23',
- 'rev_text_id' => '2',
'rev_timestamp' => '20171017114835',
'rev_user_text' => '127.0.0.1',
'rev_user' => '0',
'rev_comment_text' => 'Goat Comment!',
'rev_comment_data' => null,
'rev_comment_cid' => null,
- 'rev_content_format' => 'GOATFORMAT',
- 'rev_content_model' => 'GOATMODEL',
],
function ( RevisionTest $testCase, Revision $rev ) {
$testCase->assertSame( 42, $rev->getId() );
$testCase->assertSame( 23, $rev->getPage() );
- $testCase->assertSame( 2, $rev->getTextId() );
$testCase->assertSame( '20171017114835', $rev->getTimestamp() );
$testCase->assertSame( '127.0.0.1', $rev->getUserText() );
$testCase->assertSame( 0, $rev->getUser() );
$testCase->assertSame( 1, $rev->getParentId() );
$testCase->assertSame( 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', $rev->getSha1() );
$testCase->assertSame( 'Goat Comment!', $rev->getComment() );
- $testCase->assertSame( 'GOATFORMAT', $rev->getContentFormat() );
- $testCase->assertSame( 'GOATMODEL', $rev->getContentModel() );
}
];
yield 'default field values' => [
[
'rev_id' => '42',
'rev_page' => '23',
- 'rev_text_id' => '2',
'rev_timestamp' => '20171017114835',
'rev_user_text' => '127.0.0.1',
'rev_user' => '0',
$testCase->assertSame( $rev->getComment(), 'Goat Comment!' );
$testCase->assertSame( false, $rev->isMinor(), 'minor edit' );
$testCase->assertSame( 0, $rev->getVisibility(), 'visibility flags' );
-
- // computed fields
- $testCase->assertNotNull( $rev->getSize(), 'size' );
- $testCase->assertNotNull( $rev->getSha1(), 'hash' );
-
- // NOTE: model and format will be detected based on the namespace of the (mock) title
- $testCase->assertSame( 'text/x-wiki', $rev->getContentFormat(), 'format' );
- $testCase->assertSame( 'wikitext', $rev->getContentModel(), 'model' );
}
];
}
* @covers Revision::__construct
* @covers \MediaWiki\Storage\RevisionStore::newMutableRevisionFromArray
*/
- public function testConstructFromRow( array $arrayData, $assertions ) {
- $data = 'Hello goat.'; // needs to match model and format
-
- $blobStore = $this->getMockBuilder( SqlBlobStore::class )
- ->disableOriginalConstructor()
- ->getMock();
-
- $blobStore->method( 'getBlob' )
- ->will( $this->returnValue( $data ) );
-
- $blobStore->method( 'getTextIdFromAddress' )
- ->will( $this->returnCallback(
- function ( $address ) {
- // Turn "tt:1234" into 12345.
- // Note that this must be functional so we can test getTextId().
- // Ideally, we'd un-mock getTextIdFromAddress and use its actual implementation.
- $parts = explode( ':', $address );
- return (int)array_pop( $parts );
- }
- ) );
-
- // Note override internal service, so RevisionStore uses it as well.
- $this->setService( 'BlobStoreFactory', $this->mockBlobStoreFactory( $blobStore ) );
-
+ public function testConstructFromRow( array $arrayData, callable $assertions ) {
$row = (object)$arrayData;
$rev = new Revision( $row, 0, $this->getMockTitle() );
$assertions( $this, $rev );
$this->assertEquals( $name, $rev->getUserText( Revision::RAW ) );
}
- public function provideGetTextId() {
- yield [ [], null ];
- yield [ [ 'text_id' => '123' ], 123 ];
- yield [ [ 'text_id' => 456 ], 456 ];
- }
-
- /**
- * @dataProvider provideGetTextId
- * @covers Revision::getTextId()
- */
- public function testGetTextId( $rowArray, $expected ) {
- $rev = new Revision( $rowArray, 0, $this->getMockTitle() );
- $this->assertSame( $expected, $rev->getTextId() );
- }
-
public function provideGetParentId() {
yield [ [], null ];
yield [ [ 'parent_id' => '123' ], 123 ];
$row = (object)[
'rev_id' => '42',
'rev_page' => $title->getArticleID(),
- 'rev_text_id' => '2',
'rev_timestamp' => '20171017114835',
'rev_user_text' => '127.0.0.1',
'rev_user' => '0',
$this->assertSame( 'AAAABBAAA', $cache->get( $cacheKey ) );
}
- /**
- * @covers Revision::userJoinCond
- */
- public function testUserJoinCond() {
- $this->hideDeprecated( 'Revision::userJoinCond' );
- $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', MIGRATION_OLD );
- $this->overrideMwServices();
- $this->assertEquals(
- [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
- Revision::userJoinCond()
- );
- }
-
- /**
- * @covers Revision::pageJoinCond
- */
- public function testPageJoinCond() {
- $this->hideDeprecated( 'Revision::pageJoinCond' );
- $this->assertEquals(
- [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
- Revision::pageJoinCond()
- );
- }
-
- private function overrideCommentStoreAndActorMigration() {
- $mockStore = $this->getMockBuilder( CommentStore::class )
- ->disableOriginalConstructor()
- ->getMock();
- $mockStore->expects( $this->any() )
- ->method( 'getFields' )
- ->willReturn( [ 'commentstore' => 'fields' ] );
- $mockStore->expects( $this->any() )
- ->method( 'getJoin' )
- ->willReturn( [
- 'tables' => [ 'commentstore' => 'table' ],
- 'fields' => [ 'commentstore' => 'field' ],
- 'joins' => [ 'commentstore' => 'join' ],
- ] );
- $this->setService( 'CommentStore', $mockStore );
-
- $mockStore = $this->getMockBuilder( ActorMigration::class )
- ->disableOriginalConstructor()
- ->getMock();
- $mockStore->expects( $this->any() )
- ->method( 'getJoin' )
- ->willReturnCallback( function ( $key ) {
- $p = strtok( $key, '_' );
- return [
- 'tables' => [ 'actormigration' => 'table' ],
- 'fields' => [
- $p . '_user' => 'actormigration_user',
- $p . '_user_text' => 'actormigration_user_text',
- $p . '_actor' => 'actormigration_actor',
- ],
- 'joins' => [ 'actormigration' => 'join' ],
- ];
- } );
- $this->setService( 'ActorMigration', $mockStore );
- }
-
- public function provideSelectFields() {
- yield [
- true,
- [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_user_text',
- 'rev_user',
- 'rev_actor' => 'NULL',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'fields',
- 'rev_content_format',
- 'rev_content_model',
- ]
- ];
- yield [
- false,
- [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_user_text',
- 'rev_user',
- 'rev_actor' => 'NULL',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'fields',
- ]
- ];
- }
-
- /**
- * @dataProvider provideSelectFields
- * @covers Revision::selectFields
- */
- public function testSelectFields( $contentHandlerUseDB, $expected ) {
- $this->hideDeprecated( 'Revision::selectFields' );
- $this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB );
- $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', MIGRATION_OLD );
- $this->overrideCommentStoreAndActorMigration();
- $this->assertEquals( $expected, Revision::selectFields() );
- }
-
- public function provideSelectArchiveFields() {
- yield [
- true,
- [
- 'ar_id',
- 'ar_page_id',
- 'ar_rev_id',
- 'ar_text_id',
- 'ar_timestamp',
- 'ar_user_text',
- 'ar_user',
- 'ar_actor' => 'NULL',
- 'ar_minor_edit',
- 'ar_deleted',
- 'ar_len',
- 'ar_parent_id',
- 'ar_sha1',
- 'commentstore' => 'fields',
- 'ar_content_format',
- 'ar_content_model',
- ]
- ];
- yield [
- false,
- [
- 'ar_id',
- 'ar_page_id',
- 'ar_rev_id',
- 'ar_text_id',
- 'ar_timestamp',
- 'ar_user_text',
- 'ar_user',
- 'ar_actor' => 'NULL',
- 'ar_minor_edit',
- 'ar_deleted',
- 'ar_len',
- 'ar_parent_id',
- 'ar_sha1',
- 'commentstore' => 'fields',
- ]
- ];
- }
-
- /**
- * @dataProvider provideSelectArchiveFields
- * @covers Revision::selectArchiveFields
- */
- public function testSelectArchiveFields( $contentHandlerUseDB, $expected ) {
- $this->hideDeprecated( 'Revision::selectArchiveFields' );
- $this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB );
- $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', MIGRATION_OLD );
- $this->overrideCommentStoreAndActorMigration();
- $this->assertEquals( $expected, Revision::selectArchiveFields() );
- }
-
- /**
- * @covers Revision::selectTextFields
- */
- public function testSelectTextFields() {
- $this->hideDeprecated( 'Revision::selectTextFields' );
- $this->assertEquals(
- [
- 'old_text',
- 'old_flags',
- ],
- Revision::selectTextFields()
- );
- }
-
- /**
- * @covers Revision::selectPageFields
- */
- public function testSelectPageFields() {
- $this->hideDeprecated( 'Revision::selectPageFields' );
- $this->assertEquals(
- [
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- ],
- Revision::selectPageFields()
- );
- }
-
- /**
- * @covers Revision::selectUserFields
- */
- public function testSelectUserFields() {
- $this->hideDeprecated( 'Revision::selectUserFields' );
- $this->assertEquals(
- [
- 'user_name',
- ],
- Revision::selectUserFields()
- );
- }
-
- public function provideGetArchiveQueryInfo() {
- yield 'wgContentHandlerUseDB false' => [
- [
- 'wgContentHandlerUseDB' => false,
- ],
- [
- 'tables' => [
- 'archive',
- 'commentstore' => 'table',
- 'actormigration' => 'table',
- ],
- 'fields' => [
- 'ar_id',
- 'ar_page_id',
- 'ar_namespace',
- 'ar_title',
- 'ar_rev_id',
- 'ar_text_id',
- 'ar_timestamp',
- 'ar_minor_edit',
- 'ar_deleted',
- 'ar_len',
- 'ar_parent_id',
- 'ar_sha1',
- 'commentstore' => 'field',
- 'ar_user' => 'actormigration_user',
- 'ar_user_text' => 'actormigration_user_text',
- 'ar_actor' => 'actormigration_actor',
- ],
- 'joins' => [ 'commentstore' => 'join', 'actormigration' => 'join' ],
- ]
- ];
- yield 'wgContentHandlerUseDB true' => [
- [
- 'wgContentHandlerUseDB' => true,
- ],
- [
- 'tables' => [
- 'archive',
- 'commentstore' => 'table',
- 'actormigration' => 'table',
- ],
- 'fields' => [
- 'ar_id',
- 'ar_page_id',
- 'ar_namespace',
- 'ar_title',
- 'ar_rev_id',
- 'ar_text_id',
- 'ar_timestamp',
- 'ar_minor_edit',
- 'ar_deleted',
- 'ar_len',
- 'ar_parent_id',
- 'ar_sha1',
- 'commentstore' => 'field',
- 'ar_user' => 'actormigration_user',
- 'ar_user_text' => 'actormigration_user_text',
- 'ar_actor' => 'actormigration_actor',
- 'ar_content_format',
- 'ar_content_model',
- ],
- 'joins' => [ 'commentstore' => 'join', 'actormigration' => 'join' ],
- ]
- ];
- }
-
- /**
- * @covers Revision::getArchiveQueryInfo
- * @dataProvider provideGetArchiveQueryInfo
- */
- public function testGetArchiveQueryInfo( $globals, $expected ) {
- $this->setMwGlobals( $globals );
- $this->overrideCommentStoreAndActorMigration();
-
- $revisionStore = $this->getRevisionStore();
- $revisionStore->setContentHandlerUseDB( $globals['wgContentHandlerUseDB'] );
- $this->setService( 'RevisionStore', $revisionStore );
-
- $queryInfo = Revision::getArchiveQueryInfo();
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['tables'],
- $queryInfo['tables']
- );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['fields'],
- $queryInfo['fields']
- );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['joins'],
- $queryInfo['joins']
- );
- }
-
- /**
- * Assert that the two arrays passed are equal, ignoring the order of the values that integer
- * keys.
- *
- * Note: Failures of this assertion can be slightly confusing as the arrays are actually
- * split into a string key array and an int key array before assertions occur.
- *
- * @param array $expected
- * @param array $actual
- */
- private function assertArrayEqualsIgnoringIntKeyOrder( array $expected, array $actual ) {
- $this->objectAssociativeSort( $expected );
- $this->objectAssociativeSort( $actual );
-
- // Separate the int key values from the string key values so that assertion failures are
- // easier to understand.
- $expectedIntKeyValues = [];
- $actualIntKeyValues = [];
-
- // Remove all int keys and re add them at the end after sorting by value
- // This will result in all int keys being in the same order with same ints at the end of
- // the array
- foreach ( $expected as $key => $value ) {
- if ( is_int( $key ) ) {
- unset( $expected[$key] );
- $expectedIntKeyValues[] = $value;
- }
- }
- foreach ( $actual as $key => $value ) {
- if ( is_int( $key ) ) {
- unset( $actual[$key] );
- $actualIntKeyValues[] = $value;
- }
- }
-
- $this->assertArrayEquals( $expected, $actual, false, true );
- $this->assertArrayEquals( $expectedIntKeyValues, $actualIntKeyValues, false, true );
- }
-
- public function provideGetQueryInfo() {
- yield 'wgContentHandlerUseDB false, opts none' => [
- [
- 'wgContentHandlerUseDB' => false,
- ],
- [],
- [
- 'tables' => [ 'revision', 'commentstore' => 'table', 'actormigration' => 'table' ],
- 'fields' => [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'field',
- 'rev_user' => 'actormigration_user',
- 'rev_user_text' => 'actormigration_user_text',
- 'rev_actor' => 'actormigration_actor',
- ],
- 'joins' => [ 'commentstore' => 'join', 'actormigration' => 'join' ],
- ],
- ];
- yield 'wgContentHandlerUseDB false, opts page' => [
- [
- 'wgContentHandlerUseDB' => false,
- ],
- [ 'page' ],
- [
- 'tables' => [ 'revision', 'commentstore' => 'table', 'actormigration' => 'table', 'page' ],
- 'fields' => [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'field',
- 'rev_user' => 'actormigration_user',
- 'rev_user_text' => 'actormigration_user_text',
- 'rev_actor' => 'actormigration_actor',
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- ],
- 'joins' => [
- 'page' => [
- 'INNER JOIN',
- [ 'page_id = rev_page' ],
- ],
- 'commentstore' => 'join',
- 'actormigration' => 'join',
- ],
- ],
- ];
- yield 'wgContentHandlerUseDB false, opts user' => [
- [
- 'wgContentHandlerUseDB' => false,
- ],
- [ 'user' ],
- [
- 'tables' => [ 'revision', 'commentstore' => 'table', 'actormigration' => 'table', 'user' ],
- 'fields' => [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'field',
- 'rev_user' => 'actormigration_user',
- 'rev_user_text' => 'actormigration_user_text',
- 'rev_actor' => 'actormigration_actor',
- 'user_name',
- ],
- 'joins' => [
- 'user' => [
- 'LEFT JOIN',
- [
- 'actormigration_user != 0',
- 'user_id = actormigration_user',
- ],
- ],
- 'commentstore' => 'join',
- 'actormigration' => 'join',
- ],
- ],
- ];
- yield 'wgContentHandlerUseDB false, opts text' => [
- [
- 'wgContentHandlerUseDB' => false,
- ],
- [ 'text' ],
- [
- 'tables' => [ 'revision', 'commentstore' => 'table', 'actormigration' => 'table', 'text' ],
- 'fields' => [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'field',
- 'rev_user' => 'actormigration_user',
- 'rev_user_text' => 'actormigration_user_text',
- 'rev_actor' => 'actormigration_actor',
- 'old_text',
- 'old_flags',
- ],
- 'joins' => [
- 'text' => [
- 'INNER JOIN',
- [ 'rev_text_id=old_id' ],
- ],
- 'commentstore' => 'join',
- 'actormigration' => 'join',
- ],
- ],
- ];
- yield 'wgContentHandlerUseDB false, opts 3' => [
- [
- 'wgContentHandlerUseDB' => false,
- ],
- [ 'text', 'page', 'user' ],
- [
- 'tables' => [
- 'revision', 'commentstore' => 'table', 'actormigration' => 'table', 'page', 'user', 'text'
- ],
- 'fields' => [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'field',
- 'rev_user' => 'actormigration_user',
- 'rev_user_text' => 'actormigration_user_text',
- 'rev_actor' => 'actormigration_actor',
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- 'user_name',
- 'old_text',
- 'old_flags',
- ],
- 'joins' => [
- 'page' => [
- 'INNER JOIN',
- [ 'page_id = rev_page' ],
- ],
- 'user' => [
- 'LEFT JOIN',
- [
- 'actormigration_user != 0',
- 'user_id = actormigration_user',
- ],
- ],
- 'text' => [
- 'INNER JOIN',
- [ 'rev_text_id=old_id' ],
- ],
- 'commentstore' => 'join',
- 'actormigration' => 'join',
- ],
- ],
- ];
- yield 'wgContentHandlerUseDB true, opts none' => [
- [
- 'wgContentHandlerUseDB' => true,
- ],
- [],
- [
- 'tables' => [ 'revision', 'commentstore' => 'table', 'actormigration' => 'table' ],
- 'fields' => [
- 'rev_id',
- 'rev_page',
- 'rev_text_id',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- 'commentstore' => 'field',
- 'rev_user' => 'actormigration_user',
- 'rev_user_text' => 'actormigration_user_text',
- 'rev_actor' => 'actormigration_actor',
- 'rev_content_format',
- 'rev_content_model',
- ],
- 'joins' => [ 'commentstore' => 'join', 'actormigration' => 'join' ],
- ],
- ];
- }
-
- /**
- * @covers Revision::getQueryInfo
- * @dataProvider provideGetQueryInfo
- */
- public function testGetQueryInfo( $globals, $options, $expected ) {
- $this->setMwGlobals( $globals );
- $this->overrideCommentStoreAndActorMigration();
-
- $revisionStore = $this->getRevisionStore();
- $revisionStore->setContentHandlerUseDB( $globals['wgContentHandlerUseDB'] );
- $this->setService( 'RevisionStore', $revisionStore );
-
- $queryInfo = Revision::getQueryInfo( $options );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['tables'],
- $queryInfo['tables']
- );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['fields'],
- $queryInfo['fields']
- );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['joins'],
- $queryInfo['joins']
- );
- }
-
/**
* @covers Revision::getSize
*/
$this->assertFalse( array_key_exists( 'a_slot_data', $queryInfo['joins'] ) );
}
- public function provideGetArchiveQueryInfo() {
- yield [
- [
- 'tables' => [
- 'archive',
- ],
- 'fields' => array_merge(
- $this->getDefaultArchiveFields( false ),
- [
- 'ar_comment_text' => 'ar_comment',
- 'ar_comment_data' => 'NULL',
- 'ar_comment_cid' => 'NULL',
- 'ar_user_text' => 'ar_user_text',
- 'ar_user' => 'ar_user',
- 'ar_actor' => 'NULL',
- ]
- ),
- 'joins' => [
- ],
- ]
- ];
- }
-
- public function provideGetQueryInfo() {
- // TODO: more option variations
- yield [
- [ 'page', 'user' ],
- [
- 'tables' => [
- 'revision',
- 'page',
- 'user',
- ],
- 'fields' => array_merge(
- $this->getDefaultQueryFields( false ),
- $this->getCommentQueryFields(),
- $this->getActorQueryFields(),
- [
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- 'user_name',
- ]
- ),
- 'joins' => [
- 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
- 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
- ],
- ]
- ];
- }
-
- public function provideGetSlotsQueryInfo() {
- yield 'no options' => [
- [],
- [
- 'tables' => [
- 'slots'
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- ],
- 'joins' => [],
- ]
- ];
- yield 'role option' => [
- [ 'role' ],
- [
- 'tables' => [
- 'slots',
- 'slot_roles',
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- 'role_name',
- ],
- 'joins' => [
- 'slot_roles' => [ 'LEFT JOIN', [ 'slot_role_id = role_id' ] ],
- ],
- ]
- ];
- yield 'content option' => [
- [ 'content' ],
- [
- 'tables' => [
- 'slots',
- 'content',
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- 'content_size',
- 'content_sha1',
- 'content_address',
- 'content_model',
- ],
- 'joins' => [
- 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
- ],
- ]
- ];
- yield 'content and model options' => [
- [ 'content', 'model' ],
- [
- 'tables' => [
- 'slots',
- 'content',
- 'content_models',
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- 'content_size',
- 'content_sha1',
- 'content_address',
- 'content_model',
- 'model_name',
- ],
- 'joins' => [
- 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
- 'content_models' => [ 'LEFT JOIN', [ 'content_model = model_id' ] ],
- ],
- ]
- ];
- }
-
public function provideNewMutableRevisionFromArray() {
foreach ( parent::provideNewMutableRevisionFromArray() as $case ) {
yield $case;
$this->assertFalse( array_key_exists( 'a_slot_data', $queryInfo['joins'] ) );
}
- public function provideGetArchiveQueryInfo() {
- yield [
- [
- 'tables' => [
- 'archive',
- ],
- 'fields' => array_merge(
- $this->getDefaultArchiveFields( false ),
- [
- 'ar_comment_text' => 'ar_comment',
- 'ar_comment_data' => 'NULL',
- 'ar_comment_cid' => 'NULL',
- 'ar_user_text' => 'ar_user_text',
- 'ar_user' => 'ar_user',
- 'ar_actor' => 'NULL',
- ]
- ),
- 'joins' => [
- ],
- ]
- ];
- }
-
- public function provideGetQueryInfo() {
- // TODO: more option variations
- yield [
- [ 'page', 'user' ],
- [
- 'tables' => [
- 'revision',
- 'page',
- 'user',
- ],
- 'fields' => array_merge(
- $this->getDefaultQueryFields( false ),
- $this->getCommentQueryFields(),
- $this->getActorQueryFields(),
- [
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- 'user_name',
- ]
- ),
- 'joins' => [
- 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
- 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
- ],
- ]
- ];
- }
-
- public function provideGetSlotsQueryInfo() {
- yield 'no options' => [
- [],
- [
- 'tables' => [
- 'slots'
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- ],
- 'joins' => [],
- ]
- ];
- yield 'role option' => [
- [ 'role' ],
- [
- 'tables' => [
- 'slots',
- 'slot_roles',
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- 'role_name',
- ],
- 'joins' => [
- 'slot_roles' => [ 'LEFT JOIN', [ 'slot_role_id = role_id' ] ],
- ],
- ]
- ];
- yield 'content option' => [
- [ 'content' ],
- [
- 'tables' => [
- 'slots',
- 'content',
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- 'content_size',
- 'content_sha1',
- 'content_address',
- 'content_model',
- ],
- 'joins' => [
- 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
- ],
- ]
- ];
- yield 'content and model options' => [
- [ 'content', 'model' ],
- [
- 'tables' => [
- 'slots',
- 'content',
- 'content_models',
- ],
- 'fields' => [
- 'slot_revision_id',
- 'slot_content_id',
- 'slot_origin',
- 'slot_role_id',
- 'content_size',
- 'content_sha1',
- 'content_address',
- 'content_model',
- 'model_name',
- ],
- 'joins' => [
- 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
- 'content_models' => [ 'LEFT JOIN', [ 'content_model = model_id' ] ],
- ],
- ]
- ];
- }
-
/**
* @covers \MediaWiki\Storage\RevisionStore::insertRevisionOn
* @covers \MediaWiki\Storage\RevisionStore::insertSlotRowOn
}
}
- public function provideGetArchiveQueryInfo() {
- yield [
- [
- 'tables' => [ 'archive' ],
- 'fields' => array_merge(
- $this->getDefaultArchiveFields(),
- [
- 'ar_comment_text' => 'ar_comment',
- 'ar_comment_data' => 'NULL',
- 'ar_comment_cid' => 'NULL',
- 'ar_user_text' => 'ar_user_text',
- 'ar_user' => 'ar_user',
- 'ar_actor' => 'NULL',
- 'ar_content_format',
- 'ar_content_model',
- ]
- ),
- 'joins' => [],
- ]
- ];
- }
-
- public function provideGetQueryInfo() {
- yield [
- [],
- [
- 'tables' => [ 'revision' ],
- 'fields' => array_merge(
- $this->getDefaultQueryFields(),
- $this->getCommentQueryFields(),
- $this->getActorQueryFields(),
- $this->getContentHandlerQueryFields()
- ),
- 'joins' => [],
- ]
- ];
- yield [
- [ 'page', 'user' ],
- [
- 'tables' => [ 'revision', 'page', 'user' ],
- 'fields' => array_merge(
- $this->getDefaultQueryFields(),
- $this->getCommentQueryFields(),
- $this->getActorQueryFields(),
- $this->getContentHandlerQueryFields(),
- [
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- 'user_name',
- ]
- ),
- 'joins' => [
- 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
- 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
- ],
- ]
- ];
- }
-
- public function provideGetSlotsQueryInfo() {
- $db = wfGetDB( DB_REPLICA );
-
- yield [
- [],
- [
- 'tables' => [
- 'slots' => 'revision',
- ],
- 'fields' => array_merge(
- [
- 'slot_revision_id' => 'slots.rev_id',
- 'slot_content_id' => 'NULL',
- 'slot_origin' => 'slots.rev_id',
- 'role_name' => $db->addQuotes( 'main' ),
- ]
- ),
- 'joins' => [],
- ]
- ];
- yield [
- [ 'content' ],
- [
- 'tables' => [
- 'slots' => 'revision',
- ],
- 'fields' => array_merge(
- [
- 'slot_revision_id' => 'slots.rev_id',
- 'slot_content_id' => 'NULL',
- 'slot_origin' => 'slots.rev_id',
- 'role_name' => $db->addQuotes( 'main' ),
- 'content_size' => 'slots.rev_len',
- 'content_sha1' => 'slots.rev_sha1',
- 'content_address' => $db->buildConcat( [
- $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
- 'model_name' => 'slots.rev_content_model',
- ]
- ),
- 'joins' => [],
- ]
- ];
- }
-
public function provideInsertRevisionOn_failures() {
foreach ( parent::provideInsertRevisionOn_failures() as $case ) {
yield $case;
parent::assertRevisionExistsInDatabase( $rev );
}
- public function provideGetArchiveQueryInfo() {
- yield [
- [
- 'tables' => [ 'archive' ],
- 'fields' => array_merge(
- $this->getDefaultArchiveFields(),
- [
- 'ar_comment_text' => 'ar_comment',
- 'ar_comment_data' => 'NULL',
- 'ar_comment_cid' => 'NULL',
- 'ar_user_text' => 'ar_user_text',
- 'ar_user' => 'ar_user',
- 'ar_actor' => 'NULL',
- 'ar_content_format',
- 'ar_content_model',
- ]
- ),
- 'joins' => [],
- ]
- ];
- }
-
- public function provideGetQueryInfo() {
- yield [
- [],
- [
- 'tables' => [ 'revision' ],
- 'fields' => array_merge(
- $this->getDefaultQueryFields(),
- $this->getCommentQueryFields(),
- $this->getActorQueryFields(),
- $this->getContentHandlerQueryFields()
- ),
- 'joins' => [],
- ]
- ];
- yield [
- [ 'page', 'user', 'text' ],
- [
- 'tables' => [ 'revision', 'page', 'user', 'text' ],
- 'fields' => array_merge(
- $this->getDefaultQueryFields(),
- $this->getCommentQueryFields(),
- $this->getActorQueryFields(),
- $this->getContentHandlerQueryFields(),
- [
- 'page_namespace',
- 'page_title',
- 'page_id',
- 'page_latest',
- 'page_is_redirect',
- 'page_len',
- 'user_name',
- 'old_text',
- 'old_flags'
- ]
- ),
- 'joins' => [
- 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
- 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
- 'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ],
- ],
- ]
- ];
- }
-
- public function provideGetSlotsQueryInfo() {
- $db = wfGetDB( DB_REPLICA );
-
- yield [
- [],
- [
- 'tables' => [
- 'slots' => 'revision',
- ],
- 'fields' => array_merge(
- [
- 'slot_revision_id' => 'slots.rev_id',
- 'slot_content_id' => 'NULL',
- 'slot_origin' => 'slots.rev_id',
- 'role_name' => $db->addQuotes( 'main' ),
- ]
- ),
- 'joins' => [],
- ]
- ];
- yield [
- [ 'content' ],
- [
- 'tables' => [
- 'slots' => 'revision',
- ],
- 'fields' => array_merge(
- [
- 'slot_revision_id' => 'slots.rev_id',
- 'slot_content_id' => 'NULL',
- 'slot_origin' => 'slots.rev_id',
- 'role_name' => $db->addQuotes( 'main' ),
- 'content_size' => 'slots.rev_len',
- 'content_sha1' => 'slots.rev_sha1',
- 'content_address' =>
- $db->buildConcat( [ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
- 'model_name' => 'slots.rev_content_model',
- ]
- ),
- 'joins' => [],
- ]
- ];
- }
-
public function provideInsertRevisionOn_failures() {
foreach ( parent::provideInsertRevisionOn_failures() as $case ) {
yield $case;
--- /dev/null
+<?php
+namespace MediaWiki\Tests\Storage;
+
+use MediaWiki\MediaWikiServices;
+use MediaWikiTestCase;
+use Revision;
+
+/**
+ * Tests RevisionStore against the post-migration MCR DB schema.
+ *
+ * @group RevisionStore
+ * @group Storage
+ * @group Database
+ */
+class RevisionQueryInfoTest extends MediaWikiTestCase {
+
+ protected function getRevisionQueryFields( $returnTextIdField = true ) {
+ $fields = [
+ 'rev_id',
+ 'rev_page',
+ 'rev_timestamp',
+ 'rev_minor_edit',
+ 'rev_deleted',
+ 'rev_len',
+ 'rev_parent_id',
+ 'rev_sha1',
+ ];
+ if ( $returnTextIdField ) {
+ $fields[] = 'rev_text_id';
+ }
+ return $fields;
+ }
+
+ protected function getArchiveQueryFields( $returnTextFields = true ) {
+ $fields = [
+ 'ar_id',
+ 'ar_page_id',
+ 'ar_namespace',
+ 'ar_title',
+ 'ar_rev_id',
+ 'ar_timestamp',
+ 'ar_minor_edit',
+ 'ar_deleted',
+ 'ar_len',
+ 'ar_parent_id',
+ 'ar_sha1',
+ ];
+ if ( $returnTextFields ) {
+ $fields[] = 'ar_text_id';
+ }
+ return $fields;
+ }
+
+ protected function getOldCommentQueryFields( $prefix ) {
+ return [
+ "{$prefix}_comment_text" => "{$prefix}_comment",
+ "{$prefix}_comment_data" => 'NULL',
+ "{$prefix}_comment_cid" => 'NULL',
+ ];
+ }
+
+ protected function getCompatCommentQueryFields( $prefix ) {
+ return [
+ "{$prefix}_comment_text"
+ => "COALESCE( comment_{$prefix}_comment.comment_text, {$prefix}_comment )",
+ "{$prefix}_comment_data" => "comment_{$prefix}_comment.comment_data",
+ "{$prefix}_comment_cid" => "comment_{$prefix}_comment.comment_id",
+ ];
+ }
+
+ protected function getNewCommentQueryFields( $prefix ) {
+ return [
+ "{$prefix}_comment_text" => "comment_{$prefix}_comment.comment_text",
+ "{$prefix}_comment_data" => "comment_{$prefix}_comment.comment_data",
+ "{$prefix}_comment_cid" => "comment_{$prefix}_comment.comment_id",
+ ];
+ }
+
+ protected function getOldActorQueryFields( $prefix ) {
+ return [
+ "{$prefix}_user" => "{$prefix}_user",
+ "{$prefix}_user_text" => "{$prefix}_user_text",
+ "{$prefix}_actor" => 'NULL',
+ ];
+ }
+
+ protected function getNewActorQueryFields( $prefix, $tmp = false ) {
+ return [
+ "{$prefix}_user" => "actor_{$prefix}_user.actor_user",
+ "{$prefix}_user_text" => "actor_{$prefix}_user.actor_name",
+ "{$prefix}_actor" => $tmp ?: "{$prefix}_actor",
+ ];
+ }
+
+ protected function getCompatActorQueryFields( $prefix, $tmp = false ) {
+ return [
+ "{$prefix}_user" => "COALESCE( actor_{$prefix}_user.actor_user, {$prefix}_user )",
+ "{$prefix}_user_text" => "COALESCE( actor_{$prefix}_user.actor_name, {$prefix}_user_text )",
+ "{$prefix}_actor" => $tmp ?: "{$prefix}_actor",
+ ];
+ }
+
+ protected function getCompatActorJoins( $prefix ) {
+ return [
+ "temp_{$prefix}_user" => [
+ "LEFT JOIN",
+ "temp_{$prefix}_user.revactor_{$prefix} = {$prefix}_id",
+ ],
+ "actor_{$prefix}_user" => [
+ "LEFT JOIN",
+ "actor_{$prefix}_user.actor_id = temp_{$prefix}_user.revactor_actor",
+ ],
+ ];
+ }
+
+ protected function getCompatCommentJoins( $prefix ) {
+ return [
+ "temp_{$prefix}_comment" => [
+ "LEFT JOIN",
+ "temp_{$prefix}_comment.revcomment_{$prefix} = {$prefix}_id",
+ ],
+ "comment_{$prefix}_comment" => [
+ "LEFT JOIN",
+ "comment_{$prefix}_comment.comment_id = temp_{$prefix}_comment.revcomment_comment_id",
+ ],
+ ];
+ }
+
+ protected function getTextQueryFields() {
+ return [
+ 'old_text',
+ 'old_flags',
+ ];
+ }
+
+ protected function getPageQueryFields() {
+ return [
+ 'page_namespace',
+ 'page_title',
+ 'page_id',
+ 'page_latest',
+ 'page_is_redirect',
+ 'page_len',
+ ];
+ }
+
+ protected function getUserQueryFields() {
+ return [
+ 'user_name',
+ ];
+ }
+
+ protected function getContentHandlerQueryFields( $prefix ) {
+ return [
+ "{$prefix}_content_format",
+ "{$prefix}_content_model",
+ ];
+ }
+
+ public function provideArchiveQueryInfo() {
+ yield 'MCR, comment, actor' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_NEW,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_NEW,
+ ],
+ [
+ 'tables' => [
+ 'archive',
+ 'actor_ar_user' => 'actor',
+ 'comment_ar_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getArchiveQueryFields( false ),
+ $this->getNewActorQueryFields( 'ar' ),
+ $this->getNewCommentQueryFields( 'ar' )
+ ),
+ 'joins' => [
+ 'comment_ar_comment'
+ => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
+ 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
+ ],
+ ]
+ ];
+ yield 'read-new MCR, comment, actor' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_NEW,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_NEW,
+ ],
+ [
+ 'tables' => [
+ 'archive',
+ 'actor_ar_user' => 'actor',
+ 'comment_ar_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getArchiveQueryFields( false ),
+ $this->getCompatActorQueryFields( 'ar' ),
+ $this->getCompatCommentQueryFields( 'ar' )
+ ),
+ 'joins' => [
+ 'comment_ar_comment'
+ => [ 'LEFT JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
+ 'actor_ar_user' => [ 'LEFT JOIN', 'actor_ar_user.actor_id = ar_actor' ],
+ ],
+ ]
+ ];
+ yield 'MCR write-both/read-old' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ ],
+ [
+ 'tables' => [
+ 'archive',
+ 'actor_ar_user' => 'actor',
+ 'comment_ar_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getArchiveQueryFields( true ),
+ $this->getContentHandlerQueryFields( 'ar' ),
+ $this->getCompatActorQueryFields( 'ar' ),
+ $this->getCompatCommentQueryFields( 'ar' )
+ ),
+ 'joins' => [
+ 'comment_ar_comment'
+ => [ 'LEFT JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
+ 'actor_ar_user' => [ 'LEFT JOIN', 'actor_ar_user.actor_id = ar_actor' ],
+ ],
+ ]
+ ];
+ yield 'pre-MCR, no model' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [
+ 'tables' => [
+ 'archive',
+ ],
+ 'fields' => array_merge(
+ $this->getArchiveQueryFields( true ),
+ $this->getOldActorQueryFields( 'ar' ),
+ $this->getOldCommentQueryFields( 'ar' )
+ ),
+ 'joins' => [],
+ ]
+ ];
+ }
+
+ public function provideQueryInfo() {
+ // TODO: more option variations
+ yield 'MCR, page, user, comment, actor' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_NEW,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_NEW,
+ ],
+ [ 'page', 'user' ],
+ [
+ 'tables' => [
+ 'revision',
+ 'page',
+ 'user',
+ 'temp_rev_user' => 'revision_actor_temp',
+ 'temp_rev_comment' => 'revision_comment_temp',
+ 'actor_rev_user' => 'actor',
+ 'comment_rev_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( false ),
+ $this->getPageQueryFields(),
+ $this->getUserQueryFields(),
+ $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+ $this->getNewCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ 'user' => [
+ 'LEFT JOIN',
+ [ 'actor_rev_user.actor_user != 0', 'user_id = actor_rev_user.actor_user' ],
+ ],
+ 'comment_rev_comment' => [
+ 'JOIN',
+ 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id',
+ ],
+ 'actor_rev_user' => [
+ 'JOIN',
+ 'actor_rev_user.actor_id = temp_rev_user.revactor_actor',
+ ],
+ 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+ 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
+ ],
+ ]
+ ];
+ yield 'MCR read-new, page, user, comment, actor' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_NEW,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_NEW,
+ ],
+ [ 'page', 'user' ],
+ [
+ 'tables' => [
+ 'revision',
+ 'page',
+ 'user',
+ 'temp_rev_user' => 'revision_actor_temp',
+ 'temp_rev_comment' => 'revision_comment_temp',
+ 'actor_rev_user' => 'actor',
+ 'comment_rev_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( false ),
+ $this->getPageQueryFields(),
+ $this->getUserQueryFields(),
+ $this->getCompatActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+ $this->getCompatCommentQueryFields( 'rev' )
+ ),
+ 'joins' => array_merge(
+ [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ 'user' => [
+ 'LEFT JOIN',
+ [
+ 'COALESCE( actor_rev_user.actor_user, rev_user ) != 0',
+ 'user_id = COALESCE( actor_rev_user.actor_user, rev_user )'
+ ]
+ ],
+ ],
+ $this->getCompatActorJoins( 'rev' ),
+ $this->getCompatCommentJoins( 'rev' )
+ ),
+ ]
+ ];
+ yield 'MCR read-new' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_NEW,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_NEW,
+ ],
+ [ 'page', 'user' ],
+ [
+ 'tables' => [
+ 'revision',
+ 'page',
+ 'user',
+ 'temp_rev_user' => 'revision_actor_temp',
+ 'temp_rev_comment' => 'revision_comment_temp',
+ 'actor_rev_user' => 'actor',
+ 'comment_rev_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( false ),
+ $this->getPageQueryFields(),
+ $this->getUserQueryFields(),
+ $this->getCompatActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+ $this->getCompatCommentQueryFields( 'rev' )
+ ),
+ 'joins' => array_merge(
+ [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ 'user' => [
+ 'LEFT JOIN',
+ [
+ 'COALESCE( actor_rev_user.actor_user, rev_user ) != 0',
+ 'user_id = COALESCE( actor_rev_user.actor_user, rev_user )'
+ ]
+ ],
+ ],
+ $this->getCompatActorJoins( 'rev' ),
+ $this->getCompatCommentJoins( 'rev' )
+ ),
+ ]
+ ];
+ yield 'MCR write-both/read-old' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ ],
+ [],
+ [
+ 'tables' => [
+ 'revision',
+ 'temp_rev_user' => 'revision_actor_temp',
+ 'temp_rev_comment' => 'revision_comment_temp',
+ 'actor_rev_user' => 'actor',
+ 'comment_rev_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getContentHandlerQueryFields( 'rev' ),
+ $this->getCompatActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+ $this->getCompatCommentQueryFields( 'rev' )
+ ),
+ 'joins' => array_merge(
+ $this->getCompatActorJoins( 'rev' ),
+ $this->getCompatCommentJoins( 'rev' )
+ ),
+ ]
+ ];
+ yield 'MCR write-both/read-old, page, user' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ ],
+ [ 'page', 'user' ],
+ [
+ 'tables' => [
+ 'revision',
+ 'page',
+ 'user',
+ 'temp_rev_user' => 'revision_actor_temp',
+ 'temp_rev_comment' => 'revision_comment_temp',
+ 'actor_rev_user' => 'actor',
+ 'comment_rev_comment' => 'comment',
+ ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getContentHandlerQueryFields( 'rev' ),
+ $this->getUserQueryFields(),
+ $this->getPageQueryFields(),
+ $this->getCompatActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+ $this->getCompatCommentQueryFields( 'rev' )
+ ),
+ 'joins' => array_merge(
+ [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ 'user' => [
+ 'LEFT JOIN',
+ [
+ 'COALESCE( actor_rev_user.actor_user, rev_user ) != 0',
+ 'user_id = COALESCE( actor_rev_user.actor_user, rev_user )'
+ ]
+ ],
+ ],
+ $this->getCompatActorJoins( 'rev' ),
+ $this->getCompatCommentJoins( 'rev' )
+ ),
+ ]
+ ];
+ yield 'pre-MCR' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [],
+ [
+ 'tables' => [ 'revision' ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getContentHandlerQueryFields( 'rev' ),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [],
+ ]
+ ];
+ yield 'pre-MCR, page, user' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [ 'page', 'user' ],
+ [
+ 'tables' => [ 'revision', 'page', 'user' ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getContentHandlerQueryFields( 'rev' ),
+ $this->getPageQueryFields(),
+ $this->getUserQueryFields(),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+ ],
+ ]
+ ];
+ yield 'pre-MCR, no model' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [],
+ [
+ 'tables' => [ 'revision' ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [],
+ ],
+ ];
+ yield 'pre-MCR, no model, page' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [ 'page' ],
+ [
+ 'tables' => [ 'revision', 'page' ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getPageQueryFields(),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [
+ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ], ],
+ ],
+ ],
+ ];
+ yield 'pre-MCR, no model, user' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [ 'user' ],
+ [
+ 'tables' => [ 'revision', 'user' ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getUserQueryFields(),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [
+ 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+ ],
+ ],
+ ];
+ yield 'pre-MCR, no model, text' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [ 'text' ],
+ [
+ 'tables' => [ 'revision', 'text' ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getTextQueryFields(),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [
+ 'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ],
+ ],
+ ],
+ ];
+ yield 'pre-MCR, no model, text, page, user' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ [ 'text', 'page', 'user' ],
+ [
+ 'tables' => [
+ 'revision', 'page', 'user', 'text'
+ ],
+ 'fields' => array_merge(
+ $this->getRevisionQueryFields( true ),
+ $this->getPageQueryFields(),
+ $this->getUserQueryFields(),
+ $this->getTextQueryFields(),
+ $this->getOldActorQueryFields( 'rev' ),
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ 'joins' => [
+ 'page' => [
+ 'INNER JOIN',
+ [ 'page_id = rev_page' ],
+ ],
+ 'user' => [
+ 'LEFT JOIN',
+ [
+ 'rev_user != 0',
+ 'user_id = rev_user',
+ ],
+ ],
+ 'text' => [
+ 'INNER JOIN',
+ [ 'rev_text_id=old_id' ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function provideSlotsQueryInfo() {
+ yield 'MCR, no options' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
+ ],
+ [],
+ [
+ 'tables' => [
+ 'slots'
+ ],
+ 'fields' => [
+ 'slot_revision_id',
+ 'slot_content_id',
+ 'slot_origin',
+ 'slot_role_id',
+ ],
+ 'joins' => [],
+ ]
+ ];
+ yield 'MCR, role option' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
+ ],
+ [ 'role' ],
+ [
+ 'tables' => [
+ 'slots',
+ 'slot_roles',
+ ],
+ 'fields' => [
+ 'slot_revision_id',
+ 'slot_content_id',
+ 'slot_origin',
+ 'slot_role_id',
+ 'role_name',
+ ],
+ 'joins' => [
+ 'slot_roles' => [ 'LEFT JOIN', [ 'slot_role_id = role_id' ] ],
+ ],
+ ]
+ ];
+ yield 'MCR read-new, content option' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
+ ],
+ [ 'content' ],
+ [
+ 'tables' => [
+ 'slots',
+ 'content',
+ ],
+ 'fields' => [
+ 'slot_revision_id',
+ 'slot_content_id',
+ 'slot_origin',
+ 'slot_role_id',
+ 'content_size',
+ 'content_sha1',
+ 'content_address',
+ 'content_model',
+ ],
+ 'joins' => [
+ 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
+ ],
+ ]
+ ];
+ yield 'MCR read-new, content and model options' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
+ ],
+ [ 'content', 'model' ],
+ [
+ 'tables' => [
+ 'slots',
+ 'content',
+ 'content_models',
+ ],
+ 'fields' => [
+ 'slot_revision_id',
+ 'slot_content_id',
+ 'slot_origin',
+ 'slot_role_id',
+ 'content_size',
+ 'content_sha1',
+ 'content_address',
+ 'content_model',
+ 'model_name',
+ ],
+ 'joins' => [
+ 'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
+ 'content_models' => [ 'LEFT JOIN', [ 'content_model = model_id' ] ],
+ ],
+ ]
+ ];
+
+ $db = wfGetDB( DB_REPLICA );
+
+ yield 'MCR write-both/read-old' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+ ],
+ [],
+ [
+ 'tables' => [
+ 'slots' => 'revision',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id' => 'slots.rev_id',
+ 'slot_content_id' => 'NULL',
+ 'slot_origin' => 'slots.rev_id',
+ 'role_name' => $db->addQuotes( 'main' ),
+ ]
+ ),
+ 'joins' => [],
+ ]
+ ];
+ yield 'MCR write-both/read-old, content' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+ ],
+ [ 'content' ],
+ [
+ 'tables' => [
+ 'slots' => 'revision',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id' => 'slots.rev_id',
+ 'slot_content_id' => 'NULL',
+ 'slot_origin' => 'slots.rev_id',
+ 'role_name' => $db->addQuotes( 'main' ),
+ 'content_size' => 'slots.rev_len',
+ 'content_sha1' => 'slots.rev_sha1',
+ 'content_address' => $db->buildConcat( [
+ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
+ 'model_name' => 'slots.rev_content_model',
+ ]
+ ),
+ 'joins' => [],
+ ]
+ ];
+ yield 'MCR write-both/read-old, content, model, role' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+ ],
+ [ 'content', 'model', 'role' ],
+ [
+ 'tables' => [
+ 'slots' => 'revision',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id' => 'slots.rev_id',
+ 'slot_content_id' => 'NULL',
+ 'slot_origin' => 'slots.rev_id',
+ 'role_name' => $db->addQuotes( 'main' ),
+ 'content_size' => 'slots.rev_len',
+ 'content_sha1' => 'slots.rev_sha1',
+ 'content_address' => $db->buildConcat( [
+ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
+ 'model_name' => 'slots.rev_content_model',
+ ]
+ ),
+ 'joins' => [],
+ ]
+ ];
+ yield 'pre-MCR' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_OLD,
+ ],
+ [],
+ [
+ 'tables' => [
+ 'slots' => 'revision',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id' => 'slots.rev_id',
+ 'slot_content_id' => 'NULL',
+ 'slot_origin' => 'slots.rev_id',
+ 'role_name' => $db->addQuotes( 'main' ),
+ ]
+ ),
+ 'joins' => [],
+ ]
+ ];
+ yield 'pre-MCR, content' => [
+ [
+ 'wgMultiContentRevisionSchemaMigrationStage'
+ => SCHEMA_COMPAT_OLD,
+ ],
+ [ 'content' ],
+ [
+ 'tables' => [
+ 'slots' => 'revision',
+ ],
+ 'fields' => array_merge(
+ [
+ 'slot_revision_id' => 'slots.rev_id',
+ 'slot_content_id' => 'NULL',
+ 'slot_origin' => 'slots.rev_id',
+ 'role_name' => $db->addQuotes( 'main' ),
+ 'content_size' => 'slots.rev_len',
+ 'content_sha1' => 'slots.rev_sha1',
+ 'content_address' =>
+ $db->buildConcat( [ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
+ 'model_name' => 'slots.rev_content_model',
+ ]
+ ),
+ 'joins' => [],
+ ]
+ ];
+ }
+
+ public function provideSelectFields() {
+ yield 'with model, comment, and actor' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ ],
+ 'fields' => array_merge(
+ [
+ 'rev_id',
+ 'rev_page',
+ 'rev_text_id',
+ 'rev_timestamp',
+ 'rev_user_text',
+ 'rev_user',
+ 'rev_actor' => 'NULL',
+ 'rev_minor_edit',
+ 'rev_deleted',
+ 'rev_len',
+ 'rev_parent_id',
+ 'rev_sha1',
+ ],
+ $this->getContentHandlerQueryFields( 'rev' ),
+ [
+ 'rev_comment_old' => 'rev_comment',
+ 'rev_comment_pk' => 'rev_id',
+ ]
+ ),
+ ];
+ yield 'no mode, no comment, no actor' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ 'fields' => array_merge(
+ [
+ 'rev_id',
+ 'rev_page',
+ 'rev_text_id',
+ 'rev_timestamp',
+ 'rev_user_text',
+ 'rev_user',
+ 'rev_actor' => 'NULL',
+ 'rev_minor_edit',
+ 'rev_deleted',
+ 'rev_len',
+ 'rev_parent_id',
+ 'rev_sha1',
+ ],
+ $this->getOldCommentQueryFields( 'rev' )
+ ),
+ ];
+ }
+
+ public function provideSelectArchiveFields() {
+ yield 'with model, comment, and actor' => [
+ [
+ 'wgContentHandlerUseDB' => true,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
+ ],
+ 'fields' => array_merge(
+ [
+ 'ar_id',
+ 'ar_page_id',
+ 'ar_rev_id',
+ 'ar_text_id',
+ 'ar_timestamp',
+ 'ar_user_text',
+ 'ar_user',
+ 'ar_actor' => 'NULL',
+ 'ar_minor_edit',
+ 'ar_deleted',
+ 'ar_len',
+ 'ar_parent_id',
+ 'ar_sha1',
+ ],
+ $this->getContentHandlerQueryFields( 'ar' ),
+ [
+ 'ar_comment_old' => 'ar_comment',
+ 'ar_comment_id' => 'ar_comment_id',
+ ]
+ ),
+ ];
+ yield 'no mode, no comment, no actor' => [
+ [
+ 'wgContentHandlerUseDB' => false,
+ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD,
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD,
+ ],
+ 'fields' => array_merge(
+ [
+ 'ar_id',
+ 'ar_page_id',
+ 'ar_rev_id',
+ 'ar_text_id',
+ 'ar_timestamp',
+ 'ar_user_text',
+ 'ar_user',
+ 'ar_actor' => 'NULL',
+ 'ar_minor_edit',
+ 'ar_deleted',
+ 'ar_len',
+ 'ar_parent_id',
+ 'ar_sha1',
+ ],
+ $this->getOldCommentQueryFields( 'ar' )
+ ),
+ ];
+ }
+
+ /**
+ * @dataProvider provideSelectFields
+ * @covers Revision::selectFields
+ */
+ public function testRevisionSelectFields( $migrationStageSettings, $expected ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $this->hideDeprecated( 'Revision::selectFields' );
+ $this->assertArrayEqualsIgnoringIntKeyOrder( $expected, Revision::selectFields() );
+ }
+
+ /**
+ * @dataProvider provideSelectArchiveFields
+ * @covers Revision::selectArchiveFields
+ */
+ public function testRevisionSelectArchiveFields( $migrationStageSettings, $expected ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $this->hideDeprecated( 'Revision::selectArchiveFields' );
+ $this->assertArrayEqualsIgnoringIntKeyOrder( $expected, Revision::selectArchiveFields() );
+ }
+
+ /**
+ * @covers Revision::userJoinCond
+ */
+ public function testRevisionUserJoinCond() {
+ $this->hideDeprecated( 'Revision::userJoinCond' );
+ $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', MIGRATION_OLD );
+ $this->overrideMwServices();
+ $this->assertEquals(
+ [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+ Revision::userJoinCond()
+ );
+ }
+
+ /**
+ * @covers Revision::pageJoinCond
+ */
+ public function testRevisionPageJoinCond() {
+ $this->hideDeprecated( 'Revision::pageJoinCond' );
+ $this->assertEquals(
+ [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+ Revision::pageJoinCond()
+ );
+ }
+
+ /**
+ * @covers Revision::selectTextFields
+ */
+ public function testRevisionSelectTextFields() {
+ $this->hideDeprecated( 'Revision::selectTextFields' );
+ $this->assertEquals(
+ $this->getTextQueryFields(),
+ Revision::selectTextFields()
+ );
+ }
+
+ /**
+ * @covers Revision::selectPageFields
+ */
+ public function testRevisionSelectPageFields() {
+ $this->hideDeprecated( 'Revision::selectPageFields' );
+ $this->assertEquals(
+ $this->getPageQueryFields(),
+ Revision::selectPageFields()
+ );
+ }
+
+ /**
+ * @covers Revision::selectUserFields
+ */
+ public function testRevisionSelectUserFields() {
+ $this->hideDeprecated( 'Revision::selectUserFields' );
+ $this->assertEquals(
+ $this->getUserQueryFields(),
+ Revision::selectUserFields()
+ );
+ }
+
+ /**
+ * @covers Revision::getArchiveQueryInfo
+ * @dataProvider provideArchiveQueryInfo
+ */
+ public function testRevisionGetArchiveQueryInfo( $migrationStageSettings, $expected ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $queryInfo = Revision::getArchiveQueryInfo();
+ $this->assertQueryInfoEquals( $expected, $queryInfo );
+ }
+
+ /**
+ * @covers Revision::getQueryInfo
+ * @dataProvider provideQueryInfo
+ */
+ public function testRevisionGetQueryInfo( $migrationStageSettings, $options, $expected ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $queryInfo = Revision::getQueryInfo( $options );
+ $this->assertQueryInfoEquals( $expected, $queryInfo );
+ }
+
+ /**
+ * @dataProvider provideQueryInfo
+ * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo
+ */
+ public function testRevisionStoreGetQueryInfo( $migrationStageSettings, $options, $expected ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $store = MediaWikiServices::getInstance()->getRevisionStore();
+
+ $queryInfo = $store->getQueryInfo( $options );
+ $this->assertQueryInfoEquals( $expected, $queryInfo );
+ }
+
+ /**
+ * @dataProvider provideSlotsQueryInfo
+ * @covers \MediaWiki\Storage\RevisionStore::getSlotsQueryInfo
+ */
+ public function testRevisionStoreGetSlotsQueryInfo(
+ $migrationStageSettings,
+ $options,
+ $expected
+ ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $store = MediaWikiServices::getInstance()->getRevisionStore();
+
+ $queryInfo = $store->getSlotsQueryInfo( $options );
+ $this->assertQueryInfoEquals( $expected, $queryInfo );
+ }
+
+ /**
+ * @dataProvider provideArchiveQueryInfo
+ * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
+ */
+ public function testRevisionStoreGetArchiveQueryInfo( $migrationStageSettings, $expected ) {
+ $this->setMwGlobals( $migrationStageSettings );
+ $this->overrideMwServices();
+
+ $store = MediaWikiServices::getInstance()->getRevisionStore();
+
+ $queryInfo = $store->getArchiveQueryInfo();
+ $this->assertQueryInfoEquals( $expected, $queryInfo );
+ }
+
+ private function assertQueryInfoEquals( $expected, $queryInfo ) {
+ $this->assertArrayEqualsIgnoringIntKeyOrder(
+ $expected['tables'],
+ $queryInfo['tables'],
+ 'tables'
+ );
+ $this->assertArrayEqualsIgnoringIntKeyOrder(
+ $expected['fields'],
+ $queryInfo['fields'],
+ 'fields'
+ );
+ $this->assertArrayEqualsIgnoringIntKeyOrder(
+ $expected['joins'],
+ $queryInfo['joins'],
+ 'joins'
+ );
+ }
+
+ /**
+ * Assert that the two arrays passed are equal, ignoring the order of the values that integer
+ * keys.
+ *
+ * Note: Failures of this assertion can be slightly confusing as the arrays are actually
+ * split into a string key array and an int key array before assertions occur.
+ *
+ * @param array $expected
+ * @param array $actual
+ */
+ private function assertArrayEqualsIgnoringIntKeyOrder(
+ array $expected,
+ array $actual,
+ $message = null
+ ) {
+ $this->objectAssociativeSort( $expected );
+ $this->objectAssociativeSort( $actual );
+
+ // Separate the int key values from the string key values so that assertion failures are
+ // easier to understand.
+ $expectedIntKeyValues = [];
+ $actualIntKeyValues = [];
+
+ // Remove all int keys and re add them at the end after sorting by value
+ // This will result in all int keys being in the same order with same ints at the end of
+ // the array
+ foreach ( $expected as $key => $value ) {
+ if ( is_int( $key ) ) {
+ unset( $expected[$key] );
+ $expectedIntKeyValues[] = $value;
+ }
+ }
+ foreach ( $actual as $key => $value ) {
+ if ( is_int( $key ) ) {
+ unset( $actual[$key] );
+ $actualIntKeyValues[] = $value;
+ }
+ }
+
+ $this->objectAssociativeSort( $expected );
+ $this->objectAssociativeSort( $actual );
+
+ $this->objectAssociativeSort( $expectedIntKeyValues );
+ $this->objectAssociativeSort( $actualIntKeyValues );
+
+ $this->assertEquals( $expected, $actual, $message );
+ $this->assertEquals( $expectedIntKeyValues, $actualIntKeyValues, $message );
+ }
+
+}
$this->assertEquals( $r1->getSha1(), $r2->getSha1() );
$this->assertEquals( $r1->getSize(), $r2->getSize() );
$this->assertEquals( $r1->getPageId(), $r2->getPageId() );
- $this->assertArrayEqualsIgnoringIntKeyOrder( $r1->getSlotRoles(), $r2->getSlotRoles() );
+ $this->assertArrayEquals( $r1->getSlotRoles(), $r2->getSlotRoles() );
$this->assertEquals( $r1->getWikiId(), $r2->getWikiId() );
$this->assertEquals( $r1->isMinor(), $r2->isMinor() );
foreach ( $r1->getSlotRoles() as $role ) {
$this->assertEquals( $user->getName(), $record->getUser()->getName() );
$this->assertEquals( $baseRev->getId(), $record->getParentId() );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
+ $this->assertArrayEquals(
$baseRev->getSlotRoles(),
$record->getSlotRoles()
);
}
}
+ /**
+ * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow
+ * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo
+ */
+ public function testNewRevisionFromRow_getQueryInfo() {
+ $page = $this->getTestPage();
+ $text = __METHOD__ . 'a-ä';
+ /** @var Revision $rev */
+ $rev = $page->doEditContent(
+ new WikitextContent( $text ),
+ __METHOD__ . 'a'
+ )->value['revision'];
+
+ $store = MediaWikiServices::getInstance()->getRevisionStore();
+ $info = $store->getQueryInfo();
+ $row = $this->db->selectRow(
+ $info['tables'],
+ $info['fields'],
+ [ 'rev_id' => $rev->getId() ],
+ __METHOD__,
+ [],
+ $info['joins']
+ );
+ $record = $store->newRevisionFromRow(
+ $row,
+ [],
+ $page->getTitle()
+ );
+ $this->assertRevisionRecordMatchesRevision( $rev, $record );
+ $this->assertSame( $text, $rev->getContent()->serialize() );
+ }
+
/**
* @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow
*/
/**
* @covers \MediaWiki\Storage\RevisionStore::newRevisionFromArchiveRow
+ * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
*/
- public function testNewRevisionFromArchiveRow() {
+ public function testNewRevisionFromArchiveRow_getArchiveQueryInfo() {
$store = MediaWikiServices::getInstance()->getRevisionStore();
$title = Title::newFromText( __METHOD__ );
$text = __METHOD__ . '-bä';
$this->testNewMutableRevisionFromArray( $array );
}
- protected function getDefaultQueryFields( $returnTextIdField = true ) {
- $fields = [
- 'rev_id',
- 'rev_page',
- 'rev_timestamp',
- 'rev_minor_edit',
- 'rev_deleted',
- 'rev_len',
- 'rev_parent_id',
- 'rev_sha1',
- ];
- if ( $returnTextIdField ) {
- $fields[] = 'rev_text_id';
- }
- return $fields;
- }
-
- protected function getCommentQueryFields() {
- return [
- 'rev_comment_text' => 'rev_comment',
- 'rev_comment_data' => 'NULL',
- 'rev_comment_cid' => 'NULL',
- ];
- }
-
- protected function getActorQueryFields() {
- return [
- 'rev_user' => 'rev_user',
- 'rev_user_text' => 'rev_user_text',
- 'rev_actor' => 'NULL',
- ];
- }
-
- protected function getContentHandlerQueryFields() {
- return [
- 'rev_content_format',
- 'rev_content_model',
- ];
- }
-
- abstract public function provideGetQueryInfo();
-
- /**
- * @dataProvider provideGetQueryInfo
- * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo
- */
- public function testGetQueryInfo( $options, $expected ) {
- $store = MediaWikiServices::getInstance()->getRevisionStore();
-
- $queryInfo = $store->getQueryInfo( $options );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['tables'],
- $queryInfo['tables']
- );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['fields'],
- $queryInfo['fields']
- );
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['joins'],
- $queryInfo['joins']
- );
- }
-
- protected function getDefaultArchiveFields( $returnTextFields = true ) {
- $fields = [
- 'ar_id',
- 'ar_page_id',
- 'ar_namespace',
- 'ar_title',
- 'ar_rev_id',
- 'ar_timestamp',
- 'ar_minor_edit',
- 'ar_deleted',
- 'ar_len',
- 'ar_parent_id',
- 'ar_sha1',
- ];
- if ( $returnTextFields ) {
- $fields[] = 'ar_text_id';
- }
- return $fields;
- }
-
- abstract public function provideGetArchiveQueryInfo();
-
- /**
- * @dataProvider provideGetArchiveQueryInfo
- * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
- */
- public function testGetArchiveQueryInfo( $expected ) {
- $store = MediaWikiServices::getInstance()->getRevisionStore();
-
- $archiveQueryInfo = $store->getArchiveQueryInfo();
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['tables'],
- $archiveQueryInfo['tables']
- );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['fields'],
- $archiveQueryInfo['fields']
- );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['joins'],
- $archiveQueryInfo['joins']
- );
- }
-
- abstract public function provideGetSlotsQueryInfo();
-
- /**
- * @dataProvider provideGetSlotsQueryInfo
- * @covers \MediaWiki\Storage\RevisionStore::getSlotsQueryInfo
- */
- public function testGetSlotsQueryInfo( $options, $expected ) {
- $store = MediaWikiServices::getInstance()->getRevisionStore();
-
- $archiveQueryInfo = $store->getSlotsQueryInfo( $options );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['tables'],
- $archiveQueryInfo['tables']
- );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['fields'],
- $archiveQueryInfo['fields']
- );
-
- $this->assertArrayEqualsIgnoringIntKeyOrder(
- $expected['joins'],
- $archiveQueryInfo['joins']
- );
- }
-
- /**
- * Assert that the two arrays passed are equal, ignoring the order of the values that integer
- * keys.
- *
- * Note: Failures of this assertion can be slightly confusing as the arrays are actually
- * split into a string key array and an int key array before assertions occur.
- *
- * @param array $expected
- * @param array $actual
- */
- private function assertArrayEqualsIgnoringIntKeyOrder( array $expected, array $actual ) {
- $this->objectAssociativeSort( $expected );
- $this->objectAssociativeSort( $actual );
-
- // Separate the int key values from the string key values so that assertion failures are
- // easier to understand.
- $expectedIntKeyValues = [];
- $actualIntKeyValues = [];
-
- // Remove all int keys and re add them at the end after sorting by value
- // This will result in all int keys being in the same order with same ints at the end of
- // the array
- foreach ( $expected as $key => $value ) {
- if ( is_int( $key ) ) {
- unset( $expected[$key] );
- $expectedIntKeyValues[] = $value;
- }
- }
- foreach ( $actual as $key => $value ) {
- if ( is_int( $key ) ) {
- unset( $actual[$key] );
- $actualIntKeyValues[] = $value;
- }
- }
-
- $this->assertArrayEquals( $expected, $actual, false, true );
- $this->assertArrayEquals( $expectedIntKeyValues, $actualIntKeyValues, false, true );
- }
-
}