Make RevisionStore::getKnownCurrentRevision work for foreign wikis

Bug: T274067
Change-Id: Ia4efa113b4f3dda5a0ed77a8acd2276fc8c3b13c
This commit is contained in:
Petr Pchelko 2021-06-17 16:21:53 -07:00
parent 7837931be9
commit f312a6bfe8
2 changed files with 70 additions and 47 deletions

View file

@ -3165,32 +3165,30 @@ class RevisionStore
*/
public function getKnownCurrentRevision( PageIdentity $page, $revId = 0 ) {
$db = $this->getDBConnectionRef( DB_REPLICA );
if ( !$page instanceof Title ) {
// TODO: For foreign wikis we can not cast from PageIdentityValue to Title,
// since getLatestRevID will fetch from local database. To be fixed with cross-wiki
// aware PageStore. T274067
$page->assertWiki( PageIdentity::LOCAL );
$title = Title::castFromPageIdentity( $page );
} else {
$title = $page;
}
$revIdPassed = $revId;
$pageId = $this->getArticleId( $title );
$pageId = $this->getArticleId( $page );
if ( !$pageId ) {
return false;
}
if ( !$revId ) {
$revId = $title->getLatestRevID();
if ( $page instanceof Title ) {
$revId = $page->getLatestRevID();
} else {
$pageRecord = $this->pageStore->getPageByReference( $page );
if ( $pageRecord ) {
$revId = $pageRecord->getLatest( $this->getWikiId() );
}
}
}
if ( !$revId ) {
wfWarn(
'No latest revision known for page ' . $title->getPrefixedDBkey()
. ' even though it exists with page ID ' . $pageId
);
$this->logger->warning(
'No latest revision known for page {page} even though it exists with page ID {page_id}', [
'page' => $page->__toString(),
'page_id' => $pageId,
'wiki_id' => $this->getWikiId() ?: 'local',
] );
return false;
}
@ -3216,7 +3214,7 @@ class RevisionStore
// Reflect revision deletion and user renames.
if ( $row ) {
$title = $this->ensureRevisionRowMatchesPage( $row, $title, [
$title = $this->ensureRevisionRowMatchesPage( $row, $page, [
'from_cache_flag' => $fromCache,
'page_id_initial' => $pageId,
'rev_id_used' => $revId,

View file

@ -875,25 +875,11 @@ abstract class RevisionStoreDbTestBase extends MediaWikiIntegrationTestCase {
];
}
/**
* Test that getRevisionByTitle doesn't try to use the local wiki DB (T248756)
* @covers \MediaWiki\Revision\RevisionStore::getRevisionByTitle
*/
public function testGetRevisionByTitle_doesNotUseLocalLoadBalancerForForeignWiki() {
$page = $this->getTestPage();
$content = new WikitextContent( __METHOD__ );
$status = $page->doEditContent( $content, __METHOD__ );
/** @var RevisionRecord $revRecord */
$revRecord = $status->value['revision-record'];
$dbDomain = 'some_foreign_wiki';
$services = MediaWikiServices::getInstance();
private function executeWithForeignStore( string $dbDomain, callable $callback ) {
$services = $this->getServiceContainer();
// Configure the load balancer to route queries for the "foreign" domain to the test DB
$dbLoadBalancer = $services->getDBLoadBalancer();
$dbLoadBalancer->setDomainAliases( [ $dbDomain => $dbLoadBalancer->getLocalDomainID() ] );
$store = new RevisionStore(
$dbLoadBalancer,
$services->getBlobStore(),
@ -905,7 +891,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiIntegrationTestCase {
$services->getActorMigration(),
$services->getActorStoreFactory()->getActorStore( $dbDomain ),
$services->getContentHandlerFactory(),
$services->getPageStore(),
$services->getPageStoreFactory()->getPageStore( $dbDomain ),
$services->getTitleFactory(),
$services->getHookContainer(),
$dbDomain
@ -919,24 +905,63 @@ abstract class RevisionStoreDbTestBase extends MediaWikiIntegrationTestCase {
try {
$this->setService( 'DBLoadBalancer', $localLoadBalancerMock );
$storeRecord = $store->getRevisionByTitle(
new PageIdentityValue(
$page->getId(),
$page->getTitle()->getNamespace(),
$page->getTitle()->getDBkey(),
$dbDomain
)
);
$this->assertSame( $revRecord->getId(), $storeRecord->getId( $dbDomain ) );
$this->assertTrue( $storeRecord->getSlot( SlotRecord::MAIN )->getContent()->equals( $content ) );
$this->assertSame( __METHOD__, $storeRecord->getComment()->text );
$callback( $store );
} finally {
// Restore the original load balancer to make test teardown work
$this->setService( 'DBLoadBalancer', $dbLoadBalancer );
}
}
/**
* @covers \MediaWiki\Revision\RevisionStore::getRevisionByTitle
*/
public function testGetLatestKnownRevision_foreigh() {
$page = $this->getTestPage();
$status = $this->editPage( $page, __METHOD__ );
$this->assertTrue( $status->isGood(), 'Sanity: edited a page' );
/** @var RevisionRecord $revRecord */
$revRecord = $status->value['revision-record'];
$dbDomain = 'some_foreign_wiki';
$this->executeWithForeignStore(
$dbDomain,
function ( RevisionStore $store ) use ( $page, $dbDomain, $revRecord ) {
$storeRecord = $store->getKnownCurrentRevision(
new PageIdentityValue( $page->getId(), $page->getNamespace(), $page->getDBkey(), $dbDomain )
);
$this->assertSame( $dbDomain, $storeRecord->getWikiId() );
$this->assertSame( $revRecord->getId(), $storeRecord->getId( $dbDomain ) );
} );
}
/**
* Test that getRevisionByTitle doesn't try to use the local wiki DB (T248756)
* @covers \MediaWiki\Revision\RevisionStore::getRevisionByTitle
*/
public function testGetRevisionByTitle_doesNotUseLocalLoadBalancerForForeignWiki() {
$page = $this->getTestPage();
$content = new WikitextContent( __METHOD__ );
$comment = __METHOD__;
$status = $page->doEditContent( $content, $comment );
/** @var RevisionRecord $revRecord */
$revRecord = $status->value['revision-record'];
$dbDomain = 'some_foreign_wiki';
$this->executeWithForeignStore(
$dbDomain,
function ( RevisionStore $store ) use ( $page, $dbDomain, $revRecord, $content, $comment ) {
$storeRecord = $store->getRevisionByTitle(
new PageIdentityValue(
$page->getId(),
$page->getTitle()->getNamespace(),
$page->getTitle()->getDBkey(),
$dbDomain
)
);
$this->assertSame( $revRecord->getId(), $storeRecord->getId( $dbDomain ) );
$this->assertTrue( $storeRecord->getSlot( SlotRecord::MAIN )->getContent()->equals( $content ) );
$this->assertSame( $comment, $storeRecord->getComment()->text );
} );
}
/**
* @covers \MediaWiki\Revision\RevisionStore::getRevisionByPageId
*/