45 'categories' =>
'ApiQueryCategories',
46 'categoryinfo' =>
'ApiQueryCategoryInfo',
47 'contributors' =>
'ApiQueryContributors',
48 'duplicatefiles' =>
'ApiQueryDuplicateFiles',
49 'extlinks' =>
'ApiQueryExternalLinks',
50 'images' =>
'ApiQueryImages',
51 'imageinfo' =>
'ApiQueryImageInfo',
52 'info' =>
'ApiQueryInfo',
53 'links' =>
'ApiQueryLinks',
54 'iwlinks' =>
'ApiQueryIWLinks',
55 'langlinks' =>
'ApiQueryLangLinks',
56 'pageprops' =>
'ApiQueryPageProps',
57 'redirects' =>
'ApiQueryRedirects',
58 'revisions' =>
'ApiQueryRevisions',
59 'stashimageinfo' =>
'ApiQueryStashImageInfo',
60 'templates' =>
'ApiQueryLinks',
68 'allcategories' =>
'ApiQueryAllCategories',
69 'allfileusages' =>
'ApiQueryAllLinks',
70 'allimages' =>
'ApiQueryAllImages',
71 'alllinks' =>
'ApiQueryAllLinks',
72 'allpages' =>
'ApiQueryAllPages',
73 'allredirects' =>
'ApiQueryAllLinks',
74 'alltransclusions' =>
'ApiQueryAllLinks',
75 'allusers' =>
'ApiQueryAllUsers',
76 'backlinks' =>
'ApiQueryBacklinks',
77 'blocks' =>
'ApiQueryBlocks',
78 'categorymembers' =>
'ApiQueryCategoryMembers',
79 'deletedrevs' =>
'ApiQueryDeletedrevs',
80 'embeddedin' =>
'ApiQueryBacklinks',
81 'exturlusage' =>
'ApiQueryExtLinksUsage',
82 'filearchive' =>
'ApiQueryFilearchive',
83 'imageusage' =>
'ApiQueryBacklinks',
84 'iwbacklinks' =>
'ApiQueryIWBacklinks',
85 'langbacklinks' =>
'ApiQueryLangBacklinks',
86 'logevents' =>
'ApiQueryLogEvents',
87 'pageswithprop' =>
'ApiQueryPagesWithProp',
88 'pagepropnames' =>
'ApiQueryPagePropNames',
89 'prefixsearch' =>
'ApiQueryPrefixSearch',
90 'protectedtitles' =>
'ApiQueryProtectedTitles',
91 'querypage' =>
'ApiQueryQueryPage',
92 'random' =>
'ApiQueryRandom',
93 'recentchanges' =>
'ApiQueryRecentChanges',
94 'search' =>
'ApiQuerySearch',
95 'tags' =>
'ApiQueryTags',
96 'usercontribs' =>
'ApiQueryContributions',
97 'users' =>
'ApiQueryUsers',
98 'watchlist' =>
'ApiQueryWatchlist',
99 'watchlistraw' =>
'ApiQueryWatchlistRaw',
107 'allmessages' =>
'ApiQueryAllMessages',
108 'siteinfo' =>
'ApiQuerySiteinfo',
109 'userinfo' =>
'ApiQueryUserInfo',
110 'filerepoinfo' =>
'ApiQueryFileRepoInfo',
129 parent::__construct( $main, $action );
134 global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules;
135 $this->mModuleMgr->addModules( self::$QueryPropModules,
'prop' );
136 $this->mModuleMgr->addModules( $wgAPIPropModules,
'prop' );
137 $this->mModuleMgr->addModules( self::$QueryListModules,
'list' );
138 $this->mModuleMgr->addModules( $wgAPIListModules,
'list' );
139 $this->mModuleMgr->addModules( self::$QueryMetaModules,
'meta' );
140 $this->mModuleMgr->addModules( $wgAPIMetaModules,
'meta' );
165 if ( !array_key_exists(
$name, $this->mNamedDB ) ) {
171 return $this->mNamedDB[
$name];
201 foreach ( $this->mModuleMgr->getNamesWithClasses()
as $name => $class ) {
202 if ( is_subclass_of( $class,
'ApiQueryGeneratorBase' ) ) {
203 $gens[
$name] = $class;
229 $this->
getMain()->createPrinterByName(
'xml' ) );
251 $this->
initContinue( $pagesetParams, $completeModules );
254 $allModules =
array();
256 $propModules = $allModules;
261 $modules = $this->
initModules( $allModules, $completeModules, $pagesetParams !==
null );
264 if ( $completeModules ===
null || $pagesetParams !==
null ) {
266 $this->mPageSet->execute();
270 $this->mPageSet->executeDryRun();
273 $cacheMode = $this->mPageSet->getCacheMode();
277 foreach ( $modules
as $module ) {
278 $params = $module->extractRequestParams();
280 $cacheMode, $module->getCacheMode(
$params ) );
281 $module->profileIn();
284 $module->profileOut();
288 $this->
getMain()->setCacheMode( $cacheMode );
290 if ( $completeModules ===
null ) {
297 if ( isset( $qc[
'query-continue'] ) ) {
298 $qc = $qc[
'query-continue'];
299 $result->unsetValue(
null,
'query-continue' );
300 } elseif ( $this->mGeneratorContinue !==
null ) {
308 $completeModules = array_merge( $completeModules, array_diff_key( $modules, $qc ) );
309 if ( $pagesetParams !==
null ) {
311 $incompleteProps = array_intersect_key( $propModules, $qc );
312 if ( count( $incompleteProps ) > 0 ) {
315 $contValues =
array();
316 foreach ( $pagesetParams
as $param ) {
318 $contValues[$param] = $main->getVal( $param );
320 } elseif ( $this->mGeneratorContinue !==
null ) {
323 $pagesetParams = array_keys( $contValues );
324 $completeModules = array_diff_key( $completeModules, $propModules );
327 $pagesetParams =
null;
331 $continue =
'||' . implode(
'|', array_keys( $completeModules ) );
332 if ( $pagesetParams !==
null ) {
334 $continue = implode(
'|', $pagesetParams ) . $continue;
337 $contValues =
array();
338 $continue =
'-' . $continue;
340 $contValues[
'continue'] = $continue;
341 foreach ( $qc
as $qcModule ) {
342 foreach ( $qcModule
as $qcKey => $qcValue ) {
343 $contValues[$qcKey] = $qcValue;
346 $this->
getResult()->addValue(
null,
'continue', $contValues );
354 private function initContinue( &$pagesetParams, &$completeModules ) {
355 $pagesetParams =
array();
356 $continue = $this->mParams[
'continue'];
357 if ( $continue !==
null ) {
358 $this->mUseLegacyContinue =
false;
359 if ( $continue !==
'' ) {
362 $continue = explode(
'||', $continue );
364 if ( $continue[0] ===
'-' ) {
365 $pagesetParams =
null;
366 } elseif ( $continue[0] !==
'' ) {
368 $pagesetParams = explode(
'|', $continue[0] );
370 $continue = $continue[1];
372 if ( $continue !==
'' ) {
373 $completeModules = array_flip( explode(
'|', $continue ) );
375 $completeModules =
array();
378 $this->mUseLegacyContinue =
true;
379 $completeModules =
null;
390 private function initModules( $allModules, $completeModules, $usePageset ) {
391 $modules = $allModules;
392 $tmp = $completeModules;
393 $wasPosted = $this->
getRequest()->wasPosted();
396 foreach ( $allModules
as $moduleName => $module ) {
397 if ( !$wasPosted && $module->mustBePosted() ) {
400 if ( $completeModules !==
null && array_key_exists( $moduleName, $completeModules ) ) {
402 $module->extractRequestParams();
404 unset( $modules[$moduleName] );
405 unset( $tmp[$moduleName] );
406 } elseif ( $completeModules ===
null || $usePageset ) {
410 $module->requestExtraData( $this->mPageSet );
413 $this->
dieContinueUsageIf( $this->mModuleMgr->getModuleGroup( $moduleName ) ===
'prop' );
431 if ( $modCacheMode ===
'anon-public-user-private' ) {
432 if ( $cacheMode !==
'private' ) {
433 $cacheMode =
'anon-public-user-private';
435 } elseif ( $modCacheMode ===
'public' ) {
438 $cacheMode =
'private';
450 if ( isset( $this->mParams[$param] ) ) {
451 foreach ( $this->mParams[$param]
as $moduleName ) {
452 $instance = $this->mModuleMgr->getModule( $moduleName, $param );
453 if ( $instance ===
null ) {
457 if ( !array_key_exists( $moduleName, $modules ) ) {
458 $modules[$moduleName] = $instance;
477 $values = $pageSet->getNormalizedTitlesAsResult(
$result );
479 $result->addValue(
'query',
'normalized', $values );
481 $values = $pageSet->getConvertedTitlesAsResult(
$result );
483 $result->addValue(
'query',
'converted', $values );
485 $values = $pageSet->getInterwikiTitlesAsResult(
$result, $this->mParams[
'iwurl'] );
487 $result->addValue(
'query',
'interwiki', $values );
489 $values = $pageSet->getRedirectTitlesAsResult(
$result );
491 $result->addValue(
'query',
'redirects', $values );
493 $values = $pageSet->getMissingRevisionIDsAsResult(
$result );
495 $result->addValue(
'query',
'badrevids', $values );
502 foreach ( $pageSet->getMissingTitles()
as $fakeId =>
$title ) {
505 $vals[
'missing'] =
'';
506 $pages[$fakeId] = $vals;
509 foreach ( $pageSet->getInvalidTitles()
as $fakeId =>
$title ) {
510 $pages[$fakeId] =
array(
'title' =>
$title,
'invalid' =>
'' );
513 foreach ( $pageSet->getMissingPageIDs()
as $pageid ) {
514 $pages[$pageid] =
array(
521 foreach ( $pageSet->getSpecialTitles()
as $fakeId =>
$title ) {
524 $vals[
'special'] =
'';
525 if (
$title->isSpecialPage() &&
528 $vals[
'missing'] =
'';
532 $vals[
'missing'] =
'';
534 $pages[$fakeId] = $vals;
538 foreach ( $pageSet->getGoodTitles()
as $pageid =>
$title ) {
540 $vals[
'pageid'] = $pageid;
542 $pages[$pageid] = $vals;
545 if ( count( $pages ) ) {
546 if ( $this->mParams[
'indexpageids'] ) {
547 $pageIDs = array_keys( $pages );
549 $pageIDs = array_map(
'strval', $pageIDs );
550 $result->setIndexedTagName( $pageIDs,
'id' );
551 $result->addValue(
'query',
'pageids', $pageIDs );
554 $result->setIndexedTagName( $pages,
'page' );
555 $result->addValue(
'query',
'pages', $pages );
557 if ( $this->mParams[
'export'] ) {
572 if ( $this->mUseLegacyContinue ) {
575 $paramName = $module->encodeParamName( $paramName );
576 if ( $this->mGeneratorContinue ===
null ) {
577 $this->mGeneratorContinue =
array();
579 $this->mGeneratorContinue[$paramName] = $paramValue;
589 $exportTitles =
array();
590 $titles = $pageSet->getGoodTitles();
595 if ( $title->userCan(
'read',
$user ) ) {
605 $exporter->openStream();
606 foreach ( $exportTitles
as $title ) {
607 $exporter->pageByTitle(
$title );
609 $exporter->closeStream();
610 $exportxml = ob_get_contents();
617 if ( $this->mParams[
'exportnowrap'] ) {
620 $result->addValue(
null,
'text', $exportxml );
621 $result->addValue(
null,
'mime',
'text/xml' );
625 $result->addValue(
'query',
'export', $r );
644 'indexpageids' =>
false,
646 'exportnowrap' =>
false,
664 $msg = parent::makeHelpMsg();
666 $querySeparator = str_repeat(
'--- ', 12 );
667 $moduleSeparator = str_repeat(
'*** ', 14 );
668 $msg .=
"\n$querySeparator Query: Prop $querySeparator\n\n";
670 $msg .=
"\n$querySeparator Query: List $querySeparator\n\n";
672 $msg .=
"\n$querySeparator Query: Meta $querySeparator\n\n";
674 $msg .=
"\n\n$moduleSeparator Modules: continuation $moduleSeparator\n\n";
685 $moduleDescriptions =
array();
687 $moduleNames = $this->mModuleMgr->getNames( $group );
688 sort( $moduleNames );
689 foreach ( $moduleNames
as $name ) {
693 $module = $this->mModuleMgr->getModule(
$name );
696 $msg2 = $module->makeHelpMsg();
697 if ( $msg2 !==
false ) {
701 $msg .=
"Generator:\n This module may be used as a generator\n";
703 $moduleDescriptions[] = $msg;
706 return implode(
"\n", $moduleDescriptions );
715 'prop' =>
'Which properties to get for the titles/revisions/pageids. ' .
716 'Module help is available below',
717 'list' =>
'Which lists to get. Module help is available below',
718 'meta' =>
'Which metadata to get about the site. Module help is available below',
719 'indexpageids' =>
'Include an additional pageids section listing all returned page IDs',
720 'export' =>
'Export the current revisions of all given or generated pages',
721 'exportnowrap' =>
'Return the export XML without wrapping it in an ' .
722 'XML result (same format as Special:Export). Can only be used with export',
723 'iwurl' =>
'Whether to get the full URL if the title is an interwiki link',
725 'When present, formats query-continue as key-value pairs that ' .
726 'should simply be merged into the original request.',
727 'This parameter must be set to an empty string in the initial query.',
728 'This parameter is recommended for all new development, and ' .
729 'will be made default in the next API version.'
736 'Query API module allows applications to get needed pieces of data ' .
737 'from the MediaWiki databases,',
738 'and is loosely based on the old query.php interface.',
739 'All data modifications will first have to use query to acquire a ' .
740 'token to prevent abuse from malicious sites.'
746 parent::getPossibleErrors(),
753 'api.php?action=query&prop=revisions&meta=siteinfo&' .
754 'titles=Main%20Page&rvprop=user|comment&continue=',
755 'api.php?action=query&generator=allpages&gapprefix=API/&prop=revisions&continue=',
761 'https://www.mediawiki.org/wiki/API:Query',
762 'https://www.mediawiki.org/wiki/API:Meta',
763 'https://www.mediawiki.org/wiki/API:Properties',
764 'https://www.mediawiki.org/wiki/API:Lists',