Revert changes to SpecialSearch.php in r70608 because Special:Search didn't load...
[lhc/web/wiklou.git] / includes / api / ApiQuery.php
index ec0c04d..cb7080d 100644 (file)
@@ -19,7 +19,7 @@
  *
  * You should have received a copy of the GNU General Public License along
  * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  * http://www.gnu.org/copyleft/gpl.html
  */
 
@@ -43,12 +43,13 @@ class ApiQuery extends ApiBase {
 
        private $mPropModuleNames, $mListModuleNames, $mMetaModuleNames;
        private $mPageSet;
-       private $params, $redirect;
+       private $params;
 
        private $mQueryPropModules = array(
                'info' => 'ApiQueryInfo',
                'revisions' => 'ApiQueryRevisions',
                'links' => 'ApiQueryLinks',
+               'iwlinks' => 'ApiQueryIWLinks',
                'langlinks' => 'ApiQueryLangLinks',
                'images' => 'ApiQueryImages',
                'imageinfo' => 'ApiQueryImageInfo',
@@ -72,6 +73,7 @@ class ApiQuery extends ApiBase {
                'embeddedin' => 'ApiQueryBacklinks',
                'filearchive' => 'ApiQueryFilearchive',
                'imageusage' => 'ApiQueryBacklinks',
+               'iwbacklinks' => 'ApiQueryIWBacklinks',
                'logevents' => 'ApiQueryLogEvents',
                'recentchanges' => 'ApiQueryRecentChanges',
                'search' => 'ApiQuerySearch',
@@ -172,7 +174,7 @@ class ApiQuery extends ApiBase {
        function getModules() {
                return array_merge( $this->mQueryPropModules, $this->mQueryListModules, $this->mQueryMetaModules );
        }
-       
+
        /**
         * Get whether the specified module is a prop, list or a meta query module
         * @param $moduleName string Name of the module to find type for
@@ -182,15 +184,15 @@ class ApiQuery extends ApiBase {
                if ( array_key_exists ( $moduleName, $this->mQueryPropModules ) ) {
                        return 'prop';
                }
-               
+
                if ( array_key_exists ( $moduleName, $this->mQueryListModules ) ) {
                        return 'list';
                }
-               
+
                if ( array_key_exists ( $moduleName, $this->mQueryMetaModules ) ) {
                        return 'meta';
                }
-               
+
                return null;
        }
 
@@ -219,19 +221,26 @@ class ApiQuery extends ApiBase {
        public function execute() {
                $this->params = $this->extractRequestParams();
                $this->redirects = $this->params['redirects'];
+               $this->convertTitles = $this->params['converttitles'];
 
                // Create PageSet
-               $this->mPageSet = new ApiPageSet( $this, $this->redirects );
+               $this->mPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
 
                // Instantiate requested modules
                $modules = array();
-               $this->InstantiateModules( $modules, 'prop', $this->mQueryPropModules );
-               $this->InstantiateModules( $modules, 'list', $this->mQueryListModules );
-               $this->InstantiateModules( $modules, 'meta', $this->mQueryMetaModules );
+               $this->instantiateModules( $modules, 'prop', $this->mQueryPropModules );
+               $this->instantiateModules( $modules, 'list', $this->mQueryListModules );
+               $this->instantiateModules( $modules, 'meta', $this->mQueryMetaModules );
+
+               $cacheMode = 'public';
 
                // If given, execute generator to substitute user supplied data with generated data.
                if ( isset( $this->params['generator'] ) ) {
-                       $this->executeGeneratorModule( $this->params['generator'], $modules );
+                       $generator = $this->newGenerator( $this->params['generator'] );
+                       $params = $generator->extractRequestParams();
+                       $cacheMode = $this->mergeCacheMode( $cacheMode,
+                               $generator->getCacheMode( $params ) );
+                       $this->executeGeneratorModule( $generator, $modules );
                } else {
                        // Append custom fields and populate page/revision information
                        $this->addCustomFldsToPageSet( $modules, $this->mPageSet );
@@ -243,11 +252,35 @@ class ApiQuery extends ApiBase {
 
                // Execute all requested modules.
                foreach ( $modules as $module ) {
+                       $params = $module->extractRequestParams();
+                       $cacheMode = $this->mergeCacheMode(
+                               $cacheMode, $module->getCacheMode( $params ) );
                        $module->profileIn();
                        $module->execute();
                        wfRunHooks( 'APIQueryAfterExecute', array( &$module ) );
                        $module->profileOut();
                }
+
+               // Set the cache mode
+               $this->getMain()->setCacheMode( $cacheMode );
+       }
+
+       /**
+        * Update a cache mode string, applying the cache mode of a new module to it.
+        * The cache mode may increase in the level of privacy, but public modules
+        * added to private data do not decrease the level of privacy.
+        */
+       protected function mergeCacheMode( $cacheMode, $modCacheMode ) {
+               if ( $modCacheMode === 'anon-public-user-private' ) {
+                       if ( $cacheMode !== 'private' ) {
+                               $cacheMode = 'anon-public-user-private';
+                       }
+               } elseif ( $modCacheMode === 'public' ) {
+                       // do nothing, if it's public already it will stay public
+               } else { // private
+                       $cacheMode = 'private';
+               }
+               return $cacheMode;
        }
 
        /**
@@ -270,7 +303,7 @@ class ApiQuery extends ApiBase {
         * @param $param string Parameter name to read modules from
         * @param $moduleList array(modulename => classname)
         */
-       private function InstantiateModules( &$modules, $param, $moduleList ) {
+       private function instantiateModules( &$modules, $param, $moduleList ) {
                $list = @$this->params[$param];
                if ( !is_null ( $list ) ) {
                        foreach ( $list as $moduleName ) {
@@ -306,6 +339,20 @@ class ApiQuery extends ApiBase {
                        $result->addValue( 'query', 'normalized', $normValues );
                }
 
+               // Title conversions
+               $convValues = array();
+               foreach ( $pageSet->getConvertedTitles() as $rawTitleStr => $titleStr ) {
+                       $convValues[] = array(
+                               'from' => $rawTitleStr,
+                               'to' => $titleStr
+                       );
+               }
+
+               if ( count( $convValues ) ) {
+                       $result->setIndexedTagName( $convValues, 'c' );
+                       $result->addValue( 'query', 'converted', $convValues );
+               }
+
                // Interwiki titles
                $intrwValues = array();
                foreach ( $pageSet->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
@@ -372,6 +419,20 @@ class ApiQuery extends ApiBase {
                                'missing' => ''
                        );
                }
+               // Report special pages
+               foreach ( $pageSet->getSpecialTitles() as $fakeId => $title ) {
+                       $vals = array();
+                       ApiQueryBase::addTitleInfo( $vals, $title );
+                       $vals['special'] = '';
+                       if ( $title->getNamespace() == NS_SPECIAL &&
+                                       !SpecialPage::exists( $title->getText() ) ) {
+                               $vals['missing'] = '';
+                       } elseif ( $title->getNamespace() == NS_MEDIA &&
+                                       !wfFindFile( $title ) ) {
+                               $vals['missing'] = '';
+                       }
+                       $pages[$fakeId] = $vals;
+               }
 
                // Output general page information for found titles
                foreach ( $pageSet->getGoodTitles() as $pageid => $title ) {
@@ -427,12 +488,10 @@ class ApiQuery extends ApiBase {
        }
 
        /**
-        * For generator mode, execute generator, and use its output as new
-        * ApiPageSet
+        * Create a generator object of the given type and return it
         * @param $generatorName string Module name
-        * @param $modules array of module objects
         */
-       protected function executeGeneratorModule( $generatorName, $modules ) {
+       public function newGenerator( $generatorName ) {
                // Find class that implements requested generator
                if ( isset( $this->mQueryListModules[$generatorName] ) ) {
                        $className = $this->mQueryListModules[$generatorName];
@@ -441,17 +500,23 @@ class ApiQuery extends ApiBase {
                } else {
                        ApiBase::dieDebug( __METHOD__, "Unknown generator=$generatorName" );
                }
-
-               // Generator results
-               $resultPageSet = new ApiPageSet( $this, $this->redirects );
-
-               // Create and execute the generator
                $generator = new $className ( $this, $generatorName );
                if ( !$generator instanceof ApiQueryGeneratorBase ) {
                        $this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' );
                }
-
                $generator->setGeneratorMode();
+               return $generator;
+       }
+
+       /**
+        * For generator mode, execute generator, and use its output as new
+        * ApiPageSet
+        * @param $generatorName string Module name
+        * @param $modules array of module objects
+        */
+       protected function executeGeneratorModule( $generator, $modules ) {
+               // Generator results
+               $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
 
                // Add any additional fields modules may need
                $generator->requestExtraData( $this->mPageSet );
@@ -489,6 +554,7 @@ class ApiQuery extends ApiBase {
                                ApiBase::PARAM_TYPE => $this->mAllowedGenerators
                        ),
                        'redirects' => false,
+                       'converttitles' => false,
                        'indexpageids' => false,
                        'export' => false,
                        'exportnowrap' => false,
@@ -567,12 +633,13 @@ class ApiQuery extends ApiBase {
 
        public function getParamDescription() {
                return array(
-                       'prop' => 'Which properties to get for the titles/revisions/pageids',
-                       'list' => 'Which lists to get',
-                       'meta' => 'Which meta data to get about the site',
+                       'prop' => 'Which properties to get for the titles/revisions/pageids. Module help is available below',
+                       'list' => 'Which lists to get. Module help is available below',
+                       'meta' => 'Which metadata to get about the site. Module help is available below',
                        'generator' => array( 'Use the output of a list as the input for other prop/list/meta items',
-                                       'NOTE: generator parameter names must be prefixed with a \'g\', see examples.' ),
+                                       'NOTE: generator parameter names must be prefixed with a \'g\', see examples' ),
                        'redirects' => 'Automatically resolve redirects',
+                       'converttitles' => "Convert titles to other variants if necessary. Only works if the wiki's content language supports variant conversion.",
                        'indexpageids' => 'Include an additional pageids section listing all returned page IDs',
                        'export' => 'Export the current revisions of all given or generated pages',
                        'exportnowrap' => 'Return the export XML without wrapping it in an XML result (same format as Special:Export). Can only be used with export',