From 4c7b35105c20e1bc1eae49f5447663d58d090926 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Mon, 12 Feb 2018 10:11:40 -0500 Subject: [PATCH] Allow querying contributions of interwiki usernames Both for Special:Contributions and ApiQueryUserContributions. Bug: T187079 Change-Id: I4398e473b90172851e875b3f219f7076dceda66c --- includes/api/ApiBase.php | 4 ++ includes/api/ApiQueryUserContributions.php | 2 +- includes/specials/SpecialContributions.php | 50 ++++++++++++------- .../query/ApiQueryUserContributionsTest.php | 45 +++++++++++++++++ 4 files changed, 81 insertions(+), 20 deletions(-) diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 228d319f18..73315a0966 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -1615,6 +1615,10 @@ abstract class ApiBase extends ContextSource { * @return string Validated and normalized parameter */ private function validateUser( $value, $encParamName ) { + if ( ExternalUserNames::isExternal( $value ) && User::newFromName( $value, false ) ) { + return $value; + } + $title = Title::makeTitleSafe( NS_USER, $value ); if ( $title === null || $title->hasFragment() ) { $this->dieWithError( diff --git a/includes/api/ApiQueryUserContributions.php b/includes/api/ApiQueryUserContributions.php index e587ef4924..bb4a2ef07e 100644 --- a/includes/api/ApiQueryUserContributions.php +++ b/includes/api/ApiQueryUserContributions.php @@ -245,7 +245,7 @@ class ApiQueryContributions extends ApiQueryBase { ); } - if ( User::isIP( $u ) ) { + if ( User::isIP( $u ) || ExternalUserNames::isExternal( $u ) ) { $names[$u] = null; } else { $name = User::getCanonicalName( $u, 'valid' ); diff --git a/includes/specials/SpecialContributions.php b/includes/specials/SpecialContributions.php index 806713b4ef..6fc8306a52 100644 --- a/includes/specials/SpecialContributions.php +++ b/includes/specials/SpecialContributions.php @@ -81,21 +81,39 @@ class SpecialContributions extends IncludableSpecialPage { $this->opts['newOnly'] = $request->getBool( 'newOnly' ); $this->opts['hideMinor'] = $request->getBool( 'hideMinor' ); - $nt = Title::makeTitleSafe( NS_USER, $target ); - if ( !$nt ) { - $out->addHTML( $this->getForm() ); - - return; - } - $userObj = User::newFromName( $nt->getText(), false ); - if ( !$userObj ) { - $out->addHTML( $this->getForm() ); + $id = 0; + if ( $this->opts['contribs'] === 'newbie' ) { + $userObj = User::newFromName( $target ); // hysterical raisins + $out->addSubtitle( $this->msg( 'sp-contributions-newbies-sub' ) ); + $out->setHTMLTitle( $this->msg( + 'pagetitle', + $this->msg( 'sp-contributions-newbies-title' )->plain() + )->inContentLanguage() ); + } elseif ( ExternalUserNames::isExternal( $target ) ) { + $userObj = User::newFromName( $target, false ); + if ( !$userObj ) { + $out->addHTML( $this->getForm() ); + return; + } - return; - } - $id = $userObj->getId(); + $out->addSubtitle( $this->contributionsSub( $userObj ) ); + $out->setHTMLTitle( $this->msg( + 'pagetitle', + $this->msg( 'contributions-title', $target )->plain() + )->inContentLanguage() ); + } else { + $nt = Title::makeTitleSafe( NS_USER, $target ); + if ( !$nt ) { + $out->addHTML( $this->getForm() ); + return; + } + $userObj = User::newFromName( $nt->getText(), false ); + if ( !$userObj ) { + $out->addHTML( $this->getForm() ); + return; + } + $id = $userObj->getId(); - if ( $this->opts['contribs'] != 'newbie' ) { $target = $nt->getText(); $out->addSubtitle( $this->contributionsSub( $userObj ) ); $out->setHTMLTitle( $this->msg( @@ -108,12 +126,6 @@ class SpecialContributions extends IncludableSpecialPage { if ( !IP::isValidRange( $target ) ) { $this->getSkin()->setRelevantUser( $userObj ); } - } else { - $out->addSubtitle( $this->msg( 'sp-contributions-newbies-sub' ) ); - $out->setHTMLTitle( $this->msg( - 'pagetitle', - $this->msg( 'sp-contributions-newbies-title' )->plain() - )->inContentLanguage() ); } $ns = $request->getVal( 'namespace', null ); diff --git a/tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php b/tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php index 6e8bc0b047..ca6a929ac8 100644 --- a/tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php +++ b/tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php @@ -25,6 +25,7 @@ class ApiQueryContributionsTest extends ApiTestCase { User::createNew( __CLASS__ . ' B' ), User::createNew( __CLASS__ . ' A' ), User::createNew( __CLASS__ . ' C' ), + User::newFromName( 'IW>' . __CLASS__, false ), ]; $title = Title::newFromText( __CLASS__ ); @@ -146,4 +147,48 @@ class ApiQueryContributionsTest extends ApiTestCase { } } } + + /** + * @dataProvider provideInterwikiUser + * @param int $stage One of the MIGRATION_* constants for $wgActorTableSchemaMigrationStage + */ + public function testInterwikiUser( $stage ) { + $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage ); + $this->overrideMwServices(); + + $params = [ + 'action' => 'query', + 'list' => 'usercontribs', + 'ucuser' => 'IW>' . __CLASS__, + 'ucprop' => 'ids', + 'uclimit' => 'max', + ]; + + $apiResult = $this->doApiRequest( $params ); + $this->assertArrayNotHasKey( 'continue', $apiResult[0] ); + $this->assertArrayHasKey( 'query', $apiResult[0] ); + $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'] ); + + $count = 0; + $ids = []; + foreach ( $apiResult[0]['query']['usercontribs'] as $page ) { + $count++; + $this->assertSame( 'IW>' . __CLASS__, $page['user'], 'Correct user returned' ); + $ids[] = $page['revid']; + } + $this->assertSame( 3, $count, 'Expected number of revisions' ); + $sorted = $ids; + rsort( $sorted ); + $this->assertSame( $sorted, $ids, "IDs are sorted" ); + } + + public static function provideInterwikiUser() { + return [ + 'old' => [ MIGRATION_OLD ], + 'write both' => [ MIGRATION_WRITE_BOTH ], + 'write new' => [ MIGRATION_WRITE_NEW ], + 'new' => [ MIGRATION_NEW ], + ]; + } + } -- 2.20.1