<?php
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Storage\RevisionStore;
+use MediaWiki\Storage\IncompleteRevisionException;
+use MediaWiki\Storage\RevisionRecord;
/**
* RevisionDbTestBase contains test cases for the Revision class that have Database interactions.
MWNamespace::clearCaches();
// Reset namespace cache
$wgContLang->resetNamespaces();
+
if ( !$this->testPage ) {
/**
* We have to create a new page for each subclass as the page creation may result
$props['text'] = 'Lorem Ipsum';
}
+ if ( !isset( $props['user_text'] ) ) {
+ $props['user_text'] = 'Tester';
+ }
+
+ if ( !isset( $props['user'] ) ) {
+ $props['user'] = 0;
+ }
+
if ( !isset( $props['comment'] ) ) {
$props['comment'] = 'just a test';
}
$props['page'] = $this->testPage->getId();
}
+ if ( !isset( $props['content_model'] ) ) {
+ $props['content_model'] = CONTENT_MODEL_WIKITEXT;
+ }
+
$rev = new Revision( $props );
$dbw = wfGetDB( DB_MASTER );
$revId = $rev->insertOn( wfGetDB( DB_MASTER ) );
$this->assertInternalType( 'integer', $revId );
- $this->assertInternalType( 'integer', $rev->getTextId() );
$this->assertSame( $revId, $rev->getId() );
+ // getTextId() must be an int!
+ $this->assertInternalType( 'integer', $rev->getTextId() );
+
+ $mainSlot = $rev->getRevisionRecord()->getSlot( 'main', RevisionRecord::RAW );
+
+ // we currently only support storage in the text table
+ $textId = MediaWikiServices::getInstance()
+ ->getBlobStore()
+ ->getTextIdFromAddress( $mainSlot->getAddress() );
+
$this->assertSelect(
'text',
[ 'old_id', 'old_text' ],
- "old_id = {$rev->getTextId()}",
- [ [ strval( $rev->getTextId() ), 'Revision Text' ] ]
+ "old_id = $textId",
+ [ [ strval( $textId ), 'Revision Text' ] ]
);
$this->assertSelect(
'revision',
[ [
strval( $rev->getId() ),
strval( $this->testPage->getId() ),
- strval( $rev->getTextId() ),
+ strval( $textId ),
'0',
'0',
'0',
// If an ExternalStore is set don't use it.
$this->setMwGlobals( 'wgDefaultExternalStore', false );
$this->setExpectedException(
- MWException::class,
- "Cannot insert revision: page ID must be nonzero"
+ IncompleteRevisionException::class,
+ "rev_page field must not be 0!"
);
- $rev = new Revision( [] );
+ $title = Title::newFromText( 'Nonexistant-' . __METHOD__ );
+ $rev = new Revision( [], 0, $title );
$rev->insertOn( wfGetDB( DB_MASTER ) );
}
return $f + [ 'ar_namespace', 'ar_title' ];
},
];
+ yield [
+ function ( $f ) {
+ unset( $f['ar_text'] );
+ return $f;
+ },
+ ];
yield [
function ( $f ) {
unset( $f['ar_text_id'] );
return $f;
},
];
+ yield [
+ function ( $f ) {
+ unset( $f['ar_page_id'] );
+ return $f;
+ },
+ ];
+ yield [
+ function ( $f ) {
+ unset( $f['ar_parent_id'] );
+ return $f;
+ },
+ ];
+ yield [
+ function ( $f ) {
+ unset( $f['ar_rev_id'] );
+ return $f;
+ },
+ ];
+ yield [
+ function ( $f ) {
+ unset( $f['ar_sha1'] );
+ return $f;
+ },
+ ];
}
/**
* @covers Revision::newFromArchiveRow
*/
public function testNewFromArchiveRow( $selectModifier ) {
+ $services = MediaWikiServices::getInstance();
+
+ $store = new RevisionStore(
+ $services->getDBLoadBalancer(),
+ $services->getService( '_SqlBlobStore' ),
+ $services->getMainWANObjectCache()
+ );
+
+ $store->setContentHandlerUseDB( $this->getContentHandlerUseDB() );
+ $this->setService( 'RevisionStore', $store );
+
$page = $this->createPage(
'RevisionStorageTest_testNewFromArchiveRow',
'Lorem Ipsum',
$row = $res->fetchObject();
$res->free();
+ // MCR migration note: $row is now required to contain ar_title and ar_namespace.
+ // Alternatively, a Title object can be passed to RevisionStore::newRevisionFromArchiveRow
$rev = Revision::newFromArchiveRow( $row );
$this->assertRevEquals( $orig, $rev );
$row = $res->fetchObject();
$res->free();
- $rev = Revision::newFromArchiveRow( $row, [ 'comment' => 'SOMEOVERRIDE' ] );
+ $rev = Revision::newFromArchiveRow( $row, [ 'comment_text' => 'SOMEOVERRIDE' ] );
$this->assertNotEquals( $orig->getComment(), $rev->getComment() );
$this->assertEquals( 'SOMEOVERRIDE', $rev->getComment() );
* @covers Revision::newFromPageId
*/
public function testNewFromPageIdWithNotLatestId() {
- $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
+ $content = new WikitextContent( __METHOD__ );
+ $this->testPage->doEditContent( $content, __METHOD__ );
$rev = Revision::newFromPageId(
$this->testPage->getId(),
$this->testPage->getRevision()->getPrevious()->getId()
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
$id = $this->testPage->getRevision()->getId();
+ $this->hideDeprecated( 'Revision::fetchRevision' );
$res = Revision::fetchRevision( $this->testPage->getTitle() );
# note: order is unspecified
$rows[$row->rev_id] = $row;
}
- $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' );
- $this->assertArrayHasKey( $id, $rows, 'missing revision with id ' . $id );
+ $this->assertEmpty( $rows, 'expected empty set' );
}
/**
'new null revision should have a different id from the original revision' );
$this->assertEquals( $orig->getTextId(), $rev->getTextId(),
'new null revision should have the same text id as the original revision' );
+ $this->assertEquals( $orig->getSha1(), $rev->getSha1(),
+ 'new null revision should have the same SHA1 as the original revision' );
+ $this->assertTrue( $orig->getRevisionRecord()->hasSameContent( $rev->getRevisionRecord() ),
+ 'new null revision should have the same content as the original revision' );
$this->assertEquals( __METHOD__, $rev->getContent()->getNativeData() );
}
+ /**
+ * @covers Revision::newNullRevision
+ */
+ public function testNewNullRevision_badPage() {
+ $dbw = wfGetDB( DB_MASTER );
+ $rev = Revision::newNullRevision( $dbw, -1, 'a null revision', false );
+
+ $this->assertNull( $rev );
+ }
+
/**
* @covers Revision::insertOn
*/
$row = $res->fetchObject();
$this->assertEquals( IP::toHex( $ip ), $row->ipc_hex );
- $this->assertEquals( $orig->getTimestamp(), $row->ipc_rev_timestamp );
+ $this->assertEquals(
+ $orig->getTimestamp(),
+ wfTimestamp( TS_MW, $row->ipc_rev_timestamp )
+ );
}
public static function provideUserWasLastToEdit() {
}
/**
+ * @covers Revision::userWasLastToEdit
* @dataProvider provideUserWasLastToEdit
*/
public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
'user' => $userA->getId(),
'text' => 'zero',
'content_model' => CONTENT_MODEL_WIKITEXT,
- 'summary' => 'edit zero'
+ 'comment' => 'edit zero'
] );
$revisions[0]->insertOn( $dbw );
'user' => $userA->getId(),
'text' => 'one',
'content_model' => CONTENT_MODEL_WIKITEXT,
- 'summary' => 'edit one'
+ 'comment' => 'edit one'
] );
$revisions[1]->insertOn( $dbw );
'user' => $userB->getId(),
'text' => 'two',
'content_model' => CONTENT_MODEL_WIKITEXT,
- 'summary' => 'edit two'
+ 'comment' => 'edit two'
] );
$revisions[2]->insertOn( $dbw );
'user' => $userA->getId(),
'text' => 'three',
'content_model' => CONTENT_MODEL_WIKITEXT,
- 'summary' => 'edit three'
+ 'comment' => 'edit three'
] );
$revisions[3]->insertOn( $dbw );
'user' => $userA->getId(),
'text' => 'zero',
'content_model' => CONTENT_MODEL_WIKITEXT,
- 'summary' => 'edit four'
+ 'comment' => 'edit four'
] );
$revisions[4]->insertOn( $dbw );
// test it ---------------------------------
$since = $revisions[$sinceIdx]->getTimestamp();
+ $allRows = iterator_to_array( $dbw->select(
+ 'revision',
+ [ 'rev_id', 'rev_timestamp', 'rev_user' ],
+ [
+ 'rev_page' => $page->getId(),
+ //'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $since ) )
+ ],
+ __METHOD__,
+ [ 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 50 ]
+ ) );
+
$wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
$this->assertEquals( $expectedLast, $wasLast );
'text_id' => 123456789, // not in the test DB
] );
+ MediaWiki\suppressWarnings(); // bad text_id will trigger a warning.
+
$this->assertNull( $rev->getContent(),
"getContent() should return null if the revision's text blob could not be loaded." );
// NOTE: check this twice, once for lazy initialization, and once with the cached value.
$this->assertNull( $rev->getContent(),
"getContent() should return null if the revision's text blob could not be loaded." );
+
+ MediaWiki\suppressWarnings( 'end' );
}
public function provideGetSize() {
*/
public function testLoadFromId() {
$rev = $this->testPage->getRevision();
+ $this->hideDeprecated( 'Revision::loadFromId' );
$this->assertRevEquals(
$rev,
Revision::loadFromId( wfGetDB( DB_MASTER ), $rev->getId() )
$rev[1] = $this->testPage->getLatest();
$this->assertSame(
- [ $rev[1] => strval( $textLength ) ],
+ [ $rev[1] => $textLength ],
Revision::getParentLengths(
wfGetDB( DB_MASTER ),
[ $rev[1] ]
$rev[2] = $this->testPage->getLatest();
$this->assertSame(
- [ $rev[1] => strval( $textOneLength ), $rev[2] => strval( $textTwoLength ) ],
+ [ $rev[1] => $textOneLength, $rev[2] => $textTwoLength ],
Revision::getParentLengths(
wfGetDB( DB_MASTER ),
[ $rev[1], $rev[2] ]
);
}
- /**
- * @covers Revision::getTitle
- */
- public function testGetTitle_forBadRevision() {
- $rev = new Revision( [] );
- $this->assertNull( $rev->getTitle() );
- }
-
/**
* @covers Revision::isMinor
*/
$rev = $this->testPage->getRevision();
// Clear any previous cache for the revision during creation
- $key = $cache->makeGlobalKey( 'revision', $db->getDomainID(), $rev->getPage(), $rev->getId() );
+ $key = $cache->makeGlobalKey( 'revision-row-1.29',
+ $db->getDomainID(),
+ $rev->getPage(),
+ $rev->getId()
+ );
$cache->delete( $key, WANObjectCache::HOLDOFF_NONE );
$this->assertFalse( $cache->get( $key ) );
// Get the new revision and make sure it is in the cache and correct
$newRev = Revision::newKnownCurrent( $db, $rev->getPage(), $rev->getId() );
$this->assertRevEquals( $rev, $newRev );
- $this->assertRevEquals( $rev, $cache->get( $key ) );
+
+ $cachedRow = $cache->get( $key );
+ $this->assertNotFalse( $cachedRow );
+ $this->assertEquals( $rev->getId(), $cachedRow->rev_id );
+ }
+
+ public function testNewKnownCurrent_withPageId() {
+ $db = wfGetDB( DB_MASTER );
+
+ $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
+ $rev = $this->testPage->getRevision();
+
+ $pageId = $this->testPage->getId();
+
+ $newRev = Revision::newKnownCurrent( $db, $pageId, $rev->getId() );
+ $this->assertRevEquals( $rev, $newRev );
+ }
+
+ public function testNewKnownCurrent_returnsFalseWhenTitleDoesntExist() {
+ $db = wfGetDB( DB_MASTER );
+
+ $this->assertFalse( Revision::newKnownCurrent( $db, 0 ) );
}
public function provideUserCanBitfield() {
]
);
$user = $this->getTestUser( $userGroups )->getUser();
- $revision = new Revision( [ 'deleted' => $bitField ] );
+ $revision = new Revision( [ 'deleted' => $bitField ], 0, $this->testPage->getTitle() );
$this->assertSame(
$expected,