Merge "Wrap auto-numbering for section heading in a classed span (bug 33450)"
[lhc/web/wiklou.git] / includes / api / ApiQueryInfo.php
index 12f47d3..a6c0ed5 100644 (file)
@@ -1,9 +1,8 @@
 <?php
-
 /**
- * Created on Sep 25, 2006
  *
- * API for MediaWiki 1.8+
+ *
+ * Created on Sep 25, 2006
  *
  * Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
  *
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
  */
 
-if ( !defined( 'MEDIAWIKI' ) ) {
-       // Eclipse helper - will be ignored in production
-       require_once( 'ApiQueryBase.php' );
-}
-
 /**
  * A query module to show basic page information.
  *
@@ -40,15 +36,32 @@ class ApiQueryInfo extends ApiQueryBase {
                $fld_readable = false, $fld_watched = false,
                $fld_preload = false, $fld_displaytitle = false;
 
+       private $params, $titles, $missing, $everything, $pageCounter;
+
+       private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched,
+               $pageLatest, $pageLength;
+
+       private $protections, $watched, $talkids, $subjectids, $displaytitles;
+
+       private $tokenFunctions;
+
        public function __construct( $query, $moduleName ) {
                parent::__construct( $query, $moduleName, 'in' );
        }
 
+       /**
+        * @param $pageSet ApiPageSet
+        * @return void
+        */
        public function requestExtraData( $pageSet ) {
+               global $wgDisableCounters;
+
                $pageSet->requestField( 'page_restrictions' );
                $pageSet->requestField( 'page_is_redirect' );
                $pageSet->requestField( 'page_is_new' );
-               $pageSet->requestField( 'page_counter' );
+               if ( !$wgDisableCounters ) {
+                       $pageSet->requestField( 'page_counter' );
+               }
                $pageSet->requestField( 'page_touched' );
                $pageSet->requestField( 'page_latest' );
                $pageSet->requestField( 'page_len' );
@@ -58,7 +71,7 @@ class ApiQueryInfo extends ApiQueryBase {
         * Get an array mapping token names to their handler functions.
         * The prototype for a token function is func($pageid, $title)
         * 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
@@ -80,6 +93,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        'unblock' => array( 'ApiQueryInfo', 'getUnblockToken' ),
                        'email' => array( 'ApiQueryInfo', 'getEmailToken' ),
                        'import' => array( 'ApiQueryInfo', 'getImportToken' ),
+                       'watch' => array( 'ApiQueryInfo', 'getWatchToken'),
                );
                wfRunHooks( 'APIQueryInfoTokens', array( &$this->tokenFunctions ) );
                return $this->tokenFunctions;
@@ -100,7 +114,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedEditToken;
                }
 
-               $cachedEditToken = $wgUser->editToken();
+               $cachedEditToken = $wgUser->getEditToken();
                return $cachedEditToken;
        }
 
@@ -115,7 +129,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedDeleteToken;
                }
 
-               $cachedDeleteToken = $wgUser->editToken();
+               $cachedDeleteToken = $wgUser->getEditToken();
                return $cachedDeleteToken;
        }
 
@@ -130,7 +144,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedProtectToken;
                }
 
-               $cachedProtectToken = $wgUser->editToken();
+               $cachedProtectToken = $wgUser->getEditToken();
                return $cachedProtectToken;
        }
 
@@ -145,7 +159,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedMoveToken;
                }
 
-               $cachedMoveToken = $wgUser->editToken();
+               $cachedMoveToken = $wgUser->getEditToken();
                return $cachedMoveToken;
        }
 
@@ -160,7 +174,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedBlockToken;
                }
 
-               $cachedBlockToken = $wgUser->editToken();
+               $cachedBlockToken = $wgUser->getEditToken();
                return $cachedBlockToken;
        }
 
@@ -180,13 +194,13 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedEmailToken;
                }
 
-               $cachedEmailToken = $wgUser->editToken();
+               $cachedEmailToken = $wgUser->getEditToken();
                return $cachedEmailToken;
        }
 
        public static function getImportToken( $pageid, $title ) {
                global $wgUser;
-               if ( !$wgUser->isAllowed( 'import' ) ) {
+               if ( !$wgUser->isAllowedAny( 'import', 'importupload' ) ) {
                        return false;
                }
 
@@ -195,10 +209,40 @@ class ApiQueryInfo extends ApiQueryBase {
                        return $cachedImportToken;
                }
 
-               $cachedImportToken = $wgUser->editToken();
+               $cachedImportToken = $wgUser->getEditToken();
                return $cachedImportToken;
        }
 
+       public static function getWatchToken( $pageid, $title ) {
+               global $wgUser;
+               if ( !$wgUser->isLoggedIn() ) {
+                       return false;
+               }
+
+               static $cachedWatchToken = null;
+               if ( !is_null( $cachedWatchToken ) ) {
+                       return $cachedWatchToken;
+               }
+
+               $cachedWatchToken = $wgUser->getEditToken( 'watch' );
+               return $cachedWatchToken;
+       }
+
+       public static function getOptionsToken( $pageid, $title ) {
+               global $wgUser;
+               if ( !$wgUser->isLoggedIn() ) {
+                       return false;
+               }
+
+               static $cachedOptionsToken = null;
+               if ( !is_null( $cachedOptionsToken ) ) {
+                       return $cachedOptionsToken;
+               }
+
+               $cachedOptionsToken = $wgUser->getEditToken();
+               return $cachedOptionsToken;
+       }
+
        public function execute() {
                $this->params = $this->extractRequestParams();
                if ( !is_null( $this->params['prop'] ) ) {
@@ -242,19 +286,22 @@ class ApiQueryInfo extends ApiQueryBase {
                $this->pageRestrictions = $pageSet->getCustomField( 'page_restrictions' );
                $this->pageIsRedir = $pageSet->getCustomField( 'page_is_redirect' );
                $this->pageIsNew = $pageSet->getCustomField( 'page_is_new' );
-               $this->pageCounter = $pageSet->getCustomField( 'page_counter' );
+
+               global $wgDisableCounters;
+
+               if ( !$wgDisableCounters ) {
+                       $this->pageCounter = $pageSet->getCustomField( 'page_counter' );
+               }
                $this->pageTouched = $pageSet->getCustomField( 'page_touched' );
                $this->pageLatest = $pageSet->getCustomField( 'page_latest' );
                $this->pageLength = $pageSet->getCustomField( 'page_len' );
 
-               $db = $this->getDB();
                // Get protection info if requested
                if ( $this->fld_protection ) {
                        $this->getProtectionInfo();
                }
 
                if ( $this->fld_watched ) {
-                       $this->getMain()->setVaryCookie();
                        $this->getWatchedInfo();
                }
 
@@ -262,7 +309,7 @@ class ApiQueryInfo extends ApiQueryBase {
                if ( $this->fld_talkid || $this->fld_subjectid ) {
                        $this->getTSIDs();
                }
-               
+
                if ( $this->fld_displaytitle ) {
                        $this->getDisplayTitle();
                }
@@ -290,10 +337,17 @@ class ApiQueryInfo extends ApiQueryBase {
         */
        private function extractPageInfo( $pageid, $title ) {
                $pageInfo = array();
-               if ( $title->exists() ) {
+               $titleExists = $pageid > 0; //$title->exists() needs pageid, which is not set for all title objects
+               $ns = $title->getNamespace();
+               $dbkey = $title->getDBkey();
+               if ( $titleExists ) {
+                       global $wgDisableCounters;
+
                        $pageInfo['touched'] = wfTimestamp( TS_ISO_8601, $this->pageTouched[$pageid] );
                        $pageInfo['lastrevid'] = intval( $this->pageLatest[$pageid] );
-                       $pageInfo['counter'] = intval( $this->pageCounter[$pageid] );
+                       $pageInfo['counter'] = $wgDisableCounters
+                               ? ""
+                               : intval( $this->pageCounter[$pageid] );
                        $pageInfo['length'] = intval( $this->pageLength[$pageid] );
 
                        if ( $this->pageIsRedir[$pageid] ) {
@@ -305,9 +359,6 @@ class ApiQueryInfo extends ApiQueryBase {
                }
 
                if ( !is_null( $this->params['token'] ) ) {
-                       // Don't cache tokens
-                       $this->getMain()->setCachePrivate();
-                       
                        $tokenFunctions = $this->getTokenFunctions();
                        $pageInfo['starttimestamp'] = wfTimestamp( TS_ISO_8601, time() );
                        foreach ( $this->params['token'] as $t ) {
@@ -322,35 +373,35 @@ class ApiQueryInfo extends ApiQueryBase {
 
                if ( $this->fld_protection ) {
                        $pageInfo['protection'] = array();
-                       if ( isset( $this->protections[$title->getNamespace()][$title->getDBkey()] ) ) {
+                       if ( isset( $this->protections[$ns][$dbkey] ) ) {
                                $pageInfo['protection'] =
-                                       $this->protections[$title->getNamespace()][$title->getDBkey()];
+                                       $this->protections[$ns][$dbkey];
                        }
                        $this->getResult()->setIndexedTagName( $pageInfo['protection'], 'pr' );
                }
 
-               if ( $this->fld_watched && isset( $this->watched[$title->getNamespace()][$title->getDBkey()] ) ) {
+               if ( $this->fld_watched && isset( $this->watched[$ns][$dbkey] ) ) {
                        $pageInfo['watched'] = '';
                }
 
-               if ( $this->fld_talkid && isset( $this->talkids[$title->getNamespace()][$title->getDBkey()] ) ) {
-                       $pageInfo['talkid'] = $this->talkids[$title->getNamespace()][$title->getDBkey()];
+               if ( $this->fld_talkid && isset( $this->talkids[$ns][$dbkey] ) )        {
+                       $pageInfo['talkid'] = $this->talkids[$ns][$dbkey];
                }
 
-               if ( $this->fld_subjectid && isset( $this->subjectids[$title->getNamespace()][$title->getDBkey()] ) ) {
-                       $pageInfo['subjectid'] = $this->subjectids[$title->getNamespace()][$title->getDBkey()];
+               if ( $this->fld_subjectid && isset( $this->subjectids[$ns][$dbkey] ) ) {
+                       $pageInfo['subjectid'] = $this->subjectids[$ns][$dbkey];
                }
 
                if ( $this->fld_url ) {
-                       $pageInfo['fullurl'] = $title->getFullURL();
-                       $pageInfo['editurl'] = $title->getFullURL( 'action=edit' );
+                       $pageInfo['fullurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
+                       $pageInfo['editurl'] = wfExpandUrl( $title->getFullURL( 'action=edit' ), PROTO_CURRENT );
                }
-               if ( $this->fld_readable && $title->userCanRead() ) {
+               if ( $this->fld_readable && $title->userCan( 'read' ) ) {
                        $pageInfo['readable'] = '';
                }
 
                if ( $this->fld_preload ) {
-                       if ( $title->exists() ) {
+                       if ( $titleExists ) {
                                $pageInfo['preload'] = '';
                        } else {
                                $text = null;
@@ -359,10 +410,10 @@ class ApiQueryInfo extends ApiQueryBase {
                                $pageInfo['preload'] = $text;
                        }
                }
-               
+
                if ( $this->fld_displaytitle ) {
-                       if ( isset( $this->displaytitles[$title->getArticleId()] ) ) {
-                               $pageInfo['displaytitle'] = $this->displaytitles[$title->getArticleId()];
+                       if ( isset( $this->displaytitles[$pageid] ) ) {
+                               $pageInfo['displaytitle'] = $this->displaytitles[$pageid];
                        } else {
                                $pageInfo['displaytitle'] = $title->getPrefixedText();
                        }
@@ -375,6 +426,7 @@ class ApiQueryInfo extends ApiQueryBase {
         * Get information about protections and put it in $protections
         */
        private function getProtectionInfo() {
+               global $wgContLang;
                $this->protections = array();
                $db = $this->getDB();
 
@@ -393,7 +445,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                $a = array(
                                        'type' => $row->pr_type,
                                        'level' => $row->pr_level,
-                                       'expiry' => Block::decodeExpiry( $row->pr_expiry, TS_ISO_8601 )
+                                       'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 )
                                );
                                if ( $row->pr_cascade ) {
                                        $a['cascade'] = '';
@@ -450,7 +502,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                $this->protections[$row->pt_namespace][$row->pt_title][] = array(
                                        'type' => 'create',
                                        'level' => $row->pt_create_perm,
-                                       'expiry' => Block::decodeExpiry( $row->pt_expiry, TS_ISO_8601 )
+                                       'expiry' => $wgContLang->formatExpiry( $row->pt_expiry, TS_ISO_8601 )
                                );
                        }
                }
@@ -484,7 +536,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                $this->protections[$row->tl_namespace][$row->tl_title][] = array(
                                        'type' => $row->pr_type,
                                        'level' => $row->pr_level,
-                                       'expiry' => Block::decodeExpiry( $row->pr_expiry, TS_ISO_8601 ),
+                                       'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ),
                                        'source' => $source->getPrefixedText()
                                );
                        }
@@ -507,7 +559,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                $this->protections[NS_FILE][$row->il_to][] = array(
                                        'type' => $row->pr_type,
                                        'level' => $row->pr_level,
-                                       'expiry' => Block::decodeExpiry( $row->pr_expiry, TS_ISO_8601 ),
+                                       'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ),
                                        'source' => $source->getPrefixedText()
                                );
                        }
@@ -533,7 +585,7 @@ class ApiQueryInfo extends ApiQueryBase {
                if ( !count( $getTitles ) ) {
                        return;
                }
-               
+
                $db = $this->getDB();
 
                // Construct a custom WHERE clause that matches
@@ -554,17 +606,15 @@ class ApiQueryInfo extends ApiQueryBase {
                        }
                }
        }
-       
+
        private function getDisplayTitle() {
                $this->displaytitles = array();
-               
+
                $pageIds = array_keys( $this->titles );
-       
+
                if ( !count( $pageIds ) ) {
                        return;
                }
-               
-               $db = $this->getDB();
 
                $this->resetQueryParams();
                $this->addTables( 'page_props' );
@@ -572,7 +622,7 @@ class ApiQueryInfo extends ApiQueryBase {
                $this->addWhereFld( 'pp_page', $pageIds );
                $this->addWhereFld( 'pp_propname', 'displaytitle' );
                $res = $this->select( __METHOD__ );
-               
+
                foreach ( $res as $row ) {
                        $this->displaytitles[$row->pp_page] = $row->pp_value;
                }
@@ -582,34 +632,54 @@ class ApiQueryInfo extends ApiQueryBase {
         * Get information about watched status and put it in $this->watched
         */
        private function getWatchedInfo() {
-               global $wgUser;
+               $user = $this->getUser();
 
-               if ( $wgUser->isAnon() || count( $this->titles ) == 0 ) {
+               if ( $user->isAnon() || count( $this->everything ) == 0 ) {
                        return;
                }
 
                $this->watched = array();
                $db = $this->getDB();
 
-               $lb = new LinkBatch( $this->titles );
+               $lb = new LinkBatch( $this->everything );
 
                $this->resetQueryParams();
-               $this->addTables( array( 'page', 'watchlist' ) );
-               $this->addFields( array( 'page_title', 'page_namespace' ) );
+               $this->addTables( array( 'watchlist' ) );
+               $this->addFields( array( 'wl_title', 'wl_namespace' ) );
                $this->addWhere( array(
-                       $lb->constructSet( 'page', $db ),
-                       'wl_namespace=page_namespace',
-                       'wl_title=page_title',
-                       'wl_user' => $wgUser->getID()
+                       $lb->constructSet( 'wl', $db ),
+                       'wl_user' => $user->getID()
                ) );
 
                $res = $this->select( __METHOD__ );
 
                foreach ( $res as $row ) {
-                       $this->watched[$row->page_namespace][$row->page_title] = true;
+                       $this->watched[$row->wl_namespace][$row->wl_title] = true;
                }
        }
 
+       public function getCacheMode( $params ) {
+               $publicProps = array(
+                       'protection',
+                       'talkid',
+                       'subjectid',
+                       'url',
+                       'preload',
+                       'displaytitle',
+               );
+               if ( !is_null( $params['prop'] ) ) {
+                       foreach ( $params['prop'] as $prop ) {
+                               if ( !in_array( $prop, $publicProps ) ) {
+                                       return 'private';
+                               }
+                       }
+               }
+               if ( !is_null( $params['token'] ) ) {
+                       return 'private';
+               }
+               return 'public';
+       }
+
        public function getAllowedParams() {
                return array(
                        'prop' => array(
@@ -618,12 +688,14 @@ class ApiQueryInfo extends ApiQueryBase {
                                ApiBase::PARAM_TYPE => array(
                                        'protection',
                                        'talkid',
-                                       'watched',
+                                       'watched', # private
                                        'subjectid',
                                        'url',
-                                       'readable',
+                                       'readable', # private
                                        'preload',
                                        'displaytitle',
+                                       // If you add more properties here, please consider whether they
+                                       // need to be added to getCacheMode()
                                ) ),
                        'token' => array(
                                ApiBase::PARAM_DFLT => null,
@@ -652,6 +724,59 @@ class ApiQueryInfo extends ApiQueryBase {
                );
        }
 
+       public function getResultProperties() {
+               $props = array(
+                       ApiBase::PROP_LIST => false,
+                       '' => array(
+                               'touched' => 'timestamp',
+                               'lastrevid' => 'integer',
+                               'counter' => array(
+                                       ApiBase::PROP_TYPE => 'integer',
+                                       ApiBase::PROP_NULLABLE => true
+                               ),
+                               'length' => 'integer',
+                               'redirect' => 'boolean',
+                               'new' => 'boolean',
+                               'starttimestamp' => array(
+                                       ApiBase::PROP_TYPE => 'timestamp',
+                                       ApiBase::PROP_NULLABLE => true
+                               )
+                       ),
+                       'watched' => array(
+                               'watched' => 'boolean'
+                       ),
+                       'talkid' => array(
+                               'talkid' => array(
+                                       ApiBase::PROP_TYPE => 'integer',
+                                       ApiBase::PROP_NULLABLE => true
+                               )
+                       ),
+                       'subjectid' => array(
+                               'subjectid' => array(
+                                       ApiBase::PROP_TYPE => 'integer',
+                                       ApiBase::PROP_NULLABLE => true
+                               )
+                       ),
+                       'url' => array(
+                               'fullurl' => 'string',
+                               'editurl' => 'string'
+                       ),
+                       'readable' => array(
+                               'readable' => 'boolean'
+                       ),
+                       'preload' => array(
+                               'preload' => 'string'
+                       ),
+                       'displaytitle' => array(
+                               'displaytitle' => 'string'
+                       )
+               );
+
+               self::addTokenProperties( $props, $this->getTokenFunctions() );
+
+               return $props;
+       }
+
        public function getDescription() {
                return 'Get basic page information such as namespace, title, last touched date, ...';
        }
@@ -662,13 +787,17 @@ class ApiQueryInfo extends ApiQueryBase {
                ) );
        }
 
-       protected function getExamples() {
+       public function getExamples() {
                return array(
                        'api.php?action=query&prop=info&titles=Main%20Page',
                        'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page'
                );
        }
 
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/API:Properties#info_.2F_in';
+       }
+
        public function getVersion() {
                return __CLASS__ . ': $Id$';
        }