diff options
Diffstat (limited to 'includes/api/ApiPageSet.php')
-rw-r--r-- | includes/api/ApiPageSet.php | 560 |
1 files changed, 427 insertions, 133 deletions
diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php index 0f5be6b2..074efe4b 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -4,7 +4,7 @@ * * Created on Sep 24, 2006 * - * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com" + * Copyright © 2006, 2013 Yuri Astrakhan "<Firstname><Lastname>@gmail.com" * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,52 +36,177 @@ * the second instance for all their work. * * @ingroup API + * @since 1.21 derives from ApiBase instead of ApiQueryBase */ -class ApiPageSet extends ApiQueryBase { +class ApiPageSet extends ApiBase { - private $mAllPages; // [ns][dbkey] => page_id or negative when missing - private $mTitles, $mGoodTitles, $mMissingTitles, $mInvalidTitles; - private $mMissingPageIDs, $mRedirectTitles, $mSpecialTitles; - private $mNormalizedTitles, $mInterwikiTitles; - private $mResolveRedirects, $mPendingRedirectIDs; - private $mConvertTitles, $mConvertedTitles; - private $mGoodRevIDs, $mMissingRevIDs; - private $mFakePageId; - - private $mRequestedPageFields; + /** + * Constructor flag: The new instance of ApiPageSet will ignore the 'generator=' parameter + * @since 1.21 + */ + const DISABLE_GENERATORS = 1; + + private $mDbSource; + private $mParams; + private $mResolveRedirects; + private $mConvertTitles; + private $mAllowGenerator; + + private $mAllPages = array(); // [ns][dbkey] => page_id or negative when missing + private $mTitles = array(); + private $mGoodTitles = array(); + private $mMissingTitles = array(); + private $mInvalidTitles = array(); + private $mMissingPageIDs = array(); + private $mRedirectTitles = array(); + private $mSpecialTitles = array(); + private $mNormalizedTitles = array(); + private $mInterwikiTitles = array(); + private $mPendingRedirectIDs = array(); + private $mConvertedTitles = array(); + private $mGoodRevIDs = array(); + private $mMissingRevIDs = array(); + private $mFakePageId = -1; + private $mCacheMode = 'public'; + private $mRequestedPageFields = array(); + private $mDefaultNamespace = NS_MAIN; /** * Constructor - * @param $query ApiBase - * @param $resolveRedirects bool Whether redirects should be resolved - * @param $convertTitles bool + * @param $dbSource ApiBase Module implementing getDB(). + * Allows PageSet to reuse existing db connection from the shared state like ApiQuery. + * @param int $flags Zero or more flags like DISABLE_GENERATORS + * @param int $defaultNamespace the namespace to use if none is specified by a prefix. + * @since 1.21 accepts $flags instead of two boolean values */ - public function __construct( $query, $resolveRedirects = false, $convertTitles = false ) { - parent::__construct( $query, 'query' ); + public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) { + parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() ); + $this->mDbSource = $dbSource; + $this->mAllowGenerator = ( $flags & ApiPageSet::DISABLE_GENERATORS ) == 0; + $this->mDefaultNamespace = $defaultNamespace; - $this->mAllPages = array(); - $this->mTitles = array(); - $this->mGoodTitles = array(); - $this->mMissingTitles = array(); - $this->mInvalidTitles = array(); - $this->mMissingPageIDs = array(); - $this->mRedirectTitles = array(); - $this->mNormalizedTitles = array(); - $this->mInterwikiTitles = array(); - $this->mGoodRevIDs = array(); - $this->mMissingRevIDs = array(); - $this->mSpecialTitles = array(); + $this->profileIn(); + $this->mParams = $this->extractRequestParams(); + $this->mResolveRedirects = $this->mParams['redirects']; + $this->mConvertTitles = $this->mParams['converttitles']; + $this->profileOut(); + } - $this->mRequestedPageFields = array(); - $this->mResolveRedirects = $resolveRedirects; - if ( $resolveRedirects ) { - $this->mPendingRedirectIDs = array(); - } + /** + * In case execute() is not called, call this method to mark all relevant parameters as used + * This prevents unused parameters from being reported as warnings + */ + public function executeDryRun() { + $this->executeInternal( true ); + } - $this->mConvertTitles = $convertTitles; - $this->mConvertedTitles = array(); + /** + * Populate the PageSet from the request parameters. + */ + public function execute() { + $this->executeInternal( false ); + } + + /** + * Populate the PageSet from the request parameters. + * @param bool $isDryRun If true, instantiates generator, but only to mark relevant parameters as used + */ + private function executeInternal( $isDryRun ) { + $this->profileIn(); - $this->mFakePageId = - 1; + $generatorName = $this->mAllowGenerator ? $this->mParams['generator'] : null; + if ( isset( $generatorName ) ) { + $dbSource = $this->mDbSource; + $isQuery = $dbSource instanceof ApiQuery; + if ( !$isQuery ) { + // If the parent container of this pageset is not ApiQuery, we must create it to run generator + $dbSource = $this->getMain()->getModuleManager()->getModule( 'query' ); + // Enable profiling for query module because it will be used for db sql profiling + $dbSource->profileIn(); + } + $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true ); + if ( $generator === null ) { + $this->dieUsage( 'Unknown generator=' . $generatorName, 'badgenerator' ); + } + if ( !$generator instanceof ApiQueryGeneratorBase ) { + $this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' ); + } + // Create a temporary pageset to store generator's output, + // add any additional fields generator may need, and execute pageset to populate titles/pageids + $tmpPageSet = new ApiPageSet( $dbSource, ApiPageSet::DISABLE_GENERATORS ); + $generator->setGeneratorMode( $tmpPageSet ); + $this->mCacheMode = $generator->getCacheMode( $generator->extractRequestParams() ); + + if ( !$isDryRun ) { + $generator->requestExtraData( $tmpPageSet ); + } + $tmpPageSet->executeInternal( $isDryRun ); + + // populate this pageset with the generator output + $this->profileOut(); + $generator->profileIn(); + + if ( !$isDryRun ) { + $generator->executeGenerator( $this ); + wfRunHooks( 'APIQueryGeneratorAfterExecute', array( &$generator, &$this ) ); + $this->resolvePendingRedirects(); + } else { + // Prevent warnings from being reported on these parameters + $main = $this->getMain(); + foreach ( $generator->extractRequestParams() as $paramName => $param ) { + $main->getVal( $generator->encodeParamName( $paramName ) ); + } + } + $generator->profileOut(); + $this->profileIn(); + + if ( !$isQuery ) { + // If this pageset is not part of the query, we called profileIn() above + $dbSource->profileOut(); + } + } else { + // Only one of the titles/pageids/revids is allowed at the same time + $dataSource = null; + if ( isset( $this->mParams['titles'] ) ) { + $dataSource = 'titles'; + } + if ( isset( $this->mParams['pageids'] ) ) { + if ( isset( $dataSource ) ) { + $this->dieUsage( "Cannot use 'pageids' at the same time as '$dataSource'", 'multisource' ); + } + $dataSource = 'pageids'; + } + if ( isset( $this->mParams['revids'] ) ) { + if ( isset( $dataSource ) ) { + $this->dieUsage( "Cannot use 'revids' at the same time as '$dataSource'", 'multisource' ); + } + $dataSource = 'revids'; + } + + if ( !$isDryRun ) { + // Populate page information with the original user input + switch( $dataSource ) { + case 'titles': + $this->initFromTitles( $this->mParams['titles'] ); + break; + case 'pageids': + $this->initFromPageIds( $this->mParams['pageids'] ); + break; + case 'revids': + if ( $this->mResolveRedirects ) { + $this->setWarning( 'Redirect resolution cannot be used together with the revids= parameter. ' . + 'Any redirects the revids= point to have not been resolved.' ); + } + $this->mResolveRedirects = false; + $this->initFromRevIDs( $this->mParams['revids'] ); + break; + default: + // Do nothing - some queries do not need any of the data sources. + break; + } + } + } + $this->profileOut(); } /** @@ -93,9 +218,33 @@ class ApiPageSet extends ApiQueryBase { } /** - * Request an additional field from the page table. Must be called - * before execute() - * @param $fieldName string Field name + * Return the parameter name that is the source of data for this PageSet + * + * If multiple source parameters are specified (e.g. titles and pageids), + * one will be named arbitrarily. + * + * @return string|null + */ + public function getDataSource() { + if ( $this->mAllowGenerator && isset( $this->mParams['generator'] ) ) { + return 'generator'; + } + if ( isset( $this->mParams['titles'] ) ) { + return 'titles'; + } + if ( isset( $this->mParams['pageids'] ) ) { + return 'pageids'; + } + if ( isset( $this->mParams['revids'] ) ) { + return 'revids'; + } + return null; + } + + /** + * Request an additional field from the page table. + * Must be called before execute() + * @param string $fieldName Field name */ public function requestField( $fieldName ) { $this->mRequestedPageFields[$fieldName] = null; @@ -104,7 +253,7 @@ class ApiPageSet extends ApiQueryBase { /** * Get the value of a custom field previously requested through * requestField() - * @param $fieldName string Field name + * @param string $fieldName Field name * @return mixed Field value */ public function getCustomField( $fieldName ) { @@ -207,14 +356,39 @@ class ApiPageSet extends ApiQueryBase { /** * Get a list of redirect resolutions - maps a title to its redirect - * target. - * @return array prefixed_title (string) => Title object + * target, as an array of output-ready arrays + * @return array */ public function getRedirectTitles() { return $this->mRedirectTitles; } /** + * Get a list of redirect resolutions - maps a title to its redirect + * target. + * @param $result ApiResult + * @return array of prefixed_title (string) => Title object + * @since 1.21 + */ + public function getRedirectTitlesAsResult( $result = null ) { + $values = array(); + foreach ( $this->getRedirectTitles() as $titleStrFrom => $titleTo ) { + $r = array( + 'from' => strval( $titleStrFrom ), + 'to' => $titleTo->getPrefixedText(), + ); + if ( $titleTo->getFragment() !== '' ) { + $r['tofragment'] = $titleTo->getFragment(); + } + $values[] = $r; + } + if ( !empty( $values ) && $result ) { + $result->setIndexedTagName( $values, 'r' ); + } + return $values; + } + + /** * Get a list of title normalizations - maps a title to its normalized * version. * @return array raw_prefixed_title (string) => prefixed_title (string) @@ -224,6 +398,27 @@ class ApiPageSet extends ApiQueryBase { } /** + * Get a list of title normalizations - maps a title to its normalized + * version in the form of result array. + * @param $result ApiResult + * @return array of raw_prefixed_title (string) => prefixed_title (string) + * @since 1.21 + */ + public function getNormalizedTitlesAsResult( $result = null ) { + $values = array(); + foreach ( $this->getNormalizedTitles() as $rawTitleStr => $titleStr ) { + $values[] = array( + 'from' => $rawTitleStr, + 'to' => $titleStr + ); + } + if ( !empty( $values ) && $result ) { + $result->setIndexedTagName( $values, 'n' ); + } + return $values; + } + + /** * Get a list of title conversions - maps a title to its converted * version. * @return array raw_prefixed_title (string) => prefixed_title (string) @@ -233,6 +428,27 @@ class ApiPageSet extends ApiQueryBase { } /** + * Get a list of title conversions - maps a title to its converted + * version as a result array. + * @param $result ApiResult + * @return array of (from, to) strings + * @since 1.21 + */ + public function getConvertedTitlesAsResult( $result = null ) { + $values = array(); + foreach ( $this->getConvertedTitles() as $rawTitleStr => $titleStr ) { + $values[] = array( + 'from' => $rawTitleStr, + 'to' => $titleStr + ); + } + if ( !empty( $values ) && $result ) { + $result->setIndexedTagName( $values, 'c' ); + } + return $values; + } + + /** * Get a list of interwiki titles - maps a title to its interwiki * prefix. * @return array raw_prefixed_title (string) => interwiki_prefix (string) @@ -242,6 +458,33 @@ class ApiPageSet extends ApiQueryBase { } /** + * Get a list of interwiki titles - maps a title to its interwiki + * prefix as result. + * @param $result ApiResult + * @param $iwUrl boolean + * @return array raw_prefixed_title (string) => interwiki_prefix (string) + * @since 1.21 + */ + public function getInterwikiTitlesAsResult( $result = null, $iwUrl = false ) { + $values = array(); + foreach ( $this->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) { + $item = array( + 'title' => $rawTitleStr, + 'iw' => $interwikiStr, + ); + if ( $iwUrl ) { + $title = Title::newFromText( $rawTitleStr ); + $item['url'] = $title->getFullURL( '', false, PROTO_CURRENT ); + } + $values[] = $item; + } + if ( !empty( $values ) && $result ) { + $result->setIndexedTagName( $values, 'i' ); + } + return $values; + } + + /** * Get the list of revision IDs (requested with the revids= parameter) * @return array revID (int) => pageID (int) */ @@ -258,6 +501,25 @@ class ApiPageSet extends ApiQueryBase { } /** + * Revision IDs that were not found in the database as result array. + * @param $result ApiResult + * @return array of revision IDs + * @since 1.21 + */ + public function getMissingRevisionIDsAsResult( $result = null ) { + $values = array(); + foreach ( $this->getMissingRevisionIDs() as $revid ) { + $values[$revid] = array( + 'revid' => $revid + ); + } + if ( !empty( $values ) && $result ) { + $result->setIndexedTagName( $values, 'rev' ); + } + return $values; + } + + /** * Get the list of titles with negative namespace * @return array Title */ @@ -274,55 +536,8 @@ class ApiPageSet extends ApiQueryBase { } /** - * Populate the PageSet from the request parameters. - */ - public function execute() { - $this->profileIn(); - $params = $this->extractRequestParams(); - - // Only one of the titles/pageids/revids is allowed at the same time - $dataSource = null; - if ( isset( $params['titles'] ) ) { - $dataSource = 'titles'; - } - if ( isset( $params['pageids'] ) ) { - if ( isset( $dataSource ) ) { - $this->dieUsage( "Cannot use 'pageids' at the same time as '$dataSource'", 'multisource' ); - } - $dataSource = 'pageids'; - } - if ( isset( $params['revids'] ) ) { - if ( isset( $dataSource ) ) { - $this->dieUsage( "Cannot use 'revids' at the same time as '$dataSource'", 'multisource' ); - } - $dataSource = 'revids'; - } - - switch ( $dataSource ) { - case 'titles': - $this->initFromTitles( $params['titles'] ); - break; - case 'pageids': - $this->initFromPageIds( $params['pageids'] ); - break; - case 'revids': - if ( $this->mResolveRedirects ) { - $this->setWarning( 'Redirect resolution cannot be used together with the revids= parameter. ' . - 'Any redirects the revids= point to have not been resolved.' ); - } - $this->mResolveRedirects = false; - $this->initFromRevIDs( $params['revids'] ); - break; - default: - // Do nothing - some queries do not need any of the data sources. - break; - } - $this->profileOut(); - } - - /** * Populate this PageSet from a list of Titles - * @param $titles array of Title objects + * @param array $titles of Title objects */ public function populateFromTitles( $titles ) { $this->profileIn(); @@ -332,7 +547,7 @@ class ApiPageSet extends ApiQueryBase { /** * Populate this PageSet from a list of page IDs - * @param $pageIDs array of page IDs + * @param array $pageIDs of page IDs */ public function populateFromPageIDs( $pageIDs ) { $this->profileIn(); @@ -353,7 +568,7 @@ class ApiPageSet extends ApiQueryBase { /** * Populate this PageSet from a list of revision IDs - * @param $revIDs array of revision IDs + * @param array $revIDs of revision IDs */ public function populateFromRevisionIDs( $revIDs ) { $this->profileIn(); @@ -385,12 +600,11 @@ class ApiPageSet extends ApiQueryBase { } /** - * Resolve redirects, if applicable + * Do not use, does nothing, will be removed + * @deprecated 1.21 */ public function finishPageSetGeneration() { - $this->profileIn(); - $this->resolvePendingRedirects(); - $this->profileOut(); + wfDeprecated( __METHOD__, '1.21' ); } /** @@ -407,7 +621,7 @@ class ApiPageSet extends ApiQueryBase { * #5 Substitute the original LinkBatch object with the new list * #6 Repeat from step #1 * - * @param $titles array of Title objects or strings + * @param array $titles of Title objects or strings */ private function initFromTitles( $titles ) { // Get validated and normalized title objects @@ -434,10 +648,10 @@ class ApiPageSet extends ApiQueryBase { /** * Does the same as initFromTitles(), but is based on page IDs instead - * @param $pageids array of page IDs + * @param array $pageids of page IDs */ private function initFromPageIds( $pageids ) { - if ( !count( $pageids ) ) { + if ( !$pageids ) { return; } @@ -447,7 +661,7 @@ class ApiPageSet extends ApiQueryBase { $pageids = self::getPositiveIntegers( $pageids ); $res = null; - if ( count( $pageids ) ) { + if ( !empty( $pageids ) ) { $set = array( 'page_id' => $pageids ); @@ -460,7 +674,7 @@ class ApiPageSet extends ApiQueryBase { $this->profileDBOut(); } - $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs + $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs // Resolve any found redirects $this->resolvePendingRedirects(); @@ -470,9 +684,9 @@ class ApiPageSet extends ApiQueryBase { * Iterate through the result of the query on 'page' table, * and for each row create and store title object and save any extra fields requested. * @param $res ResultWrapper DB Query result - * @param $remaining array of either pageID or ns/title elements (optional). + * @param array $remaining of either pageID or ns/title elements (optional). * If given, any missing items will go to $mMissingPageIDs and $mMissingTitles - * @param $processTitles bool Must be provided together with $remaining. + * @param bool $processTitles Must be provided together with $remaining. * If true, treat $remaining as an array of [ns][title] * If false, treat it as an array of [pageIDs] */ @@ -499,7 +713,7 @@ class ApiPageSet extends ApiQueryBase { $this->processDbRow( $row ); // Need gender information - if( MWNamespace::hasGenderDistinction( $row->page_namespace ) ) { + if ( MWNamespace::hasGenderDistinction( $row->page_namespace ) ) { $usernames[] = $row->page_title; } } @@ -518,7 +732,7 @@ class ApiPageSet extends ApiQueryBase { $this->mTitles[] = $title; // need gender information - if( MWNamespace::hasGenderDistinction( $ns ) ) { + if ( MWNamespace::hasGenderDistinction( $ns ) ) { $usernames[] = $dbkey; } } @@ -541,10 +755,10 @@ class ApiPageSet extends ApiQueryBase { /** * Does the same as initFromTitles(), but is based on revision IDs * instead - * @param $revids array of revision IDs + * @param array $revids of revision IDs */ private function initFromRevIDs( $revids ) { - if ( !count( $revids ) ) { + if ( !$revids ) { return; } @@ -555,14 +769,14 @@ class ApiPageSet extends ApiQueryBase { $revids = self::getPositiveIntegers( $revids ); - if ( count( $revids ) ) { + if ( !empty( $revids ) ) { $tables = array( 'revision', 'page' ); $fields = array( 'rev_id', 'rev_page' ); $where = array( 'rev_id' => $revids, 'rev_page = page_id' ); // Get pageIDs data from the `page` table $this->profileDBIn(); - $res = $db->select( $tables, $fields, $where, __METHOD__ ); + $res = $db->select( $tables, $fields, $where, __METHOD__ ); foreach ( $res as $row ) { $revid = intval( $row->rev_id ); $pageid = intval( $row->rev_page ); @@ -670,44 +884,63 @@ class ApiPageSet extends ApiQueryBase { } /** + * Get the cache mode for the data generated by this module. + * All PageSet users should take into account whether this returns a more-restrictive + * cache mode than the using module itself. For possible return values and other + * details about cache modes, see ApiMain::setCacheMode() + * + * Public caching will only be allowed if *all* the modules that supply + * data for a given request return a cache mode of public. + * + * @param $params + * @return string + * @since 1.21 + */ + public function getCacheMode( $params = null ) { + return $this->mCacheMode; + } + + /** * Given an array of title strings, convert them into Title objects. - * Alternativelly, an array of Title objects may be given. + * Alternatively, an array of Title objects may be given. * This method validates access rights for the title, * and appends normalization values to the output. * - * @param $titles array of Title objects or strings + * @param array $titles of Title objects or strings * @return LinkBatch */ private function processTitlesArray( $titles ) { - $genderCache = GenderCache::singleton(); - $genderCache->doTitlesArray( $titles, __METHOD__ ); - + $usernames = array(); $linkBatch = new LinkBatch(); foreach ( $titles as $title ) { - $titleObj = is_string( $title ) ? Title::newFromText( $title ) : $title; + if ( is_string( $title ) ) { + $titleObj = Title::newFromText( $title, $this->mDefaultNamespace ); + } else { + $titleObj = $title; + } if ( !$titleObj ) { // Handle invalid titles gracefully - $this->mAllpages[0][$title] = $this->mFakePageId; + $this->mAllPages[0][$title] = $this->mFakePageId; $this->mInvalidTitles[$this->mFakePageId] = $title; $this->mFakePageId--; continue; // There's nothing else we can do } $unconvertedTitle = $titleObj->getPrefixedText(); $titleWasConverted = false; - $iw = $titleObj->getInterwiki(); - if ( strval( $iw ) !== '' ) { + if ( $titleObj->isExternal() ) { // This title is an interwiki link. - $this->mInterwikiTitles[$titleObj->getPrefixedText()] = $iw; + $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki(); } else { // Variants checking global $wgContLang; if ( $this->mConvertTitles && - count( $wgContLang->getVariants() ) > 1 && + count( $wgContLang->getVariants() ) > 1 && !$titleObj->exists() ) { - // Language::findVariantLink will modify titleObj into + // Language::findVariantLink will modify titleText and titleObj into // the canonical variant if possible - $wgContLang->findVariantLink( $title, $titleObj ); + $titleText = is_string( $title ) ? $title : $titleObj->getPrefixedText(); + $wgContLang->findVariantLink( $titleText, $titleObj ); $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText(); } @@ -728,16 +961,36 @@ class ApiPageSet extends ApiQueryBase { // namespace is localized or the capitalization is // different if ( $titleWasConverted ) { - $this->mConvertedTitles[$title] = $titleObj->getPrefixedText(); + $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText(); + // In this case the page can't be Special. + if ( is_string( $title ) && $title !== $unconvertedTitle ) { + $this->mNormalizedTitles[$title] = $unconvertedTitle; + } } elseif ( is_string( $title ) && $title !== $titleObj->getPrefixedText() ) { $this->mNormalizedTitles[$title] = $titleObj->getPrefixedText(); } + + // Need gender information + if ( MWNamespace::hasGenderDistinction( $titleObj->getNamespace() ) ) { + $usernames[] = $titleObj->getText(); + } } + // Get gender information + $genderCache = GenderCache::singleton(); + $genderCache->doQuery( $usernames, __METHOD__ ); return $linkBatch; } /** + * Get the database connection (read-only) + * @return DatabaseBase + */ + protected function getDB() { + return $this->mDbSource->getDB(); + } + + /** * Returns the input array of integers with all values < 0 removed * * @param $array array @@ -747,7 +1000,7 @@ class ApiPageSet extends ApiQueryBase { // bug 25734 API: possible issue with revids validation // It seems with a load of revision rows, MySQL gets upset // Remove any < 0 integers, as they can't be valid - foreach( $array as $i => $int ) { + foreach ( $array as $i => $int ) { if ( $int < 0 ) { unset( $array[$i] ); } @@ -756,8 +1009,8 @@ class ApiPageSet extends ApiQueryBase { return $array; } - public function getAllowedParams() { - return array( + public function getAllowedParams( $flags = 0 ) { + $result = array( 'titles' => array( ApiBase::PARAM_ISMULTI => true ), @@ -768,15 +1021,59 @@ class ApiPageSet extends ApiQueryBase { 'revids' => array( ApiBase::PARAM_TYPE => 'integer', ApiBase::PARAM_ISMULTI => true - ) + ), + 'redirects' => false, + 'converttitles' => false, ); + if ( $this->mAllowGenerator ) { + if ( $flags & ApiBase::GET_VALUES_FOR_HELP ) { + $result['generator'] = array( + ApiBase::PARAM_TYPE => $this->getGenerators() + ); + } else { + $result['generator'] = null; + } + } + return $result; + } + + private static $generators = null; + + /** + * Get an array of all available generators + * @return array + */ + private function getGenerators() { + if ( self::$generators === null ) { + $query = $this->mDbSource; + if ( !( $query instanceof ApiQuery ) ) { + // If the parent container of this pageset is not ApiQuery, + // we must create it to get module manager + $query = $this->getMain()->getModuleManager()->getModule( 'query' ); + } + $gens = array(); + $mgr = $query->getModuleManager(); + foreach ( $mgr->getNamesWithClasses() as $name => $class ) { + if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) { + $gens[] = $name; + } + } + sort( $gens ); + self::$generators = $gens; + } + return self::$generators; } public function getParamDescription() { return array( 'titles' => 'A list of titles to work on', 'pageids' => 'A list of page IDs to work on', - 'revids' => 'A list of revision IDs to work on' + 'revids' => 'A list of revision IDs to work on', + 'generator' => array( 'Get the list of pages to work on by executing the specified query module.', + '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 ) ), ); } @@ -784,10 +1081,7 @@ class ApiPageSet extends ApiQueryBase { return array_merge( parent::getPossibleErrors(), array( array( 'code' => 'multisource', 'info' => "Cannot use 'pageids' at the same time as 'dataSource'" ), array( 'code' => 'multisource', 'info' => "Cannot use 'revids' at the same time as 'dataSource'" ), + array( 'code' => 'badgenerator', 'info' => 'Module $generatorName cannot be used as a generator' ), ) ); } - - public function getVersion() { - return __CLASS__ . ': $Id$'; - } } |