MediaWiki REL1_30
ApiPageSet.php
Go to the documentation of this file.
1<?php
29
44class ApiPageSet extends ApiBase {
50
51 private $mDbSource;
52 private $mParams;
56
57 private $mAllPages = []; // [ns][dbkey] => page_id or negative when missing
58 private $mTitles = [];
59 private $mGoodAndMissingPages = []; // [ns][dbkey] => page_id or negative when missing
60 private $mGoodPages = []; // [ns][dbkey] => page_id
61 private $mGoodTitles = [];
62 private $mMissingPages = []; // [ns][dbkey] => fake page_id
63 private $mMissingTitles = [];
65 private $mInvalidTitles = [];
66 private $mMissingPageIDs = [];
67 private $mRedirectTitles = [];
68 private $mSpecialTitles = [];
69 private $mAllSpecials = []; // separate from mAllPages to avoid breaking getAllTitlesByNamespace()
70 private $mNormalizedTitles = [];
71 private $mInterwikiTitles = [];
74 private $mPendingRedirectSpecialPages = []; // [dbkey] => [ Title $from, Title $to ]
76 private $mConvertedTitles = [];
77 private $mGoodRevIDs = [];
78 private $mLiveRevIDs = [];
79 private $mDeletedRevIDs = [];
80 private $mMissingRevIDs = [];
81 private $mGeneratorData = []; // [ns][dbkey] => data array
82 private $mFakePageId = -1;
83 private $mCacheMode = 'public';
89
97 private static function addValues( array &$result, $values, $flags = [], $name = null ) {
98 foreach ( $values as $val ) {
99 if ( $val instanceof Title ) {
100 $v = [];
101 ApiQueryBase::addTitleInfo( $v, $val );
102 } elseif ( $name !== null ) {
103 $v = [ $name => $val ];
104 } else {
105 $v = $val;
106 }
107 foreach ( $flags as $flag ) {
108 $v[$flag] = true;
109 }
110 $result[] = $v;
111 }
112 }
113
121 public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) {
122 parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() );
123 $this->mDbSource = $dbSource;
124 $this->mAllowGenerator = ( $flags & self::DISABLE_GENERATORS ) == 0;
125 $this->mDefaultNamespace = $defaultNamespace;
126
127 $this->mParams = $this->extractRequestParams();
128 $this->mResolveRedirects = $this->mParams['redirects'];
129 $this->mConvertTitles = $this->mParams['converttitles'];
130 }
131
136 public function executeDryRun() {
137 $this->executeInternal( true );
138 }
139
143 public function execute() {
144 $this->executeInternal( false );
145 }
146
152 private function executeInternal( $isDryRun ) {
153 $generatorName = $this->mAllowGenerator ? $this->mParams['generator'] : null;
154 if ( isset( $generatorName ) ) {
155 $dbSource = $this->mDbSource;
156 if ( !$dbSource instanceof ApiQuery ) {
157 // If the parent container of this pageset is not ApiQuery, we must create it to run generator
158 $dbSource = $this->getMain()->getModuleManager()->getModule( 'query' );
159 }
160 $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true );
161 if ( $generator === null ) {
162 $this->dieWithError( [ 'apierror-badgenerator-unknown', $generatorName ], 'badgenerator' );
163 }
164 if ( !$generator instanceof ApiQueryGeneratorBase ) {
165 $this->dieWithError( [ 'apierror-badgenerator-notgenerator', $generatorName ], 'badgenerator' );
166 }
167 // Create a temporary pageset to store generator's output,
168 // add any additional fields generator may need, and execute pageset to populate titles/pageids
169 $tmpPageSet = new ApiPageSet( $dbSource, self::DISABLE_GENERATORS );
170 $generator->setGeneratorMode( $tmpPageSet );
171 $this->mCacheMode = $generator->getCacheMode( $generator->extractRequestParams() );
172
173 if ( !$isDryRun ) {
174 $generator->requestExtraData( $tmpPageSet );
175 }
176 $tmpPageSet->executeInternal( $isDryRun );
177
178 // populate this pageset with the generator output
179 if ( !$isDryRun ) {
180 $generator->executeGenerator( $this );
181
182 // Avoid PHP 7.1 warning of passing $this by reference
183 $apiModule = $this;
184 Hooks::run( 'APIQueryGeneratorAfterExecute', [ &$generator, &$apiModule ] );
185 } else {
186 // Prevent warnings from being reported on these parameters
187 $main = $this->getMain();
188 foreach ( $generator->extractRequestParams() as $paramName => $param ) {
189 $main->markParamsUsed( $generator->encodeParamName( $paramName ) );
190 }
191 }
192
193 if ( !$isDryRun ) {
195 }
196 } else {
197 // Only one of the titles/pageids/revids is allowed at the same time
198 $dataSource = null;
199 if ( isset( $this->mParams['titles'] ) ) {
200 $dataSource = 'titles';
201 }
202 if ( isset( $this->mParams['pageids'] ) ) {
203 if ( isset( $dataSource ) ) {
204 $this->dieWithError(
205 [
206 'apierror-invalidparammix-cannotusewith',
207 $this->encodeParamName( 'pageids' ),
208 $this->encodeParamName( $dataSource )
209 ],
210 'multisource'
211 );
212 }
213 $dataSource = 'pageids';
214 }
215 if ( isset( $this->mParams['revids'] ) ) {
216 if ( isset( $dataSource ) ) {
217 $this->dieWithError(
218 [
219 'apierror-invalidparammix-cannotusewith',
220 $this->encodeParamName( 'revids' ),
221 $this->encodeParamName( $dataSource )
222 ],
223 'multisource'
224 );
225 }
226 $dataSource = 'revids';
227 }
228
229 if ( !$isDryRun ) {
230 // Populate page information with the original user input
231 switch ( $dataSource ) {
232 case 'titles':
233 $this->initFromTitles( $this->mParams['titles'] );
234 break;
235 case 'pageids':
236 $this->initFromPageIds( $this->mParams['pageids'] );
237 break;
238 case 'revids':
239 if ( $this->mResolveRedirects ) {
240 $this->addWarning( 'apiwarn-redirectsandrevids' );
241 }
242 $this->mResolveRedirects = false;
243 $this->initFromRevIDs( $this->mParams['revids'] );
244 break;
245 default:
246 // Do nothing - some queries do not need any of the data sources.
247 break;
248 }
249 }
250 }
251 }
252
257 public function isResolvingRedirects() {
259 }
260
269 public function getDataSource() {
270 if ( $this->mAllowGenerator && isset( $this->mParams['generator'] ) ) {
271 return 'generator';
272 }
273 if ( isset( $this->mParams['titles'] ) ) {
274 return 'titles';
275 }
276 if ( isset( $this->mParams['pageids'] ) ) {
277 return 'pageids';
278 }
279 if ( isset( $this->mParams['revids'] ) ) {
280 return 'revids';
281 }
282
283 return null;
284 }
285
291 public function requestField( $fieldName ) {
292 $this->mRequestedPageFields[$fieldName] = null;
293 }
294
301 public function getCustomField( $fieldName ) {
302 return $this->mRequestedPageFields[$fieldName];
303 }
304
311 public function getPageTableFields() {
312 // Ensure we get minimum required fields
313 // DON'T change this order
314 $pageFlds = [
315 'page_namespace' => null,
316 'page_title' => null,
317 'page_id' => null,
318 ];
319
320 if ( $this->mResolveRedirects ) {
321 $pageFlds['page_is_redirect'] = null;
322 }
323
324 if ( $this->getConfig()->get( 'ContentHandlerUseDB' ) ) {
325 $pageFlds['page_content_model'] = null;
326 }
327
328 if ( $this->getConfig()->get( 'PageLanguageUseDB' ) ) {
329 $pageFlds['page_lang'] = null;
330 }
331
332 foreach ( LinkCache::getSelectFields() as $field ) {
333 $pageFlds[$field] = null;
334 }
335
336 $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
337
338 return array_keys( $pageFlds );
339 }
340
347 public function getAllTitlesByNamespace() {
348 return $this->mAllPages;
349 }
350
355 public function getTitles() {
356 return $this->mTitles;
357 }
358
363 public function getTitleCount() {
364 return count( $this->mTitles );
365 }
366
371 public function getGoodTitlesByNamespace() {
372 return $this->mGoodPages;
373 }
374
379 public function getGoodTitles() {
380 return $this->mGoodTitles;
381 }
382
387 public function getGoodTitleCount() {
388 return count( $this->mGoodTitles );
389 }
390
396 public function getMissingTitlesByNamespace() {
398 }
399
405 public function getMissingTitles() {
407 }
408
416
421 public function getGoodAndMissingTitles() {
422 return $this->mGoodTitles + $this->mMissingTitles;
423 }
424
431 public function getInvalidTitles() {
432 wfDeprecated( __METHOD__, '1.26' );
433 return array_map( function ( $t ) {
434 return $t['title'];
436 }
437
443 public function getInvalidTitlesAndReasons() {
445 }
446
451 public function getMissingPageIDs() {
453 }
454
460 public function getRedirectTitles() {
462 }
463
471 public function getRedirectTitlesAsResult( $result = null ) {
472 $values = [];
473 foreach ( $this->getRedirectTitles() as $titleStrFrom => $titleTo ) {
474 $r = [
475 'from' => strval( $titleStrFrom ),
476 'to' => $titleTo->getPrefixedText(),
477 ];
478 if ( $titleTo->hasFragment() ) {
479 $r['tofragment'] = $titleTo->getFragment();
480 }
481 if ( $titleTo->isExternal() ) {
482 $r['tointerwiki'] = $titleTo->getInterwiki();
483 }
484 if ( isset( $this->mResolvedRedirectTitles[$titleStrFrom] ) ) {
485 $titleFrom = $this->mResolvedRedirectTitles[$titleStrFrom];
486 $ns = $titleFrom->getNamespace();
487 $dbkey = $titleFrom->getDBkey();
488 if ( isset( $this->mGeneratorData[$ns][$dbkey] ) ) {
489 $r = array_merge( $this->mGeneratorData[$ns][$dbkey], $r );
490 }
491 }
492
493 $values[] = $r;
494 }
495 if ( !empty( $values ) && $result ) {
496 ApiResult::setIndexedTagName( $values, 'r' );
497 }
498
499 return $values;
500 }
501
507 public function getNormalizedTitles() {
509 }
510
518 public function getNormalizedTitlesAsResult( $result = null ) {
519 global $wgContLang;
520
521 $values = [];
522 foreach ( $this->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
523 $encode = ( $wgContLang->normalize( $rawTitleStr ) !== $rawTitleStr );
524 $values[] = [
525 'fromencoded' => $encode,
526 'from' => $encode ? rawurlencode( $rawTitleStr ) : $rawTitleStr,
527 'to' => $titleStr
528 ];
529 }
530 if ( !empty( $values ) && $result ) {
531 ApiResult::setIndexedTagName( $values, 'n' );
532 }
533
534 return $values;
535 }
536
542 public function getConvertedTitles() {
544 }
545
553 public function getConvertedTitlesAsResult( $result = null ) {
554 $values = [];
555 foreach ( $this->getConvertedTitles() as $rawTitleStr => $titleStr ) {
556 $values[] = [
557 'from' => $rawTitleStr,
558 'to' => $titleStr
559 ];
560 }
561 if ( !empty( $values ) && $result ) {
562 ApiResult::setIndexedTagName( $values, 'c' );
563 }
564
565 return $values;
566 }
567
573 public function getInterwikiTitles() {
575 }
576
585 public function getInterwikiTitlesAsResult( $result = null, $iwUrl = false ) {
586 $values = [];
587 foreach ( $this->getInterwikiTitles() as $rawTitleStr => $interwikiStr ) {
588 $item = [
589 'title' => $rawTitleStr,
590 'iw' => $interwikiStr,
591 ];
592 if ( $iwUrl ) {
593 $title = Title::newFromText( $rawTitleStr );
594 $item['url'] = $title->getFullURL( '', false, PROTO_CURRENT );
595 }
596 $values[] = $item;
597 }
598 if ( !empty( $values ) && $result ) {
599 ApiResult::setIndexedTagName( $values, 'i' );
600 }
601
602 return $values;
603 }
604
619 public function getInvalidTitlesAndRevisions( $invalidChecks = [ 'invalidTitles',
620 'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles' ]
621 ) {
622 $result = [];
623 if ( in_array( 'invalidTitles', $invalidChecks ) ) {
624 self::addValues( $result, $this->getInvalidTitlesAndReasons(), [ 'invalid' ] );
625 }
626 if ( in_array( 'special', $invalidChecks ) ) {
627 $known = [];
628 $unknown = [];
629 foreach ( $this->getSpecialTitles() as $title ) {
630 if ( $title->isKnown() ) {
631 $known[] = $title;
632 } else {
633 $unknown[] = $title;
634 }
635 }
636 self::addValues( $result, $unknown, [ 'special', 'missing' ] );
637 self::addValues( $result, $known, [ 'special' ] );
638 }
639 if ( in_array( 'missingIds', $invalidChecks ) ) {
640 self::addValues( $result, $this->getMissingPageIDs(), [ 'missing' ], 'pageid' );
641 }
642 if ( in_array( 'missingRevIds', $invalidChecks ) ) {
643 self::addValues( $result, $this->getMissingRevisionIDs(), [ 'missing' ], 'revid' );
644 }
645 if ( in_array( 'missingTitles', $invalidChecks ) ) {
646 $known = [];
647 $unknown = [];
648 foreach ( $this->getMissingTitles() as $title ) {
649 if ( $title->isKnown() ) {
650 $known[] = $title;
651 } else {
652 $unknown[] = $title;
653 }
654 }
655 self::addValues( $result, $unknown, [ 'missing' ] );
656 self::addValues( $result, $known, [ 'missing', 'known' ] );
657 }
658 if ( in_array( 'interwikiTitles', $invalidChecks ) ) {
659 self::addValues( $result, $this->getInterwikiTitlesAsResult() );
660 }
661
662 return $result;
663 }
664
669 public function getRevisionIDs() {
670 return $this->mGoodRevIDs;
671 }
672
677 public function getLiveRevisionIDs() {
678 return $this->mLiveRevIDs;
679 }
680
685 public function getDeletedRevisionIDs() {
687 }
688
693 public function getMissingRevisionIDs() {
695 }
696
703 public function getMissingRevisionIDsAsResult( $result = null ) {
704 $values = [];
705 foreach ( $this->getMissingRevisionIDs() as $revid ) {
706 $values[$revid] = [
707 'revid' => $revid
708 ];
709 }
710 if ( !empty( $values ) && $result ) {
711 ApiResult::setIndexedTagName( $values, 'rev' );
712 }
713
714 return $values;
715 }
716
721 public function getSpecialTitles() {
723 }
724
729 public function getRevisionCount() {
730 return count( $this->getRevisionIDs() );
731 }
732
737 public function populateFromTitles( $titles ) {
738 $this->initFromTitles( $titles );
739 }
740
745 public function populateFromPageIDs( $pageIDs ) {
746 $this->initFromPageIds( $pageIDs );
747 }
748
758 public function populateFromQueryResult( $db, $queryResult ) {
759 $this->initFromQueryResult( $queryResult );
760 }
761
766 public function populateFromRevisionIDs( $revIDs ) {
767 $this->initFromRevIDs( $revIDs );
768 }
769
774 public function processDbRow( $row ) {
775 // Store Title object in various data structures
776 $title = Title::newFromRow( $row );
777
778 LinkCache::singleton()->addGoodLinkObjFromRow( $title, $row );
779
780 $pageId = intval( $row->page_id );
781 $this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
782 $this->mTitles[] = $title;
783
784 if ( $this->mResolveRedirects && $row->page_is_redirect == '1' ) {
785 $this->mPendingRedirectIDs[$pageId] = $title;
786 } else {
787 $this->mGoodPages[$row->page_namespace][$row->page_title] = $pageId;
788 $this->mGoodAndMissingPages[$row->page_namespace][$row->page_title] = $pageId;
789 $this->mGoodTitles[$pageId] = $title;
790 }
791
792 foreach ( $this->mRequestedPageFields as $fieldName => &$fieldValues ) {
793 $fieldValues[$pageId] = $row->$fieldName;
794 }
795 }
796
813 private function initFromTitles( $titles ) {
814 // Get validated and normalized title objects
815 $linkBatch = $this->processTitlesArray( $titles );
816 if ( $linkBatch->isEmpty() ) {
817 // There might be special-page redirects
819 return;
820 }
821
822 $db = $this->getDB();
823 $set = $linkBatch->constructSet( 'page', $db );
824
825 // Get pageIDs data from the `page` table
826 $res = $db->select( 'page', $this->getPageTableFields(), $set,
827 __METHOD__ );
828
829 // Hack: get the ns:titles stored in [ ns => [ titles ] ] format
830 $this->initFromQueryResult( $res, $linkBatch->data, true ); // process Titles
831
832 // Resolve any found redirects
834 }
835
840 private function initFromPageIds( $pageids ) {
841 if ( !$pageids ) {
842 return;
843 }
844
845 $pageids = array_map( 'intval', $pageids ); // paranoia
846 $remaining = array_flip( $pageids );
847
848 $pageids = self::getPositiveIntegers( $pageids );
849
850 $res = null;
851 if ( !empty( $pageids ) ) {
852 $set = [
853 'page_id' => $pageids
854 ];
855 $db = $this->getDB();
856
857 // Get pageIDs data from the `page` table
858 $res = $db->select( 'page', $this->getPageTableFields(), $set,
859 __METHOD__ );
860 }
861
862 $this->initFromQueryResult( $res, $remaining, false ); // process PageIDs
863
864 // Resolve any found redirects
866 }
867
878 private function initFromQueryResult( $res, &$remaining = null, $processTitles = null ) {
879 if ( !is_null( $remaining ) && is_null( $processTitles ) ) {
880 ApiBase::dieDebug( __METHOD__, 'Missing $processTitles parameter when $remaining is provided' );
881 }
882
883 $usernames = [];
884 if ( $res ) {
885 foreach ( $res as $row ) {
886 $pageId = intval( $row->page_id );
887
888 // Remove found page from the list of remaining items
889 if ( isset( $remaining ) ) {
890 if ( $processTitles ) {
891 unset( $remaining[$row->page_namespace][$row->page_title] );
892 } else {
893 unset( $remaining[$pageId] );
894 }
895 }
896
897 // Store any extra fields requested by modules
898 $this->processDbRow( $row );
899
900 // Need gender information
901 if ( MWNamespace::hasGenderDistinction( $row->page_namespace ) ) {
902 $usernames[] = $row->page_title;
903 }
904 }
905 }
906
907 if ( isset( $remaining ) ) {
908 // Any items left in the $remaining list are added as missing
909 if ( $processTitles ) {
910 // The remaining titles in $remaining are non-existent pages
911 $linkCache = LinkCache::singleton();
912 foreach ( $remaining as $ns => $dbkeys ) {
913 foreach ( array_keys( $dbkeys ) as $dbkey ) {
914 $title = Title::makeTitle( $ns, $dbkey );
915 $linkCache->addBadLinkObj( $title );
916 $this->mAllPages[$ns][$dbkey] = $this->mFakePageId;
917 $this->mMissingPages[$ns][$dbkey] = $this->mFakePageId;
918 $this->mGoodAndMissingPages[$ns][$dbkey] = $this->mFakePageId;
919 $this->mMissingTitles[$this->mFakePageId] = $title;
920 $this->mFakePageId--;
921 $this->mTitles[] = $title;
922
923 // need gender information
924 if ( MWNamespace::hasGenderDistinction( $ns ) ) {
925 $usernames[] = $dbkey;
926 }
927 }
928 }
929 } else {
930 // The remaining pageids do not exist
931 if ( !$this->mMissingPageIDs ) {
932 $this->mMissingPageIDs = array_keys( $remaining );
933 } else {
934 $this->mMissingPageIDs = array_merge( $this->mMissingPageIDs, array_keys( $remaining ) );
935 }
936 }
937 }
938
939 // Get gender information
940 $genderCache = MediaWikiServices::getInstance()->getGenderCache();
941 $genderCache->doQuery( $usernames, __METHOD__ );
942 }
943
949 private function initFromRevIDs( $revids ) {
950 if ( !$revids ) {
951 return;
952 }
953
954 $revids = array_map( 'intval', $revids ); // paranoia
955 $db = $this->getDB();
956 $pageids = [];
957 $remaining = array_flip( $revids );
958
959 $revids = self::getPositiveIntegers( $revids );
960
961 if ( !empty( $revids ) ) {
962 $tables = [ 'revision', 'page' ];
963 $fields = [ 'rev_id', 'rev_page' ];
964 $where = [ 'rev_id' => $revids, 'rev_page = page_id' ];
965
966 // Get pageIDs data from the `page` table
967 $res = $db->select( $tables, $fields, $where, __METHOD__ );
968 foreach ( $res as $row ) {
969 $revid = intval( $row->rev_id );
970 $pageid = intval( $row->rev_page );
971 $this->mGoodRevIDs[$revid] = $pageid;
972 $this->mLiveRevIDs[$revid] = $pageid;
973 $pageids[$pageid] = '';
974 unset( $remaining[$revid] );
975 }
976 }
977
978 $this->mMissingRevIDs = array_keys( $remaining );
979
980 // Populate all the page information
981 $this->initFromPageIds( array_keys( $pageids ) );
982
983 // If the user can see deleted revisions, pull out the corresponding
984 // titles from the archive table and include them too. We ignore
985 // ar_page_id because deleted revisions are tied by title, not page_id.
986 if ( !empty( $this->mMissingRevIDs ) && $this->getUser()->isAllowed( 'deletedhistory' ) ) {
987 $remaining = array_flip( $this->mMissingRevIDs );
988 $tables = [ 'archive' ];
989 $fields = [ 'ar_rev_id', 'ar_namespace', 'ar_title' ];
990 $where = [ 'ar_rev_id' => $this->mMissingRevIDs ];
991
992 $res = $db->select( $tables, $fields, $where, __METHOD__ );
993 $titles = [];
994 foreach ( $res as $row ) {
995 $revid = intval( $row->ar_rev_id );
996 $titles[$revid] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
997 unset( $remaining[$revid] );
998 }
999
1000 $this->initFromTitles( $titles );
1001
1002 foreach ( $titles as $revid => $title ) {
1003 $ns = $title->getNamespace();
1004 $dbkey = $title->getDBkey();
1005
1006 // Handle converted titles
1007 if ( !isset( $this->mAllPages[$ns][$dbkey] ) &&
1008 isset( $this->mConvertedTitles[$title->getPrefixedText()] )
1009 ) {
1010 $title = Title::newFromText( $this->mConvertedTitles[$title->getPrefixedText()] );
1011 $ns = $title->getNamespace();
1012 $dbkey = $title->getDBkey();
1013 }
1014
1015 if ( isset( $this->mAllPages[$ns][$dbkey] ) ) {
1016 $this->mGoodRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1017 $this->mDeletedRevIDs[$revid] = $this->mAllPages[$ns][$dbkey];
1018 } else {
1019 $remaining[$revid] = true;
1020 }
1021 }
1022
1023 $this->mMissingRevIDs = array_keys( $remaining );
1024 }
1025 }
1026
1032 private function resolvePendingRedirects() {
1033 if ( $this->mResolveRedirects ) {
1034 $db = $this->getDB();
1035 $pageFlds = $this->getPageTableFields();
1036
1037 // Repeat until all redirects have been resolved
1038 // The infinite loop is prevented by keeping all known pages in $this->mAllPages
1039 while ( $this->mPendingRedirectIDs || $this->mPendingRedirectSpecialPages ) {
1040 // Resolve redirects by querying the pagelinks table, and repeat the process
1041 // Create a new linkBatch object for the next pass
1042 $linkBatch = $this->getRedirectTargets();
1043
1044 if ( $linkBatch->isEmpty() ) {
1045 break;
1046 }
1047
1048 $set = $linkBatch->constructSet( 'page', $db );
1049 if ( $set === false ) {
1050 break;
1051 }
1052
1053 // Get pageIDs data from the `page` table
1054 $res = $db->select( 'page', $pageFlds, $set, __METHOD__ );
1055
1056 // Hack: get the ns:titles stored in [ns => array(titles)] format
1057 $this->initFromQueryResult( $res, $linkBatch->data, true );
1058 }
1059 }
1060 }
1061
1069 private function getRedirectTargets() {
1070 $titlesToResolve = [];
1071 $db = $this->getDB();
1072
1073 if ( $this->mPendingRedirectIDs ) {
1074 $res = $db->select(
1075 'redirect',
1076 [
1077 'rd_from',
1078 'rd_namespace',
1079 'rd_fragment',
1080 'rd_interwiki',
1081 'rd_title'
1082 ], [ 'rd_from' => array_keys( $this->mPendingRedirectIDs ) ],
1083 __METHOD__
1084 );
1085 foreach ( $res as $row ) {
1086 $rdfrom = intval( $row->rd_from );
1087 $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
1088 $to = Title::makeTitle(
1089 $row->rd_namespace,
1090 $row->rd_title,
1091 $row->rd_fragment,
1092 $row->rd_interwiki
1093 );
1094 $this->mResolvedRedirectTitles[$from] = $this->mPendingRedirectIDs[$rdfrom];
1095 unset( $this->mPendingRedirectIDs[$rdfrom] );
1096 if ( $to->isExternal() ) {
1097 $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1098 } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1099 $titlesToResolve[] = $to;
1100 }
1101 $this->mRedirectTitles[$from] = $to;
1102 }
1103
1104 if ( $this->mPendingRedirectIDs ) {
1105 // We found pages that aren't in the redirect table
1106 // Add them
1107 foreach ( $this->mPendingRedirectIDs as $id => $title ) {
1108 $page = WikiPage::factory( $title );
1109 $rt = $page->insertRedirect();
1110 if ( !$rt ) {
1111 // What the hell. Let's just ignore this
1112 continue;
1113 }
1114 if ( $rt->isExternal() ) {
1115 $this->mInterwikiTitles[$rt->getPrefixedText()] = $rt->getInterwiki();
1116 } elseif ( !isset( $this->mAllPages[$rt->getNamespace()][$rt->getDBkey()] ) ) {
1117 $titlesToResolve[] = $rt;
1118 }
1119 $from = $title->getPrefixedText();
1120 $this->mResolvedRedirectTitles[$from] = $title;
1121 $this->mRedirectTitles[$from] = $rt;
1122 unset( $this->mPendingRedirectIDs[$id] );
1123 }
1124 }
1125 }
1126
1127 if ( $this->mPendingRedirectSpecialPages ) {
1128 foreach ( $this->mPendingRedirectSpecialPages as $key => list( $from, $to ) ) {
1129 $fromKey = $from->getPrefixedText();
1130 $this->mResolvedRedirectTitles[$fromKey] = $from;
1131 $this->mRedirectTitles[$fromKey] = $to;
1132 if ( $to->isExternal() ) {
1133 $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
1134 } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) {
1135 $titlesToResolve[] = $to;
1136 }
1137 }
1138 $this->mPendingRedirectSpecialPages = [];
1139
1140 // Set private caching since we don't know what criteria the
1141 // special pages used to decide on these redirects.
1142 $this->mCacheMode = 'private';
1143 }
1144
1145 return $this->processTitlesArray( $titlesToResolve );
1146 }
1147
1161 public function getCacheMode( $params = null ) {
1162 return $this->mCacheMode;
1163 }
1164
1174 private function processTitlesArray( $titles ) {
1175 $usernames = [];
1176 $linkBatch = new LinkBatch();
1177
1178 foreach ( $titles as $title ) {
1179 if ( is_string( $title ) ) {
1180 try {
1181 $titleObj = Title::newFromTextThrow( $title, $this->mDefaultNamespace );
1182 } catch ( MalformedTitleException $ex ) {
1183 // Handle invalid titles gracefully
1184 if ( !isset( $this->mAllPages[0][$title] ) ) {
1185 $this->mAllPages[0][$title] = $this->mFakePageId;
1186 $this->mInvalidTitles[$this->mFakePageId] = [
1187 'title' => $title,
1188 'invalidreason' => $this->getErrorFormatter()->formatException( $ex, [ 'bc' => true ] ),
1189 ];
1190 $this->mFakePageId--;
1191 }
1192 continue; // There's nothing else we can do
1193 }
1194 } else {
1195 $titleObj = $title;
1196 }
1197 $unconvertedTitle = $titleObj->getPrefixedText();
1198 $titleWasConverted = false;
1199 if ( $titleObj->isExternal() ) {
1200 // This title is an interwiki link.
1201 $this->mInterwikiTitles[$unconvertedTitle] = $titleObj->getInterwiki();
1202 } else {
1203 // Variants checking
1204 global $wgContLang;
1205 if ( $this->mConvertTitles &&
1206 count( $wgContLang->getVariants() ) > 1 &&
1207 !$titleObj->exists()
1208 ) {
1209 // Language::findVariantLink will modify titleText and titleObj into
1210 // the canonical variant if possible
1211 $titleText = is_string( $title ) ? $title : $titleObj->getPrefixedText();
1212 $wgContLang->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 $special = SpecialPageFactory::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 handle.
1229 $context = new DerivativeContext( $this );
1230 $context->setTitle( $titleObj );
1231 $context->setRequest( new FauxRequest );
1232 $special->setContext( $context );
1233 list( /* $alias */, $subpage ) = SpecialPageFactory::resolveAlias( $dbkey );
1234 $target = $special->getRedirect( $subpage );
1235 }
1236 }
1237 if ( $target ) {
1238 $this->mPendingRedirectSpecialPages[$dbkey] = [ $titleObj, $target ];
1239 } else {
1240 $this->mSpecialTitles[$this->mFakePageId] = $titleObj;
1241 $this->mFakePageId--;
1242 }
1243 }
1244 } else {
1245 // Regular page
1246 $linkBatch->addObj( $titleObj );
1247 }
1248 }
1249
1250 // Make sure we remember the original title that was
1251 // given to us. This way the caller can correlate new
1252 // titles with the originally requested when e.g. the
1253 // namespace is localized or the capitalization is
1254 // different
1255 if ( $titleWasConverted ) {
1256 $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText();
1257 // In this case the page can't be Special.
1258 if ( is_string( $title ) && $title !== $unconvertedTitle ) {
1259 $this->mNormalizedTitles[$title] = $unconvertedTitle;
1260 }
1261 } elseif ( is_string( $title ) && $title !== $titleObj->getPrefixedText() ) {
1262 $this->mNormalizedTitles[$title] = $titleObj->getPrefixedText();
1263 }
1264
1265 // Need gender information
1266 if ( MWNamespace::hasGenderDistinction( $titleObj->getNamespace() ) ) {
1267 $usernames[] = $titleObj->getText();
1268 }
1269 }
1270 // Get gender information
1271 $genderCache = MediaWikiServices::getInstance()->getGenderCache();
1272 $genderCache->doQuery( $usernames, __METHOD__ );
1273
1274 return $linkBatch;
1275 }
1276
1292 public function setGeneratorData( Title $title, array $data ) {
1293 $ns = $title->getNamespace();
1294 $dbkey = $title->getDBkey();
1295 $this->mGeneratorData[$ns][$dbkey] = $data;
1296 }
1297
1317 public function setRedirectMergePolicy( $callable ) {
1318 $this->mRedirectMergePolicy = $callable;
1319 }
1320
1341 public function populateGeneratorData( &$result, array $path = [] ) {
1342 if ( $result instanceof ApiResult ) {
1343 $data = $result->getResultData( $path );
1344 if ( $data === null ) {
1345 return true;
1346 }
1347 } else {
1348 $data = &$result;
1349 foreach ( $path as $key ) {
1350 if ( !isset( $data[$key] ) ) {
1351 // Path isn't in $result, so nothing to add, so everything
1352 // "fits"
1353 return true;
1354 }
1355 $data = &$data[$key];
1356 }
1357 }
1358 foreach ( $this->mGeneratorData as $ns => $dbkeys ) {
1359 if ( $ns === NS_SPECIAL ) {
1360 $pages = [];
1361 foreach ( $this->mSpecialTitles as $id => $title ) {
1362 $pages[$title->getDBkey()] = $id;
1363 }
1364 } else {
1365 if ( !isset( $this->mAllPages[$ns] ) ) {
1366 // No known titles in the whole namespace. Skip it.
1367 continue;
1368 }
1369 $pages = $this->mAllPages[$ns];
1370 }
1371 foreach ( $dbkeys as $dbkey => $genData ) {
1372 if ( !isset( $pages[$dbkey] ) ) {
1373 // Unknown title. Forget it.
1374 continue;
1375 }
1376 $pageId = $pages[$dbkey];
1377 if ( !isset( $data[$pageId] ) ) {
1378 // $pageId didn't make it into the result. Ignore it.
1379 continue;
1380 }
1381
1382 if ( $result instanceof ApiResult ) {
1383 $path2 = array_merge( $path, [ $pageId ] );
1384 foreach ( $genData as $key => $value ) {
1385 if ( !$result->addValue( $path2, $key, $value ) ) {
1386 return false;
1387 }
1388 }
1389 } else {
1390 $data[$pageId] = array_merge( $data[$pageId], $genData );
1391 }
1392 }
1393 }
1394
1395 // Merge data generated about redirect titles into the redirect destination
1396 if ( $this->mRedirectMergePolicy ) {
1397 foreach ( $this->mResolvedRedirectTitles as $titleFrom ) {
1398 $dest = $titleFrom;
1399 while ( isset( $this->mRedirectTitles[$dest->getPrefixedText()] ) ) {
1400 $dest = $this->mRedirectTitles[$dest->getPrefixedText()];
1401 }
1402 $fromNs = $titleFrom->getNamespace();
1403 $fromDBkey = $titleFrom->getDBkey();
1404 $toPageId = $dest->getArticleID();
1405 if ( isset( $data[$toPageId] ) &&
1406 isset( $this->mGeneratorData[$fromNs][$fromDBkey] )
1407 ) {
1408 // It is necesary to set both $data and add to $result, if an ApiResult,
1409 // to ensure multiple redirects to the same destination are all merged.
1410 $data[$toPageId] = call_user_func(
1411 $this->mRedirectMergePolicy,
1412 $data[$toPageId],
1413 $this->mGeneratorData[$fromNs][$fromDBkey]
1414 );
1415 if ( $result instanceof ApiResult ) {
1416 if ( !$result->addValue( $path, $toPageId, $data[$toPageId], ApiResult::OVERRIDE ) ) {
1417 return false;
1418 }
1419 }
1420 }
1421 }
1422 }
1423
1424 return true;
1425 }
1426
1431 protected function getDB() {
1432 return $this->mDbSource->getDB();
1433 }
1434
1441 private static function getPositiveIntegers( $array ) {
1442 // T27734 API: possible issue with revids validation
1443 // It seems with a load of revision rows, MySQL gets upset
1444 // Remove any < 0 integers, as they can't be valid
1445 foreach ( $array as $i => $int ) {
1446 if ( $int < 0 ) {
1447 unset( $array[$i] );
1448 }
1449 }
1450
1451 return $array;
1452 }
1453
1454 public function getAllowedParams( $flags = 0 ) {
1455 $result = [
1456 'titles' => [
1457 ApiBase::PARAM_ISMULTI => true,
1458 ApiBase::PARAM_HELP_MSG => 'api-pageset-param-titles',
1459 ],
1460 'pageids' => [
1461 ApiBase::PARAM_TYPE => 'integer',
1462 ApiBase::PARAM_ISMULTI => true,
1463 ApiBase::PARAM_HELP_MSG => 'api-pageset-param-pageids',
1464 ],
1465 'revids' => [
1466 ApiBase::PARAM_TYPE => 'integer',
1467 ApiBase::PARAM_ISMULTI => true,
1468 ApiBase::PARAM_HELP_MSG => 'api-pageset-param-revids',
1469 ],
1470 'generator' => [
1471 ApiBase::PARAM_TYPE => null,
1472 ApiBase::PARAM_HELP_MSG => 'api-pageset-param-generator',
1474 ],
1475 'redirects' => [
1476 ApiBase::PARAM_DFLT => false,
1477 ApiBase::PARAM_HELP_MSG => $this->mAllowGenerator
1478 ? 'api-pageset-param-redirects-generator'
1479 : 'api-pageset-param-redirects-nogenerator',
1480 ],
1481 'converttitles' => [
1482 ApiBase::PARAM_DFLT => false,
1484 'api-pageset-param-converttitles',
1485 [ Message::listParam( LanguageConverter::$languagesWithVariants, 'text' ) ],
1486 ],
1487 ],
1488 ];
1489
1490 if ( !$this->mAllowGenerator ) {
1491 unset( $result['generator'] );
1492 } elseif ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
1493 $result['generator'][ApiBase::PARAM_TYPE] = 'submodule';
1494 $result['generator'][ApiBase::PARAM_SUBMODULE_MAP] = $this->getGenerators();
1495 }
1496
1497 return $result;
1498 }
1499
1500 protected function handleParamNormalization( $paramName, $value, $rawValue ) {
1501 parent::handleParamNormalization( $paramName, $value, $rawValue );
1502
1503 if ( $paramName === 'titles' ) {
1504 // For the 'titles' parameter, we want to split it like ApiBase would
1505 // and add any changed titles to $this->mNormalizedTitles
1506 $value = $this->explodeMultiValue( $value, self::LIMIT_SML2 + 1 );
1507 $l = count( $value );
1508 $rawValue = $this->explodeMultiValue( $rawValue, $l );
1509 for ( $i = 0; $i < $l; $i++ ) {
1510 if ( $value[$i] !== $rawValue[$i] ) {
1511 $this->mNormalizedTitles[$rawValue[$i]] = $value[$i];
1512 }
1513 }
1514 }
1515 }
1516
1517 private static $generators = null;
1518
1523 private function getGenerators() {
1524 if ( self::$generators === null ) {
1526 if ( !( $query instanceof ApiQuery ) ) {
1527 // If the parent container of this pageset is not ApiQuery,
1528 // we must create it to get module manager
1529 $query = $this->getMain()->getModuleManager()->getModule( 'query' );
1530 }
1531 $gens = [];
1532 $prefix = $query->getModulePath() . '+';
1533 $mgr = $query->getModuleManager();
1534 foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
1535 if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) {
1536 $gens[$name] = $prefix . $name;
1537 }
1538 }
1539 ksort( $gens );
1540 self::$generators = $gens;
1541 }
1542
1543 return self::$generators;
1544 }
1545}
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:41
const PARAM_SUBMODULE_MAP
(string[]) When PARAM_TYPE is 'submodule', map parameter values to submodule paths.
Definition ApiBase.php:168
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition ApiBase.php:721
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition ApiBase.php:1855
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition ApiBase.php:2038
getMain()
Get the main module.
Definition ApiBase.php:528
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
Definition ApiBase.php:91
getErrorFormatter()
Get the error formatter.
Definition ApiBase.php:646
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition ApiBase.php:52
extractRequestParams( $parseLimit=true)
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:740
const PARAM_SUBMODULE_PARAM_PREFIX
(string) When PARAM_TYPE is 'submodule', used to indicate the 'g' prefix added by ApiQueryGeneratorBa...
Definition ApiBase.php:175
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:128
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition ApiBase.php:1779
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition ApiBase.php:238
explodeMultiValue( $value, $limit)
Split a multi-valued parameter string, like explode()
Definition ApiBase.php:1350
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition ApiBase.php:55
This class contains a list of pages that the client has requested.
getGoodAndMissingTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good and missing titles.
initFromPageIds( $pageids)
Does the same as initFromTitles(), but is based on page IDs instead.
populateFromRevisionIDs( $revIDs)
Populate this PageSet from a list of revision IDs.
getInterwikiTitlesAsResult( $result=null, $iwUrl=false)
Get a list of interwiki titles - maps a title to its interwiki prefix as result.
getCustomField( $fieldName)
Get the value of a custom field previously requested through requestField()
getNormalizedTitles()
Get a list of title normalizations - maps a title to its normalized version.
getGenerators()
Get an array of all available generators.
__construct(ApiBase $dbSource, $flags=0, $defaultNamespace=NS_MAIN)
getGoodTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all good titles.
getAllowedParams( $flags=0)
getRevisionIDs()
Get the list of valid revision IDs (requested with the revids= parameter)
getGoodAndMissingTitles()
Title objects for good and missing titles.
populateFromPageIDs( $pageIDs)
Populate this PageSet from a list of page IDs.
getRedirectTargets()
Get the targets of the pending redirects from the database.
getMissingTitlesByNamespace()
Returns an array [ns][dbkey] => fake_page_id for all missing titles.
static getPositiveIntegers( $array)
Returns the input array of integers with all values < 0 removed.
getMissingTitles()
Title objects that were NOT found in the database.
getDB()
Get the database connection (read-only)
static $generators
initFromRevIDs( $revids)
Does the same as initFromTitles(), but is based on revision IDs instead.
executeDryRun()
In case execute() is not called, call this method to mark all relevant parameters as used This preven...
getRedirectTitlesAsResult( $result=null)
Get a list of redirect resolutions - maps a title to its redirect target.
getPageTableFields()
Get the fields that have to be queried from the page table: the ones requested through requestField()...
getGoodTitleCount()
Returns the number of found unique pages (not revisions) in the set.
getRevisionCount()
Returns the number of revisions (requested with revids= parameter).
getAllTitlesByNamespace()
Returns an array [ns][dbkey] => page_id for all requested titles.
processDbRow( $row)
Extract all requested fields from the row received from the database.
processTitlesArray( $titles)
Given an array of title strings, convert them into Title objects.
static addValues(array &$result, $values, $flags=[], $name=null)
Add all items from $values into the result.
setRedirectMergePolicy( $callable)
Controls how generator data about a redirect source is merged into the generator data for the redirec...
handleParamNormalization( $paramName, $value, $rawValue)
Handle when a parameter was Unicode-normalized.
getNormalizedTitlesAsResult( $result=null)
Get a list of title normalizations - maps a title to its normalized version in the form of result arr...
getTitleCount()
Returns the number of unique pages (not revisions) in the set.
initFromTitles( $titles)
This method populates internal variables with page information based on the given array of title stri...
getInvalidTitlesAndReasons()
Titles that were deemed invalid by Title::newFromText() The array's index will be unique and negative...
array $mInvalidTitles
[fake_page_id] => [ 'title' => $title, 'invalidreason' => $reason ]
getSpecialTitles()
Get the list of titles with negative namespace.
Title[] $mPendingRedirectIDs
getTitles()
All Title objects provided.
int $mDefaultNamespace
executeInternal( $isDryRun)
Populate the PageSet from the request parameters.
resolvePendingRedirects()
Resolve any redirects in the result if redirect resolution was requested.
populateFromQueryResult( $db, $queryResult)
Populate this PageSet from a rowset returned from the database.
getMissingPageIDs()
Page IDs that were not found in the database.
requestField( $fieldName)
Request an additional field from the page table.
getInterwikiTitles()
Get a list of interwiki titles - maps a title to its interwiki prefix.
populateFromTitles( $titles)
Populate this PageSet from a list of Titles.
getMissingRevisionIDs()
Revision IDs that were not found in the database.
execute()
Populate the PageSet from the request parameters.
populateGeneratorData(&$result, array $path=[])
Populate the generator data for all titles in the result.
$mPendingRedirectSpecialPages
getConvertedTitlesAsResult( $result=null)
Get a list of title conversions - maps a title to its converted version as a result array.
getConvertedTitles()
Get a list of title conversions - maps a title to its converted version.
getInvalidTitles()
Titles that were deemed invalid by Title::newFromText() The array's index will be unique and negative...
getDataSource()
Return the parameter name that is the source of data for this PageSet.
getInvalidTitlesAndRevisions( $invalidChecks=[ 'invalidTitles', 'special', 'missingIds', 'missingRevIds', 'missingTitles', 'interwikiTitles'])
Get an array of invalid/special/missing titles.
getLiveRevisionIDs()
Get the list of non-deleted revision IDs (requested with the revids= parameter)
getCacheMode( $params=null)
Get the cache mode for the data generated by this module.
getGoodTitles()
Title objects that were found in the database.
$mResolvedRedirectTitles
callable null $mRedirectMergePolicy
isResolvingRedirects()
Check whether this PageSet is resolving redirects.
getRedirectTitles()
Get a list of redirect resolutions - maps a title to its redirect target, as an array of output-ready...
setGeneratorData(Title $title, array $data)
Set data for a title.
const DISABLE_GENERATORS
Constructor flag: The new instance of ApiPageSet will ignore the 'generator=' parameter.
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...
getMissingRevisionIDsAsResult( $result=null)
Revision IDs that were not found in the database as result array.
getDeletedRevisionIDs()
Get the list of revision IDs that were associated with deleted titles.
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
This is the main query class.
Definition ApiQuery.php:40
This class represents the result of the API operations.
Definition ApiResult.php:33
const OVERRIDE
Override existing value in addValue(), setValue(), and similar functions.
Definition ApiResult.php:39
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
getUser()
Get the User object.
getConfig()
Get the Config object.
IContextSource $context
An IContextSource implementation which will inherit context from another source but allow individual ...
WebRequest clone which takes values from a provided array.
static array $languagesWithVariants
languages supporting variants
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:34
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Superclass for any RedirectSpecialPage which redirects the user to a particular article (as opposed t...
static getPage( $name)
Find the object with a given name and return it (or NULL)
static resolveAlias( $alias)
Given a special page name with a possible subpage, return an array where the first element is the spe...
Represents a title within MediaWiki.
Definition Title.php:39
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition WikiPage.php:121
Result wrapper for grabbing data queried from an IDatabase object.
$res
Definition database.txt:21
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition deferred.txt:11
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
namespace being checked & $result
Definition hooks.txt:2293
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
Definition hooks.txt:1013
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:962
it s the revision text itself In either if gzip is the revision text is gzipped $flags
Definition hooks.txt:2805
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
null for the local wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition hooks.txt:1610
const PROTO_CURRENT
Definition Defines.php:223
const NS_MAIN
Definition Defines.php:65
const NS_SPECIAL
Definition Defines.php:54
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:40
linkcache txt The LinkCache class maintains a list of article titles and the information about whether or not the article exists in the database This is used to mark up links when displaying a page If the same link appears more than once on any page then it only has to be looked up once In most cases link lookups are done in batches with the LinkBatch class or the equivalent in so the link cache is mostly useful for short snippets of parsed and for links in the navigation areas of the skin The link cache was formerly used to track links used in a document for the purposes of updating the link tables This application is now deprecated To create a you can use the following $titles
Definition linkcache.txt:17
$params