*/
class ApiQuery extends ApiBase {
- private $mPropModuleNames, $mListModuleNames, $mMetaModuleNames;
-
- /**
- * @var ApiPageSet
- */
- private $mPageSet;
-
- private $params, $redirects, $convertTitles, $iwUrl;
-
/**
* List of Api Query prop modules
* @var array
*/
- private $mQueryPropModules = array(
+ private static $QueryPropModules = array(
'categories' => 'ApiQueryCategories',
'categoryinfo' => 'ApiQueryCategoryInfo',
'duplicatefiles' => 'ApiQueryDuplicateFiles',
* List of Api Query list modules
* @var array
*/
- private $mQueryListModules = array(
+ private static $QueryListModules = array(
'allcategories' => 'ApiQueryAllCategories',
'allimages' => 'ApiQueryAllImages',
'alllinks' => 'ApiQueryAllLinks',
'allpages' => 'ApiQueryAllPages',
+ 'alltransclusions' => 'ApiQueryAllLinks',
'allusers' => 'ApiQueryAllUsers',
'backlinks' => 'ApiQueryBacklinks',
'blocks' => 'ApiQueryBlocks',
* List of Api Query meta modules
* @var array
*/
- private $mQueryMetaModules = array(
+ private static $QueryMetaModules = array(
'allmessages' => 'ApiQueryAllMessages',
'siteinfo' => 'ApiQuerySiteinfo',
'userinfo' => 'ApiQueryUserInfo',
'allimages' => 'ApiQueryAllImages',
'alllinks' => 'ApiQueryAllLinks',
'allpages' => 'ApiQueryAllPages',
+ 'alltransclusions' => 'ApiQueryAllLinks',
'backlinks' => 'ApiQueryBacklinks',
'categories' => 'ApiQueryCategories',
'categorymembers' => 'ApiQueryCategoryMembers',
'watchlistraw' => 'ApiQueryWatchlistRaw',
);
- private $mSlaveDB = null;
- private $mNamedDB = array();
+ /**
+ * @var ApiPageSet
+ */
+ private $mPageSet;
- protected $mAllowedGenerators;
+ private $params;
+ private $iwUrl;
+ private $mNamedDB = array();
+ private $mModuleMgr;
/**
* @param $main ApiMain
public function __construct( $main, $action ) {
parent::__construct( $main, $action );
- // Allow custom modules to be added in LocalSettings.php
- global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules, $wgAPIGeneratorModules;
- self::appendUserModules( $this->mQueryPropModules, $wgAPIPropModules );
- self::appendUserModules( $this->mQueryListModules, $wgAPIListModules );
- self::appendUserModules( $this->mQueryMetaModules, $wgAPIMetaModules );
- self::appendUserModules( $this->mQueryGenerators, $wgAPIGeneratorModules );
-
- $this->mPropModuleNames = array_keys( $this->mQueryPropModules );
- $this->mListModuleNames = array_keys( $this->mQueryListModules );
- $this->mMetaModuleNames = array_keys( $this->mQueryMetaModules );
- $this->mAllowedGenerators = array_keys( $this->mQueryGenerators );
- }
+ $this->mModuleMgr = new ApiModuleManager( $this );
- /**
- * Helper function to append any add-in modules to the list
- * @param $modules array Module array
- * @param $newModules array Module array to add to $modules
- */
- private static function appendUserModules( &$modules, $newModules ) {
- if ( is_array( $newModules ) ) {
- foreach ( $newModules as $moduleName => $moduleClass ) {
- $modules[$moduleName] = $moduleClass;
+ // Allow custom modules to be added in LocalSettings.php
+ global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules;
+ $this->mModuleMgr->addModules( self::$QueryPropModules, 'prop' );
+ $this->mModuleMgr->addModules( $wgAPIPropModules, 'prop' );
+ $this->mModuleMgr->addModules( self::$QueryListModules, 'list' );
+ $this->mModuleMgr->addModules( $wgAPIListModules, 'list' );
+ $this->mModuleMgr->addModules( self::$QueryMetaModules, 'meta' );
+ $this->mModuleMgr->addModules( $wgAPIMetaModules, 'meta' );
+
+ global $wgAPIGeneratorModules;
+ if ( is_array( $wgAPIGeneratorModules ) ) {
+ foreach ( $wgAPIGeneratorModules as $moduleName => $moduleClass ) {
+ $this->mQueryGenerators[$moduleName] = $moduleClass;
}
}
+
+ // Create PageSet that will process titles/pageids/revids/generator
+ $this->mPageSet = new ApiPageSet( $this );
}
/**
- * Gets a default slave database connection object
- * @return DatabaseBase
+ * Overrides to return this instance's module manager.
+ * @return ApiModuleManager
*/
- public function getDB() {
- if ( !isset( $this->mSlaveDB ) ) {
- $this->profileDBIn();
- $this->mSlaveDB = wfGetDB( DB_SLAVE, 'api' );
- $this->profileDBOut();
- }
- return $this->mSlaveDB;
+ public function getModuleManager() {
+ return $this->mModuleMgr;
}
/**
/**
* Get the array mapping module names to class names
+ * @deprecated since 1.21, use getModuleManager()'s methods instead
* @return array array(modulename => classname)
*/
public function getModules() {
- return array_merge( $this->mQueryPropModules, $this->mQueryListModules, $this->mQueryMetaModules );
+ wfDeprecated( __METHOD__, '1.21' );
+ return $this->getModuleManager()->getNamesWithClasses();
}
/**
/**
* Get whether the specified module is a prop, list or a meta query module
+ * @deprecated since 1.21, use getModuleManager()->getModuleGroup()
* @param $moduleName string Name of the module to find type for
* @return mixed string or null
*/
function getModuleType( $moduleName ) {
- if ( isset( $this->mQueryPropModules[$moduleName] ) ) {
- return 'prop';
- }
-
- if ( isset( $this->mQueryListModules[$moduleName] ) ) {
- return 'list';
- }
-
- if ( isset( $this->mQueryMetaModules[$moduleName] ) ) {
- return 'meta';
- }
-
- return null;
+ return $this->getModuleManager()->getModuleGroup( $moduleName );
}
/**
*/
public function execute() {
$this->params = $this->extractRequestParams();
- $this->redirects = $this->params['redirects'];
- $this->convertTitles = $this->params['converttitles'];
$this->iwUrl = $this->params['iwurl'];
- // Create PageSet
- $this->mPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
-
// Instantiate requested modules
$modules = array();
- $this->instantiateModules( $modules, 'prop', $this->mQueryPropModules );
- $this->instantiateModules( $modules, 'list', $this->mQueryListModules );
- $this->instantiateModules( $modules, 'meta', $this->mQueryMetaModules );
-
- $cacheMode = 'public';
-
- // If given, execute generator to substitute user supplied data with generated data.
- if ( isset( $this->params['generator'] ) ) {
- $generator = $this->newGenerator( $this->params['generator'] );
- $params = $generator->extractRequestParams();
- $cacheMode = $this->mergeCacheMode( $cacheMode,
- $generator->getCacheMode( $params ) );
- $this->executeGeneratorModule( $generator, $modules );
- } else {
- // Append custom fields and populate page/revision information
- $this->addCustomFldsToPageSet( $modules, $this->mPageSet );
- $this->mPageSet->execute();
+ $this->instantiateModules( $modules, 'prop' );
+ $this->instantiateModules( $modules, 'list' );
+ $this->instantiateModules( $modules, 'meta' );
+
+ // Query modules may optimize data requests through the $this->getPageSet()
+ // object by adding extra fields from the page table.
+ // This function will gather all the extra request fields from the modules.
+ foreach ( $modules as $module ) {
+ $module->requestExtraData( $this->mPageSet );
}
+ // Populate page/revision information
+ $this->mPageSet->execute();
+ $cacheMode = $this->mPageSet->getCacheMode();
+
// Record page information (title, namespace, if exists, etc)
$this->outputGeneralPageInfo();
return $cacheMode;
}
- /**
- * Query modules may optimize data requests through the $this->getPageSet() object
- * by adding extra fields from the page table.
- * This function will gather all the extra request fields from the modules.
- * @param $modules array of module objects
- * @param $pageSet ApiPageSet
- */
- private function addCustomFldsToPageSet( $modules, $pageSet ) {
- // Query all requested modules.
- /**
- * @var $module ApiQueryBase
- */
- foreach ( $modules as $module ) {
- $module->requestExtraData( $pageSet );
- }
- }
-
/**
* Create instances of all modules requested by the client
* @param $modules Array to append instantiated modules to
* @param $param string Parameter name to read modules from
- * @param $moduleList Array array(modulename => classname)
*/
- private function instantiateModules( &$modules, $param, $moduleList ) {
+ private function instantiateModules( &$modules, $param ) {
if ( isset( $this->params[$param] ) ) {
foreach ( $this->params[$param] as $moduleName ) {
- $modules[] = new $moduleList[$moduleName] ( $this, $moduleName );
+ $modules[] = $this->mModuleMgr->getModule( $moduleName );
}
}
}
// more than 380K. The maximum revision size is in the megabyte range,
// and the maximum result size must be even higher than that.
- // Title normalizations
- $normValues = array();
- foreach ( $pageSet->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
- $normValues[] = array(
- 'from' => $rawTitleStr,
- 'to' => $titleStr
- );
+ $values = $pageSet->getNormalizedTitlesAsResult( $result );
+ if ( $values ) {
+ $result->addValue( 'query', 'normalized', $values );
}
-
- if ( count( $normValues ) ) {
- $result->setIndexedTagName( $normValues, 'n' );
- $result->addValue( 'query', 'normalized', $normValues );
+ $values = $pageSet->getConvertedTitlesAsResult( $result );
+ if ( $values ) {
+ $result->addValue( 'query', 'converted', $values );
}
-
- // Title conversions
- $convValues = array();
- foreach ( $pageSet->getConvertedTitles() as $rawTitleStr => $titleStr ) {
- $convValues[] = array(
- 'from' => $rawTitleStr,
- 'to' => $titleStr
- );
+ $values = $pageSet->getInterwikiTitlesAsResult( $result, $this->iwUrl );
+ if ( $values ) {
+ $result->addValue( 'query', 'interwiki', $values );
}
-
- if ( count( $convValues ) ) {
- $result->setIndexedTagName( $convValues, 'c' );
- $result->addValue( 'query', 'converted', $convValues );
+ $values = $pageSet->getRedirectTitlesAsResult( $result );
+ if ( $values ) {
+ $result->addValue( 'query', 'redirects', $values );
}
-
- // Interwiki titles
- $intrwValues = array();
- foreach ( $pageSet->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
- $item = array(
- 'title' => $rawTitleStr,
- 'iw' => $interwikiStr,
- );
- if ( $this->iwUrl ) {
- $title = Title::newFromText( $rawTitleStr );
- $item['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
- }
- $intrwValues[] = $item;
- }
-
- if ( count( $intrwValues ) ) {
- $result->setIndexedTagName( $intrwValues, 'i' );
- $result->addValue( 'query', 'interwiki', $intrwValues );
- }
-
- // Show redirect information
- $redirValues = array();
- /**
- * @var $titleTo Title
- */
- foreach ( $pageSet->getRedirectTitles() as $titleStrFrom => $titleTo ) {
- $r = array(
- 'from' => strval( $titleStrFrom ),
- 'to' => $titleTo->getPrefixedText(),
- );
- if ( $titleTo->getFragment() !== '' ) {
- $r['tofragment'] = $titleTo->getFragment();
- }
- $redirValues[] = $r;
- }
-
- if ( count( $redirValues ) ) {
- $result->setIndexedTagName( $redirValues, 'r' );
- $result->addValue( 'query', 'redirects', $redirValues );
- }
-
- // Missing revision elements
- $missingRevIDs = $pageSet->getMissingRevisionIDs();
- if ( count( $missingRevIDs ) ) {
- $revids = array();
- foreach ( $missingRevIDs as $revid ) {
- $revids[$revid] = array(
- 'revid' => $revid
- );
- }
- $result->setIndexedTagName( $revids, 'rev' );
- $result->addValue( 'query', 'badrevids', $revids );
+ $values = $pageSet->getMissingRevisionIDsAsResult( $result );
+ if ( $values ) {
+ $result->addValue( 'query', 'badrevids', $values );
}
// Page elements
}
/**
- * @param $pageSet ApiPageSet Pages to be exported
- * @param $result ApiResult Result to output to
+ * @param $pageSet ApiPageSet Pages to be exported
+ * @param $result ApiResult Result to output to
*/
private function doExport( $pageSet, $result ) {
$exportTitles = array();
$result->enableSizeCheck();
}
- /**
- * Create a generator object of the given type and return it
- * @param $generatorName string Module name
- * @return ApiQueryGeneratorBase
- */
- public function newGenerator( $generatorName ) {
- // Find class that implements requested generator
- if ( isset( $this->mQueryListModules[$generatorName] ) ) {
- $className = $this->mQueryListModules[$generatorName];
- } elseif ( isset( $this->mQueryPropModules[$generatorName] ) ) {
- $className = $this->mQueryPropModules[$generatorName];
- } else {
- ApiBase::dieDebug( __METHOD__, "Unknown generator=$generatorName" );
- }
- $generator = new $className ( $this, $generatorName );
- if ( !$generator instanceof ApiQueryGeneratorBase ) {
- $this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' );
- }
- $generator->setGeneratorMode();
- return $generator;
- }
-
- /**
- * For generator mode, execute generator, and use its output as new
- * ApiPageSet
- * @param $generator ApiQueryGeneratorBase Generator Module
- * @param $modules array of module objects
- */
- protected function executeGeneratorModule( $generator, $modules ) {
- // Generator results
- $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
-
- // Add any additional fields modules may need
- $generator->requestExtraData( $this->mPageSet );
- $this->addCustomFldsToPageSet( $modules, $resultPageSet );
-
- // Populate page information with the original user input
- $this->mPageSet->execute();
-
- // populate resultPageSet with the generator output
- $generator->profileIn();
- $generator->executeGenerator( $resultPageSet );
- wfRunHooks( 'APIQueryGeneratorAfterExecute', array( &$generator, &$resultPageSet ) );
- $resultPageSet->finishPageSetGeneration();
- $generator->profileOut();
-
- // Swap the resulting pageset back in
- $this->mPageSet = $resultPageSet;
- }
-
- public function getAllowedParams() {
- return array(
+ public function getAllowedParams( $flags = 0 ) {
+ $result = array(
'prop' => array(
ApiBase::PARAM_ISMULTI => true,
- ApiBase::PARAM_TYPE => $this->mPropModuleNames
+ ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'prop' )
),
'list' => array(
ApiBase::PARAM_ISMULTI => true,
- ApiBase::PARAM_TYPE => $this->mListModuleNames
+ ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'list' )
),
'meta' => array(
ApiBase::PARAM_ISMULTI => true,
- ApiBase::PARAM_TYPE => $this->mMetaModuleNames
+ ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'meta' )
),
- 'generator' => array(
- ApiBase::PARAM_TYPE => $this->mAllowedGenerators
- ),
- 'redirects' => false,
- 'converttitles' => false,
'indexpageids' => false,
'export' => false,
'exportnowrap' => false,
'iwurl' => false,
);
+ if( $flags ) {
+ $result += $this->getPageSet()->getFinalParams( $flags );
+ }
+ return $result;
}
/**
* @return string
*/
public function makeHelpMsg() {
- // Make sure the internal object is empty
- // (just in case a sub-module decides to optimize during instantiation)
- $this->mPageSet = null;
+
+ // Use parent to make default message for the query module
+ $msg = parent::makeHelpMsg();
$querySeparator = str_repeat( '--- ', 12 );
$moduleSeparator = str_repeat( '*** ', 14 );
- $msg = "\n$querySeparator Query: Prop $querySeparator\n\n";
- $msg .= $this->makeHelpMsgHelper( $this->mQueryPropModules, 'prop' );
+ $msg .= "\n$querySeparator Query: Prop $querySeparator\n\n";
+ $msg .= $this->makeHelpMsgHelper( 'prop' );
$msg .= "\n$querySeparator Query: List $querySeparator\n\n";
- $msg .= $this->makeHelpMsgHelper( $this->mQueryListModules, 'list' );
+ $msg .= $this->makeHelpMsgHelper( 'list' );
$msg .= "\n$querySeparator Query: Meta $querySeparator\n\n";
- $msg .= $this->makeHelpMsgHelper( $this->mQueryMetaModules, 'meta' );
+ $msg .= $this->makeHelpMsgHelper( 'meta' );
$msg .= "\n\n$moduleSeparator Modules: continuation $moduleSeparator\n\n";
- // Use parent to make default message for the query module
- $msg = parent::makeHelpMsg() . $msg;
-
return $msg;
}
/**
- * For all modules in $moduleList, generate help messages and join them together
- * @param $moduleList Array array(modulename => classname)
- * @param $paramName string Parameter name
+ * For all modules of a given group, generate help messages and join them together
+ * @param $group string Module group
* @return string
*/
- private function makeHelpMsgHelper( $moduleList, $paramName ) {
+ private function makeHelpMsgHelper( $group ) {
$moduleDescriptions = array();
- foreach ( $moduleList as $moduleName => $moduleClass ) {
+ $moduleNames = $this->mModuleMgr->getNames( $group );
+ sort( $moduleNames );
+ foreach ( $moduleNames as $name ) {
/**
* @var $module ApiQueryBase
*/
- $module = new $moduleClass( $this, $moduleName, null );
+ $module = $this->mModuleMgr->getModule( $name );
- $msg = ApiMain::makeHelpMsgHeader( $module, $paramName );
+ $msg = ApiMain::makeHelpMsgHeader( $module, $group );
$msg2 = $module->makeHelpMsg();
if ( $msg2 !== false ) {
$msg .= $msg2;
return implode( "\n", $moduleDescriptions );
}
- /**
- * Override to add extra parameters from PageSet
- * @return string
- */
- public function makeHelpMsgParameters() {
- $psModule = new ApiPageSet( $this );
- return $psModule->makeHelpMsgParameters() . parent::makeHelpMsgParameters();
- }
-
public function shouldCheckMaxlag() {
return true;
}
public function getParamDescription() {
- return array(
+ return $this->getPageSet()->getParamDescription() + array(
'prop' => 'Which properties to get for the titles/revisions/pageids. Module help is available below',
'list' => 'Which lists to get. Module help is available below',
'meta' => 'Which metadata to get about the site. Module help is available below',
- 'generator' => array( 'Use the output of a list as the input for other prop/list/meta items',
- 'NOTE: generator parameter names must be prefixed with a \'g\', see examples' ),
- 'redirects' => 'Automatically resolve redirects',
- 'converttitles' => array( "Convert titles to other variants if necessary. Only works if the wiki's content language supports variant conversion.",
- 'Languages that support variant conversion include ' . implode( ', ', LanguageConverter::$languagesWithVariants ) ),
'indexpageids' => 'Include an additional pageids section listing all returned page IDs',
'export' => 'Export the current revisions of all given or generated pages',
'exportnowrap' => 'Return the export XML without wrapping it in an XML result (same format as Special:Export). Can only be used with export',
}
public function getPossibleErrors() {
- return array_merge( parent::getPossibleErrors(), array(
- array( 'code' => 'badgenerator', 'info' => 'Module $generatorName cannot be used as a generator' ),
- ) );
+ return array_merge(
+ parent::getPossibleErrors(),
+ $this->getPageSet()->getPossibleErrors()
+ );
}
public function getExamples() {
'https://www.mediawiki.org/wiki/API:Lists',
);
}
-
- public function getVersion() {
- $psModule = new ApiPageSet( $this );
- $vers = array();
- $vers[] = __CLASS__ . ': $Id$';
- $vers[] = $psModule->getVersion();
- return $vers;
- }
}