From: Brad Jorsch Date: Wed, 23 Jan 2013 20:40:57 +0000 (-0500) Subject: (bug 44244) Add number of watchers to API prop=info X-Git-Tag: 1.31.0-rc.0~20504 X-Git-Url: http://git.cyclocoop.org/%24self?a=commitdiff_plain;h=b16f5bf88ea4841d077bdcf0d52cb441783a9a2c;p=lhc%2Fweb%2Fwiklou.git (bug 44244) Add number of watchers to API prop=info Following up I1cb6ee22, which added this information to each page's action=info, this adds inprop=watchers to query the number of people watching the page. It is subject to the same limitations (user has unwatchedpages or watchers >= $wgUnwatchedPageThreshold) as action=info. Also, update doc for $wgUnwatchedPageThreshold to match reality. Bug: 44244 Change-Id: Ideaac1d84bbe0349154ffe96ba54d74305e3da1d --- diff --git a/RELEASE-NOTES-1.21 b/RELEASE-NOTES-1.21 index 1d5622107b..3471dbe31a 100644 --- a/RELEASE-NOTES-1.21 +++ b/RELEASE-NOTES-1.21 @@ -248,6 +248,7 @@ production. used for action=upload's 'file' and 'chunk' parameters. This type will raise an error during parameter validation if the parameter is given but not recognized as an uploaded file. +* (bug 44244) prop=info may now return the number of people watching each page. === API internal changes in 1.21 === * For debugging only, a new global $wgDebugAPI removes many API restrictions when true. diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 7aad30c571..73c097efd0 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -5245,9 +5245,9 @@ $wgAllowCategorizedRecentChanges = false; $wgUseTagFilter = true; /** - * If set to an integer, pages that are watched by more users than this - * threshold will not require the unwatchedpages permission to view the - * number of watchers. + * If set to an integer, pages that are watched by this many users or more + * will not require the unwatchedpages permission to view the number of + * watchers. * * @since 1.21 */ diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index 779720546f..a888d997f2 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -33,7 +33,8 @@ class ApiQueryInfo extends ApiQueryBase { private $fld_protection = false, $fld_talkid = false, $fld_subjectid = false, $fld_url = false, - $fld_readable = false, $fld_watched = false, $fld_notificationtimestamp = false, + $fld_readable = false, $fld_watched = false, $fld_watchers = false, + $fld_notificationtimestamp = false, $fld_preload = false, $fld_displaytitle = false; private $params, $titles, $missing, $everything, $pageCounter; @@ -41,7 +42,8 @@ class ApiQueryInfo extends ApiQueryBase { private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched, $pageLatest, $pageLength; - private $protections, $watched, $notificationtimestamps, $talkids, $subjectids, $displaytitles; + private $protections, $watched, $watchers, $notificationtimestamps, $talkids, $subjectids, $displaytitles; + private $showZeroWatchers = false; private $tokenFunctions; @@ -248,6 +250,7 @@ class ApiQueryInfo extends ApiQueryBase { $prop = array_flip( $this->params['prop'] ); $this->fld_protection = isset( $prop['protection'] ); $this->fld_watched = isset( $prop['watched'] ); + $this->fld_watchers = isset( $prop['watchers'] ); $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] ); $this->fld_talkid = isset( $prop['talkid'] ); $this->fld_subjectid = isset( $prop['subjectid'] ); @@ -305,6 +308,10 @@ class ApiQueryInfo extends ApiQueryBase { $this->getWatchedInfo(); } + if ( $this->fld_watchers ) { + $this->getWatcherInfo(); + } + // Run the talkid/subjectid query if requested if ( $this->fld_talkid || $this->fld_subjectid ) { $this->getTSIDs(); @@ -384,6 +391,14 @@ class ApiQueryInfo extends ApiQueryBase { $pageInfo['watched'] = ''; } + if ( $this->fld_watchers ) { + if ( isset( $this->watchers[$ns][$dbkey] ) ) { + $pageInfo['watchers'] = $this->watchers[$ns][$dbkey]; + } elseif ( $this->showZeroWatchers ) { + $pageInfo['watchers'] = 0; + } + } + if ( $this->fld_notificationtimestamp ) { $pageInfo['notificationtimestamp'] = ''; if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) { @@ -675,6 +690,46 @@ class ApiQueryInfo extends ApiQueryBase { } } + /** + * Get the count of watchers and put it in $this->watchers + */ + private function getWatcherInfo() { + global $wgUnwatchedPageThreshold; + + if ( count( $this->everything ) == 0 ) { + return; + } + + $user = $this->getUser(); + $canUnwatchedpages = $user->isAllowed( 'unwatchedpages' ); + if ( !$canUnwatchedpages && !is_int( $wgUnwatchedPageThreshold ) ) { + return; + } + + $this->watchers = array(); + $this->showZeroWatchers = $canUnwatchedpages; + $db = $this->getDB(); + + $lb = new LinkBatch( $this->everything ); + + $this->resetQueryParams(); + $this->addTables( array( 'watchlist' ) ); + $this->addFields( array( 'wl_title', 'wl_namespace', 'count' => 'COUNT(*)' ) ); + $this->addWhere( array( + $lb->constructSet( 'wl', $db ) + ) ); + $this->addOption( 'GROUP BY', array( 'wl_namespace', 'wl_title' ) ); + if ( !$canUnwatchedpages ) { + $this->addOption( 'HAVING', "COUNT(*) >= $wgUnwatchedPageThreshold" ); + } + + $res = $this->select( __METHOD__ ); + + foreach ( $res as $row ) { + $this->watchers[$row->wl_namespace][$row->wl_title] = (int)$row->count; + } + } + public function getCacheMode( $params ) { $publicProps = array( 'protection', @@ -706,6 +761,7 @@ class ApiQueryInfo extends ApiQueryBase { 'protection', 'talkid', 'watched', # private + 'watchers', # private 'notificationtimestamp', # private 'subjectid', 'url', @@ -731,6 +787,7 @@ class ApiQueryInfo extends ApiQueryBase { ' protection - List the protection level of each page', ' talkid - The page ID of the talk page for each non-talk page', ' watched - List the watched status of each page', + ' watchers - The number of watchers, if allowed', ' notificationtimestamp - The watchlist notification timestamp of each page', ' subjectid - The page ID of the parent page for each talk page', ' url - Gives a full URL to the page, and also an edit URL', @@ -764,6 +821,12 @@ class ApiQueryInfo extends ApiQueryBase { 'watched' => array( 'watched' => 'boolean' ), + 'watchers' => array( + 'watchers' => array( + ApiBase::PROP_TYPE => 'integer', + ApiBase::PROP_NULLABLE => true + ) + ), 'notificationtimestamp' => array( 'notificationtimestamp' => array( ApiBase::PROP_TYPE => 'timestamp',