94 private static function addValues( array &$result, $values, $flags = [], $name =
null ) {
95 foreach ( $values as $val ) {
96 if ( $val instanceof
Title ) {
99 } elseif ( $name !==
null ) {
100 $v = [ $name => $val ];
104 foreach ( $flags as $flag ) {
120 $this->mDbSource = $dbSource;
122 $this->mDefaultNamespace = $defaultNamespace;
125 $this->mResolveRedirects = $this->mParams[
'redirects'];
126 $this->mConvertTitles = $this->mParams[
'converttitles'];
150 $generatorName = $this->mAllowGenerator ? $this->mParams[
'generator'] :
null;
151 if ( isset( $generatorName ) ) {
153 if ( !$dbSource instanceof
ApiQuery ) {
155 $dbSource = $this->
getMain()->getModuleManager()->getModule(
'query' );
157 $generator = $dbSource->getModuleManager()->getModule( $generatorName,
null,
true );
159 $this->
dieWithError( [
'apierror-badgenerator-unknown', $generatorName ],
'badgenerator' );
162 $this->
dieWithError( [
'apierror-badgenerator-notgenerator', $generatorName ],
'badgenerator' );
166 $tmpPageSet =
new ApiPageSet( $dbSource, self::DISABLE_GENERATORS );
173 $tmpPageSet->executeInternal( $isDryRun );
185 foreach (
$generator->extractRequestParams() as $paramName => $param ) {
186 $main->markParamsUsed(
$generator->encodeParamName( $paramName ) );
196 if ( isset( $this->mParams[
'titles'] ) ) {
197 $dataSource =
'titles';
199 if ( isset( $this->mParams[
'pageids'] ) ) {
200 if ( isset( $dataSource ) ) {
203 'apierror-invalidparammix-cannotusewith',
210 $dataSource =
'pageids';
212 if ( isset( $this->mParams[
'revids'] ) ) {
213 if ( isset( $dataSource ) ) {
216 'apierror-invalidparammix-cannotusewith',
223 $dataSource =
'revids';
228 switch ( $dataSource ) {
236 if ( $this->mResolveRedirects ) {
237 $this->
addWarning(
'apiwarn-redirectsandrevids' );
239 $this->mResolveRedirects =
false;
267 if ( $this->mAllowGenerator && isset( $this->mParams[
'generator'] ) ) {
270 if ( isset( $this->mParams[
'titles'] ) ) {
273 if ( isset( $this->mParams[
'pageids'] ) ) {
276 if ( isset( $this->mParams[
'revids'] ) ) {
289 $this->mRequestedPageFields[$fieldName] =
null;
299 return $this->mRequestedPageFields[$fieldName];
312 'page_namespace' =>
null,
313 'page_title' =>
null,
317 if ( $this->mResolveRedirects ) {
318 $pageFlds[
'page_is_redirect'] =
null;
321 if ( $this->
getConfig()->
get(
'ContentHandlerUseDB' ) ) {
322 $pageFlds[
'page_content_model'] =
null;
325 if ( $this->
getConfig()->
get(
'PageLanguageUseDB' ) ) {
326 $pageFlds[
'page_lang'] =
null;
330 $pageFlds[$field] =
null;
333 $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
335 return array_keys( $pageFlds );
361 return count( $this->mTitles );
385 return count( $this->mGoodTitles );
459 'from' => strval( $titleStrFrom ),
460 'to' => $titleTo->getPrefixedText(),
462 if ( $titleTo->hasFragment() ) {
463 $r[
'tofragment'] = $titleTo->getFragment();
465 if ( $titleTo->isExternal() ) {
466 $r[
'tointerwiki'] = $titleTo->getInterwiki();
468 if ( isset( $this->mResolvedRedirectTitles[$titleStrFrom] ) ) {
469 $titleFrom = $this->mResolvedRedirectTitles[$titleStrFrom];
470 $ns = $titleFrom->getNamespace();
471 $dbkey = $titleFrom->getDBkey();
472 if ( isset( $this->mGeneratorData[$ns][$dbkey] ) ) {
473 $r = array_merge( $this->mGeneratorData[$ns][$dbkey], $r );
479 if ( !empty( $values ) && $result ) {
504 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
506 $encode = $contLang->normalize( $rawTitleStr ) !== $rawTitleStr;
508 'fromencoded' => $encode,
509 'from' => $encode ? rawurlencode( $rawTitleStr ) : $rawTitleStr,
513 if ( !empty( $values ) && $result ) {
540 'from' => $rawTitleStr,
544 if ( !empty( $values ) && $result ) {
572 'title' => $rawTitleStr,
573 'iw' => $interwikiStr,
581 if ( !empty( $values ) && $result ) {
603 'special',
'missingIds',
'missingRevIds',
'missingTitles',
'interwikiTitles' ]
606 if ( in_array(
'invalidTitles', $invalidChecks ) ) {
609 if ( in_array(
'special', $invalidChecks ) ) {
613 if (
$title->isKnown() ) {
622 if ( in_array(
'missingIds', $invalidChecks ) ) {
625 if ( in_array(
'missingRevIds', $invalidChecks ) ) {
628 if ( in_array(
'missingTitles', $invalidChecks ) ) {
632 if (
$title->isKnown() ) {
641 if ( in_array(
'interwikiTitles', $invalidChecks ) ) {
693 if ( !empty( $values ) && $result ) {
761 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
762 $linkCache->addGoodLinkObjFromRow(
$title, $row );
764 $pageId = (int)$row->page_id;
765 $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
766 $this->mTitles[] =
$title;
768 if ( $this->mResolveRedirects && $row->page_is_redirect ==
'1' ) {
769 $this->mPendingRedirectIDs[$pageId] =
$title;
771 $this->mGoodPages[$row->page_namespace][$row->page_title] = $pageId;
772 $this->mGoodAndMissingPages[$row->page_namespace][$row->page_title] = $pageId;
773 $this->mGoodTitles[$pageId] =
$title;
776 foreach ( $this->mRequestedPageFields as $fieldName => &$fieldValues ) {
777 $fieldValues[$pageId] = $row->$fieldName;
800 if ( $linkBatch->isEmpty() ) {
806 $db = $this->
getDB();
807 $set = $linkBatch->constructSet(
'page', $db );
830 $pageids = array_map(
'intval', $pageids );
831 $remaining = array_flip( $pageids );
834 $pageids = $this->
filterIDs( [ [
'page',
'page_id' ] ], $pageids );
838 if ( !empty( $pageids ) ) {
840 'page_id' => $pageids
842 $db = $this->
getDB();
866 if ( !is_null( $remaining ) && is_null( $processTitles ) ) {
867 ApiBase::dieDebug( __METHOD__,
'Missing $processTitles parameter when $remaining is provided' );
870 $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
874 foreach (
$res as $row ) {
875 $pageId = (int)$row->page_id;
878 if ( isset( $remaining ) ) {
879 if ( $processTitles ) {
880 unset( $remaining[$row->page_namespace][$row->page_title] );
882 unset( $remaining[$pageId] );
890 if ( $nsInfo->hasGenderDistinction( $row->page_namespace ) ) {
891 $usernames[] = $row->page_title;
896 if ( isset( $remaining ) ) {
898 if ( $processTitles ) {
900 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
901 foreach ( $remaining as $ns => $dbkeys ) {
902 foreach ( array_keys( $dbkeys ) as $dbkey ) {
904 $linkCache->addBadLinkObj(
$title );
909 $this->mFakePageId--;
910 $this->mTitles[] =
$title;
913 if ( $nsInfo->hasGenderDistinction( $ns ) ) {
914 $usernames[] = $dbkey;
920 if ( !$this->mMissingPageIDs ) {
921 $this->mMissingPageIDs = array_keys( $remaining );
923 $this->mMissingPageIDs = array_merge( $this->mMissingPageIDs, array_keys( $remaining ) );
929 $genderCache = MediaWikiServices::getInstance()->getGenderCache();
930 $genderCache->doQuery( $usernames, __METHOD__ );
943 $revids = array_map(
'intval', $revids );
944 $db = $this->
getDB();
946 $remaining = array_flip( $revids );
948 $revids = $this->
filterIDs( [ [
'revision',
'rev_id' ], [
'archive',
'ar_rev_id' ] ], $revids );
949 $goodRemaining = array_flip( $revids );
952 $tables = [
'revision',
'page' ];
953 $fields = [
'rev_id',
'rev_page' ];
954 $where = [
'rev_id' => $revids,
'rev_page = page_id' ];
957 $res = $db->select( $tables, $fields, $where, __METHOD__ );
958 foreach (
$res as $row ) {
959 $revid = (int)$row->rev_id;
960 $pageid = (
int)$row->rev_page;
961 $this->mGoodRevIDs[$revid] = $pageid;
962 $this->mLiveRevIDs[$revid] = $pageid;
963 $pageids[$pageid] =
'';
964 unset( $remaining[$revid] );
965 unset( $goodRemaining[$revid] );
975 if ( $goodRemaining &&
977 $tables = [
'archive' ];
978 $fields = [
'ar_rev_id',
'ar_namespace',
'ar_title' ];
979 $where = [
'ar_rev_id' => array_keys( $goodRemaining ) ];
981 $res = $db->select( $tables, $fields, $where, __METHOD__ );
983 foreach (
$res as $row ) {
984 $revid = (int)$row->ar_rev_id;
986 unset( $remaining[$revid] );
991 foreach ( $titles as $revid =>
$title ) {
992 $ns =
$title->getNamespace();
993 $dbkey =
$title->getDBkey();
996 if ( !isset( $this->mAllPages[$ns][$dbkey] ) &&
997 isset( $this->mConvertedTitles[
$title->getPrefixedText()] )
1000 $ns =
$title->getNamespace();
1001 $dbkey =
$title->getDBkey();
1004 if ( isset( $this->mAllPages[$ns][$dbkey] ) ) {
1005 $this->mGoodRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1006 $this->mDeletedRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1008 $remaining[$revid] =
true;
1013 $this->mMissingRevIDs = array_keys( $remaining );
1022 if ( $this->mResolveRedirects ) {
1023 $db = $this->
getDB();
1028 while ( $this->mPendingRedirectIDs || $this->mPendingRedirectSpecialPages ) {
1033 if ( $linkBatch->isEmpty() ) {
1037 $set = $linkBatch->constructSet(
'page', $db );
1038 if ( $set ===
false ) {
1043 $res = $db->select(
'page', $pageFlds, $set, __METHOD__ );
1059 $titlesToResolve = [];
1060 $db = $this->
getDB();
1062 if ( $this->mPendingRedirectIDs ) {
1071 ], [
'rd_from' => array_keys( $this->mPendingRedirectIDs ) ],
1074 foreach (
$res as $row ) {
1075 $rdfrom = (int)$row->rd_from;
1076 $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
1083 $this->mResolvedRedirectTitles[$from] = $this->mPendingRedirectIDs[$rdfrom];
1084 unset( $this->mPendingRedirectIDs[$rdfrom] );
1085 if ( $to->isExternal() ) {
1086 $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1087 } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1088 $titlesToResolve[] = $to;
1090 $this->mRedirectTitles[$from] = $to;
1093 if ( $this->mPendingRedirectIDs ) {
1096 foreach ( $this->mPendingRedirectIDs as $id =>
$title ) {
1098 $rt = $page->insertRedirect();
1103 if ( $rt->isExternal() ) {
1104 $this->mInterwikiTitles[$rt->getPrefixedText()] = $rt->getInterwiki();
1105 } elseif ( !isset( $this->mAllPages[$rt->getNamespace()][$rt->getDBkey()] ) ) {
1106 $titlesToResolve[] = $rt;
1108 $from =
$title->getPrefixedText();
1109 $this->mResolvedRedirectTitles[$from] =
$title;
1110 $this->mRedirectTitles[$from] = $rt;
1111 unset( $this->mPendingRedirectIDs[$id] );
1116 if ( $this->mPendingRedirectSpecialPages ) {
1117 foreach ( $this->mPendingRedirectSpecialPages as $key => list( $from, $to ) ) {
1118 $fromKey = $from->getPrefixedText();
1119 $this->mResolvedRedirectTitles[$fromKey] = $from;
1120 $this->mRedirectTitles[$fromKey] = $to;
1121 if ( $to->isExternal() ) {
1122 $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1123 } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1124 $titlesToResolve[] = $to;
1127 $this->mPendingRedirectSpecialPages = [];
1131 $this->mCacheMode =
'private';
1166 $services = MediaWikiServices::getInstance();
1167 $contLang = $services->getContentLanguage();
1170 foreach ( $titles as $index =>
$title ) {
1171 if ( is_string(
$title ) ) {
1176 if ( !isset( $this->mAllPages[0][
$title] ) ) {
1180 'invalidreason' => $this->
getErrorFormatter()->formatException( $ex, [
'bc' =>
true ] ),
1182 $this->mFakePageId--;
1190 $titleObjects[$index] = $titleObj;
1194 $genderCache = $services->getGenderCache();
1195 $genderCache->doTitlesArray( $titleObjects, __METHOD__ );
1197 foreach ( $titleObjects as $index => $titleObj ) {
1198 $title = is_string( $titles[$index] ) ? $titles[$index] :
false;
1199 $unconvertedTitle = $titleObj->getPrefixedText();
1200 $titleWasConverted =
false;
1201 if ( $titleObj->isExternal() ) {
1203 $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
1207 $this->mConvertTitles && $contLang->hasVariants() && !$titleObj->exists()
1211 $titleText =
$title !==
false ?
$title : $titleObj->getPrefixedText();
1212 $contLang->findVariantLink( $titleText, $titleObj );
1213 $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText();
1216 if ( $titleObj->getNamespace() < 0 ) {
1218 $titleObj = $titleObj->fixSpecialName();
1219 $ns = $titleObj->getNamespace();
1220 $dbkey = $titleObj->getDBkey();
1221 if ( !isset( $this->mAllSpecials[$ns][$dbkey] ) ) {
1224 if ( $ns ===
NS_SPECIAL && $this->mResolveRedirects ) {
1225 $spFactory = $services->getSpecialPageFactory();
1226 $special = $spFactory->getPage( $dbkey );
1234 list( , $subpage ) = $spFactory->resolveAlias( $dbkey );
1235 $target = $special->getRedirect( $subpage );
1239 $this->mPendingRedirectSpecialPages[$dbkey] = [ $titleObj, $target ];
1242 $this->mFakePageId--;
1247 $linkBatch->addObj( $titleObj );
1256 if ( $titleWasConverted ) {
1257 $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText();
1259 if (
$title !==
false &&
$title !== $unconvertedTitle ) {
1260 $this->mNormalizedTitles[
$title] = $unconvertedTitle;
1262 } elseif (
$title !==
false &&
$title !== $titleObj->getPrefixedText() ) {
1263 $this->mNormalizedTitles[
$title] = $titleObj->getPrefixedText();
1286 $ns =
$title->getNamespace();
1287 $dbkey =
$title->getDBkey();
1288 $this->mGeneratorData[$ns][$dbkey] = $data;
1311 $this->mRedirectMergePolicy = $callable;
1336 $data = $result->getResultData(
$path );
1337 if ( $data ===
null ) {
1342 foreach (
$path as $key ) {
1343 if ( !isset( $data[$key] ) ) {
1348 $data = &$data[$key];
1351 foreach ( $this->mGeneratorData as $ns => $dbkeys ) {
1354 foreach ( $this->mSpecialTitles as $id =>
$title ) {
1355 $pages[
$title->getDBkey()] = $id;
1358 if ( !isset( $this->mAllPages[$ns] ) ) {
1362 $pages = $this->mAllPages[$ns];
1364 foreach ( $dbkeys as $dbkey => $genData ) {
1365 if ( !isset( $pages[$dbkey] ) ) {
1369 $pageId = $pages[$dbkey];
1370 if ( !isset( $data[$pageId] ) ) {
1376 $path2 = array_merge(
$path, [ $pageId ] );
1377 foreach ( $genData as $key => $value ) {
1378 if ( !$result->addValue( $path2, $key, $value ) ) {
1383 $data[$pageId] = array_merge( $data[$pageId], $genData );
1389 if ( $this->mRedirectMergePolicy ) {
1390 foreach ( $this->mResolvedRedirectTitles as $titleFrom ) {
1392 while ( isset( $this->mRedirectTitles[$dest->getPrefixedText()] ) ) {
1393 $dest = $this->mRedirectTitles[$dest->getPrefixedText()];
1395 $fromNs = $titleFrom->getNamespace();
1396 $fromDBkey = $titleFrom->getDBkey();
1397 $toPageId = $dest->getArticleID();
1398 if ( isset( $data[$toPageId] ) &&
1399 isset( $this->mGeneratorData[$fromNs][$fromDBkey] )
1403 $data[$toPageId] = call_user_func(
1404 $this->mRedirectMergePolicy,
1406 $this->mGeneratorData[$fromNs][$fromDBkey]
1425 return $this->mDbSource->getDB();
1452 ?
'api-pageset-param-redirects-generator'
1453 :
'api-pageset-param-redirects-nogenerator',
1455 'converttitles' => [
1458 'api-pageset-param-converttitles',
1459 [ Message::listParam( LanguageConverter::$languagesWithVariants,
'text' ) ],
1464 if ( !$this->mAllowGenerator ) {
1465 unset( $result[
'generator'] );
1475 parent::handleParamNormalization( $paramName, $value, $rawValue );
1477 if ( $paramName ===
'titles' ) {
1481 $l = count( $value );
1483 for ( $i = 0; $i < $l; $i++ ) {
1484 if ( $value[$i] !== $rawValue[$i] ) {
1485 $this->mNormalizedTitles[$rawValue[$i]] = $value[$i];
1498 if ( self::$generators ===
null ) {
1500 if ( !( $query instanceof
ApiQuery ) ) {
1503 $query = $this->
getMain()->getModuleManager()->getModule(
'query' );
1506 $prefix = $query->getModulePath() .
'+';
1507 $mgr = $query->getModuleManager();
1508 foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
1509 if ( is_subclass_of( $class, ApiQueryGeneratorBase::class ) ) {
1510 $gens[$name] = $prefix . $name;
1514 self::$generators = $gens;