Allow querying contributions of interwiki usernames
authorBrad Jorsch <bjorsch@wikimedia.org>
Mon, 12 Feb 2018 15:11:40 +0000 (10:11 -0500)
committerBrad Jorsch <bjorsch@wikimedia.org>
Tue, 6 Mar 2018 18:28:30 +0000 (13:28 -0500)
Both for Special:Contributions and ApiQueryUserContributions.

Bug: T187079
Change-Id: I4398e473b90172851e875b3f219f7076dceda66c

includes/api/ApiBase.php
includes/api/ApiQueryUserContributions.php
includes/specials/SpecialContributions.php
tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php

index 228d319..73315a0 100644 (file)
@@ -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(
index e587ef4..bb4a2ef 100644 (file)
@@ -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' );
index 806713b..6fc8306 100644 (file)
@@ -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 );
index 6e8bc0b..ca6a929 100644 (file)
@@ -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 ],
+               ];
+       }
+
 }