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