25 use Wikimedia\ObjectFactory\ObjectFactory;
46 private const QUERY_PROP_MODULES = [
48 'class' => ApiQueryCategories::class,
51 'class' => ApiQueryCategoryInfo::class,
54 'class' => ApiQueryContributors::class,
59 'GroupPermissionsLookup',
62 'deletedrevisions' => [
63 'class' => ApiQueryDeletedRevisions::class,
66 'ContentHandlerFactory',
77 'class' => ApiQueryDuplicateFiles::class,
83 'class' => ApiQueryExternalLinks::class,
86 'class' => ApiQueryBacklinksprop::class,
93 'class' => ApiQueryImages::class,
96 'class' => ApiQueryImageInfo::class,
105 'class' => ApiQueryInfo::class,
113 'LanguageConverterFactory',
119 'class' => ApiQueryLinks::class,
127 'class' => ApiQueryBacklinksprop::class,
134 'class' => ApiQueryIWLinks::class,
137 'class' => ApiQueryLangLinks::class,
144 'class' => ApiQueryPageProps::class,
150 'class' => ApiQueryBacklinksprop::class,
157 'class' => ApiQueryRevisions::class,
160 'ContentHandlerFactory',
166 'ContentTransformer',
170 'stashimageinfo' => [
171 'class' => ApiQueryStashImageInfo::class,
180 'class' => ApiQueryLinks::class,
188 'class' => ApiQueryBacklinksprop::class,
199 private const QUERY_LIST_MODULES = [
201 'class' => ApiQueryAllCategories::class,
203 'alldeletedrevisions' => [
204 'class' => ApiQueryAllDeletedRevisions::class,
207 'ContentHandlerFactory',
213 'ContentTransformer',
218 'class' => ApiQueryAllLinks::class,
227 'class' => ApiQueryAllImages::class,
230 'GroupPermissionsLookup',
234 'class' => ApiQueryAllLinks::class,
243 'class' => ApiQueryAllPages::class,
251 'class' => ApiQueryAllLinks::class,
260 'class' => ApiQueryAllRevisions::class,
263 'ContentHandlerFactory',
269 'ContentTransformer',
273 'mystashedfiles' => [
274 'class' => ApiQueryMyStashedFiles::class,
276 'alltransclusions' => [
277 'class' => ApiQueryAllLinks::class,
286 'class' => ApiQueryAllUsers::class,
290 'GroupPermissionsLookup',
295 'class' => ApiQueryBacklinks::class,
301 'class' => ApiQueryBlocks::class,
304 'BlockRestrictionStore',
308 'categorymembers' => [
309 'class' => ApiQueryCategoryMembers::class,
315 'class' => ApiQueryDeletedrevs::class,
318 'RowCommentFormatter',
325 'class' => ApiQueryBacklinks::class,
331 'class' => ApiQueryExtLinksUsage::class,
334 'class' => ApiQueryFilearchive::class,
341 'class' => ApiQueryBacklinks::class,
347 'class' => ApiQueryIWBacklinks::class,
350 'class' => ApiQueryLangBacklinks::class,
353 'class' => ApiQueryLogEvents::class,
356 'RowCommentFormatter',
361 'class' => ApiQueryPagesWithProp::class,
364 'class' => ApiQueryPagePropNames::class,
367 'class' => ApiQueryPrefixSearch::class,
369 'SearchEngineConfig',
370 'SearchEngineFactory',
373 'protectedtitles' => [
374 'class' => ApiQueryProtectedTitles::class,
377 'RowCommentFormatter'
381 'class' => ApiQueryQueryPage::class,
383 'SpecialPageFactory',
387 'class' => ApiQueryRandom::class,
390 'class' => ApiQueryRecentChanges::class,
393 'RowCommentFormatter',
400 'class' => ApiQuerySearch::class,
402 'SearchEngineConfig',
403 'SearchEngineFactory',
407 'class' => ApiQueryTags::class,
410 'class' => ApiQueryUserContribs::class,
413 'UserIdentityLookup',
422 'class' => ApiQueryUsers::class,
432 'class' => ApiQueryWatchlist::class,
435 'WatchedItemQueryService',
443 'class' => ApiQueryWatchlistRaw::class,
445 'WatchedItemQueryService',
456 private const QUERY_META_MODULES = [
458 'class' => ApiQueryAllMessages::class,
467 'authmanagerinfo' => [
468 'class' => ApiQueryAuthManagerInfo::class,
474 'class' => ApiQuerySiteinfo::class,
478 'LanguageConverterFactory',
486 'SpecialPageFactory',
493 'class' => ApiQueryUserInfo::class,
495 'TalkPageNotificationManager',
503 'class' => ApiQueryFileRepoInfo::class,
509 'class' => ApiQueryTokens::class,
512 'class' => ApiQueryLanguageinfo::class,
517 'LanguageConverterFactory',
528 private $mNamedDB = [];
532 private $loadBalancer;
535 private $wikiExporterFactory;
547 ObjectFactory $objectFactory,
551 parent::__construct( $main, $action );
560 $this->mModuleMgr->addModules( self::QUERY_PROP_MODULES,
'prop' );
561 $this->mModuleMgr->addModules( $config->get( MainConfigNames::APIPropModules ),
'prop' );
562 $this->mModuleMgr->addModules( self::QUERY_LIST_MODULES,
'list' );
563 $this->mModuleMgr->addModules( $config->get( MainConfigNames::APIListModules ),
'list' );
564 $this->mModuleMgr->addModules( self::QUERY_META_MODULES,
'meta' );
565 $this->mModuleMgr->addModules( $config->get( MainConfigNames::APIMetaModules ),
'meta' );
567 $this->
getHookRunner()->onApiQuery__moduleManager( $this->mModuleMgr );
571 $this->loadBalancer = $loadBalancer;
572 $this->wikiExporterFactory = $wikiExporterFactory;
580 return $this->mModuleMgr;
599 if ( !array_key_exists( $name, $this->mNamedDB ) ) {
600 $this->mNamedDB[$name] = $this->loadBalancer->getConnectionRef( $db, $groups );
603 return $this->mNamedDB[$name];
611 return $this->mPageSet;
623 $this->
getMain()->createPrinterByName(
'xml' ) );
644 $this->instantiateModules( $allModules,
'prop' );
645 $propModules = array_keys( $allModules );
646 $this->instantiateModules( $allModules,
'list' );
647 $this->instantiateModules( $allModules,
'meta' );
653 $modules = $continuationManager->getRunModules();
654 '@phan-var ApiQueryBase[] $modules';
656 if ( !$continuationManager->isGeneratorDone() ) {
660 $module->requestExtraData( $this->mPageSet );
663 $this->mPageSet->execute();
665 $this->outputGeneralPageInfo();
667 $this->mPageSet->executeDryRun();
670 $cacheMode = $this->mPageSet->getCacheMode();
674 $params = $module->extractRequestParams();
676 $cacheMode, $module->getCacheMode( $params ) );
682 $this->
getMain()->setCacheMode( $cacheMode );
686 if ( $this->mParams[
'rawcontinue'] ) {
687 $data = $continuationManager->getRawNonContinuation();
689 $this->
getResult()->addValue(
null,
'query-noncontinue', $data,
692 $data = $continuationManager->getRawContinuation();
694 $this->
getResult()->addValue(
null,
'query-continue', $data,
698 $continuationManager->setContinuationIntoResult( $this->
getResult() );
712 if ( $modCacheMode ===
'anon-public-user-private' ) {
713 if ( $cacheMode !==
'private' ) {
714 $cacheMode =
'anon-public-user-private';
716 } elseif ( $modCacheMode ===
'public' ) {
719 $cacheMode =
'private';
730 private function instantiateModules( &
$modules, $param ) {
731 $wasPosted = $this->
getRequest()->wasPosted();
732 if ( isset( $this->mParams[$param] ) ) {
733 foreach ( $this->mParams[$param] as $moduleName ) {
734 $instance = $this->mModuleMgr->getModule( $moduleName, $param );
735 if ( $instance ===
null ) {
738 if ( !$wasPosted && $instance->mustBePosted() ) {
742 if ( !array_key_exists( $moduleName,
$modules ) ) {
754 private function outputGeneralPageInfo() {
762 $values = $pageSet->getNormalizedTitlesAsResult( $result );
765 $fit = $fit && $result->addValue(
'query',
'normalized', $values );
767 $values = $pageSet->getConvertedTitlesAsResult( $result );
769 $fit = $fit && $result->addValue(
'query',
'converted', $values );
771 $values = $pageSet->getInterwikiTitlesAsResult( $result, $this->mParams[
'iwurl'] );
773 $fit = $fit && $result->addValue(
'query',
'interwiki', $values );
775 $values = $pageSet->getRedirectTitlesAsResult( $result );
777 $fit = $fit && $result->addValue(
'query',
'redirects', $values );
779 $values = $pageSet->getMissingRevisionIDsAsResult( $result );
781 $fit = $fit && $result->addValue(
'query',
'badrevids', $values );
788 foreach ( $pageSet->getMissingTitles() as $fakeId =>
$title ) {
791 $vals[
'missing'] =
true;
792 if (
$title->isKnown() ) {
793 $vals[
'known'] =
true;
795 $pages[$fakeId] = $vals;
798 foreach ( $pageSet->getInvalidTitlesAndReasons() as $fakeId => $data ) {
799 $pages[$fakeId] = $data + [
'invalid' =>
true ];
802 foreach ( $pageSet->getMissingPageIDs() as $pageid ) {
810 foreach ( $pageSet->getSpecialTitles() as $fakeId =>
$title ) {
813 $vals[
'special'] =
true;
814 if ( !
$title->isKnown() ) {
815 $vals[
'missing'] =
true;
817 $pages[$fakeId] = $vals;
821 foreach ( $pageSet->getGoodTitles() as $pageid =>
$title ) {
823 $vals[
'pageid'] = $pageid;
825 $pages[$pageid] = $vals;
828 if ( count( $pages ) ) {
829 $pageSet->populateGeneratorData( $pages );
832 if ( $this->mParams[
'indexpageids'] ) {
835 $pageIDs = array_map(
'strval', $pageIDs );
837 $fit = $fit && $result->addValue(
'query',
'pageids', $pageIDs );
841 $fit = $fit && $result->addValue(
'query',
'pages', $pages );
845 $this->
dieWithError(
'apierror-badconfig-resulttoosmall',
'badconfig' );
848 if ( $this->mParams[
'export'] ) {
849 $this->doExport( $pageSet, $result );
857 private function doExport( $pageSet, $result ) {
859 $titles = $pageSet->getGoodPages();
860 if ( count( $titles ) ) {
862 foreach ( $titles as
$title ) {
869 $exporter = $this->wikiExporterFactory->getWikiExporter( $this->
getDB() );
871 $exporter->setOutputSink( $sink );
872 $exporter->setSchemaVersion( $this->mParams[
'exportschema'] );
873 $exporter->openStream();
874 foreach ( $exportTitles as
$title ) {
875 $exporter->pageByTitle(
$title );
877 $exporter->closeStream();
882 if ( $this->mParams[
'exportnowrap'] ) {
897 ParamValidator::PARAM_ISMULTI =>
true,
898 ParamValidator::PARAM_TYPE =>
'submodule',
901 ParamValidator::PARAM_ISMULTI =>
true,
902 ParamValidator::PARAM_TYPE =>
'submodule',
905 ParamValidator::PARAM_ISMULTI =>
true,
906 ParamValidator::PARAM_TYPE =>
'submodule',
908 'indexpageids' =>
false,
910 'exportnowrap' =>
false,
919 'rawcontinue' =>
false,
922 $result += $this->
getPageSet()->getFinalParams( $flags );
935 $allowedParams = [
'rawcontinue' => 1,
'indexpageids' => 1 ];
939 $needed = $param ===
'meta';
940 if ( !isset( $allowedParams[$param] ) && $request->getCheck( $param ) !== $needed ) {
948 $this->instantiateModules(
$modules,
'meta' );
950 if ( $module->isReadMode() ) {
960 'action=query&prop=revisions&meta=siteinfo&' .
961 'titles=Main%20Page&rvprop=user|comment&continue='
962 =>
'apihelp-query-example-revisions',
963 'action=query&generator=allpages&gapprefix=API/&prop=revisions&continue='
964 =>
'apihelp-query-example-allpages',
970 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Query',
971 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Meta',
972 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Properties',
973 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Lists',
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
This abstract class implements many basic API functions, and is the base of all API classes.
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
getParameter( $paramName, $parseLimit=true)
Get a value for the given parameter.
getDB()
Gets a default replica DB connection object.
dieWithErrorOrDebug( $msg, $code=null, $data=null, $httpCode=null)
Will only set a warning instead of failing if the global $wgDebugAPI is set to true.
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
getMain()
Get the main module.
setContinuationManager(ApiContinuationManager $manager=null)
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
getHookRunner()
Get an ApiHookRunner for running core API hooks.
This manages continuation state.
This is the main API class, used for both external and internal processing.
This class holds a list of modules and handles instantiation.
This class contains a list of pages that the client has requested.
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
This is the main query class.
isReadMode()
Indicates whether this module requires read rights.
mergeCacheMode( $cacheMode, $modCacheMode)
Update a cache mode string, applying the cache mode of a new module to it.
getAllowedParams( $flags=0)
getModuleManager()
Overrides to return this instance's module manager.
getExamplesMessages()
Returns usage examples for this module.
__construct(ApiMain $main, $action, ObjectFactory $objectFactory, ILoadBalancer $loadBalancer, WikiExporterFactory $wikiExporterFactory)
getHelpUrls()
Return links to more detailed help pages about the module.
getPageSet()
Gets the set of pages the user has requested (or generated)
execute()
Query execution happens in the following steps: #1 Create a PageSet object with any pages requested b...
getNamedDB( $name, $db, $groups)
Get a cached database connection with a given name.
static stripMetadataNonRecursive( $data, &$metadata=null)
Remove metadata keys from a data array or object, non-recursive.
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
const NO_SIZE_CHECK
For addValue() and similar functions, do not check size while adding a value Don't use this unless yo...
const ADD_ON_TOP
For addValue(), setValue() and similar functions, if the value does not exist, add it as the first el...
const META_BC_SUBELEMENTS
Key for the 'BC subelements' metadata item.
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
A class containing constants representing the names of configuration variables.
static schemaVersion()
Returns the default export schema version, as defined by the XmlDumpSchemaVersion setting.
static string[] $supportedSchemas
the schema versions supported for output @final