Merge "[FileBackend] Made it easy to use registed file backend config in multi-write...
[lhc/web/wiklou.git] / includes / api / ApiQueryRecentChanges.php
index 8dc6fe3..2d2d9ff 100644 (file)
  * @file
  */
 
-if ( !defined( 'MEDIAWIKI' ) ) {
-       // Eclipse helper - will be ignored in production
-       require_once( 'ApiQueryBase.php' );
-}
-
 /**
  * A query action to enumerate the recent changes that were done to the wiki.
  * Various filters are supported.
@@ -43,7 +38,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
        private $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
                        $fld_flags = false, $fld_timestamp = false, $fld_title = false, $fld_ids = false,
-                       $fld_sizes = false, $fld_redirect = false, $fld_patrolled = false, $fld_loginfo = false, $fld_tags = false;
+                       $fld_sizes = false, $fld_redirect = false, $fld_patrolled = false, $fld_loginfo = false,
+                       $fld_tags = false, $token = array();
 
        private $tokenFunctions;
 
@@ -51,7 +47,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
         * Get an array mapping token names to their handler functions.
         * The prototype for a token function is func($pageid, $title, $rc)
         * it should return a token or false (permission denied)
-        * @return array(tokenname => function)
+        * @return array array(tokenname => function)
         */
        protected function getTokenFunctions() {
                // Don't call the hooks twice
@@ -72,27 +68,39 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @static
         * @param  $pageid
         * @param  $title
-        * @param $rc RecentChange
+        * @param $rc RecentChange (optional)
         * @return bool|String
         */
-       public static function getPatrolToken( $pageid, $title, $rc ) {
+       public static function getPatrolToken( $pageid, $title, $rc = null ) {
                global $wgUser;
-               if ( !$wgUser->useRCPatrol() && ( !$wgUser->useNPPatrol() ||
-                               $rc->getAttribute( 'rc_type' ) != RC_NEW ) )
-               {
-                       return false;
+
+               $validTokenUser = false;
+
+               if ( $rc ) {
+                       if ( ( $wgUser->useRCPatrol() && $rc->getAttribute( 'rc_type' ) == RC_EDIT ) ||
+                               ( $wgUser->useNPPatrol() && $rc->getAttribute( 'rc_type' ) == RC_NEW ) )
+                       {
+                               $validTokenUser = true;
+                       }
+               } else {
+                       if ( $wgUser->useRCPatrol() || $wgUser->useNPPatrol() ) {
+                               $validTokenUser = true;
+                       }
                }
 
-               // The patrol token is always the same, let's exploit that
-               static $cachedPatrolToken = null;
-               if ( is_null( $cachedPatrolToken ) ) {
-                       $cachedPatrolToken = $wgUser->editToken( 'patrol' );
+               if ( $validTokenUser ) {
+                       // The patrol token is always the same, let's exploit that
+                       static $cachedPatrolToken = null;
+                       if ( is_null( $cachedPatrolToken ) ) {
+                               $cachedPatrolToken = $wgUser->getEditToken( 'patrol' );
+                       }
+                       return $cachedPatrolToken;
+               } else {
+                       return false;
                }
 
-               return $cachedPatrolToken;
        }
 
        /**
@@ -129,7 +137,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
         * @param $resultPageSet ApiPageSet
         */
        public function run( $resultPageSet = null ) {
-               global $wgUser;
+               $user = $this->getUser();
                /* Get the parameters of the request. */
                $params = $this->extractRequestParams();
 
@@ -140,7 +148,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                 */
                $this->addTables( 'recentchanges' );
                $index = array( 'recentchanges' => 'rc_timestamp' ); // May change
-               $this->addWhereRange( 'rc_timestamp', $params['dir'], $params['start'], $params['end'] );
+               $this->addTimestampWhereRange( 'rc_timestamp', $params['dir'], $params['start'], $params['end'] );
                $this->addWhereFld( 'rc_namespace', $params['namespace'] );
                $this->addWhereFld( 'rc_deleted', 0 );
 
@@ -157,14 +165,13 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                        || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
                                        || ( isset( $show['redirect'] ) && isset( $show['!redirect'] ) )
                                        || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
-                       )
-                       {
-                               $this->dieUsageMsg( array( 'show' ) );
+                       ) {
+                               $this->dieUsageMsg( 'show' );
                        }
 
                        // Check permissions
                        if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
-                               if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) {
+                               if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
                                        $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
                                }
                        }
@@ -212,6 +219,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        'rc_deleted'
                ) );
 
+               $showRedirects = false;
                /* Determine what properties we need to display. */
                if ( !is_null( $params['prop'] ) ) {
                        $prop = array_flip( $params['prop'] );
@@ -219,32 +227,20 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        /* Set up internal members based upon params. */
                        $this->initProperties( $prop );
 
-                       if ( $this->fld_patrolled && !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) {
+                       if ( $this->fld_patrolled && !$user->useRCPatrol() && !$user->useNPPatrol() ) {
                                $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
                        }
 
                        /* Add fields to our query if they are specified as a needed parameter. */
-                       $this->addFieldsIf( 'rc_id', $this->fld_ids );
-                       $this->addFieldsIf( 'rc_this_oldid', $this->fld_ids );
-                       $this->addFieldsIf( 'rc_last_oldid', $this->fld_ids );
+                       $this->addFieldsIf( array( 'rc_id', 'rc_this_oldid', 'rc_last_oldid' ), $this->fld_ids );
                        $this->addFieldsIf( 'rc_comment', $this->fld_comment || $this->fld_parsedcomment );
                        $this->addFieldsIf( 'rc_user', $this->fld_user );
                        $this->addFieldsIf( 'rc_user_text', $this->fld_user || $this->fld_userid );
-                       $this->addFieldsIf( 'rc_minor', $this->fld_flags );
-                       $this->addFieldsIf( 'rc_bot', $this->fld_flags );
-                       $this->addFieldsIf( 'rc_new', $this->fld_flags );
-                       $this->addFieldsIf( 'rc_old_len', $this->fld_sizes );
-                       $this->addFieldsIf( 'rc_new_len', $this->fld_sizes );
+                       $this->addFieldsIf( array( 'rc_minor', 'rc_new', 'rc_bot' ) , $this->fld_flags );
+                       $this->addFieldsIf( array( 'rc_old_len', 'rc_new_len' ), $this->fld_sizes );
                        $this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
-                       $this->addFieldsIf( 'rc_logid', $this->fld_loginfo );
-                       $this->addFieldsIf( 'rc_log_type', $this->fld_loginfo );
-                       $this->addFieldsIf( 'rc_log_action', $this->fld_loginfo );
-                       $this->addFieldsIf( 'rc_params', $this->fld_loginfo );
-                       if ( $this->fld_redirect || isset( $show['redirect'] ) || isset( $show['!redirect'] ) ) {
-                               $this->addTables( 'page' );
-                               $this->addJoinConds( array( 'page' => array( 'LEFT JOIN', array( 'rc_namespace=page_namespace', 'rc_title=page_title' ) ) ) );
-                               $this->addFields( 'page_is_redirect' );
-                       }
+                       $this->addFieldsIf( array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ), $this->fld_loginfo );
+                       $showRedirects = $this->fld_redirect || isset( $show['redirect'] ) || isset( $show['!redirect'] );
                }
 
                if ( $this->fld_tags ) {
@@ -253,6 +249,16 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $this->addFields( 'ts_tags' );
                }
 
+               if ( $params['toponly'] || $showRedirects ) {
+                       $this->addTables( 'page' );
+                       $this->addJoinConds( array( 'page' => array( 'LEFT JOIN', array( 'rc_namespace=page_namespace', 'rc_title=page_title' ) ) ) );
+                       $this->addFields( 'page_is_redirect' );
+
+                       if ( $params['toponly'] ) {
+                               $this->addWhere( 'rc_this_oldid = page_latest' );
+                       }
+               }
+
                if ( !is_null( $params['tag'] ) ) {
                        $this->addTables( 'change_tag' );
                        $this->addJoinConds( array( 'change_tag' => array( 'INNER JOIN', array( 'rc_id=ct_rc_id' ) ) ) );
@@ -271,6 +277,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                $titles = array();
 
+               $result = $this->getResult();
+
                /* Iterate through the rows, adding data extracted from them to our query result. */
                foreach ( $res as $row ) {
                        if ( ++ $count > $params['limit'] ) {
@@ -287,7 +295,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                if ( !$vals ) {
                                        continue;
                                }
-                               $fit = $this->getResult()->addValue( array( 'query', $this->getModuleName() ), null, $vals );
+                               $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
                                if ( !$fit ) {
                                        $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) );
                                        break;
@@ -299,7 +307,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                if ( is_null( $resultPageSet ) ) {
                        /* Format the result */
-                       $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'rc' );
+                       $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'rc' );
                } else {
                        $resultPageSet->populateFromTitles( $titles );
                }
@@ -309,7 +317,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
         * Extracts from a single sql row the data needed to describe one recent change.
         *
         * @param $row The row from which to extract the data.
-        * @return An array mapping strings (descriptors) to their respective string values.
+        * @return array An array mapping strings (descriptors) to their respective string values.
         * @access public
         */
        public function extractRowInfo( $row ) {
@@ -410,8 +418,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                }
 
                if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) {
-                       global $wgUser;
-                       $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rc_comment, $title );
+                       $vals['parsedcomment'] = Linker::formatComment( $row->rc_comment, $title );
                }
 
                if ( $this->fld_redirect ) {
@@ -429,10 +436,14 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $vals['logid'] = intval( $row->rc_logid );
                        $vals['logtype'] = $row->rc_log_type;
                        $vals['logaction'] = $row->rc_log_action;
+                       $logEntry = DatabaseLogEntry::newFromRow( (array)$row );
                        ApiQueryLogEvents::addLogParams(
                                $this->getResult(),
-                               $vals, $row->rc_params,
-                               $row->rc_log_type, $row->rc_timestamp
+                               $vals,
+                               $logEntry->getParameters(),
+                               $logEntry->getType(),
+                               $logEntry->getSubtype(),
+                               $logEntry->getTimestamp()
                        );
                }
 
@@ -576,15 +587,17 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                        'new',
                                        'log'
                                )
-                       )
+                       ),
+                       'toponly' => false,
                );
        }
 
        public function getParamDescription() {
+               $p = $this->getModulePrefix();
                return array(
                        'start' => 'The timestamp to start enumerating from',
                        'end' => 'The timestamp to end enumerating',
-                       'dir' => 'In which direction to enumerate',
+                       'dir' => $this->getDirectionDescription( $p ),
                        'namespace' => 'Filter log entries to only this namespace(s)',
                        'user' => 'Only list changes by this user',
                        'excludeuser' => 'Don\'t list changes by this user',
@@ -607,11 +620,12 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        'token' => 'Which tokens to obtain for each change',
                        'show' => array(
                                'Show only items that meet this criteria.',
-                               "For example, to see only minor edits done by logged-in users, set {$this->getModulePrefix()}show=minor|!anon"
+                               "For example, to see only minor edits done by logged-in users, set {$p}show=minor|!anon"
                        ),
                        'type' => 'Which types of changes to show',
                        'limit' => 'How many total changes to return',
                        'tag' => 'Only list changes tagged with this tag',
+                       'toponly' => 'Only list changes which are the latest revision',
                );
        }
 
@@ -627,12 +641,16 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                ) );
        }
 
-       protected function getExamples() {
+       public function getExamples() {
                return array(
                        'api.php?action=query&list=recentchanges'
                );
        }
 
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/API:Recentchanges';
+       }
+
        public function getVersion() {
                return __CLASS__ . ': $Id$';
        }