MediaWiki master
PageUpdater.php
Go to the documentation of this file.
1<?php
7namespace MediaWiki\Storage;
8
9use InvalidArgumentException;
10use LogicException;
39use Psr\Log\LoggerInterface;
40use RuntimeException;
41use Wikimedia\Assert\Assert;
42use Wikimedia\NormalizedException\NormalizedException;
46
63class PageUpdater implements PageUpdateCauses {
64
70 public const CONSTRUCTOR_OPTIONS = [
73 ];
74
78 private $author;
79
84 private $wikiPage;
85
89 private $pageIdentity;
90
94 private $derivedDataUpdater;
95
99 private $dbProvider;
100
104 private $revisionStore;
105
109 private $slotRoleRegistry;
110
114 private $contentHandlerFactory;
115
119 private $hookRunner;
120
124 private $hookContainer;
125
127 private $userGroupManager;
128
130 private $titleFormatter;
131
136 private $useAutomaticEditSummaries = true;
137
141 private $rcPatrolStatus = RecentChange::PRC_UNPATROLLED;
142
146 private $usePageCreationLog = true;
147
151 private $forceEmptyRevision = false;
152
157 private $preventChange = false;
158
162 private $tags = [];
163
167 private $slotsUpdate;
168
172 private $status = null;
173
177 private $editResultBuilder;
178
182 private $editResult = null;
183
187 private $serviceOptions;
188
192 private $flags = 0;
193
197 private array $hints = [];
198
200 private $softwareTags = [];
201
203 private $logger;
204
222 public function __construct(
223 UserIdentity $author,
224 PageIdentity $page,
225 DerivedPageDataUpdater $derivedDataUpdater,
226 IConnectionProvider $dbProvider,
227 RevisionStore $revisionStore,
228 SlotRoleRegistry $slotRoleRegistry,
229 IContentHandlerFactory $contentHandlerFactory,
230 HookContainer $hookContainer,
231 UserGroupManager $userGroupManager,
232 TitleFormatter $titleFormatter,
233 ServiceOptions $serviceOptions,
234 array $softwareTags,
235 LoggerInterface $logger,
236 WikiPageFactory $wikiPageFactory
237 ) {
238 $serviceOptions->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
239 $this->serviceOptions = $serviceOptions;
240
241 $this->author = $author;
242 $this->pageIdentity = $page;
243 $this->wikiPage = $wikiPageFactory->newFromTitle( $page );
244 $this->derivedDataUpdater = $derivedDataUpdater;
245 $this->derivedDataUpdater->setCause( self::CAUSE_EDIT );
246
247 $this->dbProvider = $dbProvider;
248 $this->revisionStore = $revisionStore;
249 $this->slotRoleRegistry = $slotRoleRegistry;
250 $this->contentHandlerFactory = $contentHandlerFactory;
251 $this->hookContainer = $hookContainer;
252 $this->hookRunner = new HookRunner( $hookContainer );
253 $this->userGroupManager = $userGroupManager;
254 $this->titleFormatter = $titleFormatter;
255
256 $this->slotsUpdate = new RevisionSlotsUpdate();
257 $this->editResultBuilder = new EditResultBuilder(
258 $revisionStore,
259 $softwareTags,
260 new ServiceOptions(
262 [
265 ]
266 )
267 );
268 $this->softwareTags = $softwareTags;
269 $this->logger = $logger;
270 }
271
279 public function setCause( string $cause ): self {
280 $this->derivedDataUpdater->setCause( $cause );
281 return $this;
282 }
283
292 public function setHints( array $hints ): self {
293 $this->hints = $hints + $this->hints;
294 return $this;
295 }
296
307 public function setFlags( int $flags ) {
308 $this->flags |= $flags;
309 return $this;
310 }
311
322 public function prepareUpdate( int $flags = 0 ): PreparedUpdate {
323 $this->setFlags( $flags );
324
325 // Load the data from the primary database if needed. Needed to check flags.
326 $this->grabParentRevision();
327 if ( !$this->derivedDataUpdater->isUpdatePrepared() ) {
328 // Avoid statsd noise and wasted cycles check the edit stash (T136678)
329 $useStashed = !( ( $this->flags & EDIT_INTERNAL ) || ( $this->flags & EDIT_FORCE_BOT ) );
330 // Prepare the update. This performs PST and generates the canonical ParserOutput.
331 $this->derivedDataUpdater->prepareContent(
332 $this->author,
333 $this->slotsUpdate,
334 $useStashed
335 );
336 }
337
338 return $this->derivedDataUpdater;
339 }
340
346 private static function toLegacyUser( UserIdentity $user ) {
347 return User::newFromIdentity( $user );
348 }
349
357 public function updateAuthor( UserIdentity $author ) {
358 if ( $this->author->getName() !== $author->getName() ) {
359 throw new InvalidArgumentException( 'Cannot replace the author with an author ' .
360 'of a different name, since DerivedPageDataUpdater may have stored the ' .
361 'old name.' );
362 }
363 $this->author = $author;
364 }
365
374 public function setUseAutomaticEditSummaries( $useAutomaticEditSummaries ) {
375 $this->useAutomaticEditSummaries = $useAutomaticEditSummaries;
376 return $this;
377 }
378
389 public function setRcPatrolStatus( $status ) {
390 $this->rcPatrolStatus = $status;
391 return $this;
392 }
393
402 public function setUsePageCreationLog( $use ) {
403 $this->usePageCreationLog = $use;
404 return $this;
405 }
406
425 public function setForceEmptyRevision( bool $forceEmptyRevision ): self {
426 $this->forceEmptyRevision = $forceEmptyRevision;
427
428 if ( $forceEmptyRevision ) {
429 // XXX: throw if there is no current/parent revision?
430 $original = $this->grabParentRevision();
431 $this->setOriginalRevisionId( $original ? $original->getId() : false );
432 }
433
434 $this->derivedDataUpdater->setForceEmptyRevision( $forceEmptyRevision );
435 return $this;
436 }
437
439 private function getWikiId() {
440 return $this->revisionStore->getWikiId();
441 }
442
446 public function getPage(): PageIdentity {
447 return $this->pageIdentity;
448 }
449
453 private function getTitle() {
454 // NOTE: eventually, this won't use WikiPage any more
455 return $this->wikiPage->getTitle();
456 }
457
461 private function getWikiPage() {
462 // NOTE: eventually, this won't use WikiPage any more
463 return $this->wikiPage;
464 }
465
499 public function hasEditConflict( $expectedParentRevision ) {
500 $parent = $this->grabParentRevision();
501 $parentId = $parent ? $parent->getId() : 0;
502
503 return $parentId !== $expectedParentRevision;
504 }
505
532 public function grabParentRevision() {
533 return $this->derivedDataUpdater->grabCurrentRevision();
534 }
535
543 public function setContent( $role, Content $content ) {
544 $this->ensureRoleAllowed( $role );
545
546 $this->slotsUpdate->modifyContent( $role, $content );
547 return $this;
548 }
549
556 public function setSlot( SlotRecord $slot ) {
557 $this->ensureRoleAllowed( $slot->getRole() );
558
559 $this->slotsUpdate->modifySlot( $slot );
560 return $this;
561 }
562
578 public function inheritSlot( SlotRecord $originalSlot ) {
579 // NOTE: slots can be inherited even if the role is not "allowed" on the title.
580 // NOTE: this slot is inherited from some other revision, but it's
581 // a "modified" slot for the RevisionSlotsUpdate and DerivedPageDataUpdater,
582 // since it's not implicitly inherited from the parent revision.
583 $inheritedSlot = SlotRecord::newInherited( $originalSlot );
584 $this->slotsUpdate->modifySlot( $inheritedSlot );
585 return $this;
586 }
587
597 public function removeSlot( $role ) {
598 $this->ensureRoleNotRequired( $role );
599
600 $this->slotsUpdate->removeSlot( $role );
601 }
602
613 public function setOriginalRevisionId( $originalRevId ) {
614 $this->editResultBuilder->setOriginalRevision( $originalRevId );
615 return $this;
616 }
617
630 public function markAsRevert(
631 int $revertMethod,
632 int $newestRevertedRevId,
633 ?int $revertAfterRevId = null
634 ) {
635 $this->editResultBuilder->markAsRevert(
636 $revertMethod, $newestRevertedRevId, $revertAfterRevId
637 );
638 return $this;
639 }
640
648 public function getEditResult(): ?EditResult {
649 return $this->editResult;
650 }
651
659 public function addTag( string $tag ) {
660 $this->tags[] = trim( $tag );
661 return $this;
662 }
663
671 public function addTags( array $tags ) {
672 Assert::parameterElementType( 'string', $tags, '$tags' );
673 foreach ( $tags as $tag ) {
674 $this->addTag( $tag );
675 }
676 return $this;
677 }
678
687 public function addSoftwareTag( string $tag ): self {
688 if ( in_array( $tag, $this->softwareTags ) ) {
689 $this->addTag( $tag );
690 }
691 return $this;
692 }
693
699 public function getExplicitTags() {
700 return $this->tags;
701 }
702
706 private function computeEffectiveTags() {
707 $tags = $this->tags;
708 $editResult = $this->getEditResult();
709
710 foreach ( $this->slotsUpdate->getModifiedRoles() as $role ) {
711 $old_content = $this->getParentContent( $role );
712
713 $handler = $this->getContentHandler( $role );
714 $content = $this->slotsUpdate->getModifiedSlot( $role )->getContent();
715
716 // TODO: MCR: Do this for all slots. Also add tags for removing roles!
717 $tag = $handler->getChangeTag( $old_content, $content, $this->flags );
718 // If there is no applicable tag, null is returned, so we need to check
719 if ( $tag ) {
720 $tags[] = $tag;
721 }
722 }
723
724 $tags = array_merge( $tags, $editResult->getRevertTags() );
725
726 return array_unique( $tags );
727 }
728
736 private function getParentContent( $role ) {
737 $parent = $this->grabParentRevision();
738
739 if ( $parent && $parent->hasSlot( $role ) ) {
740 return $parent->getContent( $role, RevisionRecord::RAW );
741 }
742
743 return null;
744 }
745
750 private function getContentHandler( $role ) {
751 if ( $this->slotsUpdate->isModifiedSlot( $role ) ) {
752 $slot = $this->slotsUpdate->getModifiedSlot( $role );
753 } else {
754 $parent = $this->grabParentRevision();
755
756 if ( $parent ) {
757 $slot = $parent->getSlot( $role, RevisionRecord::RAW );
758 } else {
759 throw new RevisionAccessException(
760 'No such slot: {role}',
761 [ 'role' => $role ]
762 );
763 }
764 }
765
766 return $this->contentHandlerFactory->getContentHandler( $slot->getModel() );
767 }
768
772 private function makeAutoSummary() {
773 if ( !$this->useAutomaticEditSummaries || ( $this->flags & EDIT_AUTOSUMMARY ) === 0 ) {
774 return CommentStoreComment::newUnsavedComment( '' );
775 }
776
777 // NOTE: this generates an auto-summary for SOME RANDOM changed slot!
778 // TODO: combine auto-summaries for multiple slots!
779 // XXX: this logic should not be in the storage layer!
780 $roles = $this->slotsUpdate->getModifiedRoles();
781 $role = reset( $roles );
782
783 if ( $role === false ) {
784 return CommentStoreComment::newUnsavedComment( '' );
785 }
786
787 $handler = $this->getContentHandler( $role );
788 $content = $this->slotsUpdate->getModifiedSlot( $role )->getContent();
789 $old_content = $this->getParentContent( $role );
790 $summary = $handler->getAutosummary( $old_content, $content, $this->flags );
791
792 return CommentStoreComment::newUnsavedComment( $summary );
793 }
794
810 public function saveDummyRevision( $summary, int $flags = 0 ) {
812
813 $this->setForceEmptyRevision( true );
814 $rev = $this->saveRevision( $summary, $flags );
815
816 if ( $rev === null ) {
817 throw new NormalizedException( 'Failed to create dummy revision on ' .
818 '{page} (page ID {id})',
819 [
820 'page' => (string)$this->getPage(),
821 'id' => (string)$this->getPage()->getId(),
822 ]
823 );
824 }
825
826 return $rev;
827 }
828
858 public function saveRevision( $summary, int $flags = 0 ) {
859 Assert::parameterType(
860 [ 'string', CommentStoreComment::class, ],
861 $summary,
862 '$summary'
863 );
864
865 if ( is_string( $summary ) ) {
866 $summary = CommentStoreComment::newUnsavedComment( $summary );
867 }
868
869 $this->setFlags( $flags );
870
871 if ( $this->wasCommitted() ) {
872 throw new RuntimeException(
873 'saveRevision() or updateRevision() has already been called on this PageUpdater!'
874 );
875 }
876
877 // Low-level check
878 if ( $this->getPage()->getDBkey() === '' ) {
879 throw new RuntimeException( 'Something is trying to edit an article with an empty title' );
880 }
881
882 // NOTE: slots can be inherited even if the role is not "allowed" on the title.
883 $status = PageUpdateStatus::newGood();
884 $this->checkAllRolesAllowed(
885 $this->slotsUpdate->getModifiedRoles(),
886 $status
887 );
888 $this->checkNoRolesRequired(
889 $this->slotsUpdate->getRemovedRoles(),
890 $status
891 );
892
893 if ( !$status->isOK() ) {
894 return null;
895 }
896
897 // Make sure the given content is allowed in the respective slots of this page
898 foreach ( $this->slotsUpdate->getModifiedRoles() as $role ) {
899 $slot = $this->slotsUpdate->getModifiedSlot( $role );
900 $roleHandler = $this->slotRoleRegistry->getRoleHandler( $role );
901
902 if ( !$roleHandler->isAllowedModel( $slot->getModel(), $this->getPage() ) ) {
903 $contentHandler = $this->contentHandlerFactory
904 ->getContentHandler( $slot->getModel() );
905 $this->status = PageUpdateStatus::newFatal( 'content-not-allowed-here',
906 ContentHandler::getLocalizedName( $contentHandler->getModelID() ),
907 $this->titleFormatter->getPrefixedText( $this->getPage() ),
908 wfMessage( $roleHandler->getNameMessageKey() )
909 // TODO: defer message lookup to caller
910 );
911 return null;
912 }
913 }
914
915 // Load the data from the primary database if needed. Needed to check flags.
916 // NOTE: This grabs the parent revision as the CAS token, if grabParentRevision
917 // wasn't called yet. If the page is modified by another process before we are done with
918 // it, this method must fail (with status 'edit-conflict')!
919 // NOTE: The parent revision may be different from the edit's base revision.
920 $this->prepareUpdate();
921
922 // Detect whether update or creation should be performed.
923 if ( !( $this->flags & EDIT_NEW ) && !( $this->flags & EDIT_UPDATE ) ) {
924 $this->flags |= ( $this->derivedDataUpdater->pageExisted() ) ? EDIT_UPDATE : EDIT_NEW;
925 }
926
927 // Trigger pre-save hook (using provided edit summary)
928 $renderedRevision = $this->derivedDataUpdater->getRenderedRevision();
929 $hookStatus = PageUpdateStatus::newGood( [] );
930 $allowedByHook = $this->hookRunner->onMultiContentSave(
931 $renderedRevision, $this->author, $summary, $this->flags, $hookStatus
932 );
933 if ( $allowedByHook && $this->hookContainer->isRegistered( 'PageContentSave' ) ) {
934 // Also run the legacy hook.
935 // NOTE: WikiPage should only be used for the legacy hook,
936 // and only if something uses the legacy hook.
937 $mainContent = $this->derivedDataUpdater->getSlots()->getContent( SlotRecord::MAIN );
938
939 $legacyUser = self::toLegacyUser( $this->author );
940
941 // Deprecated since 1.35.
942 $allowedByHook = $this->hookRunner->onPageContentSave(
943 $this->getWikiPage(), $legacyUser, $mainContent, $summary,
944 (bool)( $this->flags & EDIT_MINOR ), null, null, $this->flags, $hookStatus
945 );
946 }
947
948 if ( !$allowedByHook ) {
949 // The hook has prevented this change from being saved.
950 if ( $hookStatus->isOK() ) {
951 // Hook returned false but didn't call fatal(); use generic message
952 $hookStatus->fatal( 'edit-hook-aborted' );
953 }
954
955 $this->status = $hookStatus;
956 $this->logger->info( "Hook prevented page save", [ 'status' => $hookStatus ] );
957 return null;
958 }
959
960 // Provide autosummaries if one is not provided and autosummaries are enabled
961 // XXX: $summary == null seems logical, but the empty string may actually come from the user
962 // XXX: Move this logic out of the storage layer! It does not belong here! Use a callback?
963 if ( $summary->text === '' && $summary->data === null ) {
964 $summary = $this->makeAutoSummary();
965 }
966
967 // Actually create the revision and create/update the page.
968 // Do NOT yet set $this->status!
969 if ( $this->flags & EDIT_UPDATE ) {
970 $status = $this->doModify( $summary );
971 } else {
972 $status = $this->doCreate( $summary );
973 }
974
975 // Promote user to any groups they meet the criteria for
976 DeferredUpdates::addCallableUpdate( function () {
977 $this->userGroupManager->addUserToAutopromoteOnceGroups( $this->author, 'onEdit' );
978 // Also run 'onView' for backwards compatibility
979 $this->userGroupManager->addUserToAutopromoteOnceGroups( $this->author, 'onView' );
980 } );
981
982 // NOTE: set $this->status only after all hooks have been called,
983 // so wasCommitted doesn't return true when called indirectly from a hook handler!
984 $this->status = $status;
985
986 // TODO: replace bad status with Exceptions!
987 return $this->status
988 ? $this->status->getNewRevision()
989 : null;
990 }
991
1003 public function updateRevision( int $revId = 0 ) {
1004 if ( $this->wasCommitted() ) {
1005 throw new RuntimeException(
1006 'saveRevision() or updateRevision() has already been called on this PageUpdater!'
1007 );
1008 }
1009
1010 // Low-level check
1011 if ( $this->getPage()->getDBkey() === '' ) {
1012 throw new RuntimeException( 'Something is trying to edit an article with an empty title' );
1013 }
1014
1015 $status = PageUpdateStatus::newGood();
1016 $this->checkAllRolesAllowed(
1017 $this->slotsUpdate->getModifiedRoles(),
1018 $status
1019 );
1020 $this->checkAllRolesDerived(
1021 $this->slotsUpdate->getModifiedRoles(),
1022 $status
1023 );
1024 $this->checkAllRolesDerived(
1025 $this->slotsUpdate->getRemovedRoles(),
1026 $status
1027 );
1028
1029 if ( $revId === 0 ) {
1030 $revision = $this->grabParentRevision();
1031 } else {
1032 $revision = $this->revisionStore->getRevisionById( $revId, IDBAccessObject::READ_LATEST );
1033 }
1034 if ( $revision === null ) {
1035 $status->fatal( 'edit-gone-missing' );
1036 }
1037
1038 if ( !$status->isOK() ) {
1039 $this->status = $status;
1040 return;
1041 }
1042
1043 // Make sure the given content is allowed in the respective slots of this page
1044 foreach ( $this->slotsUpdate->getModifiedRoles() as $role ) {
1045 $slot = $this->slotsUpdate->getModifiedSlot( $role );
1046 $roleHandler = $this->slotRoleRegistry->getRoleHandler( $role );
1047
1048 if ( !$roleHandler->isAllowedModel( $slot->getModel(), $this->getPage() ) ) {
1049 $contentHandler = $this->contentHandlerFactory
1050 ->getContentHandler( $slot->getModel() );
1051 $this->status = PageUpdateStatus::newFatal(
1052 'content-not-allowed-here',
1053 ContentHandler::getLocalizedName( $contentHandler->getModelID() ),
1054 $this->titleFormatter->getPrefixedText( $this->getPage() ),
1055 wfMessage( $roleHandler->getNameMessageKey() )
1056 // TODO: defer message lookup to caller
1057 );
1058 return;
1059 }
1060 }
1061
1062 // XXX: do we need PST?
1063
1064 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable revision is checked
1065 $this->status = $this->doUpdate( $revision );
1066 }
1067
1073 public function wasCommitted() {
1074 return $this->status !== null;
1075 }
1076
1100 public function getStatus(): PageUpdateStatus {
1101 if ( !$this->status ) {
1102 throw new LogicException(
1103 'getStatus() is undefined before saveRevision() or updateRevision() have been called'
1104 );
1105 }
1106 return $this->status;
1107 }
1108
1117 public function wasSuccessful() {
1118 return $this->status && $this->status->isOK();
1119 }
1120
1126 public function isNew() {
1127 return $this->status && $this->status->wasPageCreated();
1128 }
1129
1137 public function isUnchanged() {
1138 return !$this->wasRevisionCreated();
1139 }
1140
1146 public function isChange() {
1147 return $this->derivedDataUpdater->isChange();
1148 }
1149
1155 public function preventChange() {
1156 $this->preventChange = true;
1157 return $this;
1158 }
1159
1170 public function wasRevisionCreated(): bool {
1171 return $this->status
1172 && $this->status->wasRevisionCreated();
1173 }
1174
1181 public function getNewRevision() {
1182 return $this->status
1183 ? $this->status->getNewRevision()
1184 : null;
1185 }
1186
1200 private function makeNewRevision(
1201 CommentStoreComment $comment,
1202 PageUpdateStatus $status
1203 ) {
1204 $title = $this->getTitle();
1205 $parent = $this->grabParentRevision();
1206
1207 // XXX: we expect to get a MutableRevisionRecord here, but that's a bit brittle!
1208 // TODO: introduce something like an UnsavedRevisionFactory service instead!
1210 $rev = $this->derivedDataUpdater->getRevision();
1211 '@phan-var MutableRevisionRecord $rev';
1212
1213 // Avoid fatal error when the Title's ID changed, T204793
1214 if (
1215 $rev->getPageId() !== null && $title->exists()
1216 && $rev->getPageId() !== $title->getArticleID()
1217 ) {
1218 $titlePageId = $title->getArticleID();
1219 $revPageId = $rev->getPageId();
1220 $masterPageId = $title->getArticleID( IDBAccessObject::READ_LATEST );
1221
1222 if ( $revPageId === $masterPageId ) {
1223 wfWarn( __METHOD__ . ": Encountered stale Title object: old ID was $titlePageId, "
1224 . "continuing with new ID from primary DB, $masterPageId" );
1225 } else {
1226 throw new InvalidArgumentException(
1227 "Revision inherited page ID $revPageId from its parent, "
1228 . "but the provided Title object belongs to page ID $masterPageId"
1229 );
1230 }
1231 }
1232
1233 if ( $parent ) {
1234 $oldid = $parent->getId();
1235 $rev->setParentId( $oldid );
1236
1237 if ( $title->getArticleID() !== $parent->getPageId() ) {
1238 wfWarn( __METHOD__ . ': Encountered stale Title object with no page ID! '
1239 . 'Using page ID from parent revision: ' . $parent->getPageId() );
1240 }
1241 } else {
1242 $oldid = 0;
1243 }
1244
1245 $rev->setComment( $comment );
1246 $rev->setUser( $this->author );
1247 $rev->setMinorEdit( ( $this->flags & EDIT_MINOR ) > 0 );
1248
1249 foreach ( $rev->getSlots()->getSlots() as $slot ) {
1250 $content = $slot->getContent();
1251
1252 // XXX: We may push this up to the "edit controller" level, see T192777.
1253 $contentHandler = $this->contentHandlerFactory->getContentHandler( $content->getModel() );
1254 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable getId is not null here
1255 $validationParams = new ValidationParams( $this->getPage(), $this->flags, $oldid );
1256 $prepStatus = $contentHandler->validateSave( $content, $validationParams );
1257
1258 // TODO: MCR: record which problem arose in which slot.
1259 $status->merge( $prepStatus );
1260 }
1261
1262 $this->checkAllRequiredRoles(
1263 $rev->getSlotRoles(),
1264 $status
1265 );
1266
1267 return $rev;
1268 }
1269
1277 private function buildEditResult( RevisionRecord $revision, bool $isNew ) {
1278 $this->editResultBuilder->setRevisionRecord( $revision );
1279 $this->editResultBuilder->setIsNew( $isNew );
1280 $this->editResult = $this->editResultBuilder->buildEditResult();
1281 }
1282
1294 private function doUpdate( RevisionRecord $revision ): PageUpdateStatus {
1295 $currentRevision = $this->grabParentRevision();
1296 if ( !$currentRevision ) {
1297 // Article gone missing
1298 return PageUpdateStatus::newFatal( 'edit-gone-missing' );
1299 }
1300
1301 $dbw = $this->dbProvider->getPrimaryDatabase( $this->getWikiId() );
1302 $dbw->startAtomic( __METHOD__ );
1303
1304 $slots = $this->revisionStore->updateSlotsOn( $revision, $this->slotsUpdate, $dbw );
1305
1306 // Return the slots and revision to the caller
1307 $newRevisionRecord = MutableRevisionRecord::newUpdatedRevisionRecord( $revision, $slots );
1308 $status = PageUpdateStatus::newGood( [
1309 'revision-record' => $newRevisionRecord,
1310 'slots' => $slots,
1311 ] );
1312
1313 $isCurrent = $revision->getId( $this->getWikiId() ) ===
1314 $currentRevision->getId( $this->getWikiId() );
1315
1316 if ( $isCurrent ) {
1317 // Update page_touched
1318 $this->getTitle()->invalidateCache( $newRevisionRecord->getTimestamp() );
1319
1320 $this->buildEditResult( $newRevisionRecord, false );
1321
1322 // NOTE: don't trigger a PageLatestRevisionChanged event!
1323 $wikiPage = $this->getWikiPage(); // TODO: use for legacy hooks only!
1324 $this->prepareDerivedDataUpdater(
1325 $wikiPage,
1326 $newRevisionRecord,
1327 $revision->getComment(),
1328 [],
1329 [
1330 PageLatestRevisionChangedEvent::FLAG_SILENT => true,
1331 PageLatestRevisionChangedEvent::FLAG_IMPLICIT => true,
1332 'emitEvents' => false,
1333 ]
1334 );
1335
1336 $this->scheduleAtomicSectionUpdate(
1337 $dbw,
1338 $wikiPage,
1339 $newRevisionRecord,
1340 $revision->getComment(),
1341 [ 'changed' => false ]
1342 );
1343 }
1344
1345 // Mark the earliest point where the transaction round can be committed in CLI mode.
1346 // We want to make sure that the event was bound to a round of transactions. We also
1347 // want the deferred update to enqueue similarly in both web and CLI modes, in order
1348 // to simplify testing assertions.
1349 $dbw->endAtomic( __METHOD__ );
1350
1351 return $status;
1352 }
1353
1358 private function doModify( CommentStoreComment $summary ): PageUpdateStatus {
1359 $wikiPage = $this->getWikiPage(); // TODO: use for legacy hooks only!
1360
1361 // Update article, but only if changed.
1362 $status = PageUpdateStatus::newEmpty( false );
1363
1364 $oldRev = $this->grabParentRevision();
1365 $oldid = $oldRev ? $oldRev->getId() : 0;
1366
1367 if ( !$oldRev ) {
1368 // Article gone missing
1369 return $status->fatal( 'edit-gone-missing' );
1370 }
1371
1372 $newRevisionRecord = $this->makeNewRevision(
1373 $summary,
1374 $status
1375 );
1376
1377 if ( !$status->isOK() ) {
1378 return $status;
1379 }
1380
1381 $now = $newRevisionRecord->getTimestamp();
1382
1383 $changed = $this->derivedDataUpdater->isChange();
1384
1385 if ( $changed ) {
1386 if ( $this->forceEmptyRevision ) {
1387 throw new LogicException(
1388 "Content was changed even though forceEmptyRevision() was called."
1389 );
1390 }
1391 if ( $this->preventChange ) {
1392 throw new LogicException(
1393 "Content was changed even though preventChange() was called."
1394 );
1395 }
1396 }
1397
1398 // We build the EditResult before the $change if/else branch in order to pass
1399 // the correct $newRevisionRecord to EditResultBuilder. In case this is a null
1400 // edit, $newRevisionRecord will be later overridden to its parent revision, which
1401 // would confuse EditResultBuilder.
1402 if ( !$changed ) {
1403 // This is a null edit, ensure original revision ID is set properly
1404 $this->editResultBuilder->setOriginalRevision( $oldRev );
1405 }
1406 $this->buildEditResult( $newRevisionRecord, false );
1407
1408 $dbw = $this->dbProvider->getPrimaryDatabase( $this->getWikiId() );
1409 $dbw->startAtomic( __METHOD__ );
1410
1411 if ( $changed || $this->forceEmptyRevision ) {
1412 // Get the latest page_latest value while locking it.
1413 // Do a CAS style check to see if it's the same as when this method
1414 // started. If it changed then bail out before touching the DB.
1415 $latestNow = $wikiPage->lockAndGetLatest(); // TODO: move to storage service, pass DB
1416 if ( $latestNow != $oldid ) {
1417 // We don't need to roll back, since we did not modify the database yet.
1418 // XXX: Or do we want to rollback, any transaction started by calling
1419 // code will fail? If we want that, we should probably throw an exception.
1420 $dbw->endAtomic( __METHOD__ );
1421
1422 // Page updated or deleted in the mean time
1423 return $status->fatal( 'edit-conflict' );
1424 }
1425
1426 // At this point we are now committed to returning an OK
1427 // status unless some DB query error or other exception comes up.
1428 // This way callers don't have to call rollback() if $status is bad
1429 // unless they actually try to catch exceptions (which is rare).
1430
1431 // Save revision content and meta-data
1432 $newRevisionRecord = $this->revisionStore->insertRevisionOn( $newRevisionRecord, $dbw );
1433
1434 // Update page_latest and friends to reflect the new revision
1435 // TODO: move to storage service
1436 $wasRedirect = $this->derivedDataUpdater->wasRedirect();
1437 if ( !$wikiPage->updateRevisionOn( $dbw, $newRevisionRecord, null, $wasRedirect ) ) {
1438 throw new PageUpdateException( "Failed to update page row to use new revision." );
1439 }
1440
1441 $editResult = $this->getEditResult();
1442 $tags = $this->computeEffectiveTags();
1443
1444 if ( !$this->updatesSuppressed() ) {
1445 $this->hookRunner->onRevisionFromEditComplete(
1446 $wikiPage,
1447 $newRevisionRecord,
1448 $editResult->getOriginalRevisionId(),
1449 $this->author,
1450 $tags
1451 );
1452 }
1453
1454 $this->prepareDerivedDataUpdater(
1455 $wikiPage,
1456 $newRevisionRecord,
1457 $summary,
1458 $tags
1459 );
1460
1461 // Return the new revision to the caller
1462 $status->setNewRevision( $newRevisionRecord );
1463
1464 // Notify the dispatcher of the PageLatestRevisionChangedEvent during the transaction round
1465 $this->emitEvents();
1466 } else {
1467 // T34948: revision ID must be set to page {{REVISIONID}} and
1468 // related variables correctly. Likewise for {{REVISIONUSER}} (T135261).
1469 // Since we don't insert a new revision into the database, the least
1470 // error-prone way is to reuse given old revision.
1471 $newRevisionRecord = $oldRev;
1472
1473 $this->prepareDerivedDataUpdater(
1474 $wikiPage,
1475 $newRevisionRecord,
1476 $summary,
1477 [],
1478 [ 'changed' => false ]
1479 );
1480
1481 $status->warning( 'edit-no-change' );
1482 // Update page_touched as updateRevisionOn() was not called.
1483 // Other cache updates are managed in WikiPage::onArticleEdit()
1484 // via WikiPage::doEditUpdates().
1485 $this->getTitle()->invalidateCache( $now );
1486
1487 // Notify the dispatcher of the PageLatestRevisionChangedEvent during the transaction round
1488 $this->emitEvents();
1489 }
1490
1491 // Schedule the secondary updates to run after the transaction round commits.
1492 // NOTE: the updates have to be processed before sending the response to the client
1493 // (DeferredUpdates::PRESEND), otherwise the client may already be following the
1494 // HTTP redirect to the standard view before derived data has been created - most
1495 // importantly, before the parser cache has been updated. This would cause the
1496 // content to be parsed a second time, or may cause stale content to be shown.
1497 $this->scheduleAtomicSectionUpdate(
1498 $dbw,
1499 $wikiPage,
1500 $newRevisionRecord,
1501 $summary,
1502 [ 'changed' => $changed, ]
1503 );
1504
1505 // Mark the earliest point where the transaction round can be committed in CLI mode.
1506 // We want to make sure that the event was bound to a round of transactions. We also
1507 // want the deferred update to enqueue similarly in both web and CLI modes, in order
1508 // to simplify testing assertions.
1509 $dbw->endAtomic( __METHOD__ );
1510
1511 return $status;
1512 }
1513
1518 private function doCreate( CommentStoreComment $summary ): PageUpdateStatus {
1519 if ( $this->preventChange ) {
1520 throw new LogicException(
1521 "Content was changed even though preventChange() was called."
1522 );
1523 }
1524 $wikiPage = $this->getWikiPage(); // TODO: use for legacy hooks only!
1525
1526 if ( !$this->derivedDataUpdater->getSlots()->hasSlot( SlotRecord::MAIN ) ) {
1527 throw new PageUpdateException( 'Must provide a main slot when creating a page!' );
1528 }
1529
1530 $status = PageUpdateStatus::newEmpty( true );
1531
1532 $newRevisionRecord = $this->makeNewRevision(
1533 $summary,
1534 $status
1535 );
1536
1537 if ( !$status->isOK() ) {
1538 return $status;
1539 }
1540
1541 $this->buildEditResult( $newRevisionRecord, true );
1542 $now = $newRevisionRecord->getTimestamp();
1543
1544 $dbw = $this->dbProvider->getPrimaryDatabase( $this->getWikiId() );
1545 $dbw->startAtomic( __METHOD__ );
1546
1547 // Add the page record unless one already exists for the title
1548 // TODO: move to storage service
1549 $newid = $wikiPage->insertOn( $dbw );
1550 if ( $newid === false ) {
1551 $dbw->endAtomic( __METHOD__ );
1552 return $status->fatal( 'edit-already-exists' );
1553 }
1554
1555 // At this point we are now committed to returning an OK
1556 // status unless some DB query error or other exception comes up.
1557 // This way callers don't have to call rollback() if $status is bad
1558 // unless they actually try to catch exceptions (which is rare).
1559 $newRevisionRecord->setPageId( $newid );
1560
1561 // Save the revision text...
1562 $newRevisionRecord = $this->revisionStore->insertRevisionOn( $newRevisionRecord, $dbw );
1563
1564 // Update the page record with revision data
1565 // TODO: move to storage service
1566 if ( !$wikiPage->updateRevisionOn( $dbw, $newRevisionRecord, 0, false ) ) {
1567 throw new PageUpdateException( "Failed to update page row to use new revision." );
1568 }
1569
1570 $tags = $this->computeEffectiveTags();
1571 if ( !$this->updatesSuppressed() ) {
1572 $this->hookRunner->onRevisionFromEditComplete(
1573 $wikiPage, $newRevisionRecord, false, $this->author, $tags
1574 );
1575 }
1576
1577 if ( $this->usePageCreationLog ) {
1578 // Log the page creation
1579 // @TODO: Do we want a 'recreate' action?
1580 $logEntry = new ManualLogEntry( 'create', 'create' );
1581 $logEntry->setPerformer( $this->author );
1582 $logEntry->setTarget( $this->getPage() );
1583 $logEntry->setComment( $summary->text );
1584 $logEntry->setTimestamp( $now );
1585 $logEntry->setAssociatedRevId( $newRevisionRecord->getId() );
1586 $logEntry->insert();
1587 // Note that we don't publish page creation events to recentchanges
1588 // (i.e. $logEntry->publish()) since this would create duplicate entries,
1589 // one for the edit and one for the page creation.
1590 }
1591
1592 $this->prepareDerivedDataUpdater(
1593 $wikiPage,
1594 $newRevisionRecord,
1595 $summary,
1596 $tags
1597 );
1598
1599 // Return the new revision to the caller
1600 $status->setNewRevision( $newRevisionRecord );
1601
1602 // Notify the dispatcher of the PageLatestRevisionChangedEvent during the transaction round
1603 $this->emitEvents();
1604
1605 // Schedule the secondary updates to run after the transaction round commits
1606 $this->scheduleAtomicSectionUpdate(
1607 $dbw,
1608 $wikiPage,
1609 $newRevisionRecord,
1610 $summary,
1611 [ 'created' => true ]
1612 );
1613
1614 // Mark the earliest point where the transaction round can be committed in CLI mode.
1615 // We want to make sure that the event was bound to a round of transactions. We also
1616 // want the deferred update to enqueue similarly in both web and CLI modes, in order
1617 // to simplify testing assertions.
1618 $dbw->endAtomic( __METHOD__ );
1619
1620 return $status;
1621 }
1622
1623 private function prepareDerivedDataUpdater(
1624 WikiPage $wikiPage,
1625 RevisionRecord $newRevisionRecord,
1626 CommentStoreComment $summary,
1627 array $tags,
1628 array $hintOverrides = []
1629 ) {
1630 static $flagMap = [
1631 EDIT_SILENT => PageLatestRevisionChangedEvent::FLAG_SILENT,
1632 EDIT_FORCE_BOT => PageLatestRevisionChangedEvent::FLAG_BOT,
1633 EDIT_IMPLICIT => PageLatestRevisionChangedEvent::FLAG_IMPLICIT,
1634 ];
1635
1636 $hints = $this->hints;
1637 foreach ( $flagMap as $bit => $name ) {
1638 $hints[$name] = ( $this->flags & $bit ) === $bit;
1639 }
1640
1641 $hints += PageLatestRevisionChangedEvent::DEFAULT_FLAGS;
1642 $hints = $hintOverrides + $hints;
1643
1644 // set debug data
1645 $hints['causeAction'] = 'edit-page';
1646 $hints['causeAgent'] = $this->author->getName();
1647
1648 $editResult = $this->getEditResult();
1649 $hints['editResult'] = $editResult;
1650
1651 // Prepare to update links tables, site stats, etc.
1652 $hints['rcPatrolStatus'] = $this->rcPatrolStatus;
1653 $hints['tags'] = $tags;
1654
1655 $this->derivedDataUpdater->setPerformer( $this->author );
1656 $this->derivedDataUpdater->prepareUpdate( $newRevisionRecord, $hints );
1657 }
1658
1659 private function updatesSuppressed(): bool {
1660 return $this->hints['suppressDerivedDataUpdates'] ?? false;
1661 }
1662
1663 private function emitEvents(): void {
1664 if ( $this->updatesSuppressed() ) {
1665 return;
1666 }
1667
1668 $this->derivedDataUpdater->emitEvents();
1669 }
1670
1671 private function scheduleAtomicSectionUpdate(
1672 IDatabase $dbw,
1673 WikiPage $wikiPage,
1674 RevisionRecord $newRevisionRecord,
1675 CommentStoreComment $summary,
1676 array $hints = []
1677 ): void {
1678 if ( $this->updatesSuppressed() ) {
1679 return;
1680 }
1681
1682 DeferredUpdates::addUpdate(
1683 $this->getAtomicSectionUpdate(
1684 $dbw,
1685 $wikiPage,
1686 $newRevisionRecord,
1687 $summary,
1688 $hints
1689 ),
1690 DeferredUpdates::PRESEND
1691 );
1692 }
1693
1694 private function getAtomicSectionUpdate(
1695 IDatabase $dbw,
1696 WikiPage $wikiPage,
1697 RevisionRecord $newRevisionRecord,
1698 CommentStoreComment $summary,
1699 array $hints = []
1700 ): AtomicSectionUpdate {
1701 return new AtomicSectionUpdate(
1702 $dbw,
1703 __METHOD__,
1704 function () use (
1705 $wikiPage, $newRevisionRecord,
1706 $summary, $hints
1707 ) {
1708 $this->derivedDataUpdater->doUpdates();
1709
1710 $created = $hints['created'] ?? false;
1711 $this->flags |= ( $created ? EDIT_NEW : EDIT_UPDATE );
1712
1713 // PageSaveComplete replaced old PageContentInsertComplete and
1714 // PageContentSaveComplete hooks since 1.35
1715 $this->hookRunner->onPageSaveComplete(
1716 $wikiPage,
1717 $this->author,
1718 $summary->text,
1719 $this->flags,
1720 $newRevisionRecord,
1721 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable Not null already checked
1722 $this->getEditResult()
1723 );
1724 }
1725 );
1726 }
1727
1731 private function getRequiredSlotRoles() {
1732 return $this->slotRoleRegistry->getRequiredRoles( $this->getPage() );
1733 }
1734
1738 private function getAllowedSlotRoles() {
1739 return $this->slotRoleRegistry->getAllowedRoles( $this->getPage() );
1740 }
1741
1742 private function ensureRoleAllowed( string $role ) {
1743 $allowedRoles = $this->getAllowedSlotRoles();
1744 if ( !in_array( $role, $allowedRoles ) ) {
1745 throw new PageUpdateException( "Slot role `$role` is not allowed." );
1746 }
1747 }
1748
1749 private function ensureRoleNotRequired( string $role ) {
1750 $requiredRoles = $this->getRequiredSlotRoles();
1751 if ( in_array( $role, $requiredRoles ) ) {
1752 throw new PageUpdateException( "Slot role `$role` is required." );
1753 }
1754 }
1755
1756 private function checkAllRolesAllowed( array $roles, PageUpdateStatus $status ) {
1757 $allowedRoles = $this->getAllowedSlotRoles();
1758
1759 $forbidden = array_diff( $roles, $allowedRoles );
1760 if ( $forbidden ) {
1761 $status->error(
1762 'edit-slots-cannot-add',
1763 count( $forbidden ),
1764 implode( ', ', $forbidden )
1765 );
1766 }
1767 }
1768
1769 private function checkAllRolesDerived( array $roles, PageUpdateStatus $status ) {
1770 $notDerived = array_filter(
1771 $roles,
1772 function ( $role ) {
1773 return !$this->slotRoleRegistry->getRoleHandler( $role )->isDerived();
1774 }
1775 );
1776 if ( $notDerived ) {
1777 $status->error(
1778 'edit-slots-not-derived',
1779 count( $notDerived ),
1780 implode( ', ', $notDerived )
1781 );
1782 }
1783 }
1784
1785 private function checkNoRolesRequired( array $roles, PageUpdateStatus $status ) {
1786 $requiredRoles = $this->getRequiredSlotRoles();
1787
1788 $needed = array_diff( $roles, $requiredRoles );
1789 if ( $needed ) {
1790 $status->error(
1791 'edit-slots-cannot-remove',
1792 count( $needed ),
1793 implode( ', ', $needed )
1794 );
1795 }
1796 }
1797
1798 private function checkAllRequiredRoles( array $roles, PageUpdateStatus $status ) {
1799 $requiredRoles = $this->getRequiredSlotRoles();
1800
1801 $missing = array_diff( $requiredRoles, $roles );
1802 if ( $missing ) {
1803 $status->error(
1804 'edit-slots-missing',
1805 count( $missing ),
1806 implode( ', ', $missing )
1807 );
1808 }
1809 }
1810
1811}
const EDIT_FORCE_BOT
Mark the edit a "bot" edit regardless of user rights.
Definition Defines.php:129
const EDIT_INTERNAL
Signal that the page retrieve/save cycle happened entirely in this request.
Definition Defines.php:138
const EDIT_UPDATE
Article is assumed to be pre-existing, fail if it doesn't exist.
Definition Defines.php:117
const EDIT_IMPLICIT
The edit is a side effect and does not represent an active user contribution.
Definition Defines.php:141
const EDIT_SILENT
Do not notify other users (e.g.
Definition Defines.php:123
const EDIT_MINOR
Mark this edit minor, if the user is allowed to do so.
Definition Defines.php:120
const EDIT_AUTOSUMMARY
Fill in blank summaries with generated text where possible.
Definition Defines.php:135
const EDIT_NEW
Article is assumed to be non-existent, fail if it exists.
Definition Defines.php:114
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:68
Value object for a comment stored by CommentStore.
A class for passing options to services.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
Base class for content handling.
Deferrable Update for closure/callback updates via IDatabase::doAtomicSection()
Defer callable updates to run later in the PHP process.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Class for creating new log entries and inserting them into the database.
A class containing constants representing the names of configuration variables.
const UseRCPatrol
Name constant for the UseRCPatrol setting, for use with Config::get()
const ManualRevertSearchRadius
Name constant for the ManualRevertSearchRadius setting, for use with Config::get()
Domain event representing a change to the page's latest revision.
Service for creating WikiPage objects.
newFromTitle(PageReference $pageReference)
Create a WikiPage object from a title.
Base representation for an editable wiki page.
Definition WikiPage.php:82
updateRevisionOn( $dbw, RevisionRecord $revision, $lastRevision=null, $lastRevIsRedirect=null)
Update the page record to point to a newly saved revision.
insertOn( $dbw, $pageId=null)
Insert a new empty page record for this article.
lockAndGetLatest()
Lock the page row for this title+id and return page_latest (or 0)
Utility class for creating and reading rows in the recentchanges table.
Exception representing a failure to look up a revision.
Page revision base class.
Service for looking up page revisions.
Value object representing a content slot associated with a page revision.
getRole()
Returns the role of the slot.
A registry service for SlotRoleHandlers, used to define which slot roles are available on which page.
A handle for managing updates for derived page data on edit, import, purge, etc.
setCause(string $cause)
Set the cause of the update.
Builder class for the EditResult object.
Object for storing information about the effects of an edit.
Status object representing the outcome of a page update.
Controller-like object for creating and updating pages by creating new revisions.
getStatus()
The Status object indicating whether saveRevision() was successful.
setCause(string $cause)
Set the cause of the update.
inheritSlot(SlotRecord $originalSlot)
Explicitly inherit a slot from some earlier revision.
wasSuccessful()
Whether saveRevision() completed successfully.
getEditResult()
Returns the EditResult associated with this PageUpdater.
const CONSTRUCTOR_OPTIONS
Options that have to be present in the ServiceOptions object passed to the constructor.
isNew()
Whether saveRevision() was called and created a new page.
__construct(UserIdentity $author, PageIdentity $page, DerivedPageDataUpdater $derivedDataUpdater, IConnectionProvider $dbProvider, RevisionStore $revisionStore, SlotRoleRegistry $slotRoleRegistry, IContentHandlerFactory $contentHandlerFactory, HookContainer $hookContainer, UserGroupManager $userGroupManager, TitleFormatter $titleFormatter, ServiceOptions $serviceOptions, array $softwareTags, LoggerInterface $logger, WikiPageFactory $wikiPageFactory)
setFlags(int $flags)
Sets any flags to use when performing the update.
isUnchanged()
Whether saveRevision() did create a revision because the content didn't change: (null-edit).
updateAuthor(UserIdentity $author)
After creation of the user during the save process, update the stored UserIdentity.
updateRevision(int $revId=0)
Updates derived slots of an existing article.
prepareUpdate(int $flags=0)
Prepare the update.
getNewRevision()
The new revision created by saveRevision(), or null if saveRevision() has not yet been called,...
saveDummyRevision( $summary, int $flags=0)
Creates a dummy revision that does not change the content.
markAsRevert(int $revertMethod, int $newestRevertedRevId, ?int $revertAfterRevId=null)
Marks this edit as a revert and applies relevant information.
setUsePageCreationLog( $use)
Whether to create a log entry for new page creations.
removeSlot( $role)
Removes the slot with the given role.
setOriginalRevisionId( $originalRevId)
Sets the ID of an earlier revision that is being repeated or restored by this update.
addTags(array $tags)
Sets tags to apply to this update.
setUseAutomaticEditSummaries( $useAutomaticEditSummaries)
Can be used to enable or disable automatic summaries that are applied to certain kinds of changes,...
grabParentRevision()
Returns the revision that was the page's current revision when grabParentRevision() was first called.
hasEditConflict( $expectedParentRevision)
Checks whether this update conflicts with another update performed between the client loading data to...
setRcPatrolStatus( $status)
Sets the "patrolled" status of the edit.
addSoftwareTag(string $tag)
Sets software tag to this update.
saveRevision( $summary, int $flags=0)
Change an existing article or create a new article.
wasRevisionCreated()
Whether saveRevision() did create a revision.
addTag(string $tag)
Sets a tag to apply to this update.
wasCommitted()
Whether saveRevision() has been called on this instance.
setForceEmptyRevision(bool $forceEmptyRevision)
Set whether null-edits should create a revision.
isChange()
Whether the prepared edit is a change compared to the previous revision.
getExplicitTags()
Returns the list of tags set using the addTag() method.
preventChange()
Disable new revision creation, throwing an exception if it is attempted.
getPage()
Get the page we're currently updating.
setSlot(SlotRecord $slot)
Set the new slot for the given slot role.
setContent( $role, Content $content)
Set the new content for the given slot role.
Value object representing a modification of revision slots.
A title formatter service for MediaWiki.
Represents a title within MediaWiki.
Definition Title.php:69
Manage user group memberships.
User class for the MediaWiki software.
Definition User.php:130
isOK()
Returns whether the operation completed.
fatal( $message,... $parameters)
Add an error and set OK to false, indicating that the operation as a whole was fatal.
merge( $other, $overwriteValue=false)
Merge another status object into this one.
warning( $message,... $parameters)
Add a new warning.
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'=>[], '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'=> false, '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, 250, 300,], 'ThumbnailNamespaces'=>[6,], 'ThumbnailSteps'=> null, 'ThumbnailStepsRatio'=> null, 'ThumbnailBuckets'=> null, 'ThumbnailMinimumBucketDistance'=> 50, 'UploadThumbnailRenderMap'=>[], 'UploadThumbnailRenderMethod'=> 'jobqueue', 'UploadThumbnailRenderHttpCustomHost'=> false, 'UploadThumbnailRenderHttpCustomDomain'=> false, 'UseTinyRGBForJPGThumbnails'=> false, 'GalleryOptions'=>[], 'ThumbUpright'=> 0.75, 'DirectoryMode'=> 511, 'ResponsiveImages'=> true, 'ImagePreconnect'=> false, 'DjvuUseBoxedCommand'=> false, 'DjvuDump'=> null, 'DjvuRenderer'=> null, 'DjvuTxt'=> null, 'DjvuPostProcessor'=> 'pnmtojpeg', 'DjvuOutputExtension'=> 'jpg', 'EmergencyContact'=> false, 'PasswordSender'=> false, 'NoReplyAddress'=> false, 'EnableEmail'=> true, 'EnableUserEmail'=> true, 'EnableSpecialMute'=> false, 'EnableUserEmailMuteList'=> false, 'UserEmailUseReplyTo'=> true, 'PasswordReminderResendTime'=> 24, 'NewPasswordExpiry'=> 604800, 'UserEmailConfirmationTokenExpiry'=> 604800, 'UserEmailConfirmationUseHTML'=> false, 'PasswordExpirationDays'=> false, 'PasswordExpireGrace'=> 604800, 'SMTP'=> false, 'AdditionalMailParams'=> null, 'AllowHTMLEmail'=> false, 'EnotifFromEditor'=> false, 'EmailAuthentication'=> true, '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, 'ImageLinksSchemaMigrationStage'=> 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',],], 'json'=>['class'=> 'MediaWiki\\Content\\JsonContentHandler', 'services'=>['ParsoidParserFactory', 'TitleFactory',],], 'css'=>['class'=> 'MediaWiki\\Content\\CssContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup',],], 'vue'=>['class'=> 'MediaWiki\\Content\\VueContentHandler', 'services'=>['MainConfig', 'ParserFactory',],], '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'=> '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,],], 'parsoid-pcache'=>['default'=>['minCpuTime'=> 0,],], 'postproc-pcache'=>['default'=>['minCpuTime'=> 9223372036854775807,],], 'postproc-parsoid-pcache'=>['default'=>['minCpuTime'=> 9223372036854775807,],],], 'ChronologyProtectorSecret'=> '', 'ParserCacheExpireTime'=> 86400, 'ParserCacheAsyncExpireTime'=> 60, 'ParserCacheAsyncRefreshJobs'=> true, 'OldRevisionParserCacheExpireTime'=> 3600, 'ObjectCacheSessionExpiry'=> 3600, 'PHPSessionHandling'=> 'warn', 'SuspiciousIpExpiry'=> false, 'SessionPbkdf2Iterations'=> 10001, 'UseSessionCookieJwt'=> false, 'MemCachedServers'=>['127.0.0.1:11211',], 'MemCachedPersistent'=> false, 'MemCachedTimeout'=> 500000, 'UseLocalMessageCache'=> false, 'AdaptiveMessageCache'=> false, 'LocalisationCacheConf'=>['class'=> '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',],],], '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, ], '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, 'UseLegacyMediaStyles' => 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, ], ], '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, '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, ], '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, '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' => [ ], 'RestrictionTypes' => [ 'create', 'edit', 'move', 'upload', ], 'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop', ], 'CascadingRestrictionLevels' => [ 'sysop', ], 'SemiprotectedRestrictionLevels' => [ 'autoconfirmed', ], 'NamespaceProtection' => [ ], '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, 'pagelang' => true, ], 'editprotected' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editprotected' => true, ], 'editmycssjs' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, ], 'editmyoptions' => [ 'editmyoptions' => true, 'editmyuserjson' => true, ], 'editinterface' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, ], 'editsiteconfig' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => 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, '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, '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, 'editprotected' => true, 'protect' => true, ], 'viewmywatchlist' => [ 'viewmywatchlist' => true, ], 'editmywatchlist' => [ 'editmywatchlist' => true, ], 'sendemail' => [ 'sendemail' => true, ], 'createaccount' => [ 'createaccount' => true, ], 'privateinfo' => [ 'viewmyprivateinfo' => true, ], 'mergehistory' => [ 'mergehistory' => 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', ], '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, 'SecretKey' => false, 'JwtPrivateKey' => false, 'JwtPublicKey' => false, 'AllowUserJs' => false, 'AllowUserCss' => false, 'AllowUserCssPrefs' => true, 'UseSiteJs' => true, 'UseSiteCss' => true, 'BreakFrames' => false, 'EditPageFrameOptions' => 'DENY', 'ApiFrameOptions' => 'DENY', 'CSPHeader' => false, 'CSPReportOnlyHeader' => 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, '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: ], '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' => [ ], 'RCEngines' => [ 'redis' => 'MediaWiki\\RCFeed\\RedisPubSubFeedEngine', 'udp' => 'MediaWiki\\RCFeed\\UDPRCFeedEngine', ], '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, ], '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, '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\\JobQueue\\Jobs\\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', 'Access-Control-Max-Age', 'Authorization', ], 'RestAPIAdditionalRouteFiles' => [ ], 'RestSandboxSpecs' => [ ], '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, '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, 'UsePostprocCache' => false, 'ParserOptionsLogUnsafeSampleRate' => 0, ], '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', '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', ], 'ThumbnailStepsRatio' => [ 'number', 'null', ], 'ThumbnailBuckets' => [ 'array', 'null', ], 'UploadThumbnailRenderMap' => 'object', 'GalleryOptions' => 'object', 'DjvuDump' => [ 'string', 'null', ], 'DjvuRenderer' => [ 'string', 'null', ], 'DjvuTxt' => [ 'string', 'null', ], 'DjvuPostProcessor' => [ 'string', 'null', ], 'UserEmailConfirmationUseHTML' => 'boolean', 'SMTP' => [ 'boolean', 'object', ], 'EnotifFromEditor' => 'boolean', 'EnotifRevealEditorAddress' => 'boolean', 'UsersNotifiedOnAllChanges' => 'object', 'DBmwschema' => [ 'string', 'null', ], 'SharedTables' => 'array', 'DBservers' => [ 'boolean', 'array', ], 'LBFactoryConf' => 'object', 'LocalDatabases' => 'array', 'VirtualDomainsMapping' => 'object', 'FileSchemaMigrationStage' => 'integer', 'ImageLinksSchemaMigrationStage' => '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', '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', 'RestrictionTypes' => 'array', 'RestrictionLevels' => 'array', 'CascadingRestrictionLevels' => 'array', 'SemiprotectedRestrictionLevels' => 'array', 'NamespaceProtection' => 'object', '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', ], 'CSPHeader' => [ 'boolean', 'object', ], 'CSPReportOnlyHeader' => [ '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', 'RCEngines' => 'object', 'OverrideSiteFeed' => 'object', 'FeedClasses' => 'object', 'AdvertisedFeedTypes' => 'array', 'SoftwareTags' => 'object', 'RecentChangesFlags' => 'object', 'WatchlistExpiry' => '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', 'ShellRestrictionMethod' => [ 'string', 'boolean', ], 'ShellboxUrls' => 'object', 'ShellboxSecretKey' => [ 'string', 'null', ], 'ShellboxShell' => [ 'string', 'null', ], 'HTTPTimeout' => 'number', 'HTTPConnectTimeout' => 'number', 'HTTPMaxTimeout' => 'number', 'HTTPMaxConnectTimeout' => 'number', 'LocalVirtualHosts' => 'object', 'LocalHTTPProxy' => [ 'string', 'boolean', ], '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', 'UsePostprocCache' => 'boolean', 'ParserOptionsLogUnsafeSampleRate' => 'integer', ], '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', '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', ], ], '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', ], 'msg' => [ 'type' => 'string', 'description' => 'a message key', ], ], 'required' => [ 'url', ], ], ], '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.', ],]
Content objects represent page content, e.g.
Definition Content.php:28
Interface for objects (potentially) representing an editable wiki page.
Constants for representing well known causes for page updates.
An object representing a page update during an edit.
Interface for objects representing user identity.
Provide primary and replica IDatabase connections.
Interface for database access objects.
Interface to a relational database.
Definition IDatabase.php:31