MediaWiki master
ChangesListQuery.php
Go to the documentation of this file.
1<?php
2
4
5use InvalidArgumentException;
6use LogicException;
28use Psr\Log\LoggerInterface;
29use stdClass;
36use Wikimedia\Timestamp\ConvertibleTimestamp;
37use Wikimedia\Timestamp\TimestampFormat as TS;
38use function array_key_exists;
39
49 public const CONSTRUCTOR_OPTIONS = [
55 ...ExperienceCondition::CONSTRUCTOR_OPTIONS
56 ];
57
58 public const LINKS_FROM = 'from';
59 public const LINKS_TO = 'to';
60
61 private const LINK_TABLE_PREFIXES = [
62 'pagelinks' => 'pl',
63 'templatelinks' => 'tl',
64 'categorylinks' => 'cl',
65 'imagelinks' => 'il'
66 ];
67
69 public const PARTITION_THRESHOLD = 10000;
70
71 public const SORT_TIMESTAMP_DESC = 'timestamp-desc';
72 public const SORT_TIMESTAMP_ASC = 'timestamp-asc';
73
74 private int|float $rcMaxAge;
75 private bool $enablePartitioning;
76 private bool $forcePartitioning = false;
77 private array $virtualDomainsMapping;
78
79 private array $densityTunables = [
80 self::DENSITY_LINKS => 0.1,
81 self::DENSITY_WATCHLIST => 0.1,
82 self::DENSITY_USER => 0.1,
83 self::DENSITY_CHANGE_TAG_THRESHOLD => 0.5,
84 ];
85
87 private $filterModules;
88
90 private $joinModules;
91
93 private $highlights = [];
94
96 private $fields = [];
98 private $conds = [];
99
101 private $linkDirection = null;
103 private $linkTables = [];
105 private $linkTarget = null;
106
108 private $preparedEmulatedUnion = false;
109
114 private $prepareCallbacks = [];
115
117 private $minTimestamp = null;
118
120 private $startTimestamp = null;
122 private $startId = null;
124 private $endTimestamp = null;
126 private $endId = null;
128 private $sort = self::SORT_TIMESTAMP_DESC;
129
131 private ?int $limit = null;
132
134 private $density = 1;
135
140 private $joinOrderHint = self::JOIN_ORDER_RECENTCHANGES;
141
143 private ?Authority $audience = null;
144
146 private $excludeDeletedAction = false;
148 private $excludeDeletedUser = false;
149
151 private $maxExecutionTime = null;
152
154 private $forceEmptySet = false;
155
157 private $distinct = false;
158
160 private ?string $caller = null;
161
163 private $legacyMutators = [];
165 private $sqbMutators = [];
166
170 public function __construct(
171 private ServiceOptions $config,
172 private RecentChangeLookup $recentChangeLookup,
173 private WatchedItemStoreInterface $watchedItemStore,
174 private TempUserConfig $tempUserConfig,
175 private UserFactory $userFactory,
176 private LinkTargetLookup $linkTargetLookup,
177 private ChangeTagsStore $changeTagsStore,
178 private StatsFactory $statsFactory,
179 private NameTableStore $slotRoleStore,
180 private LoggerInterface $logger,
181 private IReadableDatabase $db,
182 private TableStatsProvider $rcStats,
183 ) {
184 $this->filterModules = [
185 'experience' => new ExperienceCondition(
186 $config,
187 $this->tempUserConfig,
188 $this->userFactory,
189 ),
190 'user' => new UserCondition(),
191 'named' => new NamedCondition( $this->tempUserConfig ),
192 'bot' => new BooleanFieldCondition( 'rc_bot' ),
193 'minor' => new BooleanFieldCondition( 'rc_minor' ),
194 'redirect' => new BooleanJoinFieldCondition( 'page_is_redirect', 'page' ),
195 'revisionType' => new RevisionTypeCondition(),
196 'source' => new EnumFieldCondition(
197 'rc_source',
198 $this->recentChangeLookup->getAllSources()
199 ),
200 'logType' => new FieldEqualityCondition( 'rc_log_type', true ),
201 'patrolled' => new EnumFieldCondition(
202 'rc_patrolled',
203 [
207 ]
208 ),
209 'watched' => new WatchedCondition(
210 (bool)$config->get( MainConfigNames::WatchlistExpiry )
211 ),
212 'seen' => new SeenCondition(
213 $this->watchedItemStore
214 ),
215 'watchlistLabel' => new WatchlistLabelCondition(),
216 'namespace' => new FieldEqualityCondition( 'rc_namespace' ),
217 'title' => new TitleCondition(),
218 'subpageof' => new SubpageOfCondition(),
219 ];
220
221 // ChangeTagsCondition consumes the density heuristic so it has to
222 // be prepared after the other modules. Putting it late in the list
223 // serves that purpose.
224 $this->filterModules['changeTags'] = new ChangeTagsCondition(
225 $this->changeTagsStore,
226 $this->rcStats,
227 $this->logger,
228 (bool)$config->get( MainConfigNames::MiserMode ),
229 );
230
231 $this->joinModules = [
232 'actor' => new BasicJoin( 'actor', 'recentchanges_actor', 'actor_id=rc_actor' ),
233 'change_tag' => new BasicJoin(
234 'change_tag',
235 'changetagdisplay',
236 'changetagdisplay.ct_rc_id=rc_id'
237 ),
238 'comment' => new BasicJoin( 'comment', 'recentchanges_comment', 'comment_id=rc_comment_id' ),
239 'page' => new BasicJoin( 'page', '', 'page_id=rc_cur_id' ),
240 'revision' => new BasicJoin( 'revision', '', 'rev_id=rc_this_oldid' ),
241 'slots' => new SlotsJoin(),
242 'user' => new BasicJoin( 'user', '', 'user_id=actor_user', 'actor' ),
243 'watchlist' => new WatchlistJoin(),
244 'watchlist_expiry' => new BasicJoin( 'watchlist_expiry', '', 'we_item=wl_id', 'watchlist' ),
245 'watchlist_label_member' => new BasicJoin(
246 'watchlist_label_member',
247 '',
248 'wlm_item=wl_id',
249 [ 'watchlist' ]
250 ),
251 ];
252
253 $this->rcMaxAge = (int)$config->get( MainConfigNames::RCMaxAge );
255 $this->virtualDomainsMapping = $config->get( MainConfigNames::VirtualDomainsMapping );
256 }
257
284 public function applyAction( string $verb, string $moduleName, $value = null ) {
285 $module = $this->getFilter( $moduleName );
286 switch ( $verb ) {
287 case 'require':
288 $module->require( $value );
289 break;
290 case 'exclude':
291 $module->exclude( $value );
292 break;
293 default:
294 throw new InvalidArgumentException(
295 "Unknown filter action verb: \"$verb\"" );
296 }
297 return $this;
298 }
299
306 public function requireNamespaces( array $namespaces ) {
307 return $this->applyArrayAction( 'require', 'namespace', $namespaces );
308 }
309
316 public function excludeNamespaces( array $namespaces ) {
317 return $this->applyArrayAction( 'exclude', 'namespace', $namespaces );
318 }
319
328 private function applyArrayAction( string $verb, string $moduleName, array $values ) {
329 foreach ( $values as $value ) {
330 $this->applyAction( $verb, $moduleName, $value );
331 }
332 return $this;
333 }
334
341 public function requireSubpageOf( LinkTarget|PageReference $page ) {
342 $this->getSubpageOfCondition()->require( $page );
343 return $this;
344 }
345
352 public function requireTitle( LinkTarget|PageReference $title ) {
353 $this->getTitleCondition()->require( $title );
354 return $this;
355 }
356
364 public function requireWatched( $watchTypes = [ 'watchedold', 'watchednew' ] ) {
365 return $this->applyArrayAction( 'require', 'watched', $watchTypes );
366 }
367
376 public function requireWatchlistLabelIds( array $labelIds ) {
377 return $this->applyArrayAction( 'require', 'watchlistLabel', $labelIds );
378 }
379
388 public function excludeWatchlistLabelIds( array $labelIds ) {
389 return $this->applyArrayAction( 'exclude', 'watchlistLabel', $labelIds );
390 }
391
401 public function requireLink( string $direction, array $tables, PageIdentity $page ) {
402 if ( count( $tables ) == 0 ) {
403 throw new InvalidArgumentException( 'Need at least one link table' );
404 }
405 $unknownTables = array_diff( $tables, array_keys( self::LINK_TABLE_PREFIXES ) );
406 if ( $unknownTables ) {
407 throw new InvalidArgumentException( 'Unknown link table(s): ' .
408 implode( ', ', $unknownTables ) );
409 }
410
411 $this->linkDirection = $direction;
412 $this->linkTables = $tables;
413 $this->linkTarget = $page;
414 return $this;
415 }
416
423 public function requireSources( array $sources ): self {
424 return $this->applyArrayAction( 'require', 'source', $sources );
425 }
426
433 public function requireUser( UserIdentity $user ): self {
434 $this->getUserFilter()->require( $user );
435 return $this;
436 }
437
444 public function excludeUser( UserIdentity $user ): self {
445 $this->getUserFilter()->exclude( $user );
446 return $this;
447 }
448
455 public function requirePatrolled( $value ): self {
456 $this->getPatrolledFilter()->require( $value );
457 return $this;
458 }
459
466 public function requireChangeTags( $tagNames ): self {
467 return $this->applyArrayAction( 'require', 'changeTags', $tagNames );
468 }
469
476 public function excludeChangeTags( $tagNames ): self {
477 return $this->applyArrayAction( 'exclude', 'changeTags', $tagNames );
478 }
479
486 public function requireLatest(): self {
487 $this->getRevisionTypeFilter()->require( 'latest' );
488 return $this;
489 }
490
497 public function excludeOldRevisions(): self {
498 $this->getRevisionTypeFilter()->exclude( 'old' );
499 return $this;
500 }
501
508 public function requireSlotChanged( string $role ): self {
509 try {
510 $roleId = $this->slotRoleStore->getId( $role );
511 } catch ( NameTableAccessException ) {
512 // No revisions changed this role yet
513 $this->forceEmptySet();
514 return $this;
515 }
516
517 $this->prepareCallbacks['slotChanged'] = function () use ( $roleId ) {
518 $slotsJoin = $this->getSlotsJoinModule();
519 $slotsJoin->setRoleId( $roleId );
520 $slotsJoin->forConds( $this )
521 ->left();
522
523 $slotsJoin->parentAlias()
524 ->forConds()
525 ->left();
526
527 // Detecting whether the slot has been touched as follows:
528 // 1. if slot_origin=slot_revision_id then the slot has been newly created or edited
529 // with this revision
530 // 2. otherwise if the content of a slot is different to the content of its parent slot,
531 // then the content of the slot has been changed in this revision
532 // (probably by a revert)
533 $this->where( $this->db->orExpr( [
534 new RawSQLExpression( 'slot.slot_origin = slot.slot_revision_id' ),
535 new RawSQLExpression( 'slot.slot_content_id != parent_slot.slot_content_id' ),
536 $this->db->expr( 'slot.slot_content_id', '=', null )->and( 'parent_slot.slot_content_id', '!=', null ),
537 $this->db->expr( 'slot.slot_content_id', '!=', null )->and( 'parent_slot.slot_content_id', '=', null ),
538 ] ) );
539 };
540 return $this;
541 }
542
549 public function excludeDeletedLogAction(): self {
550 $this->excludeDeletedAction = true;
551 return $this;
552 }
553
560 public function allowDeletedLogAction(): self {
561 $this->excludeDeletedAction = false;
562 return $this;
563 }
564
571 public function excludeDeletedUser(): self {
572 $this->excludeDeletedUser = true;
573 return $this;
574 }
575
583 public function denseRcSizeThreshold( $threshold ): self {
584 $this->getChangeTagsFilter()->setDenseRcSizeThreshold( $threshold );
585 return $this;
586 }
587
594 public function audience( ?Authority $authority ) {
595 $this->audience = $authority;
596 return $this;
597 }
598
618 public function highlight( string $name, string $verb, string $moduleName, $value = null ) {
619 $module = $this->getFilter( $moduleName );
620 // Validate now while the responsible caller is in the stack
621 $value = $module->validateValue( $value );
622 $module->capture();
623 $sense = match ( $verb ) {
624 'require' => true,
625 'exclude' => false,
626 };
627 $this->highlights[$name][] = new ChangesListHighlight( $sense, $moduleName, $value );
628 return $this;
629 }
630
637 public function minTimestamp( $timestamp ) {
638 $this->minTimestamp = $timestamp;
639 return $this;
640 }
641
653 public function startAt( string $timestamp, ?int $id = null ): self {
654 $this->startTimestamp = $timestamp;
655 $this->startId = $id;
656 return $this;
657 }
658
670 public function endAt( string $timestamp, ?int $id = null ): self {
671 $this->endTimestamp = $timestamp;
672 $this->endId = $id;
673 return $this;
674 }
675
682 public function orderBy( $sort ) {
683 $this->sort = $sort;
684 return $this;
685 }
686
693 public function limit( int $limit ) {
694 $this->limit = $limit;
695 $this->getChangeTagsFilter()->setLimit( $limit );
696 return $this;
697 }
698
700 public function adjustDensity( $density ): self {
701 if ( is_string( $density ) ) {
702 if ( isset( $this->densityTunables[$density] ) ) {
703 $density = $this->densityTunables[$density];
704 } else {
705 throw new \InvalidArgumentException( "Unknown density \"$density\"" );
706 }
707 }
708 $this->density *= $density;
709 $this->getChangeTagsFilter()->setDensityThresholdReached(
710 $this->density >= $this->densityTunables[self::DENSITY_CHANGE_TAG_THRESHOLD]
711 );
712 return $this;
713 }
714
716 public function joinOrderHint( $order ): self {
717 $this->joinOrderHint = $order;
718 return $this;
719 }
720
727 public function forceEmptySet(): self {
728 $this->forceEmptySet = true;
729 return $this;
730 }
731
738 public function isEmptySet(): bool {
739 return $this->forceEmptySet;
740 }
741
749 public function maxExecutionTime( float|int|null $time ) {
750 $this->maxExecutionTime = $time;
751 return $this;
752 }
753
759 public function enablePartitioning(): self {
760 $this->enablePartitioning = true;
761 return $this;
762 }
763
769 public function forcePartitioning(): self {
770 $this->forcePartitioning = true;
771 return $this;
772 }
773
774 private function getWatchlistJoinModule(): WatchlistJoin {
775 return $this->joinModules['watchlist'];
776 }
777
778 private function getWatchlistExpiryJoinModule(): BasicJoin {
779 return $this->joinModules['watchlist_expiry'];
780 }
781
782 private function getSlotsJoinModule(): SlotsJoin {
783 return $this->joinModules['slots'];
784 }
785
786 private function getUserFilter(): UserCondition {
787 return $this->filterModules['user'];
788 }
789
790 private function getWatchedFilter(): WatchedCondition {
791 return $this->filterModules['watched'];
792 }
793
794 private function getSeenFilter(): SeenCondition {
795 return $this->filterModules['seen'];
796 }
797
798 private function getChangeTagsFilter(): ChangeTagsCondition {
799 return $this->filterModules['changeTags'];
800 }
801
802 private function getWatchlistLabelFilter(): WatchlistLabelCondition {
803 return $this->filterModules['watchlistLabel'];
804 }
805
806 private function getRedirectFilter(): BooleanJoinFieldCondition {
807 return $this->filterModules['redirect'];
808 }
809
810 private function getRevisionTypeFilter(): RevisionTypeCondition {
811 return $this->filterModules['revisionType'];
812 }
813
814 private function getPatrolledFilter(): EnumFieldCondition {
815 return $this->filterModules['patrolled'];
816 }
817
818 private function getTitleCondition(): TitleCondition {
819 return $this->filterModules['title'];
820 }
821
822 private function getSubpageOfCondition(): SubpageOfCondition {
823 return $this->filterModules['subpageof'];
824 }
825
832 public function watchlistUser( UserIdentity $user ) {
833 $this->getWatchlistJoinModule()->setUser( $user );
834 $this->getSeenFilter()->setUser( $user );
835 $this->getWatchedFilter()->setUser( $user );
836 return $this;
837 }
838
846 public function fields( $fields ): self {
847 $fields = is_array( $fields ) ? $fields : [ $fields ];
848 $this->fields = array_merge( $this->fields, $fields );
849 return $this;
850 }
851
853 public function rcUserFields(): QueryBackend {
854 $this->getJoin( 'actor' )->forFields( $this )->straight();
855 $this->fields['rc_user'] = 'recentchanges_actor.actor_user';
856 $this->fields['rc_user_text'] = 'recentchanges_actor.actor_name';
857 return $this;
858 }
859
865 public function addChangeTagSummaryField(): self {
866 $this->getChangeTagsFilter()->capture();
867 return $this;
868 }
869
875 public function addWatchlistLabelSummaryField(): self {
876 $this->getWatchlistLabelFilter()->capture();
877 return $this;
878 }
879
886 public function recentChangeFields() {
887 $this->prepareCallbacks['recentChangeFields'] = function () {
888 $this->fields( RecentChange::getQueryInfo()['fields'] );
889 $this->joinForFields( 'actor' )->straight();
890 $this->joinForFields( 'comment' )->straight();
891 };
892 return $this;
893 }
894
902 public function watchlistFields(
903 $fields = [ 'wl_user', 'wl_notificationtimestamp', 'we_expiry' ]
904 ) {
905 $this->prepareCallbacks['watchlistFields'] = function () use ( $fields ) {
906 $wlFields = array_diff( $fields, [ 'we_expiry' ] );
907 $weFields = array_intersect( $fields, [ 'we_expiry' ] );
908 if ( $wlFields ) {
909 $this->fields( $wlFields );
910 }
911 $this->joinForFields( 'watchlist' )->weakLeft();
912 if ( $weFields && $this->config->get( MainConfigNames::WatchlistExpiry ) ) {
913 $this->fields( $weFields );
914 $this->joinForFields( 'watchlist_expiry' )->weakLeft();
915 }
916 };
917 return $this;
918 }
919
926 public function sha1Fields() {
927 $this->sqbMutators['sha1Fields'] = $this->applySha1Fields( ... );
928 return $this;
929 }
930
931 private function applySha1Fields( SelectQueryBuilder $query ) {
932 $pairExpr = $this->db->buildGroupConcat(
933 $this->db->buildConcat( [ 'sr.role_name', $this->db->addQuotes( ':' ), 'c.content_sha1' ] ),
934 ','
935 );
936 $revSha1Subquery = $this->db->newSelectQueryBuilder()
937 ->select( [
938 'rev_id',
939 'rev_deleted',
940 'rev_slot_pairs' => $pairExpr,
941 ] )
942 ->from( 'revision' )
943 ->join( 'slots', 's', [ 'rev_id = s.slot_revision_id' ] )
944 ->join( 'content', 'c', [ 's.slot_content_id = c.content_id' ] )
945 ->join( 'slot_roles', 'sr', [ 's.slot_role_id = sr.role_id' ] )
946 ->groupBy( [ 'rev_id', 'rev_deleted' ] )
947 ->caller( __METHOD__ );
948
949 $query->leftJoin(
950 $revSha1Subquery,
951 'revsha1',
952 [ 'rc_this_oldid = revsha1.rev_id' ]
953 );
954 $query->fields( [
955 'rev_deleted' => 'revsha1.rev_deleted',
956 'rev_slot_pairs' => 'revsha1.rev_slot_pairs'
957 ] );
958 }
959
965 public function addRedirectField(): self {
966 $this->getRedirectFilter()->capture();
967 return $this;
968 }
969
980 public function commentFields(): self {
981 $this->prepareCallbacks['commentFields'] = function () {
982 $this->joinForFields( 'comment' )->straight();
983 $this->fields( [
984 'rc_comment_text' => 'recentchanges_comment.comment_text',
985 'rc_comment_data' => 'recentchanges_comment.comment_data',
986 'rc_comment_cid' => 'recentchanges_comment.comment_id'
987 ] );
988 };
989 return $this;
990 }
991
997 public function maybeAddWatchlistExpiryField(): self {
998 if ( $this->config->get( MainConfigNames::WatchlistExpiry ) ) {
999 $this->getWatchlistExpiryJoinModule()->forFields( $this )->weakLeft();
1000 $this->fields( 'we_expiry' );
1001 }
1002 return $this;
1003 }
1004
1021 public function legacyMutator( callable $callback ) {
1022 $this->legacyMutators[] = $callback;
1023 return $this;
1024 }
1025
1040 public function sqbMutator( callable $callback ) {
1041 $this->sqbMutators[] = $callback;
1042 return $this;
1043 }
1044
1050 public function fetchResult(): ChangesListResult {
1051 $this->prepare();
1052 if ( $this->isEmptySet() ) {
1053 return $this->newResult();
1054 }
1055
1056 $shouldPartition = $this->shouldDoPartitioning();
1057 if ( $shouldPartition ) {
1058 $this->prepareEmulatedUnion();
1059 }
1060
1061 $sqb = $this->createQueryBuilder();
1062 if ( !$shouldPartition ) {
1063 $this->applyTimestampFilter( $sqb );
1064 }
1065 $sqb = $this->applyMutators( $sqb );
1066 if ( !$sqb || $this->isEmptySet() ) {
1067 return $this->newResult();
1068 }
1069
1070 $queries = $this->applyLinkTarget( $sqb );
1071
1072 $timer = $this->statsFactory->getTiming( 'ChangesListQuery_query_seconds' )
1073 ->setLabel( 'caller', $this->caller ?? 'unknown' )
1074 ->setLabel( 'union', (string)count( $queries ) )
1075 ->start();
1076
1077 if ( $shouldPartition ) {
1078 $timer->setLabel( 'strategy', 'partition' );
1079 $res = $this->doPartitionUnion( $queries );
1080 } else {
1081 $timer->setLabel( 'strategy', 'simple' );
1082 $res = $this->maybeEmulateUnion( $queries );
1083 }
1084
1085 $timer->stop();
1086
1087 return $this->newResult( $res );
1088 }
1089
1093 private function prepare() {
1094 if ( $this->linkTables ) {
1095 $this->adjustDensity( self::DENSITY_LINKS )
1096 ->joinOrderHint( self::JOIN_ORDER_OTHER );
1097 }
1098 if ( $this->audience !== null ) {
1099 $this->getChangeTagsFilter()->setAudience( $this->audience );
1100 }
1101 foreach ( $this->filterModules as $module ) {
1102 $module->prepareQuery( $this->db, $this );
1103 }
1104 foreach ( $this->prepareCallbacks as $callback ) {
1105 $callback();
1106 }
1107 $this->prepareAudienceCondition( $this->audience );
1108 if ( count( $this->linkTables ) > 1 ) {
1109 $this->prepareEmulatedUnion();
1110 }
1111 }
1112
1116 private function prepareEmulatedUnion() {
1117 $this->preparedEmulatedUnion = true;
1118 $this->fields( [ 'rc_timestamp', 'rc_id' ] );
1119 }
1120
1125 private function newResult( $rows = [] ): ChangesListResult {
1126 return new ChangesListResult( $rows, $this->getHighlightsFromRow( ... ) );
1127 }
1128
1135 private function prepareAudienceCondition( ?Authority $authority ) {
1136 if ( $this->excludeDeletedUser ) {
1137 if ( !$authority || !$authority->isAllowed( 'deletedhistory' ) ) {
1138 $bitmask = RevisionRecord::DELETED_USER;
1139 } elseif ( !$authority->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
1140 $bitmask = RevisionRecord::DELETED_USER | RevisionRecord::DELETED_RESTRICTED;
1141 } else {
1142 $bitmask = 0;
1143 }
1144 if ( $bitmask ) {
1145 $this->where( new RawSQLExpression(
1146 $this->db->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask"
1147 ) );
1148 }
1149 }
1150 if ( $this->excludeDeletedAction ) {
1151 // Log entries with DELETED_ACTION must not show up unless the user has
1152 // the necessary rights.
1153 if ( !$authority || !$authority->isAllowed( 'deletedhistory' ) ) {
1154 $bitmask = LogPage::DELETED_ACTION;
1155 } elseif ( !$authority->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
1156 $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
1157 } else {
1158 $bitmask = 0;
1159 }
1160 if ( $bitmask ) {
1161 $this->where( $this->db->expr( 'rc_source', '!=', RecentChange::SRC_LOG )
1162 ->orExpr( new RawSQLExpression(
1163 $this->db->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask"
1164 ) )
1165 );
1166 }
1167 }
1168 }
1169
1170 private function createQueryBuilder(): SelectQueryBuilder {
1171 $sqb = $this->db->newSelectQueryBuilder()
1172 ->select( $this->getUniqueFields() )
1173 ->from( 'recentchanges' )
1174 ->where( $this->conds );
1175
1176 $this->applyOptions( $sqb );
1177
1178 foreach ( $this->joinModules as $join ) {
1179 $join->prepare( $sqb );
1180 }
1181 return $sqb;
1182 }
1183
1189 private function applyOptions( SelectQueryBuilder $sqb ) {
1190 if ( $this->distinct ) {
1191 $sqb->distinct();
1192 // In order to prevent DISTINCT from causing query performance problems,
1193 // we have to GROUP BY the primary key.
1194 $sqb->groupBy( [ 'rc_timestamp', 'rc_id' ] );
1195 }
1196 $dir = $this->sort === self::SORT_TIMESTAMP_ASC ? 'ASC' : 'DESC';
1197 $sqb->orderBy( [ "rc_timestamp $dir", "rc_id $dir" ] );
1198
1199 $sqb->caller( $this->caller ?? __CLASS__ );
1200 if ( $this->limit !== null ) {
1201 $sqb->limit( $this->limit );
1202 }
1203 if ( $this->maxExecutionTime !== null ) {
1204 $sqb->setMaxExecutionTime( $this->maxExecutionTime );
1205 }
1206 }
1207
1213 private function applyTimestampFilter( SelectQueryBuilder $sqb ) {
1214 if ( $this->minTimestamp !== null ) {
1215 $sqb->andWhere( $this->db->expr( 'rc_timestamp', '>=',
1216 $this->db->timestamp( $this->minTimestamp ) ) );
1217 }
1218 $this->applyStartOrEnd( $sqb, true, $this->startTimestamp, $this->startId );
1219 $this->applyStartOrEnd( $sqb, false, $this->endTimestamp, $this->endId );
1220 }
1221
1228 private function applyStartOrEnd( SelectQueryBuilder $sqb, $isStart, $ts, $id ) {
1229 if ( $ts === null ) {
1230 return;
1231 }
1232 $op = ( $isStart === ( $this->sort === self::SORT_TIMESTAMP_ASC ) ) ? '>=' : '<=';
1233 $conds = [ 'rc_timestamp' => $this->db->timestamp( $ts ) ];
1234 if ( $id !== null ) {
1235 $conds['rc_id'] = $id;
1236 }
1237 $sqb->andWhere( $this->db->buildComparison( $op, $conds ) );
1238 }
1239
1245 private function getUniqueFields() {
1246 $seen = [];
1247 $fields = [];
1248 foreach ( $this->fields as $index => $value ) {
1249 if ( is_numeric( $index ) ) {
1250 if ( !array_key_exists( $index, $seen ) ) {
1251 $fields[] = $value;
1252 $seen[$index] = true;
1253 }
1254 } else {
1255 $fields[$index] = $value;
1256 }
1257 }
1258 return $fields;
1259 }
1260
1267 private function applyMutators( SelectQueryBuilder $sqb ) {
1268 if ( $this->legacyMutators ) {
1269 $queryInfo = $sqb->getQueryInfo();
1270 foreach ( $this->legacyMutators as $mutator ) {
1271 $ret = $mutator(
1272 $queryInfo['tables'],
1273 $queryInfo['fields'],
1274 $queryInfo['conds'],
1275 $queryInfo['options'],
1276 $queryInfo['join_conds']
1277 );
1278 if ( $ret === false ) {
1279 $this->forceEmptySet();
1280 return null;
1281 }
1282 }
1283 $sqb = $this->db->newSelectQueryBuilder()
1284 ->queryInfo( $queryInfo );
1285 }
1286 foreach ( $this->sqbMutators as $mutator ) {
1287 // Note $sqb may be passed by reference and reassigned
1288 $mutator( $sqb );
1289 }
1290 return $sqb;
1291 }
1292
1301 private function applyLinkTarget( SelectQueryBuilder $mainQueryBuilder ): array {
1302 if ( !$this->linkTarget ) {
1303 return [ $mainQueryBuilder ];
1304 }
1305
1306 $useVirtualDomains = $this->shouldUseVirtualDomains();
1307
1308 $queries = [];
1309 foreach ( $this->linkTables as $linkTable ) {
1310 $queryBuilder = clone $mainQueryBuilder;
1311
1312 if ( $this->linkDirection === self::LINKS_TO ) {
1313 $ok = $useVirtualDomains
1314 ? $this->applyLinksToFilter( $queryBuilder, $this->linkTarget, $linkTable )
1315 : $this->applyLinksToCondition( $queryBuilder, $this->linkTarget, $linkTable );
1316 } else {
1317 $ok = $useVirtualDomains
1318 ? $this->applyLinksFromFilter( $queryBuilder, $this->linkTarget, $linkTable )
1319 : $this->applyLinksFromCondition( $queryBuilder, $this->linkTarget, $linkTable );
1320 }
1321
1322 if ( $ok ) {
1323 $queries[] = $queryBuilder;
1324 }
1325 }
1326 return $queries;
1327 }
1328
1342 private function shouldUseVirtualDomains(): bool {
1343 return isset( $this->virtualDomainsMapping[LinksTable::VIRTUAL_DOMAIN] );
1344 }
1345
1354 private function applyLinksToCondition(
1355 SelectQueryBuilder $queryBuilder,
1356 PageIdentity $page,
1357 string $linkTable
1358 ): bool {
1359 $prefix = self::LINK_TABLE_PREFIXES[$linkTable];
1360 $queryBuilder->join( $linkTable, null, "rc_cur_id = {$prefix}_from" );
1361 if ( $linkTable === 'imagelinks' ) {
1362 // The imagelinks table has no xx_namespace field and has xx_to instead of xx_target_id
1363 if ( $page->getNamespace() !== NS_FILE ) {
1364 // No imagelinks to a non-image page
1365 return false;
1366 }
1367 $title = TitleValue::newFromPage( $page );
1368 $cond = MediaWikiServices::getInstance()->getLinksMigration()->getLinksConditions( 'imagelinks', $title );
1369 $queryBuilder->where( $cond );
1370 } else {
1371 $linkTarget = $page instanceof LinkTarget ? $page : TitleValue::newFromPage( $page );
1372 $targetId = $this->linkTargetLookup->getLinkTargetId( $linkTarget );
1373 if ( !$targetId ) {
1374 return false;
1375 }
1376 $queryBuilder->where( $this->db->expr( "{$prefix}_target_id", '=', $targetId ) );
1377 }
1378 return true;
1379 }
1380
1395 private function applyLinksToFilter(
1396 SelectQueryBuilder $queryBuilder,
1397 PageIdentity $page,
1398 string $linkTable
1399 ): bool {
1400 $linkTarget = $page instanceof LinkTarget ? $page : TitleValue::newFromPage( $page );
1401 $targetId = $this->linkTargetLookup->getLinkTargetId( $linkTarget );
1402 if ( !$targetId ) {
1403 return false;
1404 }
1405
1406 $connProvider = MediaWikiServices::getInstance()->getConnectionProvider();
1407 $dbr = $connProvider->getReplicaDatabase( LinksTable::VIRTUAL_DOMAIN );
1408 $prefix = self::LINK_TABLE_PREFIXES[$linkTable];
1409
1410 $res = $dbr->newSelectQuerybuilder()
1411 ->select( "{$prefix}_from" )
1412 ->from( $linkTable )
1413 ->where( [ "{$prefix}_target_id" => $targetId ] )
1414 ->limit( 5000 )
1415 ->caller( __METHOD__ )
1416 ->fetchFieldValues();
1417
1418 if ( $res === [] ) {
1419 return false;
1420 }
1421
1422 $queryBuilder->where( [ 'rc_cur_id' => $res ] );
1423
1424 return true;
1425 }
1426
1435 private function applyLinksFromCondition(
1436 SelectQueryBuilder $queryBuilder,
1437 PageIdentity $page,
1438 string $linkTable
1439 ): bool {
1440 if ( !$page->getId() ) {
1441 // No links from a non-existent page
1442 return false;
1443 }
1444 $prefix = self::LINK_TABLE_PREFIXES[$linkTable];
1445 $queryBuilder
1446 ->where( [ "{$prefix}_from" => $page->getId() ] )
1447 ->join( 'linktarget', null, [ 'rc_namespace = lt_namespace', 'rc_title = lt_title' ] )
1448 ->join( $linkTable, null, "{$prefix}_target_id = lt_id" );
1449 return true;
1450 }
1451
1466 private function applyLinksFromFilter(
1467 SelectQueryBuilder $queryBuilder,
1468 PageIdentity $page,
1469 string $linkTable
1470 ): bool {
1471 if ( !$page->getId() ) {
1472 // No links from a non-existent page
1473 return false;
1474 }
1475
1476 $connProvider = MediaWikiServices::getInstance()->getConnectionProvider();
1477 $dbr = $connProvider->getReplicaDatabase( LinksTable::VIRTUAL_DOMAIN );
1478 $prefix = self::LINK_TABLE_PREFIXES[$linkTable];
1479
1480 $res = $dbr->newSelectQuerybuilder()
1481 ->select( 'page_id' )
1482 ->from( 'linktarget' )
1483 ->join( $linkTable, null, "{$prefix}_target_id = lt_id" )
1484 ->join( 'page', null, [ 'lt_namespace = page_namespace', 'lt_title = page_title' ] )
1485 ->where( [ "{$prefix}_from" => $page->getId() ] )
1486 ->limit( 5000 )
1487 ->caller( __METHOD__ )
1488 ->fetchFieldValues();
1489
1490 if ( $res === [] ) {
1491 return false;
1492 }
1493
1494 $queryBuilder->where( [ 'rc_cur_id' => $res ] );
1495
1496 return true;
1497 }
1498
1505 private function maybeEmulateUnion( $queries ) {
1506 if ( !$queries ) {
1507 return [];
1508 } elseif ( count( $queries ) === 1 ) {
1509 return $queries[0]->fetchResultSet();
1510 } else {
1511 $rows = [];
1512 $this->emulateUnion( $queries, $this->limit, $rows );
1513 return $rows;
1514 }
1515 }
1516
1524 private function emulateUnion( array $queries, ?int $limit, &$rows ) {
1525 if ( !$this->preparedEmulatedUnion ) {
1526 throw new LogicException(
1527 'emulateUnion() was called but not prepareEmulatedUnion()' );
1528 }
1529 $unsortedRows = [];
1530 foreach ( $queries as $query ) {
1531 foreach ( $query->fetchResultSet() as $row ) {
1532 $unsortedRows[] = $row;
1533 }
1534 }
1535 $this->sortAndTruncate( $unsortedRows, $limit, $rows );
1536 }
1537
1547 public function sortAndTruncate( array $inRows, ?int $limit, &$outRows ) {
1548 usort( $inRows, static fn ( $a, $b ) =>
1549 $b->rc_timestamp <=> $a->rc_timestamp ?:
1550 $b->rc_id <=> $a->rc_id
1551 );
1552 // Remove duplicates and slice
1553 $prevId = null;
1554 $numOut = 0;
1555 foreach ( $inRows as $row ) {
1556 if ( $prevId !== $row->rc_id ) {
1557 $outRows[] = $row;
1558 $numOut++;
1559 if ( $numOut === $limit ) {
1560 break;
1561 }
1562 }
1563 $prevId = $row->rc_id;
1564 }
1565 }
1566
1578 private function shouldDoPartitioning(): bool {
1579 return $this->forcePartitioning
1580 || ( $this->enablePartitioning
1581 && $this->limit !== null
1582 && $this->minTimestamp !== null
1583 && $this->joinOrderHint === self::JOIN_ORDER_OTHER
1584 && $this->sort === self::SORT_TIMESTAMP_DESC
1585 && $this->estimateSize() > self::PARTITION_THRESHOLD
1586 );
1587 }
1588
1595 private function estimateSize() {
1596 $now = ConvertibleTimestamp::time();
1597 $min = (int)ConvertibleTimestamp::convert( TS::UNIX, $this->minTimestamp );
1598 $period = min( $now - $min, $this->rcMaxAge );
1599 return $this->rcStats->getIdDelta() * $this->density * $period;
1600 }
1601
1606 private function doPartitionUnion( array $queries ) {
1607 if ( !$this->preparedEmulatedUnion ) {
1608 throw new LogicException(
1609 'doPartitionUnion() was called but not prepareEmulatedUnion()' );
1610 }
1611 $unsortedRows = [];
1612 foreach ( $queries as $query ) {
1613 $this->doPartitionQuery( $query, $unsortedRows );
1614 }
1615 if ( count( $queries ) > 1 ) {
1616 $rows = [];
1617 $this->sortAndTruncate( $unsortedRows, $this->limit, $rows );
1618 return $rows;
1619 } else {
1620 return $unsortedRows;
1621 }
1622 }
1623
1633 private function doPartitionQuery( SelectQueryBuilder $sqb, &$rows ) {
1634 $now = ConvertibleTimestamp::time();
1635 $minTime = (int)ConvertibleTimestamp::convert( TS::UNIX,
1636 $this->minTimestamp ?? $now - $this->rcMaxAge );
1637 $limit = $this->limit ?? 10_000;
1638 $rcSize = $this->rcStats->getIdDelta();
1639
1640 $this->logger->debug( 'Beginning partition request with density={density}, period={period}',
1641 [
1642 'period' => $now - $minTime,
1643 'limit' => $limit,
1644 'density' => $this->density,
1645 'rcSize' => $rcSize,
1646 ]
1647 );
1648
1649 $partitioner = new TimestampRangePartitioner( $minTime, $now, $limit,
1650 null, $this->density, $rcSize, $this->rcMaxAge );
1651 do {
1652 [ $min, $max, $limit ] = $partitioner->getNextPartition();
1653
1654 $partitionQuery = clone $sqb;
1655 if ( $min !== null ) {
1656 $partitionQuery->where( $this->db->expr(
1657 'rc_timestamp', '>=', $this->db->timestamp( $min ) ) );
1658 }
1659 if ( $max !== null ) {
1660 $partitionQuery->where( $this->db->expr(
1661 'rc_timestamp', '<=', $this->db->timestamp( $max ) ) );
1662 }
1663 $partitionQuery->limit( $limit );
1664
1665 $row = null;
1666 $res = $partitionQuery->fetchResultSet();
1667 foreach ( $res as $row ) {
1668 $rows[] = $row;
1669 }
1670 $partitioner->notifyResult(
1671 $row ? (int)ConvertibleTimestamp::convert( TS::UNIX, $row->rc_timestamp ) : null,
1672 $res->numRows()
1673 );
1674 } while ( !$partitioner->isDone() );
1675
1676 $m = $partitioner->getMetrics();
1677 $this->logger->debug( 'Finished partition request: ' .
1678 'got {actualRows} rows in {queryCount} queries, period={actualPeriod}',
1679 $m
1680 );
1681
1682 $this->statsFactory->getCounter( 'ChangesListQuery_partition_queries_total' )
1683 ->incrementBy( $m['queryCount'] );
1684 $this->statsFactory->getCounter( 'ChangesListQuery_partition_requests_total' )
1685 ->increment();
1686 $this->statsFactory->getCounter( 'ChangesListQuery_partition_rows_total' )
1687 ->incrementBy( $m['actualRows' ] );
1688 $this->statsFactory->getCounter( 'ChangesListQuery_partition_overrun_total' )
1689 ->incrementBy(
1690 $m['actualRows'] * ( $m['queryPeriod'] / ( $m['actualPeriod'] ?: 1 ) - 1 )
1691 );
1692 }
1693
1701 private function getHighlightsFromRow( stdClass $row ) {
1702 $activeHighlights = [];
1703 foreach ( $this->highlights as $name => $highlights ) {
1704 foreach ( $highlights as $hl ) {
1705 $module = $this->getFilter( $hl->moduleName );
1706 if ( $module->evaluate( $row, $hl->value ) === $hl->sense ) {
1707 $activeHighlights[$name] = true;
1708 }
1709 }
1710 }
1711 return $activeHighlights;
1712 }
1713
1714 private function getFilter( string $name ): ChangesListCondition {
1715 if ( !isset( $this->filterModules[$name] ) ) {
1716 throw new InvalidArgumentException( "Unknown filter module \"$name\"" );
1717 }
1718 return $this->filterModules[$name];
1719 }
1720
1727 public function where( IExpression $expr ): self {
1728 $this->conds[] = $expr;
1729 return $this;
1730 }
1731
1738 public function caller( string $caller ): self {
1739 $this->caller = $caller;
1740 return $this;
1741 }
1742
1744 public function joinForFields( string $table ): ChangesListJoinBuilder {
1745 return $this->getJoin( $table )->forFields( $this );
1746 }
1747
1749 public function joinForConds( string $table ): ChangesListJoinBuilder {
1750 return $this->getJoin( $table )->forConds( $this );
1751 }
1752
1753 private function getJoin( string $name ): ChangesListJoinModule {
1754 if ( !isset( $this->joinModules[$name] ) ) {
1755 throw new InvalidArgumentException( "Unknown join module \"$name\"" );
1756 }
1757 return $this->joinModules[$name];
1758 }
1759
1761 public function distinct(): QueryBackend {
1762 $this->distinct = true;
1763 return $this;
1764 }
1765
1771 public function registerFilter( $name, ChangesListCondition $module ) {
1772 $this->filterModules[$name] = $module;
1773 }
1774
1775}
const NS_FILE
Definition Defines.php:57
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:71
Read-write access to the change_tags table.
A class for passing options to services.
The base class for classes which update a single link table.
Class to simplify the use of log pages.
Definition LogPage.php:34
A class containing constants representing the names of configuration variables.
const RCMaxAge
Name constant for the RCMaxAge setting, for use with Config::get()
const WatchlistExpiry
Name constant for the WatchlistExpiry setting, for use with Config::get()
const EnableChangesListQueryPartitioning
Name constant for the EnableChangesListQueryPartitioning setting, for use with Config::get()
const MiserMode
Name constant for the MiserMode setting, for use with Config::get()
const VirtualDomainsMapping
Name constant for the VirtualDomainsMapping setting, for use with Config::get()
Service locator for MediaWiki core services.
A simple join with a fixed join condition.
Definition BasicJoin.php:15
A filter module which builds conditions for a boolean field.
A tri-state boolean from a field of a potentially left-joined table.
An object encapsulating a single instance of a join on a table.
Build and execute a query on the recentchanges table with optional joins and conditions.
distinct()
Flag that the joins will inadvertently duplicate recentchanges rows and that the query will have to d...
minTimestamp( $timestamp)
Set the minimum (earliest) rc_timestamp value.
sha1Fields()
Add the rev_deleted and rev_slot_pair fields, used by ApiQueryRecentChanges to deliver SHA-1 hashes f...
endAt(string $timestamp, ?int $id=null)
Set the timestamp and ID for the end of the query results.
excludeNamespaces(array $namespaces)
Exclude namespaces by ID.
commentFields()
Add CommentStore fields: rc_comment_text, rc_comment_data, rc_comment_cid.
requireChangeTags( $tagNames)
Require that the change has one of the specified change tags.
maxExecutionTime(float|int|null $time)
Set the maximum query execution time in seconds, or null to disable the time limit.
allowDeletedLogAction()
Override a previous call to excludeDeletedLogAction(), allowing deleted log rows to be shown.
requireLink(string $direction, array $tables, PageIdentity $page)
Require that the changed page links from or to the specified page, via the specified links tables.
enablePartitioning()
Enable query partitioning by timestamp, overriding the config.
adjustDensity( $density)
Adjust the density heuristic by multiplying it by the given factor.This sets the proportion of recent...
legacyMutator(callable $callback)
Add a callback which will be called when building an SQL query.
requireLatest()
Require that the change is the latest change to the page.
addChangeTagSummaryField()
Add the change tag summary field ts_tags.
excludeChangeTags( $tagNames)
Exclude changes matching any of the specified change tags.
highlight(string $name, string $verb, string $moduleName, $value=null)
Add a highlight to the query.
sqbMutator(callable $callback)
Add a callback which will be called with a SelectQueryBuilder during query construction.
requireUser(UserIdentity $user)
Require changes by a specific user.
__construct(private ServiceOptions $config, private RecentChangeLookup $recentChangeLookup, private WatchedItemStoreInterface $watchedItemStore, private TempUserConfig $tempUserConfig, private UserFactory $userFactory, private LinkTargetLookup $linkTargetLookup, private ChangeTagsStore $changeTagsStore, private StatsFactory $statsFactory, private NameTableStore $slotRoleStore, private LoggerInterface $logger, private IReadableDatabase $db, private TableStatsProvider $rcStats,)
sortAndTruncate(array $inRows, ?int $limit, &$outRows)
Sort rows by rc_timestamp/rc_id, remove any duplicates, and then truncate to the current query limit.
where(IExpression $expr)
Add a condition to the query.
excludeDeletedUser()
Exclude rows with the DELETED_USER bit set, unless the configured audience has permission to view suc...
addWatchlistLabelSummaryField()
Add the labels summary field wlm_label_summary.
audience(?Authority $authority)
Set the Authority used for rc_deleted filters.
forceEmptySet()
Set a flag forcing the query to return no rows when it is executed.
requireTitle(LinkTarget|PageReference $title)
Return only changes to a given page.
requireWatched( $watchTypes=[ 'watchedold', 'watchednew'])
Require that the changed page is watched by the watchlist user specified in a call to watchlistUser()...
denseRcSizeThreshold( $threshold)
Set the minimum size of the recentchanges table at which change tag queries will be conditionally mod...
excludeDeletedLogAction()
Exclude rows relating to log entries that have the DELETED_ACTION bit set, unless the configured audi...
watchlistFields( $fields=[ 'wl_user', 'wl_notificationtimestamp', 'we_expiry'])
Add watchlist fields to the query, and the relevant join.
requireNamespaces(array $namespaces)
Require namespaces by ID.
joinForConds(string $table)
Join on the specified table and declare that it will be used to provide fields for the WHERE clause....
isEmptySet()
Check whether forceEmptySet() has been called.
requireSubpageOf(LinkTarget|PageReference $page)
Require that changed titles are subpages of a given page.
excludeWatchlistLabelIds(array $labelIds)
Require that the changed page is not watched with one of the specified watchlist label IDs.
maybeAddWatchlistExpiryField()
Add the we_expiry field and its related join, if watchlist expiry is enabled.
requireWatchlistLabelIds(array $labelIds)
Require that the changed page is watched with one of the specified watchlist label IDs.
const PARTITION_THRESHOLD
Minimum number of estimated rows before timestamp partitioning is considered.
fetchResult()
Execute the query and return the result.
requireSources(array $sources)
Require that the changes come from the specified sources, e.g.
recentChangeFields()
Add fields to the query sufficient for the subsequent construction of RecentChange objects from the r...
excludeUser(UserIdentity $user)
Exclude changes by a specific user.
startAt(string $timestamp, ?int $id=null)
Set the timestamp and ID for the start of the query results.
limit(int $limit)
Set the maximum number of rows to return.
watchlistUser(UserIdentity $user)
Set the user to be used for watchlist joins.
requireSlotChanged(string $role)
Require that a specified slot role was modified.
joinForFields(string $table)
Join on the specified table and declare that it will be used to provide fields for the SELECT clause....
rcUserFields()
Add the rc_user and rc_user_text fields to the query, conventional aliases for actor_user and actor_n...
applyAction(string $verb, string $moduleName, $value=null)
Apply an arbitrary action.
caller(string $caller)
Set the caller name to be passed down to the DBMS.
An equals or not-equals comparison with a field that is known to have a small fixed set of values.
A filter condition module for user experience levels.
A filter condition module which uses equals or not-equals operators.
A filter module which checks if the change actor is registered and "named", i.e.
Check if the recentchange row has been seen by the current watchlist user.
A join on the slots table, mostly to support requireSlotChanged().
Definition SlotsJoin.php:20
Check if the changed title is a subpage of some specified title.
Cache and provide min/max ID and "size" (ID delta) of a table.
Check if a recentchange row is watched by the current watchlist user.
A watchlist join with a settable condition on wl_user.
Utility class for creating and reading rows in the recentchanges table.
Page revision base class.
Exception representing a failure to look up a row from a name table.
Represents the target of a wiki link.
Create User objects.
and(string $field, string $op, $value)
leftJoin( $table, $alias=null, $conds=[])
Left join a table or group of tables.
Raw SQL expression to be used in query builders.
Build SELECT queries with a fluent interface.
fields( $fields)
Add a field or an array of fields to the query.
This is the primary interface for validating metrics definitions, caching defined metrics,...
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, '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, '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, 'PHPSessionHandling'=> 'warn', '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, ], 'AllowSecuritySensitiveOperationIfCannotReauthenticate' => [ 'default' => true, ], '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' => [ ], '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', ], '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', 'PHPSessionHandling' => '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', 'AllowSecuritySensitiveOperationIfCannotReauthenticate' => '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', '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', ], ], ], ], ], 'PHPSessionHandling' => [ 'deprecated' => 'since 1.45 Integration with PHP session handling will be removed in the future', ], 'RawHtmlMessages' => [ 'items' => [ 'type' => 'string', ], ], 'InterwikiLogoOverride' => [ 'items' => [ 'type' => 'string', ], ], 'LegalTitleChars' => [ 'deprecated' => 'since 1.41; use Extension:TitleBlacklist to customize', ], 'ReauthenticateTime' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'AllowSecuritySensitiveOperationIfCannotReauthenticate' => [ 'additionalProperties' => [ 'type' => 'boolean', ], ], '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.', ],]
Represents the target of a wiki link.
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.
This interface represents the authority associated with the current execution context,...
Definition Authority.php:23
Interface for modules implementing a boolean condition which may match a row in a ChangesListResult.
A module encapsulating join conditions for a ChangesListQuery join.
The narrow interface provided to join modules to allow them to declare any dependencies they have on ...
The narrow interface passed to filter modules.
const JOIN_ORDER_RECENTCHANGES
The recentchanges table will likely be first in the join.
Interface for temporary user creation config and name matching.
Interface for objects representing user identity.
A database connection without write operations.
Result wrapper for grabbing data queried from an IDatabase object.