private $fld_protection = false, $fld_talkid = false,
$fld_subjectid = false, $fld_url = false,
- $fld_readable = false, $fld_watched = false, $fld_watchers = false,
+ $fld_readable = false, $fld_watched = false,
+ $fld_watchers = false, $fld_visitingwatchers = false,
$fld_notificationtimestamp = false,
$fld_preload = false, $fld_displaytitle = false;
private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched,
$pageLatest, $pageLength;
- private $protections, $restrictionTypes, $watched, $watchers, $notificationtimestamps,
- $talkids, $subjectids, $displaytitles;
+ private $protections, $restrictionTypes, $watched, $watchers, $visitingwatchers,
+ $notificationtimestamps, $talkids, $subjectids, $displaytitles;
private $showZeroWatchers = false;
private $tokenFunctions;
$this->fld_protection = isset( $prop['protection'] );
$this->fld_watched = isset( $prop['watched'] );
$this->fld_watchers = isset( $prop['watchers'] );
+ $this->fld_visitingwatchers = isset( $prop['visitingwatchers'] );
$this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] );
$this->fld_talkid = isset( $prop['talkid'] );
$this->fld_subjectid = isset( $prop['subjectid'] );
$this->getWatcherInfo();
}
+ if ( $this->fld_visitingwatchers ) {
+ $this->getVisitingWatcherInfo();
+ }
+
// Run the talkid/subjectid query if requested
if ( $this->fld_talkid || $this->fld_subjectid ) {
$this->getTSIDs();
}
}
+ if ( $this->fld_visitingwatchers ) {
+ if ( isset( $this->visitingwatchers[$ns][$dbkey] ) ) {
+ $pageInfo['visitingwatchers'] = $this->visitingwatchers[$ns][$dbkey];
+ } elseif ( $this->showZeroWatchers ) {
+ $pageInfo['visitingwatchers'] = 0;
+ }
+ }
+
if ( $this->fld_notificationtimestamp ) {
$pageInfo['notificationtimestamp'] = '';
if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) {
}
}
+ /**
+ * Get the count of watchers who have visited recent edits and put it in
+ * $this->visitingwatchers
+ *
+ * Based on InfoAction::pageCounts
+ */
+ private function getVisitingWatcherInfo() {
+ $config = $this->getConfig();
+ $user = $this->getUser();
+ $db = $this->getDB();
+
+ $canUnwatchedpages = $user->isAllowed( 'unwatchedpages' );
+ $unwatchedPageThreshold = $this->getConfig()->get( 'UnwatchedPageThreshold' );
+ if ( !$canUnwatchedpages && !is_int( $unwatchedPageThreshold ) ) {
+ return;
+ }
+
+ $this->showZeroWatchers = $canUnwatchedpages;
+
+ // Assemble a WHERE condition to find:
+ // * if the page exists, number of users watching who have
+ // visited the page recently
+ // * if the page doesn't exist, number of users that have
+ // the page on their watchlist
+ $whereStrings = array();
+
+ // For pages that exist
+ if ( $this->titles ) {
+ $lb = new LinkBatch( $this->titles );
+
+ // Fetch last edit timestamps for pages
+ $this->resetQueryParams();
+ $this->addTables( array( 'page', 'revision' ) );
+ $this->addFields( array( 'page_namespace', 'page_title', 'rev_timestamp' ) );
+ $this->addWhere( array(
+ 'page_latest = rev_id',
+ $lb->constructSet( 'page', $db ),
+ ) );
+ $this->addOption( 'GROUP BY', array( 'page_namespace', 'page_title' ) );
+ $timestampRes = $this->select( __METHOD__ );
+
+ // Assemble SQL WHERE condition to find number of page watchers who also
+ // visited a "recent" edit (last visited about 26 weeks before latest edit)
+ $age = $config->get( 'WatchersMaxAge' );
+ $timestamps = array();
+ foreach ( $timestampRes as $row ) {
+ $revTimestamp = wfTimestamp( TS_UNIX, (int)$row->rev_timestamp );
+ $threshold = $db->timestamp( $revTimestamp - $age );
+ $timestamps[$row->page_namespace][$row->page_title] = $threshold;
+ }
+
+ foreach ( $timestamps as $ns_key => $namespace ) {
+ $pageStrings = array();
+ foreach ( $namespace as $pg_key => $threshold ) {
+ $pageStrings[] = "wl_title = '$pg_key' AND" .
+ ' (wl_notificationtimestamp >= ' .
+ $db->addQuotes( $threshold ) .
+ ' OR wl_notificationtimestamp IS NULL)';
+ }
+ $whereStrings[] = "wl_namespace = '$ns_key' AND (" .
+ $db->makeList( $pageStrings, LIST_OR ) . ')';
+ }
+ }
+
+ // For nonexistant pages
+ if ( $this->missing ) {
+ $lb = new LinkBatch( $this->missing );
+ $whereStrings[] = $lb->constructSet( 'wl', $db );
+ }
+
+ // Make the actual string and do the query
+ $whereString = $db->makeList( $whereStrings, LIST_OR );
+
+ $this->resetQueryParams();
+ $this->addTables( array( 'watchlist' ) );
+ $this->addFields( array(
+ 'wl_namespace',
+ 'wl_title',
+ 'count' => 'COUNT(*)'
+ ) );
+ $this->addWhere( array( $whereString ) );
+ $this->addOption( 'GROUP BY', array( 'wl_namespace', 'wl_title' ) );
+ if ( !$canUnwatchedpages ) {
+ $this->addOption( 'HAVING', "COUNT(*) >= $unwatchedPageThreshold" );
+ }
+
+ $res = $this->select( __METHOD__ );
+ foreach ( $res as $row ) {
+ $this->visitingwatchers[$row->wl_namespace][$row->wl_title] = (int)$row->count;
+ }
+ }
+
public function getCacheMode( $params ) {
// Other props depend on something about the current user
$publicProps = array(
'talkid',
'watched', # private
'watchers', # private
+ 'visitingwatchers', # private
'notificationtimestamp', # private
'subjectid',
'url',