2012-05-02 17:34:35 +00:00
|
|
|
<?php
|
2019-05-28 14:04:23 +00:00
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2018-09-20 17:29:04 +00:00
|
|
|
use MediaWiki\Revision\IncompleteRevisionException;
|
2020-01-10 00:00:51 +00:00
|
|
|
use MediaWiki\Revision\MutableRevisionRecord;
|
2018-09-20 17:29:04 +00:00
|
|
|
use MediaWiki\Revision\RevisionRecord;
|
2020-01-10 00:00:51 +00:00
|
|
|
use MediaWiki\Revision\RevisionStore;
|
2018-09-20 17:29:04 +00:00
|
|
|
use MediaWiki\Revision\SlotRecord;
|
2012-05-02 17:34:35 +00:00
|
|
|
|
|
|
|
|
/**
|
2019-12-17 16:20:32 +00:00
|
|
|
* Tests Revision against the MCR DB schema after schema migration.
|
2012-08-30 17:17:14 +00:00
|
|
|
*
|
2019-12-17 16:20:32 +00:00
|
|
|
* @covers Revision
|
|
|
|
|
*
|
|
|
|
|
* @group Revision
|
|
|
|
|
* @group Storage
|
|
|
|
|
* @group ContentHandler
|
2017-10-24 13:41:21 +00:00
|
|
|
* @group Database
|
2012-08-30 17:17:14 +00:00
|
|
|
* @group medium
|
2012-05-02 17:34:35 +00:00
|
|
|
*/
|
2019-12-17 16:20:32 +00:00
|
|
|
class RevisionDbTest extends MediaWikiIntegrationTestCase {
|
2017-10-12 12:23:33 +00:00
|
|
|
|
2012-07-24 15:58:02 +00:00
|
|
|
/**
|
2019-11-29 13:33:43 +00:00
|
|
|
* @var WikiPage
|
2012-07-24 15:58:02 +00:00
|
|
|
*/
|
2017-10-13 15:39:24 +00:00
|
|
|
private $testPage;
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-10 16:58:13 +00:00
|
|
|
public function __construct( $name = null, array $data = [], $dataName = '' ) {
|
2012-05-02 17:34:35 +00:00
|
|
|
parent::__construct( $name, $data, $dataName );
|
|
|
|
|
|
|
|
|
|
$this->tablesUsed = array_merge( $this->tablesUsed,
|
2017-10-12 12:23:33 +00:00
|
|
|
[
|
|
|
|
|
'page',
|
2013-02-14 11:36:35 +00:00
|
|
|
'revision',
|
2019-03-29 21:14:05 +00:00
|
|
|
'comment',
|
2017-04-21 16:17:59 +00:00
|
|
|
'ip_changes',
|
2013-02-14 11:36:35 +00:00
|
|
|
'text',
|
2017-10-12 12:23:33 +00:00
|
|
|
'archive',
|
2013-02-14 11:36:35 +00:00
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
'slots',
|
|
|
|
|
'content',
|
|
|
|
|
'content_models',
|
|
|
|
|
'slot_roles',
|
|
|
|
|
|
2013-02-14 11:36:35 +00:00
|
|
|
'recentchanges',
|
|
|
|
|
'logging',
|
|
|
|
|
|
|
|
|
|
'page_props',
|
|
|
|
|
'pagelinks',
|
|
|
|
|
'categorylinks',
|
|
|
|
|
'langlinks',
|
|
|
|
|
'externallinks',
|
|
|
|
|
'imagelinks',
|
|
|
|
|
'templatelinks',
|
2017-10-12 12:23:33 +00:00
|
|
|
'iwlinks'
|
|
|
|
|
]
|
|
|
|
|
);
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-20 18:11:08 +00:00
|
|
|
protected function setUp() : void {
|
2012-10-23 17:02:36 +00:00
|
|
|
parent::setUp();
|
|
|
|
|
|
2017-10-11 14:02:38 +00:00
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgExtraNamespaces',
|
|
|
|
|
[
|
|
|
|
|
12312 => 'Dummy',
|
|
|
|
|
12313 => 'Dummy_talk',
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgNamespaceContentModels',
|
|
|
|
|
[
|
2017-10-12 12:23:33 +00:00
|
|
|
12312 => DummyContentForTesting::MODEL_ID,
|
2017-10-11 14:02:38 +00:00
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgContentHandlers',
|
|
|
|
|
[
|
2017-10-12 12:23:33 +00:00
|
|
|
DummyContentForTesting::MODEL_ID => 'DummyContentHandlerForTesting',
|
|
|
|
|
RevisionTestModifyableContent::MODEL_ID => 'RevisionTestModifyableContentHandler',
|
2017-10-11 14:02:38 +00:00
|
|
|
]
|
|
|
|
|
);
|
2012-05-02 10:54:27 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
if ( !$this->testPage ) {
|
2017-10-24 13:41:21 +00:00
|
|
|
/**
|
|
|
|
|
* We have to create a new page for each subclass as the page creation may result
|
|
|
|
|
* in different DB fields being filled based on configuration.
|
|
|
|
|
*/
|
|
|
|
|
$this->testPage = $this->createPage( __CLASS__, __CLASS__ );
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-03 17:15:37 +00:00
|
|
|
/**
|
|
|
|
|
* @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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
private function makeRevisionWithProps( $props = null ) {
|
2020-05-21 03:19:19 +00:00
|
|
|
$this->hideDeprecated( 'Revision::insertOn' );
|
|
|
|
|
|
2013-02-14 11:36:35 +00:00
|
|
|
if ( $props === null ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$props = [];
|
2013-02-14 11:36:35 +00:00
|
|
|
}
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2013-02-14 11:36:35 +00:00
|
|
|
if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) {
|
|
|
|
|
$props['text'] = 'Lorem Ipsum';
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
if ( !isset( $props['user_text'] ) ) {
|
2017-09-12 17:12:29 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
|
|
|
|
$props['user_text'] = $user->getName();
|
|
|
|
|
$props['user'] = $user->getId();
|
2017-08-31 18:41:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !isset( $props['user'] ) ) {
|
|
|
|
|
$props['user'] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-14 11:36:35 +00:00
|
|
|
if ( !isset( $props['comment'] ) ) {
|
|
|
|
|
$props['comment'] = 'just a test';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !isset( $props['page'] ) ) {
|
2017-10-13 15:39:24 +00:00
|
|
|
$props['page'] = $this->testPage->getId();
|
2013-02-14 11:36:35 +00:00
|
|
|
}
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
if ( !isset( $props['content_model'] ) ) {
|
|
|
|
|
$props['content_model'] = CONTENT_MODEL_WIKITEXT;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
$rev = new Revision( $props );
|
|
|
|
|
|
2016-03-18 13:55:54 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2012-05-02 17:34:35 +00:00
|
|
|
$rev->insertOn( $dbw );
|
|
|
|
|
|
|
|
|
|
return $rev;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-11 13:56:37 +00:00
|
|
|
/**
|
|
|
|
|
* @param string $titleString
|
|
|
|
|
* @param string $text
|
|
|
|
|
* @param string|null $model
|
|
|
|
|
*
|
|
|
|
|
* @return WikiPage
|
|
|
|
|
*/
|
2017-10-13 15:39:24 +00:00
|
|
|
private function createPage( $titleString, $text, $model = null ) {
|
2017-10-11 13:56:37 +00:00
|
|
|
if ( !preg_match( '/:/', $titleString ) &&
|
|
|
|
|
( $model === null || $model === CONTENT_MODEL_WIKITEXT )
|
|
|
|
|
) {
|
|
|
|
|
$ns = $this->getDefaultWikitextNS();
|
2018-08-05 17:58:51 +00:00
|
|
|
$titleString = MediaWikiServices::getInstance()->getNamespaceInfo()->
|
|
|
|
|
getCanonicalName( $ns ) . ':' . $titleString;
|
2012-10-12 16:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
2017-10-11 13:56:37 +00:00
|
|
|
$title = Title::newFromText( $titleString );
|
|
|
|
|
$wikipage = new WikiPage( $title );
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-11 13:56:37 +00:00
|
|
|
// Delete the article if it already exists
|
|
|
|
|
if ( $wikipage->exists() ) {
|
2020-03-25 17:05:26 +00:00
|
|
|
$wikipage->doDeleteArticleReal( "done", $this->getTestSysop()->getUser() );
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
2017-10-11 13:56:37 +00:00
|
|
|
$content = ContentHandler::makeContent( $text, $title, $model );
|
|
|
|
|
$wikipage->doEditContent( $content, __METHOD__, EDIT_NEW );
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-11 13:56:37 +00:00
|
|
|
return $wikipage;
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
private function assertRevEquals( Revision $orig, Revision $rev = null ) {
|
2020-04-29 05:37:47 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getSha1' );
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentFormat' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentHandler' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
2020-04-29 05:37:47 +00:00
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
$this->assertNotNull( $rev, 'missing revision' );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $orig->getId(), $rev->getId() );
|
|
|
|
|
$this->assertEquals( $orig->getPage(), $rev->getPage() );
|
|
|
|
|
$this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() );
|
|
|
|
|
$this->assertEquals( $orig->getUser(), $rev->getUser() );
|
2012-05-13 22:02:29 +00:00
|
|
|
$this->assertEquals( $orig->getContentModel(), $rev->getContentModel() );
|
2012-05-02 10:54:27 +00:00
|
|
|
$this->assertEquals( $orig->getContentFormat(), $rev->getContentFormat() );
|
2012-05-02 17:34:35 +00:00
|
|
|
$this->assertEquals( $orig->getSha1(), $rev->getSha1() );
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-14 12:13:43 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getRecentChange
|
|
|
|
|
*/
|
|
|
|
|
public function testGetRecentChange() {
|
2020-03-30 17:52:30 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getRecentChange' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-05-26 22:01:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getUserText' );
|
2020-03-30 17:52:30 +00:00
|
|
|
|
2017-11-14 12:13:43 +00:00
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
$recentChange = $rev->getRecentChange();
|
|
|
|
|
|
|
|
|
|
// Make sure various attributes look right / the correct entry has been retrieved.
|
|
|
|
|
$this->assertEquals( $rev->getTimestamp(), $recentChange->getAttribute( 'rc_timestamp' ) );
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
$rev->getTitle()->getNamespace(),
|
|
|
|
|
$recentChange->getAttribute( 'rc_namespace' )
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
$rev->getTitle()->getDBkey(),
|
|
|
|
|
$recentChange->getAttribute( 'rc_title' )
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals( $rev->getUser(), $recentChange->getAttribute( 'rc_user' ) );
|
|
|
|
|
$this->assertEquals( $rev->getUserText(), $recentChange->getAttribute( 'rc_user_text' ) );
|
|
|
|
|
$this->assertEquals( $rev->getComment(), $recentChange->getAttribute( 'rc_comment' ) );
|
|
|
|
|
$this->assertEquals( $rev->getPage(), $recentChange->getAttribute( 'rc_cur_id' ) );
|
|
|
|
|
$this->assertEquals( $rev->getId(), $recentChange->getAttribute( 'rc_this_oldid' ) );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-26 12:03:43 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::insertOn
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertOn_success() {
|
2020-03-30 17:52:30 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getTextId' );
|
2020-05-21 03:19:19 +00:00
|
|
|
$this->hideDeprecated( 'Revision::insertOn' );
|
2020-03-30 17:52:30 +00:00
|
|
|
|
2017-10-26 12:03:43 +00:00
|
|
|
$parentId = $this->testPage->getLatest();
|
|
|
|
|
|
|
|
|
|
// If an ExternalStore is set don't use it.
|
|
|
|
|
$this->setMwGlobals( 'wgDefaultExternalStore', false );
|
|
|
|
|
|
|
|
|
|
$rev = new Revision( [
|
|
|
|
|
'page' => $this->testPage->getId(),
|
|
|
|
|
'title' => $this->testPage->getTitle(),
|
|
|
|
|
'text' => 'Revision Text',
|
|
|
|
|
'comment' => 'Revision comment',
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$revId = $rev->insertOn( wfGetDB( DB_MASTER ) );
|
|
|
|
|
|
2019-12-13 14:29:10 +00:00
|
|
|
$this->assertIsInt( $revId );
|
2017-12-19 10:42:34 +00:00
|
|
|
$this->assertSame( $revId, $rev->getId() );
|
2017-08-31 18:41:04 +00:00
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
// getTextId() must be an int!
|
2019-12-13 14:29:10 +00:00
|
|
|
$this->assertIsInt( $rev->getTextId() );
|
2017-08-31 18:41:04 +00:00
|
|
|
|
2018-09-24 21:10:08 +00:00
|
|
|
$mainSlot = $rev->getRevisionRecord()->getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
|
2017-08-31 18:41:04 +00:00
|
|
|
|
|
|
|
|
// we currently only support storage in the text table
|
|
|
|
|
$textId = MediaWikiServices::getInstance()
|
|
|
|
|
->getBlobStore()
|
|
|
|
|
->getTextIdFromAddress( $mainSlot->getAddress() );
|
|
|
|
|
|
2017-10-26 12:03:43 +00:00
|
|
|
$this->assertSelect(
|
|
|
|
|
'text',
|
|
|
|
|
[ 'old_id', 'old_text' ],
|
2017-08-31 18:41:04 +00:00
|
|
|
"old_id = $textId",
|
|
|
|
|
[ [ strval( $textId ), 'Revision Text' ] ]
|
2017-10-26 12:03:43 +00:00
|
|
|
);
|
|
|
|
|
$this->assertSelect(
|
|
|
|
|
'revision',
|
|
|
|
|
[
|
|
|
|
|
'rev_id',
|
|
|
|
|
'rev_page',
|
|
|
|
|
'rev_minor_edit',
|
|
|
|
|
'rev_deleted',
|
|
|
|
|
'rev_len',
|
|
|
|
|
'rev_parent_id',
|
|
|
|
|
'rev_sha1',
|
|
|
|
|
],
|
|
|
|
|
"rev_id = {$rev->getId()}",
|
|
|
|
|
[ [
|
|
|
|
|
strval( $rev->getId() ),
|
|
|
|
|
strval( $this->testPage->getId() ),
|
|
|
|
|
'0',
|
|
|
|
|
'0',
|
|
|
|
|
'13',
|
|
|
|
|
strval( $parentId ),
|
|
|
|
|
's0ngbdoxagreuf2vjtuxzwdz64n29xm',
|
|
|
|
|
] ]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 07:49:20 +00:00
|
|
|
public function provideInsertOn_exceptionOnIncomplete() {
|
|
|
|
|
$content = new TextContent( '' );
|
|
|
|
|
$user = User::newFromName( 'Foo' );
|
|
|
|
|
|
|
|
|
|
yield 'no parent' => [
|
|
|
|
|
[
|
|
|
|
|
'content' => $content,
|
|
|
|
|
'comment' => 'test',
|
|
|
|
|
'user' => $user,
|
|
|
|
|
],
|
|
|
|
|
IncompleteRevisionException::class,
|
|
|
|
|
"rev_page field must not be 0!"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'no comment' => [
|
|
|
|
|
[
|
|
|
|
|
'content' => $content,
|
|
|
|
|
'page' => 7,
|
|
|
|
|
'user' => $user,
|
|
|
|
|
],
|
|
|
|
|
IncompleteRevisionException::class,
|
|
|
|
|
"comment must not be NULL!"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'no content' => [
|
|
|
|
|
[
|
|
|
|
|
'comment' => 'test',
|
|
|
|
|
'page' => 7,
|
|
|
|
|
'user' => $user,
|
|
|
|
|
],
|
|
|
|
|
IncompleteRevisionException::class,
|
2019-12-17 16:20:32 +00:00
|
|
|
"main slot must be provided" // XXX: message may change
|
2018-04-17 07:49:20 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-26 12:03:43 +00:00
|
|
|
/**
|
2018-04-17 07:49:20 +00:00
|
|
|
* @dataProvider provideInsertOn_exceptionOnIncomplete
|
2017-10-26 12:03:43 +00:00
|
|
|
* @covers Revision::insertOn
|
|
|
|
|
*/
|
2018-04-17 07:49:20 +00:00
|
|
|
public function testInsertOn_exceptionOnIncomplete( $array, $expException, $expMessage ) {
|
2020-05-21 03:19:19 +00:00
|
|
|
$this->hideDeprecated( 'Revision::insertOn' );
|
|
|
|
|
|
2017-10-26 12:03:43 +00:00
|
|
|
// If an ExternalStore is set don't use it.
|
|
|
|
|
$this->setMwGlobals( 'wgDefaultExternalStore', false );
|
2019-10-06 12:54:19 +00:00
|
|
|
$this->expectException( $expException );
|
|
|
|
|
$this->expectExceptionMessage( $expMessage );
|
2017-10-26 12:03:43 +00:00
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
$title = Title::newFromText( 'Nonexistant-' . __METHOD__ );
|
2018-04-17 07:49:20 +00:00
|
|
|
$rev = new Revision( $array, 0, $title );
|
2017-10-26 12:03:43 +00:00
|
|
|
|
|
|
|
|
$rev->insertOn( wfGetDB( DB_MASTER ) );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-11 13:56:37 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromTitle_withoutId() {
|
2020-04-15 21:50:29 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromTitle' );
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$latestRevId = $this->testPage->getLatest();
|
2017-10-11 13:56:37 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$rev = Revision::newFromTitle( $this->testPage->getTitle() );
|
2017-10-11 13:56:37 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->assertTrue( $this->testPage->getTitle()->equals( $rev->getTitle() ) );
|
2017-10-11 13:56:37 +00:00
|
|
|
$this->assertEquals( $latestRevId, $rev->getId() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromTitle_withId() {
|
2020-04-15 21:50:29 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromTitle' );
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$latestRevId = $this->testPage->getLatest();
|
2017-10-11 13:56:37 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$rev = Revision::newFromTitle( $this->testPage->getTitle(), $latestRevId );
|
2017-10-11 13:56:37 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->assertTrue( $this->testPage->getTitle()->equals( $rev->getTitle() ) );
|
2017-10-11 13:56:37 +00:00
|
|
|
$this->assertEquals( $latestRevId, $rev->getId() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromTitle_withBadId() {
|
2020-04-15 21:50:29 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromTitle' );
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$latestRevId = $this->testPage->getLatest();
|
2017-10-11 13:56:37 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$rev = Revision::newFromTitle( $this->testPage->getTitle(), $latestRevId + 1 );
|
2017-10-11 13:56:37 +00:00
|
|
|
|
|
|
|
|
$this->assertNull( $rev );
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromRow
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testNewFromRow() {
|
2017-10-13 15:39:24 +00:00
|
|
|
$orig = $this->makeRevisionWithProps();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2020-03-26 22:40:22 +00:00
|
|
|
$revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo();
|
2017-10-06 17:03:55 +00:00
|
|
|
$res = $dbr->select( $revQuery['tables'], $revQuery['fields'], [ 'rev_id' => $orig->getId() ],
|
|
|
|
|
__METHOD__, [], $revQuery['joins'] );
|
2019-12-29 10:50:03 +00:00
|
|
|
$this->assertIsObject( $res, 'query failed' );
|
2012-05-02 17:34:35 +00:00
|
|
|
|
|
|
|
|
$row = $res->fetchObject();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
2020-03-06 06:16:49 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::newFromRow' );
|
2012-05-02 17:34:35 +00:00
|
|
|
$rev = Revision::newFromRow( $row );
|
|
|
|
|
|
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-17 11:35:28 +00:00
|
|
|
public function provideNewFromArchiveRow() {
|
|
|
|
|
yield [
|
|
|
|
|
function ( $f ) {
|
|
|
|
|
return $f;
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
yield [
|
|
|
|
|
function ( $f ) {
|
|
|
|
|
return $f + [ 'ar_namespace', 'ar_title' ];
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
yield [
|
|
|
|
|
function ( $f ) {
|
|
|
|
|
unset( $f['ar_text_id'] );
|
|
|
|
|
return $f;
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-08-31 18:41:04 +00:00
|
|
|
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;
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-10-14 10:25:28 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
/**
|
2017-10-17 11:35:28 +00:00
|
|
|
* @dataProvider provideNewFromArchiveRow
|
2012-05-02 17:34:35 +00:00
|
|
|
* @covers Revision::newFromArchiveRow
|
|
|
|
|
*/
|
2017-10-24 13:41:21 +00:00
|
|
|
public function testNewFromArchiveRow( $selectModifier ) {
|
2020-04-01 17:47:23 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromArchiveRow' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-04-01 17:47:23 +00:00
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
|
|
|
|
|
|
$store = new RevisionStore(
|
|
|
|
|
$services->getDBLoadBalancer(),
|
|
|
|
|
$services->getService( '_SqlBlobStore' ),
|
2018-01-29 14:25:49 +00:00
|
|
|
$services->getMainWANObjectCache(),
|
2017-09-12 17:12:29 +00:00
|
|
|
$services->getCommentStore(),
|
2018-01-29 15:54:02 +00:00
|
|
|
$services->getContentModelStore(),
|
|
|
|
|
$services->getSlotRoleStore(),
|
2018-11-19 11:39:56 +00:00
|
|
|
$services->getSlotRoleRegistry(),
|
2020-01-18 20:25:04 +00:00
|
|
|
$services->getActorMigration(),
|
Hooks::run() call site migration
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
2020-03-19 02:42:09 +00:00
|
|
|
$services->getContentHandlerFactory(),
|
|
|
|
|
$services->getHookContainer()
|
2017-08-31 18:41:04 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->setService( 'RevisionStore', $store );
|
|
|
|
|
|
2014-04-24 12:35:05 +00:00
|
|
|
$page = $this->createPage(
|
|
|
|
|
'RevisionStorageTest_testNewFromArchiveRow',
|
|
|
|
|
'Lorem Ipsum',
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
2012-05-02 17:34:35 +00:00
|
|
|
$orig = $page->getRevision();
|
2020-03-25 17:05:26 +00:00
|
|
|
$page->doDeleteArticleReal(
|
|
|
|
|
'test Revision::newFromArchiveRow',
|
|
|
|
|
$this->getTestSysop()->getUser()
|
|
|
|
|
);
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2020-03-26 22:40:22 +00:00
|
|
|
$arQuery = $services->getRevisionStore()->getArchiveQueryInfo();
|
2017-10-06 17:03:55 +00:00
|
|
|
$arQuery['fields'] = $selectModifier( $arQuery['fields'] );
|
2017-06-06 17:39:14 +00:00
|
|
|
$res = $dbr->select(
|
2017-10-06 17:03:55 +00:00
|
|
|
$arQuery['tables'], $arQuery['fields'], [ 'ar_rev_id' => $orig->getId() ],
|
|
|
|
|
__METHOD__, [], $arQuery['joins']
|
2017-06-06 17:39:14 +00:00
|
|
|
);
|
2019-12-29 10:50:03 +00:00
|
|
|
$this->assertIsObject( $res, 'query failed' );
|
2012-05-02 17:34:35 +00:00
|
|
|
|
|
|
|
|
$row = $res->fetchObject();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
// MCR migration note: $row is now required to contain ar_title and ar_namespace.
|
|
|
|
|
// Alternatively, a Title object can be passed to RevisionStore::newRevisionFromArchiveRow
|
2012-05-02 17:34:35 +00:00
|
|
|
$rev = Revision::newFromArchiveRow( $row );
|
|
|
|
|
|
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-17 11:35:28 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromArchiveRow
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromArchiveRowOverrides() {
|
2020-04-01 17:47:23 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromArchiveRow' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-04-01 17:47:23 +00:00
|
|
|
|
2017-10-17 11:35:28 +00:00
|
|
|
$page = $this->createPage(
|
|
|
|
|
'RevisionStorageTest_testNewFromArchiveRow',
|
|
|
|
|
'Lorem Ipsum',
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
|
|
|
|
$orig = $page->getRevision();
|
2020-03-25 17:05:26 +00:00
|
|
|
$page->doDeleteArticleReal(
|
|
|
|
|
'test Revision::newFromArchiveRow',
|
|
|
|
|
$this->getTestSysop()->getUser()
|
|
|
|
|
);
|
2017-10-17 11:35:28 +00:00
|
|
|
|
|
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2020-03-26 22:40:22 +00:00
|
|
|
$arQuery = MediaWikiServices::getInstance()
|
|
|
|
|
->getRevisionStore()
|
|
|
|
|
->getArchiveQueryInfo();
|
2017-10-17 11:35:28 +00:00
|
|
|
$res = $dbr->select(
|
2017-10-06 17:03:55 +00:00
|
|
|
$arQuery['tables'], $arQuery['fields'], [ 'ar_rev_id' => $orig->getId() ],
|
|
|
|
|
__METHOD__, [], $arQuery['joins']
|
2017-10-17 11:35:28 +00:00
|
|
|
);
|
2019-12-29 10:50:03 +00:00
|
|
|
$this->assertIsObject( $res, 'query failed' );
|
2017-10-17 11:35:28 +00:00
|
|
|
|
|
|
|
|
$row = $res->fetchObject();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
2017-08-31 18:41:04 +00:00
|
|
|
$rev = Revision::newFromArchiveRow( $row, [ 'comment_text' => 'SOMEOVERRIDE' ] );
|
2017-10-17 11:35:28 +00:00
|
|
|
|
|
|
|
|
$this->assertNotEquals( $orig->getComment(), $rev->getComment() );
|
|
|
|
|
$this->assertEquals( 'SOMEOVERRIDE', $rev->getComment() );
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromId
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testNewFromId() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-06-03 02:56:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$orig = $this->testPage->getRevision();
|
2012-05-02 17:34:35 +00:00
|
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-14 10:17:39 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromPageId
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromPageId() {
|
2020-03-04 02:43:46 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::newFromPageId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
|
|
|
|
|
2017-10-14 10:17:39 +00:00
|
|
|
$rev = Revision::newFromPageId( $this->testPage->getId() );
|
|
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
$rev
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromPageId
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromPageIdWithLatestId() {
|
2020-03-04 02:43:46 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::newFromPageId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
|
|
|
|
|
2017-10-14 10:17:39 +00:00
|
|
|
$rev = Revision::newFromPageId(
|
|
|
|
|
$this->testPage->getId(),
|
|
|
|
|
$this->testPage->getLatest()
|
|
|
|
|
);
|
|
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
$rev
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::newFromPageId
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromPageIdWithNotLatestId() {
|
2017-08-31 18:41:04 +00:00
|
|
|
$content = new WikitextContent( __METHOD__ );
|
|
|
|
|
$this->testPage->doEditContent( $content, __METHOD__ );
|
2020-03-04 02:43:46 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::newFromPageId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-06-03 00:21:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getPrevious' );
|
2020-04-18 02:39:58 +00:00
|
|
|
|
2017-10-14 10:17:39 +00:00
|
|
|
$rev = Revision::newFromPageId(
|
|
|
|
|
$this->testPage->getId(),
|
|
|
|
|
$this->testPage->getRevision()->getPrevious()->getId()
|
|
|
|
|
);
|
|
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision()->getPrevious(),
|
|
|
|
|
$rev
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getPage
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testGetPage() {
|
2020-06-03 02:56:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromId' );
|
2017-10-13 15:39:24 +00:00
|
|
|
$page = $this->testPage;
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$orig = $this->makeRevisionWithProps( [ 'page' => $page->getId() ] );
|
2012-05-02 17:34:35 +00:00
|
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $page->getId(), $rev->getPage() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::isCurrent
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testIsCurrent() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-05-26 22:01:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::isCurrent' );
|
2020-06-03 02:56:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newFromId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$rev1 = $this->testPage->getRevision();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2013-05-15 01:12:35 +00:00
|
|
|
# @todo find out if this should be true
|
2012-05-02 17:34:35 +00:00
|
|
|
# $this->assertTrue( $rev1->isCurrent() );
|
|
|
|
|
|
|
|
|
|
$rev1x = Revision::newFromId( $rev1->getId() );
|
|
|
|
|
$this->assertTrue( $rev1x->isCurrent() );
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$rev2 = $this->testPage->getRevision();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2013-05-15 01:12:35 +00:00
|
|
|
# @todo find out if this should be true
|
2012-05-02 17:34:35 +00:00
|
|
|
# $this->assertTrue( $rev2->isCurrent() );
|
|
|
|
|
|
|
|
|
|
$rev1x = Revision::newFromId( $rev1->getId() );
|
|
|
|
|
$this->assertFalse( $rev1x->isCurrent() );
|
|
|
|
|
|
|
|
|
|
$rev2x = Revision::newFromId( $rev2->getId() );
|
|
|
|
|
$this->assertTrue( $rev2x->isCurrent() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getPrevious
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testGetPrevious() {
|
2020-04-08 03:00:33 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getOldestRevision' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-06-03 00:21:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getPrevious' );
|
2020-04-08 03:00:33 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$oldestRevision = $this->testPage->getOldestRevision();
|
|
|
|
|
$latestRevision = $this->testPage->getLatest();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->assertNull( $oldestRevision->getPrevious() );
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$newRevision = $this->testPage->getRevision();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->assertNotNull( $newRevision->getPrevious() );
|
|
|
|
|
$this->assertEquals( $latestRevision, $newRevision->getPrevious()->getId() );
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-29 14:24:58 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Title::getPreviousRevisionID
|
|
|
|
|
* @covers Title::getRelativeRevisionID
|
|
|
|
|
* @covers MediaWiki\Revision\RevisionStore::getPreviousRevision
|
|
|
|
|
* @covers MediaWiki\Revision\RevisionStore::getRelativeRevision
|
|
|
|
|
*/
|
|
|
|
|
public function testTitleGetPreviousRevisionID() {
|
2020-04-08 03:00:33 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getOldestRevision' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-04-08 03:00:33 +00:00
|
|
|
|
2019-04-29 14:24:58 +00:00
|
|
|
$oldestId = $this->testPage->getOldestRevision()->getId();
|
|
|
|
|
$latestId = $this->testPage->getLatest();
|
|
|
|
|
|
|
|
|
|
$title = $this->testPage->getTitle();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $title->getPreviousRevisionID( $oldestId ) );
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$newId = $this->testPage->getRevision()->getId();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $latestId, $title->getPreviousRevisionID( $newId ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::getPreviousRevisionID
|
|
|
|
|
* @covers Title::getRelativeRevisionID
|
|
|
|
|
*/
|
|
|
|
|
public function testTitleGetPreviousRevisionID_invalid() {
|
|
|
|
|
$this->assertFalse( $this->testPage->getTitle()->getPreviousRevisionID( 123456789 ) );
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getNext
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testGetNext() {
|
2020-04-27 04:10:02 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getNext' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$rev1 = $this->testPage->getRevision();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
|
|
|
|
$this->assertNull( $rev1->getNext() );
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$rev2 = $this->testPage->getRevision();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
|
|
|
|
$this->assertNotNull( $rev1->getNext() );
|
|
|
|
|
$this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-29 14:24:58 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Title::getNextRevisionID
|
|
|
|
|
* @covers Title::getRelativeRevisionID
|
|
|
|
|
* @covers MediaWiki\Revision\RevisionStore::getNextRevision
|
|
|
|
|
* @covers MediaWiki\Revision\RevisionStore::getRelativeRevision
|
|
|
|
|
*/
|
|
|
|
|
public function testTitleGetNextRevisionID() {
|
|
|
|
|
$title = $this->testPage->getTitle();
|
|
|
|
|
|
|
|
|
|
$origId = $this->testPage->getLatest();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $title->getNextRevisionID( $origId ) );
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$newId = $this->testPage->getLatest();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $this->testPage->getLatest(), $title->getNextRevisionID( $origId ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::getNextRevisionID
|
|
|
|
|
* @covers Title::getRelativeRevisionID
|
|
|
|
|
*/
|
|
|
|
|
public function testTitleGetNextRevisionID_invalid() {
|
|
|
|
|
$this->assertFalse( $this->testPage->getTitle()->getNextRevisionID( 123456789 ) );
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newNullRevision
|
|
|
|
|
*/
|
2013-01-28 10:27:15 +00:00
|
|
|
public function testNewNullRevision() {
|
2020-03-30 17:52:30 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getTextId' );
|
2020-04-11 05:08:23 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newNullRevision' );
|
2020-04-29 05:37:47 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getSha1' );
|
2020-06-08 02:38:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContent' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-03-30 17:52:30 +00:00
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$orig = $this->testPage->getRevision();
|
2020-01-18 00:12:29 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
2012-05-02 17:34:35 +00:00
|
|
|
|
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2020-01-18 00:12:29 +00:00
|
|
|
$rev = Revision::newNullRevision(
|
|
|
|
|
$dbw, $this->testPage->getId(), 'a null revision', false, $user
|
|
|
|
|
);
|
2012-05-02 17:34:35 +00:00
|
|
|
|
2012-08-20 19:33:07 +00:00
|
|
|
$this->assertNotEquals( $orig->getId(), $rev->getId(),
|
2017-10-13 15:39:24 +00:00
|
|
|
'new null revision should have a different id from the original revision' );
|
2012-08-20 19:33:07 +00:00
|
|
|
$this->assertEquals( $orig->getTextId(), $rev->getTextId(),
|
2017-10-13 15:39:24 +00:00
|
|
|
'new null revision should have the same text id as the original revision' );
|
2017-08-31 18:41:04 +00:00
|
|
|
$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' );
|
2019-02-07 00:14:23 +00:00
|
|
|
$this->assertEquals( __METHOD__, $rev->getContent()->getText() );
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|
2012-08-30 17:17:14 +00:00
|
|
|
|
2018-01-11 12:56:17 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newNullRevision
|
|
|
|
|
*/
|
|
|
|
|
public function testNewNullRevision_badPage() {
|
2020-04-11 05:08:23 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newNullRevision' );
|
2018-01-11 12:56:17 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2020-01-18 00:12:29 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
|
|
|
|
$rev = Revision::newNullRevision( $dbw, -1, 'a null revision', false, $user );
|
2018-01-11 12:56:17 +00:00
|
|
|
|
|
|
|
|
$this->assertNull( $rev );
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-21 16:17:59 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::insertOn
|
|
|
|
|
*/
|
|
|
|
|
public function testInsertOn() {
|
|
|
|
|
$ip = '2600:387:ed7:947e:8c16:a1ad:dd34:1dd7';
|
|
|
|
|
|
2017-10-13 15:39:24 +00:00
|
|
|
$orig = $this->makeRevisionWithProps( [
|
2017-04-21 16:17:59 +00:00
|
|
|
'user_text' => $ip
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
// Make sure the revision was copied to ip_changes
|
|
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
|
|
|
|
$res = $dbr->select( 'ip_changes', '*', [ 'ipc_rev_id' => $orig->getId() ] );
|
|
|
|
|
$row = $res->fetchObject();
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
$this->assertEquals( IP::toHex( $ip ), $row->ipc_hex );
|
2017-11-30 13:49:17 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
$orig->getTimestamp(),
|
|
|
|
|
wfTimestamp( TS_MW, $row->ipc_rev_timestamp )
|
|
|
|
|
);
|
2017-04-21 16:17:59 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideUserWasLastToEdit() {
|
2017-10-10 16:58:13 +00:00
|
|
|
yield 'actually the last edit' => [ 3, true ];
|
|
|
|
|
yield 'not the current edit, but still by this user' => [ 2, true ];
|
|
|
|
|
yield 'edit by another user' => [ 1, false ];
|
|
|
|
|
yield 'first edit, by this user, but another user edited in the mean time' => [ 0, false ];
|
2012-08-30 17:17:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-25 07:28:03 +00:00
|
|
|
* @covers Revision::userWasLastToEdit
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideUserWasLastToEdit
|
2012-08-30 17:17:14 +00:00
|
|
|
*/
|
|
|
|
|
public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
|
2020-03-25 21:19:44 +00:00
|
|
|
$this->hideDeprecated( 'Revision::userWasLastToEdit' );
|
2020-05-21 03:19:19 +00:00
|
|
|
$this->hideDeprecated( 'Revision::insertOn' );
|
2013-10-21 21:09:13 +00:00
|
|
|
$userA = User::newFromName( "RevisionStorageTest_userA" );
|
|
|
|
|
$userB = User::newFromName( "RevisionStorageTest_userB" );
|
2012-08-30 17:17:14 +00:00
|
|
|
|
|
|
|
|
if ( $userA->getId() === 0 ) {
|
2013-10-21 21:09:13 +00:00
|
|
|
$userA = User::createNew( $userA->getName() );
|
2012-08-30 17:17:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $userB->getId() === 0 ) {
|
2013-10-21 21:09:13 +00:00
|
|
|
$userB = User::createNew( $userB->getName() );
|
2012-08-30 17:17:14 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-12 16:30:38 +00:00
|
|
|
$ns = $this->getDefaultWikitextNS();
|
|
|
|
|
|
2012-08-30 17:17:14 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2016-02-17 09:09:32 +00:00
|
|
|
$revisions = [];
|
2012-08-30 17:17:14 +00:00
|
|
|
|
|
|
|
|
// create revisions -----------------------------
|
2012-10-12 16:30:38 +00:00
|
|
|
$page = WikiPage::factory( Title::newFromText(
|
|
|
|
|
'RevisionStorageTest_testUserWasLastToEdit', $ns ) );
|
2013-12-07 15:40:58 +00:00
|
|
|
$page->insertOn( $dbw );
|
2012-08-30 17:17:14 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$revisions[0] = new Revision( [
|
2012-08-30 17:17:14 +00:00
|
|
|
'page' => $page->getId(),
|
2014-04-24 12:35:05 +00:00
|
|
|
// we need the title to determine the page's default content model
|
|
|
|
|
'title' => $page->getTitle(),
|
2012-08-30 17:17:14 +00:00
|
|
|
'timestamp' => '20120101000000',
|
|
|
|
|
'user' => $userA->getId(),
|
|
|
|
|
'text' => 'zero',
|
2012-09-19 18:07:56 +00:00
|
|
|
'content_model' => CONTENT_MODEL_WIKITEXT,
|
2017-08-31 18:41:04 +00:00
|
|
|
'comment' => 'edit zero'
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2012-08-30 17:17:14 +00:00
|
|
|
$revisions[0]->insertOn( $dbw );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$revisions[1] = new Revision( [
|
2012-08-30 17:17:14 +00:00
|
|
|
'page' => $page->getId(),
|
2014-04-24 12:35:05 +00:00
|
|
|
// still need the title, because $page->getId() is 0 (there's no entry in the page table)
|
|
|
|
|
'title' => $page->getTitle(),
|
2012-08-30 17:17:14 +00:00
|
|
|
'timestamp' => '20120101000100',
|
|
|
|
|
'user' => $userA->getId(),
|
|
|
|
|
'text' => 'one',
|
2012-09-19 18:07:56 +00:00
|
|
|
'content_model' => CONTENT_MODEL_WIKITEXT,
|
2017-08-31 18:41:04 +00:00
|
|
|
'comment' => 'edit one'
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2012-08-30 17:17:14 +00:00
|
|
|
$revisions[1]->insertOn( $dbw );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$revisions[2] = new Revision( [
|
2012-08-30 17:17:14 +00:00
|
|
|
'page' => $page->getId(),
|
2012-09-18 15:43:20 +00:00
|
|
|
'title' => $page->getTitle(),
|
2012-08-30 17:17:14 +00:00
|
|
|
'timestamp' => '20120101000200',
|
|
|
|
|
'user' => $userB->getId(),
|
|
|
|
|
'text' => 'two',
|
2012-09-19 18:07:56 +00:00
|
|
|
'content_model' => CONTENT_MODEL_WIKITEXT,
|
2017-08-31 18:41:04 +00:00
|
|
|
'comment' => 'edit two'
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2012-08-30 17:17:14 +00:00
|
|
|
$revisions[2]->insertOn( $dbw );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$revisions[3] = new Revision( [
|
2012-08-30 17:17:14 +00:00
|
|
|
'page' => $page->getId(),
|
2012-09-18 15:43:20 +00:00
|
|
|
'title' => $page->getTitle(),
|
2012-08-30 17:17:14 +00:00
|
|
|
'timestamp' => '20120101000300',
|
|
|
|
|
'user' => $userA->getId(),
|
|
|
|
|
'text' => 'three',
|
2012-09-19 18:07:56 +00:00
|
|
|
'content_model' => CONTENT_MODEL_WIKITEXT,
|
2017-08-31 18:41:04 +00:00
|
|
|
'comment' => 'edit three'
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2012-08-30 17:17:14 +00:00
|
|
|
$revisions[3]->insertOn( $dbw );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$revisions[4] = new Revision( [
|
2012-08-30 17:17:14 +00:00
|
|
|
'page' => $page->getId(),
|
2012-09-18 15:43:20 +00:00
|
|
|
'title' => $page->getTitle(),
|
2012-08-30 17:17:14 +00:00
|
|
|
'timestamp' => '20120101000200',
|
|
|
|
|
'user' => $userA->getId(),
|
|
|
|
|
'text' => 'zero',
|
2012-09-19 18:07:56 +00:00
|
|
|
'content_model' => CONTENT_MODEL_WIKITEXT,
|
2017-08-31 18:41:04 +00:00
|
|
|
'comment' => 'edit four'
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2012-08-30 17:17:14 +00:00
|
|
|
$revisions[4]->insertOn( $dbw );
|
|
|
|
|
|
|
|
|
|
// test it ---------------------------------
|
2013-02-14 11:36:35 +00:00
|
|
|
$since = $revisions[$sinceIdx]->getTimestamp();
|
2012-08-30 17:17:14 +00:00
|
|
|
|
2020-03-26 22:40:22 +00:00
|
|
|
$revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo();
|
2017-08-31 18:41:04 +00:00
|
|
|
$allRows = iterator_to_array( $dbw->select(
|
2017-09-12 17:12:29 +00:00
|
|
|
$revQuery['tables'],
|
|
|
|
|
[ 'rev_id', 'rev_timestamp', 'rev_user' => $revQuery['fields']['rev_user'] ],
|
2017-08-31 18:41:04 +00:00
|
|
|
[
|
|
|
|
|
'rev_page' => $page->getId(),
|
2020-05-10 00:09:19 +00:00
|
|
|
// 'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $since ) )
|
2017-08-31 18:41:04 +00:00
|
|
|
],
|
|
|
|
|
__METHOD__,
|
2017-09-12 17:12:29 +00:00
|
|
|
[ 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 50 ],
|
|
|
|
|
$revQuery['joins']
|
2017-08-31 18:41:04 +00:00
|
|
|
) );
|
|
|
|
|
|
2012-08-30 17:17:14 +00:00
|
|
|
$wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expectedLast, $wasLast );
|
|
|
|
|
}
|
2017-10-12 12:23:33 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param string $text
|
|
|
|
|
* @param string $title
|
|
|
|
|
* @param string $model
|
2019-11-23 22:28:57 +00:00
|
|
|
* @param string|null $format
|
2017-10-12 12:23:33 +00:00
|
|
|
*
|
|
|
|
|
* @return Revision
|
|
|
|
|
*/
|
|
|
|
|
private function newTestRevision( $text, $title = "Test",
|
|
|
|
|
$model = CONTENT_MODEL_WIKITEXT, $format = null
|
|
|
|
|
) {
|
|
|
|
|
if ( is_string( $title ) ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$content = ContentHandler::makeContent( $text, $title, $model, $format );
|
|
|
|
|
|
|
|
|
|
$rev = new Revision(
|
|
|
|
|
[
|
|
|
|
|
'id' => 42,
|
|
|
|
|
'page' => 23,
|
|
|
|
|
'title' => $title,
|
|
|
|
|
|
|
|
|
|
'content' => $content,
|
|
|
|
|
'length' => $content->getSize(),
|
|
|
|
|
'comment' => "testing",
|
|
|
|
|
'minor_edit' => false,
|
|
|
|
|
|
|
|
|
|
'content_format' => $format,
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return $rev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideGetContentModel() {
|
|
|
|
|
// NOTE: we expect the help namespace to always contain wikitext
|
|
|
|
|
return [
|
|
|
|
|
[ 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ],
|
|
|
|
|
[ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetContentModel
|
|
|
|
|
* @covers Revision::getContentModel
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentModel( $text, $title, $model, $format, $expectedModel ) {
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = $this->newTestRevision( $text, $title, $model, $format );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expectedModel, $rev->getContentModel() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getContentModel
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentModelForEmptyRevision() {
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
$rev = new Revision( [], 0, $this->testPage->getTitle() );
|
|
|
|
|
|
|
|
|
|
$slotRoleHandler = MediaWikiServices::getInstance()->getSlotRoleRegistry()
|
|
|
|
|
->getRoleHandler( SlotRecord::MAIN );
|
|
|
|
|
|
|
|
|
|
$expectedModel = $slotRoleHandler->getDefaultModel( $this->testPage->getTitle() );
|
|
|
|
|
$this->assertEquals( $expectedModel, $rev->getContentModel() );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
public function provideGetContentFormat() {
|
|
|
|
|
// NOTE: we expect the help namespace to always contain wikitext
|
|
|
|
|
return [
|
|
|
|
|
[ 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ],
|
|
|
|
|
[ 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ],
|
|
|
|
|
[ 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ],
|
|
|
|
|
[ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetContentFormat
|
|
|
|
|
* @covers Revision::getContentFormat
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) {
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentFormat' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentHandler' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = $this->newTestRevision( $text, $title, $model, $format );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expectedFormat, $rev->getContentFormat() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getContentFormat
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentFormatForEmptyRevision() {
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentFormat' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentHandler' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
$rev = new Revision( [], 0, $this->testPage->getTitle() );
|
|
|
|
|
|
|
|
|
|
$slotRoleHandler = MediaWikiServices::getInstance()->getSlotRoleRegistry()
|
|
|
|
|
->getRoleHandler( SlotRecord::MAIN );
|
|
|
|
|
|
|
|
|
|
$expectedModel = $slotRoleHandler->getDefaultModel( $this->testPage->getTitle() );
|
|
|
|
|
$expectedFormat = ContentHandler::getForModelID( $expectedModel )->getDefaultFormat();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expectedFormat, $rev->getContentFormat() );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
public function provideGetContentHandler() {
|
|
|
|
|
// NOTE: we expect the help namespace to always contain wikitext
|
|
|
|
|
return [
|
2018-01-13 00:02:09 +00:00
|
|
|
[ 'hello world', 'Help:Hello', null, null, WikitextContentHandler::class ],
|
|
|
|
|
[ 'hello world', 'User:hello/there.css', null, null, CssContentHandler::class ],
|
|
|
|
|
[ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentHandlerForTesting::class ],
|
2017-10-12 12:23:33 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetContentHandler
|
|
|
|
|
* @covers Revision::getContentHandler
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) {
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentHandler' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = $this->newTestRevision( $text, $title, $model, $format );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideGetContent() {
|
|
|
|
|
// NOTE: we expect the help namespace to always contain wikitext
|
|
|
|
|
return [
|
|
|
|
|
[ 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ],
|
|
|
|
|
[
|
|
|
|
|
serialize( 'hello world' ),
|
|
|
|
|
'Hello',
|
|
|
|
|
DummyContentForTesting::MODEL_ID,
|
|
|
|
|
null,
|
|
|
|
|
Revision::FOR_PUBLIC,
|
|
|
|
|
serialize( 'hello world' )
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
serialize( 'hello world' ),
|
|
|
|
|
'Dummy:Hello',
|
|
|
|
|
null,
|
|
|
|
|
null,
|
|
|
|
|
Revision::FOR_PUBLIC,
|
|
|
|
|
serialize( 'hello world' )
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetContent
|
|
|
|
|
* @covers Revision::getContent
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContent( $text, $title, $model, $format,
|
|
|
|
|
$audience, $expectedSerialization
|
|
|
|
|
) {
|
2020-06-08 02:38:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContent' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = $this->newTestRevision( $text, $title, $model, $format );
|
|
|
|
|
$content = $rev->getContent( $audience );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
$expectedSerialization,
|
2020-01-09 23:48:34 +00:00
|
|
|
$content === null ? null : $content->serialize( $format )
|
2017-10-12 12:23:33 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getContent
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContent_failure() {
|
2020-06-08 02:38:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContent' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = new Revision( [
|
2017-10-13 15:39:24 +00:00
|
|
|
'page' => $this->testPage->getId(),
|
|
|
|
|
'content_model' => $this->testPage->getContentModel(),
|
2018-04-17 07:49:20 +00:00
|
|
|
'id' => 123456789, // not in the test DB
|
2017-10-12 12:23:33 +00:00
|
|
|
] );
|
|
|
|
|
|
2018-02-10 07:52:26 +00:00
|
|
|
Wikimedia\suppressWarnings(); // bad text_id will trigger a warning.
|
2017-08-31 18:41:04 +00:00
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$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." );
|
2017-08-31 18:41:04 +00:00
|
|
|
|
2018-02-10 07:52:26 +00:00
|
|
|
Wikimedia\restoreWarnings();
|
2017-10-12 12:23:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideGetSize() {
|
|
|
|
|
return [
|
|
|
|
|
[ "hello world.", CONTENT_MODEL_WIKITEXT, 12 ],
|
|
|
|
|
[ serialize( "hello world." ), DummyContentForTesting::MODEL_ID, 12 ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getSize
|
|
|
|
|
* @dataProvider provideGetSize
|
|
|
|
|
*/
|
|
|
|
|
public function testGetSize( $text, $model, $expected_size ) {
|
|
|
|
|
$rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model );
|
|
|
|
|
$this->assertEquals( $expected_size, $rev->getSize() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideGetSha1() {
|
2020-03-25 21:09:42 +00:00
|
|
|
$this->hideDeprecated( 'Revision::base36Sha1' );
|
2017-10-12 12:23:33 +00:00
|
|
|
return [
|
|
|
|
|
[ "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ],
|
|
|
|
|
[
|
|
|
|
|
serialize( "hello world." ),
|
|
|
|
|
DummyContentForTesting::MODEL_ID,
|
|
|
|
|
Revision::base36Sha1( serialize( "hello world." ) )
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getSha1
|
|
|
|
|
* @dataProvider provideGetSha1
|
|
|
|
|
*/
|
|
|
|
|
public function testGetSha1( $text, $model, $expected_hash ) {
|
2020-04-29 05:37:47 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getSha1' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model );
|
|
|
|
|
$this->assertEquals( $expected_hash, $rev->getSha1() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests whether $rev->getContent() returns a clone when needed.
|
|
|
|
|
*
|
|
|
|
|
* @covers Revision::getContent
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentClone() {
|
2020-06-08 02:38:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContent' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$content = new RevisionTestModifyableContent( "foo" );
|
|
|
|
|
|
|
|
|
|
$rev = new Revision(
|
|
|
|
|
[
|
|
|
|
|
'id' => 42,
|
|
|
|
|
'page' => 23,
|
|
|
|
|
'title' => Title::newFromText( "testGetContentClone_dummy" ),
|
|
|
|
|
|
|
|
|
|
'content' => $content,
|
|
|
|
|
'length' => $content->getSize(),
|
|
|
|
|
'comment' => "testing",
|
|
|
|
|
'minor_edit' => false,
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/** @var RevisionTestModifyableContent $content */
|
|
|
|
|
$content = $rev->getContent( Revision::RAW );
|
|
|
|
|
$content->setText( "bar" );
|
|
|
|
|
|
|
|
|
|
/** @var RevisionTestModifyableContent $content2 */
|
|
|
|
|
$content2 = $rev->getContent( Revision::RAW );
|
|
|
|
|
// content is mutable, expect clone
|
|
|
|
|
$this->assertNotSame( $content, $content2, "expected a clone" );
|
|
|
|
|
// clone should contain the original text
|
|
|
|
|
$this->assertEquals( "foo", $content2->getText() );
|
|
|
|
|
|
|
|
|
|
$content2->setText( "bla bla" );
|
|
|
|
|
// clones should be independent
|
|
|
|
|
$this->assertEquals( "bar", $content->getText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
|
|
|
|
|
* @covers Revision::getContent
|
|
|
|
|
*/
|
|
|
|
|
public function testGetContentUncloned() {
|
2020-06-08 02:38:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContent' );
|
|
|
|
|
|
2017-10-12 12:23:33 +00:00
|
|
|
$rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT );
|
|
|
|
|
$content = $rev->getContent( Revision::RAW );
|
|
|
|
|
$content2 = $rev->getContent( Revision::RAW );
|
|
|
|
|
|
|
|
|
|
// for immutable content like wikitext, this should be the same object
|
|
|
|
|
$this->assertSame( $content, $content2 );
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-14 10:35:11 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromPageId
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromPageId() {
|
2020-03-04 01:02:30 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::loadFromPageId' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromPageId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-10-14 10:35:11 +00:00
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
Revision::loadFromPageId( wfGetDB( DB_MASTER ), $this->testPage->getId() )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromPageId
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromPageIdWithLatestRevId() {
|
2020-03-04 01:02:30 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::loadFromPageId' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromPageId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-10-14 10:35:11 +00:00
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
Revision::loadFromPageId(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
$this->testPage->getId(),
|
|
|
|
|
$this->testPage->getLatest()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromPageId
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromPageIdWithNotLatestRevId() {
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
2020-03-04 01:02:30 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::loadFromPageId' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromPageId' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-06-03 00:21:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getPrevious' );
|
2017-10-14 10:35:11 +00:00
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision()->getPrevious(),
|
|
|
|
|
Revision::loadFromPageId(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
$this->testPage->getId(),
|
|
|
|
|
$this->testPage->getRevision()->getPrevious()->getId()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-14 10:38:38 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromTitle() {
|
2020-02-29 00:22:03 +00:00
|
|
|
$this->hideDeprecated( 'Revision::loadFromTitle' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromTitle' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-10-14 10:38:38 +00:00
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
Revision::loadFromTitle( wfGetDB( DB_MASTER ), $this->testPage->getTitle() )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromTitleWithLatestRevId() {
|
2020-02-29 00:22:03 +00:00
|
|
|
$this->hideDeprecated( 'Revision::loadFromTitle' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromTitle' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-10-14 10:38:38 +00:00
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
Revision::loadFromTitle(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
$this->testPage->getTitle(),
|
|
|
|
|
$this->testPage->getLatest()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromTitleWithNotLatestRevId() {
|
2020-02-29 00:22:03 +00:00
|
|
|
$this->hideDeprecated( 'Revision::loadFromTitle' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromTitle' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-06-03 00:21:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getPrevious' );
|
2017-10-14 10:38:38 +00:00
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision()->getPrevious(),
|
|
|
|
|
Revision::loadFromTitle(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
$this->testPage->getTitle(),
|
|
|
|
|
$this->testPage->getRevision()->getPrevious()->getId()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-14 10:40:56 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::loadFromTimestamp()
|
|
|
|
|
*/
|
|
|
|
|
public function testLoadFromTimestamp() {
|
2020-03-04 01:39:36 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::loadFromTimestamp' );
|
|
|
|
|
$this->hideDeprecated( RevisionStore::class . '::loadRevisionFromTimestamp' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-10-14 10:40:56 +00:00
|
|
|
$this->assertRevEquals(
|
|
|
|
|
$this->testPage->getRevision(),
|
|
|
|
|
Revision::loadFromTimestamp(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
$this->testPage->getTitle(),
|
|
|
|
|
$this->testPage->getRevision()->getTimestamp()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 10:20:49 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getParentLengths
|
|
|
|
|
*/
|
|
|
|
|
public function testGetParentLengths_noRevIds() {
|
2020-03-07 02:10:00 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::getParentLengths' );
|
2017-11-09 10:20:49 +00:00
|
|
|
$this->assertSame(
|
|
|
|
|
[],
|
|
|
|
|
Revision::getParentLengths(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
[]
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getParentLengths
|
|
|
|
|
*/
|
|
|
|
|
public function testGetParentLengths_oneRevId() {
|
|
|
|
|
$text = '831jr091jr0921kr21kr0921kjr0921j09rj1';
|
|
|
|
|
$textLength = strlen( $text );
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( $text ), __METHOD__ );
|
|
|
|
|
$rev[1] = $this->testPage->getLatest();
|
|
|
|
|
|
2020-03-07 02:10:00 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::getParentLengths' );
|
2017-11-09 10:20:49 +00:00
|
|
|
$this->assertSame(
|
2017-08-31 18:41:04 +00:00
|
|
|
[ $rev[1] => $textLength ],
|
2017-11-09 10:20:49 +00:00
|
|
|
Revision::getParentLengths(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
[ $rev[1] ]
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getParentLengths
|
|
|
|
|
*/
|
|
|
|
|
public function testGetParentLengths_multipleRevIds() {
|
|
|
|
|
$textOne = '831jr091jr0921kr21kr0921kjr0921j09rj1';
|
|
|
|
|
$textOneLength = strlen( $textOne );
|
|
|
|
|
$textTwo = '831jr091jr092121j09rj1';
|
|
|
|
|
$textTwoLength = strlen( $textTwo );
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( $textOne ), __METHOD__ );
|
|
|
|
|
$rev[1] = $this->testPage->getLatest();
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( $textTwo ), __METHOD__ );
|
|
|
|
|
$rev[2] = $this->testPage->getLatest();
|
|
|
|
|
|
2020-03-07 02:10:00 +00:00
|
|
|
$this->hideDeprecated( Revision::class . '::getParentLengths' );
|
2017-11-09 10:20:49 +00:00
|
|
|
$this->assertSame(
|
2017-08-31 18:41:04 +00:00
|
|
|
[ $rev[1] => $textOneLength, $rev[2] => $textTwoLength ],
|
2017-11-09 10:20:49 +00:00
|
|
|
Revision::getParentLengths(
|
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
|
[ $rev[1], $rev[2] ]
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 10:36:22 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::getTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTitle_fromExistingRevision() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-11-09 10:36:22 +00:00
|
|
|
$this->assertTrue(
|
|
|
|
|
$this->testPage->getTitle()->equals(
|
|
|
|
|
$this->testPage->getRevision()->getTitle()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTitle_fromRevisionWhichWillLoadTheTitle() {
|
|
|
|
|
$rev = new Revision( [ 'id' => $this->testPage->getLatest() ] );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$this->testPage->getTitle()->equals(
|
|
|
|
|
$rev->getTitle()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 11:45:51 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::isMinor
|
|
|
|
|
*/
|
|
|
|
|
public function testIsMinor_true() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-05-26 22:01:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::isMinor' );
|
|
|
|
|
|
2017-11-09 11:45:51 +00:00
|
|
|
// Use a sysop to ensure we can mark edits as minor
|
|
|
|
|
$sysop = $this->getTestSysop()->getUser();
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( __METHOD__ ),
|
|
|
|
|
__METHOD__,
|
|
|
|
|
EDIT_MINOR,
|
|
|
|
|
false,
|
|
|
|
|
$sysop
|
|
|
|
|
);
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( true, $rev->isMinor() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::isMinor
|
|
|
|
|
*/
|
|
|
|
|
public function testIsMinor_false() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-05-26 22:01:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::isMinor' );
|
|
|
|
|
|
2017-11-09 11:45:51 +00:00
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( __METHOD__ ),
|
|
|
|
|
__METHOD__,
|
|
|
|
|
0
|
|
|
|
|
);
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( false, $rev->isMinor() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getTimestamp
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTimestamp() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-11-09 11:45:51 +00:00
|
|
|
$testTimestamp = wfTimestampNow();
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( __METHOD__ ),
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
2019-12-13 14:29:10 +00:00
|
|
|
$this->assertIsString( $rev->getTimestamp() );
|
2017-11-09 11:45:51 +00:00
|
|
|
$this->assertTrue( strlen( $rev->getTimestamp() ) == strlen( 'YYYYMMDDHHMMSS' ) );
|
2019-12-14 12:45:35 +00:00
|
|
|
$this->assertStringContainsString( substr( $testTimestamp, 0, 10 ), $rev->getTimestamp() );
|
2017-11-09 11:45:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getUser
|
|
|
|
|
* @covers Revision::getUserText
|
|
|
|
|
*/
|
|
|
|
|
public function testGetUserAndText() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-05-26 22:01:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getUserText' );
|
|
|
|
|
|
2017-11-09 11:45:51 +00:00
|
|
|
$sysop = $this->getTestSysop()->getUser();
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( __METHOD__ ),
|
|
|
|
|
__METHOD__,
|
|
|
|
|
0,
|
|
|
|
|
false,
|
|
|
|
|
$sysop
|
|
|
|
|
);
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $sysop->getId(), $rev->getUser() );
|
|
|
|
|
$this->assertSame( $sysop->getName(), $rev->getUserText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::isDeleted
|
|
|
|
|
*/
|
|
|
|
|
public function testIsDeleted_nothingDeleted() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-06-03 00:21:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::isDeleted' );
|
2017-11-09 11:45:51 +00:00
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( false, $rev->isDeleted( Revision::DELETED_TEXT ) );
|
|
|
|
|
$this->assertSame( false, $rev->isDeleted( Revision::DELETED_COMMENT ) );
|
|
|
|
|
$this->assertSame( false, $rev->isDeleted( Revision::DELETED_RESTRICTED ) );
|
|
|
|
|
$this->assertSame( false, $rev->isDeleted( Revision::DELETED_USER ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getVisibility
|
|
|
|
|
*/
|
|
|
|
|
public function testGetVisibility_nothingDeleted() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-05-27 22:49:07 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getVisibility' );
|
|
|
|
|
|
2017-11-09 11:45:51 +00:00
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 0, $rev->getVisibility() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getComment
|
|
|
|
|
*/
|
|
|
|
|
public function testGetComment_notDeleted() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-11-09 11:45:51 +00:00
|
|
|
$expectedSummary = 'goatlicious summary';
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( __METHOD__ ),
|
|
|
|
|
$expectedSummary
|
|
|
|
|
);
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $expectedSummary, $rev->getComment() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::isUnpatrolled
|
|
|
|
|
*/
|
2017-11-10 13:46:44 +00:00
|
|
|
public function testIsUnpatrolled_returnsRecentChangesId() {
|
2020-03-27 19:20:38 +00:00
|
|
|
$this->hideDeprecated( 'Revision::isUnpatrolled' );
|
2020-03-30 17:52:30 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getRecentChange' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-03-30 17:52:30 +00:00
|
|
|
|
2017-11-10 13:46:44 +00:00
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertGreaterThan( 0, $rev->isUnpatrolled() );
|
|
|
|
|
$this->assertSame( $rev->getRecentChange()->getAttribute( 'rc_id' ), $rev->isUnpatrolled() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::isUnpatrolled
|
|
|
|
|
*/
|
|
|
|
|
public function testIsUnpatrolled_returnsZeroIfPatrolled() {
|
2020-03-27 19:20:38 +00:00
|
|
|
$this->hideDeprecated( 'Revision::isUnpatrolled' );
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-11-10 13:46:44 +00:00
|
|
|
// This assumes that sysops are auto patrolled
|
|
|
|
|
$sysop = $this->getTestSysop()->getUser();
|
|
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( __METHOD__ ),
|
|
|
|
|
__METHOD__,
|
|
|
|
|
0,
|
|
|
|
|
false,
|
|
|
|
|
$sysop
|
|
|
|
|
);
|
2017-11-09 11:45:51 +00:00
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 0, $rev->isUnpatrolled() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is a simple blanket test for all simple content getters and is methods to provide some
|
|
|
|
|
* coverage before the split of Revision into multiple classes for MCR work.
|
|
|
|
|
* @covers Revision::getContent
|
|
|
|
|
* @covers Revision::getSerializedData
|
|
|
|
|
* @covers Revision::getContentModel
|
|
|
|
|
* @covers Revision::getContentFormat
|
|
|
|
|
* @covers Revision::getContentHandler
|
|
|
|
|
*/
|
|
|
|
|
public function testSimpleContentGetters() {
|
2020-03-31 16:26:16 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getSerializedData' );
|
2020-06-03 23:01:21 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContentFormat' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentHandler' );
|
|
|
|
|
$this->hideDeprecated( 'Revision::getContentModel' );
|
2020-06-08 02:38:00 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getContent' );
|
|
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2020-03-31 16:26:16 +00:00
|
|
|
|
2017-11-09 11:45:51 +00:00
|
|
|
$expectedText = 'testSimpleContentGetters in Revision. Goats love MCR...';
|
|
|
|
|
$expectedSummary = 'goatlicious testSimpleContentGetters summary';
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent(
|
|
|
|
|
new WikitextContent( $expectedText ),
|
|
|
|
|
$expectedSummary
|
|
|
|
|
);
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
2019-02-07 00:14:23 +00:00
|
|
|
$this->assertSame( $expectedText, $rev->getContent()->getText() );
|
2017-11-09 11:45:51 +00:00
|
|
|
$this->assertSame( $expectedText, $rev->getSerializedData() );
|
|
|
|
|
$this->assertSame( $this->testPage->getContentModel(), $rev->getContentModel() );
|
|
|
|
|
$this->assertSame( $this->testPage->getContent()->getDefaultFormat(), $rev->getContentFormat() );
|
|
|
|
|
$this->assertSame( $this->testPage->getContentHandler(), $rev->getContentHandler() );
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-10 14:37:44 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Revision::newKnownCurrent
|
|
|
|
|
*/
|
|
|
|
|
public function testNewKnownCurrent() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-11-10 14:37:44 +00:00
|
|
|
// Setup the services
|
2018-08-09 14:17:46 +00:00
|
|
|
$this->overrideMwServices();
|
2017-11-10 14:37:44 +00:00
|
|
|
$cache = new WANObjectCache( [ 'cache' => new HashBagOStuff() ] );
|
|
|
|
|
$this->setService( 'MainWANObjectCache', $cache );
|
|
|
|
|
$db = wfGetDB( DB_MASTER );
|
|
|
|
|
|
2019-03-29 21:14:05 +00:00
|
|
|
$now = 1553893742;
|
|
|
|
|
$cache->setMockTime( $now );
|
|
|
|
|
|
2017-11-10 14:37:44 +00:00
|
|
|
// Get a fresh revision to use during testing
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
// Clear any previous cache for the revision during creation
|
2018-07-03 15:46:30 +00:00
|
|
|
$key = $cache->makeGlobalKey(
|
|
|
|
|
RevisionStore::ROW_CACHE_KEY,
|
2017-08-31 18:41:04 +00:00
|
|
|
$db->getDomainID(),
|
|
|
|
|
$rev->getPage(),
|
|
|
|
|
$rev->getId()
|
|
|
|
|
);
|
2019-07-15 21:57:01 +00:00
|
|
|
$cache->delete( $key, WANObjectCache::HOLDOFF_TTL_NONE );
|
2017-11-10 14:37:44 +00:00
|
|
|
$this->assertFalse( $cache->get( $key ) );
|
|
|
|
|
|
2019-03-29 21:14:05 +00:00
|
|
|
++$now;
|
|
|
|
|
|
2017-11-10 14:37:44 +00:00
|
|
|
// Get the new revision and make sure it is in the cache and correct
|
2020-02-29 03:49:41 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newKnownCurrent' );
|
2017-11-10 14:37:44 +00:00
|
|
|
$newRev = Revision::newKnownCurrent( $db, $rev->getPage(), $rev->getId() );
|
|
|
|
|
$this->assertRevEquals( $rev, $newRev );
|
2017-08-31 18:41:04 +00:00
|
|
|
|
|
|
|
|
$cachedRow = $cache->get( $key );
|
|
|
|
|
$this->assertNotFalse( $cachedRow );
|
|
|
|
|
$this->assertEquals( $rev->getId(), $cachedRow->rev_id );
|
2017-11-10 14:37:44 +00:00
|
|
|
}
|
|
|
|
|
|
2017-12-27 14:17:04 +00:00
|
|
|
public function testNewKnownCurrent_withPageId() {
|
2020-04-18 02:39:58 +00:00
|
|
|
$this->hideDeprecated( 'WikiPage::getRevision' );
|
2017-12-27 14:17:04 +00:00
|
|
|
$db = wfGetDB( DB_MASTER );
|
|
|
|
|
|
|
|
|
|
$this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
|
|
|
|
|
$rev = $this->testPage->getRevision();
|
|
|
|
|
|
|
|
|
|
$pageId = $this->testPage->getId();
|
|
|
|
|
|
2020-02-29 03:49:41 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newKnownCurrent' );
|
2017-12-27 14:17:04 +00:00
|
|
|
$newRev = Revision::newKnownCurrent( $db, $pageId, $rev->getId() );
|
|
|
|
|
$this->assertRevEquals( $rev, $newRev );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testNewKnownCurrent_returnsFalseWhenTitleDoesntExist() {
|
|
|
|
|
$db = wfGetDB( DB_MASTER );
|
2020-02-29 03:49:41 +00:00
|
|
|
$this->hideDeprecated( 'Revision::newKnownCurrent' );
|
2017-12-27 14:17:04 +00:00
|
|
|
$this->assertFalse( Revision::newKnownCurrent( $db, 0 ) );
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-10 15:50:16 +00:00
|
|
|
public function provideUserCanBitfield() {
|
|
|
|
|
yield [ 0, 0, [], null, true ];
|
|
|
|
|
// Bitfields match, user has no permissions
|
|
|
|
|
yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [], null, false ];
|
|
|
|
|
yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [], null, false ];
|
|
|
|
|
yield [ Revision::DELETED_USER, Revision::DELETED_USER, [], null, false ];
|
|
|
|
|
yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [], null, false ];
|
|
|
|
|
// Bitfields match, user (admin) does have permissions
|
|
|
|
|
yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [ 'sysop' ], null, true ];
|
|
|
|
|
yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [ 'sysop' ], null, true ];
|
|
|
|
|
yield [ Revision::DELETED_USER, Revision::DELETED_USER, [ 'sysop' ], null, true ];
|
|
|
|
|
// Bitfields match, user (admin) does not have permissions
|
|
|
|
|
yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'sysop' ], null, false ];
|
|
|
|
|
// Bitfields match, user (oversight) does have permissions
|
|
|
|
|
yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'oversight' ], null, true ];
|
|
|
|
|
// Check permissions using the title
|
|
|
|
|
yield [
|
|
|
|
|
Revision::DELETED_TEXT,
|
|
|
|
|
Revision::DELETED_TEXT,
|
|
|
|
|
[ 'sysop' ],
|
2018-08-31 04:56:42 +00:00
|
|
|
__METHOD__,
|
2017-11-10 15:50:16 +00:00
|
|
|
true,
|
|
|
|
|
];
|
|
|
|
|
yield [
|
|
|
|
|
Revision::DELETED_TEXT,
|
|
|
|
|
Revision::DELETED_TEXT,
|
|
|
|
|
[],
|
2018-08-31 04:56:42 +00:00
|
|
|
__METHOD__,
|
2017-11-10 15:50:16 +00:00
|
|
|
false,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideUserCanBitfield
|
|
|
|
|
* @covers Revision::userCanBitfield
|
|
|
|
|
*/
|
|
|
|
|
public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
|
2020-02-23 21:48:54 +00:00
|
|
|
$this->hideDeprecated( 'Revision::userCanBitfield' );
|
2018-08-31 04:56:42 +00:00
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
|
2019-04-09 06:58:04 +00:00
|
|
|
$this->setGroupPermissions(
|
2017-11-10 15:50:16 +00:00
|
|
|
[
|
|
|
|
|
'sysop' => [
|
|
|
|
|
'deletedtext' => true,
|
|
|
|
|
'deletedhistory' => true,
|
|
|
|
|
],
|
|
|
|
|
'oversight' => [
|
|
|
|
|
'viewsuppressed' => true,
|
|
|
|
|
'suppressrevision' => true,
|
|
|
|
|
],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
$user = $this->getTestUser( $userGroups )->getUser();
|
|
|
|
|
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected,
|
|
|
|
|
Revision::userCanBitfield( $bitField, $field, $user, $title )
|
|
|
|
|
);
|
2017-11-15 10:37:29 +00:00
|
|
|
|
|
|
|
|
// Fallback to $wgUser
|
|
|
|
|
$this->setMwGlobals(
|
|
|
|
|
'wgUser',
|
|
|
|
|
$user
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected,
|
|
|
|
|
Revision::userCanBitfield( $bitField, $field, null, $title )
|
|
|
|
|
);
|
2017-11-10 15:50:16 +00:00
|
|
|
}
|
|
|
|
|
|
2017-11-10 15:55:39 +00:00
|
|
|
public function provideUserCan() {
|
|
|
|
|
yield [ 0, 0, [], true ];
|
|
|
|
|
// Bitfields match, user has no permissions
|
|
|
|
|
yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [], false ];
|
|
|
|
|
yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [], false ];
|
|
|
|
|
yield [ Revision::DELETED_USER, Revision::DELETED_USER, [], false ];
|
|
|
|
|
yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [], false ];
|
|
|
|
|
// Bitfields match, user (admin) does have permissions
|
|
|
|
|
yield [ Revision::DELETED_TEXT, Revision::DELETED_TEXT, [ 'sysop' ], true ];
|
|
|
|
|
yield [ Revision::DELETED_COMMENT, Revision::DELETED_COMMENT, [ 'sysop' ], true ];
|
|
|
|
|
yield [ Revision::DELETED_USER, Revision::DELETED_USER, [ 'sysop' ], true ];
|
|
|
|
|
// Bitfields match, user (admin) does not have permissions
|
|
|
|
|
yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'sysop' ], false ];
|
|
|
|
|
// Bitfields match, user (oversight) does have permissions
|
|
|
|
|
yield [ Revision::DELETED_RESTRICTED, Revision::DELETED_RESTRICTED, [ 'oversight' ], true ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideUserCan
|
|
|
|
|
* @covers Revision::userCan
|
|
|
|
|
*/
|
|
|
|
|
public function testUserCan( $bitField, $field, $userGroups, $expected ) {
|
2020-03-11 01:41:49 +00:00
|
|
|
$this->hideDeprecated( 'Revision::userCan' );
|
|
|
|
|
|
2019-04-09 06:58:04 +00:00
|
|
|
$this->setGroupPermissions(
|
2017-11-10 15:55:39 +00:00
|
|
|
[
|
|
|
|
|
'sysop' => [
|
|
|
|
|
'deletedtext' => true,
|
|
|
|
|
'deletedhistory' => true,
|
|
|
|
|
],
|
|
|
|
|
'oversight' => [
|
|
|
|
|
'viewsuppressed' => true,
|
|
|
|
|
'suppressrevision' => true,
|
|
|
|
|
],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
$user = $this->getTestUser( $userGroups )->getUser();
|
2017-08-31 18:41:04 +00:00
|
|
|
$revision = new Revision( [ 'deleted' => $bitField ], 0, $this->testPage->getTitle() );
|
2017-11-10 15:55:39 +00:00
|
|
|
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected,
|
|
|
|
|
$revision->userCan( $field, $user )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-03 17:15:37 +00:00
|
|
|
public function provideGetTextId() {
|
2019-12-17 16:20:32 +00:00
|
|
|
$title = $this->getMockTitle();
|
|
|
|
|
|
|
|
|
|
$rev = new Revision( [], 0, $title );
|
|
|
|
|
yield [ $rev, null ];
|
2018-09-03 17:15:37 +00:00
|
|
|
|
|
|
|
|
$slot = new SlotRecord( (object)[
|
|
|
|
|
'slot_revision_id' => 42,
|
|
|
|
|
'slot_content_id' => 1,
|
|
|
|
|
'content_address' => 'tt:789',
|
|
|
|
|
'model_name' => CONTENT_MODEL_WIKITEXT,
|
2018-09-24 21:10:08 +00:00
|
|
|
'role_name' => SlotRecord::MAIN,
|
2018-09-03 17:15:37 +00:00
|
|
|
'slot_origin' => 1,
|
|
|
|
|
], new WikitextContent( 'Test' ) );
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
$rec = new MutableRevisionRecord( $title );
|
|
|
|
|
$rec->setId( $slot->getRevision() );
|
2018-09-03 17:15:37 +00:00
|
|
|
$rec->setSlot( $slot );
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
$rev = new Revision( $rec );
|
|
|
|
|
yield [ $rev, 789 ];
|
2018-09-03 17:15:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTextId
|
2019-12-17 16:20:32 +00:00
|
|
|
* @covers Revision::getTextId()
|
2018-09-03 17:15:37 +00:00
|
|
|
*/
|
2019-12-17 16:20:32 +00:00
|
|
|
public function testGetTextId( Revision $rev, $expected ) {
|
2020-03-30 17:52:30 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getTextId' );
|
2018-09-03 17:15:37 +00:00
|
|
|
$this->assertSame( $expected, $rev->getTextId() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-17 16:20:32 +00:00
|
|
|
public function provideGetSerializedData() {
|
|
|
|
|
$title = $this->getMockTitle();
|
|
|
|
|
|
|
|
|
|
$rev = new Revision( [], 0, $title );
|
|
|
|
|
yield [ $rev, '' ];
|
|
|
|
|
|
|
|
|
|
$text = __METHOD__;
|
|
|
|
|
$rev = new Revision( [ 'text' => $text ], 0, $title );
|
|
|
|
|
yield [ $rev, $text ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetSerializedData
|
|
|
|
|
* @covers Revision::getTextId()
|
|
|
|
|
*
|
|
|
|
|
* @param Revision $rev
|
|
|
|
|
* @param int $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testGetSerializedData( $rev, $expected ) {
|
2020-03-31 16:26:16 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getSerializedData' );
|
2019-12-17 16:20:32 +00:00
|
|
|
$this->assertSame( $expected, $rev->getSerializedData() );
|
|
|
|
|
}
|
2018-09-30 21:34:59 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Revision::getRevisionText
|
|
|
|
|
*/
|
2019-12-17 16:20:32 +00:00
|
|
|
public function testGetRevisionText() {
|
2018-09-30 21:34:59 +00:00
|
|
|
$rev = $this->testPage->getRevisionRecord();
|
|
|
|
|
|
2020-03-26 22:40:22 +00:00
|
|
|
$queryInfo = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo();
|
2018-09-30 21:34:59 +00:00
|
|
|
|
|
|
|
|
$conds = [ 'rev_id' => $rev->getId() ];
|
|
|
|
|
$row = $this->db->selectRow(
|
|
|
|
|
$queryInfo['tables'],
|
|
|
|
|
$queryInfo['fields'],
|
|
|
|
|
$conds,
|
|
|
|
|
__METHOD__,
|
|
|
|
|
[],
|
|
|
|
|
$queryInfo['joins']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$expected = $rev->getContent( SlotRecord::MAIN )->serialize();
|
|
|
|
|
|
2019-09-30 17:11:03 +00:00
|
|
|
$this->hideDeprecated( 'Revision::getRevisionText' );
|
2018-09-30 21:34:59 +00:00
|
|
|
$this->assertSame( $expected, Revision::getRevisionText( $row ) );
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:34:35 +00:00
|
|
|
}
|