MediaWiki master
Title.php
Go to the documentation of this file.
1<?php
11namespace MediaWiki\Title;
12
13use InvalidArgumentException;
15use MediaWiki\DAO\WikiAwareEntityTrait;
47use RuntimeException;
48use stdClass;
49use Stringable;
50use Wikimedia\Assert\Assert;
51use Wikimedia\Assert\PreconditionException;
53use Wikimedia\Parsoid\Core\LinkTarget as ParsoidLinkTarget;
54use Wikimedia\Parsoid\Core\LinkTargetTrait;
59use Wikimedia\Timestamp\TimestampFormat as TS;
60
69class Title implements Stringable, LinkTarget, PageIdentity {
70 use WikiAwareEntityTrait;
71 use LinkTargetTrait;
72
74 private static $titleCache = null;
75
80 private static ?Title $cachedMainPage = null;
81
87 private const CACHE_MAX = 1000;
88
96 public const NEW_CLONE = 'clone';
97
99 private $mTextform = '';
100
102 private $mUrlform = '';
103
105 private $mDbkeyform = '';
106
108 private $mNamespace = NS_MAIN;
109
111 private $mInterwiki = '';
112
114 private $mLocalInterwiki = false;
115
117 private $mFragment = '';
118
119 /***************************************************************************/
120 // region Private member variables
128 public $mArticleID = -1;
129
131 protected $mLatestID = false;
132
137 private $mContentModel = false;
138
143 private $mForcedContentModel = false;
144
146 private $mEstimateRevisions;
147
156 public $prefixedText = null;
157
163 private const DEFAULT_NAMESPACE = NS_MAIN;
164
166 protected $mLength = -1;
167
169 public $mRedirect = null;
170
172 private $mHasSubpages;
173
175 private $mPageLanguage;
176
180 private $mDbPageLanguage = false;
181
183 private $mTitleValue = null;
184
186 private $mIsBigDeletion = null;
187
189 private $mIsValid = null;
190
192 private $mInstanceCacheKey = null;
193
194 // endregion -- end of private member variables
196 /***************************************************************************/
197
203 private function getLanguageConverter( $language ): ILanguageConverter {
204 return MediaWikiServices::getInstance()->getLanguageConverterFactory()
205 ->getLanguageConverter( $language );
206 }
207
211 private function getPageLanguageConverter(): ILanguageConverter {
212 return $this->getLanguageConverter( $this->getPageLanguage() );
213 }
214
218 private function getDbProvider(): IConnectionProvider {
219 return MediaWikiServices::getInstance()->getConnectionProvider();
220 }
221
230 private static function getTitleFormatter() {
231 return MediaWikiServices::getInstance()->getTitleFormatter();
232 }
233
242 private static function getInterwikiLookup() {
243 return MediaWikiServices::getInstance()->getInterwikiLookup();
244 }
245
246 private function __construct() {
247 }
248
257 public static function newFromDBkey( $key ) {
258 $t = new self();
259
260 try {
261 $t->secureAndSplit( $key );
262 return $t;
263 } catch ( MalformedTitleException ) {
264 return null;
265 }
266 }
267
279 public static function newFromLinkTarget( ParsoidLinkTarget $linkTarget, $forceClone = '' ) {
280 if ( $linkTarget instanceof Title ) {
281 // Special case if it's already a Title object
282 if ( $forceClone === self::NEW_CLONE ) {
283 return clone $linkTarget;
284 } else {
285 return $linkTarget;
286 }
287 }
288 return self::makeTitle(
289 $linkTarget->getNamespace(),
290 $linkTarget->getText(),
291 $linkTarget->getFragment(),
292 $linkTarget->getInterwiki()
293 );
294 }
295
303 public static function castFromLinkTarget( ?ParsoidLinkTarget $linkTarget ) {
304 if ( !$linkTarget ) {
305 return null;
306 }
307 return self::newFromLinkTarget( $linkTarget );
308 }
309
318 public static function newFromPageIdentity( PageIdentity $pageIdentity ): Title {
319 return self::newFromPageReference( $pageIdentity );
320 }
321
329 public static function castFromPageIdentity( ?PageIdentity $pageIdentity ): ?Title {
330 return self::castFromPageReference( $pageIdentity );
331 }
332
341 public static function newFromPageReference( PageReference $pageReference ): Title {
342 if ( $pageReference instanceof Title ) {
343 return $pageReference;
344 }
345
346 $pageReference->assertWiki( self::LOCAL );
347 $title = self::makeTitle( $pageReference->getNamespace(), $pageReference->getDBkey() );
348
349 if ( $pageReference instanceof PageIdentity ) {
350 $title->mArticleID = $pageReference->getId();
351 }
352 return $title;
353 }
354
362 public static function castFromPageReference( ?PageReference $pageReference ): ?Title {
363 if ( !$pageReference ) {
364 return null;
365 }
366 return self::newFromPageReference( $pageReference );
367 }
368
388 public static function newFromText( $text, $defaultNamespace = NS_MAIN ) {
389 // DWIM: Integers can be passed in here when page titles are used as array keys.
390 if ( $text !== null && !is_string( $text ) && !is_int( $text ) ) {
391 throw new InvalidArgumentException( '$text must be a string.' );
392 }
393 if ( $text === null || $text === '' ) {
394 return null;
395 }
396
397 try {
398 return self::newFromTextThrow( (string)$text, (int)$defaultNamespace );
399 } catch ( MalformedTitleException ) {
400 return null;
401 }
402 }
403
423 public static function newFromTextThrow( $text, $defaultNamespace = NS_MAIN ) {
424 if ( is_object( $text ) ) {
425 throw new InvalidArgumentException( '$text must be a string, given an object' );
426 } elseif ( $text === null ) {
427 // Legacy code relies on MalformedTitleException being thrown in this case
428 // TODO: fix(happens when URL with no title in it is parsed).
429 throw new MalformedTitleException( 'title-invalid-empty' );
430 }
431
432 $titleCache = self::getTitleCache();
433
434 // Wiki pages often contain multiple links to the same page.
435 // Title normalization and parsing can become expensive on pages with many
436 // links, so we can save a little time by caching them.
437 if ( $defaultNamespace === NS_MAIN ) {
438 $t = $titleCache->get( $text );
439 if ( $t ) {
440 return $t;
441 }
442 }
443
444 // Convert things like &eacute; &#257; or &#x3017; into normalized (T16952) text
445 $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
446
447 $t = new Title();
448 $dbKeyForm = strtr( $filteredText, ' ', '_' );
449
450 $t->secureAndSplit( $dbKeyForm, (int)$defaultNamespace );
451 if ( $defaultNamespace === NS_MAIN ) {
452 $t->mInstanceCacheKey = $text;
453 $titleCache->set( $text, $t );
454 }
455 return $t;
456 }
457
462 private function uncache() {
463 if ( $this->mInstanceCacheKey !== null ) {
464 $titleCache = self::getTitleCache();
465 $titleCache->clear( $this->mInstanceCacheKey );
466 $this->mInstanceCacheKey = null;
467 }
468 }
469
485 public static function newFromURL( $url ) {
486 $t = new Title();
487
488 # For compatibility with old buggy URLs. "+" is usually not valid in titles,
489 # but some URLs used it as a space replacement and they still come
490 # from some external search tools.
491 if ( !str_contains( self::legalChars(), '+' ) ) {
492 $url = strtr( $url, '+', ' ' );
493 }
494
495 $dbKeyForm = strtr( $url, ' ', '_' );
496
497 try {
498 $t->secureAndSplit( $dbKeyForm );
499 return $t;
500 } catch ( MalformedTitleException ) {
501 return null;
502 }
503 }
504
508 private static function getTitleCache() {
509 if ( self::$titleCache === null ) {
510 self::$titleCache = new MapCacheLRU( self::CACHE_MAX );
511 }
512 return self::$titleCache;
513 }
514
522 public static function newFromID( $id, $flags = 0 ) {
523 $pageStore = MediaWikiServices::getInstance()->getPageStore();
524 $dbr = DBAccessObjectUtils::getDBFromRecency(
525 MediaWikiServices::getInstance()->getConnectionProvider(),
526 $flags
527 );
528 $row = $dbr->newSelectQueryBuilder()
529 ->select( $pageStore->getSelectFields() )
530 ->from( 'page' )
531 ->where( [ 'page_id' => $id ] )
532 ->recency( $flags )
533 ->caller( __METHOD__ )->fetchRow();
534 if ( $row !== false ) {
535 $title = self::newFromRow( $row );
536 } else {
537 $title = null;
538 }
539
540 return $title;
541 }
542
549 public static function newFromRow( $row ) {
550 $t = self::makeTitle( $row->page_namespace, $row->page_title );
551 $t->loadFromRow( $row );
552 return $t;
553 }
554
561 public function loadFromRow( $row ) {
562 if ( $row ) { // page found
563 if ( isset( $row->page_id ) ) {
564 $this->mArticleID = (int)$row->page_id;
565 }
566 if ( isset( $row->page_len ) ) {
567 $this->mLength = (int)$row->page_len;
568 }
569 if ( isset( $row->page_is_redirect ) ) {
570 $this->mRedirect = (bool)$row->page_is_redirect;
571 }
572 if ( isset( $row->page_latest ) ) {
573 $this->mLatestID = (int)$row->page_latest;
574 }
575 if ( isset( $row->page_content_model ) ) {
576 $this->lazyFillContentModel( $row->page_content_model );
577 } else {
578 $this->lazyFillContentModel( false ); // lazily-load getContentModel()
579 }
580 if ( isset( $row->page_lang ) ) {
581 $this->mDbPageLanguage = (string)$row->page_lang;
582 }
583 } else { // page not found
584 $this->mArticleID = 0;
585 $this->mLength = 0;
586 $this->mRedirect = false;
587 $this->mLatestID = 0;
588 $this->lazyFillContentModel( false ); // lazily-load getContentModel()
589 }
590 }
591
614 public static function makeTitle( $ns, $title, $fragment = '', $interwiki = '' ) {
615 $t = new Title();
616 $t->mInterwiki = $interwiki;
617 $t->mFragment = self::normalizeFragment( $fragment );
618 $t->mNamespace = $ns = (int)$ns;
619 $t->mDbkeyform = strtr( $title, ' ', '_' );
620 $t->mArticleID = ( $ns >= 0 ) ? -1 : 0;
621 $t->mUrlform = wfUrlencode( $t->mDbkeyform );
622 $t->mTextform = strtr( $title, '_', ' ' );
623 return $t;
624 }
625
640 public static function makeTitleSafe( $ns, $title, $fragment = '', $interwiki = '' ) {
641 // NOTE: ideally, this would just call makeTitle() and then isValid(),
642 // but presently, that means more overhead on a potential performance hotspot.
643
644 if ( !MediaWikiServices::getInstance()->getNamespaceInfo()->exists( $ns ) ) {
645 return null;
646 }
647
648 $t = new Title();
649 $dbKeyForm = self::makeName( $ns, $title, $fragment, $interwiki, true );
650
651 try {
652 $t->secureAndSplit( $dbKeyForm );
653 return $t;
654 } catch ( MalformedTitleException ) {
655 return null;
656 }
657 }
658
676 public static function newMainPage( ?MessageLocalizer $localizer = null ) {
677 static $recursionGuard = false;
678
679 if ( $recursionGuard ) {
680 // Every page renders at least one link to the Main Page (e.g. sidebar).
681 // Don't produce fatal errors that would make the wiki inaccessible, and hard to fix the
682 // invalid message.
683 //
684 // Fallback scenarios:
685 // * Recursion guard
686 // If the message contains a bare local interwiki (T297571), then
687 // Title::newFromText via TitleParser::splitTitleString can get back here.
688 // * Invalid title
689 // If the 'mainpage' message contains something that is invalid, Title::newFromText
690 // will return null.
691 return self::makeTitle( NS_MAIN, 'Main Page' );
692 }
693
694 $msg = $localizer ? $localizer->msg( 'mainpage' ) : wfMessage( 'mainpage' );
695 $recursionGuard = true;
696 $title = self::newFromText( $msg->inContentLanguage()->text() );
697 $recursionGuard = false;
698 return $title ?? self::makeTitle( NS_MAIN, 'Main Page' );
699 }
700
706 public static function legalChars() {
707 global $wgLegalTitleChars;
708 return $wgLegalTitleChars;
709 }
710
720 public static function convertByteClassToUnicodeClass( $byteClass ) {
721 $length = strlen( $byteClass );
722 // Input token queue
723 $x0 = $x1 = $x2 = '';
724 // Decoded queue
725 $d0 = $d1 = '';
726 // Decoded integer codepoints
727 $ord0 = $ord1 = $ord2 = 0;
728 // Re-encoded queue
729 $r0 = $r1 = $r2 = '';
730 // Output
731 $out = '';
732 // Flags
733 $allowUnicode = false;
734 for ( $pos = 0; $pos < $length; $pos++ ) {
735 // Shift the queues down
736 $x2 = $x1;
737 $x1 = $x0;
738 $d1 = $d0;
739 $ord2 = $ord1;
740 $ord1 = $ord0;
741 $r2 = $r1;
742 $r1 = $r0;
743 // Load the current input token and decoded values
744 $inChar = $byteClass[$pos];
745 if ( $inChar === '\\' ) {
746 if ( preg_match( '/x([0-9a-fA-F]{2})/A', $byteClass, $m, 0, $pos + 1 ) ) {
747 $x0 = $inChar . $m[0];
748 $d0 = chr( hexdec( $m[1] ) );
749 $pos += strlen( $m[0] );
750 } elseif ( preg_match( '/[0-7]{3}/A', $byteClass, $m, 0, $pos + 1 ) ) {
751 $x0 = $inChar . $m[0];
752 $d0 = chr( octdec( $m[0] ) );
753 $pos += strlen( $m[0] );
754 } elseif ( $pos + 1 >= $length ) {
755 $x0 = $d0 = '\\';
756 } else {
757 $d0 = $byteClass[$pos + 1];
758 $x0 = $inChar . $d0;
759 $pos++;
760 }
761 } else {
762 $x0 = $d0 = $inChar;
763 }
764 $ord0 = ord( $d0 );
765 // Load the current re-encoded value
766 if ( $ord0 < 32 || $ord0 == 0x7f ) {
767 $r0 = sprintf( '\x%02x', $ord0 );
768 } elseif ( $ord0 >= 0x80 ) {
769 // Allow unicode if a single high-bit character appears
770 $r0 = sprintf( '\x%02x', $ord0 );
771 $allowUnicode = true;
772 // @phan-suppress-next-line PhanParamSuspiciousOrder false positive
773 } elseif ( str_contains( '-\\[]^', $d0 ) ) {
774 $r0 = '\\' . $d0;
775 } else {
776 $r0 = $d0;
777 }
778 // Do the output
779 if ( $x0 !== '' && $x1 === '-' && $x2 !== '' ) {
780 // Range
781 if ( $ord2 > $ord0 ) {
782 // Empty range
783 } elseif ( $ord0 >= 0x80 ) {
784 // Unicode range
785 $allowUnicode = true;
786 if ( $ord2 < 0x80 ) {
787 // Keep the non-unicode section of the range
788 $out .= "$r2-\\x7F";
789 }
790 } else {
791 // Normal range
792 $out .= "$r2-$r0";
793 }
794 // Reset state to the initial value
795 // @phan-suppress-next-line PhanPluginRedundantAssignmentInLoop
796 $x0 = $x1 = $d0 = $d1 = $r0 = $r1 = '';
797 } elseif ( $ord2 < 0x80 ) {
798 // ASCII character
799 $out .= $r2;
800 }
801 }
802 // @phan-suppress-next-line PhanRedundantValueComparison
803 if ( $ord1 < 0x80 ) {
804 $out .= $r1;
805 }
806 if ( $ord0 < 0x80 ) {
807 $out .= $r0;
808 }
809 if ( $allowUnicode ) {
810 $out .= '\u0080-\uFFFF';
811 }
812 return $out;
813 }
814
826 public static function makeName( $ns, $title, $fragment = '', $interwiki = '',
827 $canonicalNamespace = false
828 ) {
829 if ( $canonicalNamespace ) {
830 $namespace = MediaWikiServices::getInstance()->getNamespaceInfo()->
831 getCanonicalName( $ns );
832 } else {
833 $namespace = MediaWikiServices::getInstance()->getContentLanguage()->getNsText( $ns );
834 }
835 if ( $namespace === false ) {
836 // See T165149. Awkward, but better than erroneously linking to the main namespace.
837 $namespace = self::makeName( NS_SPECIAL, "Badtitle/NS$ns", '', '', $canonicalNamespace );
838 }
839 $name = $namespace === '' ? $title : "$namespace:$title";
840 if ( strval( $interwiki ) != '' ) {
841 $name = "$interwiki:$name";
842 }
843 if ( strval( $fragment ) != '' ) {
844 $name .= '#' . $fragment;
845 }
846 return $name;
847 }
848
857 public static function compare( $a, $b ) {
858 return $a->getNamespace() <=> $b->getNamespace()
859 ?: strcmp( $a->getDBkey(), $b->getDBkey() );
860 }
861
878 public function isValid() {
879 if ( $this->mIsValid !== null ) {
880 return $this->mIsValid;
881 }
882
883 try {
884 // Optimization: Avoid Title::getFullText because that involves GenderCache
885 // and (unbatched) database queries. For validation, canonical namespace suffices.
886 $text = self::makeName( $this->mNamespace, $this->mDbkeyform, $this->mFragment, $this->mInterwiki, true );
887 $titleParser = MediaWikiServices::getInstance()->getTitleParser();
888
889 $parts = $titleParser->splitTitleString( $text, $this->mNamespace );
890
891 // Check that nothing changed!
892 // This ensures that $text was already properly normalized.
893 if ( $parts['fragment'] !== $this->mFragment
894 || $parts['interwiki'] !== $this->mInterwiki
895 || $parts['local_interwiki'] !== $this->mLocalInterwiki
896 || $parts['namespace'] !== $this->mNamespace
897 || $parts['dbkey'] !== $this->mDbkeyform
898 ) {
899 $this->mIsValid = false;
900 return $this->mIsValid;
901 }
902 } catch ( MalformedTitleException ) {
903 $this->mIsValid = false;
904 return $this->mIsValid;
905 }
906
907 $this->mIsValid = true;
908 return $this->mIsValid;
909 }
910
918 public function isLocal() {
919 if ( $this->isExternal() ) {
920 $iw = self::getInterwikiLookup()->fetch( $this->mInterwiki );
921 if ( $iw ) {
922 return $iw->isLocal();
923 }
924 }
925 return true;
926 }
927
935 public function getInterwiki(): string {
936 return $this->mInterwiki;
937 }
938
944 public function wasLocalInterwiki() {
945 return $this->mLocalInterwiki;
946 }
947
954 public function isTrans() {
955 if ( !$this->isExternal() ) {
956 return false;
957 }
958
959 return self::getInterwikiLookup()->fetch( $this->mInterwiki )->isTranscludable();
960 }
961
967 public function getTransWikiID() {
968 if ( !$this->isExternal() ) {
969 return false;
970 }
971
972 return self::getInterwikiLookup()->fetch( $this->mInterwiki )->getWikiID();
973 }
974
984 public function getTitleValue() {
985 if ( $this->mTitleValue === null ) {
986 try {
987 $this->mTitleValue = new TitleValue(
988 $this->mNamespace,
989 $this->mDbkeyform,
990 $this->mFragment,
991 $this->mInterwiki
992 );
993 } catch ( InvalidArgumentException $ex ) {
994 wfDebug( __METHOD__ . ': Can\'t create a TitleValue for [[' .
995 $this->getPrefixedText() . ']]: ' . $ex->getMessage() );
996 }
997 }
998
999 return $this->mTitleValue;
1000 }
1001
1007 public function getText(): string {
1008 return $this->mTextform;
1009 }
1010
1016 public function getPartialURL() {
1017 return $this->mUrlform;
1018 }
1019
1025 public function getDBkey(): string {
1026 return $this->mDbkeyform;
1027 }
1028
1034 public function getNamespace(): int {
1035 return $this->mNamespace;
1036 }
1037
1044 private function shouldReadLatest( int $flags ) {
1045 return ( $flags & ( IDBAccessObject::READ_LATEST ) ) > 0;
1046 }
1047
1056 public function getContentModel( $flags = 0 ) {
1057 if ( $this->mForcedContentModel ) {
1058 if ( !$this->mContentModel ) {
1059 throw new RuntimeException( 'Got out of sync; an empty model is being forced' );
1060 }
1061 // Content model is locked to the currently loaded one
1062 return $this->mContentModel;
1063 }
1064
1065 if ( $this->shouldReadLatest( $flags ) || !$this->mContentModel ) {
1066 $this->lazyFillContentModel( $this->getFieldFromPageStore( 'page_content_model', $flags ) );
1067 }
1068
1069 if ( !$this->mContentModel ) {
1070 $slotRoleregistry = MediaWikiServices::getInstance()->getSlotRoleRegistry();
1071 $mainSlotHandler = $slotRoleregistry->getRoleHandler( 'main' );
1072 $this->lazyFillContentModel( $mainSlotHandler->getDefaultModel( $this ) );
1073 }
1074
1075 return $this->mContentModel;
1076 }
1077
1084 public function hasContentModel( $id ) {
1085 return $this->getContentModel() == $id;
1086 }
1087
1104 public function setContentModel( $model ) {
1105 if ( (string)$model === '' ) {
1106 throw new InvalidArgumentException( "Missing CONTENT_MODEL_* constant" );
1107 }
1108
1109 $this->uncache();
1110 $this->mContentModel = $model;
1111 $this->mForcedContentModel = true;
1112 }
1113
1119 private function lazyFillContentModel( $model ) {
1120 if ( !$this->mForcedContentModel ) {
1121 $this->mContentModel = ( $model === false ) ? false : (string)$model;
1122 }
1123 }
1124
1130 public function getNsText() {
1131 if ( $this->isExternal() ) {
1132 // This probably shouldn't even happen, except for interwiki transclusion.
1133 // If possible, use the canonical name for the foreign namespace.
1134 if ( $this->mNamespace === NS_MAIN ) {
1135 // Optimisation
1136 return '';
1137 } else {
1138 $nsText = MediaWikiServices::getInstance()->getNamespaceInfo()->
1139 getCanonicalName( $this->mNamespace );
1140 if ( $nsText !== false ) {
1141 return $nsText;
1142 }
1143 }
1144 }
1145
1146 try {
1147 $formatter = self::getTitleFormatter();
1148 return $formatter->getNamespaceName( $this->mNamespace, $this->mDbkeyform );
1149 } catch ( InvalidArgumentException $ex ) {
1150 wfDebug( __METHOD__ . ': ' . $ex->getMessage() );
1151 return false;
1152 }
1153 }
1154
1160 public function getSubjectNsText() {
1161 $services = MediaWikiServices::getInstance();
1162 return $services->getContentLanguage()->
1163 getNsText( $services->getNamespaceInfo()->getSubject( $this->mNamespace ) );
1164 }
1165
1171 public function getTalkNsText() {
1172 $services = MediaWikiServices::getInstance();
1173 return $services->getContentLanguage()->
1174 getNsText( $services->getNamespaceInfo()->getTalk( $this->mNamespace ) );
1175 }
1176
1188 public function canHaveTalkPage() {
1189 return MediaWikiServices::getInstance()->getNamespaceInfo()->canHaveTalkPage( $this );
1190 }
1191
1202 public function canExist(): bool {
1203 // NOTE: Don't use getArticleID(), we don't want to
1204 // trigger a database query here. This check is supposed to
1205 // act as an optimization, not add extra cost.
1206 if ( $this->mArticleID > 0 ) {
1207 // It exists, so it can exist.
1208 return true;
1209 }
1210
1211 // NOTE: we call the relatively expensive isValid() method further down,
1212 // but we can bail out early if we already know the title is invalid.
1213 if ( $this->mIsValid === false ) {
1214 // It's invalid, so it can't exist.
1215 return false;
1216 }
1217
1218 if ( $this->getNamespace() < NS_MAIN ) {
1219 // It's a special page, so it can't exist in the database.
1220 return false;
1221 }
1222
1223 if ( $this->isExternal() ) {
1224 // If it's external, it's not local, so it can't exist.
1225 return false;
1226 }
1227
1228 if ( $this->getText() === '' ) {
1229 // The title has no text, so it can't exist in the database.
1230 // It's probably an on-page section link, like "#something".
1231 return false;
1232 }
1233
1234 // Double check that the title is valid.
1235 return $this->isValid();
1236 }
1237
1243 public function isSpecialPage() {
1244 return $this->mNamespace === NS_SPECIAL;
1245 }
1246
1253 public function isSpecial( $name ) {
1254 if ( $this->isSpecialPage() ) {
1255 [ $thisName, /* $subpage */ ] =
1256 MediaWikiServices::getInstance()->getSpecialPageFactory()->
1257 resolveAlias( $this->mDbkeyform );
1258 if ( $name == $thisName ) {
1259 return true;
1260 }
1261 }
1262 return false;
1263 }
1264
1271 public function fixSpecialName() {
1272 if ( $this->isSpecialPage() ) {
1273 $spFactory = MediaWikiServices::getInstance()->getSpecialPageFactory();
1274 [ $canonicalName, $par ] = $spFactory->resolveAlias( $this->mDbkeyform );
1275 if ( $canonicalName ) {
1276 $localName = $spFactory->getLocalNameFor( $canonicalName, $par );
1277 if ( $localName != $this->mDbkeyform ) {
1278 return self::makeTitle( NS_SPECIAL, $localName );
1279 }
1280 }
1281 }
1282 return $this;
1283 }
1284
1292 public function inNamespace( int $ns ): bool {
1293 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1294 equals( $this->mNamespace, $ns );
1295 }
1296
1304 public function inNamespaces( ...$namespaces ) {
1305 if ( count( $namespaces ) > 0 && is_array( $namespaces[0] ) ) {
1306 $namespaces = $namespaces[0];
1307 }
1308
1309 foreach ( $namespaces as $ns ) {
1310 if ( $this->inNamespace( $ns ) ) {
1311 return true;
1312 }
1313 }
1314
1315 return false;
1316 }
1317
1331 public function hasSubjectNamespace( $ns ) {
1332 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1333 subjectEquals( $this->mNamespace, $ns );
1334 }
1335
1343 public function isContentPage() {
1344 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1345 isContent( $this->mNamespace );
1346 }
1347
1354 public function isMovable() {
1355 $services = MediaWikiServices::getInstance();
1356 if (
1357 !$services->getNamespaceInfo()->
1358 isMovable( $this->mNamespace ) || $this->isExternal()
1359 ) {
1360 // Interwiki title or immovable namespace. Hooks don't get to override here
1361 return false;
1362 }
1363
1364 $result = true;
1365 ( new HookRunner( $services->getHookContainer() ) )->onTitleIsMovable( $this, $result );
1366 return $result;
1367 }
1368
1376 public function isMainPage() {
1377 self::$cachedMainPage ??= self::newMainPage();
1378 return $this->equals( self::$cachedMainPage );
1379 }
1380
1386 public function isSubpage() {
1387 return MediaWikiServices::getInstance()
1388 ->getNamespaceInfo()
1389 ->hasSubpages( $this->mNamespace )
1390 && str_contains( $this->getText(), '/' );
1391 }
1392
1398 public function isConversionTable() {
1399 // @todo ConversionTable should become a separate content model.
1400 // @todo And the prefix should be localized, too!
1401
1402 return $this->mNamespace === NS_MEDIAWIKI &&
1403 str_starts_with( $this->getText(), 'Conversiontable/' );
1404 }
1405
1411 public function isWikitextPage() {
1412 return $this->hasContentModel( CONTENT_MODEL_WIKITEXT );
1413 }
1414
1429 public function isSiteConfigPage() {
1430 return (
1431 $this->isSiteCssConfigPage()
1432 || $this->isSiteJsonConfigPage()
1433 || $this->isSiteJsConfigPage()
1434 );
1435 }
1436
1443 public function isUserConfigPage() {
1444 return (
1445 $this->isUserCssConfigPage()
1446 || $this->isUserJsonConfigPage()
1447 || $this->isUserJsConfigPage()
1448 );
1449 }
1450
1457 public function getSkinFromConfigSubpage() {
1458 $text = $this->getText();
1459 $lastSlashPos = $this->findSubpageDivider( $text, -1 );
1460 if ( $lastSlashPos === false ) {
1461 return '';
1462 }
1463
1464 $lastDot = strrpos( $text, '.', $lastSlashPos );
1465 if ( $lastDot === false ) {
1466 return '';
1467 }
1468
1469 return substr( $text, $lastSlashPos + 1, $lastDot - $lastSlashPos - 1 );
1470 }
1471
1478 public function isUserCssConfigPage() {
1479 return (
1480 $this->mNamespace === NS_USER
1481 && $this->isSubpage()
1482 && $this->hasContentModel( CONTENT_MODEL_CSS )
1483 );
1484 }
1485
1492 public function isUserJsonConfigPage() {
1493 return (
1494 $this->mNamespace === NS_USER
1495 && $this->isSubpage()
1496 && $this->hasContentModel( CONTENT_MODEL_JSON )
1497 );
1498 }
1499
1506 public function isUserJsConfigPage() {
1507 return (
1508 $this->mNamespace === NS_USER
1509 && $this->isSubpage()
1510 && ( $this->hasContentModel( CONTENT_MODEL_JAVASCRIPT ) ||
1511 $this->hasContentModel( CONTENT_MODEL_VUE )
1512 )
1513 );
1514 }
1515
1522 public function isSiteCssConfigPage() {
1523 return (
1524 $this->mNamespace === NS_MEDIAWIKI
1525 && (
1526 $this->hasContentModel( CONTENT_MODEL_CSS )
1527 // paranoia - a MediaWiki: namespace page with mismatching extension and content
1528 // model is probably by mistake and might get handled incorrectly (see e.g. T112937)
1529 || str_ends_with( $this->mDbkeyform, '.css' )
1530 )
1531 );
1532 }
1533
1540 public function isSiteJsonConfigPage() {
1541 return (
1542 $this->mNamespace === NS_MEDIAWIKI
1543 && (
1544 $this->hasContentModel( CONTENT_MODEL_JSON )
1545 // paranoia - a MediaWiki: namespace page with mismatching extension and content
1546 // model is probably by mistake and might get handled incorrectly (see e.g. T112937)
1547 || str_ends_with( $this->mDbkeyform, '.json' )
1548 )
1549 );
1550 }
1551
1558 public function isSiteJsConfigPage() {
1559 return (
1560 $this->mNamespace === NS_MEDIAWIKI
1561 && (
1562 (
1563 $this->hasContentModel( CONTENT_MODEL_JAVASCRIPT )
1564 // paranoia - a MediaWiki: namespace page with mismatching extension and content
1565 // model is probably by mistake and might get handled incorrectly (see e.g. T112937)
1566 || str_ends_with( $this->mDbkeyform, '.js' )
1567 ) || (
1568 $this->hasContentModel( CONTENT_MODEL_VUE )
1569 || str_ends_with( $this->mDbkeyform, '.vue' )
1570 )
1571 )
1572 );
1573 }
1574
1581 public function isRawHtmlMessage() {
1582 global $wgRawHtmlMessages;
1583
1584 if ( !$this->inNamespace( NS_MEDIAWIKI ) ) {
1585 return false;
1586 }
1587 $message = lcfirst( $this->getRootTitle()->getDBkey() );
1588 return in_array( $message, $wgRawHtmlMessages, true );
1589 }
1590
1596 public function isTalkPage() {
1597 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1598 isTalk( $this->mNamespace );
1599 }
1600
1612 public function getTalkPage() {
1613 // NOTE: The equivalent code in NamespaceInfo is less lenient about producing invalid titles.
1614 // Instead of failing on invalid titles, let's just log the issue for now.
1615 // See the discussion on T227817.
1616
1617 // Is this the same title?
1618 $talkNS = MediaWikiServices::getInstance()->getNamespaceInfo()->getTalk( $this->mNamespace );
1619 if ( $this->mNamespace == $talkNS ) {
1620 return $this;
1621 }
1622
1623 $title = self::makeTitle( $talkNS, $this->mDbkeyform );
1624
1625 $this->warnIfPageCannotExist( $title, __METHOD__ );
1626
1627 return $title;
1628 // TODO: replace the above with the code below:
1629 // return self::castFromLinkTarget(
1630 // MediaWikiServices::getInstance()->getNamespaceInfo()->getTalkPage( $this ) );
1631 }
1632
1642 public function getTalkPageIfDefined() {
1643 if ( !$this->canHaveTalkPage() ) {
1644 return null;
1645 }
1646
1647 return $this->getTalkPage();
1648 }
1649
1657 public function getSubjectPage() {
1658 // Is this the same title?
1659 $subjectNS = MediaWikiServices::getInstance()->getNamespaceInfo()
1660 ->getSubject( $this->mNamespace );
1661 if ( $this->mNamespace == $subjectNS ) {
1662 return $this;
1663 }
1664 // NOTE: The equivalent code in NamespaceInfo is less lenient about producing invalid titles.
1665 // Instead of failing on invalid titles, let's just log the issue for now.
1666 // See the discussion on T227817.
1667 $title = self::makeTitle( $subjectNS, $this->mDbkeyform );
1668
1669 $this->warnIfPageCannotExist( $title, __METHOD__ );
1670
1671 return $title;
1672 // TODO: replace the above with the code below:
1673 // return self::castFromLinkTarget(
1674 // MediaWikiServices::getInstance()->getNamespaceInfo()->getSubjectPage( $this ) );
1675 }
1676
1683 private function warnIfPageCannotExist( Title $title, $method ) {
1684 if ( $this->getText() == '' ) {
1686 $method . ': called on empty title ' . $this->getFullText() . ', returning '
1687 . $title->getFullText()
1688 );
1689
1690 return true;
1691 }
1692
1693 if ( $this->getInterwiki() !== '' ) {
1695 $method . ': called on interwiki title ' . $this->getFullText() . ', returning '
1696 . $title->getFullText()
1697 );
1698
1699 return true;
1700 }
1701
1702 return false;
1703 }
1704
1714 public function getOtherPage() {
1715 // NOTE: Depend on the methods in this class instead of their equivalent in NamespaceInfo,
1716 // until their semantics has become exactly the same.
1717 // See the discussion on T227817.
1718 if ( $this->isSpecialPage() ) {
1719 throw new MWException( 'Special pages cannot have other pages' );
1720 }
1721 if ( $this->isTalkPage() ) {
1722 return $this->getSubjectPage();
1723 } else {
1724 if ( !$this->canHaveTalkPage() ) {
1725 throw new MWException( "{$this->getPrefixedText()} does not have an other page" );
1726 }
1727 return $this->getTalkPage();
1728 }
1729 // TODO: replace the above with the code below:
1730 // return self::castFromLinkTarget(
1731 // MediaWikiServices::getInstance()->getNamespaceInfo()->getAssociatedPage( $this ) );
1732 }
1733
1741 public function getFragment(): string {
1742 return $this->mFragment;
1743 }
1744
1750 public function getFragmentForURL() {
1751 if ( !$this->hasFragment() ) {
1752 return '';
1753 } elseif ( $this->isExternal() ) {
1754 // Note: If the interwiki is unknown, it's treated as a namespace on the local wiki,
1755 // so we treat it like a local interwiki.
1756 $interwiki = self::getInterwikiLookup()->fetch( $this->mInterwiki );
1757 if ( $interwiki && !$interwiki->isLocal() ) {
1758 return '#' . Sanitizer::escapeIdForExternalInterwiki( $this->mFragment );
1759 }
1760 }
1761
1762 return '#' . Sanitizer::escapeIdForLink( $this->mFragment );
1763 }
1764
1775 public function setFragment( $fragment ) {
1776 $this->uncache();
1777 if ( str_starts_with( $fragment, '#' ) ) {
1778 $fragment = substr( $fragment, 1 );
1779 }
1780 $this->mFragment = self::normalizeFragment( $fragment );
1781 }
1782
1790 public function createFragmentTarget( string $fragment ): self {
1791 return self::makeTitle(
1792 $this->mNamespace,
1793 $this->getText(),
1794 $fragment,
1795 $this->mInterwiki
1796 );
1797 }
1798
1805 private static function normalizeFragment( $fragment ) {
1806 return strtr( $fragment, '_', ' ' );
1807 }
1808
1816 private function prefix( $name ) {
1817 $p = '';
1818 if ( $this->isExternal() ) {
1819 $p = $this->mInterwiki . ':';
1820 }
1821
1822 if ( $this->mNamespace != 0 ) {
1823 $nsText = $this->getNsText();
1824
1825 if ( $nsText === false ) {
1826 // See T165149. Awkward, but better than erroneously linking to the main namespace.
1827 $nsText = MediaWikiServices::getInstance()->getContentLanguage()->
1828 getNsText( NS_SPECIAL ) . ":Badtitle/NS{$this->mNamespace}";
1829 }
1830
1831 $p .= $nsText . ':';
1832 }
1833 return $p . $name;
1834 }
1835
1842 public function getPrefixedDBkey() {
1843 $s = $this->prefix( $this->mDbkeyform );
1844 $s = strtr( $s, ' ', '_' );
1845 return $s;
1846 }
1847
1854 public function getPrefixedText() {
1855 if ( $this->prefixedText === null ) {
1856 $s = $this->prefix( $this->mTextform );
1857 $s = strtr( $s, '_', ' ' );
1858 $this->prefixedText = $s;
1859 }
1860 return $this->prefixedText;
1861 }
1862
1868 public function __toString(): string {
1869 return $this->getPrefixedText();
1870 }
1871
1878 public function getFullText() {
1879 $text = $this->getPrefixedText();
1880 if ( $this->hasFragment() ) {
1881 $text .= '#' . $this->mFragment;
1882 }
1883 return $text;
1884 }
1885
1900 private function findSubpageDivider( $text, $dir ) {
1901 if ( $dir > 0 ) {
1902 // Skip leading slashes, but keep the last one when there is nothing but slashes
1903 $bottom = strspn( $text, '/', 0, -1 );
1904 $idx = strpos( $text, '/', $bottom );
1905 } else {
1906 // Any slash from the end can be a divider, as subpage names can be empty
1907 $idx = strrpos( $text, '/' );
1908 }
1909
1910 // The first character can never be a divider, as that would result in an empty base
1911 return $idx === 0 ? false : $idx;
1912 }
1913
1918 private function hasSubpagesEnabled() {
1919 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1920 hasSubpages( $this->mNamespace );
1921 }
1922
1938 public function getRootText() {
1939 $text = $this->getText();
1940 if ( !$this->hasSubpagesEnabled() ) {
1941 return $text;
1942 }
1943
1944 $firstSlashPos = $this->findSubpageDivider( $text, +1 );
1945 // Don't discard the real title if there's no subpage involved
1946 if ( $firstSlashPos === false ) {
1947 return $text;
1948 }
1949
1950 return substr( $text, 0, $firstSlashPos );
1951 }
1952
1965 public function getRootTitle() {
1966 $title = self::makeTitleSafe( $this->mNamespace, $this->getRootText() );
1967
1968 if ( !$title ) {
1969 if ( !$this->isValid() ) {
1970 // If the title wasn't valid in the first place, we can't expect
1971 // to successfully parse it. T290194
1972 return $this;
1973 }
1974
1975 Assert::postcondition(
1976 $title !== null,
1977 'makeTitleSafe() should always return a Title for the text ' .
1978 'returned by getRootText().'
1979 );
1980 }
1981
1982 return $title;
1983 }
1984
1999 public function getBaseText() {
2000 $text = $this->getText();
2001 if ( !$this->hasSubpagesEnabled() ) {
2002 return $text;
2003 }
2004
2005 $lastSlashPos = $this->findSubpageDivider( $text, -1 );
2006 // Don't discard the real title if there's no subpage involved
2007 if ( $lastSlashPos === false ) {
2008 return $text;
2009 }
2010
2011 return substr( $text, 0, $lastSlashPos );
2012 }
2013
2026 public function getBaseTitle() {
2027 $title = self::makeTitleSafe( $this->mNamespace, $this->getBaseText() );
2028
2029 if ( !$title ) {
2030 if ( !$this->isValid() ) {
2031 // If the title wasn't valid in the first place, we can't expect
2032 // to successfully parse it. T290194
2033 return $this;
2034 }
2035
2036 Assert::postcondition(
2037 $title !== null,
2038 'makeTitleSafe() should always return a Title for the text ' .
2039 'returned by getBaseText().'
2040 );
2041 }
2042
2043 return $title;
2044 }
2045
2057 public function getSubpageText() {
2058 $text = $this->getText();
2059 if ( !$this->hasSubpagesEnabled() ) {
2060 return $text;
2061 }
2062
2063 $lastSlashPos = $this->findSubpageDivider( $text, -1 );
2064 if ( $lastSlashPos === false ) {
2065 // T256922 - Return the title text if no subpages
2066 return $text;
2067 }
2068 return substr( $text, $lastSlashPos + 1 );
2069 }
2070
2084 public function getSubpage( $text ) {
2085 return self::makeTitleSafe(
2086 $this->mNamespace,
2087 $this->getText() . '/' . $text,
2088 '',
2089 $this->mInterwiki
2090 );
2091 }
2092
2105 public function getFullSubpageText() {
2106 $text = $this->getText();
2107 $slashPos = strpos( $text, '/' );
2108
2109 if ( $slashPos === false ) {
2110 return '';
2111 }
2112
2113 return substr( $text, $slashPos + 1 );
2114 }
2115
2121 public function getSubpageUrlForm() {
2122 $text = $this->getSubpageText();
2123 $text = wfUrlencode( strtr( $text, ' ', '_' ) );
2124 return $text;
2125 }
2126
2133 public function getPrefixedURL( string $query = '' ) {
2134 $s = $this->prefix( $this->mDbkeyform );
2135 $s = wfUrlencode( strtr( $s, ' ', '_' ) );
2136 if ( $query !== '' ) {
2137 $s = wfAppendQuery( $s, $query );
2138 }
2139 return $s;
2140 }
2141
2153 public function getFullURL( $query = '', $query2 = false, $proto = PROTO_RELATIVE ) {
2154 $services = MediaWikiServices::getInstance();
2155
2156 $query = is_array( $query ) ? wfArrayToCgi( $query ) : $query;
2157
2158 # Hand off all the decisions on urls to getLocalURL
2159 $url = $this->getLocalURL( $query );
2160
2161 # Expand the url to make it a full url. Note that getLocalURL has the
2162 # potential to output full urls for a variety of reasons, so we use
2163 # UrlUtils::expand() instead of simply prepending $wgServer
2164 $url = (string)$services->getUrlUtils()->expand( $url, $proto );
2165
2166 # Finally, add the fragment.
2167 $url .= $this->getFragmentForURL();
2168 ( new HookRunner( $services->getHookContainer() ) )->onGetFullURL( $this, $url, $query );
2169 return $url;
2170 }
2171
2188 public function getFullUrlForRedirect( $query = '', $proto = PROTO_CURRENT ) {
2189 $target = $this;
2190 if ( $this->isExternal() && !$this->isLocal() ) {
2191 $target = SpecialPage::getTitleFor(
2192 'GoToInterwiki',
2193 $this->getPrefixedDBkey()
2194 );
2195 }
2196 return $target->getFullURL( $query, false, $proto );
2197 }
2198
2216 public function getLocalURL( $query = '' ) {
2218
2219 $query = is_array( $query ) ? wfArrayToCgi( $query ) : $query;
2220
2221 $services = MediaWikiServices::getInstance();
2222 $hookRunner = new HookRunner( $services->getHookContainer() );
2223 $interwiki = self::getInterwikiLookup()->fetch( $this->mInterwiki );
2224 if ( $interwiki ) {
2225 $namespace = $this->getNsText();
2226 if ( $namespace != '' ) {
2227 # Can this actually happen? Interwikis shouldn't be parsed.
2228 # Yes! It can in interwiki transclusion. But... it probably shouldn't.
2229 $namespace .= ':';
2230 }
2231 $url = $interwiki->getURL( $namespace . $this->mDbkeyform );
2232 $url = wfAppendQuery( $url, $query );
2233 } else {
2234 $dbkey = wfUrlencode( $this->getPrefixedDBkey() );
2235 if ( $query == '' ) {
2236 if ( $wgMainPageIsDomainRoot && $this->isMainPage() ) {
2237 $url = '/';
2238 } else {
2239 $url = str_replace( '$1', $dbkey, $wgArticlePath );
2240 }
2241 $hookRunner->onGetLocalURL__Article( $this, $url );
2242 } else {
2244 $url = false;
2245 $matches = [];
2246
2247 $articlePaths = PathRouter::getActionPaths( $wgActionPaths, $wgArticlePath );
2248
2249 if ( $articlePaths
2250 && preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches )
2251 ) {
2252 $action = urldecode( $matches[2] );
2253 if ( isset( $articlePaths[$action] ) ) {
2254 $query = $matches[1];
2255 if ( isset( $matches[4] ) ) {
2256 $query .= $matches[4];
2257 }
2258 $url = str_replace( '$1', $dbkey, $articlePaths[$action] );
2259 if ( $query != '' ) {
2260 $url = wfAppendQuery( $url, $query );
2261 }
2262 }
2263 }
2264
2265 if ( $url === false
2267 && preg_match( '/^variant=([^&]*)$/', $query, $matches )
2268 && $this->getPageLanguage()->equals( $services->getContentLanguage() )
2269 && $this->getPageLanguageConverter()->hasVariants()
2270 ) {
2271 $variant = urldecode( $matches[1] );
2272 if ( $this->getPageLanguageConverter()->hasVariant( $variant ) ) {
2273 // Only do the variant replacement if the given variant is a valid
2274 // variant for the page's language.
2275 $url = str_replace( '$2', urlencode( $variant ), $wgVariantArticlePath );
2276 $url = str_replace( '$1', $dbkey, $url );
2277 }
2278 }
2279
2280 if ( $url === false ) {
2281 if ( $query == '-' ) {
2282 $query = '';
2283 }
2284 $url = "{$wgScript}?title={$dbkey}&{$query}";
2285 }
2286 }
2287 $hookRunner->onGetLocalURL__Internal( $this, $url, $query );
2288 }
2289
2290 $hookRunner->onGetLocalURL( $this, $url, $query );
2291 return $url;
2292 }
2293
2311 public function getLinkURL( $query = '', $query2 = false, $proto = false ) {
2312 if ( $this->isExternal() || $proto !== false ) {
2313 $ret = $this->getFullURL( $query, false, $proto );
2314 } elseif ( $this->getPrefixedText() === '' && $this->hasFragment() ) {
2315 $ret = $this->getFragmentForURL();
2316 } else {
2317 $ret = $this->getLocalURL( $query ) . $this->getFragmentForURL();
2318 }
2319 return $ret;
2320 }
2321
2335 public function getInternalURL( $query = '' ) {
2337 $services = MediaWikiServices::getInstance();
2338
2339 $query = is_array( $query ) ? wfArrayToCgi( $query ) : $query;
2340
2341 $server = $wgInternalServer !== false ? $wgInternalServer : $wgServer;
2342 $url = (string)$services->getUrlUtils()->expand( $server . $this->getLocalURL( $query ), PROTO_HTTP );
2343 ( new HookRunner( $services->getHookContainer() ) )
2344 ->onGetInternalURL( $this, $url, $query );
2345 return $url;
2346 }
2347
2360 public function getCanonicalURL( $query = '' ) {
2361 $services = MediaWikiServices::getInstance();
2362
2363 $query = is_array( $query ) ? wfArrayToCgi( $query ) : $query;
2364
2365 $url = (string)$services->getUrlUtils()->expand(
2366 $this->getLocalURL( $query ) . $this->getFragmentForURL(),
2368 );
2369 ( new HookRunner( $services->getHookContainer() ) )
2370 ->onGetCanonicalURL( $this, $url, $query );
2371 return $url;
2372 }
2373
2379 public function getEditURL() {
2380 if ( $this->isExternal() ) {
2381 return '';
2382 }
2383 $s = $this->getLocalURL( 'action=edit' );
2384
2385 return $s;
2386 }
2387
2393 public static function purgeExpiredRestrictions() {
2394 if ( MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly() ) {
2395 return;
2396 }
2397
2398 DeferredUpdates::addUpdate( new AutoCommitUpdate(
2399 MediaWikiServices::getInstance()->getConnectionProvider()->getPrimaryDatabase(),
2400 __METHOD__,
2401 static function ( IDatabase $dbw, $fname ) {
2402 $config = MediaWikiServices::getInstance()->getMainConfig();
2403 $ids = $dbw->newSelectQueryBuilder()
2404 ->select( 'pr_id' )
2405 ->from( 'page_restrictions' )
2406 ->where( $dbw->expr( 'pr_expiry', '<', $dbw->timestamp() ) )
2407 ->limit( $config->get( MainConfigNames::UpdateRowsPerQuery ) ) // T135470
2408 ->caller( $fname )->fetchFieldValues();
2409 if ( $ids ) {
2410 $dbw->newDeleteQueryBuilder()
2411 ->deleteFrom( 'page_restrictions' )
2412 ->where( [ 'pr_id' => $ids ] )
2413 ->caller( $fname )->execute();
2414 }
2415
2416 $dbw->newDeleteQueryBuilder()
2417 ->deleteFrom( 'protected_titles' )
2418 ->where( $dbw->expr( 'pt_expiry', '<', $dbw->timestamp() ) )
2419 ->caller( $fname )->execute();
2420 }
2421 ) );
2422 }
2423
2429 public function hasSubpages() {
2430 if (
2431 !MediaWikiServices::getInstance()->getNamespaceInfo()->
2432 hasSubpages( $this->mNamespace )
2433 ) {
2434 # Duh
2435 return false;
2436 }
2437
2438 # We dynamically add a member variable for the purpose of this method
2439 # alone to cache the result. There's no point in having it hanging
2440 # around uninitialized in every Title object; therefore we only add it
2441 # if needed and don't declare it statically.
2442 if ( $this->mHasSubpages === null ) {
2443 $subpages = $this->getSubpages( 1 );
2444 $this->mHasSubpages = $subpages instanceof TitleArrayFromResult && $subpages->count();
2445 }
2446
2447 return $this->mHasSubpages;
2448 }
2449
2457 public function getSubpages( $limit = -1 ) {
2458 if (
2459 !MediaWikiServices::getInstance()->getNamespaceInfo()->
2460 hasSubpages( $this->mNamespace )
2461 ) {
2462 return [];
2463 }
2464
2465 $services = MediaWikiServices::getInstance();
2466 $pageStore = $services->getPageStore();
2467 $titleFactory = $services->getTitleFactory();
2468 $query = $pageStore->newSelectQueryBuilder()
2469 ->fields( $pageStore->getSelectFields() )
2470 ->whereTitlePrefix( $this->getNamespace(), $this->getDBkey() . '/' )
2471 ->caller( __METHOD__ );
2472 if ( $limit > -1 ) {
2473 $query->limit( $limit );
2474 }
2475
2476 return $titleFactory->newTitleArrayFromResult( $query->fetchResultSet() );
2477 }
2478
2485 public function isDeleted() {
2486 return $this->getDeletedEditsCount();
2487 }
2488
2495 public function getDeletedEditsCount() {
2496 if ( $this->mNamespace < 0 ) {
2497 return 0;
2498 }
2499
2500 $dbr = $this->getDbProvider()->getReplicaDatabase();
2501 $n = (int)$dbr->newSelectQueryBuilder()
2502 ->select( 'COUNT(*)' )
2503 ->from( 'archive' )
2504 ->where( [ 'ar_namespace' => $this->mNamespace, 'ar_title' => $this->mDbkeyform ] )
2505 ->caller( __METHOD__ )->fetchField();
2506 if ( $this->mNamespace === NS_FILE ) {
2507 $n += $dbr->newSelectQueryBuilder()
2508 ->select( 'COUNT(*)' )
2509 ->from( 'filearchive' )
2510 ->where( [ 'fa_name' => $this->mDbkeyform ] )
2511 ->caller( __METHOD__ )->fetchField();
2512 }
2513 return $n;
2514 }
2515
2522 public function isDeletedQuick() {
2523 return $this->hasDeletedEdits();
2524 }
2525
2532 public function hasDeletedEdits() {
2533 if ( $this->mNamespace < 0 ) {
2534 return false;
2535 }
2536 $dbr = $this->getDbProvider()->getReplicaDatabase();
2537 $deleted = (bool)$dbr->newSelectQueryBuilder()
2538 ->select( '1' )
2539 ->from( 'archive' )
2540 ->where( [ 'ar_namespace' => $this->mNamespace, 'ar_title' => $this->mDbkeyform ] )
2541 ->caller( __METHOD__ )->fetchField();
2542 if ( !$deleted && $this->mNamespace === NS_FILE ) {
2543 $deleted = (bool)$dbr->newSelectQueryBuilder()
2544 ->select( '1' )
2545 ->from( 'filearchive' )
2546 ->where( [ 'fa_name' => $this->mDbkeyform ] )
2547 ->caller( __METHOD__ )->fetchField();
2548 }
2549 return $deleted;
2550 }
2551
2559 public function getArticleID( $flags = 0 ) {
2560 if ( $this->mArticleID === -1 && !$this->canExist() ) {
2561 $this->mArticleID = 0;
2562
2563 return $this->mArticleID;
2564 }
2565
2566 if ( $this->mArticleID === -1 || $this->shouldReadLatest( $flags ) ) {
2567 $this->mArticleID = (int)$this->getFieldFromPageStore( 'page_id', $flags );
2568 }
2569
2570 return $this->mArticleID;
2571 }
2572
2587 public function isRedirect( $flags = 0 ) {
2588 if ( $this->shouldReadLatest( $flags ) || $this->mRedirect === null ) {
2589 $this->mRedirect = (bool)$this->getFieldFromPageStore( 'page_is_redirect', $flags );
2590 }
2591
2592 return $this->mRedirect;
2593 }
2594
2602 public function getLength( $flags = 0 ) {
2603 if ( $this->shouldReadLatest( $flags ) || $this->mLength < 0 ) {
2604 $this->mLength = (int)$this->getFieldFromPageStore( 'page_len', $flags );
2605 }
2606
2607 if ( $this->mLength < 0 ) {
2608 $this->mLength = 0;
2609 }
2610
2611 return $this->mLength;
2612 }
2613
2620 public function getLatestRevID( $flags = 0 ) {
2621 if ( $this->shouldReadLatest( $flags ) || $this->mLatestID === false ) {
2622 $this->mLatestID = (int)$this->getFieldFromPageStore( 'page_latest', $flags );
2623 }
2624
2625 if ( !$this->mLatestID ) {
2626 $this->mLatestID = 0;
2627 }
2628
2629 return $this->mLatestID;
2630 }
2631
2645 public function resetArticleID( $id ) {
2646 if ( $id === false ) {
2647 $this->mArticleID = -1;
2648 } else {
2649 $this->mArticleID = (int)$id;
2650 }
2651 $this->mRedirect = null;
2652 $this->mLength = -1;
2653 $this->mLatestID = false;
2654 $this->mContentModel = false;
2655 $this->mForcedContentModel = false;
2656 $this->mEstimateRevisions = null;
2657 $this->mPageLanguage = null;
2658 $this->mDbPageLanguage = false;
2659 $this->mIsBigDeletion = null;
2660
2661 $this->uncache();
2662 MediaWikiServices::getInstance()->getLinkCache()->clearLink( $this );
2663 MediaWikiServices::getInstance()->getRestrictionStore()->flushRestrictions( $this );
2664 }
2665
2666 public static function clearCaches() {
2667 if ( MediaWikiServices::hasInstance() ) {
2668 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
2669 $linkCache->clear();
2670 $pageProps = MediaWikiServices::getInstance()->getPageProps();
2671 $pageProps->clear();
2672 }
2673
2674 // Reset cached main page instance (T395214).
2675 self::$cachedMainPage = null;
2676
2677 $titleCache = self::getTitleCache();
2678 $titleCache->clear();
2679 }
2680
2688 public static function capitalize( $text, $ns = NS_MAIN ) {
2689 $services = MediaWikiServices::getInstance();
2690 if ( $services->getNamespaceInfo()->isCapitalized( $ns ) ) {
2691 return $services->getContentLanguage()->ucfirst( $text );
2692 } else {
2693 return $text;
2694 }
2695 }
2696
2713 private function secureAndSplit( $text, $defaultNamespace = null ) {
2714 $defaultNamespace ??= self::DEFAULT_NAMESPACE;
2715
2716 // @note: splitTitleString() is a temporary hack to allow TitleParser to share
2717 // the parsing code with Title, while avoiding massive refactoring.
2718 // @todo: get rid of secureAndSplit, refactor parsing code.
2719 $titleParser = MediaWikiServices::getInstance()->getTitleParser();
2720 // MalformedTitleException can be thrown here
2721 $parts = $titleParser->splitTitleString( $text, $defaultNamespace );
2722
2723 # Fill fields
2724 $this->setFragment( '#' . $parts['fragment'] );
2725 $this->mInterwiki = $parts['interwiki'];
2726 $this->mLocalInterwiki = $parts['local_interwiki'];
2727 $this->mNamespace = $parts['namespace'];
2728
2729 $this->mDbkeyform = $parts['dbkey'];
2730 $this->mUrlform = wfUrlencode( $this->mDbkeyform );
2731 $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' );
2732
2733 // splitTitleString() guarantees that this title is valid.
2734 $this->mIsValid = true;
2735
2736 # We already know that some pages won't be in the database!
2737 if ( $this->isExternal() || $this->isSpecialPage() || $this->mTextform === '' ) {
2738 $this->mArticleID = 0;
2739 }
2740 }
2741
2754 public function getLinksTo( $options = [], $table = 'pagelinks', $prefix = 'pl' ) {
2755 $domainMap = [
2756 'categorylinks' => CategoryLinksTable::VIRTUAL_DOMAIN,
2757 'imagelinks' => ImageLinksTable::VIRTUAL_DOMAIN,
2758 'pagelinks' => PageLinksTable::VIRTUAL_DOMAIN,
2759 'templatelinks' => TemplateLinksTable::VIRTUAL_DOMAIN,
2760 ];
2761 $domain = $domainMap[$table] ?? false;
2762
2763 if ( count( $options ) > 0 ) {
2764 $db = $this->getDbProvider()->getPrimaryDatabase( $domain );
2765 } else {
2766 $db = $this->getDbProvider()->getReplicaDatabase( $domain );
2767 }
2768
2769 $linksMigration = MediaWikiServices::getInstance()->getLinksMigration();
2770 if ( isset( $linksMigration::$mapping[$table] ) ) {
2771 $titleConds = $linksMigration->getLinksConditions( $table, $this );
2772 } else {
2773 $titleConds = [
2774 "{$prefix}_namespace" => $this->mNamespace,
2775 "{$prefix}_title" => $this->mDbkeyform
2776 ];
2777 }
2778
2779 $res = $db->newSelectQueryBuilder()
2780 ->select( LinkCache::getSelectFields() )
2781 ->from( $table )
2782 ->join( 'page', null, "{$prefix}_from=page_id" )
2783 ->where( $titleConds )
2784 ->options( $options )
2785 ->caller( __METHOD__ )
2786 ->fetchResultSet();
2787
2788 $retVal = [];
2789 if ( $res->numRows() ) {
2790 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
2791 foreach ( $res as $row ) {
2792 $titleObj = self::makeTitle( $row->page_namespace, $row->page_title );
2793 if ( $titleObj ) {
2794 $linkCache->addGoodLinkObjFromRow( $titleObj, $row );
2795 $retVal[] = $titleObj;
2796 }
2797 }
2798 }
2799 return $retVal;
2800 }
2801
2812 public function getTemplateLinksTo( $options = [] ) {
2813 return $this->getLinksTo( $options, 'templatelinks', 'tl' );
2814 }
2815
2828 public function getLinksFrom( $options = [], $table = 'pagelinks', $prefix = 'pl' ) {
2829 $id = $this->getArticleID();
2830
2831 # If the page doesn't exist; there can't be any link from this page
2832 if ( !$id ) {
2833 return [];
2834 }
2835
2836 $domainMap = [
2837 'categorylinks' => CategoryLinksTable::VIRTUAL_DOMAIN,
2838 'imagelinks' => ImageLinksTable::VIRTUAL_DOMAIN,
2839 'pagelinks' => PageLinksTable::VIRTUAL_DOMAIN,
2840 'templatelinks' => TemplateLinksTable::VIRTUAL_DOMAIN,
2841 ];
2842 $domain = $domainMap[$table] ?? false;
2843
2844 $db = $this->getDbProvider()->getReplicaDatabase( $domain );
2845 $linksMigration = MediaWikiServices::getInstance()->getLinksMigration();
2846
2847 $queryBuilder = $db->newSelectQueryBuilder();
2848 if ( isset( $linksMigration::$mapping[$table] ) ) {
2849 [ $blNamespace, $blTitle ] = $linksMigration->getTitleFields( $table );
2850 $linktargetQueryInfo = $linksMigration->getQueryInfo( $table );
2851 $queryBuilder->queryInfo( $linktargetQueryInfo );
2852 } else {
2853 $blNamespace = "{$prefix}_namespace";
2854 $blTitle = "{$prefix}_title";
2855 $queryBuilder->select( [ $blNamespace, $blTitle ] )
2856 ->from( $table );
2857 }
2858
2859 $pageQuery = WikiPage::getQueryInfo();
2860 $res = $queryBuilder
2861 ->where( [ "{$prefix}_from" => $id ] )
2862 ->leftJoin( 'page', null, [ "page_namespace=$blNamespace", "page_title=$blTitle" ] )
2863 ->fields( $pageQuery['fields'] )
2864 ->options( $options )
2865 ->caller( __METHOD__ )
2866 ->fetchResultSet();
2867
2868 $retVal = [];
2869 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
2870 foreach ( $res as $row ) {
2871 if ( $row->page_id ) {
2872 $titleObj = self::newFromRow( $row );
2873 } else {
2874 $titleObj = self::makeTitle( $row->$blNamespace, $row->$blTitle );
2875 $linkCache->addBadLinkObj( $titleObj );
2876 }
2877 $retVal[] = $titleObj;
2878 }
2879
2880 return $retVal;
2881 }
2882
2893 public function getTemplateLinksFrom( $options = [] ) {
2894 return $this->getLinksFrom( $options, 'templatelinks', 'tl' );
2895 }
2896
2904 public function isSingleRevRedirect() {
2905 $dbw = $this->getDbProvider()->getPrimaryDatabase();
2906 $dbw->startAtomic( __METHOD__ );
2907 $pageStore = MediaWikiServices::getInstance()->getPageStore();
2908
2909 $row = $dbw->newSelectQueryBuilder()
2910 ->select( $pageStore->getSelectFields() )
2911 ->from( 'page' )
2912 ->where( $this->pageCond() )
2913 ->caller( __METHOD__ )->fetchRow();
2914 // Update the cached fields
2915 $this->loadFromRow( $row );
2916
2917 if ( $this->mRedirect && $this->mLatestID ) {
2918 $isSingleRevRedirect = !$dbw->newSelectQueryBuilder()
2919 ->select( '1' )
2920 ->forUpdate()
2921 ->from( 'revision' )
2922 ->where( [ 'rev_page' => $this->mArticleID, $dbw->expr( 'rev_id', '!=', (int)$this->mLatestID ) ] )
2923 ->caller( __METHOD__ )->fetchField();
2924 } else {
2925 $isSingleRevRedirect = false;
2926 }
2927
2928 $dbw->endAtomic( __METHOD__ );
2929
2930 return $isSingleRevRedirect;
2931 }
2932
2940 public function getParentCategories() {
2941 $data = [];
2942
2943 $titleKey = $this->getArticleID();
2944
2945 if ( $titleKey === 0 ) {
2946 return $data;
2947 }
2948
2949 $dbr = $this->getDbProvider()->getReplicaDatabase( CategoryLinksTable::VIRTUAL_DOMAIN );
2950 $res = $dbr->newSelectQueryBuilder()
2951 ->select( 'lt_title' )
2952 ->from( 'categorylinks' )
2953 ->join( 'linktarget', null, 'cl_target_id = lt_id' )
2954 ->where( [ 'cl_from' => $titleKey, 'lt_namespace' => NS_CATEGORY ] )
2955 ->caller( __METHOD__ )
2956 ->fetchResultSet();
2957
2958 if ( $res->numRows() > 0 ) {
2959 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
2960 foreach ( $res as $row ) {
2961 // $data[] = Title::newFromText( $contLang->getNsText ( NS_CATEGORY ).':'.$row->lt_title);
2962 $data[$contLang->getNsText( NS_CATEGORY ) . ':' . $row->lt_title] =
2963 $this->getFullText();
2964 }
2965 }
2966 return $data;
2967 }
2968
2975 public function getParentCategoryTree( $children = [] ) {
2976 $stack = [];
2977 $parents = $this->getParentCategories();
2978
2979 if ( $parents ) {
2980 foreach ( $parents as $parent => $current ) {
2981 if ( array_key_exists( $parent, $children ) ) {
2982 # Circular reference
2983 $stack[$parent] = [];
2984 } else {
2985 $nt = self::newFromText( $parent );
2986 if ( $nt ) {
2987 $stack[$parent] = $nt->getParentCategoryTree( $children + [ $parent => 1 ] );
2988 }
2989 }
2990 }
2991 }
2992
2993 return $stack;
2994 }
2995
3002 public function pageCond() {
3003 if ( $this->mArticleID > 0 ) {
3004 // PK avoids secondary lookups in InnoDB, shouldn't hurt other DBs
3005 return [ 'page_id' => $this->mArticleID ];
3006 } else {
3007 return [ 'page_namespace' => $this->mNamespace, 'page_title' => $this->mDbkeyform ];
3008 }
3009 }
3010
3019 public function isNewPage( $flags = IDBAccessObject::READ_NORMAL ) {
3020 // NOTE: we rely on PHP casting "0" to false here.
3021 return (bool)$this->getFieldFromPageStore( 'page_is_new', $flags );
3022 }
3023
3030 public function isBigDeletion() {
3032
3033 if ( !$wgDeleteRevisionsLimit ) {
3034 return false;
3035 }
3036
3037 if ( $this->mIsBigDeletion === null ) {
3038 $dbr = $this->getDbProvider()->getReplicaDatabase();
3039 $revCount = $dbr->newSelectQueryBuilder()
3040 ->select( '1' )
3041 ->from( 'revision' )
3042 ->where( [ 'rev_page' => $this->getArticleID() ] )
3043 ->limit( $wgDeleteRevisionsLimit + 1 )
3044 ->caller( __METHOD__ )->fetchRowCount();
3045
3046 $this->mIsBigDeletion = $revCount > $wgDeleteRevisionsLimit;
3047 }
3048
3049 return $this->mIsBigDeletion;
3050 }
3051
3057 public function estimateRevisionCount() {
3058 if ( !$this->exists() ) {
3059 return 0;
3060 }
3061
3062 if ( $this->mEstimateRevisions === null ) {
3063 $dbr = $this->getDbProvider()->getReplicaDatabase();
3064 $this->mEstimateRevisions = $dbr->newSelectQueryBuilder()
3065 ->select( '*' )
3066 ->from( 'revision' )
3067 ->where( [ 'rev_page' => $this->getArticleID() ] )
3068 ->caller( __METHOD__ )
3069 ->estimateRowCount();
3070 }
3071
3072 return $this->mEstimateRevisions;
3073 }
3074
3089 public function equals( object $other ) {
3090 // NOTE: In contrast to isSameLinkAs(), this ignores the fragment part!
3091 // NOTE: In contrast to isSamePageAs(), this ignores the page ID!
3092 // NOTE: === is necessary for proper matching of number-like titles
3093 return $other instanceof Title
3094 && $this->getInterwiki() === $other->getInterwiki()
3095 && $this->getNamespace() === $other->getNamespace()
3096 && $this->getDBkey() === $other->getDBkey();
3097 }
3098
3103 public function isSamePageAs( PageReference $other ): bool {
3104 // NOTE: keep in sync with PageReferenceValue::isSamePageAs()!
3105 return $this->getWikiId() === $other->getWikiId()
3106 && $this->getNamespace() === $other->getNamespace()
3107 && $this->getDBkey() === $other->getDBkey();
3108 }
3109
3116 public function isSubpageOf( Title $title ) {
3117 return $this->mInterwiki === $title->mInterwiki
3118 && $this->mNamespace == $title->mNamespace
3119 && str_starts_with( $this->mDbkeyform, $title->mDbkeyform . '/' );
3120 }
3121
3132 public function exists( $flags = 0 ): bool {
3133 $exists = $this->getArticleID( $flags ) != 0;
3134 ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )->onTitleExists( $this, $exists );
3135 return $exists;
3136 }
3137
3154 public function isAlwaysKnown() {
3155 $services = MediaWikiServices::getInstance();
3156 return $services->getLinkAlwaysKnownLookup()->isAlwaysKnown( $this );
3157 }
3158
3170 public function isKnown() {
3171 return $this->isAlwaysKnown() || $this->exists();
3172 }
3173
3180 public function hasSourceText() {
3181 wfDeprecated( __METHOD__, '1.47' );
3182 if ( $this->exists() ) {
3183 return true;
3184 }
3185
3186 if ( $this->mNamespace === NS_MEDIAWIKI ) {
3187 $services = MediaWikiServices::getInstance();
3188 // If the page doesn't exist but is a known system message, default
3189 // message content will be displayed, same for language subpages-
3190 // Use always content language to avoid loading hundreds of languages
3191 // to get the link color.
3192 $contLang = $services->getContentLanguage();
3193 [ $name, ] = $services->getMessageCache()->figureMessage(
3194 $contLang->lcfirst( $this->getText() )
3195 );
3196 $message = wfMessage( $name )->inLanguage( $contLang )->useDatabase( false );
3197 return $message->exists();
3198 }
3199
3200 return false;
3201 }
3202
3210 public function getDefaultMessageText() {
3211 wfDeprecated( __METHOD__, '1.47' );
3212 $message = $this->getDefaultSystemMessage();
3213
3214 return $message ? $message->plain() : false;
3215 }
3216
3225 public function getDefaultSystemMessage(): ?Message {
3226 wfDeprecated( __METHOD__, '1.47' );
3227 if ( $this->mNamespace !== NS_MEDIAWIKI ) { // Just in case
3228 return null;
3229 }
3230
3231 [ $name, $lang ] = MediaWikiServices::getInstance()->getMessageCache()->figureMessage(
3232 MediaWikiServices::getInstance()->getContentLanguage()->lcfirst( $this->getText() )
3233 );
3234
3235 if ( wfMessage( $name )->inLanguage( $lang )->useDatabase( false )->exists() ) {
3236 return wfMessage( $name )->inLanguage( $lang );
3237 } else {
3238 return null;
3239 }
3240 }
3241
3248 public function invalidateCache( $purgeTime = null ) {
3249 if ( MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly() ) {
3250 return false;
3251 }
3252 if ( $this->mArticleID === 0 ) {
3253 // avoid gap locking if we know it's not there
3254 return true;
3255 }
3256
3257 $conds = $this->pageCond();
3258
3259 // Periodically recompute page_random (T309477). This mitigates bias on
3260 // Special:Random due deleted pages leaving "gaps" in the distribution.
3261 //
3262 // Optimization: Update page_random only for 10% of updates.
3263 // Optimization: Do this outside the main transaction to avoid locking for too long.
3264 // Optimization: Update page_random alongside page_touched to avoid extra database writes.
3265 DeferredUpdates::addUpdate(
3266 new AutoCommitUpdate(
3267 $this->getDbProvider()->getPrimaryDatabase(),
3268 __METHOD__,
3269 function ( IDatabase $dbw, $fname ) use ( $conds, $purgeTime ) {
3270 $dbTimestamp = $dbw->timestamp( $purgeTime ?: time() );
3271 $update = $dbw->newUpdateQueryBuilder()
3272 ->update( 'page' )
3273 ->set( [ 'page_touched' => $dbTimestamp ] )
3274 ->where( $conds )
3275 ->andWhere( $dbw->expr( 'page_touched', '<', $dbTimestamp ) );
3276
3277 if ( mt_rand( 1, 10 ) === 1 ) {
3278 $update->andSet( [ 'page_random' => wfRandom() ] );
3279 }
3280
3281 $update->caller( $fname )->execute();
3282 MediaWikiServices::getInstance()->getLinkWriteDuplicator()->duplicate( $update );
3283
3284 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $this );
3285 }
3286 ),
3287 DeferredUpdates::PRESEND
3288 );
3289
3290 return true;
3291 }
3292
3298 public function touchLinks() {
3299 $jobs = [];
3300 $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
3301 $this,
3302 'pagelinks',
3303 [ 'causeAction' => 'page-touch' ]
3304 );
3305 $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
3306 $this,
3307 'existencelinks',
3308 [ 'causeAction' => 'existence-touch' ]
3309 );
3310 if ( $this->mNamespace === NS_CATEGORY ) {
3311 $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
3312 $this,
3313 'categorylinks',
3314 [ 'causeAction' => 'category-touch' ]
3315 );
3316 }
3317
3318 MediaWikiServices::getInstance()->getJobQueueGroup()->lazyPush( $jobs );
3319 }
3320
3327 public function getTouched( int $flags = IDBAccessObject::READ_NORMAL ) {
3328 $touched = $this->getFieldFromPageStore( 'page_touched', $flags );
3329 return $touched ? MWTimestamp::convert( TS::MW, $touched ) : false;
3330 }
3331
3338 public function getNamespaceKey( $prepend = 'nstab-' ) {
3339 // Gets the subject namespace of this title
3340 $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
3341 $subjectNS = $nsInfo->getSubject( $this->mNamespace );
3342 // Prefer canonical namespace name for HTML IDs
3343 $namespaceKey = $nsInfo->getCanonicalName( $subjectNS );
3344 if ( $namespaceKey === false ) {
3345 // Fallback to localised text
3346 $namespaceKey = $this->getSubjectNsText();
3347 }
3348 // Makes namespace key lowercase
3349 $namespaceKey = MediaWikiServices::getInstance()->getContentLanguage()->lc( $namespaceKey );
3350 // Uses main
3351 if ( $namespaceKey == '' ) {
3352 $namespaceKey = 'main';
3353 }
3354 // Changes file to image for backwards compatibility
3355 if ( $namespaceKey == 'file' ) {
3356 $namespaceKey = 'image';
3357 }
3358 return $prepend . $namespaceKey;
3359 }
3360
3367 public function getRedirectsHere( $ns = null ) {
3368 $redirs = [];
3369
3370 $queryBuilder = $this->getDbProvider()->getReplicaDatabase()->newSelectQueryBuilder()
3371 ->select( [ 'page_namespace', 'page_title' ] )
3372 ->from( 'redirect' )
3373 ->join( 'page', null, 'rd_from = page_id' )
3374 ->where( [
3375 'rd_namespace' => $this->mNamespace,
3376 'rd_title' => $this->mDbkeyform,
3377 'rd_interwiki' => $this->isExternal() ? $this->mInterwiki : '',
3378 ] );
3379
3380 if ( $ns !== null ) {
3381 $queryBuilder->andWhere( [ 'page_namespace' => $ns ] );
3382 }
3383
3384 $res = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
3385
3386 foreach ( $res as $row ) {
3387 $redirs[] = self::newFromRow( $row );
3388 }
3389 return $redirs;
3390 }
3391
3397 public function isValidRedirectTarget() {
3399
3400 if ( $this->isSpecialPage() ) {
3401 // invalid redirect targets are stored in a global array, but explicitly disallow Userlogout here
3402 foreach ( [ 'Userlogout', ...$wgInvalidRedirectTargets ] as $target ) {
3403 if ( $this->isSpecial( $target ) ) {
3404 return false;
3405 }
3406 }
3407 return true;
3408 }
3409
3410 // relative section links are not valid redirect targets (T278367)
3411 return $this->getDBkey() !== '' && $this->isValid();
3412 }
3413
3420 public function canUseNoindex() {
3421 wfDeprecated( __METHOD__, '1.47' );
3422 return MediaWikiServices::getInstance()->getNamespaceInfo()->canUseNoindex(
3423 $this->mNamespace
3424 );
3425 }
3426
3437 public function getCategorySortkey( $prefix = '' ) {
3438 $unprefixed = $this->getText();
3439
3440 // Anything that uses this hook should only depend
3441 // on the Title object passed in, and should probably
3442 // tell the users to run updateCollations.php --force
3443 // in order to re-sort existing category relations.
3444 ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
3445 ->onGetDefaultSortkey( $this, $unprefixed );
3446 if ( $prefix !== '' ) {
3447 # Separate with a line feed, so the unprefixed part is only used as
3448 # a tiebreaker when two pages have the exact same prefix.
3449 # In UCA, tab is the only character that can sort above LF
3450 # so we strip both of them from the original prefix.
3451 $prefix = strtr( $prefix, "\n\t", ' ' );
3452 return "$prefix\n$unprefixed";
3453 }
3454 return $unprefixed;
3455 }
3456
3466 private function getDbPageLanguageCode( int $flags = 0 ): ?string {
3467 global $wgPageLanguageUseDB;
3468
3469 // check, if the page language could be saved in the database, and if so and
3470 // the value is not requested already, lookup the page language using PageStore
3471 if ( $wgPageLanguageUseDB && $this->mDbPageLanguage === false ) {
3472 $this->mDbPageLanguage = $this->getFieldFromPageStore( 'page_lang', $flags ) ?: null;
3473 }
3474
3475 return $this->mDbPageLanguage ?: null;
3476 }
3477
3485 private function getDbPageLanguage(): ?Language {
3486 $languageCode = $this->getDbPageLanguageCode();
3487 if ( $languageCode === null ) {
3488 return null;
3489 }
3490 $services = MediaWikiServices::getInstance();
3491 if ( !$services->getLanguageNameUtils()->isKnownLanguageTag( $languageCode ) ) {
3492 return null;
3493 }
3494 return $services->getLanguageFactory()->getLanguage( $languageCode );
3495 }
3496
3505 public function getPageLanguage() {
3506 global $wgLanguageCode;
3507 if ( $this->isSpecialPage() ) {
3508 // special pages are in the user language
3509 return RequestContext::getMain()->getLanguage();
3510 }
3511
3512 // Checking if DB language is set
3513 $dbPageLanguage = $this->getDbPageLanguage();
3514 if ( $dbPageLanguage ) {
3515 return $dbPageLanguage;
3516 }
3517
3518 $services = MediaWikiServices::getInstance();
3519 if ( !$this->mPageLanguage || $this->mPageLanguage[1] !== $wgLanguageCode ) {
3520 // Note that this may depend on user settings, so the cache should
3521 // be only per-request.
3522 // NOTE: ContentHandler::getPageLanguage() may need to load the
3523 // content to determine the page language!
3524 // Checking $wgLanguageCode hasn't changed for the benefit of unit
3525 // tests.
3526 $contentHandler = $services->getContentHandlerFactory()
3527 ->getContentHandler( $this->getContentModel() );
3528 $langObj = $contentHandler->getPageLanguage( $this );
3529 $this->mPageLanguage = [ $langObj->getCode(), $wgLanguageCode ];
3530 } else {
3531 $langObj = $services->getLanguageFactory()
3532 ->getLanguage( $this->mPageLanguage[0] );
3533 }
3534
3535 return $langObj;
3536 }
3537
3548 public function getPageViewLanguage() {
3549 wfDeprecated( __METHOD__, '1.42' );
3550 $services = MediaWikiServices::getInstance();
3551
3552 if ( $this->isSpecialPage() ) {
3553 // If the user chooses a variant, the content is actually
3554 // in a language whose code is the variant code.
3555 $userLang = RequestContext::getMain()->getLanguage();
3556 $variant = $this->getLanguageConverter( $userLang )->getPreferredVariant();
3557 if ( $userLang->getCode() !== $variant ) {
3558 return $services->getLanguageFactory()
3559 ->getLanguage( $variant );
3560 }
3561
3562 return $userLang;
3563 }
3564
3565 // Checking if DB language is set
3566 $pageLang = $this->getDbPageLanguage();
3567 if ( $pageLang ) {
3568 $variant = $this->getLanguageConverter( $pageLang )->getPreferredVariant();
3569 if ( $pageLang->getCode() !== $variant ) {
3570 return $services->getLanguageFactory()
3571 ->getLanguage( $variant );
3572 }
3573
3574 return $pageLang;
3575 }
3576
3577 // @note Can't be cached persistently, depends on user settings.
3578 // @note ContentHandler::getPageViewLanguage() may need to load the
3579 // content to determine the page language!
3580 $contentHandler = $services->getContentHandlerFactory()
3581 ->getContentHandler( $this->getContentModel() );
3582 $pageLang = $contentHandler->getPageViewLanguage( $this );
3583 return $pageLang;
3584 }
3585
3596 public function getEditNotices( $oldid = 0 ) {
3597 $notices = [];
3598
3599 $editnotice_base = 'editnotice-' . $this->mNamespace;
3600 // Optional notice for the entire namespace
3601 $messages = [ $editnotice_base => 'namespace' ];
3602
3603 if (
3604 MediaWikiServices::getInstance()->getNamespaceInfo()->
3605 hasSubpages( $this->mNamespace )
3606 ) {
3607 // Optional notice for page itself and any parent page
3608 foreach ( explode( '/', $this->mDbkeyform ) as $part ) {
3609 $editnotice_base .= '-' . $part;
3610 $messages[$editnotice_base] = 'base';
3611 }
3612 } else {
3613 // Even if there are no subpages in namespace, we still don't want "/" in MediaWiki message keys
3614 $messages[$editnotice_base . '-' . strtr( $this->mDbkeyform, '/', '-' )] = 'page';
3615 }
3616
3617 foreach ( $messages as $editnoticeText => $class ) {
3618 // The following messages are used here:
3619 // * editnotice-0
3620 // * editnotice-0-Title
3621 // * editnotice-0-Title-Subpage
3622 // * editnotice-…
3623 $msg = wfMessage( $editnoticeText )->page( $this );
3624 if ( $msg->exists() ) {
3625 $html = $msg->parseAsBlock();
3626 // Edit notices may have complex logic, but output nothing (T91715)
3627 if ( trim( $html ) !== '' ) {
3628 $notices[$editnoticeText] = Html::rawElement(
3629 'div',
3630 [ 'class' => [
3631 'mw-editnotice',
3632 // The following classes are used here:
3633 // * mw-editnotice-namespace
3634 // * mw-editnotice-base
3635 // * mw-editnotice-page
3636 "mw-editnotice-$class",
3637 // The following classes are used here:
3638 // * mw-editnotice-0
3639 // * mw-editnotice-…
3640 Sanitizer::escapeClass( "mw-$editnoticeText" )
3641 ] ],
3642 $html
3643 );
3644 }
3645 }
3646 }
3647
3648 ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
3649 ->onTitleGetEditNotices( $this, $oldid, $notices );
3650 return $notices;
3651 }
3652
3658 private function getFieldFromPageStore( $field, $flags ) {
3659 $pageStore = MediaWikiServices::getInstance()->getPageStore();
3660
3661 if ( !in_array( $field, $pageStore->getSelectFields(), true ) ) {
3662 throw new InvalidArgumentException( "Unknown field: $field" );
3663 }
3664
3665 if ( $flags === IDBAccessObject::READ_NORMAL && $this->mArticleID === 0 ) {
3666 // page does not exist
3667 return false;
3668 }
3669
3670 if ( !$this->canExist() ) {
3671 return false;
3672 }
3673
3674 $page = $pageStore->getPageByReference( $this, $flags );
3675
3676 if ( $page instanceof PageStoreRecord ) {
3677 return $page->getField( $field );
3678 } else {
3679 // The page record failed to load, remember the page as non-existing.
3680 // Note that this can happen even if a page ID was known before under some
3681 // rare circumstances, if this method is called with the READ_LATEST bit set
3682 // and the page has been deleted since the ID had initially been determined.
3683 $this->mArticleID = 0;
3684 return false;
3685 }
3686 }
3687
3691 public function __sleep() {
3692 return [
3693 'mNamespace',
3694 'mDbkeyform',
3695 'mFragment',
3696 'mInterwiki',
3697 'mLocalInterwiki',
3698 ];
3699 }
3700
3701 public function __wakeup() {
3702 $this->mArticleID = ( $this->mNamespace >= 0 ) ? -1 : 0;
3703 $this->mUrlform = wfUrlencode( $this->mDbkeyform );
3704 $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' );
3705 }
3706
3707 public function __clone() {
3708 $this->mInstanceCacheKey = null;
3709 }
3710
3720 public function getWikiId() {
3721 return self::LOCAL;
3722 }
3723
3740 public function getId( $wikiId = self::LOCAL ): int {
3741 $this->assertWiki( $wikiId );
3742 $this->assertProperPage();
3743 return $this->getArticleID();
3744 }
3745
3758 private function assertProperPage() {
3759 Assert::precondition(
3760 $this->canExist(),
3761 'This Title instance does not represent a proper page, but merely a link target.'
3762 );
3763 }
3764
3778 // TODO: replace individual member fields with a PageIdentityValue that is always present
3779
3780 $this->assertProperPage();
3781
3782 return new PageIdentityValue(
3783 $this->getId(),
3784 $this->getNamespace(),
3785 $this->getDBkey(),
3786 $this->getWikiId()
3787 );
3788 }
3789
3804 public function toPageRecord( $flags = 0 ): ExistingPageRecord {
3805 // TODO: Cache this? Construct is more efficiently?
3806
3807 $this->assertProperPage();
3808
3809 Assert::precondition(
3810 $this->exists( $flags ),
3811 'This Title instance does not represent an existing page: ' . $this
3812 );
3813
3814 return new PageStoreRecord(
3815 (object)[
3816 'page_id' => $this->getArticleID( $flags ),
3817 'page_namespace' => $this->getNamespace(),
3818 'page_title' => $this->getDBkey(),
3819 'page_wiki_id' => $this->getWikiId(),
3820 'page_latest' => $this->getLatestRevID( $flags ),
3821 'page_is_new' => $this->isNewPage( $flags ),
3822 'page_is_redirect' => $this->isRedirect( $flags ),
3823 'page_touched' => $this->getTouched( $flags ),
3824 'page_lang' => $this->getDbPageLanguageCode( $flags ),
3825 ],
3826 PageIdentity::LOCAL
3827 );
3828 }
3829
3837 public function toPageReference(): PageReference {
3838 $this->assertProperPage();
3839 return new PageReferenceValue(
3840 $this->getNamespace(),
3841 $this->getDBkey(),
3842 PageReferenceValue::LOCAL
3843 );
3844 }
3845
3846}
const PROTO_CANONICAL
Definition Defines.php:223
const CONTENT_MODEL_VUE
Definition Defines.php:241
const NS_USER
Definition Defines.php:53
const CONTENT_MODEL_CSS
Definition Defines.php:237
const NS_FILE
Definition Defines.php:57
const PROTO_CURRENT
Definition Defines.php:222
const NS_MAIN
Definition Defines.php:51
const NS_MEDIAWIKI
Definition Defines.php:59
const NS_SPECIAL
Definition Defines.php:40
const CONTENT_MODEL_WIKITEXT
Definition Defines.php:235
const CONTENT_MODEL_JSON
Definition Defines.php:239
const PROTO_HTTP
Definition Defines.php:217
const PROTO_RELATIVE
Definition Defines.php:219
const NS_CATEGORY
Definition Defines.php:65
const CONTENT_MODEL_JAVASCRIPT
Definition Defines.php:236
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:71
Group all the pieces relevant to the context of a request into one instance.
Deferrable Update for closure/callback updates that should use auto-commit mode.
Defer callable updates to run later in the PHP process.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
This class is a collection of static functions that serve two purposes:
Definition Html.php:44
Job to purge the HTML/file cache for all pages that link to or use another page or file.
Base class for language-specific code.
Definition Language.php:65
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:144
inLanguage( $lang)
Request the message in any language that is supported.
Definition Message.php:890
Page existence and metadata cache.
Definition LinkCache.php:53
Immutable value object representing a page identity.
Immutable value object representing a page reference.
Immutable data record representing an editable page on a wiki.
Base representation for an editable wiki page.
Definition WikiPage.php:83
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:34
MediaWiki\Request\PathRouter class.
Parent class for all special pages.
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Represents the target of a wiki link.
Represents a title within MediaWiki.
Definition Title.php:69
getFullText()
Get the prefixed title with spaces, plus any fragment (part beginning with '#')
Definition Title.php:1878
getTalkPage()
Get a Title object associated with the talk page of this article.
Definition Title.php:1612
getSubpageUrlForm()
Get a URL-encoded form of the subpage text.
Definition Title.php:2121
toPageRecord( $flags=0)
Returns the page represented by this Title as a ProperPageRecord.
Definition Title.php:3804
getOtherPage()
Get the other title for this page, if this is a subject page get the talk page, if it is a subject pa...
Definition Title.php:1714
isKnown()
Does this title refer to a page that can (or might) be meaningfully viewed? In particular,...
Definition Title.php:3170
canExist()
Can this title represent a page in the wiki's database?
Definition Title.php:1202
toPageReference()
Returns the page represented by this Title as a PageReferenceValue.
Definition Title.php:3837
isSubpage()
Is this a subpage?
Definition Title.php:1386
static convertByteClassToUnicodeClass( $byteClass)
Utility method for converting a character sequence from bytes to Unicode.
Definition Title.php:720
isMovable()
Would anybody with sufficient privileges be able to move this page? Some pages just aren't movable.
Definition Title.php:1354
getFragment()
Get the Title fragment (i.e.
Definition Title.php:1741
isLocal()
Determine whether the object refers to a page within this project (either this wiki or a wiki with a ...
Definition Title.php:918
getLocalURL( $query='')
Get a URL with no fragment or server name (relative URL) from a Title object.
Definition Title.php:2216
getEditNotices( $oldid=0)
Get a list of rendered edit notices for this page.
Definition Title.php:3596
canHaveTalkPage()
Can this title have a corresponding talk page?
Definition Title.php:1188
isSamePageAs(PageReference $other)
Checks whether the given PageReference refers to the same page as this PageReference....
Definition Title.php:3103
getDefaultMessageText()
Get the default (plain) message contents for a page that overrides an interface message key.
Definition Title.php:3210
static capitalize( $text, $ns=NS_MAIN)
Capitalize a text string for a title if it belongs to a namespace that capitalizes.
Definition Title.php:2688
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid,...
Definition Title.php:423
canUseNoindex()
Whether the magic words INDEX and NOINDEX function for this page.
Definition Title.php:3420
getPageLanguage()
Get the language in which the content of this page is written in wikitext.
Definition Title.php:3505
const NEW_CLONE
Flag for use with factory methods like newFromLinkTarget() that have a $forceClone parameter.
Definition Title.php:96
getLatestRevID( $flags=0)
What is the page_latest field for this page?
Definition Title.php:2620
getDeletedEditsCount()
Is there a version of this page in the deletion archive?
Definition Title.php:2495
isTrans()
Determine whether the object refers to a page within this project and is transcludable.
Definition Title.php:954
getNamespaceKey( $prepend='nstab-')
Generate strings used for xml 'id' names in monobook tabs.
Definition Title.php:3338
inNamespaces(... $namespaces)
Returns true if the title is inside one of the specified namespaces.
Definition Title.php:1304
isUserJsConfigPage()
Is this a JS "config" subpage of a user page?
Definition Title.php:1506
getSubjectNsText()
Get the namespace text of the subject (rather than talk) page.
Definition Title.php:1160
isRawHtmlMessage()
Is this a message which can contain raw HTML?
Definition Title.php:1581
static newFromID( $id, $flags=0)
Create a new Title from an article ID.
Definition Title.php:522
getSubpageText()
Get the lowest-level subpage name, i.e.
Definition Title.php:2057
getEditURL()
Get the edit URL for this Title.
Definition Title.php:2379
getSkinFromConfigSubpage()
Trim down a .css, .json, or .js subpage title to get the corresponding skin name.
Definition Title.php:1457
static purgeExpiredRestrictions()
Purge expired restrictions from the page_restrictions table.
Definition Title.php:2393
touchLinks()
Update page_touched timestamps and send CDN purge messages for pages linking to this title.
Definition Title.php:3298
getFullUrlForRedirect( $query='', $proto=PROTO_CURRENT)
Get a url appropriate for making redirects based on an untrusted url arg.
Definition Title.php:2188
setContentModel( $model)
Set a proposed content model for the page for permissions checking.
Definition Title.php:1104
static newFromRow( $row)
Make a Title object from a DB row.
Definition Title.php:549
getNsText()
Get the namespace text.
Definition Title.php:1130
isSiteJsonConfigPage()
Is this a sitewide JSON "config" page?
Definition Title.php:1540
isSiteConfigPage()
Could this MediaWiki namespace page contain custom CSS, JSON, or JavaScript for the global UI.
Definition Title.php:1429
isValid()
Returns true if the title is a valid link target, and that it has been properly normalized.
Definition Title.php:878
isValidRedirectTarget()
Check if this Title is a valid redirect target.
Definition Title.php:3397
createFragmentTarget(string $fragment)
Creates a new Title for a different fragment of the same page.
Definition Title.php:1790
setFragment( $fragment)
Set the fragment for this title.
Definition Title.php:1775
getSubpages( $limit=-1)
Get all subpages of this page.
Definition Title.php:2457
isNewPage( $flags=IDBAccessObject::READ_NORMAL)
Check if this is a new page.
Definition Title.php:3019
isRedirect( $flags=0)
Is this an article that is a redirect page? Uses link cache, adding it if necessary.
Definition Title.php:2587
int $mLength
The page length, 0 for special pages.
Definition Title.php:166
static newFromLinkTarget(ParsoidLinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
Definition Title.php:279
isSiteJsConfigPage()
Is this a sitewide JS "config" page?
Definition Title.php:1558
getCanonicalURL( $query='')
Get the URL for a canonical link, for use in things like IRC and e-mail notifications.
Definition Title.php:2360
int false $mLatestID
ID of most recent revision.
Definition Title.php:131
isSingleRevRedirect()
Locks the page row and check if this page is single revision redirect.
Definition Title.php:2904
isDeletedQuick()
Is there a version of this page in the deletion archive?
Definition Title.php:2522
getTalkPageIfDefined()
Get a Title object associated with the talk page of this article, if such a talk page can exist.
Definition Title.php:1642
static newMainPage(?MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition Title.php:676
static makeName( $ns, $title, $fragment='', $interwiki='', $canonicalNamespace=false)
Make a prefixed DB key from a DB key and a namespace index.
Definition Title.php:826
inNamespace(int $ns)
Returns true if the title is inside the specified namespace.
Definition Title.php:1292
isConversionTable()
Is this a conversion table for the LanguageConverter?
Definition Title.php:1398
isUserCssConfigPage()
Is this a CSS "config" subpage of a user page?
Definition Title.php:1478
hasSubjectNamespace( $ns)
Returns true if the title has the same subject namespace as the namespace specified.
Definition Title.php:1331
static compare( $a, $b)
Callback for usort() to do title sorts by (namespace, title)
Definition Title.php:857
exists( $flags=0)
Check if page exists.
Definition Title.php:3132
getSubpage( $text)
Get the title for a subpage of the current page.
Definition Title.php:2084
static newFromPageIdentity(PageIdentity $pageIdentity)
Return a Title for a given PageIdentity.
Definition Title.php:318
equals(object $other)
Compares with another Title.
Definition Title.php:3089
hasSourceText()
Does this page have source text?
Definition Title.php:3180
pageCond()
Get an associative array for selecting this title from the "page" table.
Definition Title.php:3002
getLinksTo( $options=[], $table='pagelinks', $prefix='pl')
Get an array of Title objects linking to this Title Also stores the IDs in the link cache.
Definition Title.php:2754
isBigDeletion()
Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit.
Definition Title.php:3030
getBaseTitle()
Get the base page name title, i.e.
Definition Title.php:2026
estimateRevisionCount()
Get the approximate revision count of this page.
Definition Title.php:3057
isUserConfigPage()
Is this a "config" (.css, .json, or .js) subpage of a user page?
Definition Title.php:1443
resetArticleID( $id)
Inject a page ID, reset DB-loaded fields, and clear the link cache for this title.
Definition Title.php:2645
getTouched(int $flags=IDBAccessObject::READ_NORMAL)
Get the last touched timestamp.
Definition Title.php:3327
getPrefixedURL(string $query='')
Get a URL-encoded title (not an actual URL) including interwiki.
Definition Title.php:2133
isTalkPage()
Is this a talk page of some sort?
Definition Title.php:1596
hasDeletedEdits()
Is there a version of this page in the deletion archive?
Definition Title.php:2532
static castFromPageReference(?PageReference $pageReference)
Same as newFromPageReference(), but if passed null, returns null.
Definition Title.php:362
getId( $wikiId=self::LOCAL)
Returns the page ID.
Definition Title.php:3740
getFullURL( $query='', $query2=false, $proto=PROTO_RELATIVE)
Get a real URL referring to this title, with interwiki link and fragment.
Definition Title.php:2153
null bool $mRedirect
Is the article at this title a redirect?
Definition Title.php:169
getArticleID( $flags=0)
Get the article ID for this Title from the link cache, adding it if necessary.
Definition Title.php:2559
getPageViewLanguage()
Get the language in which the content of this page is written when viewed by user.
Definition Title.php:3548
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition Title.php:388
getFragmentForURL()
Get the fragment in URL form, including the "#" character if there is one.
Definition Title.php:1750
getNamespace()
Get the namespace index, i.e.
Definition Title.php:1034
static newFromURL( $url)
THIS IS NOT THE FUNCTION YOU WANT.
Definition Title.php:485
getInterwiki()
Get the interwiki prefix.
Definition Title.php:935
getTemplateLinksTo( $options=[])
Get an array of Title objects using this Title as a template Also stores the IDs in the link cache.
Definition Title.php:2812
getLinksFrom( $options=[], $table='pagelinks', $prefix='pl')
Get an array of Title objects linked from this Title Also stores the IDs in the link cache.
Definition Title.php:2828
hasContentModel( $id)
Convenience method for checking a title's content model name.
Definition Title.php:1084
getSubjectPage()
Get a title object associated with the subject page of this talk page.
Definition Title.php:1657
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition Title.php:640
getDefaultSystemMessage()
Same as getDefaultMessageText, but returns a Message object.
Definition Title.php:3225
getFullSubpageText()
Get the entire subpage string of a title.
Definition Title.php:2105
getPartialURL()
Get the URL-encoded form of the main part.
Definition Title.php:1016
getWikiId()
Returns false to indicate that this Title belongs to the local wiki.
Definition Title.php:3720
getLength( $flags=0)
What is the length of this page? Uses link cache, adding it if necessary.
Definition Title.php:2602
getDBkey()
Get the main part with underscores.
Definition Title.php:1025
getContentModel( $flags=0)
Get the page's content model id, see the CONTENT_MODEL_XXX constants.
Definition Title.php:1056
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition Title.php:614
static castFromPageIdentity(?PageIdentity $pageIdentity)
Same as newFromPageIdentity(), but if passed null, returns null.
Definition Title.php:329
static castFromLinkTarget(?ParsoidLinkTarget $linkTarget)
Same as newFromLinkTarget(), but if passed null, returns null.
Definition Title.php:303
getTitleValue()
Get a TitleValue object representing this Title.
Definition Title.php:984
int $mArticleID
Article ID, fetched from the link cache on demand.
Definition Title.php:128
isSubpageOf(Title $title)
Check if this title is a subpage of another title.
Definition Title.php:3116
isSpecialPage()
Returns true if this is a special page.
Definition Title.php:1243
getText()
Get the text form (spaces not underscores) of the main part.
Definition Title.php:1007
isMainPage()
Is this the mainpage?
Definition Title.php:1376
isAlwaysKnown()
Should links to this title be shown as potentially viewable (i.e.
Definition Title.php:3154
toPageIdentity()
Returns the page represented by this Title as a ProperPageIdentity.
Definition Title.php:3777
getParentCategories()
Get categories to which this Title belongs and return an array of categories' names.
Definition Title.php:2940
string null $prefixedText
Text form including namespace/interwiki, initialised on demand.
Definition Title.php:156
static newFromDBkey( $key)
Create a new Title from a prefixed DB key.
Definition Title.php:257
isSpecial( $name)
Returns true if this title resolves to the named special page.
Definition Title.php:1253
getPrefixedDBkey()
Get the prefixed database key form.
Definition Title.php:1842
getRootText()
Get the root page name text without a namespace, i.e.
Definition Title.php:1938
isWikitextPage()
Does that page contain wikitext, or it is JS, CSS or whatever?
Definition Title.php:1411
fixSpecialName()
If the Title refers to a special page alias which is not the local default, resolve the alias,...
Definition Title.php:1271
getTransWikiID()
Returns the DB name of the distant wiki which owns the object.
Definition Title.php:967
getTemplateLinksFrom( $options=[])
Get an array of Title objects used on this Title as a template Also stores the IDs in the link cache.
Definition Title.php:2893
invalidateCache( $purgeTime=null)
Updates page_touched for this page; called from LinksUpdate.php.
Definition Title.php:3248
getTalkNsText()
Get the namespace text of the talk page.
Definition Title.php:1171
hasSubpages()
Does this have subpages? (Warning, usually requires an extra DB query.)
Definition Title.php:2429
getRedirectsHere( $ns=null)
Get all extant redirects to this Title.
Definition Title.php:3367
getPrefixedText()
Get the prefixed title with spaces.
Definition Title.php:1854
wasLocalInterwiki()
Was this a local interwiki link?
Definition Title.php:944
getLinkURL( $query='', $query2=false, $proto=false)
Get a URL that's the simplest URL that will be valid to link, locally, to the current Title.
Definition Title.php:2311
getCategorySortkey( $prefix='')
Returns the raw sort key to be used for categories, with the specified prefix.
Definition Title.php:3437
getInternalURL( $query='')
Get the URL form for an internal link.
Definition Title.php:2335
static newFromPageReference(PageReference $pageReference)
Return a Title for a given Reference.
Definition Title.php:341
isContentPage()
Is this Title in a namespace which contains content? In other words, is this a content page,...
Definition Title.php:1343
static legalChars()
Get a regex character class describing the legal characters in a link.
Definition Title.php:706
getParentCategoryTree( $children=[])
Get a tree of parent categories.
Definition Title.php:2975
getRootTitle()
Get the root page name title, i.e.
Definition Title.php:1965
isSiteCssConfigPage()
Is this a sitewide CSS "config" page?
Definition Title.php:1522
isDeleted()
Is there a version of this page in the deletion archive?
Definition Title.php:2485
isUserJsonConfigPage()
Is this a JSON "config" subpage of a user page?
Definition Title.php:1492
__toString()
Return a string representation of this title.
Definition Title.php:1868
getBaseText()
Get the base page name without a namespace, i.e.
Definition Title.php:1999
loadFromRow( $row)
Load Title object fields from a DB row.
Definition Title.php:561
Library for creating and parsing MW-style timestamps.
Store key-value entries in a size-limited in-memory LRU cache.
return[ 'config-schema-inverse'=>['default'=>['ConfigRegistry'=>['main'=> 'MediaWiki\\Config\\GlobalVarConfig::newInstance',], 'Sitename'=> 'MediaWiki', 'Server'=> false, 'CanonicalServer'=> false, 'ServerName'=> false, 'AssumeProxiesUseDefaultProtocolPorts'=> true, 'HttpsPort'=> 443, 'ForceHTTPS'=> false, 'ScriptPath'=> '/wiki', 'UsePathInfo'=> null, 'Script'=> false, 'LoadScript'=> false, 'RestPath'=> false, 'StylePath'=> false, 'LocalStylePath'=> false, 'ExtensionAssetsPath'=> false, 'ExtensionDirectory'=> null, 'StyleDirectory'=> null, 'ArticlePath'=> false, 'UploadPath'=> false, 'ImgAuthPath'=> false, 'ThumbPath'=> false, 'UploadDirectory'=> false, 'FileCacheDirectory'=> false, 'Logo'=> false, 'Logos'=> false, 'Favicon'=> '/favicon.ico', 'AppleTouchIcon'=> false, 'ReferrerPolicy'=> false, 'TmpDirectory'=> false, 'UploadBaseUrl'=> '', 'UploadStashScalerBaseUrl'=> false, 'ActionPaths'=>[], 'MainPageIsDomainRoot'=> false, 'EnableUploads'=> false, 'UploadStashMaxAge'=> 21600, 'EnableAsyncUploads'=> false, 'EnableAsyncUploadsByURL'=> false, 'EnableChunkedUploads'=> false, 'UploadMaintenance'=> false, 'IllegalFileChars'=> ':\\/\\\\', 'DeletedDirectory'=> false, 'ImgAuthDetails'=> false, 'ImgAuthUrlPathMap'=>[], 'LocalFileRepo'=>['class'=> 'MediaWiki\\FileRepo\\LocalRepo', 'name'=> 'local', 'directory'=> null, 'scriptDirUrl'=> null, 'favicon'=> null, 'url'=> null, 'hashLevels'=> null, 'thumbScriptUrl'=> null, 'transformVia404'=> null, 'deletedDir'=> null, 'deletedHashLevels'=> null, 'updateCompatibleMetadata'=> null, 'reserializeMetadata'=> null,], 'ForeignFileRepos'=>[], 'UseInstantCommons'=> false, 'UseSharedUploads'=> false, 'SharedUploadDirectory'=> null, 'SharedUploadPath'=> null, 'HashedSharedUploadDirectory'=> true, 'RepositoryBaseUrl'=> 'https:'FetchCommonsDescriptions'=> false, 'SharedUploadDBname'=> false, 'SharedUploadDBprefix'=> '', 'CacheSharedUploads'=> true, 'ForeignUploadTargets'=>['local',], 'UploadDialog'=>['fields'=>['description'=> true, 'date'=> false, 'categories'=> false,], 'licensemessages'=>['local'=> 'generic-local', 'foreign'=> 'generic-foreign',], 'comment'=>['local'=> '', 'foreign'=> '',], 'format'=>['filepage'=> ' $DESCRIPTION', 'description'=> ' $TEXT', 'ownwork'=> '', 'license'=> '', 'uncategorized'=> '',],], 'FileBackends'=>[], 'LockManagers'=>[], 'DefaultLockManager'=> null, 'ShowEXIF'=> null, 'UpdateCompatibleMetadata'=> false, 'AllowCopyUploads'=> false, 'CopyUploadsDomains'=>[], 'CopyUploadsFromSpecialUpload'=> false, 'CopyUploadProxy'=> false, 'CopyUploadTimeout'=> false, 'CopyUploadAllowOnWikiDomainConfig'=> false, 'MaxUploadSize'=> 104857600, 'MinUploadChunkSize'=> 1024, 'UploadNavigationUrl'=> false, 'UploadMissingFileUrl'=> false, 'ThumbnailScriptPath'=> false, 'SharedThumbnailScriptPath'=> false, 'HashedUploadDirectory'=> true, 'CSPUploadEntryPoint'=> true, 'FileExtensions'=>['png', 'gif', 'jpg', 'jpeg', 'webp',], 'ProhibitedFileExtensions'=>['html', 'htm', 'js', 'jsb', 'mhtml', 'mht', 'xhtml', 'xht', 'php', 'phtml', 'php3', 'php4', 'php5', 'phps', 'phar', 'shtml', 'jhtml', 'pl', 'py', 'cgi', 'exe', 'scr', 'dll', 'msi', 'vbs', 'bat', 'com', 'pif', 'cmd', 'vxd', 'cpl', 'xml',], 'MimeTypeExclusions'=>['text/html', 'application/javascript', 'text/javascript', 'text/x-javascript', 'application/x-shellscript', 'application/x-php', 'text/x-php', 'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh', 'text/scriptlet', 'application/x-msdownload', 'application/x-msmetafile', 'application/java', 'application/xml', 'text/xml',], 'CheckFileExtensions'=> true, 'StrictFileExtensions'=> true, 'DisableUploadScriptChecks'=> false, 'UploadSizeWarning'=> false, 'TrustedMediaFormats'=>['BITMAP', 'AUDIO', 'VIDEO', 'image/svg+xml', 'application/pdf',], 'MediaHandlers'=>[], 'NativeImageLazyLoading'=> false, 'ParserTestMediaHandlers'=>['image/jpeg'=> 'MockBitmapHandler', 'image/png'=> 'MockBitmapHandler', 'image/gif'=> 'MockBitmapHandler', 'image/tiff'=> 'MockBitmapHandler', 'image/webp'=> 'MockBitmapHandler', 'image/x-ms-bmp'=> 'MockBitmapHandler', 'image/x-bmp'=> 'MockBitmapHandler', 'image/x-xcf'=> 'MockBitmapHandler', 'image/svg+xml'=> 'MockSvgHandler', 'image/vnd.djvu'=> 'MockDjVuHandler',], 'UseImageResize'=> true, 'UseImageMagick'=> false, 'ImageMagickConvertCommand'=> '/usr/bin/convert', 'MaxInterlacingAreas'=>[], 'SharpenParameter'=> '0x0.4', 'SharpenReductionThreshold'=> 0.85, 'ImageMagickTempDir'=> false, 'CustomConvertCommand'=> false, 'JpegTran'=> '/usr/bin/jpegtran', 'JpegPixelFormat'=> 'yuv420', 'JpegQuality'=> 80, 'Exiv2Command'=> '/usr/bin/exiv2', 'Exiftool'=> '/usr/bin/exiftool', 'SVGConverters'=>['ImageMagick'=> ' $path/convert -background "#ffffff00" -thumbnail $widthx$height\\! $input PNG:$output', 'inkscape'=> ' $path/inkscape -w $width -o $output $input', 'batik'=> 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input', 'rsvg'=> ' $path/rsvg-convert -w $width -h $height -o $output $input', 'ImagickExt'=>['SvgHandler::rasterizeImagickExt',],], 'SVGConverter'=> 'ImageMagick', 'SVGConverterPath'=> '', 'SVGMaxSize'=> 5120, 'SVGMetadataCutoff'=> 5242880, 'SVGNativeRendering'=> true, 'SVGNativeRenderingSizeLimit'=> 51200, 'MediaInTargetLanguage'=> true, 'MaxImageArea'=> 12500000, 'MaxAnimatedGifArea'=> 12500000, 'TiffThumbnailType'=>[], 'ThumbnailEpoch'=> '20030516000000', 'AttemptFailureEpoch'=> 1, 'IgnoreImageErrors'=> false, 'GenerateThumbnailOnParse'=> true, 'ShowArchiveThumbnails'=> true, 'EnableAutoRotation'=> null, 'Antivirus'=> null, 'AntivirusSetup'=>['clamav'=>['command'=> 'clamscan --no-summary ', 'codemap'=>[0=> 0, 1=> 1, 52=> -1, ' *'=> false,], 'messagepattern'=> '/.*?:(.*)/sim',],], 'AntivirusRequired'=> true, 'VerifyMimeType'=> true, 'MimeTypeFile'=> 'internal', 'MimeInfoFile'=> 'internal', 'MimeDetectorCommand'=> null, 'TrivialMimeDetection'=> false, 'XMLMimeTypes'=>['http:'svg'=> 'image/svg+xml', 'http:'http:'html'=> 'text/html',], 'ImageLimits'=>[[320, 240,], [640, 480,], [800, 600,], [1024, 768,], [1280, 1024,], [2560, 2048,],], 'ThumbLimits'=>[120, 150, 180, 200, 220, 250, 300, 400,], 'ThumbnailNamespaces'=>[6,], 'ThumbnailSteps'=> null, 'ThumbnailBuckets'=> null, 'ThumbnailMinimumBucketDistance'=> 50, 'UploadThumbnailRenderMap'=>[], 'UploadThumbnailRenderMethod'=> 'jobqueue', 'UploadThumbnailRenderHttpCustomHost'=> false, 'UploadThumbnailRenderHttpCustomDomain'=> false, 'UseTinyRGBForJPGThumbnails'=> false, 'GalleryOptions'=>[], 'ThumbUpright'=> 0.75, 'DirectoryMode'=> 511, 'ResponsiveImages'=> true, 'ImagePreconnect'=> false, 'TrackMediaRequestProvenance'=> false, 'DjvuUseBoxedCommand'=> false, 'DjvuDump'=> null, 'DjvuRenderer'=> null, 'DjvuTxt'=> null, 'DjvuPostProcessor'=> 'pnmtojpeg', 'DjvuOutputExtension'=> 'jpg', 'EmergencyContact'=> false, 'RestTermsOfServiceUrl'=> null, 'PasswordSender'=> false, 'NoReplyAddress'=> false, 'EnableEmail'=> true, 'EnableUserEmail'=> true, 'UserEmailUseReplyTo'=> true, 'PasswordReminderResendTime'=> 24, 'NewPasswordExpiry'=> 604800, 'UserEmailConfirmationTokenExpiry'=> 604800, 'PasswordExpirationDays'=> false, 'PasswordExpireGrace'=> 604800, 'SMTP'=> false, 'AdditionalMailParams'=> null, 'AllowHTMLEmail'=> false, 'EnotifFromEditor'=> false, 'EmailAuthentication'=> true, 'EmailConfirmationBanner'=> false, 'EnotifWatchlist'=> false, 'EnotifUserTalk'=> false, 'EnotifRevealEditorAddress'=> false, 'EnotifMinorEdits'=> true, 'EnotifUseRealName'=> false, 'UsersNotifiedOnAllChanges'=>[], 'DBname'=> 'my_wiki', 'DBmwschema'=> null, 'DBprefix'=> '', 'DBserver'=> 'localhost', 'DBport'=> 5432, 'DBuser'=> 'wikiuser', 'DBpassword'=> '', 'DBtype'=> 'mysql', 'DBssl'=> false, 'DBcompress'=> false, 'DBStrictWarnings'=> false, 'DBadminuser'=> null, 'DBadminpassword'=> null, 'SearchType'=> null, 'SearchTypeAlternatives'=> null, 'DBTableOptions'=> 'ENGINE=InnoDB, DEFAULT CHARSET=binary', 'SQLMode'=> '', 'SQLiteDataDir'=> '', 'SharedDB'=> null, 'SharedPrefix'=> false, 'SharedTables'=>['user', 'user_properties', 'user_autocreate_serial',], 'SharedSchema'=> false, 'DBservers'=> false, 'LBFactoryConf'=>['class'=> 'Wikimedia\\Rdbms\\LBFactorySimple',], 'DataCenterUpdateStickTTL'=> 10, 'DBerrorLog'=> false, 'DBerrorLogTZ'=> false, 'LocalDatabases'=>[], 'DatabaseReplicaLagWarning'=> 10, 'DatabaseReplicaLagCritical'=> 30, 'MaxExecutionTimeForExpensiveQueries'=> 0, 'VirtualDomainsMapping'=>[], 'FileSchemaMigrationStage'=> 3, 'ExternalLinksDomainGaps'=>[], 'ContentHandlers'=>['wikitext'=>['class'=> 'MediaWiki\\Content\\WikitextContentHandler', 'services'=>['TitleFactory', 'ParserFactory', 'GlobalIdGenerator', 'LanguageNameUtils', 'LinkRenderer', 'MagicWordFactory', 'ParsoidParserFactory',],], 'javascript'=>['class'=> 'MediaWiki\\Content\\JavaScriptContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup', 'CodeHighlighter',],], 'json'=>['class'=> 'MediaWiki\\Content\\JsonContentHandler', 'services'=>['ParsoidParserFactory', 'TitleFactory',],], 'css'=>['class'=> 'MediaWiki\\Content\\CssContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup', 'CodeHighlighter',],], 'vue'=>['class'=> 'MediaWiki\\Content\\VueContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'CodeHighlighter',],], 'text'=> 'MediaWiki\\Content\\TextContentHandler', 'unknown'=> 'MediaWiki\\Content\\FallbackContentHandler',], 'NamespaceContentModels'=>[], 'TextModelsToParse'=>['wikitext', 'javascript', 'css',], 'CompressRevisions'=> false, 'ExternalStores'=>[], 'ExternalServers'=>[], 'DefaultExternalStore'=> false, 'RevisionCacheExpiry'=> 604800, 'PageLanguageUseDB'=> false, 'DiffEngine'=> null, 'ExternalDiffEngine'=> false, 'Wikidiff2Options'=>[], 'RequestTimeLimit'=> null, 'TransactionalTimeLimit'=> 120, 'CriticalSectionTimeLimit'=> 180.0, 'MiserMode'=> false, 'DisableQueryPages'=> false, 'QueryCacheLimit'=> 1000, 'WantedPagesThreshold'=> 1, 'AllowSlowParserFunctions'=> false, 'AllowSchemaUpdates'=> true, 'MaxArticleSize'=> 2048, 'MemoryLimit'=> '50M', 'PoolCounterConf'=> null, 'PoolCountClientConf'=>['servers'=>['127.0.0.1',], 'timeout'=> 0.1,], 'MaxUserDBWriteDuration'=> false, 'MaxJobDBWriteDuration'=> false, 'LinkHolderBatchSize'=> 1000, 'MaximumMovedPages'=> 100, 'ForceDeferredUpdatesPreSend'=> false, 'MultiShardSiteStats'=> false, 'CacheDirectory'=> false, 'MainCacheType'=> 0, 'MessageCacheType'=> -1, 'ParserCacheType'=> -1, 'SessionCacheType'=> -1, 'AnonSessionCacheType'=> false, 'LanguageConverterCacheType'=> -1, 'ObjectCaches'=>[0=>['class'=> 'Wikimedia\\ObjectCache\\EmptyBagOStuff', 'reportDupes'=> false,], 1=>['class'=> 'MediaWiki\\ObjectCache\\SqlBagOStuff', 'loggroup'=> 'SQLBagOStuff',], 'memcached-php'=>['class'=> 'Wikimedia\\ObjectCache\\MemcachedPhpBagOStuff', 'loggroup'=> 'memcached',], 'memcached-pecl'=>['class'=> 'Wikimedia\\ObjectCache\\MemcachedPeclBagOStuff', 'loggroup'=> 'memcached',], 'hash'=>['class'=> 'Wikimedia\\ObjectCache\\HashBagOStuff', 'reportDupes'=> false,], 'apc'=>['class'=> 'Wikimedia\\ObjectCache\\APCUBagOStuff', 'reportDupes'=> false,], 'apcu'=>['class'=> 'Wikimedia\\ObjectCache\\APCUBagOStuff', 'reportDupes'=> false,],], 'WANObjectCache'=>[], 'MicroStashType'=> -1, 'MainStash'=> 1, 'ParsoidCacheConfig'=>['StashType'=> null, 'StashDuration'=> 86400, 'WarmParsoidParserCache'=> false,], 'ParsoidSelectiveUpdateSampleRate'=> 0, 'ParserCacheFilterConfig'=>['pcache'=>['default'=>['minCpuTime'=> 0,],], 'postproc-pcache'=>['default'=>['minCpuTime'=> 9223372036854775807,],], 'parsoid-pcache'=>['default'=>['minCpuTime'=> 0,],], 'postproc-parsoid-pcache'=>['default'=>['minCpuTime'=> 0,],],], 'ChronologyProtectorSecret'=> '', 'ParserCacheExpireTime'=> 86400, 'ParserCacheAsyncExpireTime'=> 60, 'ParserCacheAsyncRefreshJobs'=> true, 'OldRevisionParserCacheExpireTime'=> 3600, 'ObjectCacheSessionExpiry'=> 3600, 'SuspiciousIpExpiry'=> false, 'SessionPbkdf2Iterations'=> 10001, 'UseSessionCookieJwt'=> false, 'JwtSessionCookieIssuer'=> null, 'MemCachedServers'=>['127.0.0.1:11211',], 'MemCachedPersistent'=> false, 'MemCachedTimeout'=> 500000, 'UseLocalMessageCache'=> false, 'AdaptiveMessageCache'=> false, 'LocalisationCacheConf'=>['class'=> 'MediaWiki\\Language\\LocalisationCache', 'store'=> 'detect', 'storeClass'=> false, 'storeDirectory'=> false, 'storeServer'=>[], 'forceRecache'=> false, 'manualRecache'=> false,], 'CachePages'=> true, 'CacheEpoch'=> '20030516000000', 'GitInfoCacheDirectory'=> false, 'UseFileCache'=> false, 'FileCacheDepth'=> 2, 'RenderHashAppend'=> '', 'EnableSidebarCache'=> false, 'SidebarCacheExpiry'=> 86400, 'UseGzip'=> false, 'InvalidateCacheOnLocalSettingsChange'=> true, 'ExtensionInfoMTime'=> false, 'EnableRemoteBagOStuffTests'=> false, 'UseCdn'=> false, 'VaryOnXFP'=> false, 'InternalServer'=> false, 'CdnMaxAge'=> 18000, 'CdnMaxageLagged'=> 30, 'CdnMaxageStale'=> 10, 'CdnReboundPurgeDelay'=> 0, 'CdnMaxageSubstitute'=> 60, 'ForcedRawSMaxage'=> 300, 'CdnServers'=>[], 'CdnServersNoPurge'=>[], 'HTCPRouting'=>[], 'HTCPMulticastTTL'=> 1, 'UsePrivateIPs'=> false, 'CdnMatchParameterOrder'=> true, 'LanguageCode'=> 'en', 'GrammarForms'=>[], 'InterwikiMagic'=> true, 'HideInterlanguageLinks'=> false, 'ExtraInterlanguageLinkPrefixes'=>[], 'InterlanguageLinkCodeMap'=>[], 'ExtraLanguageNames'=>[], 'ExtraLanguageCodes'=>['bh'=> 'bho', 'no'=> 'nb', 'simple'=> 'en',], 'DummyLanguageCodes'=>[], 'AllUnicodeFixes'=> false, 'LegacyEncoding'=> false, 'AmericanDates'=> false, 'TranslateNumerals'=> true, 'UseDatabaseMessages'=> true, 'MaxMsgCacheEntrySize'=> 10000, 'DisableLangConversion'=> false, 'DisableTitleConversion'=> false, 'DefaultLanguageVariant'=> false, 'UsePigLatinVariant'=> false, 'DisabledVariants'=>[], 'VariantArticlePath'=> false, 'UseXssLanguage'=> false, 'LoginLanguageSelector'=> false, 'ForceUIMsgAsContentMsg'=>[], 'RawHtmlMessages'=>[], 'Localtimezone'=> null, 'LocalTZoffset'=> null, 'OverrideUcfirstCharacters'=>[], 'MimeType'=> 'text/html', 'Html5Version'=> null, 'EditSubmitButtonLabelPublish'=> false, 'XhtmlNamespaces'=>[], 'SiteNotice'=> '', 'BrowserFormatDetection'=> 'telephone=no', 'SkinMetaTags'=>[], 'DefaultSkin'=> 'vector-2022', 'FallbackSkin'=> 'fallback', 'SkipSkins'=>[], 'DisableOutputCompression'=> false, 'FragmentMode'=>['html5', 'legacy',], 'ExternalInterwikiFragmentMode'=> 'legacy', 'FooterIcons'=>['copyright'=>['copyright'=>[],], 'poweredby'=>['mediawiki'=>['src'=> null, 'url'=> 'https:'alt'=> 'Powered by MediaWiki', 'lang'=> 'en',],],], 'EnableSectionShare'=> false, 'UseCombinedLoginLink'=> false, 'Edititis'=> false, 'Send404Code'=> true, 'ShowRollbackEditCount'=> 10, 'EnableCanonicalServerLink'=> false, 'InterwikiLogoOverride'=>[], 'ResourceModules'=>[], 'ResourceModuleSkinStyles'=>[], 'ResourceLoaderSources'=>[], 'ResourceBasePath'=> null, 'ResourceLoaderMaxage'=>[], 'ResourceLoaderDebug'=> false, 'ResourceLoaderMaxQueryLength'=> false, 'ResourceLoaderValidateJS'=> true, 'ResourceLoaderEnableJSProfiler'=> false, 'ResourceLoaderStorageEnabled'=> true, 'ResourceLoaderStorageVersion'=> 1, 'ResourceLoaderEnableSourceMapLinks'=> true, 'AllowSiteCSSOnRestrictedPages'=> false, 'VueDevelopmentMode'=> false, 'CodexDevelopmentDir'=> null, 'MetaNamespace'=> false, 'MetaNamespaceTalk'=> false, 'CanonicalNamespaceNames'=>[-2=> 'Media', -1=> 'Special', 0=> '', 1=> 'Talk', 2=> 'User', 3=> 'User_talk', 4=> 'Project', 5=> 'Project_talk', 6=> 'File', 7=> 'File_talk', 8=> 'MediaWiki', 9=> 'MediaWiki_talk', 10=> 'Template', 11=> 'Template_talk', 12=> 'Help', 13=> 'Help_talk', 14=> 'Category', 15=> 'Category_talk',], 'ExtraNamespaces'=>[], 'ExtraGenderNamespaces'=>[], 'NamespaceAliases'=>[], 'LegalTitleChars'=> ' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+', 'CapitalLinks' => true, 'CapitalLinkOverrides' => [ ], 'NamespacesWithSubpages' => [ 1 => true, 2 => true, 3 => true, 4 => true, 5 => true, 7 => true, 8 => true, 9 => true, 10 => true, 11 => true, 12 => true, 13 => true, 15 => true, ], 'NamespacesWithoutAutoSummaries' => [ ], 'ContentNamespaces' => [ 0, ], 'ShortPagesNamespaceExclusions' => [ ], 'ExtraSignatureNamespaces' => [ ], 'InvalidRedirectTargets' => [ 'Filepath', 'Mypage', 'Mytalk', 'Redirect', 'Mylog', ], 'DisableHardRedirects' => false, 'FixDoubleRedirects' => false, 'LocalInterwikis' => [ ], 'InterwikiExpiry' => 10800, 'InterwikiCache' => false, 'InterwikiScopes' => 3, 'InterwikiFallbackSite' => 'wiki', 'RedirectSources' => false, 'SiteTypes' => [ 'mediawiki' => 'MediaWiki\\Site\\MediaWikiSite', ], 'MaxTocLevel' => 999, 'MaxPPNodeCount' => 1000000, 'MaxTemplateDepth' => 100, 'MaxPPExpandDepth' => 100, 'UrlProtocols' => [ 'bitcoin:', 'ftp: 'ftps: 'geo:', 'git: 'gopher: 'http: 'https: 'irc: 'ircs: 'magnet:', 'mailto:', 'matrix:', 'mms: 'news:', 'nntp: 'redis: 'sftp: 'sip:', 'sips:', 'sms:', 'ssh: 'svn: 'tel:', 'telnet: 'urn:', 'wikipedia: 'worldwind: 'xmpp:', ' ], 'CleanSignatures' => true, 'AllowExternalImages' => false, 'AllowExternalImagesFrom' => '', 'EnableImageWhitelist' => false, 'TidyConfig' => [ ], 'ParsoidSettings' => [ 'useSelser' => true, ], 'ParsoidExperimentalParserFunctionOutput' => false, 'RawHtml' => false, 'ExternalLinkTarget' => false, 'NoFollowLinks' => true, 'NoFollowNsExceptions' => [ ], 'NoFollowDomainExceptions' => [ 'mediawiki.org', ], 'RegisterInternalExternals' => false, 'ExternalLinksIgnoreDomains' => [ ], 'AllowDisplayTitle' => true, 'RestrictDisplayTitle' => true, 'ExpensiveParserFunctionLimit' => 100, 'PreprocessorCacheThreshold' => 1000, 'EnableScaryTranscluding' => false, 'TranscludeCacheExpiry' => 3600, 'EnableMagicLinks' => [ 'ISBN' => false, 'PMID' => false, 'RFC' => false, ], 'ParserEnableUserLanguage' => false, 'ArticleCountMethod' => 'link', 'ActiveUserDays' => 30, 'LearnerEdits' => 10, 'LearnerMemberSince' => 4, 'ExperiencedUserEdits' => 500, 'ExperiencedUserMemberSince' => 30, 'ManualRevertSearchRadius' => 15, 'RevertedTagMaxDepth' => 15, 'CentralIdLookupProviders' => [ 'local' => [ 'class' => 'MediaWiki\\User\\CentralId\\LocalIdLookup', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', 'HideUserUtils', ], ], ], 'CentralIdLookupProvider' => 'local', 'UserRegistrationProviders' => [ 'local' => [ 'class' => 'MediaWiki\\User\\Registration\\LocalUserRegistrationProvider', 'services' => [ 'ConnectionProvider', ], ], ], 'PasswordPolicy' => [ 'policies' => [ 'bureaucrat' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'sysop' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'interface-admin' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'bot' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'default' => [ 'MinimalPasswordLength' => [ 'value' => 8, 'suggestChangeOnLogin' => true, ], 'PasswordCannotBeSubstringInUsername' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], 'PasswordCannotMatchDefaults' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], 'MaximalPasswordLength' => [ 'value' => 4096, 'suggestChangeOnLogin' => true, ], 'PasswordNotInCommonList' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], ], ], 'checks' => [ 'MinimalPasswordLength' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMinimalPasswordLength', ], 'MinimumPasswordLengthToLogin' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMinimumPasswordLengthToLogin', ], 'PasswordCannotBeSubstringInUsername' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordCannotBeSubstringInUsername', ], 'PasswordCannotMatchDefaults' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordCannotMatchDefaults', ], 'MaximalPasswordLength' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMaximalPasswordLength', ], 'PasswordNotInCommonList' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordNotInCommonList', ], ], ], 'AuthManagerConfig' => null, 'AuthManagerAutoConfig' => [ 'preauth' => [ 'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider', 'sort' => 0, ], 'MediaWiki\\Auth\\PreviouslyRenamedAccountPreAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\PreviouslyRenamedAccountPreAuthenticationProvider', 'services' => [ 'ConnectionProvider', 'UserFactory', ], 'sort' => 0, ], ], 'primaryauth' => [ 'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', 'UserOptionsLookup', ], 'args' => [ [ 'authoritative' => false, ], ], 'sort' => 0, ], 'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', ], 'args' => [ [ 'authoritative' => true, ], ], 'sort' => 100, ], ], 'secondaryauth' => [ 'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider', 'sort' => 0, ], 'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider', 'sort' => 100, ], 'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', ], 'sort' => 200, ], ], ], 'RememberMe' => 'choose', 'ReauthenticateTime' => [ 'default' => 3600, ], 'ChangeCredentialsBlacklist' => [ 'MediaWiki\\Auth\\TemporaryPasswordAuthenticationRequest', ], 'RemoveCredentialsBlacklist' => [ 'MediaWiki\\Auth\\PasswordAuthenticationRequest', ], 'InvalidPasswordReset' => true, 'PasswordDefault' => 'pbkdf2', 'PasswordConfig' => [ 'A' => [ 'class' => 'MediaWiki\\Password\\MWOldPassword', ], 'B' => [ 'class' => 'MediaWiki\\Password\\MWSaltedPassword', ], 'pbkdf2-legacyA' => [ 'class' => 'MediaWiki\\Password\\LayeredParameterizedPassword', 'types' => [ 'A', 'pbkdf2', ], ], 'pbkdf2-legacyB' => [ 'class' => 'MediaWiki\\Password\\LayeredParameterizedPassword', 'types' => [ 'B', 'pbkdf2', ], ], 'bcrypt' => [ 'class' => 'MediaWiki\\Password\\BcryptPassword', 'cost' => 9, ], 'pbkdf2' => [ 'class' => 'MediaWiki\\Password\\Pbkdf2PasswordUsingOpenSSL', 'algo' => 'sha512', 'cost' => '30000', 'length' => '64', ], 'argon2' => [ 'class' => 'MediaWiki\\Password\\Argon2Password', 'algo' => 'auto', ], ], 'PasswordResetRoutes' => [ 'username' => true, 'email' => true, ], 'MaxSigChars' => 255, 'SignatureValidation' => 'warning', 'SignatureAllowedLintErrors' => [ 'obsolete-tag', ], 'MaxNameChars' => 255, 'ReservedUsernames' => [ 'MediaWiki default', 'Conversion script', 'Maintenance script', 'Template namespace initialisation script', 'ScriptImporter', 'Delete page script', 'Move page script', 'Command line script', 'Unknown user', 'msg:double-redirect-fixer', 'msg:usermessage-editor', 'msg:proxyblocker', 'msg:sorbs', 'msg:spambot_username', 'msg:autochange-username', ], 'DefaultUserOptions' => [ 'ccmeonemails' => 0, 'date' => 'default', 'diffonly' => 0, 'diff-type' => 'table', 'disablemail' => 0, 'editfont' => 'monospace', 'editondblclick' => 0, 'editrecovery' => 0, 'editsectiononrightclick' => 0, 'email-allow-new-users' => 1, 'enotifminoredits' => 0, 'enotifrevealaddr' => 0, 'enotifusertalkpages' => 1, 'enotifwatchlistpages' => 1, 'extendwatchlist' => 1, 'fancysig' => 0, 'forceeditsummary' => 0, 'forcesafemode' => 0, 'gender' => 'unknown', 'hidecategorization' => 1, 'hideminor' => 0, 'hidepatrolled' => 0, 'imagesize' => 2, 'minordefault' => 0, 'newpageshidepatrolled' => 0, 'nickname' => '', 'norollbackdiff' => 0, 'prefershttps' => 1, 'previewonfirst' => 0, 'previewontop' => 1, 'pst-cssjs' => 1, 'rcdays' => 7, 'rcenhancedfilters-disable' => 0, 'rclimit' => 50, 'requireemail' => 0, 'search-match-redirect' => true, 'search-special-page' => 'Search', 'search-thumbnail-extra-namespaces' => true, 'searchlimit' => 20, 'showhiddencats' => 0, 'shownumberswatching' => 1, 'showrollbackconfirmation' => 0, 'skin' => false, 'skin-responsive' => 1, 'thumbsize' => 5, 'underline' => 2, 'useeditwarning' => 1, 'uselivepreview' => 0, 'usenewrc' => 1, 'watchcreations' => 1, 'watchcreations-expiry' => 'infinite', 'watchdefault' => 1, 'watchdefault-expiry' => 'infinite', 'watchdeletion' => 0, 'watchlistdays' => 7, 'watchlisthideanons' => 0, 'watchlisthidebots' => 0, 'watchlisthidecategorization' => 1, 'watchlisthideliu' => 0, 'watchlisthideminor' => 0, 'watchlisthideown' => 0, 'watchlisthidepatrolled' => 0, 'watchlistreloadautomatically' => 0, 'watchlistunwatchlinks' => 0, 'watchmoves' => 0, 'watchrollback' => 0, 'watchuploads' => 1, 'watchrollback-expiry' => 'infinite', 'watchstar-expiry' => 'infinite', 'wlenhancedfilters-disable' => 0, 'wllimit' => 250, ], 'ConditionalUserOptions' => [ ], 'HiddenPrefs' => [ ], 'UserJsPrefLimit' => 100, 'InvalidUsernameCharacters' => '@:>=', 'UserrightsInterwikiDelimiter' => '@', 'SecureLogin' => false, 'AuthenticationTokenVersion' => null, 'SessionProviders' => [ 'MediaWiki\\Session\\CookieSessionProvider' => [ 'class' => 'MediaWiki\\Session\\CookieSessionProvider', 'args' => [ [ 'priority' => 30, ], ], 'services' => [ 'JwtCodec', 'UrlUtils', ], ], 'MediaWiki\\Session\\BotPasswordSessionProvider' => [ 'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider', 'args' => [ [ 'priority' => 75, ], ], 'services' => [ 'GrantsInfo', ], ], ], 'AutoCreateTempUser' => [ 'known' => false, 'enabled' => false, 'actions' => [ 'edit', ], 'genPattern' => '~$1', 'matchPattern' => null, 'reservedPattern' => '~$1', 'serialProvider' => [ 'type' => 'local', 'useYear' => true, ], 'serialMapping' => [ 'type' => 'readable-numeric', ], 'expireAfterDays' => 90, 'notifyBeforeExpirationDays' => 10, ], 'AutoblockExemptions' => [ ], 'AutoblockExpiry' => 86400, 'BlockAllowsUTEdit' => true, 'BlockCIDRLimit' => [ 'IPv4' => 16, 'IPv6' => 19, ], 'BlockDisablesLogin' => false, 'EnableMultiBlocks' => false, 'WhitelistRead' => false, 'WhitelistReadRegexp' => false, 'EmailConfirmToEdit' => false, 'HideIdentifiableRedirects' => true, 'GroupPermissions' => [ '*' => [ 'createaccount' => true, 'autocreateaccount' => true, 'read' => true, 'edit' => true, 'createpage' => true, 'createtalk' => true, 'viewmyprivateinfo' => true, 'editmyprivateinfo' => true, 'editmyoptions' => true, ], 'user' => [ 'move' => true, 'move-subpages' => true, 'move-rootuserpages' => true, 'move-categorypages' => true, 'movefile' => true, 'read' => true, 'edit' => true, 'createpage' => true, 'createtalk' => true, 'upload' => true, 'reupload' => true, 'reupload-shared' => true, 'minoredit' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, 'editmyuserjsredirect' => true, 'sendemail' => true, 'applychangetags' => true, 'changetags' => true, 'viewmywatchlist' => true, 'editmywatchlist' => true, 'createwithcontentmodel' => true, 'logout' => true, ], 'autoconfirmed' => [ 'autoconfirmed' => true, 'editsemiprotected' => true, ], 'bot' => [ 'bot' => true, 'autoconfirmed' => true, 'editsemiprotected' => true, 'nominornewtalk' => true, 'autopatrol' => true, 'suppressredirect' => true, 'apihighlimits' => true, ], 'sysop' => [ 'block' => true, 'createaccount' => true, 'createpreviouslyrenamedaccount' => true, 'delete' => true, 'bigdelete' => true, 'deletedhistory' => true, 'deletedtext' => true, 'undelete' => true, 'editcontentmodel' => true, 'editinterface' => true, 'editsitejson' => true, 'edituserjson' => true, 'import' => true, 'importupload' => true, 'move' => true, 'move-subpages' => true, 'move-rootuserpages' => true, 'move-categorypages' => true, 'patrol' => true, 'autopatrol' => true, 'protect' => true, 'editprotected' => true, 'rollback' => true, 'upload' => true, 'reupload' => true, 'reupload-shared' => true, 'unwatchedpages' => true, 'autoconfirmed' => true, 'editsemiprotected' => true, 'ipblock-exempt' => true, 'blockemail' => true, 'markbotedits' => true, 'apihighlimits' => true, 'browsearchive' => true, 'noratelimit' => true, 'movefile' => true, 'unblockself' => true, 'suppressredirect' => true, 'mergehistory' => true, 'managechangetags' => true, 'deletechangetags' => true, ], 'interface-admin' => [ 'editinterface' => true, 'editsitecss' => true, 'editsitejson' => true, 'editsitejs' => true, 'editusercss' => true, 'edituserjson' => true, 'edituserjs' => true, ], 'bureaucrat' => [ 'userrights' => true, 'noratelimit' => true, 'renameuser' => true, ], 'suppress' => [ 'hideuser' => true, 'suppressrevision' => true, 'viewsuppressed' => true, 'suppressionlog' => true, 'deleterevision' => true, 'deletelogentry' => true, ], ], 'PrivilegedGroups' => [ 'bureaucrat', 'interface-admin', 'suppress', 'sysop', ], 'RevokePermissions' => [ ], 'GroupInheritsPermissions' => [ ], 'ImplicitGroups' => [ '*', 'user', 'autoconfirmed', ], 'GroupsAddToSelf' => [ ], 'GroupsRemoveFromSelf' => [ ], 'RestrictedGroups' => [ ], 'UserRequirementsPrivateConditions' => [ ], 'RestrictionTypes' => [ 'create', 'edit', 'move', 'upload', ], 'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop', ], 'CascadingRestrictionLevels' => [ 'sysop', ], 'SemiprotectedRestrictionLevels' => [ 'autoconfirmed', ], 'NamespaceProtection' => [ ], 'RestrictUserPageEditing' => false, 'NonincludableNamespaces' => [ ], 'AutoConfirmAge' => 0, 'AutoConfirmCount' => 0, 'Autopromote' => [ 'autoconfirmed' => [ '&', [ 1, null, ], [ 2, null, ], ], ], 'AutopromoteOnce' => [ 'onEdit' => [ ], ], 'AutopromoteOnceLogInRC' => true, 'AutopromoteOnceRCExcludedGroups' => [ ], 'AddGroups' => [ ], 'RemoveGroups' => [ ], 'AvailableRights' => [ ], 'ImplicitRights' => [ ], 'DeleteRevisionsLimit' => 0, 'DeleteRevisionsBatchSize' => 1000, 'HideUserContribLimit' => 1000, 'AccountCreationThrottle' => [ [ 'count' => 0, 'seconds' => 86400, ], ], 'TempAccountCreationThrottle' => [ [ 'count' => 1, 'seconds' => 600, ], [ 'count' => 6, 'seconds' => 86400, ], ], 'TempAccountNameAcquisitionThrottle' => [ [ 'count' => 60, 'seconds' => 86400, ], ], 'SpamRegex' => [ ], 'SummarySpamRegex' => [ ], 'EnableDnsBlacklist' => false, 'DnsBlacklistUrls' => [ ], 'ProxyList' => [ ], 'ProxyWhitelist' => [ ], 'SoftBlockRanges' => [ ], 'ApplyIpBlocksToXff' => false, 'RateLimits' => [ 'edit' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], 'user' => [ 90, 60, ], ], 'move' => [ 'newbie' => [ 2, 120, ], 'user' => [ 8, 60, ], ], 'upload' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], ], 'rollback' => [ 'user' => [ 10, 60, ], 'newbie' => [ 5, 120, ], ], 'mailpassword' => [ 'ip' => [ 5, 3600, ], ], 'sendemail' => [ 'ip' => [ 5, 86400, ], 'newbie' => [ 5, 86400, ], 'user' => [ 20, 86400, ], ], 'changeemail' => [ 'ip-all' => [ 10, 3600, ], 'user' => [ 4, 86400, ], ], 'confirmemail' => [ 'ip-all' => [ 10, 3600, ], 'user' => [ 4, 86400, ], ], 'purge' => [ 'ip' => [ 30, 60, ], 'user' => [ 30, 60, ], ], 'linkpurge' => [ 'ip' => [ 30, 60, ], 'user' => [ 30, 60, ], ], 'renderfile' => [ 'ip' => [ 700, 30, ], 'user' => [ 700, 30, ], ], 'renderfile-nonstandard' => [ 'ip' => [ 70, 30, ], 'user' => [ 70, 30, ], ], 'stashedit' => [ 'ip' => [ 30, 60, ], 'newbie' => [ 30, 60, ], ], 'stashbasehtml' => [ 'ip' => [ 5, 60, ], 'newbie' => [ 5, 60, ], ], 'changetags' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], ], 'editcontentmodel' => [ 'newbie' => [ 2, 120, ], 'user' => [ 8, 60, ], ], ], 'RateLimitsExcludedIPs' => [ ], 'PutIPinRC' => true, 'QueryPageDefaultLimit' => 50, 'ExternalQuerySources' => [ ], 'PasswordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300, ], [ 'count' => 150, 'seconds' => 172800, ], ], 'GrantPermissions' => [ 'basic' => [ 'autocreateaccount' => true, 'autoconfirmed' => true, 'autopatrol' => true, 'editsemiprotected' => true, 'ipblock-exempt' => true, 'nominornewtalk' => true, 'patrolmarks' => true, 'read' => true, 'unwatchedpages' => true, ], 'highvolume' => [ 'bot' => true, 'apihighlimits' => true, 'noratelimit' => true, 'markbotedits' => true, ], 'import' => [ 'import' => true, 'importupload' => true, ], 'editpage' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'pagelang' => true, ], 'editprotected' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editprotected' => true, ], 'editmycssjs' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, ], 'editmyoptions' => [ 'editmyoptions' => true, 'editmyuserjson' => true, ], 'editinterface' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, ], 'editsiteconfig' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, 'editusercss' => true, 'edituserjs' => true, 'editsitecss' => true, 'editsitejs' => true, ], 'createeditmovepage' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'createpage' => true, 'createtalk' => true, 'delete-redirect' => true, 'move' => true, 'move-rootuserpages' => true, 'move-subpages' => true, 'move-categorypages' => true, 'suppressredirect' => true, ], 'uploadfile' => [ 'upload' => true, 'reupload-own' => true, ], 'uploadeditmovefile' => [ 'upload' => true, 'reupload-own' => true, 'reupload' => true, 'reupload-shared' => true, 'upload_by_url' => true, 'movefile' => true, 'suppressredirect' => true, ], 'patrol' => [ 'patrol' => true, ], 'rollback' => [ 'rollback' => true, ], 'blockusers' => [ 'block' => true, 'blockemail' => true, ], 'viewdeleted' => [ 'browsearchive' => true, 'deletedhistory' => true, 'deletedtext' => true, ], 'viewrestrictedlogs' => [ 'suppressionlog' => true, ], 'delete' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'browsearchive' => true, 'deletedhistory' => true, 'deletedtext' => true, 'delete' => true, 'bigdelete' => true, 'deletelogentry' => true, 'deleterevision' => true, 'undelete' => true, ], 'oversight' => [ 'suppressrevision' => true, 'viewsuppressed' => true, ], 'protect' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editprotected' => true, 'protect' => true, ], 'viewmywatchlist' => [ 'viewmywatchlist' => true, ], 'editmywatchlist' => [ 'editmywatchlist' => true, ], 'sendemail' => [ 'sendemail' => true, ], 'createaccount' => [ 'createaccount' => true, ], 'privateinfo' => [ 'viewmyprivateinfo' => true, ], 'mergehistory' => [ 'mergehistory' => true, ], 'managesessions' => [ 'logout' => true, ], ], 'GrantPermissionGroups' => [ 'basic' => 'hidden', 'editpage' => 'page-interaction', 'createeditmovepage' => 'page-interaction', 'editprotected' => 'page-interaction', 'patrol' => 'page-interaction', 'uploadfile' => 'file-interaction', 'uploadeditmovefile' => 'file-interaction', 'sendemail' => 'email', 'viewmywatchlist' => 'watchlist-interaction', 'editviewmywatchlist' => 'watchlist-interaction', 'editmycssjs' => 'customization', 'editmyoptions' => 'customization', 'editinterface' => 'administration', 'editsiteconfig' => 'administration', 'rollback' => 'administration', 'blockusers' => 'administration', 'delete' => 'administration', 'viewdeleted' => 'administration', 'viewrestrictedlogs' => 'administration', 'protect' => 'administration', 'oversight' => 'administration', 'createaccount' => 'administration', 'mergehistory' => 'administration', 'import' => 'administration', 'highvolume' => 'high-volume', 'privateinfo' => 'private-information', 'managesessions' => 'private-information', ], 'GrantRiskGroups' => [ 'basic' => 'low', 'editpage' => 'low', 'createeditmovepage' => 'low', 'editprotected' => 'vandalism', 'patrol' => 'low', 'uploadfile' => 'low', 'uploadeditmovefile' => 'low', 'sendemail' => 'security', 'viewmywatchlist' => 'low', 'editviewmywatchlist' => 'low', 'editmycssjs' => 'security', 'editmyoptions' => 'security', 'editinterface' => 'vandalism', 'editsiteconfig' => 'security', 'rollback' => 'low', 'blockusers' => 'vandalism', 'delete' => 'vandalism', 'viewdeleted' => 'vandalism', 'viewrestrictedlogs' => 'security', 'protect' => 'vandalism', 'oversight' => 'security', 'createaccount' => 'low', 'mergehistory' => 'vandalism', 'import' => 'security', 'highvolume' => 'low', 'privateinfo' => 'low', ], 'EnableBotPasswords' => true, 'BotPasswordsCluster' => false, 'BotPasswordsDatabase' => false, 'BotPasswordsLimit' => 100, 'SecretKey' => false, 'JwtPrivateKey' => false, 'JwtPublicKey' => false, 'AllowUserJs' => false, 'ReauthenticateForActions' => [ 'edituserjs' => 'edituserjscss', 'editusercss' => 'edituserjscss', 'editsitejs' => 'editsitejscss', 'editsitecss' => 'editsitejscss', ], 'AllowUserCss' => false, 'AllowUserCssPrefs' => true, 'UseSiteJs' => true, 'UseSiteCss' => true, 'BreakFrames' => false, 'EditPageFrameOptions' => 'DENY', 'ApiFrameOptions' => 'DENY', 'CSPHeader' => false, 'CSPReportOnlyHeader' => false, 'CSPUseReportURIDirective' => false, 'CSPFalsePositiveUrls' => [ 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'chrome-extension' => true, ], 'AllowCrossOrigin' => false, 'RestAllowCrossOriginCookieAuth' => false, 'SessionSecret' => false, 'CookieExpiration' => 2592000, 'ExtendedLoginCookieExpiration' => 15552000, 'SessionCookieJwtExpiration' => 14400, 'CookieDomain' => '', 'CookiePath' => '/', 'CookieSecure' => 'detect', 'CookiePrefix' => false, 'CookieHttpOnly' => true, 'CookieSameSite' => null, 'CacheVaryCookies' => [ ], 'SessionName' => false, 'CookieSetOnAutoblock' => true, 'CookieSetOnIpBlock' => true, 'DebugLogFile' => '', 'DebugLogPrefix' => '', 'DebugRedirects' => false, 'DebugRawPage' => false, 'DebugComments' => false, 'DebugDumpSql' => false, 'TrxProfilerLimits' => [ 'GET' => [ 'masterConns' => 0, 'writes' => 0, 'readQueryTime' => 5, 'readQueryRows' => 10000, ], 'POST' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 100000, 'maxAffected' => 1000, ], 'POST-nonwrite' => [ 'writes' => 0, 'readQueryTime' => 5, 'readQueryRows' => 10000, ], 'PostSend-GET' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 10000, 'maxAffected' => 1000, 'masterConns' => 0, 'writes' => 0, ], 'PostSend-POST' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 100000, 'maxAffected' => 1000, ], 'JobRunner' => [ 'readQueryTime' => 30, 'writeQueryTime' => 5, 'readQueryRows' => 100000, 'maxAffected' => 500, ], 'Maintenance' => [ 'writeQueryTime' => 5, 'maxAffected' => 1000, ], ], 'DebugLogGroups' => [ ], 'MWLoggerDefaultSpi' => [ 'class' => 'MediaWiki\\Logger\\LegacySpi', ], 'ShowDebug' => false, 'SpecialVersionShowHooks' => false, 'ShowExceptionDetails' => false, 'LogExceptionBacktrace' => true, 'PropagateErrors' => true, 'ShowHostnames' => false, 'OverrideHostname' => false, 'DevelopmentWarnings' => false, 'DeprecationReleaseLimit' => false, 'Profiler' => [ ], 'StatsdServer' => false, 'StatsdMetricPrefix' => 'MediaWiki', 'StatsTarget' => null, 'StatsFormat' => null, 'StatsPrefix' => 'mediawiki', 'OpenTelemetryConfig' => null, 'PageInfoTransclusionLimit' => 50, 'EnableJavaScriptTest' => false, 'CachePrefix' => false, 'DebugToolbar' => false, 'ApiClientErrorSampleRate' => 1.0, 'DisableTextSearch' => false, 'AdvancedSearchHighlighting' => false, 'SearchHighlightBoundaries' => '[\\p{Z}\\p{P}\\p{C}]', 'OpenSearchTemplates' => [ 'application/x-suggestions+json' => false, 'application/x-suggestions+xml' => false, ], 'OpenSearchDefaultLimit' => 10, 'OpenSearchDescriptionLength' => 100, 'SearchSuggestCacheExpiry' => 1200, 'DisableSearchUpdate' => false, 'NamespacesToBeSearchedDefault' => [ true, ], 'DisableInternalSearch' => false, 'SearchForwardUrl' => null, 'SitemapNamespaces' => false, 'SitemapNamespacesPriorities' => false, 'SitemapApiConfig' => [ ], 'SpecialSearchFormOptions' => [ ], 'SearchMatchRedirectPreference' => false, 'SearchRunSuggestedQuery' => true, 'Diff3' => '/usr/bin/diff3', 'Diff' => '/usr/bin/diff', 'PreviewOnOpenNamespaces' => [ 14 => true, ], 'UniversalEditButton' => true, 'UseAutomaticEditSummaries' => true, 'CommandLineDarkBg' => false, 'ReadOnly' => null, 'ReadOnlyWatchedItemStore' => false, 'ReadOnlyFile' => false, 'UpgradeKey' => false, 'GitBin' => '/usr/bin/git', 'GitRepositoryViewers' => [ 'https: 'ssh: 'https: 'git@github\\.com:(.*?)(\\.git)?' => 'https: ], 'InstallerInitialPages' => [ [ 'titlemsg' => 'mainpage', 'text' => '{{subst:int:mainpagetext}}{{subst:int:mainpagedocfooter}}', ], ], 'RCMaxAge' => 7776000, 'WatchersMaxAge' => 15552000, 'UnwatchedPageSecret' => 1, 'RCFilterByAge' => false, 'RCLinkLimits' => [ 50, 100, 250, 500, ], 'RCLinkDays' => [ 1, 3, 7, 14, 30, ], 'RCFeeds' => [ ], 'RCWatchCategoryMembership' => false, 'UseRCPatrol' => true, 'StructuredChangeFiltersLiveUpdatePollingRate' => 3, 'UseNPPatrol' => true, 'UseFilePatrol' => true, 'Feed' => true, 'FeedLimit' => 50, 'FeedCacheTimeout' => 60, 'FeedDiffCutoff' => 32768, 'OverrideSiteFeed' => [ ], 'FeedClasses' => [ 'rss' => 'MediaWiki\\Feed\\RSSFeed', 'atom' => 'MediaWiki\\Feed\\AtomFeed', ], 'AdvertisedFeedTypes' => [ 'atom', ], 'RCShowWatchingUsers' => false, 'RCShowChangedSize' => true, 'RCChangedSizeThreshold' => 500, 'ShowUpdatedMarker' => true, 'DisableAnonTalk' => false, 'UseTagFilter' => true, 'SoftwareTags' => [ 'mw-contentmodelchange' => true, 'mw-new-redirect' => true, 'mw-removed-redirect' => true, 'mw-changed-redirect-target' => true, 'mw-blank' => true, 'mw-replace' => true, 'mw-recreated' => true, 'mw-rollback' => true, 'mw-undo' => true, 'mw-manual-revert' => true, 'mw-reverted' => true, 'mw-server-side-upload' => true, 'mw-ipblock-appeal' => true, 'mw-edited-other-users-js' => true, 'mw-edited-other-users-css' => true, ], 'RestrictedTagViewRights' => [ ], 'UnwatchedPageThreshold' => false, 'RecentChangesFlags' => [ 'newpage' => [ 'letter' => 'newpageletter', 'title' => 'recentchanges-label-newpage', 'legend' => 'recentchanges-legend-newpage', 'grouping' => 'any', ], 'minor' => [ 'letter' => 'minoreditletter', 'title' => 'recentchanges-label-minor', 'legend' => 'recentchanges-legend-minor', 'class' => 'minoredit', 'grouping' => 'all', ], 'bot' => [ 'letter' => 'boteditletter', 'title' => 'recentchanges-label-bot', 'legend' => 'recentchanges-legend-bot', 'class' => 'botedit', 'grouping' => 'all', ], 'unpatrolled' => [ 'letter' => 'unpatrolledletter', 'title' => 'recentchanges-label-unpatrolled', 'legend' => 'recentchanges-legend-unpatrolled', 'grouping' => 'any', ], ], 'WatchlistExpiry' => false, 'EnableWatchstarPopover' => false, 'EnableWatchlistLabels' => false, 'WatchlistLabelsMaxPerUser' => 100, 'WatchlistPurgeRate' => 0.1, 'WatchlistExpiryMaxDuration' => '1 year', 'EnableChangesListQueryPartitioning' => false, 'RightsPage' => null, 'RightsUrl' => null, 'RightsText' => null, 'RightsIcon' => null, 'UseCopyrightUpload' => false, 'MaxCredits' => 0, 'ShowCreditsIfMax' => true, 'ImportSources' => [ ], 'ImportTargetNamespace' => null, 'ExportAllowHistory' => true, 'ExportMaxHistory' => 0, 'ExportAllowListContributors' => false, 'ExportMaxLinkDepth' => 0, 'ExportFromNamespaces' => false, 'ExportAllowAll' => false, 'ExportPagelistLimit' => 5000, 'XmlDumpSchemaVersion' => '0.11', 'WikiFarmSettingsDirectory' => null, 'WikiFarmSettingsExtension' => 'yaml', 'ExtensionFunctions' => [ ], 'ExtensionMessagesFiles' => [ ], 'MessagesDirs' => [ ], 'TranslationAliasesDirs' => [ ], 'ExtensionEntryPointListFiles' => [ ], 'EnableParserLimitReporting' => true, 'ValidSkinNames' => [ ], 'SpecialPages' => [ ], 'ExtensionCredits' => [ ], 'Hooks' => [ ], 'ServiceWiringFiles' => [ ], 'JobClasses' => [ 'deletePage' => 'MediaWiki\\Page\\DeletePageJob', 'refreshLinks' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'deleteLinks' => 'MediaWiki\\Page\\DeleteLinksJob', 'htmlCacheUpdate' => 'MediaWiki\\JobQueue\\Jobs\\HTMLCacheUpdateJob', 'sendMail' => [ 'class' => 'MediaWiki\\Mail\\EmaillingJob', 'services' => [ 'Emailer', ], ], 'enotifNotify' => [ 'class' => 'MediaWiki\\RecentChanges\\RecentChangeNotifyJob', 'services' => [ 'RecentChangeLookup', ], ], 'fixDoubleRedirect' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\DoubleRedirectJob', 'services' => [ 'RevisionLookup', 'MagicWordFactory', 'WikiPageFactory', ], 'needsPage' => true, ], 'AssembleUploadChunks' => 'MediaWiki\\JobQueue\\Jobs\\AssembleUploadChunksJob', 'PublishStashedFile' => 'MediaWiki\\JobQueue\\Jobs\\PublishStashedFileJob', 'ThumbnailRender' => 'MediaWiki\\JobQueue\\Jobs\\ThumbnailRenderJob', 'UploadFromUrl' => 'MediaWiki\\JobQueue\\Jobs\\UploadFromUrlJob', 'recentChangesUpdate' => 'MediaWiki\\RecentChanges\\RecentChangesUpdateJob', 'refreshLinksPrioritized' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'refreshLinksDynamic' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'activityUpdateJob' => 'MediaWiki\\Watchlist\\ActivityUpdateJob', 'categoryMembershipChange' => [ 'class' => 'MediaWiki\\RecentChanges\\CategoryMembershipChangeJob', 'services' => [ 'RecentChangeFactory', ], ], 'CategoryCountUpdateJob' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\CategoryCountUpdateJob', 'services' => [ 'ConnectionProvider', 'NamespaceInfo', ], ], 'clearUserWatchlist' => 'MediaWiki\\Watchlist\\ClearUserWatchlistJob', 'watchlistExpiry' => 'MediaWiki\\Watchlist\\WatchlistExpiryJob', 'cdnPurge' => 'MediaWiki\\JobQueue\\Jobs\\CdnPurgeJob', 'userGroupExpiry' => 'MediaWiki\\User\\UserGroupExpiryJob', 'clearWatchlistNotifications' => 'MediaWiki\\Watchlist\\ClearWatchlistNotificationsJob', 'userOptionsUpdate' => 'MediaWiki\\User\\Options\\UserOptionsUpdateJob', 'revertedTagUpdate' => 'MediaWiki\\JobQueue\\Jobs\\RevertedTagUpdateJob', 'null' => 'MediaWiki\\JobQueue\\Jobs\\NullJob', 'userEditCountInit' => 'MediaWiki\\User\\UserEditCountInitJob', 'parsoidCachePrewarm' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\ParsoidCachePrewarmJob', 'services' => [ 'ParserOutputAccess', 'PageStore', 'RevisionLookup', 'ParsoidSiteConfig', ], 'needsPage' => false, ], 'renameUserTable' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserTableJob', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', ], ], 'renameUserDerived' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserDerivedJob', 'services' => [ 'RenameUserFactory', 'UserFactory', ], ], 'renameUser' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserTableJob', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', ], ], ], 'JobTypesExcludedFromDefaultQueue' => [ 'AssembleUploadChunks', 'PublishStashedFile', 'UploadFromUrl', ], 'JobBackoffThrottling' => [ ], 'JobTypeConf' => [ 'default' => [ 'class' => 'MediaWiki\\JobQueue\\JobQueueDB', 'order' => 'random', 'claimTTL' => 3600, ], ], 'JobQueueIncludeInMaxLagFactor' => false, 'SpecialPageCacheUpdates' => [ 'Statistics' => [ 'MediaWiki\\Deferred\\SiteStatsUpdate', 'cacheUpdate', ], ], 'PagePropLinkInvalidations' => [ 'hiddencat' => 'categorylinks', ], 'CategoryMagicGallery' => true, 'CategoryPagingLimit' => 200, 'CategoryCollation' => 'uppercase', 'TempCategoryCollations' => [ ], 'SortedCategories' => false, 'TrackingCategories' => [ ], 'LogTypes' => [ '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'import', 'interwiki', 'patrol', 'merge', 'suppress', 'tag', 'managetags', 'contentmodel', 'renameuser', ], 'LogRestrictions' => [ 'suppress' => 'suppressionlog', ], 'FilterLogTypes' => [ 'patrol' => true, 'tag' => true, 'newusers' => false, ], 'LogNames' => [ '' => 'all-logs-page', 'block' => 'blocklogpage', 'protect' => 'protectlogpage', 'rights' => 'rightslog', 'delete' => 'dellogpage', 'upload' => 'uploadlogpage', 'move' => 'movelogpage', 'import' => 'importlogpage', 'patrol' => 'patrol-log-page', 'merge' => 'mergelog', 'suppress' => 'suppressionlog', ], 'LogHeaders' => [ '' => 'alllogstext', 'block' => 'blocklogtext', 'delete' => 'dellogpagetext', 'import' => 'importlogpagetext', 'merge' => 'mergelogpagetext', 'move' => 'movelogpagetext', 'patrol' => 'patrol-log-header', 'protect' => 'protectlogtext', 'rights' => 'rightslogtext', 'suppress' => 'suppressionlogtext', 'upload' => 'uploadlogpagetext', ], 'LogActions' => [ ], 'LogActionsHandlers' => [ 'block/block' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'block/reblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'block/unblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'contentmodel/change' => 'MediaWiki\\Logging\\ContentModelLogFormatter', 'contentmodel/new' => 'MediaWiki\\Logging\\ContentModelLogFormatter', 'delete/delete' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/delete_redir' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/delete_redir2' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/event' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/restore' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/revision' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'import/interwiki' => 'MediaWiki\\Logging\\ImportLogFormatter', 'import/upload' => 'MediaWiki\\Logging\\ImportLogFormatter', 'interwiki/iw_add' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'interwiki/iw_delete' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'interwiki/iw_edit' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'managetags/activate' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/create' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/deactivate' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/delete' => 'MediaWiki\\Logging\\LogFormatter', 'merge/merge' => [ 'class' => 'MediaWiki\\Logging\\MergeLogFormatter', 'services' => [ 'TitleParser', ], ], 'merge/merge-into' => [ 'class' => 'MediaWiki\\Logging\\MergeLogFormatter', 'services' => [ 'TitleParser', ], ], 'move/move' => [ 'class' => 'MediaWiki\\Logging\\MoveLogFormatter', 'services' => [ 'TitleParser', ], ], 'move/move_redir' => [ 'class' => 'MediaWiki\\Logging\\MoveLogFormatter', 'services' => [ 'TitleParser', ], ], 'patrol/patrol' => 'MediaWiki\\Logging\\PatrolLogFormatter', 'patrol/autopatrol' => 'MediaWiki\\Logging\\PatrolLogFormatter', 'protect/modify' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/move_prot' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/protect' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/unprotect' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'renameuser/renameuser' => [ 'class' => 'MediaWiki\\Logging\\RenameuserLogFormatter', 'services' => [ 'TitleParser', ], ], 'rights/autopromote' => 'MediaWiki\\Logging\\RightsLogFormatter', 'rights/rights' => 'MediaWiki\\Logging\\RightsLogFormatter', 'suppress/block' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'suppress/delete' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'suppress/event' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'suppress/reblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'suppress/revision' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'tag/update' => 'MediaWiki\\Logging\\TagLogFormatter', 'upload/overwrite' => 'MediaWiki\\Logging\\UploadLogFormatter', 'upload/revert' => 'MediaWiki\\Logging\\UploadLogFormatter', 'upload/upload' => 'MediaWiki\\Logging\\UploadLogFormatter', ], 'ActionFilteredLogs' => [ 'block' => [ 'block' => [ 'block', ], 'reblock' => [ 'reblock', ], 'unblock' => [ 'unblock', ], ], 'contentmodel' => [ 'change' => [ 'change', ], 'new' => [ 'new', ], ], 'delete' => [ 'delete' => [ 'delete', ], 'delete_redir' => [ 'delete_redir', 'delete_redir2', ], 'restore' => [ 'restore', ], 'event' => [ 'event', ], 'revision' => [ 'revision', ], ], 'import' => [ 'interwiki' => [ 'interwiki', ], 'upload' => [ 'upload', ], ], 'managetags' => [ 'create' => [ 'create', ], 'delete' => [ 'delete', ], 'activate' => [ 'activate', ], 'deactivate' => [ 'deactivate', ], ], 'move' => [ 'move' => [ 'move', ], 'move_redir' => [ 'move_redir', ], ], 'newusers' => [ 'create' => [ 'create', 'newusers', ], 'create2' => [ 'create2', ], 'autocreate' => [ 'autocreate', ], 'byemail' => [ 'byemail', ], ], 'protect' => [ 'protect' => [ 'protect', ], 'modify' => [ 'modify', ], 'unprotect' => [ 'unprotect', ], 'move_prot' => [ 'move_prot', ], ], 'rights' => [ 'rights' => [ 'rights', ], 'autopromote' => [ 'autopromote', ], ], 'suppress' => [ 'event' => [ 'event', ], 'revision' => [ 'revision', ], 'delete' => [ 'delete', ], 'block' => [ 'block', ], 'reblock' => [ 'reblock', ], ], 'upload' => [ 'upload' => [ 'upload', ], 'overwrite' => [ 'overwrite', ], 'revert' => [ 'revert', ], ], ], 'NewUserLog' => true, 'PageCreationLog' => true, 'AllowSpecialInclusion' => true, 'DisableQueryPageUpdate' => false, 'CountCategorizedImagesAsUsed' => false, 'MaxRedirectLinksRetrieved' => 500, 'RangeContributionsCIDRLimit' => [ 'IPv4' => 16, 'IPv6' => 32, ], 'Actions' => [ ], 'DefaultRobotPolicy' => 'index,follow', 'NamespaceRobotPolicies' => [ ], 'ArticleRobotPolicies' => [ ], 'ExemptFromUserRobotsControl' => null, 'DebugAPI' => false, 'APIModules' => [ ], 'APIFormatModules' => [ ], 'APIMetaModules' => [ ], 'APIPropModules' => [ ], 'APIListModules' => [ ], 'APIMaxDBRows' => 5000, 'APIMaxResultSize' => 8388608, 'APIMaxUncachedDiffs' => 1, 'APIMaxLagThreshold' => 7, 'APICacheHelpTimeout' => 3600, 'APIUselessQueryPages' => [ 'MIMEsearch', 'LinkSearch', ], 'AjaxLicensePreview' => true, 'CrossSiteAJAXdomains' => [ ], 'CrossSiteAJAXdomainExceptions' => [ ], 'AllowedCorsHeaders' => [ 'Accept', 'Accept-Language', 'Content-Language', 'Content-Type', 'Accept-Encoding', 'DNT', 'Origin', 'User-Agent', 'Api-User-Agent', 'Promise-Non-Write-API-Action', 'Access-Control-Max-Age', 'Authorization', ], 'RestAPIAdditionalRouteFiles' => [ ], 'RestSandboxSpecs' => [ ], 'RestLocalModuleTestBaseUrl' => null, 'RestModuleOverrides' => [ ], 'RestExternalModules' => [ ], 'MaxShellMemory' => 307200, 'MaxShellFileSize' => 102400, 'MaxShellTime' => 180, 'MaxShellWallClockTime' => 180, 'ShellCgroup' => false, 'PhpCli' => '/usr/bin/php', 'ShellRestrictionMethod' => 'autodetect', 'ShellboxUrls' => [ 'default' => null, ], 'ShellboxSecretKey' => null, 'ShellboxShell' => '/bin/sh', 'HTTPTimeout' => 25, 'HTTPConnectTimeout' => 5.0, 'HTTPMaxTimeout' => 0, 'HTTPMaxConnectTimeout' => 0, 'HTTPImportTimeout' => 25, 'AsyncHTTPTimeout' => 25, 'HTTPProxy' => '', 'LocalVirtualHosts' => [ ], 'LocalHTTPProxy' => false, 'AllowExternalReqID' => false, 'GenerateReqIDFormat' => 'rand24', 'JobRunRate' => 1, 'RunJobsAsync' => false, 'UpdateRowsPerJob' => 300, 'UpdateRowsPerQuery' => 100, 'RedirectOnLogin' => null, 'VirtualRestConfig' => [ 'paths' => [ ], 'modules' => [ ], 'global' => [ 'timeout' => 360, 'forwardCookies' => false, 'HTTPProxy' => null, ], ], 'EventRelayerConfig' => [ 'default' => [ 'class' => 'Wikimedia\\EventRelayer\\EventRelayerNull', ], ], 'Pingback' => false, 'OriginTrials' => [ ], 'ReportToExpiry' => 86400, 'ReportToEndpoints' => [ ], 'FeaturePolicyReportOnly' => [ ], 'SkinsPreferred' => [ 'vector-2022', 'vector', ], 'SpecialContributeSkinsEnabled' => [ ], 'SpecialContributeNewPageTarget' => null, 'EnableEditRecovery' => false, 'EditRecoveryExpiry' => 2592000, 'UseCodexSpecialBlock' => false, 'ShowLogoutConfirmation' => false, 'EnableProtectionIndicators' => true, 'OutputPipelineStages' => [ ], 'FeatureShutdown' => [ ], 'CloneArticleParserOutput' => true, 'UseLeximorph' => false, 'UsePostprocCacheLegacy' => false, 'UsePostprocCacheParsoid' => true, 'ParserOptionsLogUnsafeSampleRate' => 0, 'ReturnExperimentalPFragmentTypes' => [ ], ], 'type' => [ 'ConfigRegistry' => 'object', 'AssumeProxiesUseDefaultProtocolPorts' => 'boolean', 'ForceHTTPS' => 'boolean', 'ExtensionDirectory' => [ 'string', 'null', ], 'StyleDirectory' => [ 'string', 'null', ], 'UploadDirectory' => [ 'string', 'boolean', 'null', ], 'Logos' => [ 'object', 'boolean', ], 'ReferrerPolicy' => [ 'array', 'string', 'boolean', ], 'ActionPaths' => 'object', 'MainPageIsDomainRoot' => 'boolean', 'ImgAuthUrlPathMap' => 'object', 'LocalFileRepo' => 'object', 'ForeignFileRepos' => 'array', 'UseSharedUploads' => 'boolean', 'SharedUploadDirectory' => [ 'string', 'null', ], 'SharedUploadPath' => [ 'string', 'null', ], 'HashedSharedUploadDirectory' => 'boolean', 'FetchCommonsDescriptions' => 'boolean', 'SharedUploadDBname' => [ 'boolean', 'string', ], 'SharedUploadDBprefix' => 'string', 'CacheSharedUploads' => 'boolean', 'ForeignUploadTargets' => 'array', 'UploadDialog' => 'object', 'FileBackends' => 'object', 'LockManagers' => 'array', 'DefaultLockManager' => [ 'string', 'null', ], 'CopyUploadsDomains' => 'array', 'CopyUploadTimeout' => [ 'boolean', 'integer', ], 'SharedThumbnailScriptPath' => [ 'string', 'boolean', ], 'HashedUploadDirectory' => 'boolean', 'CSPUploadEntryPoint' => 'boolean', 'FileExtensions' => 'array', 'ProhibitedFileExtensions' => 'array', 'MimeTypeExclusions' => 'array', 'TrustedMediaFormats' => 'array', 'MediaHandlers' => 'object', 'NativeImageLazyLoading' => 'boolean', 'ParserTestMediaHandlers' => 'object', 'MaxInterlacingAreas' => 'object', 'SVGConverters' => 'object', 'SVGNativeRendering' => [ 'string', 'boolean', ], 'MaxImageArea' => [ 'string', 'integer', 'boolean', ], 'TiffThumbnailType' => 'array', 'GenerateThumbnailOnParse' => 'boolean', 'EnableAutoRotation' => [ 'boolean', 'null', ], 'Antivirus' => [ 'string', 'null', ], 'AntivirusSetup' => 'object', 'MimeDetectorCommand' => [ 'string', 'null', ], 'XMLMimeTypes' => 'object', 'ImageLimits' => 'array', 'ThumbLimits' => 'array', 'ThumbnailNamespaces' => 'array', 'ThumbnailSteps' => [ 'array', 'null', ], 'ThumbnailBuckets' => [ 'array', 'null', ], 'UploadThumbnailRenderMap' => 'object', 'GalleryOptions' => 'object', 'DjvuDump' => [ 'string', 'null', ], 'DjvuRenderer' => [ 'string', 'null', ], 'DjvuTxt' => [ 'string', 'null', ], 'DjvuPostProcessor' => [ 'string', 'null', ], 'RestTermsOfServiceUrl' => [ 'string', 'null', ], 'SMTP' => [ 'boolean', 'object', ], 'EnotifFromEditor' => 'boolean', 'EmailConfirmationBanner' => 'boolean', 'EnotifRevealEditorAddress' => 'boolean', 'UsersNotifiedOnAllChanges' => 'object', 'DBmwschema' => [ 'string', 'null', ], 'SharedTables' => 'array', 'DBservers' => [ 'boolean', 'array', ], 'LBFactoryConf' => 'object', 'LocalDatabases' => 'array', 'VirtualDomainsMapping' => 'object', 'FileSchemaMigrationStage' => 'integer', 'ExternalLinksDomainGaps' => 'object', 'ContentHandlers' => 'object', 'NamespaceContentModels' => 'object', 'TextModelsToParse' => 'array', 'ExternalStores' => 'array', 'ExternalServers' => 'object', 'DefaultExternalStore' => [ 'array', 'boolean', ], 'RevisionCacheExpiry' => 'integer', 'PageLanguageUseDB' => 'boolean', 'DiffEngine' => [ 'string', 'null', ], 'ExternalDiffEngine' => [ 'string', 'boolean', ], 'Wikidiff2Options' => 'object', 'RequestTimeLimit' => [ 'integer', 'null', ], 'CriticalSectionTimeLimit' => 'number', 'PoolCounterConf' => [ 'object', 'null', ], 'PoolCountClientConf' => 'object', 'MaxUserDBWriteDuration' => [ 'integer', 'boolean', ], 'MaxJobDBWriteDuration' => [ 'integer', 'boolean', ], 'MultiShardSiteStats' => 'boolean', 'ObjectCaches' => 'object', 'WANObjectCache' => 'object', 'MicroStashType' => [ 'string', 'integer', ], 'ParsoidCacheConfig' => 'object', 'ParsoidSelectiveUpdateSampleRate' => 'integer', 'ParserCacheFilterConfig' => 'object', 'ChronologyProtectorSecret' => 'string', 'SuspiciousIpExpiry' => [ 'integer', 'boolean', ], 'MemCachedServers' => 'array', 'LocalisationCacheConf' => 'object', 'ExtensionInfoMTime' => [ 'integer', 'boolean', ], 'CdnServers' => 'object', 'CdnServersNoPurge' => 'object', 'HTCPRouting' => 'object', 'GrammarForms' => 'object', 'ExtraInterlanguageLinkPrefixes' => 'array', 'InterlanguageLinkCodeMap' => 'object', 'ExtraLanguageNames' => 'object', 'ExtraLanguageCodes' => 'object', 'DummyLanguageCodes' => 'object', 'DisabledVariants' => 'object', 'ForceUIMsgAsContentMsg' => 'object', 'RawHtmlMessages' => 'array', 'OverrideUcfirstCharacters' => 'object', 'XhtmlNamespaces' => 'object', 'BrowserFormatDetection' => 'string', 'SkinMetaTags' => 'object', 'SkipSkins' => 'object', 'FragmentMode' => 'array', 'FooterIcons' => 'object', 'InterwikiLogoOverride' => 'array', 'ResourceModules' => 'object', 'ResourceModuleSkinStyles' => 'object', 'ResourceLoaderSources' => 'object', 'ResourceLoaderMaxage' => 'object', 'ResourceLoaderMaxQueryLength' => [ 'integer', 'boolean', ], 'CanonicalNamespaceNames' => 'object', 'ExtraNamespaces' => 'object', 'ExtraGenderNamespaces' => 'object', 'NamespaceAliases' => 'object', 'CapitalLinkOverrides' => 'object', 'NamespacesWithSubpages' => 'object', 'NamespacesWithoutAutoSummaries' => 'array', 'ContentNamespaces' => 'array', 'ShortPagesNamespaceExclusions' => 'array', 'ExtraSignatureNamespaces' => 'array', 'InvalidRedirectTargets' => 'array', 'LocalInterwikis' => 'array', 'InterwikiCache' => [ 'boolean', 'object', ], 'SiteTypes' => 'object', 'UrlProtocols' => 'array', 'TidyConfig' => 'object', 'ParsoidSettings' => 'object', 'ParsoidExperimentalParserFunctionOutput' => 'boolean', 'NoFollowNsExceptions' => 'array', 'NoFollowDomainExceptions' => 'array', 'ExternalLinksIgnoreDomains' => 'array', 'EnableMagicLinks' => 'object', 'ManualRevertSearchRadius' => 'integer', 'RevertedTagMaxDepth' => 'integer', 'CentralIdLookupProviders' => 'object', 'CentralIdLookupProvider' => 'string', 'UserRegistrationProviders' => 'object', 'PasswordPolicy' => 'object', 'AuthManagerConfig' => [ 'object', 'null', ], 'AuthManagerAutoConfig' => 'object', 'RememberMe' => 'string', 'ReauthenticateTime' => 'object', 'ChangeCredentialsBlacklist' => 'array', 'RemoveCredentialsBlacklist' => 'array', 'PasswordConfig' => 'object', 'PasswordResetRoutes' => 'object', 'SignatureAllowedLintErrors' => 'array', 'ReservedUsernames' => 'array', 'DefaultUserOptions' => 'object', 'ConditionalUserOptions' => 'object', 'HiddenPrefs' => 'array', 'UserJsPrefLimit' => 'integer', 'AuthenticationTokenVersion' => [ 'string', 'null', ], 'SessionProviders' => 'object', 'AutoCreateTempUser' => 'object', 'AutoblockExemptions' => 'array', 'BlockCIDRLimit' => 'object', 'EnableMultiBlocks' => 'boolean', 'GroupPermissions' => 'object', 'PrivilegedGroups' => 'array', 'RevokePermissions' => 'object', 'GroupInheritsPermissions' => 'object', 'ImplicitGroups' => 'array', 'GroupsAddToSelf' => 'object', 'GroupsRemoveFromSelf' => 'object', 'RestrictedGroups' => 'object', 'UserRequirementsPrivateConditions' => 'array', 'RestrictionTypes' => 'array', 'RestrictionLevels' => 'array', 'CascadingRestrictionLevels' => 'array', 'SemiprotectedRestrictionLevels' => 'array', 'NamespaceProtection' => 'object', 'RestrictUserPageEditing' => 'boolean', 'NonincludableNamespaces' => 'object', 'Autopromote' => 'object', 'AutopromoteOnce' => 'object', 'AutopromoteOnceRCExcludedGroups' => 'array', 'AddGroups' => 'object', 'RemoveGroups' => 'object', 'AvailableRights' => 'array', 'ImplicitRights' => 'array', 'AccountCreationThrottle' => [ 'integer', 'array', ], 'TempAccountCreationThrottle' => 'array', 'TempAccountNameAcquisitionThrottle' => 'array', 'SpamRegex' => 'array', 'SummarySpamRegex' => 'array', 'DnsBlacklistUrls' => 'array', 'ProxyList' => [ 'string', 'array', ], 'ProxyWhitelist' => 'array', 'SoftBlockRanges' => 'array', 'RateLimits' => 'object', 'RateLimitsExcludedIPs' => 'array', 'ExternalQuerySources' => 'object', 'PasswordAttemptThrottle' => 'array', 'GrantPermissions' => 'object', 'GrantPermissionGroups' => 'object', 'GrantRiskGroups' => 'object', 'EnableBotPasswords' => 'boolean', 'BotPasswordsCluster' => [ 'string', 'boolean', ], 'BotPasswordsDatabase' => [ 'string', 'boolean', ], 'BotPasswordsLimit' => 'integer', 'ReauthenticateForActions' => 'object', 'CSPHeader' => [ 'boolean', 'object', ], 'CSPReportOnlyHeader' => [ 'boolean', 'object', ], 'CSPUseReportURIDirective' => [ 'boolean', 'object', ], 'CSPFalsePositiveUrls' => 'object', 'AllowCrossOrigin' => 'boolean', 'RestAllowCrossOriginCookieAuth' => 'boolean', 'CookieSameSite' => [ 'string', 'null', ], 'CacheVaryCookies' => 'array', 'TrxProfilerLimits' => 'object', 'DebugLogGroups' => 'object', 'MWLoggerDefaultSpi' => 'object', 'Profiler' => 'object', 'StatsTarget' => [ 'string', 'null', ], 'StatsFormat' => [ 'string', 'null', ], 'StatsPrefix' => 'string', 'OpenTelemetryConfig' => [ 'object', 'null', ], 'OpenSearchTemplates' => 'object', 'NamespacesToBeSearchedDefault' => 'object', 'SitemapNamespaces' => [ 'boolean', 'array', ], 'SitemapNamespacesPriorities' => [ 'boolean', 'object', ], 'SitemapApiConfig' => 'object', 'SpecialSearchFormOptions' => 'object', 'SearchMatchRedirectPreference' => 'boolean', 'SearchRunSuggestedQuery' => 'boolean', 'PreviewOnOpenNamespaces' => 'object', 'ReadOnlyWatchedItemStore' => 'boolean', 'GitRepositoryViewers' => 'object', 'InstallerInitialPages' => 'array', 'RCLinkLimits' => 'array', 'RCLinkDays' => 'array', 'RCFeeds' => 'object', 'OverrideSiteFeed' => 'object', 'FeedClasses' => 'object', 'AdvertisedFeedTypes' => 'array', 'SoftwareTags' => 'object', 'RestrictedTagViewRights' => 'object', 'RecentChangesFlags' => 'object', 'WatchlistExpiry' => 'boolean', 'EnableWatchstarPopover' => 'boolean', 'EnableWatchlistLabels' => 'boolean', 'WatchlistLabelsMaxPerUser' => 'integer', 'WatchlistPurgeRate' => 'number', 'WatchlistExpiryMaxDuration' => [ 'string', 'null', ], 'EnableChangesListQueryPartitioning' => 'boolean', 'ImportSources' => 'object', 'ExtensionFunctions' => 'array', 'ExtensionMessagesFiles' => 'object', 'MessagesDirs' => 'object', 'TranslationAliasesDirs' => 'object', 'ExtensionEntryPointListFiles' => 'object', 'ValidSkinNames' => 'object', 'SpecialPages' => 'object', 'ExtensionCredits' => 'object', 'Hooks' => 'object', 'ServiceWiringFiles' => 'array', 'JobClasses' => 'object', 'JobTypesExcludedFromDefaultQueue' => 'array', 'JobBackoffThrottling' => 'object', 'JobTypeConf' => 'object', 'SpecialPageCacheUpdates' => 'object', 'PagePropLinkInvalidations' => 'object', 'TempCategoryCollations' => 'array', 'SortedCategories' => 'boolean', 'TrackingCategories' => 'array', 'LogTypes' => 'array', 'LogRestrictions' => 'object', 'FilterLogTypes' => 'object', 'LogNames' => 'object', 'LogHeaders' => 'object', 'LogActions' => 'object', 'LogActionsHandlers' => 'object', 'ActionFilteredLogs' => 'object', 'RangeContributionsCIDRLimit' => 'object', 'Actions' => 'object', 'NamespaceRobotPolicies' => 'object', 'ArticleRobotPolicies' => 'object', 'ExemptFromUserRobotsControl' => [ 'array', 'null', ], 'APIModules' => 'object', 'APIFormatModules' => 'object', 'APIMetaModules' => 'object', 'APIPropModules' => 'object', 'APIListModules' => 'object', 'APIUselessQueryPages' => 'array', 'CrossSiteAJAXdomains' => 'object', 'CrossSiteAJAXdomainExceptions' => 'object', 'AllowedCorsHeaders' => 'array', 'RestAPIAdditionalRouteFiles' => 'array', 'RestSandboxSpecs' => 'object', 'RestLocalModuleTestBaseUrl' => [ 'string', 'null', ], 'RestModuleOverrides' => 'object', 'RestExternalModules' => 'object', 'ShellRestrictionMethod' => [ 'string', 'boolean', ], 'ShellboxUrls' => 'object', 'ShellboxSecretKey' => [ 'string', 'null', ], 'ShellboxShell' => [ 'string', 'null', ], 'HTTPTimeout' => 'number', 'HTTPConnectTimeout' => 'number', 'HTTPMaxTimeout' => 'number', 'HTTPMaxConnectTimeout' => 'number', 'LocalVirtualHosts' => 'object', 'LocalHTTPProxy' => [ 'string', 'boolean', ], 'GenerateReqIDFormat' => 'string', 'VirtualRestConfig' => 'object', 'EventRelayerConfig' => 'object', 'Pingback' => 'boolean', 'OriginTrials' => 'array', 'ReportToExpiry' => 'integer', 'ReportToEndpoints' => 'array', 'FeaturePolicyReportOnly' => 'array', 'SkinsPreferred' => 'array', 'SpecialContributeSkinsEnabled' => 'array', 'SpecialContributeNewPageTarget' => [ 'string', 'null', ], 'EnableEditRecovery' => 'boolean', 'EditRecoveryExpiry' => 'integer', 'UseCodexSpecialBlock' => 'boolean', 'ShowLogoutConfirmation' => 'boolean', 'EnableProtectionIndicators' => 'boolean', 'OutputPipelineStages' => 'object', 'FeatureShutdown' => 'array', 'CloneArticleParserOutput' => 'boolean', 'UseLeximorph' => 'boolean', 'UsePostprocCacheLegacy' => 'boolean', 'UsePostprocCacheParsoid' => 'boolean', 'ParserOptionsLogUnsafeSampleRate' => 'integer', 'ReturnExperimentalPFragmentTypes' => 'array', ], 'mergeStrategy' => [ 'TiffThumbnailType' => 'replace', 'LBFactoryConf' => 'replace', 'InterwikiCache' => 'replace', 'PasswordPolicy' => 'array_replace_recursive', 'AuthManagerAutoConfig' => 'array_plus_2d', 'GroupPermissions' => 'array_plus_2d', 'RevokePermissions' => 'array_plus_2d', 'AddGroups' => 'array_merge_recursive', 'RemoveGroups' => 'array_merge_recursive', 'RateLimits' => 'array_plus_2d', 'GrantPermissions' => 'array_plus_2d', 'MWLoggerDefaultSpi' => 'replace', 'Profiler' => 'replace', 'Hooks' => 'array_merge_recursive', 'RestModuleOverrides' => 'array_replace_recursive', 'RestExternalModules' => 'array_replace_recursive', 'VirtualRestConfig' => 'array_plus_2d', ], 'dynamicDefault' => [ 'UsePathInfo' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultUsePathInfo', ], ], 'Script' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultScript', ], ], 'LoadScript' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLoadScript', ], ], 'RestPath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultRestPath', ], ], 'StylePath' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultStylePath', ], ], 'LocalStylePath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocalStylePath', ], ], 'ExtensionAssetsPath' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultExtensionAssetsPath', ], ], 'ArticlePath' => [ 'use' => [ 'Script', 'UsePathInfo', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultArticlePath', ], ], 'UploadPath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultUploadPath', ], ], 'FileCacheDirectory' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultFileCacheDirectory', ], ], 'Logo' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLogo', ], ], 'DeletedDirectory' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultDeletedDirectory', ], ], 'ShowEXIF' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultShowEXIF', ], ], 'SharedPrefix' => [ 'use' => [ 'DBprefix', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultSharedPrefix', ], ], 'SharedSchema' => [ 'use' => [ 'DBmwschema', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultSharedSchema', ], ], 'DBerrorLogTZ' => [ 'use' => [ 'Localtimezone', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultDBerrorLogTZ', ], ], 'Localtimezone' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocaltimezone', ], ], 'LocalTZoffset' => [ 'use' => [ 'Localtimezone', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocalTZoffset', ], ], 'ResourceBasePath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultResourceBasePath', ], ], 'MetaNamespace' => [ 'use' => [ 'Sitename', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultMetaNamespace', ], ], 'CookieSecure' => [ 'use' => [ 'ForceHTTPS', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultCookieSecure', ], ], 'CookiePrefix' => [ 'use' => [ 'SharedDB', 'SharedPrefix', 'SharedTables', 'DBname', 'DBprefix', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultCookiePrefix', ], ], 'ReadOnlyFile' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultReadOnlyFile', ], ], ], ], 'config-schema' => [ 'UploadStashScalerBaseUrl' => [ 'deprecated' => 'since 1.36 Use thumbProxyUrl in $wgLocalFileRepo', ], 'IllegalFileChars' => [ 'deprecated' => 'since 1.41; no longer customizable', ], 'ThumbnailNamespaces' => [ 'items' => [ 'type' => 'integer', ], ], 'LocalDatabases' => [ 'items' => [ 'type' => 'string', ], ], 'ParserCacheFilterConfig' => [ 'additionalProperties' => [ 'type' => 'object', 'description' => 'A map of namespace IDs to filter definitions.', 'additionalProperties' => [ 'type' => 'object', 'description' => 'A map of filter names to values.', 'properties' => [ 'minCpuTime' => [ 'type' => 'number', ], ], ], ], ], 'RawHtmlMessages' => [ 'items' => [ 'type' => 'string', ], ], 'InterwikiLogoOverride' => [ 'items' => [ 'type' => 'string', ], ], 'LegalTitleChars' => [ 'deprecated' => 'since 1.41; use Extension:TitleBlacklist to customize', ], 'ReauthenticateTime' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'ChangeCredentialsBlacklist' => [ 'items' => [ 'type' => 'string', ], ], 'RemoveCredentialsBlacklist' => [ 'items' => [ 'type' => 'string', ], ], 'GroupPermissions' => [ 'additionalProperties' => [ 'type' => 'object', 'additionalProperties' => [ 'type' => 'boolean', ], ], ], 'GroupInheritsPermissions' => [ 'additionalProperties' => [ 'type' => 'string', ], ], 'AvailableRights' => [ 'items' => [ 'type' => 'string', ], ], 'ImplicitRights' => [ 'items' => [ 'type' => 'string', ], ], 'SoftBlockRanges' => [ 'items' => [ 'type' => 'string', ], ], 'ExternalQuerySources' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'enabled' => [ 'type' => 'boolean', 'default' => false, ], 'url' => [ 'type' => 'string', 'format' => 'uri', ], 'timeout' => [ 'type' => 'integer', 'default' => 10, ], ], 'required' => [ 'enabled', 'url', ], 'additionalProperties' => false, ], ], 'GrantPermissions' => [ 'additionalProperties' => [ 'type' => 'object', 'additionalProperties' => [ 'type' => 'boolean', ], ], ], 'GrantPermissionGroups' => [ 'additionalProperties' => [ 'type' => 'string', ], ], 'SitemapNamespacesPriorities' => [ 'deprecated' => 'since 1.45 and ignored', ], 'SitemapApiConfig' => [ 'additionalProperties' => [ 'enabled' => [ 'type' => 'bool', ], 'sitemapsPerIndex' => [ 'type' => 'int', ], 'pagesPerSitemap' => [ 'type' => 'int', ], 'expiry' => [ 'type' => 'int', ], ], ], 'SoftwareTags' => [ 'additionalProperties' => [ 'type' => 'boolean', ], ], 'UseCopyrightUpload' => [ 'deprecated' => 'since 1.47 This feature is being removed.', ], 'JobBackoffThrottling' => [ 'additionalProperties' => [ 'type' => 'number', ], ], 'JobTypeConf' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'class' => [ 'type' => 'string', ], 'order' => [ 'type' => 'string', ], 'claimTTL' => [ 'type' => 'integer', ], ], ], ], 'TrackingCategories' => [ 'deprecated' => 'since 1.25 Extensions should now register tracking categories using the new extension registration system.', ], 'RangeContributionsCIDRLimit' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'RestSandboxSpecs' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'url' => [ 'type' => 'string', 'format' => 'url', ], 'name' => [ 'type' => 'string', ], 'file' => [ 'type' => 'string', ], 'msg' => [ 'type' => 'string', 'description' => 'a message key', ], ], ], ], 'RestModuleOverrides' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'mode' => [ 'type' => 'string', ], ], 'required' => [ 'mode', ], ], ], 'RestExternalModules' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'info' => [ 'type' => 'object', 'properties' => [ 'version' => [ 'type' => 'string', ], 'title' => [ 'type' => 'string', ], 'x-i18n-title' => [ 'type' => 'string', ], 'description' => [ 'type' => 'string', ], 'x-i18n-description' => [ 'type' => 'string', ], ], 'required' => [ 'version', ], ], 'base' => [ 'type' => 'string', 'format' => 'uri', ], 'spec' => [ 'type' => 'string', 'format' => 'uri', ], ], 'required' => [ 'info', 'base', 'spec', ], ], ], 'ShellboxUrls' => [ 'additionalProperties' => [ 'type' => [ 'string', 'boolean', 'null', ], ], ], ], 'obsolete-config' => [ 'MangleFlashPolicy' => 'Since 1.39; no longer has any effect.', 'EnableOpenSearchSuggest' => 'Since 1.35, no longer used', 'AutoloadAttemptLowercase' => 'Since 1.40; no longer has any effect.', ],]
$wgLegalTitleChars
Config variable stub for the LegalTitleChars setting, for use by phpdoc and IDEs.
$wgLanguageCode
Config variable stub for the LanguageCode setting, for use by phpdoc and IDEs.
$wgPageLanguageUseDB
Config variable stub for the PageLanguageUseDB setting, for use by phpdoc and IDEs.
$wgScript
Config variable stub for the Script setting, for use by phpdoc and IDEs.
$wgInternalServer
Config variable stub for the InternalServer setting, for use by phpdoc and IDEs.
$wgActionPaths
Config variable stub for the ActionPaths setting, for use by phpdoc and IDEs.
$wgMainPageIsDomainRoot
Config variable stub for the MainPageIsDomainRoot setting, for use by phpdoc and IDEs.
$wgInvalidRedirectTargets
Config variable stub for the InvalidRedirectTargets setting, for use by phpdoc and IDEs.
$wgArticlePath
Config variable stub for the ArticlePath setting, for use by phpdoc and IDEs.
$wgDeleteRevisionsLimit
Config variable stub for the DeleteRevisionsLimit setting, for use by phpdoc and IDEs.
$wgVariantArticlePath
Config variable stub for the VariantArticlePath setting, for use by phpdoc and IDEs.
$wgRawHtmlMessages
Config variable stub for the RawHtmlMessages setting, for use by phpdoc and IDEs.
$wgServer
Config variable stub for the Server setting, for use by phpdoc and IDEs.
assertWiki( $wikiId)
Throws if $wikiId is different from the return value of getWikiId().
Service interface for looking up Interwiki records.
The shared interface for all language converters.
Interface for localizing messages in MediaWiki.
Represents the target of a wiki link.
Data record representing a page that currently exists as an editable page on a wiki.
Interface for objects (potentially) representing an editable wiki page.
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Interface for a page that is (or could be, or used to be) an editable wiki page.
Provide primary and replica IDatabase connections.
Interface for database access objects.
Interface to a relational database.
Definition IDatabase.php:31
newUpdateQueryBuilder()
Get an UpdateQueryBuilder bound to this connection.
newDeleteQueryBuilder()
Get an DeleteQueryBuilder bound to this connection.
newSelectQueryBuilder()
Create an empty SelectQueryBuilder which can be used to run queries against this connection.
expr(string $field, string $op, $value)
See Expression::__construct()
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by ConvertibleTimestamp to the format used for ins...
__construct(array $options, callable $shouldModifyCallback, callable $modifyCallback)