SpecialContributions: Use PoolCounter to limit concurrency
[lhc/web/wiklou.git] / includes / specials / SpecialContributions.php
index 4775a7f..2812541 100644 (file)
@@ -40,14 +40,12 @@ class SpecialContributions extends IncludableSpecialPage {
                $this->setHeaders();
                $this->outputHeader();
                $out = $this->getOutput();
+               // Modules required for viewing the list of contributions (also when included on other pages)
                $out->addModuleStyles( [
                        'mediawiki.special',
                        'mediawiki.special.changeslist',
-                       'mediawiki.widgets.DateInputWidget.styles',
                ] );
-               $out->addModules( 'mediawiki.special.contributions' );
                $this->addHelpLink( 'Help:User contributions' );
-               $out->enableOOUI();
 
                $this->opts = [];
                $request = $this->getRequest();
@@ -83,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(
@@ -110,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 );
@@ -220,20 +230,39 @@ class SpecialContributions extends IncludableSpecialPage {
                        } elseif ( !$pager->getNumRows() ) {
                                $out->addWikiMsg( 'nocontribs', $target );
                        } else {
-                               # Show a message about replica DB lag, if applicable
-                               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
-                               $lag = $lb->safeGetLag( $pager->getDatabase() );
-                               if ( $lag > 0 ) {
-                                       $out->showLagWarning( $lag );
-                               }
-
-                               $output = $pager->getBody();
-                               if ( !$this->including() ) {
-                                       $output = '<p>' . $pager->getNavigationBar() . '</p>' .
-                                               $output .
-                                               '<p>' . $pager->getNavigationBar() . '</p>';
+                               // @todo We just want a wiki ID here, not a "DB domain", but
+                               // current status of MediaWiki conflates the two. See T235955.
+                               $poolKey = WikiMap::getCurrentWikiDbDomain() . ':SpecialContributions:';
+                               if ( $this->getUser()->isAnon() ) {
+                                       $poolKey .= 'a:' . $this->getUser()->getName();
+                               } else {
+                                       $poolKey .= 'u:' . $this->getUser()->getId();
                                }
-                               $out->addHTML( $output );
+                               $work = new PoolCounterWorkViaCallback( 'SpecialContributions', $poolKey, [
+                                       'doWork' => function () use ( $pager, $out ) {
+                                               # Show a message about replica DB lag, if applicable
+                                               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
+                                               $lag = $lb->safeGetLag( $pager->getDatabase() );
+                                               if ( $lag > 0 ) {
+                                                       $out->showLagWarning( $lag );
+                                               }
+
+                                               $output = $pager->getBody();
+                                               if ( !$this->including() ) {
+                                                       $output = '<p>' . $pager->getNavigationBar() . '</p>' .
+                                                               $output .
+                                                               '<p>' . $pager->getNavigationBar() . '</p>';
+                                               }
+                                               $out->addHTML( $output );
+                                       },
+                                       'error' => function () use ( $out ) {
+                                               $msg = $this->getUser()->isAnon()
+                                                       ? 'sp-contributions-concurrency-ip'
+                                                       : 'sp-contributions-concurrency-user';
+                                               $out->wrapWikiMsg( "<div class='errorbox'>\n$1\n</div>", $msg );
+                                       }
+                               ] );
+                               $work->execute();
                        }
 
                        $out->preventClickjacking( $pager->getPreventClickjacking() );
@@ -497,6 +526,14 @@ class SpecialContributions extends IncludableSpecialPage {
                        $this->opts['hideMinor'] = false;
                }
 
+               // Modules required only for the form
+               $this->getOutput()->addModules( [
+                       'mediawiki.userSuggest',
+                       'mediawiki.special.contributions',
+               ] );
+               $this->getOutput()->addModuleStyles( 'mediawiki.widgets.DateInputWidget.styles' );
+               $this->getOutput()->enableOOUI();
+
                $form = Html::openElement(
                        'form',
                        [
@@ -544,8 +581,6 @@ class SpecialContributions extends IncludableSpecialPage {
                        $filterSelection = Html::rawElement( 'div', [], '' );
                }
 
-               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
-
                $labelNewbies = Xml::radioLabel(
                        $this->msg( 'sp-contributions-newbies' )->text(),
                        'contribs',