MediaWiki  master
ApiPageSet.php
Go to the documentation of this file.
1 <?php
30 
45 class ApiPageSet extends ApiBase {
50  private const DISABLE_GENERATORS = 1;
51 
53  private $mDbSource;
54 
56  private $mParams;
57 
60 
62  private $mConvertTitles;
63 
66 
68  private $mAllPages = [];
69 
71  private $mTitles = [];
72 
74  private $mGoodAndMissingPages = [];
75 
77  private $mGoodPages = [];
78 
80  private $mGoodTitles = [];
81 
83  private $mMissingPages = [];
84 
86  private $mMissingTitles = [];
87 
89  private $mInvalidTitles = [];
90 
92  private $mMissingPageIDs = [];
93 
95  private $mRedirectTitles = [];
96 
98  private $mSpecialTitles = [];
99 
101  private $mAllSpecials = [];
102 
104  private $mNormalizedTitles = [];
105 
107  private $mInterwikiTitles = [];
108 
110  private $mPendingRedirectIDs = [];
111 
114 
117 
119  private $mConvertedTitles = [];
120 
122  private $mGoodRevIDs = [];
123 
125  private $mLiveRevIDs = [];
126 
128  private $mDeletedRevIDs = [];
129 
131  private $mMissingRevIDs = [];
132 
134  private $mGeneratorData = [];
135 
137  private $mFakePageId = -1;
138 
140  private $mCacheMode = 'public';
141 
143  private $mRequestedPageFields = [];
144 
147 
150 
152  private static $generators = null;
153 
161  private static function addValues( array &$result, $values, $flags = [], $name = null ) {
162  foreach ( $values as $val ) {
163  if ( $val instanceof Title ) {
164  $v = [];
165  ApiQueryBase::addTitleInfo( $v, $val );
166  } elseif ( $name !== null ) {
167  $v = [ $name => $val ];
168  } else {
169  $v = $val;
170  }
171  foreach ( $flags as $flag ) {
172  $v[$flag] = true;
173  }
174  $result[] = $v;
175  }
176  }
177 
185  public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) {
186  parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() );
187  $this->mDbSource = $dbSource;
188  $this->mAllowGenerator = ( $flags & self::DISABLE_GENERATORS ) == 0;
189  $this->mDefaultNamespace = $defaultNamespace;
190 
191  $this->mParams = $this->extractRequestParams();
192  $this->mResolveRedirects = $this->mParams['redirects'];
193  $this->mConvertTitles = $this->mParams['converttitles'];
194  }
195 
200  public function executeDryRun() {
201  $this->executeInternal( true );
202  }
203 
207  public function execute() {
208  $this->executeInternal( false );
209  }
210 
216  private function executeInternal( $isDryRun ) {
217  $generatorName = $this->mAllowGenerator ? $this->mParams['generator'] : null;
218  if ( isset( $generatorName ) ) {
219  $dbSource = $this->mDbSource;
220  if ( !$dbSource instanceof ApiQuery ) {
221  // If the parent container of this pageset is not ApiQuery, we must create it to run generator
222  $dbSource = $this->getMain()->getModuleManager()->getModule( 'query' );
223  }
224  $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true );
225  if ( $generator === null ) {
226  $this->dieWithError( [ 'apierror-badgenerator-unknown', $generatorName ], 'badgenerator' );
227  }
228  if ( !$generator instanceof ApiQueryGeneratorBase ) {
229  $this->dieWithError( [ 'apierror-badgenerator-notgenerator', $generatorName ], 'badgenerator' );
230  }
231  // Create a temporary pageset to store generator's output,
232  // add any additional fields generator may need, and execute pageset to populate titles/pageids
233  $tmpPageSet = new ApiPageSet( $dbSource, self::DISABLE_GENERATORS );
234  $generator->setGeneratorMode( $tmpPageSet );
235  $this->mCacheMode = $generator->getCacheMode( $generator->extractRequestParams() );
236 
237  if ( !$isDryRun ) {
238  $generator->requestExtraData( $tmpPageSet );
239  }
240  $tmpPageSet->executeInternal( $isDryRun );
241 
242  // populate this pageset with the generator output
243  if ( !$isDryRun ) {
244  $generator->executeGenerator( $this );
245 
246  $this->getHookRunner()->onAPIQueryGeneratorAfterExecute( $generator, $this );
247  } else {
248  // Prevent warnings from being reported on these parameters
249  $main = $this->getMain();
250  foreach ( $generator->extractRequestParams() as $paramName => $param ) {
251  $main->markParamsUsed( $generator->encodeParamName( $paramName ) );
252  }
253  }
254 
255  if ( !$isDryRun ) {
256  $this->resolvePendingRedirects();
257  }
258  } else {
259  // Only one of the titles/pageids/revids is allowed at the same time
260  $dataSource = null;
261  if ( isset( $this->mParams['titles'] ) ) {
262  $dataSource = 'titles';
263  }
264  if ( isset( $this->mParams['pageids'] ) ) {
265  if ( isset( $dataSource ) ) {
266  $this->dieWithError(
267  [
268  'apierror-invalidparammix-cannotusewith',
269  $this->encodeParamName( 'pageids' ),
270  $this->encodeParamName( $dataSource )
271  ],
272  'multisource'
273  );
274  }
275  $dataSource = 'pageids';
276  }
277  if ( isset( $this->mParams['revids'] ) ) {
278  if ( isset( $dataSource ) ) {
279  $this->dieWithError(
280  [
281  'apierror-invalidparammix-cannotusewith',
282  $this->encodeParamName( 'revids' ),
283  $this->encodeParamName( $dataSource )
284  ],
285  'multisource'
286  );
287  }
288  $dataSource = 'revids';
289  }
290 
291  if ( !$isDryRun ) {
292  // Populate page information with the original user input
293  switch ( $dataSource ) {
294  case 'titles':
295  $this->initFromTitles( $this->mParams['titles'] );
296  break;
297  case 'pageids':
298  $this->initFromPageIds( $this->mParams['pageids'] );
299  break;
300  case 'revids':
301  if ( $this->mResolveRedirects ) {
302  $this->addWarning( 'apiwarn-redirectsandrevids' );
303  }
304  $this->mResolveRedirects = false;
305  $this->initFromRevIDs( $this->mParams['revids'] );
306  break;
307  default:
308  // Do nothing - some queries do not need any of the data sources.
309  break;
310  }
311  }
312  }
313  }
314 
319  public function isResolvingRedirects() {
321  }
322 
331  public function getDataSource() {
332  if ( $this->mAllowGenerator && isset( $this->mParams['generator'] ) ) {
333  return 'generator';
334  }
335  if ( isset( $this->mParams['titles'] ) ) {
336  return 'titles';
337  }
338  if ( isset( $this->mParams['pageids'] ) ) {
339  return 'pageids';
340  }
341  if ( isset( $this->mParams['revids'] ) ) {
342  return 'revids';
343  }
344 
345  return null;
346  }
347 
353  public function requestField( $fieldName ) {
354  $this->mRequestedPageFields[$fieldName] = null;
355  }
356 
363  public function getCustomField( $fieldName ) {
364  return $this->mRequestedPageFields[$fieldName];
365  }
366 
373  public function getPageTableFields() {
374  // Ensure we get minimum required fields
375  // DON'T change this order
376  $pageFlds = [
377  'page_namespace' => null,
378  'page_title' => null,
379  'page_id' => null,
380  ];
381 
382  if ( $this->mResolveRedirects ) {
383  $pageFlds['page_is_redirect'] = null;
384  }
385 
386  $pageFlds['page_content_model'] = null;
387 
388  if ( $this->getConfig()->get( 'PageLanguageUseDB' ) ) {
389  $pageFlds['page_lang'] = null;
390  }
391 
392  foreach ( LinkCache::getSelectFields() as $field ) {
393  $pageFlds[$field] = null;
394  }
395 
396  $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
397 
398  return array_keys( $pageFlds );
399  }
400 
407  public function getAllTitlesByNamespace() {
408  return $this->mAllPages;
409  }
410 
419  public function getTitles() {
420  return $this->mTitles;
421  }
422 
431  public function getPages(): array {
432  return $this->mTitles;
433  }
434 
439  public function getTitleCount() {
440  return count( $this->mTitles );
441  }
442 
447  public function getGoodTitlesByNamespace() {
448  return $this->mGoodPages;
449  }
450 
457  public function getGoodTitles() {
458  return $this->mGoodTitles;
459  }
460 
467  public function getGoodPages(): array {
468  return $this->mGoodTitles;
469  }
470 
475  public function getGoodTitleCount() {
476  return count( $this->mGoodTitles );
477  }
478 
484  public function getMissingTitlesByNamespace() {
485  return $this->mMissingPages;
486  }
487 
495  public function getMissingTitles() {
496  return $this->mMissingTitles;
497  }
498 
506  public function getMissingPages(): array {
507  return $this->mMissingTitles;
508  }
509 
516  }
517 
523  public function getGoodAndMissingTitles() {
524  return $this->mGoodTitles + $this->mMissingTitles;
525  }
526 
532  public function getGoodAndMissingPages(): array {
533  return $this->mGoodTitles + $this->mMissingTitles;
534  }
535 
541  public function getInvalidTitlesAndReasons() {
542  return $this->mInvalidTitles;
543  }
544 
549  public function getMissingPageIDs() {
550  return $this->mMissingPageIDs;
551  }
552 
559  public function getRedirectTitles() {
560  return $this->mRedirectTitles;
561  }
562 
569  public function getRedirectTargets(): array {
570  return $this->mRedirectTitles;
571  }
572 
580  public function getRedirectTitlesAsResult( $result = null ) {
581  $values = [];
582  foreach ( $this->getRedirectTitles() as $titleStrFrom => $titleTo ) {
583  $r = [
584  'from' => strval( $titleStrFrom ),
585  'to' => $titleTo->getPrefixedText(),
586  ];
587  if ( $titleTo->hasFragment() ) {
588  $r['tofragment'] = $titleTo->getFragment();
589  }
590  if ( $titleTo->isExternal() ) {
591  $r['tointerwiki'] = $titleTo->getInterwiki();
592  }
593  if ( isset( $this->mResolvedRedirectTitles[$titleStrFrom] ) ) {
594  $titleFrom = $this->mResolvedRedirectTitles[$titleStrFrom];
595  $ns = $titleFrom->getNamespace();
596  $dbkey = $titleFrom->getDBkey();
597  if ( isset( $this->mGeneratorData[$ns][$dbkey] ) ) {
598  $r = array_merge( $this->mGeneratorData[$ns][$dbkey], $r );
599  }
600  }
601 
602  $values[] = $r;
603  }
604  if ( !empty( $values ) && $result ) {
605  ApiResult::setIndexedTagName( $values, 'r' );
606  }
607 
608  return $values;
609  }
610 
616  public function getNormalizedTitles() {
618  }
619 
627  public function getNormalizedTitlesAsResult( $result = null ) {
628  $values = [];
629  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
630  foreach ( $this->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
631  $encode = $contLang->normalize( $rawTitleStr ) !== $rawTitleStr;
632  $values[] = [
633  'fromencoded' => $encode,
634  'from' => $encode ? rawurlencode( $rawTitleStr ) : $rawTitleStr,
635  'to' => $titleStr
636  ];
637  }
638  if ( !empty( $values ) && $result ) {
639  ApiResult::setIndexedTagName( $values, 'n' );
640  }
641 
642  return $values;
643  }
644 
650  public function getConvertedTitles() {
652  }
653 
661  public function getConvertedTitlesAsResult( $result = null ) {
662  $values = [];
663  foreach ( $this->getConvertedTitles() as $rawTitleStr => $titleStr ) {
664  $values[] = [
665  'from' => $rawTitleStr,
666  'to' => $titleStr
667  ];
668  }
669  if ( !empty( $values ) && $result ) {
670  ApiResult::setIndexedTagName( $values, 'c' );
671  }
672 
673  return $values;
674  }
675 
681  public function getInterwikiTitles() {
683  }
684 
693  public function getInterwikiTitlesAsResult( $result = null, $iwUrl = false ) {
694  $values = [];
695  foreach ( $this->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
696  $item = [
697  'title' => $rawTitleStr,
698  'iw' => $interwikiStr,
699  ];
700  if ( $iwUrl ) {
701  $title = Title::newFromText( $rawTitleStr );
702  $item['url'] = $title->getFullURL( '', false, PROTO_CURRENT );
703  }
704  $values[] = $item;
705  }
706  if ( !empty( $values ) && $result ) {
707  ApiResult::setIndexedTagName( $values, 'i' );
708  }
709 
710  return $values;
711  }
712 
727  public function getInvalidTitlesAndRevisions( $invalidChecks = [ 'invalidTitles',
728  'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles' ]
729  ) {
730  $result = [];
731  if ( in_array( 'invalidTitles', $invalidChecks ) ) {
732  self::addValues( $result, $this->getInvalidTitlesAndReasons(), [ 'invalid' ] );
733  }
734  if ( in_array( 'special', $invalidChecks ) ) {
735  $known = [];
736  $unknown = [];
737  foreach ( $this->getSpecialTitles() as $title ) {
738  if ( $title->isKnown() ) {
739  $known[] = $title;
740  } else {
741  $unknown[] = $title;
742  }
743  }
744  self::addValues( $result, $unknown, [ 'special', 'missing' ] );
745  self::addValues( $result, $known, [ 'special' ] );
746  }
747  if ( in_array( 'missingIds', $invalidChecks ) ) {
748  self::addValues( $result, $this->getMissingPageIDs(), [ 'missing' ], 'pageid' );
749  }
750  if ( in_array( 'missingRevIds', $invalidChecks ) ) {
751  self::addValues( $result, $this->getMissingRevisionIDs(), [ 'missing' ], 'revid' );
752  }
753  if ( in_array( 'missingTitles', $invalidChecks ) ) {
754  $known = [];
755  $unknown = [];
756  foreach ( $this->getMissingTitles() as $title ) {
757  if ( $title->isKnown() ) {
758  $known[] = $title;
759  } else {
760  $unknown[] = $title;
761  }
762  }
763  self::addValues( $result, $unknown, [ 'missing' ] );
764  self::addValues( $result, $known, [ 'missing', 'known' ] );
765  }
766  if ( in_array( 'interwikiTitles', $invalidChecks ) ) {
767  self::addValues( $result, $this->getInterwikiTitlesAsResult() );
768  }
769 
770  return $result;
771  }
772 
777  public function getRevisionIDs() {
778  return $this->mGoodRevIDs;
779  }
780 
785  public function getLiveRevisionIDs() {
786  return $this->mLiveRevIDs;
787  }
788 
793  public function getDeletedRevisionIDs() {
794  return $this->mDeletedRevIDs;
795  }
796 
801  public function getMissingRevisionIDs() {
802  return $this->mMissingRevIDs;
803  }
804 
811  public function getMissingRevisionIDsAsResult( $result = null ) {
812  $values = [];
813  foreach ( $this->getMissingRevisionIDs() as $revid ) {
814  $values[$revid] = [
815  'revid' => $revid
816  ];
817  }
818  if ( !empty( $values ) && $result ) {
819  ApiResult::setIndexedTagName( $values, 'rev' );
820  }
821 
822  return $values;
823  }
824 
830  public function getSpecialTitles() {
831  return $this->mSpecialTitles;
832  }
833 
839  public function getSpecialPages(): array {
840  return $this->mSpecialTitles;
841  }
842 
847  public function getRevisionCount() {
848  return count( $this->getRevisionIDs() );
849  }
850 
855  public function populateFromTitles( $titles ) {
856  $this->initFromTitles( $titles );
857  }
858 
863  public function populateFromPageIDs( $pageIDs ) {
864  $this->initFromPageIds( $pageIDs );
865  }
866 
876  public function populateFromQueryResult( $db, $queryResult ) {
877  $this->initFromQueryResult( $queryResult );
878  }
879 
884  public function populateFromRevisionIDs( $revIDs ) {
885  $this->initFromRevIDs( $revIDs );
886  }
887 
892  public function processDbRow( $row ) {
893  // Store Title object in various data structures
894  $title = Title::newFromRow( $row );
895 
896  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
897  $linkCache->addGoodLinkObjFromRow( $title, $row );
898 
899  $pageId = (int)$row->page_id;
900  $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
901  $this->mTitles[] = $title;
902 
903  if ( $this->mResolveRedirects && $row->page_is_redirect == '1' ) {
904  $this->mPendingRedirectIDs[$pageId] = $title;
905  } else {
906  $this->mGoodPages[$row->page_namespace][$row->page_title] = $pageId;
907  $this->mGoodAndMissingPages[$row->page_namespace][$row->page_title] = $pageId;
908  $this->mGoodTitles[$pageId] = $title;
909  }
910 
911  foreach ( $this->mRequestedPageFields as $fieldName => &$fieldValues ) {
912  $fieldValues[$pageId] = $row->$fieldName;
913  }
914  }
915 
932  private function initFromTitles( $titles ) {
933  // Get validated and normalized title objects
934  $linkBatch = $this->processTitlesArray( $titles );
935  if ( $linkBatch->isEmpty() ) {
936  // There might be special-page redirects
937  $this->resolvePendingRedirects();
938  return;
939  }
940 
941  $db = $this->getDB();
942  $set = $linkBatch->constructSet( 'page', $db );
943 
944  // Get pageIDs data from the `page` table
945  $res = $db->select( 'page', $this->getPageTableFields(), $set,
946  __METHOD__ );
947 
948  // Hack: get the ns:titles stored in [ ns => [ titles ] ] format
949  $this->initFromQueryResult( $res, $linkBatch->data, true ); // process Titles
950 
951  // Resolve any found redirects
952  $this->resolvePendingRedirects();
953  }
954 
960  private function initFromPageIds( $pageids, $filterIds = true ) {
961  if ( !$pageids ) {
962  return;
963  }
964 
965  $pageids = array_map( 'intval', $pageids ); // paranoia
966  $remaining = array_fill_keys( $pageids, true );
967 
968  if ( $filterIds ) {
969  $pageids = $this->filterIDs( [ [ 'page', 'page_id' ] ], $pageids );
970  }
971 
972  $res = null;
973  if ( !empty( $pageids ) ) {
974  $set = [
975  'page_id' => $pageids
976  ];
977  $db = $this->getDB();
978 
979  // Get pageIDs data from the `page` table
980  $res = $db->select( 'page', $this->getPageTableFields(), $set,
981  __METHOD__ );
982  }
983 
984  $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
985 
986  // Resolve any found redirects
987  $this->resolvePendingRedirects();
988  }
989 
1000  private function initFromQueryResult( $res, &$remaining = null, $processTitles = null ) {
1001  if ( $remaining !== null && $processTitles === null ) {
1002  ApiBase::dieDebug( __METHOD__, 'Missing $processTitles parameter when $remaining is provided' );
1003  }
1004 
1005  $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
1006 
1007  $usernames = [];
1008  if ( $res ) {
1009  foreach ( $res as $row ) {
1010  $pageId = (int)$row->page_id;
1011 
1012  // Remove found page from the list of remaining items
1013  if ( $remaining ) {
1014  if ( $processTitles ) {
1015  unset( $remaining[$row->page_namespace][$row->page_title] );
1016  } else {
1017  unset( $remaining[$pageId] );
1018  }
1019  }
1020 
1021  // Store any extra fields requested by modules
1022  $this->processDbRow( $row );
1023 
1024  // Need gender information
1025  if ( $nsInfo->hasGenderDistinction( $row->page_namespace ) ) {
1026  $usernames[] = $row->page_title;
1027  }
1028  }
1029  }
1030 
1031  if ( $remaining ) {
1032  // Any items left in the $remaining list are added as missing
1033  if ( $processTitles ) {
1034  // The remaining titles in $remaining are non-existent pages
1035  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1036  foreach ( $remaining as $ns => $dbkeys ) {
1037  foreach ( array_keys( $dbkeys ) as $dbkey ) {
1038  $title = Title::makeTitle( $ns, $dbkey );
1039  $linkCache->addBadLinkObj( $title );
1040  $this->mAllPages[$ns][$dbkey] = $this->mFakePageId;
1041  $this->mMissingPages[$ns][$dbkey] = $this->mFakePageId;
1042  $this->mGoodAndMissingPages[$ns][$dbkey] = $this->mFakePageId;
1043  $this->mMissingTitles[$this->mFakePageId] = $title;
1044  $this->mFakePageId--;
1045  $this->mTitles[] = $title;
1046 
1047  // need gender information
1048  if ( $nsInfo->hasGenderDistinction( $ns ) ) {
1049  $usernames[] = $dbkey;
1050  }
1051  }
1052  }
1053  } else {
1054  // The remaining pageids do not exist
1055  if ( !$this->mMissingPageIDs ) {
1056  $this->mMissingPageIDs = array_keys( $remaining );
1057  } else {
1058  $this->mMissingPageIDs = array_merge( $this->mMissingPageIDs, array_keys( $remaining ) );
1059  }
1060  }
1061  }
1062 
1063  // Get gender information
1064  $genderCache = MediaWikiServices::getInstance()->getGenderCache();
1065  $genderCache->doQuery( $usernames, __METHOD__ );
1066  }
1067 
1073  private function initFromRevIDs( $revids ) {
1074  if ( !$revids ) {
1075  return;
1076  }
1077 
1078  $revids = array_map( 'intval', $revids ); // paranoia
1079  $db = $this->getDB();
1080  $pageids = [];
1081  $remaining = array_fill_keys( $revids, true );
1082 
1083  $revids = $this->filterIDs( [ [ 'revision', 'rev_id' ], [ 'archive', 'ar_rev_id' ] ], $revids );
1084  $goodRemaining = array_fill_keys( $revids, true );
1085 
1086  if ( $revids ) {
1087  $tables = [ 'revision', 'page' ];
1088  $fields = [ 'rev_id', 'rev_page' ];
1089  $where = [ 'rev_id' => $revids, 'rev_page = page_id' ];
1090 
1091  // Get pageIDs data from the `page` table
1092  $res = $db->select( $tables, $fields, $where, __METHOD__ );
1093  foreach ( $res as $row ) {
1094  $revid = (int)$row->rev_id;
1095  $pageid = (int)$row->rev_page;
1096  $this->mGoodRevIDs[$revid] = $pageid;
1097  $this->mLiveRevIDs[$revid] = $pageid;
1098  $pageids[$pageid] = '';
1099  unset( $remaining[$revid] );
1100  unset( $goodRemaining[$revid] );
1101  }
1102  }
1103 
1104  // Populate all the page information
1105  $this->initFromPageIds( array_keys( $pageids ), false );
1106 
1107  // If the user can see deleted revisions, pull out the corresponding
1108  // titles from the archive table and include them too. We ignore
1109  // ar_page_id because deleted revisions are tied by title, not page_id.
1110  if ( $goodRemaining &&
1111  $this->getAuthority()->isAllowed( 'deletedhistory' ) ) {
1112  $tables = [ 'archive' ];
1113  $fields = [ 'ar_rev_id', 'ar_namespace', 'ar_title' ];
1114  $where = [ 'ar_rev_id' => array_keys( $goodRemaining ) ];
1115 
1116  $res = $db->select( $tables, $fields, $where, __METHOD__ );
1117  $titles = [];
1118  foreach ( $res as $row ) {
1119  $revid = (int)$row->ar_rev_id;
1120  $titles[$revid] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
1121  unset( $remaining[$revid] );
1122  }
1123 
1124  $this->initFromTitles( $titles );
1125 
1126  foreach ( $titles as $revid => $title ) {
1127  $ns = $title->getNamespace();
1128  $dbkey = $title->getDBkey();
1129 
1130  // Handle converted titles
1131  if ( !isset( $this->mAllPages[$ns][$dbkey] ) &&
1132  isset( $this->mConvertedTitles[$title->getPrefixedText()] )
1133  ) {
1134  $title = Title::newFromText( $this->mConvertedTitles[$title->getPrefixedText()] );
1135  $ns = $title->getNamespace();
1136  $dbkey = $title->getDBkey();
1137  }
1138 
1139  if ( isset( $this->mAllPages[$ns][$dbkey] ) ) {
1140  $this->mGoodRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1141  $this->mDeletedRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1142  } else {
1143  $remaining[$revid] = true;
1144  }
1145  }
1146  }
1147 
1148  $this->mMissingRevIDs = array_keys( $remaining );
1149  }
1150 
1156  private function resolvePendingRedirects() {
1157  if ( $this->mResolveRedirects ) {
1158  $db = $this->getDB();
1159  $pageFlds = $this->getPageTableFields();
1160 
1161  // Repeat until all redirects have been resolved
1162  // The infinite loop is prevented by keeping all known pages in $this->mAllPages
1163  while ( $this->mPendingRedirectIDs || $this->mPendingRedirectSpecialPages ) {
1164  // Resolve redirects by querying the pagelinks table, and repeat the process
1165  // Create a new linkBatch object for the next pass
1166  $linkBatch = $this->loadRedirectTargets();
1167 
1168  if ( $linkBatch->isEmpty() ) {
1169  break;
1170  }
1171 
1172  $set = $linkBatch->constructSet( 'page', $db );
1173  if ( $set === false ) {
1174  break;
1175  }
1176 
1177  // Get pageIDs data from the `page` table
1178  $res = $db->select( 'page', $pageFlds, $set, __METHOD__ );
1179 
1180  // Hack: get the ns:titles stored in [ns => array(titles)] format
1181  $this->initFromQueryResult( $res, $linkBatch->data, true );
1182  }
1183  }
1184  }
1185 
1193  private function loadRedirectTargets() {
1194  $titlesToResolve = [];
1195  $db = $this->getDB();
1196 
1197  if ( $this->mPendingRedirectIDs ) {
1198  $res = $db->select(
1199  'redirect',
1200  [
1201  'rd_from',
1202  'rd_namespace',
1203  'rd_fragment',
1204  'rd_interwiki',
1205  'rd_title'
1206  ], [ 'rd_from' => array_keys( $this->mPendingRedirectIDs ) ],
1207  __METHOD__
1208  );
1209  foreach ( $res as $row ) {
1210  $rdfrom = (int)$row->rd_from;
1211  $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
1212  $to = Title::makeTitle(
1213  $row->rd_namespace,
1214  $row->rd_title,
1215  $row->rd_fragment,
1216  $row->rd_interwiki
1217  );
1218  $this->mResolvedRedirectTitles[$from] = $this->mPendingRedirectIDs[$rdfrom];
1219  unset( $this->mPendingRedirectIDs[$rdfrom] );
1220  if ( $to->isExternal() ) {
1221  $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1222  } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1223  $titlesToResolve[] = $to;
1224  }
1225  $this->mRedirectTitles[$from] = $to;
1226  }
1227 
1228  if ( $this->mPendingRedirectIDs ) {
1229  // We found pages that aren't in the redirect table
1230  // Add them
1231  foreach ( $this->mPendingRedirectIDs as $id => $title ) {
1232  $page = WikiPage::factory( $title );
1233  $rt = $page->insertRedirect();
1234  if ( !$rt ) {
1235  // What the hell. Let's just ignore this
1236  continue;
1237  }
1238  if ( $rt->isExternal() ) {
1239  $this->mInterwikiTitles[$rt->getPrefixedText()] = $rt->getInterwiki();
1240  } elseif ( !isset( $this->mAllPages[$rt->getNamespace()][$rt->getDBkey()] ) ) {
1241  $titlesToResolve[] = $rt;
1242  }
1243  $from = $title->getPrefixedText();
1244  $this->mResolvedRedirectTitles[$from] = $title;
1245  $this->mRedirectTitles[$from] = $rt;
1246  unset( $this->mPendingRedirectIDs[$id] );
1247  }
1248  }
1249  }
1250 
1251  if ( $this->mPendingRedirectSpecialPages ) {
1252  foreach ( $this->mPendingRedirectSpecialPages as $key => list( $from, $to ) ) {
1254  $fromKey = $from->getPrefixedText();
1255  $this->mResolvedRedirectTitles[$fromKey] = $from;
1256  $this->mRedirectTitles[$fromKey] = $to;
1257  if ( $to->isExternal() ) {
1258  $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1259  } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1260  $titlesToResolve[] = $to;
1261  }
1262  }
1263  $this->mPendingRedirectSpecialPages = [];
1264 
1265  // Set private caching since we don't know what criteria the
1266  // special pages used to decide on these redirects.
1267  $this->mCacheMode = 'private';
1268  }
1269 
1270  return $this->processTitlesArray( $titlesToResolve );
1271  }
1272 
1286  public function getCacheMode( $params = null ) {
1287  return $this->mCacheMode;
1288  }
1289 
1299  private function processTitlesArray( $titles ) {
1300  $services = MediaWikiServices::getInstance();
1301  $linkBatchFactory = $services->getLinkBatchFactory();
1302  $linkBatch = $linkBatchFactory->newLinkBatch();
1303  $languageConverter = $services
1304  ->getLanguageConverterFactory()
1305  ->getLanguageConverter( $services->getContentLanguage() );
1306 
1307  $titleFactory = $services->getTitleFactory();
1308 
1310  $titleObjects = [];
1311  foreach ( $titles as $index => $title ) {
1312  if ( is_string( $title ) ) {
1313  try {
1315  $titleObj = Title::newFromTextThrow( $title, $this->mDefaultNamespace );
1316  } catch ( MalformedTitleException $ex ) {
1317  // Handle invalid titles gracefully
1318  if ( !isset( $this->mAllPages[0][$title] ) ) {
1319  $this->mAllPages[0][$title] = $this->mFakePageId;
1320  $this->mInvalidTitles[$this->mFakePageId] = [
1321  'title' => $title,
1322  'invalidreason' => $this->getErrorFormatter()->formatException( $ex, [ 'bc' => true ] ),
1323  ];
1324  $this->mFakePageId--;
1325  }
1326  continue; // There's nothing else we can do
1327  }
1328  } elseif ( $title instanceof LinkTarget ) {
1329  $titleObj = $titleFactory->castFromLinkTarget( $title );
1330  } else {
1331  $titleObj = $titleFactory->castFromPageReference( $title );
1332  }
1333 
1334  $titleObjects[$index] = $titleObj;
1335  }
1336 
1337  // Get gender information
1338  $genderCache = $services->getGenderCache();
1339  $genderCache->doTitlesArray( $titleObjects, __METHOD__ );
1340 
1341  foreach ( $titleObjects as $index => $titleObj ) {
1342  $title = is_string( $titles[$index] ) ? $titles[$index] : false;
1343  $unconvertedTitle = $titleObj->getPrefixedText();
1344  $titleWasConverted = false;
1345  if ( $titleObj->isExternal() ) {
1346  // This title is an interwiki link.
1347  $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
1348  } else {
1349  // Variants checking
1350  if (
1351  $this->mConvertTitles
1352  && $languageConverter->hasVariants()
1353  && !$titleObj->exists()
1354  ) {
1355  // ILanguageConverter::findVariantLink will modify titleText and
1356  // titleObj into the canonical variant if possible
1357  $titleText = $title !== false ? $title : $titleObj->getPrefixedText();
1358  $languageConverter->findVariantLink( $titleText, $titleObj );
1359  $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText();
1360  }
1361 
1362  if ( $titleObj->getNamespace() < 0 ) {
1363  // Handle Special and Media pages
1364  $titleObj = $titleObj->fixSpecialName();
1365  $ns = $titleObj->getNamespace();
1366  $dbkey = $titleObj->getDBkey();
1367  if ( !isset( $this->mAllSpecials[$ns][$dbkey] ) ) {
1368  $this->mAllSpecials[$ns][$dbkey] = $this->mFakePageId;
1369  $target = null;
1370  if ( $ns === NS_SPECIAL && $this->mResolveRedirects ) {
1371  $spFactory = $services->getSpecialPageFactory();
1372  $special = $spFactory->getPage( $dbkey );
1373  if ( $special instanceof RedirectSpecialArticle ) {
1374  // Only RedirectSpecialArticle is intended to redirect to an article, other kinds of
1375  // RedirectSpecialPage are probably applying weird URL parameters we don't want to
1376  // handle.
1377  $context = new DerivativeContext( $this );
1378  $context->setTitle( $titleObj );
1379  $context->setRequest( new FauxRequest );
1380  $special->setContext( $context );
1381  list( /* $alias */, $subpage ) = $spFactory->resolveAlias( $dbkey );
1382  $target = $special->getRedirect( $subpage );
1383  }
1384  }
1385  if ( $target ) {
1386  $this->mPendingRedirectSpecialPages[$dbkey] = [ $titleObj, $target ];
1387  } else {
1388  $this->mSpecialTitles[$this->mFakePageId] = $titleObj;
1389  $this->mFakePageId--;
1390  }
1391  }
1392  } else {
1393  // Regular page
1394  $linkBatch->addObj( $titleObj );
1395  }
1396  }
1397 
1398  // Make sure we remember the original title that was
1399  // given to us. This way the caller can correlate new
1400  // titles with the originally requested when e.g. the
1401  // namespace is localized or the capitalization is
1402  // different
1403  if ( $titleWasConverted ) {
1404  $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText();
1405  // In this case the page can't be Special.
1406  if ( $title !== false && $title !== $unconvertedTitle ) {
1407  $this->mNormalizedTitles[$title] = $unconvertedTitle;
1408  }
1409  } elseif ( $title !== false && $title !== $titleObj->getPrefixedText() ) {
1410  $this->mNormalizedTitles[$title] = $titleObj->getPrefixedText();
1411  }
1412  }
1413 
1414  return $linkBatch;
1415  }
1416 
1432  public function setGeneratorData( $title, array $data ) {
1433  $ns = $title->getNamespace();
1434  $dbkey = $title->getDBkey();
1435  $this->mGeneratorData[$ns][$dbkey] = $data;
1436  }
1437 
1457  public function setRedirectMergePolicy( $callable ) {
1458  $this->mRedirectMergePolicy = $callable;
1459  }
1460 
1472  private function resolveRedirectTitleDest( Title $titleFrom ): Title {
1473  $seen = [];
1474  $dest = $titleFrom;
1475  while ( isset( $this->mRedirectTitles[$dest->getPrefixedText()] ) ) {
1476  $dest = $this->mRedirectTitles[$dest->getPrefixedText()];
1477  if ( isset( $seen[$dest->getPrefixedText()] ) ) {
1478  return $titleFrom;
1479  }
1480  $seen[$dest->getPrefixedText()] = true;
1481  }
1482  return $dest;
1483  }
1484 
1505  public function populateGeneratorData( &$result, array $path = [] ) {
1506  if ( $result instanceof ApiResult ) {
1507  $data = $result->getResultData( $path );
1508  if ( $data === null ) {
1509  return true;
1510  }
1511  } else {
1512  $data = &$result;
1513  foreach ( $path as $key ) {
1514  if ( !isset( $data[$key] ) ) {
1515  // Path isn't in $result, so nothing to add, so everything
1516  // "fits"
1517  return true;
1518  }
1519  $data = &$data[$key];
1520  }
1521  }
1522  foreach ( $this->mGeneratorData as $ns => $dbkeys ) {
1523  if ( $ns === NS_SPECIAL ) {
1524  $pages = [];
1525  foreach ( $this->mSpecialTitles as $id => $title ) {
1526  $pages[$title->getDBkey()] = $id;
1527  }
1528  } else {
1529  if ( !isset( $this->mAllPages[$ns] ) ) {
1530  // No known titles in the whole namespace. Skip it.
1531  continue;
1532  }
1533  $pages = $this->mAllPages[$ns];
1534  }
1535  foreach ( $dbkeys as $dbkey => $genData ) {
1536  if ( !isset( $pages[$dbkey] ) ) {
1537  // Unknown title. Forget it.
1538  continue;
1539  }
1540  $pageId = $pages[$dbkey];
1541  if ( !isset( $data[$pageId] ) ) {
1542  // $pageId didn't make it into the result. Ignore it.
1543  continue;
1544  }
1545 
1546  if ( $result instanceof ApiResult ) {
1547  $path2 = array_merge( $path, [ $pageId ] );
1548  foreach ( $genData as $key => $value ) {
1549  if ( !$result->addValue( $path2, $key, $value ) ) {
1550  return false;
1551  }
1552  }
1553  } else {
1554  $data[$pageId] = array_merge( $data[$pageId], $genData );
1555  }
1556  }
1557  }
1558 
1559  // Merge data generated about redirect titles into the redirect destination
1560  if ( $this->mRedirectMergePolicy ) {
1561  foreach ( $this->mResolvedRedirectTitles as $titleFrom ) {
1562  $dest = $this->resolveRedirectTitleDest( $titleFrom );
1563  $fromNs = $titleFrom->getNamespace();
1564  $fromDBkey = $titleFrom->getDBkey();
1565  $toPageId = $dest->getArticleID();
1566  if ( isset( $data[$toPageId] ) &&
1567  isset( $this->mGeneratorData[$fromNs][$fromDBkey] )
1568  ) {
1569  // It is necessary to set both $data and add to $result, if an ApiResult,
1570  // to ensure multiple redirects to the same destination are all merged.
1571  $data[$toPageId] = call_user_func(
1572  $this->mRedirectMergePolicy,
1573  $data[$toPageId],
1574  $this->mGeneratorData[$fromNs][$fromDBkey]
1575  );
1576  if ( $result instanceof ApiResult &&
1577  !$result->addValue( $path, $toPageId, $data[$toPageId], ApiResult::OVERRIDE )
1578  ) {
1579  return false;
1580  }
1581  }
1582  }
1583  }
1584 
1585  return true;
1586  }
1587 
1592  protected function getDB() {
1593  return $this->mDbSource->getDB();
1594  }
1595 
1596  public function getAllowedParams( $flags = 0 ) {
1597  $result = [
1598  'titles' => [
1599  ApiBase::PARAM_ISMULTI => true,
1600  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-titles',
1601  ],
1602  'pageids' => [
1603  ApiBase::PARAM_TYPE => 'integer',
1604  ApiBase::PARAM_ISMULTI => true,
1605  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-pageids',
1606  ],
1607  'revids' => [
1608  ApiBase::PARAM_TYPE => 'integer',
1609  ApiBase::PARAM_ISMULTI => true,
1610  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-revids',
1611  ],
1612  'generator' => [
1613  ApiBase::PARAM_TYPE => null,
1614  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-generator',
1616  ],
1617  'redirects' => [
1618  ApiBase::PARAM_DFLT => false,
1619  ApiBase::PARAM_HELP_MSG => $this->mAllowGenerator
1620  ? 'api-pageset-param-redirects-generator'
1621  : 'api-pageset-param-redirects-nogenerator',
1622  ],
1623  'converttitles' => [
1624  ApiBase::PARAM_DFLT => false,
1626  'api-pageset-param-converttitles',
1628  ],
1629  ],
1630  ];
1631 
1632  if ( !$this->mAllowGenerator ) {
1633  unset( $result['generator'] );
1634  } elseif ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
1635  $result['generator'][ApiBase::PARAM_TYPE] = 'submodule';
1636  $result['generator'][ApiBase::PARAM_SUBMODULE_MAP] = $this->getGenerators();
1637  }
1638 
1639  return $result;
1640  }
1641 
1642  public function handleParamNormalization( $paramName, $value, $rawValue ) {
1643  parent::handleParamNormalization( $paramName, $value, $rawValue );
1644 
1645  if ( $paramName === 'titles' ) {
1646  // For the 'titles' parameter, we want to split it like ApiBase would
1647  // and add any changed titles to $this->mNormalizedTitles
1648  $value = ParamValidator::explodeMultiValue( $value, self::LIMIT_SML2 + 1 );
1649  $l = count( $value );
1650  $rawValue = ParamValidator::explodeMultiValue( $rawValue, $l );
1651  for ( $i = 0; $i < $l; $i++ ) {
1652  if ( $value[$i] !== $rawValue[$i] ) {
1653  $this->mNormalizedTitles[$rawValue[$i]] = $value[$i];
1654  }
1655  }
1656  }
1657  }
1658 
1663  private function getGenerators() {
1664  if ( self::$generators === null ) {
1665  $query = $this->mDbSource;
1666  if ( !( $query instanceof ApiQuery ) ) {
1667  // If the parent container of this pageset is not ApiQuery,
1668  // we must create it to get module manager
1669  $query = $this->getMain()->getModuleManager()->getModule( 'query' );
1670  }
1671  $gens = [];
1672  $prefix = $query->getModulePath() . '+';
1673  $mgr = $query->getModuleManager();
1674  foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
1675  if ( is_subclass_of( $class, ApiQueryGeneratorBase::class ) ) {
1676  $gens[$name] = $prefix . $name;
1677  }
1678  }
1679  ksort( $gens );
1680  self::$generators = $gens;
1681  }
1682 
1683  return self::$generators;
1684  }
1685 }
ApiPageSet\$mPendingRedirectIDs
Title[] $mPendingRedirectIDs
Definition: ApiPageSet.php:110
Page\PageIdentity
Interface for objects (potentially) representing an editable wiki page.
Definition: PageIdentity.php:64
ApiPageSet\getTitleCount
getTitleCount()
Returns the number of unique pages (not revisions) in the set.
Definition: ApiPageSet.php:439
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:39
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:72
ApiBase\PARAM_SUBMODULE_MAP
const PARAM_SUBMODULE_MAP
Definition: ApiBase.php:79
ApiPageSet\initFromTitles
initFromTitles( $titles)
This method populates internal variables with page information based on the given array of title stri...
Definition: ApiPageSet.php:932
ApiPageSet\$mConvertTitles
bool $mConvertTitles
Definition: ApiPageSet.php:62
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:35
ApiPageSet\$mLiveRevIDs
int[] $mLiveRevIDs
Array of revID (int) => pageID (int)
Definition: ApiPageSet.php:125
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:383
ApiPageSet\$mInterwikiTitles
string[] $mInterwikiTitles
Definition: ApiPageSet.php:107
ApiQuery
This is the main query class.
Definition: ApiQuery.php:37
ApiBase\addWarning
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1297
ApiPageSet\processDbRow
processDbRow( $row)
Extract all requested fields from the row received from the database.
Definition: ApiPageSet.php:892
ApiPageSet\resolveRedirectTitleDest
resolveRedirectTitleDest(Title $titleFrom)
Resolve the title a redirect points to.
Definition: ApiPageSet.php:1472
ApiPageSet\getGoodTitleCount
getGoodTitleCount()
Returns the number of found unique pages (not revisions) in the set.
Definition: ApiPageSet.php:475
ApiPageSet\$mSpecialTitles
Title[] $mSpecialTitles
Definition: ApiPageSet.php:98
ApiPageSet\$mGoodAndMissingPages
int[][] $mGoodAndMissingPages
[ns][dbkey] => page_id or negative when missing
Definition: ApiPageSet.php:74
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:193
ApiPageSet\processTitlesArray
processTitlesArray( $titles)
Given an array of title strings, convert them into Title objects.
Definition: ApiPageSet.php:1299
if
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:88
ApiPageSet\getTitles
getTitles()
All existing and missing pages including redirects.
Definition: ApiPageSet.php:419
ApiPageSet\getConvertedTitles
getConvertedTitles()
Get a list of title conversions - maps a title to its converted version.
Definition: ApiPageSet.php:650
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1379
ApiBase\PARAM_HELP_MSG
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:105
ApiPageSet\__construct
__construct(ApiBase $dbSource, $flags=0, $defaultNamespace=NS_MAIN)
Definition: ApiPageSet.php:185
ApiPageSet\getLiveRevisionIDs
getLiveRevisionIDs()
Get the list of non-deleted revision IDs (requested with the revids= parameter)
Definition: ApiPageSet.php:785
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:72
ApiPageSet\$mTitles
Title[] $mTitles
Definition: ApiPageSet.php:71
ApiPageSet\initFromQueryResult
initFromQueryResult( $res, &$remaining=null, $processTitles=null)
Iterate through the result of the query on 'page' table, and for each row create and store title obje...
Definition: ApiPageSet.php:1000
ApiPageSet\requestField
requestField( $fieldName)
Request an additional field from the page table.
Definition: ApiPageSet.php:353
ApiPageSet\execute
execute()
Populate the PageSet from the request parameters.
Definition: ApiPageSet.php:207
Title\getPrefixedText
getPrefixedText()
Get the prefixed title with spaces.
Definition: Title.php:1912
ApiPageSet\$mDefaultNamespace
int $mDefaultNamespace
Definition: ApiPageSet.php:146
ApiPageSet\$mRedirectMergePolicy
callable null $mRedirectMergePolicy
Definition: ApiPageSet.php:149
ApiPageSet\initFromPageIds
initFromPageIds( $pageids, $filterIds=true)
Does the same as initFromTitles(), but is based on page IDs instead.
Definition: ApiPageSet.php:960
ApiPageSet\resolvePendingRedirects
resolvePendingRedirects()
Resolve any redirects in the result if redirect resolution was requested.
Definition: ApiPageSet.php:1156
ApiPageSet\getDeletedRevisionIDs
getDeletedRevisionIDs()
Get the list of revision IDs that were associated with deleted titles.
Definition: ApiPageSet.php:793
ApiPageSet\populateFromRevisionIDs
populateFromRevisionIDs( $revIDs)
Populate this PageSet from a list of revision IDs.
Definition: ApiPageSet.php:884
ApiPageSet\getPages
getPages()
All existing and missing pages including redirects.
Definition: ApiPageSet.php:431
ApiPageSet\addValues
static addValues(array &$result, $values, $flags=[], $name=null)
Add all items from $values into the result.
Definition: ApiPageSet.php:161
$res
$res
Definition: testCompression.php:57
ApiPageSet\getGoodAndMissingTitlesByNamespace
getGoodAndMissingTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good and missing titles.
Definition: ApiPageSet.php:514
ApiPageSet\$mFakePageId
int $mFakePageId
Definition: ApiPageSet.php:137
Page\PageReference
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Definition: PageReference.php:49
ApiPageSet\populateFromTitles
populateFromTitles( $titles)
Populate this PageSet.
Definition: ApiPageSet.php:855
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:382
Message\listParam
static listParam(array $list, $type='text')
Definition: Message.php:1195
ApiPageSet\$mConvertedTitles
string[] $mConvertedTitles
Definition: ApiPageSet.php:119
ApiPageSet
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:45
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:55
ApiPageSet\executeDryRun
executeDryRun()
In case execute() is not called, call this method to mark all relevant parameters as used This preven...
Definition: ApiPageSet.php:200
ApiPageSet\$mMissingTitles
Title[] $mMissingTitles
Definition: ApiPageSet.php:86
ApiPageSet\setGeneratorData
setGeneratorData( $title, array $data)
Set data for a title.
Definition: ApiPageSet.php:1432
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
ApiPageSet\getRedirectTitlesAsResult
getRedirectTitlesAsResult( $result=null)
Get a list of redirect resolutions - maps a title to its redirect target.
Definition: ApiPageSet.php:580
ApiPageSet\getPageTableFields
getPageTableFields()
Get the fields that have to be queried from the page table: the ones requested through requestField()...
Definition: ApiPageSet.php:373
NS_MAIN
const NS_MAIN
Definition: Defines.php:64
ApiPageSet\$mMissingRevIDs
int[] $mMissingRevIDs
Definition: ApiPageSet.php:131
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:53
ApiPageSet\getConvertedTitlesAsResult
getConvertedTitlesAsResult( $result=null)
Get a list of title conversions - maps a title to its converted version as a result array.
Definition: ApiPageSet.php:661
ApiPageSet\getMissingTitles
getMissingTitles()
Title objects that were NOT found in the database.
Definition: ApiPageSet.php:495
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:32
ApiPageSet\$mPendingRedirectSpecialPages
Title[][] $mPendingRedirectSpecialPages
[dbkey] => [ Title $from, Title $to ]
Definition: ApiPageSet.php:113
ApiPageSet\getMissingTitlesByNamespace
getMissingTitlesByNamespace()
Returns an array [ns][dbkey] => fake_page_id for all missing titles.
Definition: ApiPageSet.php:484
ApiPageSet\getSpecialPages
getSpecialPages()
Get the list of pages with negative namespace.
Definition: ApiPageSet.php:839
ApiPageSet\loadRedirectTargets
loadRedirectTargets()
Get the targets of the pending redirects from the database.
Definition: ApiPageSet.php:1193
ApiPageSet\$mResolvedRedirectTitles
Title[] $mResolvedRedirectTitles
Definition: ApiPageSet.php:116
ApiPageSet\$mInvalidTitles
array[] $mInvalidTitles
[fake_page_id] => [ 'title' => $title, 'invalidreason' => $reason ]
Definition: ApiPageSet.php:89
ApiPageSet\populateFromQueryResult
populateFromQueryResult( $db, $queryResult)
Populate this PageSet from a rowset returned from the database.
Definition: ApiPageSet.php:876
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:26
ApiResult
This class represents the result of the API operations.
Definition: ApiResult.php:35
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:580
ApiPageSet\$mGoodRevIDs
int[] $mGoodRevIDs
Array of revID (int) => pageID (int)
Definition: ApiPageSet.php:122
ApiPageSet\getGenerators
getGenerators()
Get an array of all available generators.
Definition: ApiPageSet.php:1663
ApiPageSet\getDataSource
getDataSource()
Return the parameter name that is the source of data for this PageSet.
Definition: ApiPageSet.php:331
ApiPageSet\$mRequestedPageFields
array $mRequestedPageFields
Definition: ApiPageSet.php:143
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:707
ApiPageSet\getRevisionIDs
getRevisionIDs()
Get the list of valid revision IDs (requested with the revids= parameter)
Definition: ApiPageSet.php:777
$generator
$generator
Definition: generateLocalAutoload.php:13
$title
$title
Definition: testCompression.php:38
ApiPageSet\getRedirectTitles
getRedirectTitles()
Get a list of redirect resolutions - maps a title to its redirect target.
Definition: ApiPageSet.php:559
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:651
ApiPageSet\$mAllSpecials
int[][] $mAllSpecials
separate from mAllPages to avoid breaking getAllTitlesByNamespace()
Definition: ApiPageSet.php:101
ApiPageSet\$mDbSource
ApiBase $mDbSource
used for getDb() call
Definition: ApiPageSet.php:53
ApiPageSet\getGoodAndMissingPages
getGoodAndMissingPages()
Pages for good and missing titles.
Definition: ApiPageSet.php:532
ApiPageSet\getGoodTitles
getGoodTitles()
Title objects that were found in the database, including redirects.
Definition: ApiPageSet.php:457
ApiResult\addValue
addValue( $path, $name, $value, $flags=0)
Add value to the output data at the given path.
Definition: ApiResult.php:393
RedirectSpecialArticle
Superclass for any RedirectSpecialPage which redirects the user to a particular article (as opposed t...
Definition: RedirectSpecialArticle.php:89
Title\newFromTextThrow
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid,...
Definition: Title.php:418
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:195
ApiPageSet\$mAllPages
int[][] $mAllPages
[ns][dbkey] => page_id or negative when missing
Definition: ApiPageSet.php:68
ApiPageSet\isResolvingRedirects
isResolvingRedirects()
Check whether this PageSet is resolving redirects.
Definition: ApiPageSet.php:319
ApiPageSet\getGoodAndMissingTitles
getGoodAndMissingTitles()
Title objects for good and missing titles.
Definition: ApiPageSet.php:523
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:603
ApiPageSet\getCacheMode
getCacheMode( $params=null)
Get the cache mode for the data generated by this module.
Definition: ApiPageSet.php:1286
ContextSource\getAuthority
getAuthority()
Definition: ContextSource.php:144
ApiPageSet\initFromRevIDs
initFromRevIDs( $revids)
Does the same as initFromTitles(), but is based on revision IDs instead.
Definition: ApiPageSet.php:1073
ApiBase\encodeParamName
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:685
ApiBase\GET_VALUES_FOR_HELP
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition: ApiBase.php:176
ApiPageSet\getInterwikiTitles
getInterwikiTitles()
Get a list of interwiki titles - maps a title to its interwiki prefix.
Definition: ApiPageSet.php:681
ApiPageSet\getAllTitlesByNamespace
getAllTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all requested titles.
Definition: ApiPageSet.php:407
ApiPageSet\$mMissingPages
int[][] $mMissingPages
[ns][dbkey] => fake page_id
Definition: ApiPageSet.php:83
ApiPageSet\getNormalizedTitlesAsResult
getNormalizedTitlesAsResult( $result=null)
Get a list of title normalizations - maps a title to its normalized version in the form of result arr...
Definition: ApiPageSet.php:627
ApiPageSet\populateFromPageIDs
populateFromPageIDs( $pageIDs)
Populate this PageSet from a list of page IDs.
Definition: ApiPageSet.php:863
ApiPageSet\$mNormalizedTitles
string[] $mNormalizedTitles
Definition: ApiPageSet.php:104
ApiPageSet\getDB
getDB()
Get the database connection (read-only)
Definition: ApiPageSet.php:1592
ApiPageSet\getAllowedParams
getAllowedParams( $flags=0)
Definition: ApiPageSet.php:1596
ApiPageSet\getInterwikiTitlesAsResult
getInterwikiTitlesAsResult( $result=null, $iwUrl=false)
Get a list of interwiki titles - maps a title to its interwiki prefix as result.
Definition: ApiPageSet.php:693
ApiPageSet\getMissingPageIDs
getMissingPageIDs()
Page IDs that were not found in the database.
Definition: ApiPageSet.php:549
ApiPageSet\$mRedirectTitles
Title[] $mRedirectTitles
Definition: ApiPageSet.php:95
ApiPageSet\getRedirectTargets
getRedirectTargets()
Get a list of redirect resolutions - maps a title to its redirect target.
Definition: ApiPageSet.php:569
ApiQueryGeneratorBase
Definition: ApiQueryGeneratorBase.php:28
ApiPageSet\$mAllowGenerator
bool $mAllowGenerator
Definition: ApiPageSet.php:65
Title
Represents a title within MediaWiki.
Definition: Title.php:48
LanguageConverter\$languagesWithVariants
static array $languagesWithVariants
languages supporting variants
Definition: LanguageConverter.php:44
ApiBase\filterIDs
filterIDs( $fields, array $ids)
Filter out-of-range values from a list of positive integer IDs.
Definition: ApiBase.php:1250
ApiPageSet\getMissingRevisionIDsAsResult
getMissingRevisionIDsAsResult( $result=null)
Revision IDs that were not found in the database as result array.
Definition: ApiPageSet.php:811
MalformedTitleException
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Definition: MalformedTitleException.php:26
WikiPage\factory
static factory(PageIdentity $pageIdentity)
Create a WikiPage object of the appropriate class for the given PageIdentity.
Definition: WikiPage.php:200
ApiPageSet\getInvalidTitlesAndRevisions
getInvalidTitlesAndRevisions( $invalidChecks=[ 'invalidTitles', 'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles'])
Get an array of invalid/special/missing titles.
Definition: ApiPageSet.php:727
ApiPageSet\getGoodTitlesByNamespace
getGoodTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good titles.
Definition: ApiPageSet.php:447
ApiPageSet\executeInternal
executeInternal( $isDryRun)
Populate the PageSet from the request parameters.
Definition: ApiPageSet.php:216
ApiPageSet\handleParamNormalization
handleParamNormalization( $paramName, $value, $rawValue)
Handle when a parameter was Unicode-normalized.
Definition: ApiPageSet.php:1642
ApiPageSet\setRedirectMergePolicy
setRedirectMergePolicy( $callable)
Controls how generator data about a redirect source is merged into the generator data for the redirec...
Definition: ApiPageSet.php:1457
$path
$path
Definition: NoLocalSettings.php:25
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:70
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:440
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:71
ApiPageSet\getMissingRevisionIDs
getMissingRevisionIDs()
Revision IDs that were not found in the database.
Definition: ApiPageSet.php:801
ApiResult\OVERRIDE
const OVERRIDE
Override existing value in addValue(), setValue(), and similar functions.
Definition: ApiResult.php:41
ApiPageSet\$mGoodTitles
Title[] $mGoodTitles
Definition: ApiPageSet.php:80
ApiPageSet\getInvalidTitlesAndReasons
getInvalidTitlesAndReasons()
Titles that were deemed invalid by Title::newFromText() The array's index will be unique and negative...
Definition: ApiPageSet.php:541
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:456
ApiPageSet\$mDeletedRevIDs
int[] $mDeletedRevIDs
Array of revID (int) => pageID (int)
Definition: ApiPageSet.php:128
ApiPageSet\$mResolveRedirects
bool $mResolveRedirects
Definition: ApiPageSet.php:59
ApiPageSet\getCustomField
getCustomField( $fieldName)
Get the value of a custom field previously requested through requestField()
Definition: ApiPageSet.php:363
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
ApiPageSet\getRevisionCount
getRevisionCount()
Returns the number of revisions (requested with revids= parameter).
Definition: ApiPageSet.php:847
ApiBase\PARAM_SUBMODULE_PARAM_PREFIX
const PARAM_SUBMODULE_PARAM_PREFIX
Definition: ApiBase.php:80
ApiPageSet\getGoodPages
getGoodPages()
Pages that were found in the database, including redirects.
Definition: ApiPageSet.php:467
ApiPageSet\DISABLE_GENERATORS
const DISABLE_GENERATORS
Constructor flag: The new instance of ApiPageSet will ignore the 'generator=' parameter.
Definition: ApiPageSet.php:50
ApiBase\getHookRunner
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition: ApiBase.php:653
ApiPageSet\getSpecialTitles
getSpecialTitles()
Get the list of titles with negative namespace.
Definition: ApiPageSet.php:830
ApiPageSet\getNormalizedTitles
getNormalizedTitles()
Get a list of title normalizations - maps a title to its normalized version.
Definition: ApiPageSet.php:616
ApiBase\dieDebug
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition: ApiBase.php:1582
ApiPageSet\$generators
static string[] null $generators
see getGenerators()
Definition: ApiPageSet.php:152
ApiBase\getErrorFormatter
getErrorFormatter()
Definition: ApiBase.php:582
ApiPageSet\$mMissingPageIDs
int[] $mMissingPageIDs
Definition: ApiPageSet.php:92
Wikimedia\ParamValidator\ParamValidator
Service for formatting and validating API parameters.
Definition: ParamValidator.php:42
ApiPageSet\populateGeneratorData
populateGeneratorData(&$result, array $path=[])
Populate the generator data for all titles in the result.
Definition: ApiPageSet.php:1505
ApiQueryBase\addTitleInfo
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
Definition: ApiQueryBase.php:466
ApiPageSet\$mCacheMode
string $mCacheMode
Definition: ApiPageSet.php:140
ApiPageSet\$mGoodPages
int[][] $mGoodPages
[ns][dbkey] => page_id
Definition: ApiPageSet.php:77
ApiPageSet\$mParams
array $mParams
Definition: ApiPageSet.php:56
ApiPageSet\getMissingPages
getMissingPages()
Pages that were NOT found in the database.
Definition: ApiPageSet.php:506
ApiPageSet\$mGeneratorData
array[][] $mGeneratorData
[ns][dbkey] => data array
Definition: ApiPageSet.php:134