MediaWiki  REL1_20
ApiQuery.php
Go to the documentation of this file.
00001 <?php
00038 class ApiQuery extends ApiBase {
00039 
00040         private $mPropModuleNames, $mListModuleNames, $mMetaModuleNames;
00041 
00045         private $mPageSet;
00046 
00047         private $params, $redirects, $convertTitles, $iwUrl;
00048 
00049         private $mQueryPropModules = array(
00050                 'categories' => 'ApiQueryCategories',
00051                 'categoryinfo' => 'ApiQueryCategoryInfo',
00052                 'duplicatefiles' => 'ApiQueryDuplicateFiles',
00053                 'extlinks' => 'ApiQueryExternalLinks',
00054                 'images' => 'ApiQueryImages',
00055                 'imageinfo' => 'ApiQueryImageInfo',
00056                 'info' => 'ApiQueryInfo',
00057                 'links' => 'ApiQueryLinks',
00058                 'iwlinks' => 'ApiQueryIWLinks',
00059                 'langlinks' => 'ApiQueryLangLinks',
00060                 'pageprops' => 'ApiQueryPageProps',
00061                 'revisions' => 'ApiQueryRevisions',
00062                 'stashimageinfo' => 'ApiQueryStashImageInfo',
00063                 'templates' => 'ApiQueryLinks',
00064         );
00065 
00066         private $mQueryListModules = array(
00067                 'allcategories' => 'ApiQueryAllCategories',
00068                 'allimages' => 'ApiQueryAllImages',
00069                 'alllinks' => 'ApiQueryAllLinks',
00070                 'allpages' => 'ApiQueryAllPages',
00071                 'allusers' => 'ApiQueryAllUsers',
00072                 'backlinks' => 'ApiQueryBacklinks',
00073                 'blocks' => 'ApiQueryBlocks',
00074                 'categorymembers' => 'ApiQueryCategoryMembers',
00075                 'deletedrevs' => 'ApiQueryDeletedrevs',
00076                 'embeddedin' => 'ApiQueryBacklinks',
00077                 'exturlusage' => 'ApiQueryExtLinksUsage',
00078                 'filearchive' => 'ApiQueryFilearchive',
00079                 'imageusage' => 'ApiQueryBacklinks',
00080                 'iwbacklinks' => 'ApiQueryIWBacklinks',
00081                 'langbacklinks' => 'ApiQueryLangBacklinks',
00082                 'logevents' => 'ApiQueryLogEvents',
00083                 'protectedtitles' => 'ApiQueryProtectedTitles',
00084                 'querypage' => 'ApiQueryQueryPage',
00085                 'random' => 'ApiQueryRandom',
00086                 'recentchanges' => 'ApiQueryRecentChanges',
00087                 'search' => 'ApiQuerySearch',
00088                 'tags' => 'ApiQueryTags',
00089                 'usercontribs' => 'ApiQueryContributions',
00090                 'users' => 'ApiQueryUsers',
00091                 'watchlist' => 'ApiQueryWatchlist',
00092                 'watchlistraw' => 'ApiQueryWatchlistRaw',
00093         );
00094 
00095         private $mQueryMetaModules = array(
00096                 'allmessages' => 'ApiQueryAllMessages',
00097                 'siteinfo' => 'ApiQuerySiteinfo',
00098                 'userinfo' => 'ApiQueryUserInfo',
00099         );
00100 
00101         private $mSlaveDB = null;
00102         private $mNamedDB = array();
00103 
00104         protected $mAllowedGenerators = array();
00105 
00110         public function __construct( $main, $action ) {
00111                 parent::__construct( $main, $action );
00112 
00113                 // Allow custom modules to be added in LocalSettings.php
00114                 global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules,
00115                         $wgMemc, $wgAPICacheHelpTimeout;
00116                 self::appendUserModules( $this->mQueryPropModules, $wgAPIPropModules );
00117                 self::appendUserModules( $this->mQueryListModules, $wgAPIListModules );
00118                 self::appendUserModules( $this->mQueryMetaModules, $wgAPIMetaModules );
00119 
00120                 $this->mPropModuleNames = array_keys( $this->mQueryPropModules );
00121                 $this->mListModuleNames = array_keys( $this->mQueryListModules );
00122                 $this->mMetaModuleNames = array_keys( $this->mQueryMetaModules );
00123 
00124                 // Get array of query generators from cache if present
00125                 $key = wfMemcKey( 'apiquerygenerators', SpecialVersion::getVersion( 'nodb' ) );
00126 
00127                 if ( $wgAPICacheHelpTimeout > 0 ) {
00128                         $cached = $wgMemc->get( $key );
00129                         if ( $cached ) {
00130                                 $this->mAllowedGenerators = $cached;
00131                                 return;
00132                         }
00133                 }
00134                 $this->makeGeneratorList( $this->mQueryPropModules );
00135                 $this->makeGeneratorList( $this->mQueryListModules );
00136 
00137                 if ( $wgAPICacheHelpTimeout > 0 ) {
00138                         $wgMemc->set( $key, $this->mAllowedGenerators, $wgAPICacheHelpTimeout );
00139                 }
00140         }
00141 
00147         private static function appendUserModules( &$modules, $newModules ) {
00148                 if ( is_array( $newModules ) ) {
00149                         foreach ( $newModules as $moduleName => $moduleClass ) {
00150                                 $modules[$moduleName] = $moduleClass;
00151                         }
00152                 }
00153         }
00154 
00159         public function getDB() {
00160                 if ( !isset( $this->mSlaveDB ) ) {
00161                         $this->profileDBIn();
00162                         $this->mSlaveDB = wfGetDB( DB_SLAVE, 'api' );
00163                         $this->profileDBOut();
00164                 }
00165                 return $this->mSlaveDB;
00166         }
00167 
00178         public function getNamedDB( $name, $db, $groups ) {
00179                 if ( !array_key_exists( $name, $this->mNamedDB ) ) {
00180                         $this->profileDBIn();
00181                         $this->mNamedDB[$name] = wfGetDB( $db, $groups );
00182                         $this->profileDBOut();
00183                 }
00184                 return $this->mNamedDB[$name];
00185         }
00186 
00191         public function getPageSet() {
00192                 return $this->mPageSet;
00193         }
00194 
00199         function getModules() {
00200                 return array_merge( $this->mQueryPropModules, $this->mQueryListModules, $this->mQueryMetaModules );
00201         }
00202 
00208         function getModuleType( $moduleName ) {
00209                 if ( isset( $this->mQueryPropModules[$moduleName] ) ) {
00210                         return 'prop';
00211                 }
00212 
00213                 if ( isset( $this->mQueryListModules[$moduleName] ) ) {
00214                         return 'list';
00215                 }
00216 
00217                 if ( isset( $this->mQueryMetaModules[$moduleName] ) ) {
00218                         return 'meta';
00219                 }
00220 
00221                 return null;
00222         }
00223 
00227         public function getCustomPrinter() {
00228                 // If &exportnowrap is set, use the raw formatter
00229                 if ( $this->getParameter( 'export' ) &&
00230                                 $this->getParameter( 'exportnowrap' ) )
00231                 {
00232                         return new ApiFormatRaw( $this->getMain(),
00233                                 $this->getMain()->createPrinterByName( 'xml' ) );
00234                 } else {
00235                         return null;
00236                 }
00237         }
00238 
00249         public function execute() {
00250                 $this->params = $this->extractRequestParams();
00251                 $this->redirects = $this->params['redirects'];
00252                 $this->convertTitles = $this->params['converttitles'];
00253                 $this->iwUrl = $this->params['iwurl'];
00254 
00255                 // Create PageSet
00256                 $this->mPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
00257 
00258                 // Instantiate requested modules
00259                 $modules = array();
00260                 $this->instantiateModules( $modules, 'prop', $this->mQueryPropModules );
00261                 $this->instantiateModules( $modules, 'list', $this->mQueryListModules );
00262                 $this->instantiateModules( $modules, 'meta', $this->mQueryMetaModules );
00263 
00264                 $cacheMode = 'public';
00265 
00266                 // If given, execute generator to substitute user supplied data with generated data.
00267                 if ( isset( $this->params['generator'] ) ) {
00268                         $generator = $this->newGenerator( $this->params['generator'] );
00269                         $params = $generator->extractRequestParams();
00270                         $cacheMode = $this->mergeCacheMode( $cacheMode,
00271                                 $generator->getCacheMode( $params ) );
00272                         $this->executeGeneratorModule( $generator, $modules );
00273                 } else {
00274                         // Append custom fields and populate page/revision information
00275                         $this->addCustomFldsToPageSet( $modules, $this->mPageSet );
00276                         $this->mPageSet->execute();
00277                 }
00278 
00279                 // Record page information (title, namespace, if exists, etc)
00280                 $this->outputGeneralPageInfo();
00281 
00282                 // Execute all requested modules.
00286                 foreach ( $modules as $module ) {
00287                         $params = $module->extractRequestParams();
00288                         $cacheMode = $this->mergeCacheMode(
00289                                 $cacheMode, $module->getCacheMode( $params ) );
00290                         $module->profileIn();
00291                         $module->execute();
00292                         wfRunHooks( 'APIQueryAfterExecute', array( &$module ) );
00293                         $module->profileOut();
00294                 }
00295 
00296                 // Set the cache mode
00297                 $this->getMain()->setCacheMode( $cacheMode );
00298         }
00299 
00309         protected function mergeCacheMode( $cacheMode, $modCacheMode ) {
00310                 if ( $modCacheMode === 'anon-public-user-private' ) {
00311                         if ( $cacheMode !== 'private' ) {
00312                                 $cacheMode = 'anon-public-user-private';
00313                         }
00314                 } elseif ( $modCacheMode === 'public' ) {
00315                         // do nothing, if it's public already it will stay public
00316                 } else { // private
00317                         $cacheMode = 'private';
00318                 }
00319                 return $cacheMode;
00320         }
00321 
00329         private function addCustomFldsToPageSet( $modules, $pageSet ) {
00330                 // Query all requested modules.
00334                 foreach ( $modules as $module ) {
00335                         $module->requestExtraData( $pageSet );
00336                 }
00337         }
00338 
00345         private function instantiateModules( &$modules, $param, $moduleList ) {
00346                 if ( isset( $this->params[$param] ) ) {
00347                         foreach ( $this->params[$param] as $moduleName ) {
00348                                 $modules[] = new $moduleList[$moduleName] ( $this, $moduleName );
00349                         }
00350                 }
00351         }
00352 
00358         private function outputGeneralPageInfo() {
00359                 $pageSet = $this->getPageSet();
00360                 $result = $this->getResult();
00361 
00362                 // We don't check for a full result set here because we can't be adding
00363                 // more than 380K. The maximum revision size is in the megabyte range,
00364                 // and the maximum result size must be even higher than that.
00365 
00366                 // Title normalizations
00367                 $normValues = array();
00368                 foreach ( $pageSet->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
00369                         $normValues[] = array(
00370                                 'from' => $rawTitleStr,
00371                                 'to' => $titleStr
00372                         );
00373                 }
00374 
00375                 if ( count( $normValues ) ) {
00376                         $result->setIndexedTagName( $normValues, 'n' );
00377                         $result->addValue( 'query', 'normalized', $normValues );
00378                 }
00379 
00380                 // Title conversions
00381                 $convValues = array();
00382                 foreach ( $pageSet->getConvertedTitles() as $rawTitleStr => $titleStr ) {
00383                         $convValues[] = array(
00384                                 'from' => $rawTitleStr,
00385                                 'to' => $titleStr
00386                         );
00387                 }
00388 
00389                 if ( count( $convValues ) ) {
00390                         $result->setIndexedTagName( $convValues, 'c' );
00391                         $result->addValue( 'query', 'converted', $convValues );
00392                 }
00393 
00394                 // Interwiki titles
00395                 $intrwValues = array();
00396                 foreach ( $pageSet->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
00397                         $item = array(
00398                                 'title' => $rawTitleStr,
00399                                 'iw' => $interwikiStr,
00400                         );
00401                         if ( $this->iwUrl ) {
00402                                 $title = Title::newFromText( $rawTitleStr );
00403                                 $item['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
00404                         }
00405                         $intrwValues[] = $item;
00406                 }
00407 
00408                 if ( count( $intrwValues ) ) {
00409                         $result->setIndexedTagName( $intrwValues, 'i' );
00410                         $result->addValue( 'query', 'interwiki', $intrwValues );
00411                 }
00412 
00413                 // Show redirect information
00414                 $redirValues = array();
00418                 foreach ( $pageSet->getRedirectTitles() as $titleStrFrom => $titleTo ) {
00419                         $r = array(
00420                                 'from' => strval( $titleStrFrom ),
00421                                 'to' => $titleTo->getPrefixedText(),
00422                         );
00423                         if ( $titleTo->getFragment() !== '' ) {
00424                                 $r['tofragment'] = $titleTo->getFragment();
00425                         }
00426                         $redirValues[] = $r;
00427                 }
00428 
00429                 if ( count( $redirValues ) ) {
00430                         $result->setIndexedTagName( $redirValues, 'r' );
00431                         $result->addValue( 'query', 'redirects', $redirValues );
00432                 }
00433 
00434                 // Missing revision elements
00435                 $missingRevIDs = $pageSet->getMissingRevisionIDs();
00436                 if ( count( $missingRevIDs ) ) {
00437                         $revids = array();
00438                         foreach ( $missingRevIDs as $revid ) {
00439                                 $revids[$revid] = array(
00440                                         'revid' => $revid
00441                                 );
00442                         }
00443                         $result->setIndexedTagName( $revids, 'rev' );
00444                         $result->addValue( 'query', 'badrevids', $revids );
00445                 }
00446 
00447                 // Page elements
00448                 $pages = array();
00449 
00450                 // Report any missing titles
00451                 foreach ( $pageSet->getMissingTitles() as $fakeId => $title ) {
00452                         $vals = array();
00453                         ApiQueryBase::addTitleInfo( $vals, $title );
00454                         $vals['missing'] = '';
00455                         $pages[$fakeId] = $vals;
00456                 }
00457                 // Report any invalid titles
00458                 foreach ( $pageSet->getInvalidTitles() as $fakeId => $title ) {
00459                         $pages[$fakeId] = array( 'title' => $title, 'invalid' => '' );
00460                 }
00461                 // Report any missing page ids
00462                 foreach ( $pageSet->getMissingPageIDs() as $pageid ) {
00463                         $pages[$pageid] = array(
00464                                 'pageid' => $pageid,
00465                                 'missing' => ''
00466                         );
00467                 }
00468                 // Report special pages
00469                 foreach ( $pageSet->getSpecialTitles() as $fakeId => $title ) {
00470                         $vals = array();
00471                         ApiQueryBase::addTitleInfo( $vals, $title );
00472                         $vals['special'] = '';
00473                         if ( $title->isSpecialPage() &&
00474                                         !SpecialPageFactory::exists( $title->getDbKey() ) ) {
00475                                 $vals['missing'] = '';
00476                         } elseif ( $title->getNamespace() == NS_MEDIA &&
00477                                         !wfFindFile( $title ) ) {
00478                                 $vals['missing'] = '';
00479                         }
00480                         $pages[$fakeId] = $vals;
00481                 }
00482 
00483                 // Output general page information for found titles
00484                 foreach ( $pageSet->getGoodTitles() as $pageid => $title ) {
00485                         $vals = array();
00486                         $vals['pageid'] = $pageid;
00487                         ApiQueryBase::addTitleInfo( $vals, $title );
00488                         $pages[$pageid] = $vals;
00489                 }
00490 
00491                 if ( count( $pages ) ) {
00492                         if ( $this->params['indexpageids'] ) {
00493                                 $pageIDs = array_keys( $pages );
00494                                 // json treats all map keys as strings - converting to match
00495                                 $pageIDs = array_map( 'strval', $pageIDs );
00496                                 $result->setIndexedTagName( $pageIDs, 'id' );
00497                                 $result->addValue( 'query', 'pageids', $pageIDs );
00498                         }
00499 
00500                         $result->setIndexedTagName( $pages, 'page' );
00501                         $result->addValue( 'query', 'pages', $pages );
00502                 }
00503                 if ( $this->params['export'] ) {
00504                         $this->doExport( $pageSet, $result );
00505                 }
00506         }
00507 
00512         private function doExport( $pageSet, $result )  {
00513                 $exportTitles = array();
00514                 $titles = $pageSet->getGoodTitles();
00515                 if ( count( $titles ) ) {
00516                         foreach ( $titles as $title ) {
00517                                 if ( $title->userCan( 'read' ) ) {
00518                                         $exportTitles[] = $title;
00519                                 }
00520                         }
00521                 }
00522 
00523                 $exporter = new WikiExporter( $this->getDB() );
00524                 // WikiExporter writes to stdout, so catch its
00525                 // output with an ob
00526                 ob_start();
00527                 $exporter->openStream();
00528                 foreach ( $exportTitles as $title ) {
00529                         $exporter->pageByTitle( $title );
00530                 }
00531                 $exporter->closeStream();
00532                 $exportxml = ob_get_contents();
00533                 ob_end_clean();
00534 
00535                 // Don't check the size of exported stuff
00536                 // It's not continuable, so it would cause more
00537                 // problems than it'd solve
00538                 $result->disableSizeCheck();
00539                 if ( $this->params['exportnowrap'] ) {
00540                         $result->reset();
00541                         // Raw formatter will handle this
00542                         $result->addValue( null, 'text', $exportxml );
00543                         $result->addValue( null, 'mime', 'text/xml' );
00544                 } else {
00545                         $r = array();
00546                         ApiResult::setContent( $r, $exportxml );
00547                         $result->addValue( 'query', 'export', $r );
00548                 }
00549                 $result->enableSizeCheck();
00550         }
00551 
00557         public function newGenerator( $generatorName ) {
00558                 // Find class that implements requested generator
00559                 if ( isset( $this->mQueryListModules[$generatorName] ) ) {
00560                         $className = $this->mQueryListModules[$generatorName];
00561                 } elseif ( isset( $this->mQueryPropModules[$generatorName] ) ) {
00562                         $className = $this->mQueryPropModules[$generatorName];
00563                 } else {
00564                         ApiBase::dieDebug( __METHOD__, "Unknown generator=$generatorName" );
00565                 }
00566                 $generator = new $className ( $this, $generatorName );
00567                 if ( !$generator instanceof ApiQueryGeneratorBase ) {
00568                         $this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' );
00569                 }
00570                 $generator->setGeneratorMode();
00571                 return $generator;
00572         }
00573 
00580         protected function executeGeneratorModule( $generator, $modules ) {
00581                 // Generator results
00582                 $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
00583 
00584                 // Add any additional fields modules may need
00585                 $generator->requestExtraData( $this->mPageSet );
00586                 $this->addCustomFldsToPageSet( $modules, $resultPageSet );
00587 
00588                 // Populate page information with the original user input
00589                 $this->mPageSet->execute();
00590 
00591                 // populate resultPageSet with the generator output
00592                 $generator->profileIn();
00593                 $generator->executeGenerator( $resultPageSet );
00594                 wfRunHooks( 'APIQueryGeneratorAfterExecute', array( &$generator, &$resultPageSet ) );
00595                 $resultPageSet->finishPageSetGeneration();
00596                 $generator->profileOut();
00597 
00598                 // Swap the resulting pageset back in
00599                 $this->mPageSet = $resultPageSet;
00600         }
00601 
00602         public function getAllowedParams() {
00603                 return array(
00604                         'prop' => array(
00605                                 ApiBase::PARAM_ISMULTI => true,
00606                                 ApiBase::PARAM_TYPE => $this->mPropModuleNames
00607                         ),
00608                         'list' => array(
00609                                 ApiBase::PARAM_ISMULTI => true,
00610                                 ApiBase::PARAM_TYPE => $this->mListModuleNames
00611                         ),
00612                         'meta' => array(
00613                                 ApiBase::PARAM_ISMULTI => true,
00614                                 ApiBase::PARAM_TYPE => $this->mMetaModuleNames
00615                         ),
00616                         'generator' => array(
00617                                 ApiBase::PARAM_TYPE => $this->mAllowedGenerators
00618                         ),
00619                         'redirects' => false,
00620                         'converttitles' => false,
00621                         'indexpageids' => false,
00622                         'export' => false,
00623                         'exportnowrap' => false,
00624                         'iwurl' => false,
00625                 );
00626         }
00627 
00632         public function makeHelpMsg() {
00633                 // Make sure the internal object is empty
00634                 // (just in case a sub-module decides to optimize during instantiation)
00635                 $this->mPageSet = null;
00636 
00637                 $querySeparator = str_repeat( '--- ', 12 );
00638                 $moduleSeparator = str_repeat( '*** ', 14 );
00639                 $msg = "\n$querySeparator Query: Prop  $querySeparator\n\n";
00640                 $msg .= $this->makeHelpMsgHelper( $this->mQueryPropModules, 'prop' );
00641                 $msg .= "\n$querySeparator Query: List  $querySeparator\n\n";
00642                 $msg .= $this->makeHelpMsgHelper( $this->mQueryListModules, 'list' );
00643                 $msg .= "\n$querySeparator Query: Meta  $querySeparator\n\n";
00644                 $msg .= $this->makeHelpMsgHelper( $this->mQueryMetaModules, 'meta' );
00645                 $msg .= "\n\n$moduleSeparator Modules: continuation  $moduleSeparator\n\n";
00646 
00647                 // Use parent to make default message for the query module
00648                 $msg = parent::makeHelpMsg() . $msg;
00649 
00650                 return $msg;
00651         }
00652 
00659         private function makeHelpMsgHelper( $moduleList, $paramName ) {
00660                 $moduleDescriptions = array();
00661 
00662                 foreach ( $moduleList as $moduleName => $moduleClass ) {
00666                         $module = new $moduleClass( $this, $moduleName, null );
00667 
00668                         $msg = ApiMain::makeHelpMsgHeader( $module, $paramName );
00669                         $msg2 = $module->makeHelpMsg();
00670                         if ( $msg2 !== false ) {
00671                                 $msg .= $msg2;
00672                         }
00673                         if ( $module instanceof ApiQueryGeneratorBase ) {
00674                                 $msg .= "Generator:\n  This module may be used as a generator\n";
00675                         }
00676                         $moduleDescriptions[] = $msg;
00677                 }
00678 
00679                 return implode( "\n", $moduleDescriptions );
00680         }
00681 
00687         private function makeGeneratorList( $moduleList ) {
00688                 foreach( $moduleList as  $moduleName => $moduleClass ) {
00689                         if ( is_subclass_of( $moduleClass, 'ApiQueryGeneratorBase'  ) ) {
00690                                 $this->mAllowedGenerators[] = $moduleName;
00691                         }
00692                 }
00693         }
00694 
00699         public function makeHelpMsgParameters() {
00700                 $psModule = new ApiPageSet( $this );
00701                 return $psModule->makeHelpMsgParameters() . parent::makeHelpMsgParameters();
00702         }
00703 
00704         public function shouldCheckMaxlag() {
00705                 return true;
00706         }
00707 
00708         public function getParamDescription() {
00709                 return array(
00710                         'prop' => 'Which properties to get for the titles/revisions/pageids. Module help is available below',
00711                         'list' => 'Which lists to get. Module help is available below',
00712                         'meta' => 'Which metadata to get about the site. Module help is available below',
00713                         'generator' => array( 'Use the output of a list as the input for other prop/list/meta items',
00714                                         'NOTE: generator parameter names must be prefixed with a \'g\', see examples' ),
00715                         'redirects' => 'Automatically resolve redirects',
00716                         'converttitles' => array( "Convert titles to other variants if necessary. Only works if the wiki's content language supports variant conversion.",
00717                                         'Languages that support variant conversion include ' . implode( ', ', LanguageConverter::$languagesWithVariants ) ),
00718                         'indexpageids' => 'Include an additional pageids section listing all returned page IDs',
00719                         'export' => 'Export the current revisions of all given or generated pages',
00720                         'exportnowrap' => 'Return the export XML without wrapping it in an XML result (same format as Special:Export). Can only be used with export',
00721                         'iwurl' => 'Whether to get the full URL if the title is an interwiki link',
00722                 );
00723         }
00724 
00725         public function getDescription() {
00726                 return array(
00727                         'Query API module allows applications to get needed pieces of data from the MediaWiki databases,',
00728                         'and is loosely based on the old query.php interface.',
00729                         'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites'
00730                 );
00731         }
00732 
00733         public function getPossibleErrors() {
00734                 return array_merge( parent::getPossibleErrors(), array(
00735                         array( 'code' => 'badgenerator', 'info' => 'Module $generatorName cannot be used as a generator' ),
00736                 ) );
00737         }
00738 
00739         public function getExamples() {
00740                 return array(
00741                         'api.php?action=query&prop=revisions&meta=siteinfo&titles=Main%20Page&rvprop=user|comment',
00742                         'api.php?action=query&generator=allpages&gapprefix=API/&prop=revisions',
00743                 );
00744         }
00745 
00746         public function getHelpUrls() {
00747                 return array(
00748                         'https://www.mediawiki.org/wiki/API:Meta',
00749                         'https://www.mediawiki.org/wiki/API:Properties',
00750                         'https://www.mediawiki.org/wiki/API:Lists',
00751                 );
00752         }
00753 
00754         public function getVersion() {
00755                 $psModule = new ApiPageSet( $this );
00756                 $vers = array();
00757                 $vers[] = __CLASS__ . ': $Id$';
00758                 $vers[] = $psModule->getVersion();
00759                 return $vers;
00760         }
00761 }