1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
<?php
use MediaWiki\Cache\LinkBatchFactory;
use MediaWiki\CommentFormatter\CommentFormatter;
use MediaWiki\Context\RequestContext;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\Linker\LinkRenderer;
use MediaWiki\Pager\ContributionsPager;
use MediaWiki\Revision\RevisionStore;
use MediaWiki\Title\NamespaceInfo;
use MediaWiki\Title\Title;
use MediaWiki\User\User;
use MediaWiki\User\UserFactory;
use MediaWiki\User\UserIdentity;
/**
* Test class for ContributionsPagerTest handling of revision and archive modes.
*
* @group Pager
* @group Database
* @covers \MediaWiki\Pager\ContributionsPager
*/
class ContributionsPagerTest extends MediaWikiIntegrationTestCase {
private static User $user;
private function getPagerForTryCreatingRevisionRecord( $isArchive = false ) {
$revisionStore = $this->createMock( RevisionStore::class );
$revisionStore->method( 'isRevisionRow' )
->willReturn( true );
$revisionStore->expects( $this->never() )
->method( $isArchive ? 'newRevisionFromRow' : 'newRevisionFromArchiveRow' );
return $this->getMockForAbstractClass(
ContributionsPager::class,
[
$this->createMock( LinkRenderer::class ),
$this->createMock( LinkBatchFactory::class ),
$this->createMock( HookContainer::class ),
$this->createMock( RevisionStore::class ),
$this->createMock( NamespaceInfo::class ),
$this->createMock( CommentFormatter::class ),
$this->createMock( UserFactory::class ),
new RequestContext(),
[
'isArchive' => $isArchive,
],
$this->createMock( UserIdentity::class ),
]
);
}
/**
* @dataProvider provideIsArchive
*/
public function testTryCreatingRevisionRecord( $isArchive, $row ) {
$pager = $this->getPagerForTryCreatingRevisionRecord( $isArchive );
$pager->tryCreatingRevisionRecord( $row );
}
/**
* @dataProvider provideIsArchive
*/
public function testCreateRevisionRecord( $isArchive, $row ) {
$pager = $this->getPagerForTryCreatingRevisionRecord( $isArchive );
$pager->createRevisionRecord( $row );
}
public function provideIsArchive() {
return [
'Get revisions from the revision table' => [ false, [ 'rev_id' => 6789 ] ],
'Get revisions from the archive table' => [ true, [ 'ar_rev_id' => 9876 ] ],
];
}
private function getPager( $context, $target ) {
$services = $this->getServiceContainer();
// Define a pager in 'archive' mode.
$pager = new class(
$services->getLinkRenderer(),
$services->getLinkBatchFactory(),
$services->getHookContainer(),
$services->getRevisionStore(),
$services->getNamespaceInfo(),
$services->getCommentFormatter(),
$services->getUserFactory(),
$context,
[
'isArchive' => true,
'target' => $target,
// The topOnly filter should be ignored and not throw an error: T371495
'topOnly' => true,
],
$this->createMock( UserIdentity::class ),
) extends ContributionsPager {
protected string $revisionIdField = 'ar_rev_id';
protected string $revisionParentIdField = 'ar_parent_id';
protected string $revisionTimestampField = 'ar_timestamp';
protected string $revisionLengthField = 'ar_len';
protected string $revisionDeletedField = 'ar_deleted';
protected string $revisionMinorField = 'ar_minor_edit';
protected string $userNameField = 'ar_user_text';
protected string $pageNamespaceField = 'ar_namespace';
protected string $pageTitleField = 'ar_title';
protected function getRevisionQuery() {
$revQuery = $this->revisionStore->newArchiveSelectQueryBuilder( $this->getDatabase() )
->joinComment()
->where( [ 'actor_name' => $this->target ] )
->andWhere( $this->getNamespaceCond() )
->getQueryInfo( 'joins' );
return [
'tables' => $revQuery['tables'],
'fields' => $revQuery['fields'],
'conds' => [],
'options' => [],
'join_conds' => $revQuery['joins'],
];
}
public function getIndexField() {
return 'ar_timestamp';
}
};
return $pager;
}
/**
* Test the pager in 'archive' mode. This involves making a new class, since no
* concrete subclass in MediaWiki core currently uses this mode.
*
* In the future, SpecialDeletedContributions could use a subclass of ContributionsPager
* instead of DeletedContribsPager. In that case, this test can be moved to the tests
* for that class.
*/
public function testFormatRow() {
$context = new RequestContext();
$context->setLanguage( 'qqx' );
$pager = $this->getPager( $context, self::$user->getName() );
// Perform assertions
$this->assertSame( 1, $pager->getNumRows() );
$html = $pager->getBody();
$this->assertStringContainsString( 'deletionlog', $html );
$this->assertStringContainsString( 'undeleteviewlink', $html );
// The performing user does not have the right to undelete
$this->assertStringNotContainsString( 'mw-changeslist-date', $html );
}
public function testFormatRowDateLinks() {
$context = new RequestContext();
$context->setUser( $this->getTestSysop()->getUser() );
$pager = $this->getPager( $context, self::$user->getName() );
$html = $pager->getBody();
$this->assertStringContainsString( 'mw-changeslist-date', $html );
}
public function addDbDataOnce() {
// Set up data
self::$user = $this->getTestUser()->getUser();
$this->editPage(
'Test page for deletion', 'Test Content', 'test', NS_MAIN, self::$user
);
$title = Title::newFromText( 'Test page for deletion' );
$page = $this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title );
$this->deletePage( $page );
}
}
|