Merge "Indicate the actual version of HHVM in use"
[lhc/web/wiklou.git] / includes / api / ApiQueryAllUsers.php
index e32104f..dfef286 100644 (file)
@@ -45,8 +45,15 @@ class ApiQueryAllUsers extends ApiQueryBase {
        }
 
        public function execute() {
-               $db = $this->getDB();
                $params = $this->extractRequestParams();
+               $activeUserDays = $this->getConfig()->get( 'ActiveUserDays' );
+
+               if ( $params['activeusers'] ) {
+                       // Update active user cache
+                       SpecialActiveUsers::mergeActiveUsers( 600, $activeUserDays );
+               }
+
+               $db = $this->getDB();
 
                $prop = $params['prop'];
                if ( !is_null( $prop ) ) {
@@ -71,9 +78,9 @@ class ApiQueryAllUsers extends ApiQueryBase {
                $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 );
 
@@ -155,19 +162,32 @@ class ApiQueryAllUsers extends ApiQueryBase {
                }
 
                if ( $params['activeusers'] ) {
-                       $this->addTables( 'recentchanges' );
-
-                       $this->addJoinConds( array( 'recentchanges' => array(
-                               'INNER JOIN', 'rc_user_text=user_name'
+                       $activeUserSeconds = $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 );
@@ -203,8 +223,13 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        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;
 
@@ -241,7 +266,9 @@ class ApiQueryAllUsers extends ApiQueryBase {
                                        $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 ?
@@ -302,7 +329,9 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        }
                }
 
-               if ( is_array( $lastUserData ) ) {
+               if ( is_array( $lastUserData ) &&
+                       !( $params['activeusers'] && $lastUserData['recentactions'] === 0 )
+               ) {
                        $fit = $result->addValue( array( 'query', $this->getModuleName() ),
                                null, $lastUserData );
                        if ( !$fit ) {
@@ -392,61 +421,10 @@ class ApiQueryAllUsers extends ApiQueryBase {
                );
        }
 
-       public function getResultProperties() {
-               return array(
-                       '' => array(
-                               'userid' => 'integer',
-                               'name' => 'string',
-                               'recenteditcount' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               )
-                       ),
-                       'blockinfo' => array(
-                               'blockid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedby' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedbyid' => array(
-                                       ApiBase::PROP_TYPE => 'integer',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedreason' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'blockedexpiry' => array(
-                                       ApiBase::PROP_TYPE => 'string',
-                                       ApiBase::PROP_NULLABLE => true
-                               ),
-                               'hidden' => 'boolean'
-                       ),
-                       'editcount' => array(
-                               'editcount' => 'integer'
-                       ),
-                       'registration' => array(
-                               'registration' => 'string'
-                       )
-               );
-       }
-
        public function getDescription() {
                return 'Enumerate all registered users.';
        }
 
-       public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array(
-                               'code' => 'group-excludegroup',
-                               'info' => 'group and excludegroup cannot be used together'
-                       ),
-               ) );
-       }
-
        public function getExamples() {
                return array(
                        'api.php?action=query&list=allusers&aufrom=Y',