94 foreach ( $values
as $val ) {
95 if ( $val instanceof
Title ) {
98 } elseif (
$name !==
null ) {
99 $v = [
$name => $val ];
103 foreach ( $flags
as $flag ) {
119 $this->mDbSource = $dbSource;
121 $this->mDefaultNamespace = $defaultNamespace;
124 $this->mResolveRedirects = $this->mParams[
'redirects'];
125 $this->mConvertTitles = $this->mParams[
'converttitles'];
149 $generatorName = $this->mAllowGenerator ? $this->mParams[
'generator'] :
null;
150 if ( isset( $generatorName ) ) {
152 if ( !$dbSource instanceof
ApiQuery ) {
154 $dbSource = $this->
getMain()->getModuleManager()->getModule(
'query' );
156 $generator = $dbSource->getModuleManager()->getModule( $generatorName,
null,
true );
158 $this->
dieWithError( [
'apierror-badgenerator-unknown', $generatorName ],
'badgenerator' );
161 $this->
dieWithError( [
'apierror-badgenerator-notgenerator', $generatorName ],
'badgenerator' );
165 $tmpPageSet =
new ApiPageSet( $dbSource, self::DISABLE_GENERATORS );
172 $tmpPageSet->executeInternal( $isDryRun );
184 foreach (
$generator->extractRequestParams()
as $paramName => $param ) {
185 $main->markParamsUsed(
$generator->encodeParamName( $paramName ) );
195 if ( isset( $this->mParams[
'titles'] ) ) {
196 $dataSource =
'titles';
198 if ( isset( $this->mParams[
'pageids'] ) ) {
199 if ( isset( $dataSource ) ) {
202 'apierror-invalidparammix-cannotusewith',
209 $dataSource =
'pageids';
211 if ( isset( $this->mParams[
'revids'] ) ) {
212 if ( isset( $dataSource ) ) {
215 'apierror-invalidparammix-cannotusewith',
222 $dataSource =
'revids';
227 switch ( $dataSource ) {
235 if ( $this->mResolveRedirects ) {
236 $this->
addWarning(
'apiwarn-redirectsandrevids' );
238 $this->mResolveRedirects =
false;
266 if ( $this->mAllowGenerator && isset( $this->mParams[
'generator'] ) ) {
269 if ( isset( $this->mParams[
'titles'] ) ) {
272 if ( isset( $this->mParams[
'pageids'] ) ) {
275 if ( isset( $this->mParams[
'revids'] ) ) {
288 $this->mRequestedPageFields[$fieldName] =
null;
298 return $this->mRequestedPageFields[$fieldName];
311 'page_namespace' =>
null,
312 'page_title' =>
null,
316 if ( $this->mResolveRedirects ) {
317 $pageFlds[
'page_is_redirect'] =
null;
320 if ( $this->
getConfig()->
get(
'ContentHandlerUseDB' ) ) {
321 $pageFlds[
'page_content_model'] =
null;
324 if ( $this->
getConfig()->
get(
'PageLanguageUseDB' ) ) {
325 $pageFlds[
'page_lang'] =
null;
329 $pageFlds[$field] =
null;
332 $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
334 return array_keys( $pageFlds );
360 return count( $this->mTitles );
384 return count( $this->mGoodTitles );
458 'from' => strval( $titleStrFrom ),
459 'to' => $titleTo->getPrefixedText(),
461 if ( $titleTo->hasFragment() ) {
462 $r[
'tofragment'] = $titleTo->getFragment();
464 if ( $titleTo->isExternal() ) {
465 $r[
'tointerwiki'] = $titleTo->getInterwiki();
467 if ( isset( $this->mResolvedRedirectTitles[$titleStrFrom] ) ) {
468 $titleFrom = $this->mResolvedRedirectTitles[$titleStrFrom];
469 $ns = $titleFrom->getNamespace();
470 $dbkey = $titleFrom->getDBkey();
471 if ( isset( $this->mGeneratorData[$ns][$dbkey] ) ) {
472 $r = array_merge( $this->mGeneratorData[$ns][$dbkey], $r );
478 if ( !empty( $values ) &&
$result ) {
503 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
505 $encode = $contLang->normalize( $rawTitleStr ) !== $rawTitleStr;
507 'fromencoded' => $encode,
508 'from' => $encode ? rawurlencode( $rawTitleStr ) : $rawTitleStr,
512 if ( !empty( $values ) &&
$result ) {
539 'from' => $rawTitleStr,
543 if ( !empty( $values ) &&
$result ) {
571 'title' => $rawTitleStr,
572 'iw' => $interwikiStr,
580 if ( !empty( $values ) &&
$result ) {
602 'special',
'missingIds',
'missingRevIds',
'missingTitles',
'interwikiTitles' ]
605 if ( in_array(
'invalidTitles', $invalidChecks ) ) {
608 if ( in_array(
'special', $invalidChecks ) ) {
612 if ( $title->isKnown() ) {
621 if ( in_array(
'missingIds', $invalidChecks ) ) {
624 if ( in_array(
'missingRevIds', $invalidChecks ) ) {
627 if ( in_array(
'missingTitles', $invalidChecks ) ) {
631 if ( $title->isKnown() ) {
640 if ( in_array(
'interwikiTitles', $invalidChecks ) ) {
692 if ( !empty( $values ) &&
$result ) {
760 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
761 $linkCache->addGoodLinkObjFromRow(
$title, $row );
763 $pageId = (int)$row->page_id;
764 $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
765 $this->mTitles[] =
$title;
767 if ( $this->mResolveRedirects && $row->page_is_redirect ==
'1' ) {
768 $this->mPendingRedirectIDs[$pageId] =
$title;
770 $this->mGoodPages[$row->page_namespace][$row->page_title] = $pageId;
771 $this->mGoodAndMissingPages[$row->page_namespace][$row->page_title] = $pageId;
772 $this->mGoodTitles[$pageId] =
$title;
775 foreach ( $this->mRequestedPageFields
as $fieldName => &$fieldValues ) {
776 $fieldValues[$pageId] = $row->$fieldName;
799 if ( $linkBatch->isEmpty() ) {
805 $db = $this->
getDB();
806 $set = $linkBatch->constructSet(
'page', $db );
829 $pageids = array_map(
'intval', $pageids );
830 $remaining = array_flip( $pageids );
833 $pageids = $this->
filterIDs( [ [
'page',
'page_id' ] ], $pageids );
837 if ( !empty( $pageids ) ) {
839 'page_id' => $pageids
841 $db = $this->
getDB();
865 if ( !is_null( $remaining ) && is_null( $processTitles ) ) {
866 ApiBase::dieDebug( __METHOD__,
'Missing $processTitles parameter when $remaining is provided' );
871 foreach (
$res as $row ) {
872 $pageId = (int)$row->page_id;
875 if ( isset( $remaining ) ) {
876 if ( $processTitles ) {
877 unset( $remaining[$row->page_namespace][$row->page_title] );
879 unset( $remaining[$pageId] );
888 $usernames[] = $row->page_title;
893 if ( isset( $remaining ) ) {
895 if ( $processTitles ) {
897 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
898 foreach ( $remaining
as $ns => $dbkeys ) {
899 foreach ( array_keys( $dbkeys )
as $dbkey ) {
901 $linkCache->addBadLinkObj(
$title );
906 $this->mFakePageId--;
907 $this->mTitles[] =
$title;
911 $usernames[] = $dbkey;
917 if ( !$this->mMissingPageIDs ) {
918 $this->mMissingPageIDs = array_keys( $remaining );
920 $this->mMissingPageIDs = array_merge( $this->mMissingPageIDs, array_keys( $remaining ) );
926 $genderCache = MediaWikiServices::getInstance()->getGenderCache();
927 $genderCache->doQuery( $usernames, __METHOD__ );
940 $revids = array_map(
'intval', $revids );
941 $db = $this->
getDB();
943 $remaining = array_flip( $revids );
945 $revids = $this->
filterIDs( [ [
'revision',
'rev_id' ], [
'archive',
'ar_rev_id' ] ], $revids );
946 $goodRemaining = array_flip( $revids );
949 $tables = [
'revision',
'page' ];
950 $fields = [
'rev_id',
'rev_page' ];
951 $where = [
'rev_id' => $revids,
'rev_page = page_id' ];
954 $res = $db->select(
$tables, $fields, $where, __METHOD__ );
955 foreach (
$res as $row ) {
956 $revid = (int)$row->rev_id;
957 $pageid = (
int)$row->rev_page;
958 $this->mGoodRevIDs[$revid] = $pageid;
959 $this->mLiveRevIDs[$revid] = $pageid;
960 $pageids[$pageid] =
'';
961 unset( $remaining[$revid] );
962 unset( $goodRemaining[$revid] );
972 if ( $goodRemaining && $this->
getUser()->isAllowed(
'deletedhistory' ) ) {
974 $fields = [
'ar_rev_id',
'ar_namespace',
'ar_title' ];
975 $where = [
'ar_rev_id' => array_keys( $goodRemaining ) ];
977 $res = $db->select(
$tables, $fields, $where, __METHOD__ );
979 foreach (
$res as $row ) {
980 $revid = (int)$row->ar_rev_id;
982 unset( $remaining[$revid] );
988 $ns =
$title->getNamespace();
989 $dbkey =
$title->getDBkey();
992 if ( !isset( $this->mAllPages[$ns][$dbkey] ) &&
993 isset( $this->mConvertedTitles[
$title->getPrefixedText()] )
996 $ns =
$title->getNamespace();
997 $dbkey =
$title->getDBkey();
1000 if ( isset( $this->mAllPages[$ns][$dbkey] ) ) {
1001 $this->mGoodRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1002 $this->mDeletedRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1004 $remaining[$revid] =
true;
1009 $this->mMissingRevIDs = array_keys( $remaining );
1018 if ( $this->mResolveRedirects ) {
1019 $db = $this->
getDB();
1024 while ( $this->mPendingRedirectIDs || $this->mPendingRedirectSpecialPages ) {
1029 if ( $linkBatch->isEmpty() ) {
1033 $set = $linkBatch->constructSet(
'page', $db );
1034 if ( $set ===
false ) {
1039 $res = $db->select(
'page', $pageFlds, $set, __METHOD__ );
1055 $titlesToResolve = [];
1056 $db = $this->
getDB();
1058 if ( $this->mPendingRedirectIDs ) {
1067 ], [
'rd_from' => array_keys( $this->mPendingRedirectIDs ) ],
1070 foreach (
$res as $row ) {
1071 $rdfrom = (int)$row->rd_from;
1072 $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
1079 $this->mResolvedRedirectTitles[$from] = $this->mPendingRedirectIDs[$rdfrom];
1080 unset( $this->mPendingRedirectIDs[$rdfrom] );
1081 if ( $to->isExternal() ) {
1082 $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1083 } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1084 $titlesToResolve[] = $to;
1086 $this->mRedirectTitles[$from] = $to;
1089 if ( $this->mPendingRedirectIDs ) {
1092 foreach ( $this->mPendingRedirectIDs
as $id =>
$title ) {
1094 $rt = $page->insertRedirect();
1099 if ( $rt->isExternal() ) {
1100 $this->mInterwikiTitles[$rt->getPrefixedText()] = $rt->getInterwiki();
1101 } elseif ( !isset( $this->mAllPages[$rt->getNamespace()][$rt->getDBkey()] ) ) {
1102 $titlesToResolve[] = $rt;
1104 $from =
$title->getPrefixedText();
1105 $this->mResolvedRedirectTitles[$from] =
$title;
1106 $this->mRedirectTitles[$from] = $rt;
1107 unset( $this->mPendingRedirectIDs[$id] );
1112 if ( $this->mPendingRedirectSpecialPages ) {
1113 foreach ( $this->mPendingRedirectSpecialPages
as $key =>
list( $from, $to ) ) {
1114 $fromKey = $from->getPrefixedText();
1115 $this->mResolvedRedirectTitles[$fromKey] = $from;
1116 $this->mRedirectTitles[$fromKey] = $to;
1117 if ( $to->isExternal() ) {
1118 $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1119 } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1120 $titlesToResolve[] = $to;
1123 $this->mPendingRedirectSpecialPages = [];
1127 $this->mCacheMode =
'private';
1162 $services = MediaWikiServices::getInstance();
1163 $contLang =
$services->getContentLanguage();
1166 if ( is_string(
$title ) ) {
1171 if ( !isset( $this->mAllPages[0][
$title] ) ) {
1175 'invalidreason' => $this->
getErrorFormatter()->formatException( $ex, [
'bc' =>
true ] ),
1177 $this->mFakePageId--;
1184 $unconvertedTitle = $titleObj->getPrefixedText();
1185 $titleWasConverted =
false;
1186 if ( $titleObj->isExternal() ) {
1188 $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
1192 $this->mConvertTitles && $contLang->hasVariants() && !$titleObj->exists()
1196 $titleText = is_string(
$title ) ?
$title : $titleObj->getPrefixedText();
1197 $contLang->findVariantLink( $titleText, $titleObj );
1198 $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText();
1201 if ( $titleObj->getNamespace() < 0 ) {
1203 $titleObj = $titleObj->fixSpecialName();
1204 $ns = $titleObj->getNamespace();
1205 $dbkey = $titleObj->getDBkey();
1206 if ( !isset( $this->mAllSpecials[$ns][$dbkey] ) ) {
1209 if ( $ns ===
NS_SPECIAL && $this->mResolveRedirects ) {
1210 $spFactory =
$services->getSpecialPageFactory();
1211 $special = $spFactory->getPage( $dbkey );
1219 list( , $subpage ) = $spFactory->resolveAlias( $dbkey );
1220 $target = $special->getRedirect( $subpage );
1224 $this->mPendingRedirectSpecialPages[$dbkey] = [ $titleObj, $target ];
1227 $this->mFakePageId--;
1232 $linkBatch->addObj( $titleObj );
1241 if ( $titleWasConverted ) {
1242 $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText();
1244 if ( is_string(
$title ) &&
$title !== $unconvertedTitle ) {
1245 $this->mNormalizedTitles[
$title] = $unconvertedTitle;
1247 } elseif ( is_string(
$title ) &&
$title !== $titleObj->getPrefixedText() ) {
1248 $this->mNormalizedTitles[
$title] = $titleObj->getPrefixedText();
1253 $usernames[] = $titleObj->getText();
1257 $genderCache =
$services->getGenderCache();
1258 $genderCache->doQuery( $usernames, __METHOD__ );
1279 $ns =
$title->getNamespace();
1280 $dbkey =
$title->getDBkey();
1281 $this->mGeneratorData[$ns][$dbkey] =
$data;
1304 $this->mRedirectMergePolicy = $callable;
1330 if (
$data ===
null ) {
1336 if ( !isset(
$data[$key] ) ) {
1344 foreach ( $this->mGeneratorData
as $ns => $dbkeys ) {
1347 foreach ( $this->mSpecialTitles
as $id =>
$title ) {
1348 $pages[
$title->getDBkey()] = $id;
1351 if ( !isset( $this->mAllPages[$ns] ) ) {
1355 $pages = $this->mAllPages[$ns];
1357 foreach ( $dbkeys
as $dbkey => $genData ) {
1358 if ( !isset( $pages[$dbkey] ) ) {
1362 $pageId = $pages[$dbkey];
1363 if ( !isset(
$data[$pageId] ) ) {
1369 $path2 = array_merge(
$path, [ $pageId ] );
1370 foreach ( $genData
as $key =>
$value ) {
1376 $data[$pageId] = array_merge(
$data[$pageId], $genData );
1382 if ( $this->mRedirectMergePolicy ) {
1383 foreach ( $this->mResolvedRedirectTitles
as $titleFrom ) {
1385 while ( isset( $this->mRedirectTitles[$dest->getPrefixedText()] ) ) {
1386 $dest = $this->mRedirectTitles[$dest->getPrefixedText()];
1388 $fromNs = $titleFrom->getNamespace();
1389 $fromDBkey = $titleFrom->getDBkey();
1390 $toPageId = $dest->getArticleID();
1391 if ( isset(
$data[$toPageId] ) &&
1392 isset( $this->mGeneratorData[$fromNs][$fromDBkey] )
1396 $data[$toPageId] = call_user_func(
1397 $this->mRedirectMergePolicy,
1399 $this->mGeneratorData[$fromNs][$fromDBkey]
1418 return $this->mDbSource->getDB();
1445 ?
'api-pageset-param-redirects-generator'
1446 :
'api-pageset-param-redirects-nogenerator',
1448 'converttitles' => [
1451 'api-pageset-param-converttitles',
1452 [ Message::listParam( LanguageConverter::$languagesWithVariants,
'text' ) ],
1457 if ( !$this->mAllowGenerator ) {
1458 unset(
$result[
'generator'] );
1468 parent::handleParamNormalization( $paramName,
$value, $rawValue );
1470 if ( $paramName ===
'titles' ) {
1476 for ( $i = 0; $i < $l; $i++ ) {
1477 if (
$value[$i] !== $rawValue[$i] ) {
1478 $this->mNormalizedTitles[$rawValue[$i]] =
$value[$i];
1491 if ( self::$generators ===
null ) {
1496 $query = $this->
getMain()->getModuleManager()->getModule(
'query' );
1499 $prefix =
$query->getModulePath() .
'+';
1500 $mgr =
$query->getModuleManager();
1501 foreach ( $mgr->getNamesWithClasses()
as $name => $class ) {
1507 self::$generators = $gens;