MediaWiki  master
ApiPageSet.php
Go to the documentation of this file.
1 <?php
25 
40 class ApiPageSet extends ApiBase {
45  const DISABLE_GENERATORS = 1;
46 
47  private $mDbSource;
48  private $mParams;
50  private $mConvertTitles;
52 
53  private $mAllPages = []; // [ns][dbkey] => page_id or negative when missing
54  private $mTitles = [];
55  private $mGoodAndMissingPages = []; // [ns][dbkey] => page_id or negative when missing
56  private $mGoodPages = []; // [ns][dbkey] => page_id
57  private $mGoodTitles = [];
58  private $mMissingPages = []; // [ns][dbkey] => fake page_id
59  private $mMissingTitles = [];
61  private $mInvalidTitles = [];
62  private $mMissingPageIDs = [];
63  private $mRedirectTitles = [];
64  private $mSpecialTitles = [];
65  private $mAllSpecials = []; // separate from mAllPages to avoid breaking getAllTitlesByNamespace()
66  private $mNormalizedTitles = [];
67  private $mInterwikiTitles = [];
69  private $mPendingRedirectIDs = [];
70  private $mPendingRedirectSpecialPages = []; // [dbkey] => [ Title $from, Title $to ]
72  private $mConvertedTitles = [];
73  private $mGoodRevIDs = [];
74  private $mLiveRevIDs = [];
75  private $mDeletedRevIDs = [];
76  private $mMissingRevIDs = [];
77  private $mGeneratorData = []; // [ns][dbkey] => data array
78  private $mFakePageId = -1;
79  private $mCacheMode = 'public';
81  private $mRequestedPageFields = [];
86 
94  private static function addValues( array &$result, $values, $flags = [], $name = null ) {
95  foreach ( $values as $val ) {
96  if ( $val instanceof Title ) {
97  $v = [];
98  ApiQueryBase::addTitleInfo( $v, $val );
99  } elseif ( $name !== null ) {
100  $v = [ $name => $val ];
101  } else {
102  $v = $val;
103  }
104  foreach ( $flags as $flag ) {
105  $v[$flag] = true;
106  }
107  $result[] = $v;
108  }
109  }
110 
118  public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) {
119  parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() );
120  $this->mDbSource = $dbSource;
121  $this->mAllowGenerator = ( $flags & self::DISABLE_GENERATORS ) == 0;
122  $this->mDefaultNamespace = $defaultNamespace;
123 
124  $this->mParams = $this->extractRequestParams();
125  $this->mResolveRedirects = $this->mParams['redirects'];
126  $this->mConvertTitles = $this->mParams['converttitles'];
127  }
128 
133  public function executeDryRun() {
134  $this->executeInternal( true );
135  }
136 
140  public function execute() {
141  $this->executeInternal( false );
142  }
143 
149  private function executeInternal( $isDryRun ) {
150  $generatorName = $this->mAllowGenerator ? $this->mParams['generator'] : null;
151  if ( isset( $generatorName ) ) {
152  $dbSource = $this->mDbSource;
153  if ( !$dbSource instanceof ApiQuery ) {
154  // If the parent container of this pageset is not ApiQuery, we must create it to run generator
155  $dbSource = $this->getMain()->getModuleManager()->getModule( 'query' );
156  }
157  $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true );
158  if ( $generator === null ) {
159  $this->dieWithError( [ 'apierror-badgenerator-unknown', $generatorName ], 'badgenerator' );
160  }
161  if ( !$generator instanceof ApiQueryGeneratorBase ) {
162  $this->dieWithError( [ 'apierror-badgenerator-notgenerator', $generatorName ], 'badgenerator' );
163  }
164  // Create a temporary pageset to store generator's output,
165  // add any additional fields generator may need, and execute pageset to populate titles/pageids
166  $tmpPageSet = new ApiPageSet( $dbSource, self::DISABLE_GENERATORS );
167  $generator->setGeneratorMode( $tmpPageSet );
168  $this->mCacheMode = $generator->getCacheMode( $generator->extractRequestParams() );
169 
170  if ( !$isDryRun ) {
171  $generator->requestExtraData( $tmpPageSet );
172  }
173  $tmpPageSet->executeInternal( $isDryRun );
174 
175  // populate this pageset with the generator output
176  if ( !$isDryRun ) {
177  $generator->executeGenerator( $this );
178 
179  // Avoid PHP 7.1 warning of passing $this by reference
180  $apiModule = $this;
181  Hooks::run( 'APIQueryGeneratorAfterExecute', [ &$generator, &$apiModule ] );
182  } else {
183  // Prevent warnings from being reported on these parameters
184  $main = $this->getMain();
185  foreach ( $generator->extractRequestParams() as $paramName => $param ) {
186  $main->markParamsUsed( $generator->encodeParamName( $paramName ) );
187  }
188  }
189 
190  if ( !$isDryRun ) {
191  $this->resolvePendingRedirects();
192  }
193  } else {
194  // Only one of the titles/pageids/revids is allowed at the same time
195  $dataSource = null;
196  if ( isset( $this->mParams['titles'] ) ) {
197  $dataSource = 'titles';
198  }
199  if ( isset( $this->mParams['pageids'] ) ) {
200  if ( isset( $dataSource ) ) {
201  $this->dieWithError(
202  [
203  'apierror-invalidparammix-cannotusewith',
204  $this->encodeParamName( 'pageids' ),
205  $this->encodeParamName( $dataSource )
206  ],
207  'multisource'
208  );
209  }
210  $dataSource = 'pageids';
211  }
212  if ( isset( $this->mParams['revids'] ) ) {
213  if ( isset( $dataSource ) ) {
214  $this->dieWithError(
215  [
216  'apierror-invalidparammix-cannotusewith',
217  $this->encodeParamName( 'revids' ),
218  $this->encodeParamName( $dataSource )
219  ],
220  'multisource'
221  );
222  }
223  $dataSource = 'revids';
224  }
225 
226  if ( !$isDryRun ) {
227  // Populate page information with the original user input
228  switch ( $dataSource ) {
229  case 'titles':
230  $this->initFromTitles( $this->mParams['titles'] );
231  break;
232  case 'pageids':
233  $this->initFromPageIds( $this->mParams['pageids'] );
234  break;
235  case 'revids':
236  if ( $this->mResolveRedirects ) {
237  $this->addWarning( 'apiwarn-redirectsandrevids' );
238  }
239  $this->mResolveRedirects = false;
240  $this->initFromRevIDs( $this->mParams['revids'] );
241  break;
242  default:
243  // Do nothing - some queries do not need any of the data sources.
244  break;
245  }
246  }
247  }
248  }
249 
254  public function isResolvingRedirects() {
256  }
257 
266  public function getDataSource() {
267  if ( $this->mAllowGenerator && isset( $this->mParams['generator'] ) ) {
268  return 'generator';
269  }
270  if ( isset( $this->mParams['titles'] ) ) {
271  return 'titles';
272  }
273  if ( isset( $this->mParams['pageids'] ) ) {
274  return 'pageids';
275  }
276  if ( isset( $this->mParams['revids'] ) ) {
277  return 'revids';
278  }
279 
280  return null;
281  }
282 
288  public function requestField( $fieldName ) {
289  $this->mRequestedPageFields[$fieldName] = null;
290  }
291 
298  public function getCustomField( $fieldName ) {
299  return $this->mRequestedPageFields[$fieldName];
300  }
301 
308  public function getPageTableFields() {
309  // Ensure we get minimum required fields
310  // DON'T change this order
311  $pageFlds = [
312  'page_namespace' => null,
313  'page_title' => null,
314  'page_id' => null,
315  ];
316 
317  if ( $this->mResolveRedirects ) {
318  $pageFlds['page_is_redirect'] = null;
319  }
320 
321  if ( $this->getConfig()->get( 'ContentHandlerUseDB' ) ) {
322  $pageFlds['page_content_model'] = null;
323  }
324 
325  if ( $this->getConfig()->get( 'PageLanguageUseDB' ) ) {
326  $pageFlds['page_lang'] = null;
327  }
328 
329  foreach ( LinkCache::getSelectFields() as $field ) {
330  $pageFlds[$field] = null;
331  }
332 
333  $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
334 
335  return array_keys( $pageFlds );
336  }
337 
344  public function getAllTitlesByNamespace() {
345  return $this->mAllPages;
346  }
347 
352  public function getTitles() {
353  return $this->mTitles;
354  }
355 
360  public function getTitleCount() {
361  return count( $this->mTitles );
362  }
363 
368  public function getGoodTitlesByNamespace() {
369  return $this->mGoodPages;
370  }
371 
376  public function getGoodTitles() {
377  return $this->mGoodTitles;
378  }
379 
384  public function getGoodTitleCount() {
385  return count( $this->mGoodTitles );
386  }
387 
393  public function getMissingTitlesByNamespace() {
394  return $this->mMissingPages;
395  }
396 
402  public function getMissingTitles() {
403  return $this->mMissingTitles;
404  }
405 
412  }
413 
418  public function getGoodAndMissingTitles() {
419  return $this->mGoodTitles + $this->mMissingTitles;
420  }
421 
427  public function getInvalidTitlesAndReasons() {
428  return $this->mInvalidTitles;
429  }
430 
435  public function getMissingPageIDs() {
436  return $this->mMissingPageIDs;
437  }
438 
444  public function getRedirectTitles() {
445  return $this->mRedirectTitles;
446  }
447 
455  public function getRedirectTitlesAsResult( $result = null ) {
456  $values = [];
457  foreach ( $this->getRedirectTitles() as $titleStrFrom => $titleTo ) {
458  $r = [
459  'from' => strval( $titleStrFrom ),
460  'to' => $titleTo->getPrefixedText(),
461  ];
462  if ( $titleTo->hasFragment() ) {
463  $r['tofragment'] = $titleTo->getFragment();
464  }
465  if ( $titleTo->isExternal() ) {
466  $r['tointerwiki'] = $titleTo->getInterwiki();
467  }
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 );
474  }
475  }
476 
477  $values[] = $r;
478  }
479  if ( !empty( $values ) && $result ) {
480  ApiResult::setIndexedTagName( $values, 'r' );
481  }
482 
483  return $values;
484  }
485 
491  public function getNormalizedTitles() {
493  }
494 
502  public function getNormalizedTitlesAsResult( $result = null ) {
503  $values = [];
504  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
505  foreach ( $this->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
506  $encode = $contLang->normalize( $rawTitleStr ) !== $rawTitleStr;
507  $values[] = [
508  'fromencoded' => $encode,
509  'from' => $encode ? rawurlencode( $rawTitleStr ) : $rawTitleStr,
510  'to' => $titleStr
511  ];
512  }
513  if ( !empty( $values ) && $result ) {
514  ApiResult::setIndexedTagName( $values, 'n' );
515  }
516 
517  return $values;
518  }
519 
525  public function getConvertedTitles() {
527  }
528 
536  public function getConvertedTitlesAsResult( $result = null ) {
537  $values = [];
538  foreach ( $this->getConvertedTitles() as $rawTitleStr => $titleStr ) {
539  $values[] = [
540  'from' => $rawTitleStr,
541  'to' => $titleStr
542  ];
543  }
544  if ( !empty( $values ) && $result ) {
545  ApiResult::setIndexedTagName( $values, 'c' );
546  }
547 
548  return $values;
549  }
550 
556  public function getInterwikiTitles() {
558  }
559 
568  public function getInterwikiTitlesAsResult( $result = null, $iwUrl = false ) {
569  $values = [];
570  foreach ( $this->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
571  $item = [
572  'title' => $rawTitleStr,
573  'iw' => $interwikiStr,
574  ];
575  if ( $iwUrl ) {
576  $title = Title::newFromText( $rawTitleStr );
577  $item['url'] = $title->getFullURL( '', false, PROTO_CURRENT );
578  }
579  $values[] = $item;
580  }
581  if ( !empty( $values ) && $result ) {
582  ApiResult::setIndexedTagName( $values, 'i' );
583  }
584 
585  return $values;
586  }
587 
602  public function getInvalidTitlesAndRevisions( $invalidChecks = [ 'invalidTitles',
603  'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles' ]
604  ) {
605  $result = [];
606  if ( in_array( 'invalidTitles', $invalidChecks ) ) {
607  self::addValues( $result, $this->getInvalidTitlesAndReasons(), [ 'invalid' ] );
608  }
609  if ( in_array( 'special', $invalidChecks ) ) {
610  $known = [];
611  $unknown = [];
612  foreach ( $this->getSpecialTitles() as $title ) {
613  if ( $title->isKnown() ) {
614  $known[] = $title;
615  } else {
616  $unknown[] = $title;
617  }
618  }
619  self::addValues( $result, $unknown, [ 'special', 'missing' ] );
620  self::addValues( $result, $known, [ 'special' ] );
621  }
622  if ( in_array( 'missingIds', $invalidChecks ) ) {
623  self::addValues( $result, $this->getMissingPageIDs(), [ 'missing' ], 'pageid' );
624  }
625  if ( in_array( 'missingRevIds', $invalidChecks ) ) {
626  self::addValues( $result, $this->getMissingRevisionIDs(), [ 'missing' ], 'revid' );
627  }
628  if ( in_array( 'missingTitles', $invalidChecks ) ) {
629  $known = [];
630  $unknown = [];
631  foreach ( $this->getMissingTitles() as $title ) {
632  if ( $title->isKnown() ) {
633  $known[] = $title;
634  } else {
635  $unknown[] = $title;
636  }
637  }
638  self::addValues( $result, $unknown, [ 'missing' ] );
639  self::addValues( $result, $known, [ 'missing', 'known' ] );
640  }
641  if ( in_array( 'interwikiTitles', $invalidChecks ) ) {
642  self::addValues( $result, $this->getInterwikiTitlesAsResult() );
643  }
644 
645  return $result;
646  }
647 
652  public function getRevisionIDs() {
653  return $this->mGoodRevIDs;
654  }
655 
660  public function getLiveRevisionIDs() {
661  return $this->mLiveRevIDs;
662  }
663 
668  public function getDeletedRevisionIDs() {
669  return $this->mDeletedRevIDs;
670  }
671 
676  public function getMissingRevisionIDs() {
677  return $this->mMissingRevIDs;
678  }
679 
686  public function getMissingRevisionIDsAsResult( $result = null ) {
687  $values = [];
688  foreach ( $this->getMissingRevisionIDs() as $revid ) {
689  $values[$revid] = [
690  'revid' => $revid
691  ];
692  }
693  if ( !empty( $values ) && $result ) {
694  ApiResult::setIndexedTagName( $values, 'rev' );
695  }
696 
697  return $values;
698  }
699 
704  public function getSpecialTitles() {
705  return $this->mSpecialTitles;
706  }
707 
712  public function getRevisionCount() {
713  return count( $this->getRevisionIDs() );
714  }
715 
720  public function populateFromTitles( $titles ) {
721  $this->initFromTitles( $titles );
722  }
723 
728  public function populateFromPageIDs( $pageIDs ) {
729  $this->initFromPageIds( $pageIDs );
730  }
731 
741  public function populateFromQueryResult( $db, $queryResult ) {
742  $this->initFromQueryResult( $queryResult );
743  }
744 
749  public function populateFromRevisionIDs( $revIDs ) {
750  $this->initFromRevIDs( $revIDs );
751  }
752 
757  public function processDbRow( $row ) {
758  // Store Title object in various data structures
759  $title = Title::newFromRow( $row );
760 
761  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
762  $linkCache->addGoodLinkObjFromRow( $title, $row );
763 
764  $pageId = (int)$row->page_id;
765  $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
766  $this->mTitles[] = $title;
767 
768  if ( $this->mResolveRedirects && $row->page_is_redirect == '1' ) {
769  $this->mPendingRedirectIDs[$pageId] = $title;
770  } else {
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;
774  }
775 
776  foreach ( $this->mRequestedPageFields as $fieldName => &$fieldValues ) {
777  $fieldValues[$pageId] = $row->$fieldName;
778  }
779  }
780 
797  private function initFromTitles( $titles ) {
798  // Get validated and normalized title objects
799  $linkBatch = $this->processTitlesArray( $titles );
800  if ( $linkBatch->isEmpty() ) {
801  // There might be special-page redirects
802  $this->resolvePendingRedirects();
803  return;
804  }
805 
806  $db = $this->getDB();
807  $set = $linkBatch->constructSet( 'page', $db );
808 
809  // Get pageIDs data from the `page` table
810  $res = $db->select( 'page', $this->getPageTableFields(), $set,
811  __METHOD__ );
812 
813  // Hack: get the ns:titles stored in [ ns => [ titles ] ] format
814  $this->initFromQueryResult( $res, $linkBatch->data, true ); // process Titles
815 
816  // Resolve any found redirects
817  $this->resolvePendingRedirects();
818  }
819 
825  private function initFromPageIds( $pageids, $filterIds = true ) {
826  if ( !$pageids ) {
827  return;
828  }
829 
830  $pageids = array_map( 'intval', $pageids ); // paranoia
831  $remaining = array_flip( $pageids );
832 
833  if ( $filterIds ) {
834  $pageids = $this->filterIDs( [ [ 'page', 'page_id' ] ], $pageids );
835  }
836 
837  $res = null;
838  if ( !empty( $pageids ) ) {
839  $set = [
840  'page_id' => $pageids
841  ];
842  $db = $this->getDB();
843 
844  // Get pageIDs data from the `page` table
845  $res = $db->select( 'page', $this->getPageTableFields(), $set,
846  __METHOD__ );
847  }
848 
849  $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
850 
851  // Resolve any found redirects
852  $this->resolvePendingRedirects();
853  }
854 
865  private function initFromQueryResult( $res, &$remaining = null, $processTitles = null ) {
866  if ( !is_null( $remaining ) && is_null( $processTitles ) ) {
867  ApiBase::dieDebug( __METHOD__, 'Missing $processTitles parameter when $remaining is provided' );
868  }
869 
870  $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
871 
872  $usernames = [];
873  if ( $res ) {
874  foreach ( $res as $row ) {
875  $pageId = (int)$row->page_id;
876 
877  // Remove found page from the list of remaining items
878  if ( isset( $remaining ) ) {
879  if ( $processTitles ) {
880  unset( $remaining[$row->page_namespace][$row->page_title] );
881  } else {
882  unset( $remaining[$pageId] );
883  }
884  }
885 
886  // Store any extra fields requested by modules
887  $this->processDbRow( $row );
888 
889  // Need gender information
890  if ( $nsInfo->hasGenderDistinction( $row->page_namespace ) ) {
891  $usernames[] = $row->page_title;
892  }
893  }
894  }
895 
896  if ( isset( $remaining ) ) {
897  // Any items left in the $remaining list are added as missing
898  if ( $processTitles ) {
899  // The remaining titles in $remaining are non-existent pages
900  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
901  foreach ( $remaining as $ns => $dbkeys ) {
902  foreach ( array_keys( $dbkeys ) as $dbkey ) {
903  $title = Title::makeTitle( $ns, $dbkey );
904  $linkCache->addBadLinkObj( $title );
905  $this->mAllPages[$ns][$dbkey] = $this->mFakePageId;
906  $this->mMissingPages[$ns][$dbkey] = $this->mFakePageId;
907  $this->mGoodAndMissingPages[$ns][$dbkey] = $this->mFakePageId;
908  $this->mMissingTitles[$this->mFakePageId] = $title;
909  $this->mFakePageId--;
910  $this->mTitles[] = $title;
911 
912  // need gender information
913  if ( $nsInfo->hasGenderDistinction( $ns ) ) {
914  $usernames[] = $dbkey;
915  }
916  }
917  }
918  } else {
919  // The remaining pageids do not exist
920  if ( !$this->mMissingPageIDs ) {
921  $this->mMissingPageIDs = array_keys( $remaining );
922  } else {
923  $this->mMissingPageIDs = array_merge( $this->mMissingPageIDs, array_keys( $remaining ) );
924  }
925  }
926  }
927 
928  // Get gender information
929  $genderCache = MediaWikiServices::getInstance()->getGenderCache();
930  $genderCache->doQuery( $usernames, __METHOD__ );
931  }
932 
938  private function initFromRevIDs( $revids ) {
939  if ( !$revids ) {
940  return;
941  }
942 
943  $revids = array_map( 'intval', $revids ); // paranoia
944  $db = $this->getDB();
945  $pageids = [];
946  $remaining = array_flip( $revids );
947 
948  $revids = $this->filterIDs( [ [ 'revision', 'rev_id' ], [ 'archive', 'ar_rev_id' ] ], $revids );
949  $goodRemaining = array_flip( $revids );
950 
951  if ( $revids ) {
952  $tables = [ 'revision', 'page' ];
953  $fields = [ 'rev_id', 'rev_page' ];
954  $where = [ 'rev_id' => $revids, 'rev_page = page_id' ];
955 
956  // Get pageIDs data from the `page` table
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] );
966  }
967  }
968 
969  // Populate all the page information
970  $this->initFromPageIds( array_keys( $pageids ), false );
971 
972  // If the user can see deleted revisions, pull out the corresponding
973  // titles from the archive table and include them too. We ignore
974  // ar_page_id because deleted revisions are tied by title, not page_id.
975  if ( $goodRemaining &&
976  $this->getPermissionManager()->userHasRight( $this->getUser(), 'deletedhistory' ) ) {
977  $tables = [ 'archive' ];
978  $fields = [ 'ar_rev_id', 'ar_namespace', 'ar_title' ];
979  $where = [ 'ar_rev_id' => array_keys( $goodRemaining ) ];
980 
981  $res = $db->select( $tables, $fields, $where, __METHOD__ );
982  $titles = [];
983  foreach ( $res as $row ) {
984  $revid = (int)$row->ar_rev_id;
985  $titles[$revid] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
986  unset( $remaining[$revid] );
987  }
988 
989  $this->initFromTitles( $titles );
990 
991  foreach ( $titles as $revid => $title ) {
992  $ns = $title->getNamespace();
993  $dbkey = $title->getDBkey();
994 
995  // Handle converted titles
996  if ( !isset( $this->mAllPages[$ns][$dbkey] ) &&
997  isset( $this->mConvertedTitles[$title->getPrefixedText()] )
998  ) {
999  $title = Title::newFromText( $this->mConvertedTitles[$title->getPrefixedText()] );
1000  $ns = $title->getNamespace();
1001  $dbkey = $title->getDBkey();
1002  }
1003 
1004  if ( isset( $this->mAllPages[$ns][$dbkey] ) ) {
1005  $this->mGoodRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1006  $this->mDeletedRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1007  } else {
1008  $remaining[$revid] = true;
1009  }
1010  }
1011  }
1012 
1013  $this->mMissingRevIDs = array_keys( $remaining );
1014  }
1015 
1021  private function resolvePendingRedirects() {
1022  if ( $this->mResolveRedirects ) {
1023  $db = $this->getDB();
1024  $pageFlds = $this->getPageTableFields();
1025 
1026  // Repeat until all redirects have been resolved
1027  // The infinite loop is prevented by keeping all known pages in $this->mAllPages
1028  while ( $this->mPendingRedirectIDs || $this->mPendingRedirectSpecialPages ) {
1029  // Resolve redirects by querying the pagelinks table, and repeat the process
1030  // Create a new linkBatch object for the next pass
1031  $linkBatch = $this->getRedirectTargets();
1032 
1033  if ( $linkBatch->isEmpty() ) {
1034  break;
1035  }
1036 
1037  $set = $linkBatch->constructSet( 'page', $db );
1038  if ( $set === false ) {
1039  break;
1040  }
1041 
1042  // Get pageIDs data from the `page` table
1043  $res = $db->select( 'page', $pageFlds, $set, __METHOD__ );
1044 
1045  // Hack: get the ns:titles stored in [ns => array(titles)] format
1046  $this->initFromQueryResult( $res, $linkBatch->data, true );
1047  }
1048  }
1049  }
1050 
1058  private function getRedirectTargets() {
1059  $titlesToResolve = [];
1060  $db = $this->getDB();
1061 
1062  if ( $this->mPendingRedirectIDs ) {
1063  $res = $db->select(
1064  'redirect',
1065  [
1066  'rd_from',
1067  'rd_namespace',
1068  'rd_fragment',
1069  'rd_interwiki',
1070  'rd_title'
1071  ], [ 'rd_from' => array_keys( $this->mPendingRedirectIDs ) ],
1072  __METHOD__
1073  );
1074  foreach ( $res as $row ) {
1075  $rdfrom = (int)$row->rd_from;
1076  $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
1077  $to = Title::makeTitle(
1078  $row->rd_namespace,
1079  $row->rd_title,
1080  $row->rd_fragment,
1081  $row->rd_interwiki
1082  );
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;
1089  }
1090  $this->mRedirectTitles[$from] = $to;
1091  }
1092 
1093  if ( $this->mPendingRedirectIDs ) {
1094  // We found pages that aren't in the redirect table
1095  // Add them
1096  foreach ( $this->mPendingRedirectIDs as $id => $title ) {
1097  $page = WikiPage::factory( $title );
1098  $rt = $page->insertRedirect();
1099  if ( !$rt ) {
1100  // What the hell. Let's just ignore this
1101  continue;
1102  }
1103  if ( $rt->isExternal() ) {
1104  $this->mInterwikiTitles[$rt->getPrefixedText()] = $rt->getInterwiki();
1105  } elseif ( !isset( $this->mAllPages[$rt->getNamespace()][$rt->getDBkey()] ) ) {
1106  $titlesToResolve[] = $rt;
1107  }
1108  $from = $title->getPrefixedText();
1109  $this->mResolvedRedirectTitles[$from] = $title;
1110  $this->mRedirectTitles[$from] = $rt;
1111  unset( $this->mPendingRedirectIDs[$id] );
1112  }
1113  }
1114  }
1115 
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;
1125  }
1126  }
1127  $this->mPendingRedirectSpecialPages = [];
1128 
1129  // Set private caching since we don't know what criteria the
1130  // special pages used to decide on these redirects.
1131  $this->mCacheMode = 'private';
1132  }
1133 
1134  return $this->processTitlesArray( $titlesToResolve );
1135  }
1136 
1150  public function getCacheMode( $params = null ) {
1151  return $this->mCacheMode;
1152  }
1153 
1163  private function processTitlesArray( $titles ) {
1164  $usernames = [];
1165  $linkBatch = new LinkBatch();
1166  $services = MediaWikiServices::getInstance();
1167  $contLang = $services->getContentLanguage();
1168 
1169  $titleObjects = [];
1170  foreach ( $titles as $index => $title ) {
1171  if ( is_string( $title ) ) {
1172  try {
1173  $titleObj = Title::newFromTextThrow( $title, $this->mDefaultNamespace );
1174  } catch ( MalformedTitleException $ex ) {
1175  // Handle invalid titles gracefully
1176  if ( !isset( $this->mAllPages[0][$title] ) ) {
1177  $this->mAllPages[0][$title] = $this->mFakePageId;
1178  $this->mInvalidTitles[$this->mFakePageId] = [
1179  'title' => $title,
1180  'invalidreason' => $this->getErrorFormatter()->formatException( $ex, [ 'bc' => true ] ),
1181  ];
1182  $this->mFakePageId--;
1183  }
1184  continue; // There's nothing else we can do
1185  }
1186  } else {
1187  $titleObj = $title;
1188  }
1189 
1190  $titleObjects[$index] = $titleObj;
1191  }
1192 
1193  // Get gender information
1194  $genderCache = $services->getGenderCache();
1195  $genderCache->doTitlesArray( $titleObjects, __METHOD__ );
1196 
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() ) {
1202  // This title is an interwiki link.
1203  $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
1204  } else {
1205  // Variants checking
1206  if (
1207  $this->mConvertTitles && $contLang->hasVariants() && !$titleObj->exists()
1208  ) {
1209  // Language::findVariantLink will modify titleText and titleObj into
1210  // the canonical variant if possible
1211  $titleText = $title !== false ? $title : $titleObj->getPrefixedText();
1212  $contLang->findVariantLink( $titleText, $titleObj );
1213  $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText();
1214  }
1215 
1216  if ( $titleObj->getNamespace() < 0 ) {
1217  // Handle Special and Media pages
1218  $titleObj = $titleObj->fixSpecialName();
1219  $ns = $titleObj->getNamespace();
1220  $dbkey = $titleObj->getDBkey();
1221  if ( !isset( $this->mAllSpecials[$ns][$dbkey] ) ) {
1222  $this->mAllSpecials[$ns][$dbkey] = $this->mFakePageId;
1223  $target = null;
1224  if ( $ns === NS_SPECIAL && $this->mResolveRedirects ) {
1225  $spFactory = $services->getSpecialPageFactory();
1226  $special = $spFactory->getPage( $dbkey );
1227  if ( $special instanceof RedirectSpecialArticle ) {
1228  // Only RedirectSpecialArticle is intended to redirect to an article, other kinds of
1229  // RedirectSpecialPage are probably applying weird URL parameters we don't want to handle.
1230  $context = new DerivativeContext( $this );
1231  $context->setTitle( $titleObj );
1232  $context->setRequest( new FauxRequest );
1233  $special->setContext( $context );
1234  list( /* $alias */, $subpage ) = $spFactory->resolveAlias( $dbkey );
1235  $target = $special->getRedirect( $subpage );
1236  }
1237  }
1238  if ( $target ) {
1239  $this->mPendingRedirectSpecialPages[$dbkey] = [ $titleObj, $target ];
1240  } else {
1241  $this->mSpecialTitles[$this->mFakePageId] = $titleObj;
1242  $this->mFakePageId--;
1243  }
1244  }
1245  } else {
1246  // Regular page
1247  $linkBatch->addObj( $titleObj );
1248  }
1249  }
1250 
1251  // Make sure we remember the original title that was
1252  // given to us. This way the caller can correlate new
1253  // titles with the originally requested when e.g. the
1254  // namespace is localized or the capitalization is
1255  // different
1256  if ( $titleWasConverted ) {
1257  $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText();
1258  // In this case the page can't be Special.
1259  if ( $title !== false && $title !== $unconvertedTitle ) {
1260  $this->mNormalizedTitles[$title] = $unconvertedTitle;
1261  }
1262  } elseif ( $title !== false && $title !== $titleObj->getPrefixedText() ) {
1263  $this->mNormalizedTitles[$title] = $titleObj->getPrefixedText();
1264  }
1265  }
1266 
1267  return $linkBatch;
1268  }
1269 
1285  public function setGeneratorData( Title $title, array $data ) {
1286  $ns = $title->getNamespace();
1287  $dbkey = $title->getDBkey();
1288  $this->mGeneratorData[$ns][$dbkey] = $data;
1289  }
1290 
1310  public function setRedirectMergePolicy( $callable ) {
1311  $this->mRedirectMergePolicy = $callable;
1312  }
1313 
1334  public function populateGeneratorData( &$result, array $path = [] ) {
1335  if ( $result instanceof ApiResult ) {
1336  $data = $result->getResultData( $path );
1337  if ( $data === null ) {
1338  return true;
1339  }
1340  } else {
1341  $data = &$result;
1342  foreach ( $path as $key ) {
1343  if ( !isset( $data[$key] ) ) {
1344  // Path isn't in $result, so nothing to add, so everything
1345  // "fits"
1346  return true;
1347  }
1348  $data = &$data[$key];
1349  }
1350  }
1351  foreach ( $this->mGeneratorData as $ns => $dbkeys ) {
1352  if ( $ns === NS_SPECIAL ) {
1353  $pages = [];
1354  foreach ( $this->mSpecialTitles as $id => $title ) {
1355  $pages[$title->getDBkey()] = $id;
1356  }
1357  } else {
1358  if ( !isset( $this->mAllPages[$ns] ) ) {
1359  // No known titles in the whole namespace. Skip it.
1360  continue;
1361  }
1362  $pages = $this->mAllPages[$ns];
1363  }
1364  foreach ( $dbkeys as $dbkey => $genData ) {
1365  if ( !isset( $pages[$dbkey] ) ) {
1366  // Unknown title. Forget it.
1367  continue;
1368  }
1369  $pageId = $pages[$dbkey];
1370  if ( !isset( $data[$pageId] ) ) {
1371  // $pageId didn't make it into the result. Ignore it.
1372  continue;
1373  }
1374 
1375  if ( $result instanceof ApiResult ) {
1376  $path2 = array_merge( $path, [ $pageId ] );
1377  foreach ( $genData as $key => $value ) {
1378  if ( !$result->addValue( $path2, $key, $value ) ) {
1379  return false;
1380  }
1381  }
1382  } else {
1383  $data[$pageId] = array_merge( $data[$pageId], $genData );
1384  }
1385  }
1386  }
1387 
1388  // Merge data generated about redirect titles into the redirect destination
1389  if ( $this->mRedirectMergePolicy ) {
1390  foreach ( $this->mResolvedRedirectTitles as $titleFrom ) {
1391  $dest = $titleFrom;
1392  while ( isset( $this->mRedirectTitles[$dest->getPrefixedText()] ) ) {
1393  $dest = $this->mRedirectTitles[$dest->getPrefixedText()];
1394  }
1395  $fromNs = $titleFrom->getNamespace();
1396  $fromDBkey = $titleFrom->getDBkey();
1397  $toPageId = $dest->getArticleID();
1398  if ( isset( $data[$toPageId] ) &&
1399  isset( $this->mGeneratorData[$fromNs][$fromDBkey] )
1400  ) {
1401  // It is necessary to set both $data and add to $result, if an ApiResult,
1402  // to ensure multiple redirects to the same destination are all merged.
1403  $data[$toPageId] = call_user_func(
1404  $this->mRedirectMergePolicy,
1405  $data[$toPageId],
1406  $this->mGeneratorData[$fromNs][$fromDBkey]
1407  );
1408  if ( $result instanceof ApiResult &&
1409  !$result->addValue( $path, $toPageId, $data[$toPageId], ApiResult::OVERRIDE )
1410  ) {
1411  return false;
1412  }
1413  }
1414  }
1415  }
1416 
1417  return true;
1418  }
1419 
1424  protected function getDB() {
1425  return $this->mDbSource->getDB();
1426  }
1427 
1428  public function getAllowedParams( $flags = 0 ) {
1429  $result = [
1430  'titles' => [
1431  ApiBase::PARAM_ISMULTI => true,
1432  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-titles',
1433  ],
1434  'pageids' => [
1435  ApiBase::PARAM_TYPE => 'integer',
1436  ApiBase::PARAM_ISMULTI => true,
1437  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-pageids',
1438  ],
1439  'revids' => [
1440  ApiBase::PARAM_TYPE => 'integer',
1441  ApiBase::PARAM_ISMULTI => true,
1442  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-revids',
1443  ],
1444  'generator' => [
1445  ApiBase::PARAM_TYPE => null,
1446  ApiBase::PARAM_HELP_MSG => 'api-pageset-param-generator',
1448  ],
1449  'redirects' => [
1450  ApiBase::PARAM_DFLT => false,
1451  ApiBase::PARAM_HELP_MSG => $this->mAllowGenerator
1452  ? 'api-pageset-param-redirects-generator'
1453  : 'api-pageset-param-redirects-nogenerator',
1454  ],
1455  'converttitles' => [
1456  ApiBase::PARAM_DFLT => false,
1457  ApiBase::PARAM_HELP_MSG => [
1458  'api-pageset-param-converttitles',
1460  ],
1461  ],
1462  ];
1463 
1464  if ( !$this->mAllowGenerator ) {
1465  unset( $result['generator'] );
1466  } elseif ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
1467  $result['generator'][ApiBase::PARAM_TYPE] = 'submodule';
1468  $result['generator'][ApiBase::PARAM_SUBMODULE_MAP] = $this->getGenerators();
1469  }
1470 
1471  return $result;
1472  }
1473 
1474  protected function handleParamNormalization( $paramName, $value, $rawValue ) {
1475  parent::handleParamNormalization( $paramName, $value, $rawValue );
1476 
1477  if ( $paramName === 'titles' ) {
1478  // For the 'titles' parameter, we want to split it like ApiBase would
1479  // and add any changed titles to $this->mNormalizedTitles
1480  $value = $this->explodeMultiValue( $value, self::LIMIT_SML2 + 1 );
1481  $l = count( $value );
1482  $rawValue = $this->explodeMultiValue( $rawValue, $l );
1483  for ( $i = 0; $i < $l; $i++ ) {
1484  if ( $value[$i] !== $rawValue[$i] ) {
1485  $this->mNormalizedTitles[$rawValue[$i]] = $value[$i];
1486  }
1487  }
1488  }
1489  }
1490 
1491  private static $generators = null;
1492 
1497  private function getGenerators() {
1498  if ( self::$generators === null ) {
1499  $query = $this->mDbSource;
1500  if ( !( $query instanceof ApiQuery ) ) {
1501  // If the parent container of this pageset is not ApiQuery,
1502  // we must create it to get module manager
1503  $query = $this->getMain()->getModuleManager()->getModule( 'query' );
1504  }
1505  $gens = [];
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;
1511  }
1512  }
1513  ksort( $gens );
1514  self::$generators = $gens;
1515  }
1516 
1517  return self::$generators;
1518  }
1519 }
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:142
static $generators
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below...
Definition: ApiBase.php:94
getErrorFormatter()
Get the error formatter.
Definition: ApiBase.php:654
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
setGeneratorData(Title $title, array $data)
Set data for a title.
getRedirectTitles()
Get a list of redirect resolutions - maps a title to its redirect target, as an array of output-ready...
Definition: ApiPageSet.php:444
$mGoodAndMissingPages
Definition: ApiPageSet.php:55
$mPendingRedirectSpecialPages
Definition: ApiPageSet.php:70
getSpecialTitles()
Get the list of titles with negative namespace.
Definition: ApiPageSet.php:704
const NS_MAIN
Definition: Defines.php:60
getDataSource()
Return the parameter name that is the source of data for this PageSet.
Definition: ApiPageSet.php:266
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:40
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition: ApiBase.php:55
getMain()
Get the main module.
Definition: ApiBase.php:536
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition: ApiBase.php:272
An IContextSource implementation which will inherit context from another source but allow individual ...
getConvertedTitles()
Get a list of title conversions - maps a title to its converted version.
Definition: ApiPageSet.php:525
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:58
getMissingRevisionIDs()
Revision IDs that were not found in the database.
Definition: ApiPageSet.php:676
const NS_SPECIAL
Definition: Defines.php:49
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:2005
const PROTO_CURRENT
Definition: Defines.php:202
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user...
Definition: ApiBase.php:761
getMissingTitlesByNamespace()
Returns an array [ns][dbkey] => fake_page_id for all missing titles.
Definition: ApiPageSet.php:393
populateFromRevisionIDs( $revIDs)
Populate this PageSet from a list of revision IDs.
Definition: ApiPageSet.php:749
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:518
getRevisionIDs()
Get the list of valid revision IDs (requested with the revids= parameter)
Definition: ApiPageSet.php:652
getTitleCount()
Returns the number of unique pages (not revisions) in the set.
Definition: ApiPageSet.php:360
IContextSource $context
getAllTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all requested titles.
Definition: ApiPageSet.php:344
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:616
getPageTableFields()
Get the fields that have to be queried from the page table: the ones requested through requestField()...
Definition: ApiPageSet.php:308
getTitles()
All Title objects provided.
Definition: ApiPageSet.php:352
getLiveRevisionIDs()
Get the list of non-deleted revision IDs (requested with the revids= parameter)
Definition: ApiPageSet.php:660
callable null $mRedirectMergePolicy
Definition: ApiPageSet.php:85
initFromQueryResult( $res, &$remaining=null, $processTitles=null)
Iterate through the result of the query on &#39;page&#39; table, and for each row create and store title obje...
Definition: ApiPageSet.php:865
resolvePendingRedirects()
Resolve any redirects in the result if redirect resolution was requested.
array $mRequestedPageFields
Definition: ApiPageSet.php:81
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:34
getGoodAndMissingTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good and missing titles.
Definition: ApiPageSet.php:410
static addValues(array &$result, $values, $flags=[], $name=null)
Add all items from $values into the result.
Definition: ApiPageSet.php:94
getGoodTitleCount()
Returns the number of found unique pages (not revisions) in the set.
Definition: ApiPageSet.php:384
initFromPageIds( $pageids, $filterIds=true)
Does the same as initFromTitles(), but is based on page IDs instead.
Definition: ApiPageSet.php:825
const PARAM_SUBMODULE_PARAM_PREFIX
(string) When PARAM_TYPE is &#39;submodule&#39;, used to indicate the &#39;g&#39; prefix added by ApiQueryGeneratorBa...
Definition: ApiBase.php:179
getInvalidTitlesAndReasons()
Titles that were deemed invalid by Title::newFromText() The array&#39;s index will be unique and negative...
Definition: ApiPageSet.php:427
populateGeneratorData(&$result, array $path=[])
Populate the generator data for all titles in the result.
getGoodAndMissingTitles()
Title objects for good and missing titles.
Definition: ApiPageSet.php:418
populateFromTitles( $titles)
Populate this PageSet from a list of Titles.
Definition: ApiPageSet.php:720
getDBkey()
Get the main part with underscores.
Definition: Title.php:1016
getGoodTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good titles.
Definition: ApiPageSet.php:368
requestField( $fieldName)
Request an additional field from the page table.
Definition: ApiPageSet.php:288
getGenerators()
Get an array of all available generators.
executeDryRun()
In case execute() is not called, call this method to mark all relevant parameters as used This preven...
Definition: ApiPageSet.php:133
processTitlesArray( $titles)
Given an array of title strings, convert them into Title objects.
explodeMultiValue( $value, $limit)
Split a multi-valued parameter string, like explode()
Definition: ApiBase.php:1460
const PARAM_SUBMODULE_MAP
(string[]) When PARAM_TYPE is &#39;submodule&#39;, map parameter values to submodule paths.
Definition: ApiBase.php:172
getGoodTitles()
Title objects that were found in the database.
Definition: ApiPageSet.php:376
getMissingTitles()
Title objects that were NOT found in the database.
Definition: ApiPageSet.php:402
getDB()
Get the database connection (read-only)
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
This class represents the result of the API operations.
Definition: ApiResult.php:35
getNamespace()
Get the namespace index, i.e.
Definition: Title.php:1040
This is the main query class.
Definition: ApiQuery.php:37
getInvalidTitlesAndRevisions( $invalidChecks=[ 'invalidTitles', 'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles'])
Get an array of invalid/special/missing titles.
Definition: ApiPageSet.php:602
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter...
Definition: ApiBase.php:131
$mResolvedRedirectTitles
Definition: ApiPageSet.php:71
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid, rather than returning null.
Definition: Title.php:354
populateFromQueryResult( $db, $queryResult)
Populate this PageSet from a rowset returned from the database.
Definition: ApiPageSet.php:741
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:219
getAllowedParams( $flags=0)
int $mDefaultNamespace
Definition: ApiPageSet.php:83
getInterwikiTitlesAsResult( $result=null, $iwUrl=false)
Get a list of interwiki titles - maps a title to its interwiki prefix as result.
Definition: ApiPageSet.php:568
getMissingPageIDs()
Page IDs that were not found in the database.
Definition: ApiPageSet.php:435
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:586
getInterwikiTitles()
Get a list of interwiki titles - maps a title to its interwiki prefix.
Definition: ApiPageSet.php:556
executeInternal( $isDryRun)
Populate the PageSet from the request parameters.
Definition: ApiPageSet.php:149
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:739
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:502
populateFromPageIDs( $pageIDs)
Populate this PageSet from a list of page IDs.
Definition: ApiPageSet.php:728
processDbRow( $row)
Extract all requested fields from the row received from the database.
Definition: ApiPageSet.php:757
filterIDs( $fields, array $ids)
Filter out-of-range values from a list of positive integer IDs.
Definition: ApiBase.php:1876
getRedirectTargets()
Get the targets of the pending redirects from the database.
initFromRevIDs( $revids)
Does the same as initFromTitles(), but is based on revision IDs instead.
Definition: ApiPageSet.php:938
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1924
getCustomField( $fieldName)
Get the value of a custom field previously requested through requestField()
Definition: ApiPageSet.php:298
getNormalizedTitles()
Get a list of title normalizations - maps a title to its normalized version.
Definition: ApiPageSet.php:491
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition: ApiBase.php:58
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks...
Definition: ApiBase.php:710
array $mInvalidTitles
[fake_page_id] => [ &#39;title&#39; => $title, &#39;invalidreason&#39; => $reason ]
Definition: ApiPageSet.php:61
__construct(ApiBase $dbSource, $flags=0, $defaultNamespace=NS_MAIN)
Definition: ApiPageSet.php:118
getMissingRevisionIDsAsResult( $result=null)
Revision IDs that were not found in the database as result array.
Definition: ApiPageSet.php:686
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition: ApiBase.php:2211
getConvertedTitlesAsResult( $result=null)
Get a list of title conversions - maps a title to its converted version as a result array...
Definition: ApiPageSet.php:536
This abstract class implements many basic API functions, and is the base of all API classes...
Definition: ApiBase.php:42
setRedirectMergePolicy( $callable)
Controls how generator data about a redirect source is merged into the generator data for the redirec...
getCacheMode( $params=null)
Get the cache mode for the data generated by this module.
isResolvingRedirects()
Check whether this PageSet is resolving redirects.
Definition: ApiPageSet.php:254
getRevisionCount()
Returns the number of revisions (requested with revids= parameter).
Definition: ApiPageSet.php:712
initFromTitles( $titles)
This method populates internal variables with page information based on the given array of title stri...
Definition: ApiPageSet.php:797
const DISABLE_GENERATORS
Constructor flag: The new instance of ApiPageSet will ignore the &#39;generator=&#39; parameter.
Definition: ApiPageSet.php:45
Title [] $mPendingRedirectIDs
Definition: ApiPageSet.php:69
Superclass for any RedirectSpecialPage which redirects the user to a particular article (as opposed t...
static array $languagesWithVariants
languages supporting variants
const OVERRIDE
Override existing value in addValue(), setValue(), and similar functions.
Definition: ApiResult.php:41
handleParamNormalization( $paramName, $value, $rawValue)
execute()
Populate the PageSet from the request parameters.
Definition: ApiPageSet.php:140
static listParam(array $list, $type='text')
Definition: Message.php:1115
getDeletedRevisionIDs()
Get the list of revision IDs that were associated with deleted titles.
Definition: ApiPageSet.php:668
getRedirectTitlesAsResult( $result=null)
Get a list of redirect resolutions - maps a title to its redirect target.
Definition: ApiPageSet.php:455
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319