diff options
-rw-r--r-- | autoload.php | 1 | ||||
-rw-r--r-- | includes/MediaWikiServices.php | 8 | ||||
-rw-r--r-- | includes/Revision/ContributionsLookup.php | 278 | ||||
-rw-r--r-- | includes/ServiceWiring.php | 13 | ||||
-rw-r--r-- | tests/phpunit/includes/Revision/ContributionsLookupTest.php | 413 |
5 files changed, 0 insertions, 713 deletions
diff --git a/autoload.php b/autoload.php index 8def8d54f7af..84aca5275a70 100644 --- a/autoload.php +++ b/autoload.php @@ -2006,7 +2006,6 @@ $wgAutoloadLocalClasses = [ 'MediaWiki\\Revision\\ArchiveSelectQueryBuilder' => __DIR__ . '/includes/Revision/ArchiveSelectQueryBuilder.php', 'MediaWiki\\Revision\\ArchivedRevisionLookup' => __DIR__ . '/includes/Revision/ArchivedRevisionLookup.php', 'MediaWiki\\Revision\\BadRevisionException' => __DIR__ . '/includes/Revision/BadRevisionException.php', - 'MediaWiki\\Revision\\ContributionsLookup' => __DIR__ . '/includes/Revision/ContributionsLookup.php', 'MediaWiki\\Revision\\ContributionsSegment' => __DIR__ . '/includes/Revision/ContributionsSegment.php', 'MediaWiki\\Revision\\FallbackSlotRoleHandler' => __DIR__ . '/includes/Revision/FallbackSlotRoleHandler.php', 'MediaWiki\\Revision\\Hook\\ContentHandlerDefaultModelForHook' => __DIR__ . '/includes/Revision/Hook/ContentHandlerDefaultModelForHook.php', diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php index 052ae40137ef..43e1e987cc51 100644 --- a/includes/MediaWikiServices.php +++ b/includes/MediaWikiServices.php @@ -134,7 +134,6 @@ use MediaWiki\Request\ProxyLookup; use MediaWiki\ResourceLoader\ResourceLoader; use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory; use MediaWiki\Revision\ArchivedRevisionLookup; -use MediaWiki\Revision\ContributionsLookup; use MediaWiki\Revision\RevisionFactory; use MediaWiki\Revision\RevisionLookup; use MediaWiki\Revision\RevisionRenderer; @@ -1002,13 +1001,6 @@ class MediaWikiServices extends ServiceContainer { } /** - * @since 1.35 - */ - public function getContributionsLookup(): ContributionsLookup { - return $this->getService( 'ContributionsLookup' ); - } - - /** * @since 1.36 */ public function getCriticalSectionProvider(): CriticalSectionProvider { diff --git a/includes/Revision/ContributionsLookup.php b/includes/Revision/ContributionsLookup.php deleted file mode 100644 index b5a73fe4b61e..000000000000 --- a/includes/Revision/ContributionsLookup.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php - -namespace MediaWiki\Revision; - -use ChangeTags; -use MediaWiki\Cache\LinkBatchFactory; -use MediaWiki\CommentFormatter\CommentFormatter; -use MediaWiki\Context\IContextSource; -use MediaWiki\Context\RequestContext; -use MediaWiki\HookContainer\HookContainer; -use MediaWiki\Linker\LinkRendererFactory; -use MediaWiki\Message\Message; -use MediaWiki\Pager\ContribsPager; -use MediaWiki\Permissions\Authority; -use MediaWiki\Request\FauxRequest; -use MediaWiki\Title\NamespaceInfo; -use MediaWiki\User\UserIdentity; -use Wikimedia\Rdbms\IConnectionProvider; - -/** - * @since 1.35 - */ -class ContributionsLookup { - - /** @var RevisionStore */ - private $revisionStore; - - /** @var LinkRendererFactory */ - private $linkRendererFactory; - - /** @var LinkBatchFactory */ - private $linkBatchFactory; - - /** @var HookContainer */ - private $hookContainer; - - /** @var IConnectionProvider */ - private $dbProvider; - - /** @var NamespaceInfo */ - private $namespaceInfo; - - /** @var CommentFormatter */ - private $commentFormatter; - - /** - * @param RevisionStore $revisionStore - * @param LinkRendererFactory $linkRendererFactory - * @param LinkBatchFactory $linkBatchFactory - * @param HookContainer $hookContainer - * @param IConnectionProvider $dbProvider - * @param NamespaceInfo $namespaceInfo - * @param CommentFormatter $commentFormatter - */ - public function __construct( - RevisionStore $revisionStore, - LinkRendererFactory $linkRendererFactory, - LinkBatchFactory $linkBatchFactory, - HookContainer $hookContainer, - IConnectionProvider $dbProvider, - NamespaceInfo $namespaceInfo, - CommentFormatter $commentFormatter - ) { - $this->revisionStore = $revisionStore; - $this->linkRendererFactory = $linkRendererFactory; - $this->linkBatchFactory = $linkBatchFactory; - $this->hookContainer = $hookContainer; - $this->dbProvider = $dbProvider; - $this->namespaceInfo = $namespaceInfo; - $this->commentFormatter = $commentFormatter; - } - - /** - * Constructs fake query parameters to be passed to ContribsPager - * - * @param int $limit Maximum number of revisions to return. - * @param string $segment Indicates which segment of the contributions to return. - * The segment should consist of 2 parts separated by a pipe character. - * The first part is mapped to the 'dir' parameter. - * The second part is mapped to the 'offset' parameter. - * The value for the offset is opaque and is ultimately supplied by ContribsPager::getPagingQueries(). - * @return array - */ - private function getPagerParams( int $limit, string $segment ): array { - $dir = 'next'; - $seg = explode( '|', $segment, 2 ); - if ( count( $seg ) > 1 ) { - if ( $seg[0] === 'after' ) { - $dir = 'prev'; - $segment = $seg[1]; - } elseif ( $seg[0] == 'before' ) { - $segment = $seg[1]; - } else { - $dir = null; - $segment = null; - } - } else { - $segment = null; - } - return [ - 'limit' => $limit, - 'offset' => $segment, - 'dir' => $dir - ]; - } - - /** - * @param UserIdentity $target the user from whom to retrieve contributions - * @param int $limit the maximum number of revisions to return - * @param Authority $performer the user used for permission checks - * @param string $segment - * @param string|null $tag - * - * @return ContributionsSegment - */ - public function getContributions( - UserIdentity $target, - int $limit, - Authority $performer, - string $segment = '', - string $tag = null - ): ContributionsSegment { - $context = new RequestContext(); - $context->setAuthority( $performer ); - - $paramArr = $this->getPagerParams( $limit, $segment ); - $context->setRequest( new FauxRequest( $paramArr ) ); - - // TODO: explore moving this to factory method for testing - $pager = $this->getContribsPager( $context, $target, [ - 'tagfilter' => $tag, - 'revisionsOnly' => true - ] ); - $revisions = []; - $tags = []; - $count = 0; - if ( $pager->getNumRows() > 0 ) { - foreach ( $pager->mResult as $row ) { - // We retrieve and ignore one extra record to see if we are on the oldest segment. - if ( ++$count > $limit ) { - break; - } - - // TODO: pre-load title batch? - $revision = $this->revisionStore->newRevisionFromRow( $row, 0 ); - $revisions[] = $revision; - if ( $row->ts_tags ) { - $tagNames = explode( ',', $row->ts_tags ); - $tags[ $row->rev_id ] = $this->getContributionTags( $tagNames ); - } - } - } - - $deltas = $this->getContributionDeltas( $revisions ); - - $flags = [ - 'newest' => $pager->mIsFirst, - 'oldest' => $pager->mIsLast, - ]; - - // TODO: Make me an option in IndexPager - $pager->mIsFirst = false; // XXX: nasty... - $pagingQueries = $pager->getPagingQueries(); - - $prev = $pagingQueries['prev']['offset'] ?? null; - $next = $pagingQueries['next']['offset'] ?? null; - - $after = $prev ? 'after|' . $prev : null; // later in time - $before = $next ? 'before|' . $next : null; // earlier in time - - // TODO: Possibly return public $pager properties to segment for populating URLS ($mIsFirst, $mIsLast) - // HACK: Force result set order to be descending. Sorting logic in ContribsPager::reallyDoQuery is confusing. - if ( $paramArr['dir'] === 'prev' ) { - $revisions = array_reverse( $revisions ); - } - return new ContributionsSegment( $revisions, $tags, $before, $after, $deltas, $flags ); - } - - /** - * @param string[] $tagNames Array of tag names - * @return Message[] Associative array mapping tag name to a Message object containing the tag's display value - */ - private function getContributionTags( array $tagNames ): array { - $tagMetadata = []; - foreach ( $tagNames as $name ) { - $tagDisplay = ChangeTags::tagShortDescriptionMessage( $name, RequestContext::getMain() ); - if ( $tagDisplay ) { - $tagMetadata[$name] = $tagDisplay; - } - } - return $tagMetadata; - } - - /** - * Gets size deltas of a revision and its parent revision - * @param RevisionRecord[] $revisions - * @return int[] Associative array of revision ids and their deltas. - * If revision is the first on a page, delta is revision size. - * If parent revision is unknown, delta is null. - */ - private function getContributionDeltas( $revisions ): array { - // SpecialContributions uses the size of the revision if the parent revision is unknown. Cases include: - // - revision has been deleted - // - parent rev id has not been populated (this is the case for very old revisions) - $parentIds = []; - foreach ( $revisions as $revision ) { - $revId = $revision->getId(); - $parentIds[$revId] = $revision->getParentId(); - } - $parentSizes = $this->revisionStore->getRevisionSizes( $parentIds ); - $deltas = []; - foreach ( $revisions as $revision ) { - $parentId = $revision->getParentId(); - if ( $parentId === 0 ) { // first revision on a page - $delta = $revision->getSize(); - } elseif ( !isset( $parentSizes[$parentId] ) ) { // parent revision is either deleted or untracked - $delta = null; - } else { - $delta = $revision->getSize() - $parentSizes[$parentId]; - } - $deltas[ $revision->getId() ] = $delta; - } - return $deltas; - } - - /** - * Returns the number of edits by the given user. - * - * @param UserIdentity $user - * @param Authority $performer the user used for permission checks - * @param string|null $tag - * - * @return int - */ - public function getContributionCount( UserIdentity $user, Authority $performer, $tag = null ): int { - $context = new RequestContext(); - $context->setAuthority( $performer ); - $context->setRequest( new FauxRequest( [] ) ); - - // TODO: explore moving this to factory method for testing - $pager = $this->getContribsPager( $context, $user, [ - 'tagfilter' => $tag, - ] ); - - $query = $pager->getQueryInfo(); - - $count = $pager->mDb->selectField( - $query['tables'], - 'COUNT(*)', - $query['conds'], - __METHOD__, - [], - $query['join_conds'] - ); - - return (int)$count; - } - - private function getContribsPager( - IContextSource $context, - UserIdentity $targetUser, - array $options - ) { - return new ContribsPager( - $context, - $options, - $this->linkRendererFactory->create(), - $this->linkBatchFactory, - $this->hookContainer, - $this->dbProvider, - $this->revisionStore, - $this->namespaceInfo, - $targetUser, - $this->commentFormatter - ); - } - -} diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index c53bb60329af..8f74fb7556c7 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -171,7 +171,6 @@ use MediaWiki\ResourceLoader\MessageBlobStore; use MediaWiki\ResourceLoader\ResourceLoader; use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory; use MediaWiki\Revision\ArchivedRevisionLookup; -use MediaWiki\Revision\ContributionsLookup; use MediaWiki\Revision\MainSlotRoleHandler; use MediaWiki\Revision\RevisionFactory; use MediaWiki\Revision\RevisionLookup; @@ -630,18 +629,6 @@ return [ return new ContentTransformer( $services->getContentHandlerFactory() ); }, - 'ContributionsLookup' => static function ( MediaWikiServices $services ): ContributionsLookup { - return new ContributionsLookup( - $services->getRevisionStore(), - $services->getLinkRendererFactory(), - $services->getLinkBatchFactory(), - $services->getHookContainer(), - $services->getConnectionProvider(), - $services->getNamespaceInfo(), - $services->getCommentFormatter() - ); - }, - 'CriticalSectionProvider' => static function ( MediaWikiServices $services ): CriticalSectionProvider { $config = $services->getMainConfig(); $limit = MW_ENTRY_POINT === 'cli' ? INF : $config->get( MainConfigNames::CriticalSectionTimeLimit ); diff --git a/tests/phpunit/includes/Revision/ContributionsLookupTest.php b/tests/phpunit/includes/Revision/ContributionsLookupTest.php deleted file mode 100644 index 295f621f78b6..000000000000 --- a/tests/phpunit/includes/Revision/ContributionsLookupTest.php +++ /dev/null @@ -1,413 +0,0 @@ -<?php - -namespace MediaWiki\Tests\Revision; - -use ChangeTags; -use MediaWiki\Message\Message; -use MediaWiki\Permissions\Authority; -use MediaWiki\Permissions\SimpleAuthority; -use MediaWiki\Permissions\UltimateAuthority; -use MediaWiki\Revision\ContributionsLookup; -use MediaWiki\Revision\ContributionsSegment; -use MediaWiki\Revision\RevisionRecord; -use MediaWiki\User\User; -use MediaWiki\User\UserIdentityValue; -use MediaWikiIntegrationTestCase; -use Wikimedia\Timestamp\ConvertibleTimestamp; - -/** - * @covers \MediaWiki\Revision\ContributionsLookup - * - * @group Database - */ -class ContributionsLookupTest extends MediaWikiIntegrationTestCase { - - /** - * @var RevisionRecord[] Associative array mapping revision number (e.g. 1 for first - * revision made) to revision record - */ - private static $storedRevisions; - - /** - * @var User - */ - private static $testUser; - - /** - * @var Authority - */ - private static $performer; - - /** - * @var int[][] - */ - private static $storedDeltas; - - /** - * @var string[][] - */ - private static $storedTags; - - private const TAG1 = 'test-ContributionsLookup-1'; - private const TAG2 = 'test-ContributionsLookup-2'; - private const TAG3 = 'test-ContributionsLookup-3'; - - private const TAG_DISPLAY = 'ContributionsLookup Tag Display Text'; - - protected function setUp(): void { - parent::setUp(); - - if ( $this->db->getType() === 'mysql' && str_contains( $this->db->getSoftwareLink(), 'MySQL' ) ) { - $this->markTestSkipped( 'See T256006' ); - } - - // MessageCache needs to be explicitly enabled to load changetag display text. - $this->getServiceContainer()->getMessageCache()->enable(); - } - - protected function tearDown(): void { - $this->getServiceContainer()->getMessageCache()->disable(); - - parent::tearDown(); - } - - public function addDBDataOnce() { - $user = $this->getTestUser()->getUser(); - - $clock = (int)ConvertibleTimestamp::now( TS_UNIX ); - ConvertibleTimestamp::setFakeTime( static function () use ( &$clock ) { - return ++$clock; - } ); - - self::$testUser = $user; - self::$performer = new UltimateAuthority( $user ); - - $revisionText = [ 1 => 'Lorem', 2 => 'Lorem Ipsum', 3 => 'Lor', 4 => 'Lorem' ]; - // maps $storedRevision revision number to delta of revision length from its parent - self::$storedDeltas = [ 1 => 5, 2 => 11, 3 => -2, 4 => -6 ]; - - self::$storedRevisions[1] = $this->editPage( __METHOD__ . '_1', $revisionText[1], 'test', NS_MAIN, $user ) - ->getNewRevision(); - self::$storedRevisions[2] = $this->editPage( __METHOD__ . '_2', $revisionText[2], 'test', NS_TALK, $user ) - ->getNewRevision(); - self::$storedRevisions[3] = $this->editPage( __METHOD__ . '_1', $revisionText[3], 'test', NS_MAIN, $user ) - ->getNewRevision(); - self::$storedRevisions[4] = $this->editPage( __METHOD__ . '_2', $revisionText[4], 'test', NS_TALK, $user ) - ->getNewRevision(); - - ChangeTags::defineTag( self::TAG1 ); - ChangeTags::defineTag( self::TAG2 ); - - self::$storedTags = [ - 1 => [], - 2 => [ self::TAG1, self::TAG2 ], - 3 => [ self::TAG2 ], - 4 => [], - ]; - - foreach ( self::$storedTags as $idx => $tags ) { - if ( !$tags ) { - continue; - } - $revId = self::$storedRevisions[$idx]->getId(); - ChangeTags::addTags( $tags, null, $revId ); - } - - // Pages at MediaWiki:tag-{tag_name} override any tag display text - $this->insertPage( "tag-" . self::TAG1, "''" . self::TAG_DISPLAY . "''", NS_MEDIAWIKI ); - $this->insertPage( "tag-" . self::TAG2, "''" . self::TAG_DISPLAY . "''", NS_MEDIAWIKI ); - - // Add a 3rd disabled tag (empty string as display name equates to disabled tag) - ChangeTags::addTags( [ self::TAG3 ], null, $revId ); - $this->insertPage( "tag-" . self::TAG3, '', NS_MEDIAWIKI ); - - ConvertibleTimestamp::setFakeTime( false ); - } - - /** - * @return ContributionsLookup - */ - private function getContributionsLookup() { - // Helper to simplify potential switch to unit tests - return $this->getServiceContainer()->getContributionsLookup(); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributions() - */ - public function testGetDeltas() { - $contributionsLookup = $this->getContributionsLookup(); - - $segment = - $contributionsLookup->getContributions( self::$testUser, 10, self::$performer ); - - // Contributions are returned in descending order. - $revIds = array_map( - static function ( RevisionRecord $rev ) { - return $rev->getId(); - }, - $segment->getRevisions() - ); - - $this->assertEquals( self::$storedDeltas[ 4 ], $segment->getDeltaForRevision( $revIds[0] ) ); - $this->assertEquals( self::$storedDeltas[ 3 ], $segment->getDeltaForRevision( $revIds[1] ) ); - $this->assertEquals( self::$storedDeltas[ 2 ], $segment->getDeltaForRevision( $revIds[2] ) ); - $this->assertEquals( self::$storedDeltas[ 1 ], $segment->getDeltaForRevision( $revIds[3] ) ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributions() - */ - public function testGetUnknownDeltas() { - $user = $this->getTestUser()->getUser(); - - $rev1 = $this->editPage( __METHOD__ . '_1', 'foo', 'test', NS_MAIN, $user ) - ->getNewRevision(); - $rev2 = $this->editPage( __METHOD__ . '_2', 'bar', 'test', NS_TALK, $user ) - ->getNewRevision(); - - // Parent of revision 1 is not in revision table (deleted) - $this->db->newUpdateQueryBuilder() - ->update( 'revision' ) - ->set( [ 'rev_parent_id' => $rev2->getId() + 100 ] ) - ->where( [ 'rev_id' => $rev1->getId() ] ) - ->caller( __METHOD__ ) - ->execute(); - // Parent of revision 2 is unknown - $this->db->newUpdateQueryBuilder() - ->update( 'revision' ) - ->set( [ 'rev_parent_id' => null ] ) - ->where( [ 'rev_id' => $rev2->getId() ] ) - ->caller( __METHOD__ ) - ->execute(); - - $contributionsLookup = $this->getContributionsLookup(); - - $segment = - $contributionsLookup->getContributions( $user, 10, self::$performer ); - - $this->assertNull( $segment->getDeltaForRevision( $rev1->getId() ) ); - $this->assertNull( $segment->getDeltaForRevision( $rev2->getId() ) ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributions() - */ - public function testGetContributionsByUserIdentity() { - $contributionsLookup = $this->getContributionsLookup(); - - $segment = - $contributionsLookup->getContributions( self::$testUser, 2, self::$performer ); - - // Desc order comes back from db query - $this->assertSegmentRevisions( [ 4, 3 ], $segment ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributions() - */ - public function testGetListOfContributions_revisionOnly() { - $this->setTemporaryHook( 'ContribsPager::reallyDoQuery', function ( &$data ) { - $this->fail( 'ContribsPager::reallyDoQuery was not expected to be called' ); - } ); - - $contributionsLookup = $this->getContributionsLookup(); - - $segment = - $contributionsLookup->getContributions( self::$testUser, 2, self::$performer ); - - // Desc order comes back from db query - $this->assertSegmentRevisions( [ 4, 3 ], $segment ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributions() - */ - public function testGetContributionsFilteredByTag() { - $contributionsLookup = $this->getContributionsLookup(); - - $target = self::$testUser; - - $segment1 = - $contributionsLookup->getContributions( $target, 10, self::$performer, '', self::TAG1 ); - - $this->assertSegmentRevisions( [ 2 ], $segment1 ); - $this->assertTrue( $segment1->isOldest() ); - - $segment2 = - $contributionsLookup->getContributions( $target, 10, self::$performer, '', self::TAG2 ); - - $this->assertSegmentRevisions( [ 3, 2 ], $segment2 ); - $this->assertTrue( $segment1->isOldest() ); - - $segment0 = - $contributionsLookup->getContributions( $target, 10, self::$performer, '', 'not-a-tag' ); - - $this->assertSame( [], $segment0->getRevisions() ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributions() - */ - public function testGetSegmentChain() { - $contributionsLookup = $this->getContributionsLookup(); - - $segment1 = $contributionsLookup->getContributions( self::$testUser, 2, self::$performer ); - $this->assertInstanceOf( ContributionsSegment::class, $segment1 ); - $this->assertCount( 2, $segment1->getRevisions() ); - $this->assertNotNull( $segment1->getAfter() ); - $this->assertNotNull( $segment1->getBefore() ); - $this->assertFalse( $segment1->isOldest() ); - - $segment2 = - $contributionsLookup->getContributions( self::$testUser, 2, self::$performer, $segment1->getBefore() ); - $this->assertCount( 2, $segment2->getRevisions() ); - $this->assertNotNull( $segment2->getAfter() ); - $this->assertNull( $segment2->getBefore() ); - $this->assertTrue( $segment2->isOldest() ); - - $segment3 = - $contributionsLookup->getContributions( self::$testUser, 2, self::$performer, $segment2->getAfter() ); - $this->assertInstanceOf( ContributionsSegment::class, $segment3 ); - $this->assertCount( 2, $segment3->getRevisions() ); - $this->assertNotNull( $segment3->getAfter() ); - $this->assertNotNull( $segment3->getBefore() ); - $this->assertFalse( $segment3->isOldest() ); - - $this->assertSegmentRevisions( [ 4, 3 ], $segment1 ); - $this->assertSegmentRevisions( [ 2, 1 ], $segment2 ); - $this->assertSegmentRevisions( [ 4, 3 ], $segment3 ); - } - - /** - * @param int[] $expectedRevisions A list of indexes into self::$storedRevisions - * @param ContributionsSegment $segmentObject - */ - private function assertSegmentRevisions( $expectedRevisions, $segmentObject ) { - $revisions = $segmentObject->getRevisions(); - - $this->assertSameSize( $expectedRevisions, $revisions ); - - foreach ( $expectedRevisions as $idx => $editNumber ) { - $expected = self::$storedRevisions[$editNumber]; - $actual = $revisions[$idx]; - $this->assertSame( $expected->getId(), $actual->getId(), 'rev_id' ); - $this->assertSame( $expected->getPageId(), $actual->getPageId(), 'rev_page_id' ); - $this->assertTrue( - $expected->getPageAsLinkTarget()->isSameLinkAs( $actual->getPageAsLinkTarget() ), - 'getPageAsLinkTarget' - ); - - $expectedUser = $expected->getUser( RevisionRecord::RAW )->getName(); - $actualUser = $actual->getUser( RevisionRecord::RAW )->getName(); - $this->assertSame( $expectedUser, $actualUser ); - - $expectedTags = self::$storedTags[ $editNumber ]; - $this->assertRevisionTags( $expectedTags, $segmentObject, $actual ); - - $expectedDelta = self::$storedDeltas[$editNumber]; - $actualDelta = $segmentObject->getDeltaForRevision( $actual->getId() ); - $this->assertSame( $expectedDelta, $actualDelta, 'delta' ); - } - } - - public static function provideBadSegmentMarker() { - yield [ '' ]; - yield [ '|' ]; - yield [ '0' ]; - yield [ '9' ]; - yield [ 'x|0' ]; - yield [ 'x|9' ]; - yield [ 'x|x' ]; - } - - /** - * @dataProvider provideBadSegmentMarker - */ - public function testBadSegmentMarkerReturnsLatestSegment( $segment ) { - $contributionsLookup = $this->getContributionsLookup(); - - $segment = $contributionsLookup->getContributions( self::$testUser, 2, self::$performer, $segment ); - $this->assertSegmentRevisions( [ 4, 3 ], $segment ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributionCount() - */ - public function testGetCountOfContributionsByUserIdentity() { - $contributionsLookup = $this->getContributionsLookup(); - - $count = $contributionsLookup->getContributionCount( self::$testUser, self::$performer ); - $this->assertSame( count( self::$storedRevisions ), $count ); - } - - /** - * @covers \MediaWiki\Revision\ContributionsLookup::getContributionCount() - */ - public function testGetCountOfContributionsByUserAndTag() { - $contributionsLookup = $this->getContributionsLookup(); - $count = $contributionsLookup->getContributionCount( - self::$testUser, - self::$performer, - self::TAG2 - ); - $this->assertSame( 2, $count ); - } - - public function testPermissionChecksAreApplied() { - $editingUser = self::$testUser; - $dummyUser = new UserIdentityValue( 0, 'test' ); - - $contributionsLookup = $this->getContributionsLookup(); - - $revIds = [ self::$storedRevisions[1]->getId(), self::$storedRevisions[2]->getId() ]; - $this->db->newUpdateQueryBuilder() - ->update( 'revision' ) - ->set( [ 'rev_deleted' => RevisionRecord::DELETED_USER ] ) - ->where( [ 'rev_id' => $revIds ] ) - ->caller( __METHOD__ ) - ->execute(); - - $this->assertSame( 2, $this->db->affectedRows() ); - - // anons should not see suppressed contribs - $segment = $contributionsLookup->getContributions( $editingUser, 10, - new SimpleAuthority( $dummyUser, [] ) ); - $this->assertSegmentRevisions( [ 4, 3 ], $segment ); - - $count = $contributionsLookup->getContributionCount( $editingUser, - new SimpleAuthority( $dummyUser, [] ) ); - $this->assertSame( 2, $count ); - - // Actor with suppressrevision right should - $segment = $contributionsLookup->getContributions( $editingUser, 10, - new SimpleAuthority( $dummyUser, [ 'deletedhistory', 'suppressrevision' ] ) ); - $this->assertSegmentRevisions( [ 4, 3, 2, 1 ], $segment ); - - $count = $contributionsLookup->getContributionCount( $editingUser, - new SimpleAuthority( $dummyUser, [ 'deletedhistory', 'suppressrevision' ] ) ); - $this->assertSame( 4, $count ); - } - - /** - * @param array $expectedTags - * @param ContributionsSegment $segmentObject - * @param RevisionRecord $actual - */ - private function assertRevisionTags( - array $expectedTags, - ContributionsSegment $segmentObject, - RevisionRecord $actual - ): void { - $actualTags = $segmentObject->getTagsForRevision( $actual->getId() ); - - // Tag 3 was disabled and should not be included in results - $this->assertArrayNotHasKey( self::TAG3, $actualTags ); - foreach ( $actualTags as $tagName => $actualTag ) { - $this->assertContains( $tagName, $expectedTags ); - $this->assertInstanceOf( Message::class, $actualTag ); - $this->assertEquals( "<i>" . self::TAG_DISPLAY . "</i>", $actualTag->parse() ); - $this->assertEquals( "''" . self::TAG_DISPLAY . "''", $actualTag->text() ); - } - } -} |