MediaWiki  master
ApiPageSet.php
Go to the documentation of this file.
1 <?php
27 
42 class ApiPageSet extends ApiBase {
47  private const DISABLE_GENERATORS = 1;
48 
49  private $mDbSource;
50  private $mParams = [];
52  private $mConvertTitles;
54 
55  private $mAllPages = []; // [ns][dbkey] => page_id or negative when missing
56  private $mTitles = [];
57  private $mGoodAndMissingPages = []; // [ns][dbkey] => page_id or negative when missing
58  private $mGoodPages = []; // [ns][dbkey] => page_id
59  private $mGoodTitles = [];
60  private $mMissingPages = []; // [ns][dbkey] => fake page_id
61  private $mMissingTitles = [];
63  private $mInvalidTitles = [];
64  private $mMissingPageIDs = [];
65  private $mRedirectTitles = [];
66  private $mSpecialTitles = [];
67  private $mAllSpecials = []; // separate from mAllPages to avoid breaking getAllTitlesByNamespace()
68  private $mNormalizedTitles = [];
69  private $mInterwikiTitles = [];
71  private $mPendingRedirectIDs = [];
72  private $mPendingRedirectSpecialPages = []; // [dbkey] => [ Title $from, Title $to ]
74  private $mConvertedTitles = [];
75  private $mGoodRevIDs = [];
76  private $mLiveRevIDs = [];
77  private $mDeletedRevIDs = [];
78  private $mMissingRevIDs = [];
79  private $mGeneratorData = []; // [ns][dbkey] => data array
80  private $mFakePageId = -1;
81  private $mCacheMode = 'public';
83  private $mRequestedPageFields = [];
88 
96  private static function addValues( array &$result, $values, $flags = [], $name = null ) {
97  foreach ( $values as $val ) {
98  if ( $val instanceof Title ) {
99  $v = [];
100  ApiQueryBase::addTitleInfo( $v, $val );
101  } elseif ( $name !== null ) {
102  $v = [ $name => $val ];
103  } else {
104  $v = $val;
105  }
106  foreach ( $flags as $flag ) {
107  $v[$flag] = true;
108  }
109  $result[] = $v;
110  }
111  }
112 
120  public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) {
121  parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() );
122  $this->mDbSource = $dbSource;
123  $this->mAllowGenerator = ( $flags & self::DISABLE_GENERATORS ) == 0;
124  $this->mDefaultNamespace = $defaultNamespace;
125 
126  $this->mParams = $this->extractRequestParams();
127  $this->mResolveRedirects = $this->mParams['redirects'];
128  $this->mConvertTitles = $this->mParams['converttitles'];
129  }
130 
135  public function executeDryRun() {
136  $this->executeInternal( true );
137  }
138 
142  public function execute() {
143  $this->executeInternal( false );
144  }
145 
151  private function executeInternal( $isDryRun ) {
152  $generatorName = $this->mAllowGenerator ? $this->mParams['generator'] : null;
153  if ( isset( $generatorName ) ) {
154  $dbSource = $this->mDbSource;
155  if ( !$dbSource instanceof ApiQuery ) {
156  // If the parent container of this pageset is not ApiQuery, we must create it to run generator
157  $dbSource = $this->getMain()->getModuleManager()->getModule( 'query' );
158  }
159  $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true );
160  if ( $generator === null ) {
161  $this->dieWithError( [ 'apierror-badgenerator-unknown', $generatorName ], 'badgenerator' );
162  }
163  if ( !$generator instanceof ApiQueryGeneratorBase ) {
164  $this->dieWithError( [ 'apierror-badgenerator-notgenerator', $generatorName ], 'badgenerator' );
165  }
166  // Create a temporary pageset to store generator's output,
167  // add any additional fields generator may need, and execute pageset to populate titles/pageids
168  $tmpPageSet = new ApiPageSet( $dbSource, self::DISABLE_GENERATORS );
169  $generator->setGeneratorMode( $tmpPageSet );
170  $this->mCacheMode = $generator->getCacheMode( $generator->extractRequestParams() );
171 
172  if ( !$isDryRun ) {
173  $generator->requestExtraData( $tmpPageSet );
174  }
175  $tmpPageSet->executeInternal( $isDryRun );
176 
177  // populate this pageset with the generator output
178  if ( !$isDryRun ) {
179  $generator->executeGenerator( $this );
180 
181  $this->getHookRunner()->onAPIQueryGeneratorAfterExecute( $generator, $this );
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  $pageFlds['page_content_model'] = null;
322 
323  if ( $this->getConfig()->get( 'PageLanguageUseDB' ) ) {
324  $pageFlds['page_lang'] = null;
325  }
326 
327  foreach ( LinkCache::getSelectFields() as $field ) {
328  $pageFlds[$field] = null;
329  }
330 
331  $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
332 
333  return array_keys( $pageFlds );
334  }
335 
342  public function getAllTitlesByNamespace() {
343  return $this->mAllPages;
344  }
345 
350  public function getTitles() {
351  return $this->mTitles;
352  }
353 
358  public function getTitleCount() {
359  return count( $this->mTitles );
360  }
361 
366  public function getGoodTitlesByNamespace() {
367  return $this->mGoodPages;
368  }
369 
374  public function getGoodTitles() {
375  return $this->mGoodTitles;
376  }
377 
382  public function getGoodTitleCount() {
383  return count( $this->mGoodTitles );
384  }
385 
391  public function getMissingTitlesByNamespace() {
392  return $this->mMissingPages;
393  }
394 
400  public function getMissingTitles() {
401  return $this->mMissingTitles;
402  }
403 
410  }
411 
416  public function getGoodAndMissingTitles() {
417  return $this->mGoodTitles + $this->mMissingTitles;
418  }
419 
425  public function getInvalidTitlesAndReasons() {
426  return $this->mInvalidTitles;
427  }
428 
433  public function getMissingPageIDs() {
434  return $this->mMissingPageIDs;
435  }
436 
442  public function getRedirectTitles() {
443  return $this->mRedirectTitles;
444  }
445 
453  public function getRedirectTitlesAsResult( $result = null ) {
454  $values = [];
455  foreach ( $this->getRedirectTitles() as $titleStrFrom => $titleTo ) {
456  $r = [
457  'from' => strval( $titleStrFrom ),
458  'to' => $titleTo->getPrefixedText(),
459  ];
460  if ( $titleTo->hasFragment() ) {
461  $r['tofragment'] = $titleTo->getFragment();
462  }
463  if ( $titleTo->isExternal() ) {
464  $r['tointerwiki'] = $titleTo->getInterwiki();
465  }
466  if ( isset( $this->mResolvedRedirectTitles[$titleStrFrom] ) ) {
467  $titleFrom = $this->mResolvedRedirectTitles[$titleStrFrom];
468  $ns = $titleFrom->getNamespace();
469  $dbkey = $titleFrom->getDBkey();
470  if ( isset( $this->mGeneratorData[$ns][$dbkey] ) ) {
471  $r = array_merge( $this->mGeneratorData[$ns][$dbkey], $r );
472  }
473  }
474 
475  $values[] = $r;
476  }
477  if ( !empty( $values ) && $result ) {
478  ApiResult::setIndexedTagName( $values, 'r' );
479  }
480 
481  return $values;
482  }
483 
489  public function getNormalizedTitles() {
491  }
492 
500  public function getNormalizedTitlesAsResult( $result = null ) {
501  $values = [];
502  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
503  foreach ( $this->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
504  $encode = $contLang->normalize( $rawTitleStr ) !== $rawTitleStr;
505  $values[] = [
506  'fromencoded' => $encode,
507  'from' => $encode ? rawurlencode( $rawTitleStr ) : $rawTitleStr,
508  'to' => $titleStr
509  ];
510  }
511  if ( !empty( $values ) && $result ) {
512  ApiResult::setIndexedTagName( $values, 'n' );
513  }
514 
515  return $values;
516  }
517 
523  public function getConvertedTitles() {
525  }
526 
534  public function getConvertedTitlesAsResult( $result = null ) {
535  $values = [];
536  foreach ( $this->getConvertedTitles() as $rawTitleStr => $titleStr ) {
537  $values[] = [
538  'from' => $rawTitleStr,
539  'to' => $titleStr
540  ];
541  }
542  if ( !empty( $values ) && $result ) {
543  ApiResult::setIndexedTagName( $values, 'c' );
544  }
545 
546  return $values;
547  }
548 
554  public function getInterwikiTitles() {
556  }
557 
566  public function getInterwikiTitlesAsResult( $result = null, $iwUrl = false ) {
567  $values = [];
568  foreach ( $this->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
569  $item = [
570  'title' => $rawTitleStr,
571  'iw' => $interwikiStr,
572  ];
573  if ( $iwUrl ) {
574  $title = Title::newFromText( $rawTitleStr );
575  $item['url'] = $title->getFullURL( '', false, PROTO_CURRENT );
576  }
577  $values[] = $item;
578  }
579  if ( !empty( $values ) && $result ) {
580  ApiResult::setIndexedTagName( $values, 'i' );
581  }
582 
583  return $values;
584  }
585 
600  public function getInvalidTitlesAndRevisions( $invalidChecks = [ 'invalidTitles',
601  'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles' ]
602  ) {
603  $result = [];
604  if ( in_array( 'invalidTitles', $invalidChecks ) ) {
605  self::addValues( $result, $this->getInvalidTitlesAndReasons(), [ 'invalid' ] );
606  }
607  if ( in_array( 'special', $invalidChecks ) ) {
608  $known = [];
609  $unknown = [];
610  foreach ( $this->getSpecialTitles() as $title ) {
611  if ( $title->isKnown() ) {
612  $known[] = $title;
613  } else {
614  $unknown[] = $title;
615  }
616  }
617  self::addValues( $result, $unknown, [ 'special', 'missing' ] );
618  self::addValues( $result, $known, [ 'special' ] );
619  }
620  if ( in_array( 'missingIds', $invalidChecks ) ) {
621  self::addValues( $result, $this->getMissingPageIDs(), [ 'missing' ], 'pageid' );
622  }
623  if ( in_array( 'missingRevIds', $invalidChecks ) ) {
624  self::addValues( $result, $this->getMissingRevisionIDs(), [ 'missing' ], 'revid' );
625  }
626  if ( in_array( 'missingTitles', $invalidChecks ) ) {
627  $known = [];
628  $unknown = [];
629  foreach ( $this->getMissingTitles() as $title ) {
630  if ( $title->isKnown() ) {
631  $known[] = $title;
632  } else {
633  $unknown[] = $title;
634  }
635  }
636  self::addValues( $result, $unknown, [ 'missing' ] );
637  self::addValues( $result, $known, [ 'missing', 'known' ] );
638  }
639  if ( in_array( 'interwikiTitles', $invalidChecks ) ) {
640  self::addValues( $result, $this->getInterwikiTitlesAsResult() );
641  }
642 
643  return $result;
644  }
645 
650  public function getRevisionIDs() {
651  return $this->mGoodRevIDs;
652  }
653 
658  public function getLiveRevisionIDs() {
659  return $this->mLiveRevIDs;
660  }
661 
666  public function getDeletedRevisionIDs() {
667  return $this->mDeletedRevIDs;
668  }
669 
674  public function getMissingRevisionIDs() {
675  return $this->mMissingRevIDs;
676  }
677 
684  public function getMissingRevisionIDsAsResult( $result = null ) {
685  $values = [];
686  foreach ( $this->getMissingRevisionIDs() as $revid ) {
687  $values[$revid] = [
688  'revid' => $revid
689  ];
690  }
691  if ( !empty( $values ) && $result ) {
692  ApiResult::setIndexedTagName( $values, 'rev' );
693  }
694 
695  return $values;
696  }
697 
702  public function getSpecialTitles() {
703  return $this->mSpecialTitles;
704  }
705 
710  public function getRevisionCount() {
711  return count( $this->getRevisionIDs() );
712  }
713 
718  public function populateFromTitles( $titles ) {
719  $this->initFromTitles( $titles );
720  }
721 
726  public function populateFromPageIDs( $pageIDs ) {
727  $this->initFromPageIds( $pageIDs );
728  }
729 
739  public function populateFromQueryResult( $db, $queryResult ) {
740  $this->initFromQueryResult( $queryResult );
741  }
742 
747  public function populateFromRevisionIDs( $revIDs ) {
748  $this->initFromRevIDs( $revIDs );
749  }
750 
755  public function processDbRow( $row ) {
756  // Store Title object in various data structures
757  $title = Title::newFromRow( $row );
758 
759  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
760  $linkCache->addGoodLinkObjFromRow( $title, $row );
761 
762  $pageId = (int)$row->page_id;
763  $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
764  $this->mTitles[] = $title;
765 
766  if ( $this->mResolveRedirects && $row->page_is_redirect == '1' ) {
767  $this->mPendingRedirectIDs[$pageId] = $title;
768  } else {
769  $this->mGoodPages[$row->page_namespace][$row->page_title] = $pageId;
770  $this->mGoodAndMissingPages[$row->page_namespace][$row->page_title] = $pageId;
771  $this->mGoodTitles[$pageId] = $title;
772  }
773 
774  foreach ( $this->mRequestedPageFields as $fieldName => &$fieldValues ) {
775  $fieldValues[$pageId] = $row->$fieldName;
776  }
777  }
778 
795  private function initFromTitles( $titles ) {
796  // Get validated and normalized title objects
797  $linkBatch = $this->processTitlesArray( $titles );
798  if ( $linkBatch->isEmpty() ) {
799  // There might be special-page redirects
800  $this->resolvePendingRedirects();
801  return;
802  }
803 
804  $db = $this->getDB();
805  $set = $linkBatch->constructSet( 'page', $db );
806 
807  // Get pageIDs data from the `page` table
808  $res = $db->select( 'page', $this->getPageTableFields(), $set,
809  __METHOD__ );
810 
811  // Hack: get the ns:titles stored in [ ns => [ titles ] ] format
812  $this->initFromQueryResult( $res, $linkBatch->data, true ); // process Titles
813 
814  // Resolve any found redirects
815  $this->resolvePendingRedirects();
816  }
817 
823  private function initFromPageIds( $pageids, $filterIds = true ) {
824  if ( !$pageids ) {
825  return;
826  }
827 
828  $pageids = array_map( 'intval', $pageids ); // paranoia
829  $remaining = array_flip( $pageids );
830 
831  if ( $filterIds ) {
832  $pageids = $this->filterIDs( [ [ 'page', 'page_id' ] ], $pageids );
833  }
834 
835  $res = null;
836  if ( !empty( $pageids ) ) {
837  $set = [
838  'page_id' => $pageids
839  ];
840  $db = $this->getDB();
841 
842  // Get pageIDs data from the `page` table
843  $res = $db->select( 'page', $this->getPageTableFields(), $set,
844  __METHOD__ );
845  }
846 
847  $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
848 
849  // Resolve any found redirects
850  $this->resolvePendingRedirects();
851  }
852 
863  private function initFromQueryResult( $res, &$remaining = null, $processTitles = null ) {
864  if ( $remaining !== null && $processTitles === null ) {
865  ApiBase::dieDebug( __METHOD__, 'Missing $processTitles parameter when $remaining is provided' );
866  }
867 
868  $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
869 
870  $usernames = [];
871  if ( $res ) {
872  foreach ( $res as $row ) {
873  $pageId = (int)$row->page_id;
874 
875  // Remove found page from the list of remaining items
876  if ( isset( $remaining ) ) {
877  if ( $processTitles ) {
878  unset( $remaining[$row->page_namespace][$row->page_title] );
879  } else {
880  unset( $remaining[$pageId] );
881  }
882  }
883 
884  // Store any extra fields requested by modules
885  $this->processDbRow( $row );
886 
887  // Need gender information
888  if ( $nsInfo->hasGenderDistinction( $row->page_namespace ) ) {
889  $usernames[] = $row->page_title;
890  }
891  }
892  }
893 
894  if ( isset( $remaining ) ) {
895  // Any items left in the $remaining list are added as missing
896  if ( $processTitles ) {
897  // The remaining titles in $remaining are non-existent pages
898  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
899  foreach ( $remaining as $ns => $dbkeys ) {
900  foreach ( array_keys( $dbkeys ) as $dbkey ) {
901  $title = Title::makeTitle( $ns, $dbkey );
902  $linkCache->addBadLinkObj( $title );
903  $this->mAllPages[$ns][$dbkey] = $this->mFakePageId;
904  $this->mMissingPages[$ns][$dbkey] = $this->mFakePageId;
905  $this->mGoodAndMissingPages[$ns][$dbkey] = $this->mFakePageId;
906  $this->mMissingTitles[$this->mFakePageId] = $title;
907  $this->mFakePageId--;
908  $this->mTitles[] = $title;
909 
910  // need gender information
911  if ( $nsInfo->hasGenderDistinction( $ns ) ) {
912  $usernames[] = $dbkey;
913  }
914  }
915  }
916  } else {
917  // The remaining pageids do not exist
918  if ( !$this->mMissingPageIDs ) {
919  $this->mMissingPageIDs = array_keys( $remaining );
920  } else {
921  $this->mMissingPageIDs = array_merge( $this->mMissingPageIDs, array_keys( $remaining ) );
922  }
923  }
924  }
925 
926  // Get gender information
927  $genderCache = MediaWikiServices::getInstance()->getGenderCache();
928  $genderCache->doQuery( $usernames, __METHOD__ );
929  }
930 
936  private function initFromRevIDs( $revids ) {
937  if ( !$revids ) {
938  return;
939  }
940 
941  $revids = array_map( 'intval', $revids ); // paranoia
942  $db = $this->getDB();
943  $pageids = [];
944  $remaining = array_flip( $revids );
945 
946  $revids = $this->filterIDs( [ [ 'revision', 'rev_id' ], [ 'archive', 'ar_rev_id' ] ], $revids );
947  $goodRemaining = array_flip( $revids );
948 
949  if ( $revids ) {
950  $tables = [ 'revision', 'page' ];
951  $fields = [ 'rev_id', 'rev_page' ];
952  $where = [ 'rev_id' => $revids, 'rev_page = page_id' ];
953 
954  // Get pageIDs data from the `page` table
955  $res = $db->select( $tables, $fields, $where, __METHOD__ );
956  foreach ( $res as $row ) {
957  $revid = (int)$row->rev_id;
958  $pageid = (int)$row->rev_page;
959  $this->mGoodRevIDs[$revid] = $pageid;
960  $this->mLiveRevIDs[$revid] = $pageid;
961  $pageids[$pageid] = '';
962  unset( $remaining[$revid] );
963  unset( $goodRemaining[$revid] );
964  }
965  }
966 
967  // Populate all the page information
968  $this->initFromPageIds( array_keys( $pageids ), false );
969 
970  // If the user can see deleted revisions, pull out the corresponding
971  // titles from the archive table and include them too. We ignore
972  // ar_page_id because deleted revisions are tied by title, not page_id.
973  if ( $goodRemaining &&
974  $this->getPermissionManager()->userHasRight( $this->getUser(), 'deletedhistory' ) ) {
975  $tables = [ 'archive' ];
976  $fields = [ 'ar_rev_id', 'ar_namespace', 'ar_title' ];
977  $where = [ 'ar_rev_id' => array_keys( $goodRemaining ) ];
978 
979  $res = $db->select( $tables, $fields, $where, __METHOD__ );
980  $titles = [];
981  foreach ( $res as $row ) {
982  $revid = (int)$row->ar_rev_id;
983  $titles[$revid] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
984  unset( $remaining[$revid] );
985  }
986 
987  $this->initFromTitles( $titles );
988 
989  foreach ( $titles as $revid => $title ) {
990  $ns = $title->getNamespace();
991  $dbkey = $title->getDBkey();
992 
993  // Handle converted titles
994  if ( !isset( $this->mAllPages[$ns][$dbkey] ) &&
995  isset( $this->mConvertedTitles[$title->getPrefixedText()] )
996  ) {
997  $title = Title::newFromText( $this->mConvertedTitles[$title->getPrefixedText()] );
998  $ns = $title->getNamespace();
999  $dbkey = $title->getDBkey();
1000  }
1001 
1002  if ( isset( $this->mAllPages[$ns][$dbkey] ) ) {
1003  $this->mGoodRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1004  $this->mDeletedRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1005  } else {
1006  $remaining[$revid] = true;
1007  }
1008  }
1009  }
1010 
1011  $this->mMissingRevIDs = array_keys( $remaining );
1012  }
1013 
1019  private function resolvePendingRedirects() {
1020  if ( $this->mResolveRedirects ) {
1021  $db = $this->getDB();
1022  $pageFlds = $this->getPageTableFields();
1023 
1024  // Repeat until all redirects have been resolved
1025  // The infinite loop is prevented by keeping all known pages in $this->mAllPages
1026  while ( $this->mPendingRedirectIDs || $this->mPendingRedirectSpecialPages ) {
1027  // Resolve redirects by querying the pagelinks table, and repeat the process
1028  // Create a new linkBatch object for the next pass
1029  $linkBatch = $this->getRedirectTargets();
1030 
1031  if ( $linkBatch->isEmpty() ) {
1032  break;
1033  }
1034 
1035  $set = $linkBatch->constructSet( 'page', $db );
1036  if ( $set === false ) {
1037  break;
1038  }
1039 
1040  // Get pageIDs data from the `page` table
1041  $res = $db->select( 'page', $pageFlds, $set, __METHOD__ );
1042 
1043  // Hack: get the ns:titles stored in [ns => array(titles)] format
1044  $this->initFromQueryResult( $res, $linkBatch->data, true );
1045  }
1046  }
1047  }
1048 
1056  private function getRedirectTargets() {
1057  $titlesToResolve = [];
1058  $db = $this->getDB();
1059 
1060  if ( $this->mPendingRedirectIDs ) {
1061  $res = $db->select(
1062  'redirect',
1063  [
1064  'rd_from',
1065  'rd_namespace',
1066  'rd_fragment',
1067  'rd_interwiki',
1068  'rd_title'
1069  ], [ 'rd_from' => array_keys( $this->mPendingRedirectIDs ) ],
1070  __METHOD__
1071  );
1072  foreach ( $res as $row ) {
1073  $rdfrom = (int)$row->rd_from;
1074  $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
1075  $to = Title::makeTitle(
1076  $row->rd_namespace,
1077  $row->rd_title,
1078  $row->rd_fragment,
1079  $row->rd_interwiki
1080  );
1081  $this->mResolvedRedirectTitles[$from] = $this->mPendingRedirectIDs[$rdfrom];
1082  unset( $this->mPendingRedirectIDs[$rdfrom] );
1083  if ( $to->isExternal() ) {
1084  $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1085  } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1086  $titlesToResolve[] = $to;
1087  }
1088  $this->mRedirectTitles[$from] = $to;
1089  }
1090 
1091  if ( $this->mPendingRedirectIDs ) {
1092  // We found pages that aren't in the redirect table
1093  // Add them
1094  foreach ( $this->mPendingRedirectIDs as $id => $title ) {
1095  $page = WikiPage::factory( $title );
1096  $rt = $page->insertRedirect();
1097  if ( !$rt ) {
1098  // What the hell. Let's just ignore this
1099  continue;
1100  }
1101  if ( $rt->isExternal() ) {
1102  $this->mInterwikiTitles[$rt->getPrefixedText()] = $rt->getInterwiki();
1103  } elseif ( !isset( $this->mAllPages[$rt->getNamespace()][$rt->getDBkey()] ) ) {
1104  $titlesToResolve[] = $rt;
1105  }
1106  $from = $title->getPrefixedText();
1107  $this->mResolvedRedirectTitles[$from] = $title;
1108  $this->mRedirectTitles[$from] = $rt;
1109  unset( $this->mPendingRedirectIDs[$id] );
1110  }
1111  }
1112  }
1113 
1114  if ( $this->mPendingRedirectSpecialPages ) {
1115  foreach ( $this->mPendingRedirectSpecialPages as $key => list( $from, $to ) ) {
1117  $fromKey = $from->getPrefixedText();
1118  $this->mResolvedRedirectTitles[$fromKey] = $from;
1119  $this->mRedirectTitles[$fromKey] = $to;
1120  if ( $to->isExternal() ) {
1121  $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1122  } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1123  $titlesToResolve[] = $to;
1124  }
1125  }
1126  $this->mPendingRedirectSpecialPages = [];
1127 
1128  // Set private caching since we don't know what criteria the
1129  // special pages used to decide on these redirects.
1130  $this->mCacheMode = 'private';
1131  }
1132 
1133  return $this->processTitlesArray( $titlesToResolve );
1134  }
1135 
1149  public function getCacheMode( $params = null ) {
1150  return $this->mCacheMode;
1151  }
1152 
1162  private function processTitlesArray( $titles ) {
1163  $linkBatch = new LinkBatch();
1164  $services = MediaWikiServices::getInstance();
1165  $contLang = $services->getContentLanguage();
1166 
1167  $titleObjects = [];
1168  foreach ( $titles as $index => $title ) {
1169  if ( is_string( $title ) ) {
1170  try {
1172  $titleObj = Title::newFromTextThrow( $title, $this->mDefaultNamespace );
1173  } catch ( MalformedTitleException $ex ) {
1174  // Handle invalid titles gracefully
1175  if ( !isset( $this->mAllPages[0][$title] ) ) {
1176  $this->mAllPages[0][$title] = $this->mFakePageId;
1177  $this->mInvalidTitles[$this->mFakePageId] = [
1178  'title' => $title,
1179  'invalidreason' => $this->getErrorFormatter()->formatException( $ex, [ 'bc' => true ] ),
1180  ];
1181  $this->mFakePageId--;
1182  }
1183  continue; // There's nothing else we can do
1184  }
1185  } else {
1186  $titleObj = $title;
1187  }
1188 
1189  $titleObjects[$index] = $titleObj;
1190  }
1191 
1192  // Get gender information
1193  $genderCache = $services->getGenderCache();
1194  $genderCache->doTitlesArray( $titleObjects, __METHOD__ );
1195 
1196  foreach ( $titleObjects as $index => $titleObj ) {
1197  $title = is_string( $titles[$index] ) ? $titles[$index] : false;
1198  $unconvertedTitle = $titleObj->getPrefixedText();
1199  $titleWasConverted = false;
1200  if ( $titleObj->isExternal() ) {
1201  // This title is an interwiki link.
1202  $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
1203  } else {
1204  // Variants checking
1205  if (
1206  $this->mConvertTitles && $contLang->hasVariants() && !$titleObj->exists()
1207  ) {
1208  // Language::findVariantLink will modify titleText and titleObj into
1209  // the canonical variant if possible
1210  $titleText = $title !== false ? $title : $titleObj->getPrefixedText();
1211  $contLang->findVariantLink( $titleText, $titleObj );
1212  $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText();
1213  }
1214 
1215  if ( $titleObj->getNamespace() < 0 ) {
1216  // Handle Special and Media pages
1217  $titleObj = $titleObj->fixSpecialName();
1218  $ns = $titleObj->getNamespace();
1219  $dbkey = $titleObj->getDBkey();
1220  if ( !isset( $this->mAllSpecials[$ns][$dbkey] ) ) {
1221  $this->mAllSpecials[$ns][$dbkey] = $this->mFakePageId;
1222  $target = null;
1223  if ( $ns === NS_SPECIAL && $this->mResolveRedirects ) {
1224  $spFactory = $services->getSpecialPageFactory();
1225  $special = $spFactory->getPage( $dbkey );
1226  if ( $special instanceof RedirectSpecialArticle ) {
1227  // Only RedirectSpecialArticle is intended to redirect to an article, other kinds of
1228  // RedirectSpecialPage are probably applying weird URL parameters we don't want to
1229  // 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,
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  public 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 = ParamValidator::explodeMultiValue( $value, self::LIMIT_SML2 + 1 );
1481  $l = count( $value );
1482  $rawValue = ParamValidator::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 }
ApiPageSet\$mPendingRedirectIDs
Title[] $mPendingRedirectIDs
Definition: ApiPageSet.php:71
ApiPageSet\$mConvertedTitles
$mConvertedTitles
Definition: ApiPageSet.php:74
ApiPageSet\getTitleCount
getTitleCount()
Returns the number of unique pages (not revisions) in the set.
Definition: ApiPageSet.php:358
ApiPageSet\$mRedirectTitles
$mRedirectTitles
Definition: ApiPageSet.php:65
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:33
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:63
ApiBase\PARAM_SUBMODULE_MAP
const PARAM_SUBMODULE_MAP
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:75
ApiPageSet\initFromTitles
initFromTitles( $titles)
This method populates internal variables with page information based on the given array of title stri...
Definition: ApiPageSet.php:795
ApiPageSet\$mSpecialTitles
$mSpecialTitles
Definition: ApiPageSet.php:66
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:33
ApiPageSet\$mMissingTitles
$mMissingTitles
Definition: ApiPageSet.php:61
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:329
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:1334
ApiPageSet\processDbRow
processDbRow( $row)
Extract all requested fields from the row received from the database.
Definition: ApiPageSet.php:755
ApiPageSet\$mResolveRedirects
$mResolveRedirects
Definition: ApiPageSet.php:51
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:35
ApiPageSet\getGoodTitleCount
getGoodTitleCount()
Returns the number of found unique pages (not revisions) in the set.
Definition: ApiPageSet.php:382
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:152
ApiPageSet\processTitlesArray
processTitlesArray( $titles)
Given an array of title strings, convert them into Title objects.
Definition: ApiPageSet.php:1162
if
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:85
ApiPageSet\getTitles
getTitles()
All Title objects provided.
Definition: ApiPageSet.php:350
ApiPageSet\getConvertedTitles
getConvertedTitles()
Get a list of title conversions - maps a title to its converted version.
Definition: ApiPageSet.php:523
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1415
ApiBase\PARAM_HELP_MSG
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:104
ApiPageSet\__construct
__construct(ApiBase $dbSource, $flags=0, $defaultNamespace=NS_MAIN)
Definition: ApiPageSet.php:120
ApiPageSet\getLiveRevisionIDs
getLiveRevisionIDs()
Get the list of non-deleted revision IDs (requested with the revids= parameter)
Definition: ApiPageSet.php:658
ApiBase\PARAM_TYPE
const PARAM_TYPE
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:68
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:863
ApiPageSet\requestField
requestField( $fieldName)
Request an additional field from the page table.
Definition: ApiPageSet.php:288
ApiPageSet\execute
execute()
Populate the PageSet from the request parameters.
Definition: ApiPageSet.php:142
Title\getPrefixedText
getPrefixedText()
Get the prefixed title with spaces.
Definition: Title.php:1850
ApiPageSet\$mDefaultNamespace
int $mDefaultNamespace
Definition: ApiPageSet.php:85
ApiPageSet\$mCacheMode
$mCacheMode
Definition: ApiPageSet.php:81
ApiPageSet\$mInterwikiTitles
$mInterwikiTitles
Definition: ApiPageSet.php:69
ApiPageSet\$mGoodPages
$mGoodPages
Definition: ApiPageSet.php:58
ApiPageSet\$mRedirectMergePolicy
callable null $mRedirectMergePolicy
Definition: ApiPageSet.php:87
ApiPageSet\initFromPageIds
initFromPageIds( $pageids, $filterIds=true)
Does the same as initFromTitles(), but is based on page IDs instead.
Definition: ApiPageSet.php:823
ApiPageSet\resolvePendingRedirects
resolvePendingRedirects()
Resolve any redirects in the result if redirect resolution was requested.
Definition: ApiPageSet.php:1019
ApiPageSet\getDeletedRevisionIDs
getDeletedRevisionIDs()
Get the list of revision IDs that were associated with deleted titles.
Definition: ApiPageSet.php:666
ApiPageSet\$mLiveRevIDs
$mLiveRevIDs
Definition: ApiPageSet.php:76
ApiPageSet\populateFromRevisionIDs
populateFromRevisionIDs( $revIDs)
Populate this PageSet from a list of revision IDs.
Definition: ApiPageSet.php:747
ApiPageSet\addValues
static addValues(array &$result, $values, $flags=[], $name=null)
Add all items from $values into the result.
Definition: ApiPageSet.php:96
ApiPageSet\$mConvertTitles
$mConvertTitles
Definition: ApiPageSet.php:52
ApiPageSet\$mGeneratorData
$mGeneratorData
Definition: ApiPageSet.php:79
$res
$res
Definition: testCompression.php:57
ContextSource\getUser
getUser()
Definition: ContextSource.php:120
ApiPageSet\$mMissingPages
$mMissingPages
Definition: ApiPageSet.php:60
ApiPageSet\getGoodAndMissingTitlesByNamespace
getGoodAndMissingTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good and missing titles.
Definition: ApiPageSet.php:408
ApiPageSet\$mPendingRedirectSpecialPages
$mPendingRedirectSpecialPages
Definition: ApiPageSet.php:72
ApiPageSet\populateFromTitles
populateFromTitles( $titles)
Populate this PageSet from a list of Titles.
Definition: ApiPageSet.php:718
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:219
Message\listParam
static listParam(array $list, $type='text')
Definition: Message.php:1123
ApiPageSet\setGeneratorData
setGeneratorData(Title $title, array $data)
Set data for a title.
Definition: ApiPageSet.php:1285
ApiPageSet\$mGoodRevIDs
$mGoodRevIDs
Definition: ApiPageSet.php:75
ApiPageSet
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:42
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:50
ApiPageSet\executeDryRun
executeDryRun()
In case execute() is not called, call this method to mark all relevant parameters as used This preven...
Definition: ApiPageSet.php:135
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:453
ApiPageSet\getPageTableFields
getPageTableFields()
Get the fields that have to be queried from the page table: the ones requested through requestField()...
Definition: ApiPageSet.php:308
ApiPageSet\$mInvalidTitles
array $mInvalidTitles
[fake_page_id] => [ 'title' => $title, 'invalidreason' => $reason ]
Definition: ApiPageSet.php:63
ApiPageSet\$mAllowGenerator
$mAllowGenerator
Definition: ApiPageSet.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:534
ApiPageSet\$mParams
$mParams
Definition: ApiPageSet.php:50
NS_MAIN
const NS_MAIN
Definition: Defines.php:69
ApiPageSet\getMissingTitles
getMissingTitles()
Title objects that were NOT found in the database.
Definition: ApiPageSet.php:400
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:58
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:30
ApiPageSet\getMissingTitlesByNamespace
getMissingTitlesByNamespace()
Returns an array [ns][dbkey] => fake_page_id for all missing titles.
Definition: ApiPageSet.php:391
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:154
ApiPageSet\populateFromQueryResult
populateFromQueryResult( $db, $queryResult)
Populate this PageSet from a rowset returned from the database.
Definition: ApiPageSet.php:739
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:24
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:524
ApiPageSet\$mGoodAndMissingPages
$mGoodAndMissingPages
Definition: ApiPageSet.php:57
ApiPageSet\getGenerators
getGenerators()
Get an array of all available generators.
Definition: ApiPageSet.php:1497
ApiPageSet\getDataSource
getDataSource()
Return the parameter name that is the source of data for this PageSet.
Definition: ApiPageSet.php:266
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:211
ApiPageSet\$mRequestedPageFields
array $mRequestedPageFields
Definition: ApiPageSet.php:83
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:695
ApiPageSet\getRevisionIDs
getRevisionIDs()
Get the list of valid revision IDs (requested with the revids= parameter)
Definition: ApiPageSet.php:650
ApiPageSet\$mTitles
$mTitles
Definition: ApiPageSet.php:56
$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, as an array of output-ready...
Definition: ApiPageSet.php:442
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:592
ApiPageSet\getGoodTitles
getGoodTitles()
Title objects that were found in the database.
Definition: ApiPageSet.php:374
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:87
Title\newFromTextThrow
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid,...
Definition: Title.php:364
ApiPageSet\isResolvingRedirects
isResolvingRedirects()
Check whether this PageSet is resolving redirects.
Definition: ApiPageSet.php:254
ApiPageSet\$mGoodTitles
$mGoodTitles
Definition: ApiPageSet.php:59
ApiPageSet\getGoodAndMissingTitles
getGoodAndMissingTitles()
Title objects for good and missing titles.
Definition: ApiPageSet.php:416
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:604
ApiPageSet\getCacheMode
getCacheMode( $params=null)
Get the cache mode for the data generated by this module.
Definition: ApiPageSet.php:1149
ApiPageSet\initFromRevIDs
initFromRevIDs( $revids)
Does the same as initFromTitles(), but is based on revision IDs instead.
Definition: ApiPageSet.php:936
ApiBase\encodeParamName
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:673
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:175
ApiPageSet\getInterwikiTitles
getInterwikiTitles()
Get a list of interwiki titles - maps a title to its interwiki prefix.
Definition: ApiPageSet.php:554
ApiPageSet\getAllTitlesByNamespace
getAllTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all requested titles.
Definition: ApiPageSet.php:342
ApiPageSet\$mMissingRevIDs
$mMissingRevIDs
Definition: ApiPageSet.php:78
ApiPageSet\$generators
static $generators
Definition: ApiPageSet.php:1491
ApiPageSet\$mDbSource
$mDbSource
Definition: ApiPageSet.php:49
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:616
ApiPageSet\$mMissingPageIDs
$mMissingPageIDs
Definition: ApiPageSet.php:64
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:500
ApiPageSet\populateFromPageIDs
populateFromPageIDs( $pageIDs)
Populate this PageSet from a list of page IDs.
Definition: ApiPageSet.php:726
ApiPageSet\getDB
getDB()
Get the database connection (read-only)
Definition: ApiPageSet.php:1424
ApiPageSet\getAllowedParams
getAllowedParams( $flags=0)
Definition: ApiPageSet.php:1428
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:566
ApiPageSet\getMissingPageIDs
getMissingPageIDs()
Page IDs that were not found in the database.
Definition: ApiPageSet.php:433
ApiPageSet\$mDeletedRevIDs
$mDeletedRevIDs
Definition: ApiPageSet.php:77
ApiPageSet\$mResolvedRedirectTitles
$mResolvedRedirectTitles
Definition: ApiPageSet.php:73
ApiPageSet\getRedirectTargets
getRedirectTargets()
Get the targets of the pending redirects from the database.
Definition: ApiPageSet.php:1056
ApiQueryGeneratorBase
Definition: ApiQueryGeneratorBase.php:26
Title
Represents a title within MediaWiki.
Definition: Title.php:42
LanguageConverter\$languagesWithVariants
static array $languagesWithVariants
languages supporting variants
Definition: LanguageConverter.php:43
ApiBase\filterIDs
filterIDs( $fields, array $ids)
Filter out-of-range values from a list of positive integer IDs.
Definition: ApiBase.php:1286
ApiPageSet\getMissingRevisionIDsAsResult
getMissingRevisionIDsAsResult( $result=null)
Revision IDs that were not found in the database as result array.
Definition: ApiPageSet.php:684
MalformedTitleException
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Definition: MalformedTitleException.php:25
ApiPageSet\getInvalidTitlesAndRevisions
getInvalidTitlesAndRevisions( $invalidChecks=[ 'invalidTitles', 'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles'])
Get an array of invalid/special/missing titles.
Definition: ApiPageSet.php:600
ApiPageSet\getGoodTitlesByNamespace
getGoodTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good titles.
Definition: ApiPageSet.php:366
ApiPageSet\executeInternal
executeInternal( $isDryRun)
Populate the PageSet from the request parameters.
Definition: ApiPageSet.php:151
ApiPageSet\handleParamNormalization
handleParamNormalization( $paramName, $value, $rawValue)
Handle when a parameter was Unicode-normalized.
Definition: ApiPageSet.php:1474
ApiPageSet\setRedirectMergePolicy
setRedirectMergePolicy( $callable)
Controls how generator data about a redirect source is merged into the generator data for the redirec...
Definition: ApiPageSet.php:1310
$path
$path
Definition: NoLocalSettings.php:25
ApiBase\PARAM_DFLT
const PARAM_DFLT
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:66
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:426
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:67
ApiPageSet\getMissingRevisionIDs
getMissingRevisionIDs()
Revision IDs that were not found in the database.
Definition: ApiPageSet.php:674
ApiResult\OVERRIDE
const OVERRIDE
Override existing value in addValue(), setValue(), and similar functions.
Definition: ApiResult.php:41
ApiPageSet\getInvalidTitlesAndReasons
getInvalidTitlesAndReasons()
Titles that were deemed invalid by Title::newFromText() The array's index will be unique and negative...
Definition: ApiPageSet.php:425
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:442
ApiPageSet\$mAllSpecials
$mAllSpecials
Definition: ApiPageSet.php:67
ApiPageSet\getCustomField
getCustomField( $fieldName)
Get the value of a custom field previously requested through requestField()
Definition: ApiPageSet.php:298
ApiPageSet\getRevisionCount
getRevisionCount()
Returns the number of revisions (requested with revids= parameter).
Definition: ApiPageSet.php:710
ApiPageSet\$mAllPages
$mAllPages
Definition: ApiPageSet.php:55
ApiBase\PARAM_SUBMODULE_PARAM_PREFIX
const PARAM_SUBMODULE_PARAM_PREFIX
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:76
ApiPageSet\DISABLE_GENERATORS
const DISABLE_GENERATORS
Constructor flag: The new instance of ApiPageSet will ignore the 'generator=' parameter.
Definition: ApiPageSet.php:47
ApiBase\getHookRunner
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition: ApiBase.php:641
ApiPageSet\$mFakePageId
$mFakePageId
Definition: ApiPageSet.php:80
ApiPageSet\getSpecialTitles
getSpecialTitles()
Get the list of titles with negative namespace.
Definition: ApiPageSet.php:702
ApiPageSet\getNormalizedTitles
getNormalizedTitles()
Get a list of title normalizations - maps a title to its normalized version.
Definition: ApiPageSet.php:489
ApiBase\dieDebug
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition: ApiBase.php:1607
ApiPageSet\$mNormalizedTitles
$mNormalizedTitles
Definition: ApiPageSet.php:68
ApiBase\getErrorFormatter
getErrorFormatter()
Get the error formatter.
Definition: ApiBase.php:560
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:1334
ApiQueryBase\addTitleInfo
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
Definition: ApiQueryBase.php:463