}
public function execute() {
- $db = $this->getDB();
$params = $this->extractRequestParams();
+ if ( $params['activeusers'] ) {
+ // Update active user cache
+ SpecialActiveUsers::mergeActiveUsers( 600 );
+ }
+
+ $db = $this->getDB();
+
$prop = $params['prop'];
if ( !is_null( $prop ) ) {
$prop = array_flip( $prop );
$from = is_null( $params['from'] ) ? null : $this->getCanonicalUserName( $params['from'] );
$to = is_null( $params['to'] ) ? null : $this->getCanonicalUserName( $params['to'] );
- # MySQL doesn't seem to use 'equality propagation' here, so like the
- # ActiveUsers special page, we have to use rc_user_text for some cases.
- $userFieldToSort = $params['activeusers'] ? 'rc_user_text' : 'user_name';
+ # MySQL can't figure out that 'user_name' and 'qcc_title' are the same
+ # despite the JOIN condition, so manually sort on the correct one.
+ $userFieldToSort = $params['activeusers'] ? 'qcc_title' : 'user_name';
$this->addWhereRange( $userFieldToSort, $dir, $from, $to );
}
if ( $params['activeusers'] ) {
- $this->addTables( 'recentchanges' );
-
- $this->addJoinConds( array( 'recentchanges' => array(
- 'INNER JOIN', 'rc_user_text=user_name'
+ $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
+
+ // Filter query to only include users in the active users cache
+ $this->addTables( 'querycachetwo' );
+ $this->addJoinConds( array( 'querycachetwo' => array(
+ 'INNER JOIN', array(
+ 'qcc_type' => 'activeusers',
+ 'qcc_namespace' => NS_USER,
+ 'qcc_title=user_name',
+ ),
) ) );
- $this->addFields( array( 'recentedits' => 'COUNT(*)' ) );
-
- $this->addWhere( 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes( 'newusers' ) );
- $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $this->getConfig()->get( 'ActiveUserDays' ) * 24 * 3600 );
- $this->addWhere( 'rc_timestamp >= ' . $db->addQuotes( $timestamp ) );
-
- $this->addOption( 'GROUP BY', $userFieldToSort );
+ // Actually count the actions using a subquery (bug 64505 and bug 64507)
+ $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
+ $this->addFields( array(
+ 'recentactions' => '(' . $db->selectSQLText(
+ 'recentchanges',
+ 'COUNT(*)',
+ array(
+ 'rc_user_text = user_name',
+ 'rc_type != ' . $db->addQuotes( RC_EXTERNAL ), // no wikidata
+ 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes( 'newusers' ),
+ 'rc_timestamp >= ' . $db->addQuotes( $timestamp ),
+ )
+ ) . ')'
+ ) );
}
$this->addOption( 'LIMIT', $sqlLimit );
if ( $lastUser !== $row->user_name ) {
// Save the last pass's user data
if ( is_array( $lastUserData ) ) {
- $fit = $result->addValue( array( 'query', $this->getModuleName() ),
- null, $lastUserData );
+ if ( $params['activeusers'] && $lastUserData['recentactions'] === 0 ) {
+ // activeusers cache was out of date
+ $fit = true;
+ } else {
+ $fit = $result->addValue( array( 'query', $this->getModuleName() ),
+ null, $lastUserData );
+ }
$lastUserData = null;
$lastUserData['editcount'] = intval( $row->user_editcount );
}
if ( $params['activeusers'] ) {
- $lastUserData['recenteditcount'] = intval( $row->recentedits );
+ $lastUserData['recentactions'] = intval( $row->recentactions );
+ // @todo 'recenteditcount' is set for BC, remove in 1.25
+ $lastUserData['recenteditcount'] = $lastUserData['recentactions'];
}
if ( $fld_registration ) {
$lastUserData['registration'] = $row->user_registration ?
}
}
- if ( is_array( $lastUserData ) ) {
+ if ( is_array( $lastUserData ) &&
+ !( $params['activeusers'] && $lastUserData['recentactions'] === 0 )
+ ) {
$fit = $result->addValue( array( 'query', $this->getModuleName() ),
null, $lastUserData );
if ( !$fit ) {
'' => array(
'userid' => 'integer',
'name' => 'string',
- 'recenteditcount' => array(
+ 'recentactions' => array(
ApiBase::PROP_TYPE => 'integer',
ApiBase::PROP_NULLABLE => true
)