44 'categories' => ApiQueryCategories::class,
45 'categoryinfo' => ApiQueryCategoryInfo::class,
46 'contributors' => ApiQueryContributors::class,
47 'deletedrevisions' => ApiQueryDeletedRevisions::class,
48 'duplicatefiles' => ApiQueryDuplicateFiles::class,
49 'extlinks' => ApiQueryExternalLinks::class,
50 'fileusage' => ApiQueryBacklinksprop::class,
51 'images' => ApiQueryImages::class,
52 'imageinfo' => ApiQueryImageInfo::class,
53 'info' => ApiQueryInfo::class,
54 'links' => ApiQueryLinks::class,
55 'linkshere' => ApiQueryBacklinksprop::class,
56 'iwlinks' => ApiQueryIWLinks::class,
57 'langlinks' => ApiQueryLangLinks::class,
58 'pageprops' => ApiQueryPageProps::class,
59 'redirects' => ApiQueryBacklinksprop::class,
60 'revisions' => ApiQueryRevisions::class,
61 'stashimageinfo' => ApiQueryStashImageInfo::class,
62 'templates' => ApiQueryLinks::class,
63 'transcludedin' => ApiQueryBacklinksprop::class,
71 'allcategories' => ApiQueryAllCategories::class,
72 'alldeletedrevisions' => ApiQueryAllDeletedRevisions::class,
73 'allfileusages' => ApiQueryAllLinks::class,
74 'allimages' => ApiQueryAllImages::class,
75 'alllinks' => ApiQueryAllLinks::class,
76 'allpages' => ApiQueryAllPages::class,
77 'allredirects' => ApiQueryAllLinks::class,
78 'allrevisions' => ApiQueryAllRevisions::class,
79 'mystashedfiles' => ApiQueryMyStashedFiles::class,
80 'alltransclusions' => ApiQueryAllLinks::class,
81 'allusers' => ApiQueryAllUsers::class,
82 'backlinks' => ApiQueryBacklinks::class,
83 'blocks' => ApiQueryBlocks::class,
84 'categorymembers' => ApiQueryCategoryMembers::class,
85 'deletedrevs' => ApiQueryDeletedrevs::class,
86 'embeddedin' => ApiQueryBacklinks::class,
87 'exturlusage' => ApiQueryExtLinksUsage::class,
88 'filearchive' => ApiQueryFilearchive::class,
89 'imageusage' => ApiQueryBacklinks::class,
90 'iwbacklinks' => ApiQueryIWBacklinks::class,
91 'langbacklinks' => ApiQueryLangBacklinks::class,
92 'logevents' => ApiQueryLogEvents::class,
93 'pageswithprop' => ApiQueryPagesWithProp::class,
94 'pagepropnames' => ApiQueryPagePropNames::class,
95 'prefixsearch' => ApiQueryPrefixSearch::class,
96 'protectedtitles' => ApiQueryProtectedTitles::class,
97 'querypage' => ApiQueryQueryPage::class,
98 'random' => ApiQueryRandom::class,
99 'recentchanges' => ApiQueryRecentChanges::class,
100 'search' => ApiQuerySearch::class,
101 'tags' => ApiQueryTags::class,
102 'usercontribs' => ApiQueryUserContribs::class,
103 'users' => ApiQueryUsers::class,
104 'watchlist' => ApiQueryWatchlist::class,
105 'watchlistraw' => ApiQueryWatchlistRaw::class,
113 'allmessages' => ApiQueryAllMessages::class,
114 'authmanagerinfo' => ApiQueryAuthManagerInfo::class,
115 'siteinfo' => ApiQuerySiteinfo::class,
116 'userinfo' => ApiQueryUserInfo::class,
117 'filerepoinfo' => ApiQueryFileRepoInfo::class,
118 'tokens' => ApiQueryTokens::class,
119 'languageinfo' => ApiQueryLanguageinfo::class,
136 parent::__construct( $main, $action );
140 MediaWikiServices::getInstance()->getObjectFactory()
145 $this->mModuleMgr->addModules( self::$QueryPropModules,
'prop' );
146 $this->mModuleMgr->addModules( $config->get(
'APIPropModules' ),
'prop' );
147 $this->mModuleMgr->addModules( self::$QueryListModules,
'list' );
148 $this->mModuleMgr->addModules( $config->get(
'APIListModules' ),
'list' );
149 $this->mModuleMgr->addModules( self::$QueryMetaModules,
'meta' );
150 $this->mModuleMgr->addModules( $config->get(
'APIMetaModules' ),
'meta' );
152 Hooks::run(
'ApiQuery::moduleManager', [ $this->mModuleMgr ] );
177 if ( !array_key_exists( $name, $this->mNamedDB ) ) {
178 $this->mNamedDB[$name] =
wfGetDB( $db, $groups );
181 return $this->mNamedDB[$name];
201 $this->
getMain()->createPrinterByName(
'xml' ) );
223 $propModules = array_keys( $allModules );
231 $modules = $continuationManager->getRunModules();
232 '@phan-var ApiQueryBase[] $modules';
234 if ( !$continuationManager->isGeneratorDone() ) {
238 $module->requestExtraData( $this->mPageSet );
241 $this->mPageSet->execute();
245 $this->mPageSet->executeDryRun();
248 $cacheMode = $this->mPageSet->getCacheMode();
252 $params = $module->extractRequestParams();
254 $cacheMode, $module->getCacheMode( $params ) );
256 Hooks::run(
'APIQueryAfterExecute', [ &$module ] );
260 $this->
getMain()->setCacheMode( $cacheMode );
264 if ( $this->mParams[
'rawcontinue'] ) {
265 $data = $continuationManager->getRawNonContinuation();
267 $this->
getResult()->addValue(
null,
'query-noncontinue', $data,
268 ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
270 $data = $continuationManager->getRawContinuation();
272 $this->
getResult()->addValue(
null,
'query-continue', $data,
273 ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
276 $continuationManager->setContinuationIntoResult( $this->
getResult() );
290 if ( $modCacheMode ===
'anon-public-user-private' ) {
291 if ( $cacheMode !==
'private' ) {
292 $cacheMode =
'anon-public-user-private';
294 } elseif ( $modCacheMode ===
'public' ) {
297 $cacheMode =
'private';
309 $wasPosted = $this->
getRequest()->wasPosted();
310 if ( isset( $this->mParams[$param] ) ) {
311 foreach ( $this->mParams[$param] as $moduleName ) {
312 $instance = $this->mModuleMgr->getModule( $moduleName, $param );
313 if ( $instance ===
null ) {
316 if ( !$wasPosted && $instance->mustBePosted() ) {
320 if ( !array_key_exists( $moduleName,
$modules ) ) {
340 $values = $pageSet->getNormalizedTitlesAsResult( $result );
342 $fit = $fit && $result->addValue(
'query',
'normalized', $values );
344 $values = $pageSet->getConvertedTitlesAsResult( $result );
346 $fit = $fit && $result->addValue(
'query',
'converted', $values );
348 $values = $pageSet->getInterwikiTitlesAsResult( $result, $this->mParams[
'iwurl'] );
350 $fit = $fit && $result->addValue(
'query',
'interwiki', $values );
352 $values = $pageSet->getRedirectTitlesAsResult( $result );
354 $fit = $fit && $result->addValue(
'query',
'redirects', $values );
356 $values = $pageSet->getMissingRevisionIDsAsResult( $result );
358 $fit = $fit && $result->addValue(
'query',
'badrevids', $values );
365 foreach ( $pageSet->getMissingTitles() as $fakeId =>
$title ) {
367 ApiQueryBase::addTitleInfo( $vals,
$title );
368 $vals[
'missing'] =
true;
369 if (
$title->isKnown() ) {
370 $vals[
'known'] =
true;
372 $pages[$fakeId] = $vals;
375 foreach ( $pageSet->getInvalidTitlesAndReasons() as $fakeId => $data ) {
376 $pages[$fakeId] = $data + [
'invalid' =>
true ];
379 foreach ( $pageSet->getMissingPageIDs() as $pageid ) {
387 foreach ( $pageSet->getSpecialTitles() as $fakeId =>
$title ) {
389 ApiQueryBase::addTitleInfo( $vals,
$title );
390 $vals[
'special'] =
true;
391 if ( !
$title->isKnown() ) {
392 $vals[
'missing'] =
true;
394 $pages[$fakeId] = $vals;
398 foreach ( $pageSet->getGoodTitles() as $pageid =>
$title ) {
400 $vals[
'pageid'] = $pageid;
401 ApiQueryBase::addTitleInfo( $vals,
$title );
402 $pages[$pageid] = $vals;
405 if ( count( $pages ) ) {
406 $pageSet->populateGeneratorData( $pages );
407 ApiResult::setArrayType( $pages,
'BCarray' );
409 if ( $this->mParams[
'indexpageids'] ) {
410 $pageIDs = array_keys( ApiResult::stripMetadataNonRecursive( $pages ) );
412 $pageIDs = array_map(
'strval', $pageIDs );
413 ApiResult::setIndexedTagName( $pageIDs,
'id' );
414 $fit = $fit && $result->addValue(
'query',
'pageids', $pageIDs );
417 ApiResult::setIndexedTagName( $pages,
'page' );
418 $fit = $fit && $result->addValue(
'query',
'pages', $pages );
422 $this->
dieWithError(
'apierror-badconfig-resulttoosmall',
'badconfig' );
425 if ( $this->mParams[
'export'] ) {
426 $this->
doExport( $pageSet, $result );
436 $titles = $pageSet->getGoodTitles();
437 if ( count( $titles ) ) {
439 foreach ( $titles as
$title ) {
448 $exporter->setOutputSink( $sink );
449 $exporter->setSchemaVersion( $this->mParams[
'exportschema'] );
450 $exporter->openStream();
451 foreach ( $exportTitles as
$title ) {
452 $exporter->pageByTitle(
$title );
454 $exporter->closeStream();
459 if ( $this->mParams[
'exportnowrap'] ) {
462 $result->addValue(
null,
'text', $sink, ApiResult::NO_SIZE_CHECK );
463 $result->addValue(
null,
'mime',
'text/xml', ApiResult::NO_SIZE_CHECK );
464 $result->addValue(
null,
'filename',
'export.xml', ApiResult::NO_SIZE_CHECK );
466 $result->addValue(
'query',
'export', $sink, ApiResult::NO_SIZE_CHECK );
467 $result->addValue(
'query', ApiResult::META_BC_SUBELEMENTS, [
'export' ] );
485 'indexpageids' =>
false,
487 'exportnowrap' =>
false,
496 'rawcontinue' =>
false,
499 $result += $this->
getPageSet()->getFinalParams( $flags );
512 $allowedParams = [
'rawcontinue' => 1,
'indexpageids' => 1 ];
516 $needed = $param ===
'meta';
517 if ( !isset( $allowedParams[$param] ) && $request->getCheck( $param ) !== $needed ) {
527 if ( $module->isReadMode() ) {
537 'action=query&prop=revisions&meta=siteinfo&' .
538 'titles=Main%20Page&rvprop=user|comment&continue='
539 =>
'apihelp-query-example-revisions',
540 'action=query&generator=allpages&gapprefix=API/&prop=revisions&continue='
541 =>
'apihelp-query-example-allpages',
547 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Query',
548 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Meta',
549 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Properties',
550 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Lists',
This is the main API class, used for both external and internal processing.
This class contains a list of pages that the client has requested.