Merge "StringUtils: Add a utility for checking if a string is a valid regex"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 19 Sep 2019 08:03:33 +0000 (08:03 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 19 Sep 2019 08:03:33 +0000 (08:03 +0000)
662 files changed:
.phan/config.php
.phpcs.xml
.travis.yml
CODE_OF_CONDUCT.md
INSTALL
RELEASE-NOTES-1.34
api.php
autoload.php
composer.json
docs/extension.schema.v1.json
docs/extension.schema.v2.json
docs/hooks.txt
img_auth.php
includes/ActorMigration.php
includes/AjaxResponse.php
includes/DefaultSettings.php
includes/DevelopmentSettings.php
includes/EditPage.php
includes/FeedUtils.php
includes/FileDeleteForm.php
includes/GlobalFunctions.php
includes/Linker.php
includes/MergeHistory.php
includes/MovePage.php
includes/OutputPage.php
includes/PHPVersionCheck.php
includes/ProtectionForm.php
includes/Rest/BasicAccess/MWBasicAuthorizer.php
includes/Rest/BasicAccess/MWBasicRequestAuthorizer.php
includes/Rest/EntryPoint.php
includes/Rest/LocalizedHttpException.php
includes/Rest/ResponseFactory.php
includes/Rest/Router.php
includes/Rest/Validator/ParamValidatorCallbacks.php
includes/Rest/Validator/Validator.php
includes/Revision.php
includes/Revision/RevisionRecord.php
includes/Revision/RevisionStore.php
includes/Revision/RevisionStoreFactory.php
includes/ServiceWiring.php
includes/Setup.php
includes/Status.php
includes/Storage/DerivedPageDataUpdater.php
includes/Storage/SqlBlobStore.php
includes/StreamFile.php
includes/Title.php
includes/WebRequest.php
includes/actions/Action.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/McrUndoAction.php
includes/actions/RawAction.php
includes/actions/RollbackAction.php
includes/actions/SpecialPageAction.php
includes/api/ApiComparePages.php
includes/api/ApiEditPage.php
includes/api/ApiExpandTemplates.php
includes/api/ApiFormatXmlRsd.php
includes/api/ApiHelpParamValueMessage.php
includes/api/ApiImageRotate.php
includes/api/ApiMain.php
includes/api/ApiModuleManager.php
includes/api/ApiPageSet.php
includes/api/ApiParse.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllDeletedRevisions.php
includes/api/ApiQueryAllRevisions.php
includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryBlockInfoTrait.php [new file with mode: 0644]
includes/api/ApiQueryContributors.php
includes/api/ApiQueryDeletedRevisions.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryFilearchive.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryQueryPage.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryUserContribs.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiQueryUsers.php
includes/api/ApiResetPassword.php
includes/api/ApiRevisionDelete.php
includes/api/ApiSetNotificationTimestamp.php
includes/api/ApiTag.php
includes/api/i18n/ar.json
includes/api/i18n/en.json
includes/api/i18n/fr.json
includes/api/i18n/he.json
includes/api/i18n/it.json
includes/api/i18n/ko.json
includes/api/i18n/mk.json
includes/api/i18n/pl.json
includes/api/i18n/pt-br.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/zh-hant.json
includes/auth/AuthenticationRequest.php
includes/auth/ResetPasswordSecondaryAuthenticationProvider.php
includes/block/BlockManager.php
includes/block/DatabaseBlock.php
includes/cache/LinkCache.php
includes/cache/UserCache.php
includes/cache/localisation/LCStoreDB.php
includes/changes/CategoryMembershipChange.php
includes/changes/ChangesFeed.php
includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/changes/RCCacheEntryFactory.php
includes/changes/RecentChange.php
includes/changetags/ChangeTags.php
includes/changetags/ChangeTagsLogItem.php
includes/clientpool/SquidPurgeClient.php
includes/collation/CustomUppercaseCollation.php
includes/composer/ComposerPhpunitXmlCoverageEdit.php [new file with mode: 0644]
includes/content/ContentHandler.php
includes/context/RequestContext.php
includes/dao/DBAccessBase.php
includes/debug/logger/ConsoleLogger.php
includes/deferred/CdnCacheUpdate.php
includes/deferred/HTMLCacheUpdate.php
includes/deferred/LinksUpdate.php
includes/deferred/SearchUpdate.php
includes/diff/DifferenceEngine.php
includes/exception/MWExceptionHandler.php
includes/export/DumpMultiWriter.php
includes/export/WikiExporter.php
includes/externalstore/ExternalStoreDB.php
includes/filerepo/FileRepo.php
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/LocalFileDeleteBatch.php
includes/filerepo/file/LocalFileMoveBatch.php
includes/filerepo/file/OldLocalFile.php
includes/gallery/ImageGalleryBase.php
includes/historyblob/ConcatenatedGzipHistoryBlob.php
includes/historyblob/HistoryBlobCurStub.php
includes/historyblob/HistoryBlobStub.php
includes/htmlform/HTMLFormField.php
includes/htmlform/fields/HTMLSelectAndOtherField.php
includes/http/MWCallbackStream.php
includes/import/ImportStreamSource.php
includes/import/ImportStringSource.php
includes/import/WikiImporter.php
includes/installer/CliInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/InstallDocFormatter.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/MysqlUpdater.php
includes/installer/PostgresInstaller.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/WebInstallerOptions.php
includes/installer/i18n/be-tarask.json
includes/installer/i18n/ckb.json
includes/installer/i18n/fr.json
includes/installer/i18n/ia.json
includes/installer/i18n/io.json
includes/installer/i18n/it.json
includes/installer/i18n/ja.json
includes/installer/i18n/nl.json
includes/installer/i18n/pl.json
includes/jobqueue/jobs/RefreshLinksJob.php
includes/libs/MemoizedCallable.php
includes/libs/composer/ComposerInstalled.php
includes/libs/composer/ComposerJson.php
includes/libs/composer/ComposerLock.php
includes/libs/filebackend/FSFileBackend.php
includes/libs/filebackend/FileBackendStore.php
includes/libs/filebackend/MemoryFileBackend.php
includes/libs/filebackend/SwiftFileBackend.php
includes/libs/filebackend/fileophandle/FileBackendStoreOpHandle.php
includes/libs/filebackend/fileophandle/SwiftFileOpHandle.php
includes/libs/filebackend/fsfile/FSFile.php
includes/libs/lockmanager/QuorumLockManager.php
includes/libs/mime/XmlTypeCheck.php
includes/libs/objectcache/MultiWriteBagOStuff.php
includes/libs/objectcache/ReplicatedBagOStuff.php
includes/libs/objectcache/wancache/WANObjectCache.php
includes/libs/rdbms/lbfactory/LBFactoryMulti.php
includes/libs/redis/RedisConnectionPool.php
includes/logging/BlockLogFormatter.php
includes/logging/ContentModelLogFormatter.php
includes/logging/DeleteLogFormatter.php
includes/logging/LogEventsList.php
includes/logging/LogFormatter.php
includes/logging/LogPager.php
includes/logging/ManualLogEntry.php
includes/logging/MergeLogFormatter.php
includes/logging/MoveLogFormatter.php
includes/logging/ProtectLogFormatter.php
includes/mail/EmailNotification.php
includes/mail/UserMailer.php
includes/media/DjVuHandler.php
includes/media/DjVuImage.php
includes/media/JpegMetadataExtractor.php
includes/objectcache/ObjectCache.php
includes/objectcache/SqlBagOStuff.php
includes/page/Article.php
includes/page/ImageHistoryList.php
includes/page/ImagePage.php
includes/page/PageArchive.php
includes/page/WikiFilePage.php
includes/page/WikiPage.php
includes/parser/CoreParserFunctions.php
includes/parser/PPDPart.php
includes/parser/PPDStack.php
includes/parser/PPDStackElement.php
includes/parser/PPFrame.php
includes/parser/PPFrame_DOM.php
includes/parser/PPTemplateFrame_Hash.php
includes/parser/Preprocessor.php
includes/parser/Preprocessor_Hash.php
includes/password/PasswordPolicyChecks.php
includes/preferences/DefaultPreferencesFactory.php
includes/profiler/SectionProfiler.php
includes/resourceloader/DerivativeResourceLoaderContext.php
includes/resourceloader/MessageBlobStore.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderCircularDependencyError.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/resourceloader/ResourceLoaderContext.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderFilePath.php
includes/resourceloader/ResourceLoaderForeignApiModule.php
includes/resourceloader/ResourceLoaderImage.php
includes/resourceloader/ResourceLoaderImageModule.php
includes/resourceloader/ResourceLoaderLanguageDataModule.php
includes/resourceloader/ResourceLoaderLessVarFileModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderOOUIFileModule.php
includes/resourceloader/ResourceLoaderOOUIIconPackModule.php
includes/resourceloader/ResourceLoaderOOUIModule.php
includes/resourceloader/ResourceLoaderSiteModule.php
includes/resourceloader/ResourceLoaderSiteStylesModule.php
includes/resourceloader/ResourceLoaderSkinModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/resourceloader/ResourceLoaderUserDefaultsModule.php
includes/resourceloader/ResourceLoaderUserModule.php
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/resourceloader/ResourceLoaderUserStylesModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/revisiondelete/RevDelArchivedFileItem.php
includes/revisiondelete/RevDelFileItem.php
includes/revisiondelete/RevDelList.php
includes/revisiondelete/RevDelLogItem.php
includes/revisiondelete/RevDelLogList.php
includes/revisiondelete/RevDelRevisionItem.php
includes/revisiondelete/RevDelRevisionList.php
includes/revisiondelete/RevisionDeleteUser.php
includes/revisiondelete/RevisionDeleter.php
includes/revisionlist/RevisionItem.php
includes/session/SessionManager.php
includes/session/SessionOverflowException.php [new file with mode: 0644]
includes/site/MediaWikiSite.php
includes/site/Site.php
includes/skins/BaseTemplate.php
includes/skins/SkinTemplate.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specialpage/QueryPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialAncientPages.php [new file with mode: 0644]
includes/specials/SpecialAncientpages.php [deleted file]
includes/specials/SpecialApiSandbox.php
includes/specials/SpecialAutoblockList.php
includes/specials/SpecialBlock.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialBrokenRedirects.php
includes/specials/SpecialChangeContentModel.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialConfirmEmail.php [new file with mode: 0644]
includes/specials/SpecialConfirmemail.php [deleted file]
includes/specials/SpecialContributions.php
includes/specials/SpecialCreateAccount.php
includes/specials/SpecialDeadendPages.php [new file with mode: 0644]
includes/specials/SpecialDeadendpages.php [deleted file]
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialDoubleRedirects.php
includes/specials/SpecialEditTags.php
includes/specials/SpecialEmailInvalidate.php
includes/specials/SpecialEmailUser.php
includes/specials/SpecialExpandTemplates.php
includes/specials/SpecialExport.php
includes/specials/SpecialFewestRevisions.php [new file with mode: 0644]
includes/specials/SpecialFewestrevisions.php [deleted file]
includes/specials/SpecialFileDuplicateSearch.php
includes/specials/SpecialImport.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListDuplicatedFiles.php
includes/specials/SpecialListFiles.php
includes/specials/SpecialListRedirects.php [new file with mode: 0644]
includes/specials/SpecialListredirects.php [deleted file]
includes/specials/SpecialLog.php
includes/specials/SpecialLonelyPages.php [new file with mode: 0644]
includes/specials/SpecialLonelypages.php [deleted file]
includes/specials/SpecialLongPages.php [new file with mode: 0644]
includes/specials/SpecialLongpages.php [deleted file]
includes/specials/SpecialMIMESearch.php [new file with mode: 0644]
includes/specials/SpecialMIMEsearch.php [deleted file]
includes/specials/SpecialMediaStatistics.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialMostCategories.php [new file with mode: 0644]
includes/specials/SpecialMostInterwikis.php [new file with mode: 0644]
includes/specials/SpecialMostLinked.php [new file with mode: 0644]
includes/specials/SpecialMostLinkedCategories.php [new file with mode: 0644]
includes/specials/SpecialMostLinkedTemplates.php [new file with mode: 0644]
includes/specials/SpecialMostRevisions.php [new file with mode: 0644]
includes/specials/SpecialMostcategories.php [deleted file]
includes/specials/SpecialMostinterwikis.php [deleted file]
includes/specials/SpecialMostlinked.php [deleted file]
includes/specials/SpecialMostlinkedcategories.php [deleted file]
includes/specials/SpecialMostlinkedtemplates.php [deleted file]
includes/specials/SpecialMostrevisions.php [deleted file]
includes/specials/SpecialMovepage.php
includes/specials/SpecialNewFiles.php [new file with mode: 0644]
includes/specials/SpecialNewimages.php [deleted file]
includes/specials/SpecialPageData.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialPreferences.php
includes/specials/SpecialRecentChanges.php
includes/specials/SpecialRecentChangesLinked.php
includes/specials/SpecialRedirect.php
includes/specials/SpecialRevisionDelete.php
includes/specials/SpecialRunJobs.php
includes/specials/SpecialShortPages.php [new file with mode: 0644]
includes/specials/SpecialShortpages.php [deleted file]
includes/specials/SpecialTags.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUncategorizedCategories.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedImages.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedPages.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedTemplates.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedcategories.php [deleted file]
includes/specials/SpecialUncategorizedimages.php [deleted file]
includes/specials/SpecialUncategorizedpages.php [deleted file]
includes/specials/SpecialUncategorizedtemplates.php [deleted file]
includes/specials/SpecialUndelete.php
includes/specials/SpecialUnusedCategories.php [new file with mode: 0644]
includes/specials/SpecialUnusedImages.php [new file with mode: 0644]
includes/specials/SpecialUnusedTemplates.php [new file with mode: 0644]
includes/specials/SpecialUnusedcategories.php [deleted file]
includes/specials/SpecialUnusedimages.php [deleted file]
includes/specials/SpecialUnusedtemplates.php [deleted file]
includes/specials/SpecialUnwatchedPages.php [new file with mode: 0644]
includes/specials/SpecialUnwatchedpages.php [deleted file]
includes/specials/SpecialUpload.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialWantedCategories.php [new file with mode: 0644]
includes/specials/SpecialWantedTemplates.php [new file with mode: 0644]
includes/specials/SpecialWantedcategories.php [deleted file]
includes/specials/SpecialWantedtemplates.php [deleted file]
includes/specials/SpecialWatchlist.php
includes/specials/SpecialWhatLinksHere.php
includes/specials/SpecialWithoutInterwiki.php [new file with mode: 0644]
includes/specials/SpecialWithoutinterwiki.php [deleted file]
includes/specials/forms/PreferencesFormOOUI.php
includes/specials/forms/UploadForm.php
includes/specials/pagers/ActiveUsersPager.php
includes/specials/pagers/AllMessagesTablePager.php
includes/specials/pagers/BlockListPager.php
includes/specials/pagers/ContribsPager.php
includes/specials/pagers/DeletedContribsPager.php
includes/specials/pagers/MergeHistoryPager.php
includes/specials/pagers/NewFilesPager.php
includes/specials/pagers/ProtectedPagesPager.php
includes/specials/pagers/ProtectedTitlesPager.php
includes/specials/pagers/UsersPager.php
includes/title/MediaWikiTitleCodec.php
includes/upload/UploadBase.php
includes/upload/UploadFromUrl.php
includes/user/LocalIdLookup.php
includes/user/PasswordReset.php
includes/user/User.php
includes/user/UserNamePrefixSearch.php
includes/utils/AvroValidator.php
includes/watcheditem/NoWriteWatchedItemStore.php
includes/watcheditem/WatchedItemQueryService.php
includes/widget/CheckMatrixWidget.php
includes/widget/ComplexTitleInputWidget.php
includes/widget/NamespaceInputWidget.php
includes/widget/SelectWithInputWidget.php
includes/widget/SizeFilterWidget.php
includes/widget/TagMultiselectWidget.php
index.php
jsduck.json
languages/LanguageConverter.php
languages/data/Names.php
languages/data/ZhConversion.php
languages/i18n/ar.json
languages/i18n/ast.json
languages/i18n/awa.json
languages/i18n/ban.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dtp.json
languages/i18n/dty.json
languages/i18n/en.json
languages/i18n/exif/id.json
languages/i18n/exif/nb.json
languages/i18n/exif/nds-nl.json
languages/i18n/exif/pl.json
languages/i18n/exif/sd.json
languages/i18n/exif/sr-ec.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/gom-deva.json
languages/i18n/gom-latn.json
languages/i18n/gv.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/io.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/khw.json
languages/i18n/kiu.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/luz.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/mni.json
languages/i18n/my.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/ne.json
languages/i18n/nl.json
languages/i18n/nqo.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/sd.json
languages/i18n/sh.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/szl.json
languages/i18n/te.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/uk.json
languages/i18n/zgh.json
languages/i18n/zh-hant.json
languages/i18n/zh-hk.json
languages/messages/MessagesHyw.php
load.php
maintenance/Doxyfile
maintenance/Maintenance.php
maintenance/archives/patch-drop-user-fields.sql [new file with mode: 0644]
maintenance/archives/upgradeLogging.php
maintenance/cleanupImages.php
maintenance/cleanupRevActorPage.php [new file with mode: 0644]
maintenance/cleanupSpam.php
maintenance/cleanupTitles.php
maintenance/compareParsers.php
maintenance/dumpIterator.php
maintenance/findDeprecated.php
maintenance/getReplicaServer.php
maintenance/getText.php
maintenance/importDump.php
maintenance/includes/BackupDumper.php
maintenance/includes/MigrateActors.php
maintenance/install.php
maintenance/language/zhtable/simp2trad.manual
maintenance/language/zhtable/simp2trad_noconvert.manual
maintenance/language/zhtable/toCN.manual
maintenance/language/zhtable/toHK.manual
maintenance/language/zhtable/toSimp.manual
maintenance/language/zhtable/toTW.manual
maintenance/language/zhtable/toTrad.manual
maintenance/language/zhtable/trad2simp.manual
maintenance/language/zhtable/tradphrases.manual
maintenance/language/zhtable/tradphrases_exclude.manual
maintenance/mediawiki.Title/generatePhpCharToUpperMappings.php
maintenance/mwdocgen.php
maintenance/populateRevisionLength.php
maintenance/postgres/tables.sql
maintenance/preprocessDump.php
maintenance/preprocessorFuzzTest.php
maintenance/purgeList.php
maintenance/reassignEdits.php
maintenance/rebuildImages.php
maintenance/recountCategories.php
maintenance/refreshLinks.php
maintenance/removeUnusedAccounts.php
maintenance/renderDump.php
maintenance/sqlite/archives/patch-archive-drop-ar_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-filearchive-drop-fa_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-image-drop-img_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-ipblocks-drop-ipb_by.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-logging-drop-log_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-oldimage-drop-oi_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-recentchanges-drop-rc_user.sql [new file with mode: 0644]
maintenance/storage/blobs.sql
maintenance/storage/checkStorage.php
maintenance/storage/recompressTracked.php
maintenance/tables.sql
maintenance/userDupes.inc
maintenance/userOptions.php
mw-config/config.css
opensearch_desc.php
profileinfo.php
resources/Resources.php
resources/lib/foreign-resources.yaml
resources/lib/ooui/History.md
resources/lib/ooui/i18n/fr.json
resources/lib/ooui/i18n/pl.json
resources/lib/ooui/oojs-ui-apex.js
resources/lib/ooui/oojs-ui-core-apex.css
resources/lib/ooui/oojs-ui-core-wikimediaui.css
resources/lib/ooui/oojs-ui-core.js
resources/lib/ooui/oojs-ui-toolbars-apex.css
resources/lib/ooui/oojs-ui-toolbars-wikimediaui.css
resources/lib/ooui/oojs-ui-toolbars.js
resources/lib/ooui/oojs-ui-widgets-apex.css
resources/lib/ooui/oojs-ui-widgets-wikimediaui.css
resources/lib/ooui/oojs-ui-widgets.js
resources/lib/ooui/oojs-ui-wikimediaui.js
resources/lib/ooui/oojs-ui-windows-apex.css
resources/lib/ooui/oojs-ui-windows-wikimediaui.css
resources/lib/ooui/oojs-ui-windows.js
resources/lib/ooui/themes/apex/icons-editing-advanced.json
resources/lib/ooui/themes/apex/icons-user.json
resources/lib/ooui/themes/wikimediaui/icons-editing-advanced.json
resources/lib/ooui/themes/wikimediaui/icons-user.json
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline-invert.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline-progressive.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg [new file with mode: 0644]
resources/src/jquery.color/jquery.color.js [new file with mode: 0644]
resources/src/jquery.color/jquery.colorUtil.js [new file with mode: 0644]
resources/src/jquery/jquery.checkboxShiftClick.js [deleted file]
resources/src/jquery/jquery.color.js [deleted file]
resources/src/jquery/jquery.colorUtil.js [deleted file]
resources/src/mediawiki.ForeignApi.core.js
resources/src/mediawiki.RegExp.js [deleted file]
resources/src/mediawiki.Title/Title.js
resources/src/mediawiki.Title/phpCharToUpper.json
resources/src/mediawiki.htmlform.checker.js
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.page.ready.js [deleted file]
resources/src/mediawiki.page.ready/.eslintrc.json [new file with mode: 0644]
resources/src/mediawiki.page.ready/checkboxShift.js [new file with mode: 0644]
resources/src/mediawiki.page.ready/ready.js [new file with mode: 0644]
resources/src/mediawiki.special/listFiles.less [new file with mode: 0644]
resources/src/mediawiki.util/util.js
rest.php
tests/parser/ParserTestRunner.php
tests/parser/parserTests.txt
tests/phpunit/MediaWikiIntegrationTestCase.php
tests/phpunit/data/media/jpeg-xmp-nullchar.jpg [new file with mode: 0644]
tests/phpunit/includes/ActorMigrationTest.php
tests/phpunit/includes/ActorMigrationTest.sql [new file with mode: 0644]
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/Rest/BasicAccess/MWBasicRequestAuthorizerTest.php
tests/phpunit/includes/Rest/EntryPointTest.php
tests/phpunit/includes/Revision/RenderedRevisionTest.php
tests/phpunit/includes/Revision/RevisionQueryInfoTest.php
tests/phpunit/includes/Revision/RevisionStoreDbTestBase.php
tests/phpunit/includes/Revision/RevisionStoreFactoryTest.php
tests/phpunit/includes/RevisionDbTestBase.php
tests/phpunit/includes/RevisionTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/api/ApiBlockTest.php
tests/phpunit/includes/api/ApiDeleteTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/api/ApiModuleManagerTest.php
tests/phpunit/includes/api/ApiPageSetTest.php
tests/phpunit/includes/api/ApiQueryBlockInfoTraitTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiQueryLanguageinfoTest.php
tests/phpunit/includes/api/ApiQuerySiteinfoTest.php
tests/phpunit/includes/api/ApiRevisionDeleteTest.php
tests/phpunit/includes/api/format/ApiFormatBaseTest.php
tests/phpunit/includes/api/format/ApiFormatTestBase.php
tests/phpunit/includes/api/query/ApiQueryUserContribsTest.php
tests/phpunit/includes/block/BlockManagerTest.php
tests/phpunit/includes/deferred/LinksUpdateTest.php
tests/phpunit/includes/filebackend/FileBackendTest.php
tests/phpunit/includes/filebackend/SwiftFileBackendTest.php
tests/phpunit/includes/filerepo/file/LocalFileTest.php
tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php
tests/phpunit/includes/logging/DatabaseLogEntryTest.php
tests/phpunit/includes/media/JpegMetadataExtractorTest.php
tests/phpunit/includes/page/PageArchiveTestBase.php
tests/phpunit/includes/preferences/DefaultPreferencesFactoryTest.php
tests/phpunit/includes/session/SessionManagerTest.php
tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php
tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
tests/phpunit/includes/specials/QueryAllSpecialPagesTest.php
tests/phpunit/includes/specials/SpecialBlankPageTest.php
tests/phpunit/includes/specials/SpecialMIMESearchTest.php
tests/phpunit/includes/specials/SpecialShortPagesTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialShortpagesTest.php [deleted file]
tests/phpunit/includes/specials/SpecialUncategorizedCategoriesTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/UncategorizedCategoriesPageTest.php [deleted file]
tests/phpunit/includes/user/LocalIdLookupTest.php
tests/phpunit/includes/user/PasswordResetTest.php
tests/phpunit/includes/user/UserGroupMembershipTest.php
tests/phpunit/includes/user/UserTest.php
tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php
tests/phpunit/maintenance/MWDoxygenFilterTest.php
tests/phpunit/maintenance/deleteAutoPatrolLogsTest.php
tests/phpunit/maintenance/fetchTextTest.php
tests/phpunit/unit/includes/Rest/Handler/HelloHandlerTest.php
tests/phpunit/unit/includes/Rest/ResponseFactoryTest.php
tests/phpunit/unit/includes/Rest/RouterTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
tests/selenium/wdio-mediawiki/Api.js
tests/selenium/wdio-mediawiki/CHANGELOG.md
tests/selenium/wdio-mediawiki/README.md
tests/selenium/wdio-mediawiki/package.json
thumb.php
thumb_handler.php

index fc775fe..56a8ccb 100644 (file)
@@ -104,8 +104,6 @@ $cfg['suppress_issue_types'] = array_merge( $cfg['suppress_issue_types'], [
 
        // approximate error count: 45
        "PhanTypeMismatchArgument",
-       // approximate error count: 693
-       "PhanUndeclaredProperty",
 ] );
 
 // This helps a lot in discovering bad code, but unfortunately it will always fail for
@@ -113,6 +111,10 @@ $cfg['suppress_issue_types'] = array_merge( $cfg['suppress_issue_types'], [
 // @todo Enable when the issue above is resolved and we update our config!
 $cfg['redundant_condition_detection'] = false;
 
+// Do not use aliases in core.
+// Use the correct name, because we don't need backward compatibility
+$cfg['enable_class_alias_support'] = false;
+
 $cfg['ignore_undeclared_variables_in_global_scope'] = true;
 // @todo It'd be great if we could just make phan read these from DefaultSettings, to avoid
 // duplicating the types.
index 9f11ebc..f971881 100644 (file)
                        Whitelist existing violations, but enable the sniff to prevent
                        any new occurrences.
                -->
-               <exclude-pattern>*/includes/specials/SpecialMostinterwikis\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialAncientpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialBrokenRedirects\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialConfirmemail\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialDeadendpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialDeletedContributions\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialDoubleRedirects\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialEmailInvalidate\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialFewestrevisions\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialFileDuplicateSearch\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialLinkSearch\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialListDuplicatedFiles\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialListredirects\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialLonelypages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialLongpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMIMEsearch\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMediaStatistics\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostcategories\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialMostimages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostlinked\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostlinkedcategories\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostlinkedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostrevisions\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialMovepage\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialNewimages\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialRandompage\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialShortpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedcategories\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedimages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnusedcategories\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnusedimages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnusedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnwatchedpages\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialUserrights\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialWantedcategories\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialWantedfiles\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialWantedpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialWantedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialWithoutinterwiki\.php</exclude-pattern>
                <exclude-pattern>*/maintenance/CodeCleanerGlobalsPass.inc</exclude-pattern>
                <exclude-pattern>*/maintenance/archives/upgradeLogging\.php</exclude-pattern>
                <exclude-pattern>*/maintenance/benchmarks/bench_HTTP_HTTPS\.php</exclude-pattern>
index d5607f1..8dbc5f2 100644 (file)
@@ -26,8 +26,6 @@ matrix:
   include:
     - php: 7.3
     - php: 7.2
-    - php: 7.1
-    - php: 7
 
 services:
   - mysql
index 498acf7..3d9f26a 100644 (file)
@@ -1 +1,4 @@
+Code of Conduct
+===============
+
 The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct).
diff --git a/INSTALL b/INSTALL
index 07dd9c3..0359166 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -7,7 +7,7 @@ Starting with MediaWiki 1.2.0, it's possible to install and configure the wiki
 
 Required software as of MediaWiki 1.34.0:
 
-* Web server with PHP 7.0.13 or higher, plus the following extesnsions:
+* Web server with PHP 7.2.0 or higher, plus the following extesnsions:
 ** ctype
 ** dom
 ** fileinfo
index aaf4d78..af87e2b 100644 (file)
@@ -80,6 +80,7 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
 * $wgWikiDiff2MovedParagraphDetectionCutoff — If you still want a custom change
   size threshold, please specify in php.ini, using the configuration variable
   wikidiff2.moved_paragraph_detection_cutoff.
+* $wgUseESI - This experimental setting, deprecated in 1.33, is now removed.
 * $wgDebugPrintHttpHeaders - The default of including HTTP headers in the
   debug log channel is no longer configurable. The debug log itself remains
   configurable via $wgDebugLogFile.
@@ -90,6 +91,8 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
 * $wgDBOracleDRCP - If you must use persistent connections, set DBO_PERSISTENT
   in the 'flags' field for servers in $wgDBServers (or $wgLBFactoryConf).
 * $wgMemCachedDebug - Set the cache "debug" field in $wgObjectCaches instead.
+* $wgActorTableSchemaMigrationStage has been removed. Extension code for
+  MediaWiki 1.31+ finding it unset should treat it as being SCHEMA_COMPAT_NEW.
 
 === New user-facing features in 1.34 ===
 * Special:Mute has been added as a quick way for users to block unwanted emails
@@ -117,6 +120,12 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
   GetBlockedStatus.
 * ObjectFactory is available as a service. When used as a service, the object
   specs can now specify needed DI services.
+* (T222388) Special pages can now be specified as an ObjectFactory spec,
+  allowing the construction of special pages that require services to be
+  injected in their constructor.
+* (T222388) API modules can now be specified as an ObjectFactory spec,
+  allowing the construction of modules that require services to be injected
+  in their constructor.
 
 === External library changes in 1.34 ===
 
@@ -153,9 +162,31 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
 === Action API changes in 1.34 ===
 * The 'recenteditcount' response property from action=query list=allusers,
   deprecated in 1.25, has been removed.
+* (T60993) action=query list=filearchive, list=alldeletedrevisions and
+  prop=deletedrevisions no longer require the 'deletedhistory' user right.
+* In the response to queries that use 'prop=imageinfo', entries for
+  non-existing files (indicated by the 'filemissing' field) now omit the
+  following fields, since they are meaningless in this context:
+  'timestamp', 'userhidden', 'user', 'userid', 'anon', 'size', 'width',
+  'height', 'pagecount', 'duration', 'commenthidden', 'parsedcomment',
+  'comment', 'thumburl', 'thumbwidth', 'thumbheight', 'thumbmime',
+  'thumberror', 'url', 'sha1', 'metadata', 'extmetadata', 'commonmetadata',
+  'mime', 'mediadtype', 'bitdepth'.
+  Clients that process these fields should first check if 'filemissing' is
+  set. Fields that are supported even if the file is missing include:
+  'canonicaltitle', ''archivename' (deleted files only), 'descriptionurl',
+  'descriptionshorturl'.
+* The 'blockexpiry' result property in list=users and list=allusers will now be
+  returned in the same format used by the rest of the API: ISO 8601 for
+  expiring blocks, and "infinite" for non-expiring blocks.
 
 === Action API internal changes in 1.34 ===
-* …
+* The exception thrown in ApiModuleManager::getModule has been changed
+  from an MWException to an UnexpectedValueException, thrown by ObjectFactory.
+  ApiModuleManager::getModule now also throws InvalidArgumentExceptions when
+  ObjectFactory is presented with an invalid spec or incorrectly constructed
+  objects.
+* Added ApiQueryBlockInfoTrait.
 
 === Languages updated in 1.34 ===
 MediaWiki supports over 350 languages. Many localisations are updated regularly.
@@ -174,6 +205,34 @@ because of Phabricator reports.
   * CryptRand class
   * CryptRand service
   * Functions of the MWCryptRand class: singleton(), wasStrong() and generate().
+* Various Special Page PHP Classes were renamed (mostly casing changes):
+  * SpecialAncientpages => SpecialAncientPages
+  * SpecialConfirmemail => SpecialConfirmEmail
+  * SpecialDeadendpages => SpecialDeadendPages
+  * SpecialFewestrevisions => SpecialFewestRevisions
+  * SpecialListredirects => SpecialListRedirects
+  * SpecialLonelypages => SpecialLonelyPages
+  * SpecialLongpages => SpecialLongPages
+  * SpecialMIMEsearch => SpecialMIMESearch
+  * SpecialMostcategories => SpecialMostCategories
+  * SpecialMostinterwikis => SpecialMostInterwikis
+  * SpecialMostlinked => SpecialMostLinked
+  * SpecialMostlinkedcategories => SpecialMostLinkedCategories
+  * SpecialMostlinkedtemplates => SpecialMostLinkedTemplates
+  * SpecialMostrevisions => SpecialMostRevisions
+  * SpecialNewimages => SpecialNewFiles
+  * SpecialShortpages => SpecialShortPages
+  * SpecialUncategorizedcategories => SpecialUncategorizedCategories
+  * SpecialUncategorizedimages => SpecialUncategorizedImages
+  * SpecialUncategorizedpages => SpecialUncategorizedPages
+  * SpecialUncategorizedtemplates => SpecialUncategorizedTemplates
+  * SpecialUnusedcategories => SpecialUnusedCategories
+  * SpecialUnusedimages => SpecialUnusedImages
+  * SpecialUnusedtemplates => SpecialUnusedTemplates
+  * SpecialUnwatchedpages => SpecialUnwatchedPages
+  * SpecialWantedcategories => SpecialWantedCategories
+  * SpecialWantedtemplates => SpecialWantedTemplates
+  * SpecialWithoutinterwiki => SpecialWithoutInterwiki
 * Language::setCode, deprecated in 1.32, was removed. Use Language::factory to
   create a new Language object with a different language code.
 * MWNamespace::clearCaches() has been removed.  So has the $rebuild parameter
@@ -258,6 +317,11 @@ because of Phabricator reports.
   Use the mediawiki.String module instead.
 * mw.language.specialCharacters, deprecated in 1.33, has been removed.
   Use require( 'mediawiki.language.specialCharacters' ) instead.
+* The jquery.colorUtil module was removed. Use jquery.color instead.
+* The jquery.checkboxShiftClick module was removed. The functionality
+  is provided by mediawiki.page.ready instead (T232688).
+* The 'jquery.accessKeyLabel' module has been removed. This jQuery
+  plugin now ships as part of the 'mediawiki.util' module bundle.
 * EditPage::submit(), deprecated in 1.29, has been removed. Use $this->edit()
   directly.
 * HTMLForm::getErrors(), deprecated in 1.28, has been removed. Use
@@ -371,7 +435,22 @@ because of Phabricator reports.
   should only be used to unblock a blocked user.
 * Parameters for index.php from PATH_INFO, such as the title, are no longer
   written to $_GET.
-* …
+* The selectFields() methods on classes LocalFile, ArchivedFile, OldLocalFile,
+  DatabaseBlock, and RecentChange, deprecated in 1.31, have been removed. Use
+  the corresponding getQueryInfo() methods instead.
+* The following methods on Revision, deprecated since 1.31, have been removed.
+  Use RevisionStore::getQueryInfo() or RevisionStore::getArchiveQueryInfo()
+  instead.
+  * Revision::userJoinCond()
+  * Revision::pageJoinCond()
+  * Revision::selectFields()
+  * Revision::selectArchiveFields()
+  * Revision::selectTextFields()
+  * Revision::selectPageFields()
+  * Revision::selectUserFields()
+* User::setNewpassword(), deprecated in 1.27 has been removed.
+* The ObjectCache::getMainWANInstance and ObjectCache::getMainStashInstance
+  functions, deprecated since 1.28, have been removed.
 
 === Deprecations in 1.34 ===
 * The MWNamespace class is deprecated. Use NamespaceInfo.
@@ -427,8 +506,6 @@ because of Phabricator reports.
 * ResourceLoaderContext::getConfig and ResourceLoaderContext::getLogger have
   been deprecated. Inside ResourceLoaderModule subclasses, use the local methods
   instead. Elsewhere, use the methods from the ResourceLoader class.
-* The 'jquery.accessKeyLabel' module has been deprecated. This jQuery
-  plugin is now ships as part of the 'mediawiki.util' module bundle.
 * The Profiler::setTemplated and Profiler::getTemplated methods have been
   deprecated. Use Profiler::setAllowOutput and Profiler::getAllowOutput
   instead.
@@ -492,13 +569,36 @@ because of Phabricator reports.
   or extend RevisionSearchResult.
 * Skin::getSkinNameMessages() is deprecated and no longer used.
 * The mediawiki.RegExp module is deprecated; use mw.util.escapeRegExp() instead.
+* Specifying a SpecialPage object for the list of special pages (either through
+  the SpecialPage_initList hook or by adding to $wgSpecialPages) is now
+  deprecated.
+* Use of ActorMigration with 'ar_user', 'img_user', 'oi_user', 'fa_user',
+  'rc_user', 'log_user', and 'ipb_by' is deprecated. Queries should be adjusted
+  to use the corresponding actor fields directly. Note that use with
+  'rev_user' is *not* deprecated at this time.
+* Specifying both the class and factory parameters for
+  ApiModuleManager::addModule is now deprecated. The ObjectFactory spec should
+  be used instead.
+* The UserIsHidden hook is deprecated. Use GetUserBlock instead, and add a
+  system block that hides the user.
+* The GetBlockedStatus hook is deprecated. Use GetUserBlock instead, to add or
+  remove a block.
+* $wgContentHandlerUseDB is deprecated and should always be true.
+* StreamFile::send404Message() and StreamFile::parseRange() are now deprecated.
+  Use HTTPFileStreamer::send404Message() and HTTPFileStreamer::parseRange()
+  respectively instead.
+* Global variable $wgSysopEmailBans is deprecated; to allow sysops to ban
+  users from sending emails, use
+  $wgGroupPermissions['sysop']['blockemail'] = true;
+* ApiQueryBase::showHiddenUsersAddBlockInfo() is deprecated. Use
+  ApiQueryBlockInfoTrait instead.
 
 === Other changes in 1.34 ===
 * …
 
 == Compatibility ==
-MediaWiki 1.34 requires PHP 7.0.13 or later. Although HHVM 3.18.5 or later is
-supported, it is generally advised to use PHP 7.0.13 or later for long term
+MediaWiki 1.34 requires PHP 7.2.0 or later. Although HHVM 3.18.5 or later is
+supported, it is generally advised to use PHP 7.2.0 or later for long term
 support. It also requires the following PHP extensions:
 
 * ctype
diff --git a/api.php b/api.php
index fe13263..6f4bac3 100644 (file)
--- a/api.php
+++ b/api.php
@@ -31,6 +31,7 @@ use MediaWiki\Logger\LegacyLogger;
 
 // So extensions (and other code) can check whether they're running in API mode
 define( 'MW_API', true );
+define( 'MW_ENTRY_POINT', 'api' );
 
 require __DIR__ . '/includes/WebStart.php';
 
index 0255a23..7ff29ce 100644 (file)
@@ -20,7 +20,6 @@ $wgAutoloadLocalClasses = [
        'AllMessagesTablePager' => __DIR__ . '/includes/specials/pagers/AllMessagesTablePager.php',
        'AllTrans' => __DIR__ . '/maintenance/language/alltrans.php',
        'AlphabeticPager' => __DIR__ . '/includes/pager/AlphabeticPager.php',
-       'AncientPagesPage' => __DIR__ . '/includes/specials/SpecialAncientpages.php',
        'AnsiTermColorer' => __DIR__ . '/maintenance/term/MWTerm.php',
        'ApiAMCreateAccount' => __DIR__ . '/includes/api/ApiAMCreateAccount.php',
        'ApiAuthManagerHelper' => __DIR__ . '/includes/api/ApiAuthManagerHelper.php',
@@ -90,6 +89,7 @@ $wgAutoloadLocalClasses = [
        'ApiQueryBacklinks' => __DIR__ . '/includes/api/ApiQueryBacklinks.php',
        'ApiQueryBacklinksprop' => __DIR__ . '/includes/api/ApiQueryBacklinksprop.php',
        'ApiQueryBase' => __DIR__ . '/includes/api/ApiQueryBase.php',
+       'ApiQueryBlockInfoTrait' => __DIR__ . '/includes/api/ApiQueryBlockInfoTrait.php',
        'ApiQueryBlocks' => __DIR__ . '/includes/api/ApiQueryBlocks.php',
        'ApiQueryCategories' => __DIR__ . '/includes/api/ApiQueryCategories.php',
        'ApiQueryCategoryInfo' => __DIR__ . '/includes/api/ApiQueryCategoryInfo.php',
@@ -215,7 +215,6 @@ $wgAutoloadLocalClasses = [
        'BlockLogFormatter' => __DIR__ . '/includes/logging/BlockLogFormatter.php',
        'BmpHandler' => __DIR__ . '/includes/media/BmpHandler.php',
        'BotPassword' => __DIR__ . '/includes/user/BotPassword.php',
-       'BrokenRedirectsPage' => __DIR__ . '/includes/specials/SpecialBrokenRedirects.php',
        'BufferingStatsdDataFactory' => __DIR__ . '/includes/libs/stats/BufferingStatsdDataFactory.php',
        'CLIParser' => __DIR__ . '/maintenance/parse.php',
        'CSSMin' => __DIR__ . '/includes/libs/CSSMin.php',
@@ -274,6 +273,7 @@ $wgAutoloadLocalClasses = [
        'CleanupInvalidDbKeys' => __DIR__ . '/maintenance/cleanupInvalidDbKeys.php',
        'CleanupPreferences' => __DIR__ . '/maintenance/cleanupPreferences.php',
        'CleanupRemovedModules' => __DIR__ . '/maintenance/cleanupRemovedModules.php',
+       'CleanupRevActorPage' => __DIR__ . '/maintenance/cleanupRevActorPage.php',
        'CleanupSpam' => __DIR__ . '/maintenance/cleanupSpam.php',
        'CleanupUploadStash' => __DIR__ . '/maintenance/cleanupUploadStash.php',
        'CleanupUsersWithNoId' => __DIR__ . '/maintenance/cleanupUsersWithNoId.php',
@@ -298,6 +298,7 @@ $wgAutoloadLocalClasses = [
        'ComposerJson' => __DIR__ . '/includes/libs/composer/ComposerJson.php',
        'ComposerLock' => __DIR__ . '/includes/libs/composer/ComposerLock.php',
        'ComposerPackageModifier' => __DIR__ . '/includes/composer/ComposerPackageModifier.php',
+       'ComposerPhpunitXmlCoverageEdit' => __DIR__ . '/includes/composer/ComposerPhpunitXmlCoverageEdit.php',
        'ComposerVendorHtaccessCreator' => __DIR__ . '/includes/composer/ComposerVendorHtaccessCreator.php',
        'ComposerVersionNormalizer' => __DIR__ . '/includes/composer/ComposerVersionNormalizer.php',
        'CompressOld' => __DIR__ . '/maintenance/storage/compressOld.php',
@@ -365,7 +366,6 @@ $wgAutoloadLocalClasses = [
        'DateFormats' => __DIR__ . '/maintenance/language/date-formats.php',
        'DateFormatter' => __DIR__ . '/includes/parser/DateFormatter.php',
        'DateFormatterFactory' => __DIR__ . '/includes/parser/DateFormatterFactory.php',
-       'DeadendPagesPage' => __DIR__ . '/includes/specials/SpecialDeadendpages.php',
        'DeduplicateArchiveRevId' => __DIR__ . '/maintenance/deduplicateArchiveRevId.php',
        'DeferrableCallback' => __DIR__ . '/includes/deferred/DeferrableCallback.php',
        'DeferrableUpdate' => __DIR__ . '/includes/deferred/DeferrableUpdate.php',
@@ -387,7 +387,6 @@ $wgAutoloadLocalClasses = [
        'DeletePageJob' => __DIR__ . '/includes/jobqueue/jobs/DeletePageJob.php',
        'DeleteSelfExternals' => __DIR__ . '/maintenance/deleteSelfExternals.php',
        'DeletedContribsPager' => __DIR__ . '/includes/specials/pagers/DeletedContribsPager.php',
-       'DeletedContributionsPage' => __DIR__ . '/includes/specials/SpecialDeletedContributions.php',
        'DependencyWrapper' => __DIR__ . '/includes/cache/dependency/DependencyWrapper.php',
        'DeprecatedGlobal' => __DIR__ . '/includes/DeprecatedGlobal.php',
        'DeprecatedInterfaceFinder' => __DIR__ . '/maintenance/findDeprecated.php',
@@ -413,7 +412,6 @@ $wgAutoloadLocalClasses = [
        'DjVuImage' => __DIR__ . '/includes/media/DjVuImage.php',
        'DnsSrvDiscoverer' => __DIR__ . '/includes/libs/DnsSrvDiscoverer.php',
        'DoubleRedirectJob' => __DIR__ . '/includes/jobqueue/jobs/DoubleRedirectJob.php',
-       'DoubleRedirectsPage' => __DIR__ . '/includes/specials/SpecialDoubleRedirects.php',
        'DummyLinker' => __DIR__ . '/includes/DummyLinker.php',
        'DummySearchIndexFieldDefinition' => __DIR__ . '/includes/search/DummySearchIndexFieldDefinition.php',
        'DummyTermColorer' => __DIR__ . '/maintenance/term/MWTerm.php',
@@ -446,8 +444,6 @@ $wgAutoloadLocalClasses = [
        'EditPage' => __DIR__ . '/includes/EditPage.php',
        'EditWatchlistCheckboxSeriesField' => __DIR__ . '/includes/specials/formfields/EditWatchlistCheckboxSeriesField.php',
        'EditWatchlistNormalHTMLForm' => __DIR__ . '/includes/specials/forms/EditWatchlistNormalHTMLForm.php',
-       'EmailConfirmation' => __DIR__ . '/includes/specials/SpecialConfirmemail.php',
-       'EmailInvalidation' => __DIR__ . '/includes/specials/SpecialEmailInvalidate.php',
        'EmailNotification' => __DIR__ . '/includes/mail/EmailNotification.php',
        'EmaillingJob' => __DIR__ . '/includes/jobqueue/jobs/EmaillingJob.php',
        'EmptyBagOStuff' => __DIR__ . '/includes/libs/objectcache/EmptyBagOStuff.php',
@@ -504,7 +500,6 @@ $wgAutoloadLocalClasses = [
        'FeedItem' => __DIR__ . '/includes/changes/FeedItem.php',
        'FeedUtils' => __DIR__ . '/includes/FeedUtils.php',
        'FetchText' => __DIR__ . '/maintenance/fetchText.php',
-       'FewestrevisionsPage' => __DIR__ . '/includes/specials/SpecialFewestrevisions.php',
        'Field' => __DIR__ . '/includes/libs/rdbms/field/Field.php',
        'File' => __DIR__ . '/includes/filerepo/file/File.php',
        'FileAwareNodeVisitor' => __DIR__ . '/maintenance/findDeprecated.php',
@@ -524,7 +519,6 @@ $wgAutoloadLocalClasses = [
        'FileContentsHasher' => __DIR__ . '/includes/utils/FileContentsHasher.php',
        'FileDeleteForm' => __DIR__ . '/includes/FileDeleteForm.php',
        'FileDependency' => __DIR__ . '/includes/cache/dependency/FileDependency.php',
-       'FileDuplicateSearchPage' => __DIR__ . '/includes/specials/SpecialFileDuplicateSearch.php',
        'FileJournal' => __DIR__ . '/includes/libs/filebackend/filejournal/FileJournal.php',
        'FileOp' => __DIR__ . '/includes/libs/filebackend/fileop/FileOp.php',
        'FileOpBatch' => __DIR__ . '/includes/libs/filebackend/FileOpBatch.php',
@@ -784,14 +778,11 @@ $wgAutoloadLocalClasses = [
        'LinkCache' => __DIR__ . '/includes/cache/LinkCache.php',
        'LinkFilter' => __DIR__ . '/includes/LinkFilter.php',
        'LinkHolderArray' => __DIR__ . '/includes/parser/LinkHolderArray.php',
-       'LinkSearchPage' => __DIR__ . '/includes/specials/SpecialLinkSearch.php',
        'Linker' => __DIR__ . '/includes/Linker.php',
        'LinksDeletionUpdate' => __DIR__ . '/includes/deferred/LinksDeletionUpdate.php',
        'LinksUpdate' => __DIR__ . '/includes/deferred/LinksUpdate.php',
-       'ListDuplicatedFilesPage' => __DIR__ . '/includes/specials/SpecialListDuplicatedFiles.php',
        'ListToggle' => __DIR__ . '/includes/ListToggle.php',
        'ListVariants' => __DIR__ . '/maintenance/language/listVariants.php',
-       'ListredirectsPage' => __DIR__ . '/includes/specials/SpecialListredirects.php',
        'LoadBalancer' => __DIR__ . '/includes/libs/rdbms/loadbalancer/LoadBalancer.php',
        'LoadBalancerSingle' => __DIR__ . '/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php',
        'LocalFile' => __DIR__ . '/includes/filerepo/file/LocalFile.php',
@@ -817,9 +808,6 @@ $wgAutoloadLocalClasses = [
        'LoggedUpdateMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'LoginHelper' => __DIR__ . '/includes/specials/helpers/LoginHelper.php',
        'LoginSignupSpecialPage' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
-       'LonelyPagesPage' => __DIR__ . '/includes/specials/SpecialLonelypages.php',
-       'LongPagesPage' => __DIR__ . '/includes/specials/SpecialLongpages.php',
-       'MIMEsearchPage' => __DIR__ . '/includes/specials/SpecialMIMEsearch.php',
        'MSCompoundFileReader' => __DIR__ . '/includes/libs/mime/MSCompoundFileReader.php',
        'MWCallableUpdate' => __DIR__ . '/includes/deferred/MWCallableUpdate.php',
        'MWCallbackStream' => __DIR__ . '/includes/http/MWCallbackStream.php',
@@ -866,7 +854,6 @@ $wgAutoloadLocalClasses = [
        'McrUndoAction' => __DIR__ . '/includes/actions/McrUndoAction.php',
        'MediaHandler' => __DIR__ . '/includes/media/MediaHandler.php',
        'MediaHandlerFactory' => __DIR__ . '/includes/media/MediaHandlerFactory.php',
-       'MediaStatisticsPage' => __DIR__ . '/includes/specials/SpecialMediaStatistics.php',
        'MediaTransformError' => __DIR__ . '/includes/media/MediaTransformError.php',
        'MediaTransformInvalidParametersException' => __DIR__ . '/includes/media/MediaTransformInvalidParametersException.php',
        'MediaTransformOutput' => __DIR__ . '/includes/media/MediaTransformOutput.php',
@@ -1001,13 +988,7 @@ $wgAutoloadLocalClasses = [
        'MigrateUserGroup' => __DIR__ . '/maintenance/migrateUserGroup.php',
        'MimeAnalyzer' => __DIR__ . '/includes/libs/mime/MimeAnalyzer.php',
        'MinifyScript' => __DIR__ . '/maintenance/minify.php',
-       'MostcategoriesPage' => __DIR__ . '/includes/specials/SpecialMostcategories.php',
        'MostimagesPage' => __DIR__ . '/includes/specials/SpecialMostimages.php',
-       'MostinterwikisPage' => __DIR__ . '/includes/specials/SpecialMostinterwikis.php',
-       'MostlinkedCategoriesPage' => __DIR__ . '/includes/specials/SpecialMostlinkedcategories.php',
-       'MostlinkedPage' => __DIR__ . '/includes/specials/SpecialMostlinked.php',
-       'MostlinkedTemplatesPage' => __DIR__ . '/includes/specials/SpecialMostlinkedtemplates.php',
-       'MostrevisionsPage' => __DIR__ . '/includes/specials/SpecialMostrevisions.php',
        'MoveBatch' => __DIR__ . '/maintenance/moveBatch.php',
        'MoveFileOp' => __DIR__ . '/includes/libs/filebackend/fileop/MoveFileOp.php',
        'MoveLogFormatter' => __DIR__ . '/includes/logging/MoveLogFormatter.php',
@@ -1330,7 +1311,6 @@ $wgAutoloadLocalClasses = [
        'SerializedValueContainer' => __DIR__ . '/includes/libs/objectcache/serialized/SerializedValueContainer.php',
        'SevenZipStream' => __DIR__ . '/maintenance/includes/SevenZipStream.php',
        'ShiConverter' => __DIR__ . '/languages/classes/LanguageShi.php',
-       'ShortPagesPage' => __DIR__ . '/includes/specials/SpecialShortpages.php',
        'ShowJobs' => __DIR__ . '/maintenance/showJobs.php',
        'ShowSiteStats' => __DIR__ . '/maintenance/showSiteStats.php',
        'Site' => __DIR__ . '/includes/site/Site.php',
@@ -1357,6 +1337,7 @@ $wgAutoloadLocalClasses = [
        'SpecialAllMessages' => __DIR__ . '/includes/specials/SpecialAllMessages.php',
        'SpecialAllMyUploads' => __DIR__ . '/includes/specials/redirects/SpecialAllMyUploads.php',
        'SpecialAllPages' => __DIR__ . '/includes/specials/SpecialAllPages.php',
+       'SpecialAncientPages' => __DIR__ . '/includes/specials/SpecialAncientPages.php',
        'SpecialApiHelp' => __DIR__ . '/includes/specials/SpecialApiHelp.php',
        'SpecialApiSandbox' => __DIR__ . '/includes/specials/SpecialApiSandbox.php',
        'SpecialAutoblockList' => __DIR__ . '/includes/specials/SpecialAutoblockList.php',
@@ -1365,6 +1346,7 @@ $wgAutoloadLocalClasses = [
        'SpecialBlockList' => __DIR__ . '/includes/specials/SpecialBlockList.php',
        'SpecialBookSources' => __DIR__ . '/includes/specials/SpecialBookSources.php',
        'SpecialBotPasswords' => __DIR__ . '/includes/specials/SpecialBotPasswords.php',
+       'SpecialBrokenRedirects' => __DIR__ . '/includes/specials/SpecialBrokenRedirects.php',
        'SpecialCachedPage' => __DIR__ . '/includes/specials/SpecialCachedPage.php',
        'SpecialCategories' => __DIR__ . '/includes/specials/SpecialCategories.php',
        'SpecialChangeContentModel' => __DIR__ . '/includes/specials/SpecialChangeContentModel.php',
@@ -1372,35 +1354,55 @@ $wgAutoloadLocalClasses = [
        'SpecialChangeEmail' => __DIR__ . '/includes/specials/SpecialChangeEmail.php',
        'SpecialChangePassword' => __DIR__ . '/includes/specials/SpecialChangePassword.php',
        'SpecialComparePages' => __DIR__ . '/includes/specials/SpecialComparePages.php',
+       'SpecialConfirmEmail' => __DIR__ . '/includes/specials/SpecialConfirmEmail.php',
        'SpecialContributions' => __DIR__ . '/includes/specials/SpecialContributions.php',
        'SpecialCreateAccount' => __DIR__ . '/includes/specials/SpecialCreateAccount.php',
+       'SpecialDeadendPages' => __DIR__ . '/includes/specials/SpecialDeadendPages.php',
+       'SpecialDeletedContributions' => __DIR__ . '/includes/specials/SpecialDeletedContributions.php',
        'SpecialDiff' => __DIR__ . '/includes/specials/SpecialDiff.php',
+       'SpecialDoubleRedirects' => __DIR__ . '/includes/specials/SpecialDoubleRedirects.php',
        'SpecialEditTags' => __DIR__ . '/includes/specials/SpecialEditTags.php',
        'SpecialEditWatchlist' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
+       'SpecialEmailInvalidate' => __DIR__ . '/includes/specials/SpecialEmailInvalidate.php',
        'SpecialEmailUser' => __DIR__ . '/includes/specials/SpecialEmailUser.php',
        'SpecialExpandTemplates' => __DIR__ . '/includes/specials/SpecialExpandTemplates.php',
        'SpecialExport' => __DIR__ . '/includes/specials/SpecialExport.php',
+       'SpecialFewestRevisions' => __DIR__ . '/includes/specials/SpecialFewestRevisions.php',
+       'SpecialFileDuplicateSearch' => __DIR__ . '/includes/specials/SpecialFileDuplicateSearch.php',
        'SpecialFilepath' => __DIR__ . '/includes/specials/SpecialFilepath.php',
        'SpecialGoToInterwiki' => __DIR__ . '/includes/specials/SpecialGoToInterwiki.php',
        'SpecialImport' => __DIR__ . '/includes/specials/SpecialImport.php',
        'SpecialJavaScriptTest' => __DIR__ . '/includes/specials/SpecialJavaScriptTest.php',
        'SpecialLinkAccounts' => __DIR__ . '/includes/specials/SpecialLinkAccounts.php',
+       'SpecialLinkSearch' => __DIR__ . '/includes/specials/SpecialLinkSearch.php',
        'SpecialListAdmins' => __DIR__ . '/includes/specials/redirects/SpecialListAdmins.php',
        'SpecialListBots' => __DIR__ . '/includes/specials/redirects/SpecialListBots.php',
+       'SpecialListDuplicatedFiles' => __DIR__ . '/includes/specials/SpecialListDuplicatedFiles.php',
        'SpecialListFiles' => __DIR__ . '/includes/specials/SpecialListFiles.php',
        'SpecialListGrants' => __DIR__ . '/includes/specials/SpecialListGrants.php',
        'SpecialListGroupRights' => __DIR__ . '/includes/specials/SpecialListGroupRights.php',
+       'SpecialListRedirects' => __DIR__ . '/includes/specials/SpecialListRedirects.php',
        'SpecialListUsers' => __DIR__ . '/includes/specials/SpecialListUsers.php',
        'SpecialLockdb' => __DIR__ . '/includes/specials/SpecialLockdb.php',
        'SpecialLog' => __DIR__ . '/includes/specials/SpecialLog.php',
+       'SpecialLonelyPages' => __DIR__ . '/includes/specials/SpecialLonelyPages.php',
+       'SpecialLongPages' => __DIR__ . '/includes/specials/SpecialLongPages.php',
+       'SpecialMIMESearch' => __DIR__ . '/includes/specials/SpecialMIMESearch.php',
+       'SpecialMediaStatistics' => __DIR__ . '/includes/specials/SpecialMediaStatistics.php',
        'SpecialMergeHistory' => __DIR__ . '/includes/specials/SpecialMergeHistory.php',
+       'SpecialMostCategories' => __DIR__ . '/includes/specials/SpecialMostCategories.php',
+       'SpecialMostInterwikis' => __DIR__ . '/includes/specials/SpecialMostInterwikis.php',
+       'SpecialMostLinked' => __DIR__ . '/includes/specials/SpecialMostLinked.php',
+       'SpecialMostLinkedCategories' => __DIR__ . '/includes/specials/SpecialMostLinkedCategories.php',
+       'SpecialMostLinkedTemplates' => __DIR__ . '/includes/specials/SpecialMostLinkedTemplates.php',
+       'SpecialMostRevisions' => __DIR__ . '/includes/specials/SpecialMostRevisions.php',
        'SpecialMute' => __DIR__ . '/includes/specials/SpecialMute.php',
        'SpecialMyLanguage' => __DIR__ . '/includes/specials/SpecialMyLanguage.php',
        'SpecialMycontributions' => __DIR__ . '/includes/specials/redirects/SpecialMycontributions.php',
        'SpecialMypage' => __DIR__ . '/includes/specials/redirects/SpecialMypage.php',
        'SpecialMytalk' => __DIR__ . '/includes/specials/redirects/SpecialMytalk.php',
        'SpecialMyuploads' => __DIR__ . '/includes/specials/redirects/SpecialMyuploads.php',
-       'SpecialNewFiles' => __DIR__ . '/includes/specials/SpecialNewimages.php',
+       'SpecialNewFiles' => __DIR__ . '/includes/specials/SpecialNewFiles.php',
        'SpecialNewSection' => __DIR__ . '/includes/specials/SpecialNewSection.php',
        'SpecialNewpages' => __DIR__ . '/includes/specials/SpecialNewpages.php',
        'SpecialPage' => __DIR__ . '/includes/specialpage/SpecialPage.php',
@@ -1428,22 +1430,34 @@ $wgAutoloadLocalClasses = [
        'SpecialRevisionDelete' => __DIR__ . '/includes/specials/SpecialRevisionDelete.php',
        'SpecialRunJobs' => __DIR__ . '/includes/specials/SpecialRunJobs.php',
        'SpecialSearch' => __DIR__ . '/includes/specials/SpecialSearch.php',
+       'SpecialShortPages' => __DIR__ . '/includes/specials/SpecialShortPages.php',
        'SpecialSpecialpages' => __DIR__ . '/includes/specials/SpecialSpecialpages.php',
        'SpecialStatistics' => __DIR__ . '/includes/specials/SpecialStatistics.php',
        'SpecialTags' => __DIR__ . '/includes/specials/SpecialTags.php',
        'SpecialTrackingCategories' => __DIR__ . '/includes/specials/SpecialTrackingCategories.php',
        'SpecialUnblock' => __DIR__ . '/includes/specials/SpecialUnblock.php',
+       'SpecialUncategorizedCategories' => __DIR__ . '/includes/specials/SpecialUncategorizedCategories.php',
+       'SpecialUncategorizedImages' => __DIR__ . '/includes/specials/SpecialUncategorizedImages.php',
+       'SpecialUncategorizedPages' => __DIR__ . '/includes/specials/SpecialUncategorizedPages.php',
+       'SpecialUncategorizedTemplates' => __DIR__ . '/includes/specials/SpecialUncategorizedTemplates.php',
        'SpecialUndelete' => __DIR__ . '/includes/specials/SpecialUndelete.php',
        'SpecialUnlinkAccounts' => __DIR__ . '/includes/specials/SpecialUnlinkAccounts.php',
        'SpecialUnlockdb' => __DIR__ . '/includes/specials/SpecialUnlockdb.php',
+       'SpecialUnusedCategories' => __DIR__ . '/includes/specials/SpecialUnusedCategories.php',
+       'SpecialUnusedImages' => __DIR__ . '/includes/specials/SpecialUnusedImages.php',
+       'SpecialUnusedTemplates' => __DIR__ . '/includes/specials/SpecialUnusedTemplates.php',
+       'SpecialUnwatchedPages' => __DIR__ . '/includes/specials/SpecialUnwatchedPages.php',
        'SpecialUpload' => __DIR__ . '/includes/specials/SpecialUpload.php',
        'SpecialUploadStash' => __DIR__ . '/includes/specials/SpecialUploadStash.php',
        'SpecialUploadStashTooLargeException' => __DIR__ . '/includes/specials/exception/SpecialUploadStashTooLargeException.php',
        'SpecialUserLogin' => __DIR__ . '/includes/specials/SpecialUserLogin.php',
        'SpecialUserLogout' => __DIR__ . '/includes/specials/SpecialUserLogout.php',
        'SpecialVersion' => __DIR__ . '/includes/specials/SpecialVersion.php',
+       'SpecialWantedCategories' => __DIR__ . '/includes/specials/SpecialWantedCategories.php',
+       'SpecialWantedTemplates' => __DIR__ . '/includes/specials/SpecialWantedTemplates.php',
        'SpecialWatchlist' => __DIR__ . '/includes/specials/SpecialWatchlist.php',
        'SpecialWhatLinksHere' => __DIR__ . '/includes/specials/SpecialWhatLinksHere.php',
+       'SpecialWithoutInterwiki' => __DIR__ . '/includes/specials/SpecialWithoutInterwiki.php',
        'SqlBagOStuff' => __DIR__ . '/includes/objectcache/SqlBagOStuff.php',
        'SqlSearchResult' => __DIR__ . '/includes/search/SqlSearchResult.php',
        'SqlSearchResultSet' => __DIR__ . '/includes/search/SqlSearchResultSet.php',
@@ -1516,10 +1530,6 @@ $wgAutoloadLocalClasses = [
        'UDPTransport' => __DIR__ . '/includes/libs/UDPTransport.php',
        'UIDGenerator' => __DIR__ . '/includes/utils/UIDGenerator.php',
        'UcdXmlReader' => __DIR__ . '/maintenance/language/generateCollationData.php',
-       'UncategorizedCategoriesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedcategories.php',
-       'UncategorizedImagesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedimages.php',
-       'UncategorizedPagesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedpages.php',
-       'UncategorizedTemplatesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedtemplates.php',
        'Undelete' => __DIR__ . '/maintenance/undelete.php',
        'UnifiedDiffFormatter' => __DIR__ . '/includes/diff/UnifiedDiffFormatter.php',
        'UnknownContent' => __DIR__ . '/includes/content/UnknownContent.php',
@@ -1528,11 +1538,7 @@ $wgAutoloadLocalClasses = [
        'UnprotectAction' => __DIR__ . '/includes/actions/UnprotectAction.php',
        'UnregisteredLocalFile' => __DIR__ . '/includes/filerepo/file/UnregisteredLocalFile.php',
        'UnsupportedSlotDiffRenderer' => __DIR__ . '/includes/diff/UnsupportedSlotDiffRenderer.php',
-       'UnusedCategoriesPage' => __DIR__ . '/includes/specials/SpecialUnusedcategories.php',
-       'UnusedimagesPage' => __DIR__ . '/includes/specials/SpecialUnusedimages.php',
-       'UnusedtemplatesPage' => __DIR__ . '/includes/specials/SpecialUnusedtemplates.php',
        'UnwatchAction' => __DIR__ . '/includes/actions/UnwatchAction.php',
-       'UnwatchedpagesPage' => __DIR__ . '/includes/specials/SpecialUnwatchedpages.php',
        'UpdateArticleCount' => __DIR__ . '/maintenance/updateArticleCount.php',
        'UpdateCollation' => __DIR__ . '/maintenance/updateCollation.php',
        'UpdateDoubleWidthSearch' => __DIR__ . '/maintenance/updateDoubleWidthSearch.php',
@@ -1596,11 +1602,9 @@ $wgAutoloadLocalClasses = [
        'WANCacheReapUpdate' => __DIR__ . '/includes/deferred/WANCacheReapUpdate.php',
        'WANObjectCache' => __DIR__ . '/includes/libs/objectcache/wancache/WANObjectCache.php',
        'WANObjectCacheReaper' => __DIR__ . '/includes/libs/objectcache/wancache/WANObjectCacheReaper.php',
-       'WantedCategoriesPage' => __DIR__ . '/includes/specials/SpecialWantedcategories.php',
        'WantedFilesPage' => __DIR__ . '/includes/specials/SpecialWantedfiles.php',
        'WantedPagesPage' => __DIR__ . '/includes/specials/SpecialWantedpages.php',
        'WantedQueryPage' => __DIR__ . '/includes/specialpage/WantedQueryPage.php',
-       'WantedTemplatesPage' => __DIR__ . '/includes/specials/SpecialWantedtemplates.php',
        'WatchAction' => __DIR__ . '/includes/actions/WatchAction.php',
        'WatchedItem' => __DIR__ . '/includes/watcheditem/WatchedItem.php',
        'WatchedItemQueryService' => __DIR__ . '/includes/watcheditem/WatchedItemQueryService.php',
@@ -1704,7 +1708,6 @@ $wgAutoloadLocalClasses = [
        'WikitextContentHandler' => __DIR__ . '/includes/content/WikitextContentHandler.php',
        'WikitextLogFormatter' => __DIR__ . '/includes/logging/WikitextLogFormatter.php',
        'WinCacheBagOStuff' => __DIR__ . '/includes/libs/objectcache/WinCacheBagOStuff.php',
-       'WithoutInterwikiPage' => __DIR__ . '/includes/specials/SpecialWithoutinterwiki.php',
        'WordLevelDiff' => __DIR__ . '/includes/diff/WordLevelDiff.php',
        'WrapOldPasswords' => __DIR__ . '/maintenance/wrapOldPasswords.php',
        'XCFHandler' => __DIR__ . '/includes/media/XCFHandler.php',
index ac89d71..5785873 100644 (file)
@@ -28,7 +28,7 @@
                "ext-xml": "*",
                "guzzlehttp/guzzle": "6.3.3",
                "liuggio/statsd-php-client": "1.0.18",
-               "oojs/oojs-ui": "0.34.0",
+               "oojs/oojs-ui": "0.34.1",
                "pear/mail": "1.4.1",
                "pear/mail_mime": "1.10.2",
                "pear/net_smtp": "1.8.1",
@@ -97,7 +97,8 @@
        "autoload": {
                "psr-0": {
                        "ComposerHookHandler": "includes/composer",
-                       "ComposerVendorHtaccessCreator": "includes/composer"
+                       "ComposerVendorHtaccessCreator": "includes/composer",
+                       "ComposerPhpunitXmlCoverageEdit":"includes/composer"
                }
        },
        "autoload-dev": {
                "phpunit": "phpunit",
                "phpunit:unit": "phpunit --colors=always --testsuite=core:unit,extensions:unit,skins:unit",
                "phpunit:integration": "phpunit --colors=always --testsuite=core:integration,extensions:integration,skins:integration",
-               "phpunit:coverage": "phpunit --testsuite=core:unit --exclude-group Dump,Broken"
+               "phpunit:coverage": "phpunit --testsuite=core:unit --exclude-group Dump,Broken",
+               "phpunit:coverage-edit": "ComposerPhpunitXmlCoverageEdit::onEvent"
        },
        "config": {
                "optimize-autoloader": true,
index 9ce016f..06701cd 100644 (file)
                },
                "SpecialPages": {
                        "type": "object",
-                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name or to ObjectFactory spec)"
                },
                "AutoloadNamespaces": {
                        "type": "object",
index 9d874f4..56d274b 100644 (file)
                },
                "SpecialPages": {
                        "type": "object",
-                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name or to ObjectFactory spec)"
                },
                "AutoloadNamespaces": {
                        "type": "object",
index b7ea02c..55ba06e 100644 (file)
@@ -1585,7 +1585,8 @@ entitled to be in.
 $user: user to promote.
 &$promote: groups that will be added.
 
-'GetBlockedStatus': after loading blocking status of an user from the database
+'GetBlockedStatus': DEPRECATED since 1.34 - use GetUserBlock instead. After
+loading blocking status of a user from the database
 &$user: user (object) being checked
 
 'GetCacheVaryCookies': Get cookies that should vary cache options.
@@ -2827,6 +2828,7 @@ or request state must be added through MakeGlobalVariablesScript instead.
 Skin is made available for skin specific config.
 &$vars: [ variable name => value ]
 $skin: Skin
+$config: Config object (since 1.34)
 
 'ResourceLoaderJqueryMsgModuleMagicWords': Called in
 ResourceLoaderJqueryMsgModule to allow adding magic words for jQueryMsg.
@@ -2919,7 +2921,7 @@ result augmentors.
 Note that lists should be in the format name => object and the names in both
   lists should be distinct.
 
-'SecondaryDataUpdates': DEPRECATED! Use RevisionDataUpdates or override
+'SecondaryDataUpdates': DEPRECATED since 1.32! Use RevisionDataUpdates or override
 ContentHandler::getSecondaryDataUpdates instead.
 Allows modification of the list of DataUpdates to perform when page content is modified.
 $title: Title of the page that is being edited.
@@ -3728,7 +3730,9 @@ $ip: User's IP address
 false if a UserGetRights hook might remove the named right.
 $right: The user right being checked
 
-'UserIsHidden': Check if the user's name should be hidden. See User::isHidden().
+'UserIsHidden': DEPRECATED since 1.34 - use GetUserBlock instead, and add a
+system block that hides the user. Check if the user's name should be hidden.
+See User::isHidden().
 $user: User in question.
 &$hidden: Set true if the user's name should be hidden.
 
@@ -3965,7 +3969,7 @@ dumps. One, and only one hook should set this, and return false.
 &$opts: Options to use for the query
 &$join: Join conditions
 
-'WikiPageDeletionUpdates': DEPRECATED! Use PageDeletionDataUpdates or
+'WikiPageDeletionUpdates': DEPRECATED since 1.32! Use PageDeletionDataUpdates or
 override ContentHandler::getDeletionDataUpdates instead.
 Manipulates the list of DeferrableUpdates to be applied when a page is deleted.
 $page: the WikiPage
index 6e45e4e..f23de4f 100644 (file)
@@ -39,6 +39,7 @@
  */
 
 define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
+define( 'MW_ENTRY_POINT', 'img_auth' );
 require __DIR__ . '/includes/WebStart.php';
 
 # Set action base paths so that WebRequest::getPathInfo()
index 5dde8a0..c79074d 100644 (file)
@@ -28,15 +28,18 @@ use Wikimedia\Rdbms\IDatabase;
  * This class handles the logic for the actor table migration.
  *
  * This is not intended to be a long-term part of MediaWiki; it will be
- * deprecated and removed along with $wgActorTableSchemaMigrationStage.
+ * deprecated and removed once actor migration is complete.
  *
  * @since 1.31
+ * @since 1.34 Use with 'ar_user', 'img_user', 'oi_user', 'fa_user',
+ *  'rc_user', 'log_user', and 'ipb_by' is deprecated. Callers should
+ *  reference the corresponding actor fields directly.
  */
 class ActorMigration {
 
        /**
         * Constant for extensions to feature-test whether $wgActorTableSchemaMigrationStage
-        * expects MIGRATION_* or SCHEMA_COMPAT_*
+        * (in MW <1.34) expects MIGRATION_* or SCHEMA_COMPAT_*
         */
        const MIGRATION_STAGE_SCHEMA_COMPAT = 1;
 
@@ -68,6 +71,28 @@ class ActorMigration {
         */
        private static $formerTempTables = [];
 
+       /**
+        * Define fields that are deprecated for use with this class.
+        * @var (string|null)[] Keys are '$key', value is null for soft deprecation
+        *  or a string naming the deprecated version for hard deprecation.
+        */
+       private static $deprecated = [
+               'ar_user' => null, // 1.34
+               'img_user' => null, // 1.34
+               'oi_user' => null, // 1.34
+               'fa_user' => null, // 1.34
+               'rc_user' => null, // 1.34
+               'log_user' => null, // 1.34
+               'ipb_by' => null, // 1.34
+       ];
+
+       /**
+        * Define fields that are removed for use with this class.
+        * @var string[] Keys are '$key', value is the MediaWiki version in which
+        *  use was removed.
+        */
+       private static $removed = [];
+
        /**
         * Define fields that use non-standard mapping
         * @var array Keys are the user id column name, values are arrays with two
@@ -112,6 +137,21 @@ class ActorMigration {
                return MediaWikiServices::getInstance()->getActorMigration();
        }
 
+       /**
+        * Issue deprecation warning/error as appropriate.
+        * @param string $key
+        */
+       private static function checkDeprecation( $key ) {
+               if ( isset( self::$removed[$key] ) ) {
+                       throw new InvalidArgumentException(
+                               "Use of " . static::class . " for '$key' was removed in MediaWiki " . self::$removed[$key]
+                       );
+               }
+               if ( !empty( self::$deprecated[$key] ) ) {
+                       wfDeprecated( static::class . " for '$key'", self::$deprecated[$key], false, 3 );
+               }
+       }
+
        /**
         * Return an SQL condition to test if a user field is anonymous
         * @param string $field Field name or SQL fragment
@@ -152,6 +192,8 @@ class ActorMigration {
         * @phan-return array{tables:string[],fields:string[],joins:array}
         */
        public function getJoin( $key ) {
+               self::checkDeprecation( $key );
+
                if ( !isset( $this->joinCache[$key] ) ) {
                        $tables = [];
                        $fields = [];
@@ -203,6 +245,8 @@ class ActorMigration {
         * @return array to merge into `$values` to `IDatabase->update()` or `$a` to `IDatabase->insert()`
         */
        public function getInsertValues( IDatabase $dbw, $key, UserIdentity $user ) {
+               self::checkDeprecation( $key );
+
                if ( isset( self::$tempTables[$key] ) ) {
                        throw new InvalidArgumentException( "Must use getInsertValuesWithTempTable() for $key" );
                }
@@ -236,6 +280,8 @@ class ActorMigration {
         *    and extra fields needed for the temp table.
         */
        public function getInsertValuesWithTempTable( IDatabase $dbw, $key, UserIdentity $user ) {
+               self::checkDeprecation( $key );
+
                if ( isset( self::$formerTempTables[$key] ) ) {
                        wfDeprecated( __METHOD__ . " for $key", self::$formerTempTables[$key] );
                } elseif ( !isset( self::$tempTables[$key] ) ) {
@@ -319,6 +365,8 @@ class ActorMigration {
         *  All tables and joins are aliased, so `+` is safe to use.
         */
        public function getWhere( IDatabase $db, $key, $users, $useId = true ) {
+               self::checkDeprecation( $key );
+
                $tables = [];
                $conds = [];
                $joins = [];
index 323c5d3..0664652 100644 (file)
@@ -182,16 +182,7 @@ class AjaxResponse {
                        if ( $this->mConfig->get( 'UseCdn' ) ) {
                                # Expect explicit purge of the proxy cache, but require end user agents
                                # to revalidate against the proxy on each visit.
-                               # Surrogate-Control controls our CDN, Cache-Control downstream caches
-
-                               if ( $this->mConfig->get( 'UseESI' ) ) {
-                                       wfDeprecated( '$wgUseESI = true', '1.33' );
-                                       header( 'Surrogate-Control: max-age=' . $this->mCacheDuration . ', content="ESI/1.0"' );
-                                       header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
-                               } else {
-                                       header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
-                               }
-
+                               header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
                        } else {
                                # Let the client do the caching. Cache is not purged.
                                header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $this->mCacheDuration ) . " GMT" );
index 5d3fba7..fd1affc 100644 (file)
@@ -2733,27 +2733,22 @@ $wgExtensionInfoMTime = false;
  * although they are sometimes still referred to as Squid settings for
  * historical reasons.
  *
- * Achieving a high hit ratio with an HTTP proxy requires special
- * configuration. See https://www.mediawiki.org/wiki/Manual:Squid_caching for
- * more details.
+ * Achieving a high hit ratio with an HTTP proxy requires special configuration.
+ * See https://www.mediawiki.org/wiki/Manual:Performance_tuning#Page_view_caching
+ * for more details.
  *
  * @{
  */
 
 /**
  * Enable/disable CDN.
- * See https://www.mediawiki.org/wiki/Manual:Squid_caching
+ *
+ * See https://www.mediawiki.org/wiki/Manual:Performance_tuning#Page_view_caching
  *
  * @since 1.34 Renamed from $wgUseSquid.
  */
 $wgUseCdn = false;
 
-/**
- * If you run Squid3 with ESI support, enable this (default:false):
- * @deprecated in 1.33. This was a now-defunct experimental feature.
- */
-$wgUseESI = false;
-
 /**
  * Add X-Forwarded-Proto to the Vary and Key headers for API requests and
  * RSS/Atom feeds. Use this if you have an SSL termination setup
@@ -4450,7 +4445,8 @@ $wgCentralIdLookupProvider = 'local';
  * The checks supported by core are:
  *     - MinimalPasswordLength - Minimum length a user can set.
  *     - MinimumPasswordLengthToLogin - Passwords shorter than this will
- *             not be allowed to login, regardless if it is correct.
+ *             not be allowed to login, or offered a chance to reset their password
+ *             as part of the login workflow, regardless if it is correct.
  *     - MaximalPasswordLength - maximum length password a user is allowed
  *             to attempt. Prevents DoS attacks with pbkdf2.
  *     - PasswordCannotMatchUsername - Password cannot match the username.
@@ -4894,6 +4890,7 @@ $wgDefaultUserOptions = [
        'wllimit' => 250,
        'useeditwarning' => 1,
        'prefershttps' => 1,
+       'requireemail' => 0,
 ];
 
 /**
@@ -4963,6 +4960,15 @@ $wgSessionProviders = [
        ],
 ];
 
+/**
+ * Temporary feature flag that controls whether users will see a checkbox allowing them to
+ * require providing email during password resets.
+ *
+ * @deprecated This feature is under development, don't assume this flag's existence or function
+ *     outside of MediaWiki.
+ */
+$wgAllowRequiringEmailForResets = false;
+
 /** @} */ # end user accounts }
 
 /************************************************************************//**
@@ -4986,6 +4992,8 @@ $wgBlockAllowsUTEdit = true;
 
 /**
  * Allow sysops to ban users from accessing Emailuser
+ * @deprecated since 1.34; `$wgGroupPermissions['sysop']['blockemail'] = true;`
+ * should be used instead
  */
 $wgSysopEmailBans = true;
 
@@ -8615,6 +8623,7 @@ $wgContentHandlerTextFallback = 'ignore';
  * handling is less robust and less flexible.
  *
  * @since 1.21
+ * @deprecated since 1.34, and should always be set true.
  */
 $wgContentHandlerUseDB = true;
 
@@ -8985,24 +8994,6 @@ $wgMultiContentRevisionSchemaMigrationStage = SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_
  */
 $wgXmlDumpSchemaVersion = XML_DUMP_SCHEMA_VERSION_10;
 
-/**
- * Actor table schema migration stage.
- *
- * Use the SCHEMA_COMPAT_XXX flags. Supported values:
- * - SCHEMA_COMPAT_OLD
- * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
- * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
- * - SCHEMA_COMPAT_NEW
- *
- * Note that reading the old and new schema at the same time is not supported
- * in 1.32, but was (with significant query performance issues) in 1.31.
- *
- * @since 1.31
- * @since 1.32 changed allowed flags
- * @var int An appropriate combination of SCHEMA_COMPAT_XXX flags.
- */
-$wgActorTableSchemaMigrationStage = SCHEMA_COMPAT_NEW;
-
 /**
  * Flag to enable Partial Blocks. This allows an admin to prevent a user from editing specific pages
  * or namespaces.
index d93caa7..668de39 100644 (file)
@@ -27,7 +27,7 @@ ini_set( 'display_errors', 1 );
 
 global $wgDevelopmentWarnings, $wgShowExceptionDetails, $wgShowHostnames,
        $wgDebugRawPage, $wgCommandLineMode, $wgDebugLogFile,
-       $wgDBerrorLog, $wgDebugLogGroups;
+       $wgDBerrorLog, $wgDebugLogGroups, $wgLocalisationCacheConf;
 
 // Use of wfWarn() should cause tests to fail
 $wgDevelopmentWarnings = true;
@@ -74,3 +74,6 @@ $wgSQLMode = 'TRADITIONAL';
 
 // Disable legacy javascript globals in CI and for devs (T72470)
 $wgLegacyJavaScriptGlobals = false;
+
+// Localisation Cache to StaticArray (T218207)
+$wgLocalisationCacheConf['store'] = 'array';
index 6ae4371..d047f6e 100644 (file)
@@ -25,7 +25,7 @@ use MediaWiki\EditPage\TextboxBuilder;
 use MediaWiki\EditPage\TextConflictHelper;
 use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
-use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Revision\RevisionRecord;
 use Wikimedia\ScopedCallback;
 
 /**
@@ -1193,6 +1193,8 @@ class EditPage {
         * @since 1.21
         */
        protected function getContentObject( $def_content = null ) {
+               global $wgDisableAnonTalk;
+
                $content = false;
 
                $user = $this->context->getUser();
@@ -1292,8 +1294,11 @@ class EditPage {
                                                                                $undo
                                                                        )->inContentLanguage()->text();
                                                                } else {
+                                                                       $undoMessage = ( $undorev->getUser() === 0 && $wgDisableAnonTalk ) ?
+                                                                               'undo-summary-anon' :
+                                                                               'undo-summary';
                                                                        $undoSummary = $this->context->msg(
-                                                                               'undo-summary',
+                                                                               $undoMessage,
                                                                                $undo,
                                                                                $userText
                                                                        )->inContentLanguage()->text();
@@ -2737,7 +2742,7 @@ ERROR;
         * content.
         *
         * @param Content|null|bool|string $content
-        * @return string The editable text form of the content.
+        * @return string|false|null The editable text form of the content.
         *
         * @throws MWException If $content is not an instance of TextContent and
         *   $this->allowNonTextContent is not true.
@@ -4040,11 +4045,11 @@ ERROR;
 
                if ( $this->isConflict ) {
                        $conflict = Html::rawElement(
-                               'h2', [ 'id' => 'mw-previewconflict' ],
+                               'div', [ 'id' => 'mw-previewconflict', 'class' => 'warningbox' ],
                                $this->context->msg( 'previewconflict' )->escaped()
                        );
                } else {
-                       $conflict = '<hr />';
+                       $conflict = '';
                }
 
                $previewhead = Html::rawElement(
@@ -4053,7 +4058,9 @@ ERROR;
                                'h2', [ 'id' => 'mw-previewheader' ],
                                $this->context->msg( 'preview' )->escaped()
                        ) .
-                       $out->parseAsInterface( $note ) . $conflict
+                       Html::rawElement( 'div', [ 'class' => 'warningbox' ],
+                               $out->parseAsInterface( $note )
+                       ) . $conflict
                );
 
                $pageViewLang = $this->mTitle->getPageViewLanguage();
index 8efae4f..bfd1e2a 100644 (file)
@@ -21,7 +21,7 @@
  * @ingroup Feed
  */
 
-use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Revision\RevisionRecord;
 
 /**
  * Helper functions for feeds
index 1241e1c..e31f9d2 100644 (file)
@@ -36,18 +36,18 @@ class FileDeleteForm {
        private $title = null;
 
        /**
-        * @var File
+        * @var LocalFile
         */
        private $file = null;
 
        /**
-        * @var File
+        * @var LocalFile
         */
        private $oldfile = null;
        private $oldimage = '';
 
        /**
-        * @param File $file File object we're deleting
+        * @param LocalFile $file File object we're deleting
         */
        public function __construct( $file ) {
                $this->title = $file->getTitle();
@@ -451,9 +451,9 @@ class FileDeleteForm {
         * value was provided, does it correspond to an
         * existing, local, old version of this file?
         *
-        * @param File &$file
-        * @param File &$oldfile
-        * @param File $oldimage
+        * @param LocalFile &$file
+        * @param LocalFile &$oldfile
+        * @param LocalFile $oldimage
         * @return bool
         */
        public static function haveDeletableFile( &$file, &$oldfile, $oldimage ) {
index 38daab5..3b4e657 100644 (file)
@@ -1816,10 +1816,11 @@ function mimeTypeMatch( $type, $avail ) {
  *
  * @param array $cprefs Client's acceptable type list
  * @param array $sprefs Server's offered types
- * @return string
+ * @return string|null
  *
  * @todo FIXME: Doesn't handle params like 'text/plain; charset=UTF-8'
  * XXX: generalize to negotiate other stuff
+ * @todo The function appears unused. Is it worth to keep?
  */
 function wfNegotiateType( $cprefs, $sprefs ) {
        $combine = [];
index 1a5058d..324b1f5 100644 (file)
@@ -21,7 +21,7 @@
  */
 use MediaWiki\Linker\LinkTarget;
 use MediaWiki\MediaWikiServices;
-use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Revision\RevisionRecord;
 
 /**
  * Some internal bits split of from Skin.php. These functions are used
index 4045a54..1a950c5 100644 (file)
@@ -273,6 +273,18 @@ class MergeHistory {
                        return $status;
                }
 
+               // Update denormalized revactor_page too
+               $this->dbw->update(
+                       'revision_actor_temp',
+                       [ 'revactor_page' => $this->dest->getArticleID() ],
+                       [
+                               'revactor_page' => $this->source->getArticleID(),
+                               // Slightly hacky, but should work given the values assigned in this class
+                               str_replace( 'rev_timestamp', 'revactor_timestamp', $this->timeWhere )
+                       ],
+                       __METHOD__
+               );
+
                // Make the source page a redirect if no revisions are left
                $haveRevisions = $this->dbw->lockForUpdate(
                        'revision',
index 564c8f4..634e7af 100644 (file)
@@ -473,6 +473,7 @@ class MovePage {
 
                        $mp = new MovePage( $oldSubpage, $newSubpage );
                        $method = $checkPermissions ? 'moveIfAllowed' : 'move';
+                       /** @var Status $status */
                        $status = $mp->$method( $user, $reason, $createRedirect, $changeTags );
                        if ( $status->isOK() ) {
                                $status->setResult( true, $newSubpage->getPrefixedText() );
@@ -508,7 +509,7 @@ class MovePage {
 
                Hooks::run( 'TitleMoveStarting', [ $this->oldTitle, $this->newTitle, $user ] );
 
-               $pageid = $this->oldTitle->getArticleID( Title::GAID_FOR_UPDATE );
+               $pageid = $this->oldTitle->getArticleID( Title::READ_LATEST );
                $protected = $this->oldTitle->isProtected();
 
                // Do the actual move; if this fails, it will throw an MWException(!)
index 15a759b..c9b4193 100644 (file)
@@ -332,7 +332,7 @@ class OutputPage extends ContextSource {
         * a OutputPage tied to that context.
         * @param IContextSource $context
         */
-       function __construct( IContextSource $context ) {
+       public function __construct( IContextSource $context ) {
                $this->setContext( $context );
        }
 
@@ -385,8 +385,8 @@ class OutputPage extends ContextSource {
         * @param string $name Name of the meta tag
         * @param string $val Value of the meta tag
         */
-       function addMeta( $name, $val ) {
-               array_push( $this->mMetatags, [ $name, $val ] );
+       public function addMeta( $name, $val ) {
+               $this->mMetatags[] = [ $name, $val ];
        }
 
        /**
@@ -406,8 +406,8 @@ class OutputPage extends ContextSource {
         *
         * @param array $linkarr Associative array of attributes.
         */
-       function addLink( array $linkarr ) {
-               array_push( $this->mLinktags, $linkarr );
+       public function addLink( array $linkarr ) {
+               $this->mLinktags[] = $linkarr;
        }
 
        /**
@@ -425,7 +425,7 @@ class OutputPage extends ContextSource {
         * in preference to addLink(), to avoid duplicate link tags.
         * @param string $url
         */
-       function setCanonicalUrl( $url ) {
+       public function setCanonicalUrl( $url ) {
                $this->mCanonicalUrl = $url;
        }
 
@@ -447,7 +447,7 @@ class OutputPage extends ContextSource {
         *
         * @param string $script Raw HTML
         */
-       function addScript( $script ) {
+       public function addScript( $script ) {
                $this->mScripts .= $script;
        }
 
@@ -621,7 +621,7 @@ class OutputPage extends ContextSource {
         *
         * @return array
         */
-       function getHeadItemsArray() {
+       public function getHeadItemsArray() {
                return $this->mHeadItems;
        }
 
@@ -1598,6 +1598,7 @@ class OutputPage extends ContextSource {
         * @param ParserOptions|null $options Either the ParserOption to use or null to only get the
         *   current ParserOption object. This parameter is deprecated since 1.31.
         * @return ParserOptions
+        * @suppress PhanUndeclaredProperty For isBogus
         */
        public function parserOptions( $options = null ) {
                if ( $options !== null ) {
@@ -1954,7 +1955,7 @@ class OutputPage extends ContextSource {
         * @param ParserOutput $parserOutput
         * @param array $poOptions Options to ParserOutput::getText()
         */
-       function addParserOutput( ParserOutput $parserOutput, $poOptions = [] ) {
+       public function addParserOutput( ParserOutput $parserOutput, $poOptions = [] ) {
                $this->addParserOutputMetadata( $parserOutput );
                $this->addParserOutputText( $parserOutput, $poOptions );
        }
@@ -2188,7 +2189,7 @@ class OutputPage extends ContextSource {
         *
         * @return array
         */
-       function getCacheVaryCookies() {
+       public function getCacheVaryCookies() {
                if ( self::$cacheVaryCookies === null ) {
                        $config = $this->getConfig();
                        self::$cacheVaryCookies = array_values( array_unique( array_merge(
@@ -2209,7 +2210,7 @@ class OutputPage extends ContextSource {
         *
         * @return bool
         */
-       function haveCacheVaryCookies() {
+       public function haveCacheVaryCookies() {
                $request = $this->getRequest();
                foreach ( $this->getCacheVaryCookies() as $cookieName ) {
                        if ( $request->getCookie( $cookieName, '', '' ) !== '' ) {
@@ -2414,32 +2415,16 @@ class OutputPage extends ContextSource {
                                $this->mCdnMaxage != 0 &&
                                !$this->haveCacheVaryCookies()
                        ) {
-                               if ( $config->get( 'UseESI' ) ) {
-                                       wfDeprecated( '$wgUseESI = true', '1.33' );
-                                       # We'll purge the proxy cache explicitly, but require end user agents
-                                       # to revalidate against the proxy on each visit.
-                                       # Surrogate-Control controls our CDN, Cache-Control downstream caches
-                                       wfDebug( __METHOD__ .
-                                               ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
-                                       # start with a shorter timeout for initial testing
-                                       # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
-                                       $response->header(
-                                               "Surrogate-Control: max-age={$config->get( 'CdnMaxAge' )}" .
-                                               "+{$this->mCdnMaxage}, content=\"ESI/1.0\""
-                                       );
-                                       $response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
-                               } else {
-                                       # We'll purge the proxy cache for anons explicitly, but require end user agents
-                                       # to revalidate against the proxy on each visit.
-                                       # IMPORTANT! The CDN needs to replace the Cache-Control header with
-                                       # Cache-Control: s-maxage=0, must-revalidate, max-age=0
-                                       wfDebug( __METHOD__ .
-                                               ": local proxy caching; {$this->mLastModified} **", 'private' );
-                                       # start with a shorter timeout for initial testing
-                                       # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
-                                       $response->header( "Cache-Control: " .
-                                               "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
-                               }
+                               # We'll purge the proxy cache for anons explicitly, but require end user agents
+                               # to revalidate against the proxy on each visit.
+                               # IMPORTANT! The CDN needs to replace the Cache-Control header with
+                               # Cache-Control: s-maxage=0, must-revalidate, max-age=0
+                               wfDebug( __METHOD__ .
+                                       ": local proxy caching; {$this->mLastModified} **", 'private' );
+                               # start with a shorter timeout for initial testing
+                               # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
+                               $response->header( "Cache-Control: " .
+                                       "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
                        } else {
                                # We do want clients to cache if they can, but they *must* check for updates
                                # on revisiting the page.
@@ -2838,7 +2823,7 @@ class OutputPage extends ContextSource {
        /**
         * Add a "return to" link pointing to a specified title
         *
-        * @param Title $title Title to link
+        * @param LinkTarget $title Title to link
         * @param array $query Query string parameters
         * @param string|null $text Text of the link (input is not escaped)
         * @param array $options Options array to pass to Linker
index b63a84d..e726729 100644 (file)
@@ -31,8 +31,6 @@
  *
  * @note This class uses setter methods instead of a constructor so that
  * it can be compatible with PHP 4, PHP 5 and PHP 7 (without warnings).
- *
- * @class
  */
 class PHPVersionCheck {
        /* @var string The number of the MediaWiki version used. */
@@ -110,8 +108,8 @@ class PHPVersionCheck {
                        'implementation' => 'PHP',
                        'version' => PHP_VERSION,
                        'vendor' => 'the PHP Group',
-                       'upstreamSupported' => '5.6.0',
-                       'minSupported' => '7.0.13',
+                       'upstreamSupported' => '7.1.0',
+                       'minSupported' => '7.2.0',
                        'upgradeURL' => 'https://www.php.net/downloads.php',
                );
        }
index 8b5d995..a1be271 100644 (file)
@@ -58,6 +58,18 @@ class ProtectionForm {
        /** @var array Map of action to the expiry time of the existing protection */
        protected $mExistingExpiry = [];
 
+       /** @var Article */
+       protected $mArticle;
+
+       /** @var Title */
+       protected $mTitle;
+
+       /** @var bool */
+       protected $disabled;
+
+       /** @var array */
+       protected $disabledAttrib;
+
        /** @var IContextSource */
        private $mContext;
 
@@ -78,7 +90,7 @@ class ProtectionForm {
                if ( wfReadOnly() ) {
                        $this->mPermErrors[] = [ 'readonlytext', wfReadOnlyReason() ];
                }
-               $this->disabled = $this->mPermErrors != [];
+               $this->disabled = $this->mPermErrors !== [];
                $this->disabledAttrib = $this->disabled
                        ? [ 'disabled' => 'disabled' ]
                        : [];
index 43014f1..92529b3 100644 (file)
@@ -2,24 +2,24 @@
 
 namespace MediaWiki\Rest\BasicAccess;
 
-use User;
 use MediaWiki\Permissions\PermissionManager;
 use MediaWiki\Rest\Handler;
 use MediaWiki\Rest\RequestInterface;
+use MediaWiki\User\UserIdentity;
 
 /**
- * A factory for MWBasicRequestAuthorizer which passes through a User object
+ * A factory for MWBasicRequestAuthorizer which passes through a UserIdentity.
  *
  * @internal
  */
 class MWBasicAuthorizer extends BasicAuthorizerBase {
-       /** @var User */
+       /** @var UserIdentity */
        private $user;
 
        /** @var PermissionManager */
        private $permissionManager;
 
-       public function __construct( User $user, PermissionManager $permissionManager ) {
+       public function __construct( UserIdentity $user, PermissionManager $permissionManager ) {
                $this->user = $user;
                $this->permissionManager = $permissionManager;
        }
index 8c459c6..671488a 100644 (file)
@@ -2,7 +2,7 @@
 
 namespace MediaWiki\Rest\BasicAccess;
 
-use User;
+use MediaWiki\User\UserIdentity;
 use MediaWiki\Permissions\PermissionManager;
 use MediaWiki\Rest\Handler;
 use MediaWiki\Rest\RequestInterface;
@@ -13,14 +13,14 @@ use MediaWiki\Rest\RequestInterface;
  * @internal
  */
 class MWBasicRequestAuthorizer extends BasicRequestAuthorizer {
-       /** @var User */
+       /** @var UserIdentity */
        private $user;
 
        /** @var PermissionManager */
        private $permissionManager;
 
        public function __construct( RequestInterface $request, Handler $handler,
-               User $user, PermissionManager $permissionManager
+               UserIdentity $user, PermissionManager $permissionManager
        ) {
                parent::__construct( $request, $handler );
                $this->user = $user;
index ee3441e..070451d 100644 (file)
@@ -10,6 +10,7 @@ use MediaWiki\Rest\Validator\Validator;
 use RequestContext;
 use Title;
 use WebResponse;
+use Wikimedia\Message\ITextFormatter;
 
 class EntryPoint {
        /** @var RequestInterface */
@@ -49,12 +50,18 @@ class EntryPoint {
                        'cookiePrefix' => $conf->get( 'CookiePrefix' )
                ] );
 
+               $responseFactory = new ResponseFactory( self::getTextFormatters( $services ) );
+
                // @phan-suppress-next-line PhanAccessMethodInternal
                $authorizer = new MWBasicAuthorizer( $context->getUser(),
                        $services->getPermissionManager() );
 
                // @phan-suppress-next-line PhanAccessMethodInternal
-               $restValidator = new Validator( $objectFactory, $request, RequestContext::getMain()->getUser() );
+               $restValidator = new Validator( $objectFactory,
+                       $services->getPermissionManager(),
+                       $request,
+                       RequestContext::getMain()->getUser()
+               );
 
                global $IP;
                $router = new Router(
@@ -62,7 +69,7 @@ class EntryPoint {
                        ExtensionRegistry::getInstance()->getAttribute( 'RestRoutes' ),
                        $conf->get( 'RestPath' ),
                        $services->getLocalServerObjectCache(),
-                       new ResponseFactory,
+                       $responseFactory,
                        $authorizer,
                        $objectFactory,
                        $restValidator
@@ -76,6 +83,25 @@ class EntryPoint {
                $entryPoint->execute();
        }
 
+       /**
+        * Get a TextFormatter array from MediaWikiServices
+        *
+        * @param MediaWikiServices $services
+        * @return ITextFormatter[]
+        */
+       public static function getTextFormatters( MediaWikiServices $services ) {
+               $langs = array_unique( [
+                       $services->getMainConfig()->get( 'ContLang' )->getCode(),
+                       'en'
+               ] );
+               $textFormatters = [];
+               $factory = $services->getMessageFormatterFactory();
+               foreach ( $langs as $lang ) {
+                       $textFormatters[] = $factory->getTextFormatter( $lang );
+               }
+               return $textFormatters;
+       }
+
        public function __construct( RequestContext $context, RequestInterface $request,
                WebResponse $webResponse, Router $router
        ) {
index 10d3a40..184fe16 100644 (file)
@@ -5,7 +5,14 @@ namespace MediaWiki\Rest;
 use Wikimedia\Message\MessageValue;
 
 class LocalizedHttpException extends HttpException {
-       public function __construct( MessageValue $message, $code = 500 ) {
-               parent::__construct( 'Localized exception with key ' . $message->getKey(), $code );
+       private $messageValue;
+
+       public function __construct( MessageValue $messageValue, $code = 500 ) {
+               parent::__construct( 'Localized exception with key ' . $messageValue->getKey(), $code );
+               $this->messageValue = $messageValue;
+       }
+
+       public function getMessageValue() {
+               return $this->messageValue;
        }
 }
index 5e5a198..fd0f3c7 100644 (file)
@@ -5,19 +5,31 @@ namespace MediaWiki\Rest;
 use Exception;
 use HttpStatus;
 use InvalidArgumentException;
+use LanguageCode;
 use MWExceptionHandler;
 use stdClass;
 use Throwable;
+use Wikimedia\Message\ITextFormatter;
+use Wikimedia\Message\MessageValue;
 
 /**
  * Generates standardized response objects.
  */
 class ResponseFactory {
-
        const CT_PLAIN = 'text/plain; charset=utf-8';
        const CT_HTML = 'text/html; charset=utf-8';
        const CT_JSON = 'application/json';
 
+       /** @var ITextFormatter[] */
+       private $textFormatters;
+
+       /**
+        * @param ITextFormatter[] $textFormatters
+        */
+       public function __construct( $textFormatters ) {
+               $this->textFormatters = $textFormatters;
+       }
+
        /**
         * Encode a stdClass object or array to a JSON string
         *
@@ -167,13 +179,23 @@ class ResponseFactory {
                return $response;
        }
 
+       /**
+        * Create an HTTP 4xx or 5xx response with error message localisation
+        */
+       public function createLocalizedHttpError( $errorCode, MessageValue $messageValue ) {
+               return $this->createHttpError( $errorCode, $this->formatMessage( $messageValue ) );
+       }
+
        /**
         * Turn an exception into a JSON error response.
         * @param Exception|Throwable $exception
         * @return Response
         */
        public function createFromException( $exception ) {
-               if ( $exception instanceof HttpException ) {
+               if ( $exception instanceof LocalizedHttpException ) {
+                       $response = $this->createLocalizedHttpError( $exception->getCode(),
+                               $exception->getMessageValue() );
+               } elseif ( $exception instanceof HttpException ) {
                        // FIXME can HttpException represent 2xx or 3xx responses?
                        $response = $this->createHttpError(
                                $exception->getCode(),
@@ -240,4 +262,18 @@ class ResponseFactory {
                return "<!doctype html><title>Redirect</title><a href=\"$url\">$url</a>";
        }
 
+       public function formatMessage( MessageValue $messageValue ) {
+               if ( !$this->textFormatters ) {
+                       // For unit tests
+                       return [];
+               }
+               $translations = [];
+               foreach ( $this->textFormatters as $formatter ) {
+                       $lang = LanguageCode::bcp47( $formatter->getLangCode() );
+                       $messageText = $formatter->format( $messageValue );
+                       $translations[$lang] = $messageText;
+               }
+               return [ 'messageTranslations' => $translations ];
+       }
+
 }
index a520130..6821d89 100644 (file)
@@ -4,6 +4,7 @@ namespace MediaWiki\Rest;
 
 use AppendIterator;
 use BagOStuff;
+use Wikimedia\Message\MessageValue;
 use MediaWiki\Rest\BasicAccess\BasicAuthorizerInterface;
 use MediaWiki\Rest\PathTemplateMatcher\PathMatcher;
 use MediaWiki\Rest\Validator\Validator;
@@ -226,18 +227,28 @@ class Router {
                $path = $request->getUri()->getPath();
                $relPath = $this->getRelativePath( $path );
                if ( $relPath === false ) {
-                       return $this->responseFactory->createHttpError( 404 );
+                       return $this->responseFactory->createLocalizedHttpError( 404,
+                               ( new MessageValue( 'rest-prefix-mismatch' ) )
+                                       ->plaintextParams( $path, $this->rootPath )
+                       );
                }
 
+               $requestMethod = $request->getMethod();
                $matchers = $this->getMatchers();
-               $matcher = $matchers[$request->getMethod()] ?? null;
+               $matcher = $matchers[$requestMethod] ?? null;
                $match = $matcher ? $matcher->match( $relPath ) : null;
 
+               // For a HEAD request, execute the GET handler instead if one exists.
+               // The webserver will discard the body.
+               if ( !$match && $requestMethod === 'HEAD' && isset( $matchers['GET'] ) ) {
+                       $match = $matchers['GET']->match( $relPath );
+               }
+
                if ( !$match ) {
                        // Check for 405 wrong method
                        $allowed = [];
                        foreach ( $matchers as $allowedMethod => $allowedMatcher ) {
-                               if ( $allowedMethod === $request->getMethod() ) {
+                               if ( $allowedMethod === $requestMethod ) {
                                        continue;
                                }
                                if ( $allowedMatcher->match( $relPath ) ) {
@@ -245,12 +256,20 @@ class Router {
                                }
                        }
                        if ( $allowed ) {
-                               $response = $this->responseFactory->createHttpError( 405 );
+                               $response = $this->responseFactory->createLocalizedHttpError( 405,
+                                       ( new MessageValue( 'rest-wrong-method' ) )
+                                               ->textParams( $requestMethod )
+                                               ->commaListParams( $allowed )
+                                               ->numParams( count( $allowed ) )
+                               );
                                $response->setHeader( 'Allow', $allowed );
                                return $response;
                        } else {
                                // Did not match with any other method, must be 404
-                               return $this->responseFactory->createHttpError( 404 );
+                               return $this->responseFactory->createLocalizedHttpError( 404,
+                                       ( new MessageValue( 'rest-no-match' ) )
+                                               ->plaintextParams( $relPath )
+                               );
                        }
                }
 
@@ -272,6 +291,7 @@ class Router {
 
        /**
         * Execute a fully-constructed handler
+        *
         * @param Handler $handler
         * @return ResponseInterface
         */
index 6c54a50..93de911 100644 (file)
@@ -3,21 +3,30 @@
 namespace MediaWiki\Rest\Validator;
 
 use InvalidArgumentException;
+use MediaWiki\Permissions\PermissionManager;
 use MediaWiki\Rest\RequestInterface;
+use MediaWiki\User\UserIdentity;
 use Psr\Http\Message\UploadedFileInterface;
-use User;
 use Wikimedia\ParamValidator\Callbacks;
 use Wikimedia\ParamValidator\ValidationException;
 
 class ParamValidatorCallbacks implements Callbacks {
 
+       /** @var PermissionManager */
+       private $permissionManager;
+
        /** @var RequestInterface */
        private $request;
 
-       /** @var User */
+       /** @var UserIdentity */
        private $user;
 
-       public function __construct( RequestInterface $request, User $user ) {
+       public function __construct(
+               PermissionManager $permissionManager,
+               RequestInterface $request,
+               UserIdentity $user
+       ) {
+               $this->permissionManager = $permissionManager;
                $this->request = $request;
                $this->user = $user;
        }
@@ -76,7 +85,7 @@ class ParamValidatorCallbacks implements Callbacks {
        }
 
        public function useHighLimits( array $options ) {
-               return $this->user->isAllowed( 'apihighlimits' );
+               return $this->permissionManager->userHasRight( $this->user, 'apihighlimits' );
        }
 
 }
index cee1cdb..be8d7a4 100644 (file)
@@ -2,10 +2,11 @@
 
 namespace MediaWiki\Rest\Validator;
 
+use MediaWiki\Permissions\PermissionManager;
 use MediaWiki\Rest\Handler;
 use MediaWiki\Rest\HttpException;
 use MediaWiki\Rest\RequestInterface;
-use User;
+use MediaWiki\User\UserIdentity;
 use Wikimedia\ObjectFactory;
 use Wikimedia\ParamValidator\ParamValidator;
 use Wikimedia\ParamValidator\TypeDef\BooleanDef;
@@ -62,16 +63,20 @@ class Validator {
        private $paramValidator;
 
        /**
-        * @internal
         * @param ObjectFactory $objectFactory
+        * @param PermissionManager $permissionManager
         * @param RequestInterface $request
-        * @param User $user
+        * @param UserIdentity $user
+        * @internal
         */
        public function __construct(
-               ObjectFactory $objectFactory, RequestInterface $request, User $user
+               ObjectFactory $objectFactory,
+               PermissionManager $permissionManager,
+               RequestInterface $request,
+               UserIdentity $user
        ) {
                $this->paramValidator = new ParamValidator(
-                       new ParamValidatorCallbacks( $request, $user ),
+                       new ParamValidatorCallbacks( $permissionManager, $request, $user ),
                        $objectFactory,
                        [
                                'typeDefs' => self::$typeDefs,
index c6e727e..828f647 100644 (file)
@@ -298,203 +298,6 @@ class Revision implements IDBAccessObject {
                return $rec ? new Revision( $rec ) : null;
        }
 
-       /**
-        * Return the value of a select() JOIN conds array for the user table.
-        * This will get user table rows for logged-in users.
-        * @since 1.19
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'user' ] ) instead.
-        * @return array
-        */
-       public static function userJoinCond() {
-               global $wgActorTableSchemaMigrationStage;
-
-               wfDeprecated( __METHOD__, '1.31' );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's
-                       // no way the join it's trying to do can work once the old fields
-                       // aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               return [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ];
-       }
-
-       /**
-        * Return the value of a select() page conds array for the page table.
-        * This will assure that the revision(s) are not orphaned from live pages.
-        * @since 1.19
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'page' ] ) instead.
-        * @return array
-        */
-       public static function pageJoinCond() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [ 'JOIN', [ 'page_id = rev_page' ] ];
-       }
-
-       /**
-        * Return the list of revision fields that should be selected to create
-        * a new revision.
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo() instead.
-        * @return array
-        */
-       public static function selectFields() {
-               global $wgContentHandlerUseDB, $wgActorTableSchemaMigrationStage;
-               global $wgMultiContentRevisionSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->rev_user or $row->rev_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               if ( !( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->rev_text_id or $row->rev_content_model and we can't give it
-                       // useful values here once those aren't being written anymore,
-                       // and may not exist at all.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__ . ' when $wgMultiContentRevisionSchemaMigrationStage '
-                               . 'does not have SCHEMA_COMPAT_WRITE_OLD set.'
-                       );
-               }
-
-               wfDeprecated( __METHOD__, '1.31' );
-
-               $fields = [
-                       'rev_id',
-                       'rev_page',
-                       'rev_text_id',
-                       'rev_timestamp',
-                       'rev_user_text',
-                       'rev_user',
-                       'rev_actor' => 'NULL',
-                       'rev_minor_edit',
-                       'rev_deleted',
-                       'rev_len',
-                       'rev_parent_id',
-                       'rev_sha1',
-               ];
-
-               $fields += CommentStore::getStore()->getFields( 'rev_comment' );
-
-               if ( $wgContentHandlerUseDB ) {
-                       $fields[] = 'rev_content_format';
-                       $fields[] = 'rev_content_model';
-               }
-
-               return $fields;
-       }
-
-       /**
-        * Return the list of revision fields that should be selected to create
-        * a new revision from an archive row.
-        * @deprecated since 1.31, use RevisionStore::getArchiveQueryInfo() instead.
-        * @return array
-        */
-       public static function selectArchiveFields() {
-               global $wgContentHandlerUseDB, $wgActorTableSchemaMigrationStage;
-               global $wgMultiContentRevisionSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->ar_user or $row->ar_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               if ( !( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->ar_text_id or $row->ar_content_model and we can't give it
-                       // useful values here once those aren't being written anymore,
-                       // and may not exist at all.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__ . ' when $wgMultiContentRevisionSchemaMigrationStage '
-                               . 'does not have SCHEMA_COMPAT_WRITE_OLD set.'
-                       );
-               }
-
-               wfDeprecated( __METHOD__, '1.31' );
-
-               $fields = [
-                       'ar_id',
-                       'ar_page_id',
-                       'ar_rev_id',
-                       'ar_text_id',
-                       'ar_timestamp',
-                       'ar_user_text',
-                       'ar_user',
-                       'ar_actor' => 'NULL',
-                       'ar_minor_edit',
-                       'ar_deleted',
-                       'ar_len',
-                       'ar_parent_id',
-                       'ar_sha1',
-               ];
-
-               $fields += CommentStore::getStore()->getFields( 'ar_comment' );
-
-               if ( $wgContentHandlerUseDB ) {
-                       $fields[] = 'ar_content_format';
-                       $fields[] = 'ar_content_model';
-               }
-               return $fields;
-       }
-
-       /**
-        * Return the list of text fields that should be selected to read the
-        * revision text
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'text' ] ) instead.
-        * @return array
-        */
-       public static function selectTextFields() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [
-                       'old_text',
-                       'old_flags'
-               ];
-       }
-
-       /**
-        * Return the list of page fields that should be selected from page table
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'page' ] ) instead.
-        * @return array
-        */
-       public static function selectPageFields() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [
-                       'page_namespace',
-                       'page_title',
-                       'page_id',
-                       'page_latest',
-                       'page_is_redirect',
-                       'page_len',
-               ];
-       }
-
-       /**
-        * Return the list of user fields that should be selected from user table
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'user' ] ) instead.
-        * @return array
-        */
-       public static function selectUserFields() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [ 'user_name' ];
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new revision object.
@@ -1202,7 +1005,7 @@ class Revision implements IDBAccessObject {
 
                $comment = CommentStoreComment::newUnsavedComment( $summary, null );
 
-               $title = Title::newFromID( $pageId, Title::GAID_FOR_UPDATE );
+               $title = Title::newFromID( $pageId, Title::READ_LATEST );
                if ( $title === null ) {
                        return null;
                }
index ff9ac57..759180a 100644 (file)
@@ -531,8 +531,6 @@ abstract class RevisionRecord {
                                $text = $title->getPrefixedText();
                                wfDebug( "Checking for $permissionlist on $text due to $field match on $bitfield\n" );
 
-                               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
-
                                foreach ( $permissions as $perm ) {
                                        if ( $permissionManager->userCan( $perm, $user, $title ) ) {
                                                return true;
index 73f622a..735a212 100644 (file)
@@ -326,10 +326,10 @@ class RevisionStore
 
                $canUseTitleNewFromId = ( $pageId !== null && $pageId > 0 && $this->dbDomain === false );
                list( $dbMode, $dbOptions ) = DBAccessObjectUtils::getDBOptions( $queryFlags );
-               $titleFlags = ( $dbMode == DB_MASTER ? Title::GAID_FOR_UPDATE : 0 );
 
                // Loading by ID is best, but Title::newFromID does not support that for foreign IDs.
                if ( $canUseTitleNewFromId ) {
+                       $titleFlags = ( $dbMode == DB_MASTER ? Title::READ_LATEST : 0 );
                        // TODO: better foreign title handling (introduce TitleFactory)
                        $title = Title::newFromID( $pageId, $titleFlags );
                        if ( $title ) {
index acecee1..1de4d7f 100644 (file)
@@ -27,7 +27,7 @@ namespace MediaWiki\Revision;
 
 use ActorMigration;
 use CommentStore;
-use MediaWiki\Logger\Spi as LoggerSpi;
+use Psr\Log\LoggerInterface;
 use MediaWiki\Storage\BlobStoreFactory;
 use MediaWiki\Storage\NameTableStoreFactory;
 use WANObjectCache;
@@ -54,8 +54,8 @@ class RevisionStoreFactory {
        private $dbLoadBalancerFactory;
        /** @var WANObjectCache */
        private $cache;
-       /** @var LoggerSpi */
-       private $loggerProvider;
+       /** @var LoggerInterface */
+       private $logger;
 
        /** @var CommentStore */
        private $commentStore;
@@ -84,7 +84,7 @@ class RevisionStoreFactory {
         * @param CommentStore $commentStore
         * @param ActorMigration $actorMigration
         * @param int $migrationStage
-        * @param LoggerSpi $loggerProvider
+        * @param LoggerInterface $logger
         * @param bool $contentHandlerUseDB see {@link $wgContentHandlerUseDB}. Must be the same
         *        for all wikis in the cluster. Will go away after MCR migration.
         */
@@ -97,7 +97,7 @@ class RevisionStoreFactory {
                CommentStore $commentStore,
                ActorMigration $actorMigration,
                $migrationStage,
-               LoggerSpi $loggerProvider,
+               LoggerInterface $logger,
                $contentHandlerUseDB
        ) {
                Assert::parameterType( 'integer', $migrationStage, '$migrationStage' );
@@ -109,7 +109,7 @@ class RevisionStoreFactory {
                $this->commentStore = $commentStore;
                $this->actorMigration = $actorMigration;
                $this->mcrMigrationStage = $migrationStage;
-               $this->loggerProvider = $loggerProvider;
+               $this->logger = $logger;
                $this->contentHandlerUseDB = $contentHandlerUseDB;
        }
 
@@ -118,7 +118,7 @@ class RevisionStoreFactory {
         *
         * @param bool|string $dbDomain DB domain of the relevant wiki or false for the current one
         *
-        * @return RevisionStore for the given wikiId with all necessary services and a logger
+        * @return RevisionStore for the given wikiId with all necessary services
         */
        public function getRevisionStore( $dbDomain = false ) {
                Assert::parameterType( 'string|boolean', $dbDomain, '$dbDomain' );
@@ -137,7 +137,7 @@ class RevisionStoreFactory {
                        $dbDomain
                );
 
-               $store->setLogger( $this->loggerProvider->getLogger( 'RevisionStore' ) );
+               $store->setLogger( $this->logger );
                $store->setContentHandlerUseDB( $this->contentHandlerUseDB );
 
                return $store;
index 740377c..8807d04 100644 (file)
@@ -77,9 +77,7 @@ use Wikimedia\ObjectFactory;
 
 return [
        'ActorMigration' => function ( MediaWikiServices $services ) : ActorMigration {
-               return new ActorMigration(
-                       $services->getMainConfig()->get( 'ActorTableSchemaMigrationStage' )
-               );
+               return new ActorMigration( SCHEMA_COMPAT_NEW );
        },
 
        'BadFileLookup' => function ( MediaWikiServices $services ) : BadFileLookup {
@@ -109,14 +107,12 @@ return [
        },
 
        'BlockManager' => function ( MediaWikiServices $services ) : BlockManager {
-               $context = RequestContext::getMain();
                return new BlockManager(
                        new ServiceOptions(
                                BlockManager::$constructorOptions, $services->getMainConfig()
                        ),
-                       $context->getUser(),
-                       $context->getRequest(),
-                       $services->getPermissionManager()
+                       $services->getPermissionManager(),
+                       LoggerFactory::getInstance( 'BlockManager' )
                );
        },
 
@@ -547,7 +543,8 @@ return [
                        $services->getContentLanguage(),
                        AuthManager::singleton(),
                        $services->getLinkRendererFactory()->create(),
-                       $services->getNamespaceInfo()
+                       $services->getNamespaceInfo(),
+                       $services->getPermissionManager()
                );
                $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) );
 
@@ -636,7 +633,7 @@ return [
                        $services->getCommentStore(),
                        $services->getActorMigration(),
                        $config->get( 'MultiContentRevisionSchemaMigrationStage' ),
-                       LoggerFactory::getProvider(),
+                       LoggerFactory::getInstance( 'RevisionStore' ),
                        $config->get( 'ContentHandlerUseDB' )
                );
 
@@ -734,7 +731,8 @@ return [
                return new SpecialPageFactory(
                        new ServiceOptions(
                                SpecialPageFactory::$constructorOptions, $services->getMainConfig() ),
-                       $services->getContentLanguage()
+                       $services->getContentLanguage(),
+                       $services->getObjectFactory()
                );
        },
 
@@ -786,7 +784,8 @@ return [
                        $services->getDBLoadBalancer(),
                        $services->getCommentStore(),
                        $services->getActorMigration(),
-                       $services->getWatchedItemStore()
+                       $services->getWatchedItemStore(),
+                       $services->getPermissionManager()
                );
        },
 
index cfb2ac1..6838c37 100644 (file)
@@ -52,6 +52,17 @@ if ( ini_get( 'mbstring.func_overload' ) ) {
        die( 'MediaWiki does not support installations where mbstring.func_overload is non-zero.' );
 }
 
+// Define MW_ENTRY_POINT if it's not already, so that config code can check the
+// value without using defined()
+if ( !defined( 'MW_ENTRY_POINT' ) ) {
+       /**
+        * The entry point, which may be either the script filename without the
+        * file extension, or "cli" for maintenance scripts, or "unknown" for any
+        * entry point that does not set the constant.
+        */
+       define( 'MW_ENTRY_POINT', 'unknown' );
+}
+
 // Start the autoloader, so that extensions can derive classes from core files
 require_once "$IP/includes/AutoLoader.php";
 
@@ -429,6 +440,13 @@ if ( $wgEnableEmail ) {
        $wgUsersNotifiedOnAllChanges = [];
 }
 
+// $wgSysopEmailBans deprecated in 1.34
+if ( isset( $wgSysopEmailBans ) && $wgSysopEmailBans === false ) {
+       foreach ( $wgGroupPermissions as $group => $_ ) {
+               unset( $wgGroupPermissions[$group]['blockemail'] );
+       }
+}
+
 if ( $wgMetaNamespace === false ) {
        $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
 }
@@ -797,22 +815,17 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
        // Initialize the session
        try {
                $session = MediaWiki\Session\SessionManager::getGlobalSession();
-       } catch ( OverflowException $ex ) {
-               if ( isset( $ex->sessionInfos ) && count( $ex->sessionInfos ) >= 2 ) {
-                       // The exception is because the request had multiple possible
-                       // sessions tied for top priority. Report this to the user.
-                       $list = [];
-                       foreach ( $ex->sessionInfos as $info ) {
-                               $list[] = $info->getProvider()->describe( $wgContLang );
-                       }
-                       $list = $wgContLang->listToText( $list );
-                       throw new HttpError( 400,
-                               Message::newFromKey( 'sessionmanager-tie', $list )->inLanguage( $wgContLang )->plain()
-                       );
+       } catch ( MediaWiki\Session\SessionOverflowException $ex ) {
+               // The exception is because the request had multiple possible
+               // sessions tied for top priority. Report this to the user.
+               $list = [];
+               foreach ( $ex->getSessionInfos() as $info ) {
+                       $list[] = $info->getProvider()->describe( $wgContLang );
                }
-
-               // Not the one we want, rethrow
-               throw $ex;
+               $list = $wgContLang->listToText( $list );
+               throw new HttpError( 400,
+                       Message::newFromKey( 'sessionmanager-tie', $list )->inLanguage( $wgContLang )->plain()
+               );
        }
 
        if ( $session->isPersistent() ) {
index 76b905e..932fd2a 100644 (file)
@@ -115,6 +115,7 @@ class Status extends StatusValue {
         * ]
         *
         * @return Status[]
+        * @suppress PhanUndeclaredProperty Status vs StatusValue
         */
        public function splitByErrorType() {
                list( $errorsOnlyStatus, $warningsOnlyStatus ) = parent::splitByErrorType();
index 4903cf0..b2c003a 100644 (file)
@@ -1531,7 +1531,9 @@ class DerivedPageDataUpdater implements IDBAccessObject, LoggerAwareInterface {
                if ( $this->options['changed']
                        && $title->getNamespace() == NS_USER_TALK
                        && $shortTitle != $legacyUser->getTitleKey()
-                       && !( $this->revision->isMinor() && $legacyUser->isAllowed( 'nominornewtalk' ) )
+                       && !( $this->revision->isMinor() && MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $legacyUser, 'nominornewtalk' ) )
                ) {
                        $recipient = User::newFromName( $shortTitle, false );
                        if ( !$recipient ) {
index 8c011df..bcbc9e8 100644 (file)
@@ -103,10 +103,10 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
         * @param ExternalStoreAccess $extStoreAccess Access layer for external storage
         * @param WANObjectCache $cache A cache manager for caching blobs. This can be the local
         *        wiki's default instance even if $dbDomain refers to a different wiki, since
-        *        makeGlobalKey() is used to constructed a key that allows cached blobs from the
-        *        same database to be re-used between wikis. For example, enwiki and frwiki will
-        *        use the same cache keys for blobs from the wikidatawiki database, regardless of
-        *        the cache's default key space.
+        *        makeGlobalKey() is used to construct a key that allows cached blobs from the
+        *        same database to be re-used between wikis. For example, wiki A and wiki B will
+        *        use the same cache keys for blobs fetched from wiki C, regardless of the
+        *        wiki-specific default key space.
         * @param bool|string $dbDomain The ID of the target wiki database. Use false for the local wiki.
         */
        public function __construct(
@@ -449,16 +449,15 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
         * Get a cache key for a given Blob address.
         *
         * The cache key is constructed in a way that allows cached blobs from the same database
-        * to be re-used between wikis. For example, enwiki and frwiki will use the same cache keys
-        * for blobs from the wikidatawiki database.
+        * to be re-used between wikis. For example, wiki A and wiki B will use the same cache keys
+        * for blobs fetched from wiki C.
         *
         * @param string $blobAddress
         * @return string
         */
        private function getCacheKey( $blobAddress ) {
                return $this->cache->makeGlobalKey(
-                       'BlobStore',
-                       'address',
+                       'SqlBlobStore-blob',
                        $this->dbLoadBalancer->resolveDomainID( $this->dbDomain ),
                        $blobAddress
                );
index 2ad42e5..c9b2c33 100644 (file)
  */
 class StreamFile {
        // Do not send any HTTP headers unless requested by caller (e.g. body only)
+       /** @deprecated since 1.34 */
        const STREAM_HEADLESS = HTTPFileStreamer::STREAM_HEADLESS;
        // Do not try to tear down any PHP output buffers
+       /** @deprecated since 1.34 */
        const STREAM_ALLOW_OB = HTTPFileStreamer::STREAM_ALLOW_OB;
 
        /**
@@ -66,8 +68,10 @@ class StreamFile {
         * @param string $fname Full name and path of the file to stream
         * @param int $flags Bitfield of STREAM_* constants
         * @since 1.24
+        * @deprecated since 1.34, use HTTPFileStreamer::send404Message() instead
         */
        public static function send404Message( $fname, $flags = 0 ) {
+               wfDeprecated( __METHOD__, '1.34' );
                HTTPFileStreamer::send404Message( $fname, $flags );
        }
 
@@ -78,8 +82,10 @@ class StreamFile {
         * @param int $size File size
         * @return array|string Returns error string on failure (start, end, length)
         * @since 1.24
+        * @deprecated since 1.34, use HTTPFileStreamer::parseRange() instead
         */
        public static function parseRange( $range, $size ) {
+               wfDeprecated( __METHOD__, '1.34' );
                return HTTPFileStreamer::parseRange( $range, $size );
        }
 
@@ -105,7 +111,6 @@ class StreamFile {
                                case 'png':
                                        return 'image/png';
                                case 'jpg':
-                                       return 'image/jpeg';
                                case 'jpeg':
                                        return 'image/jpeg';
                        }
index 1e93c44..0f5c384 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 use MediaWiki\Permissions\PermissionManager;
-use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Revision\RevisionRecord;
 use Wikimedia\Assert\Assert;
 use Wikimedia\Rdbms\Database;
 use Wikimedia\Rdbms\IDatabase;
@@ -1059,7 +1059,7 @@ class Title implements LinkTarget, IDBAccessObject {
                        $this->lazyFillContentModel( $this->loadFieldFromDB( 'page_content_model', $flags ) );
                } elseif (
                        ( !$this->mContentModel || $flags & self::GAID_FOR_UPDATE ) &&
-                       $this->getArticleId( $flags )
+                       $this->getArticleID( $flags )
                ) {
                        $linkCache = MediaWikiServices::getInstance()->getLinkCache();
                        $linkCache->addLinkObj( $this ); # in case we already had an article ID
@@ -1561,14 +1561,32 @@ class Title implements LinkTarget, IDBAccessObject {
         * Get a Title object associated with the talk page of this article
         *
         * @deprecated since 1.34, use getTalkPageIfDefined() or NamespaceInfo::getTalkPage()
-        *             with NamespaceInfo::canHaveTalkPage().
+        *             with NamespaceInfo::canHaveTalkPage(). Note that the new method will
+        *             throw if asked for the talk page of a section-only link, or of an interwiki
+        *             link.
         * @return Title The object for the talk page
         * @throws MWException if $target doesn't have talk pages, e.g. because it's in NS_SPECIAL
         *         or because it's a relative link, or an interwiki link.
         */
        public function getTalkPage() {
-               return self::castFromLinkTarget(
-                       MediaWikiServices::getInstance()->getNamespaceInfo()->getTalkPage( $this ) );
+               // NOTE: The equivalent code in NamespaceInfo is less lenient about producing invalid titles.
+               //       Instead of failing on invalid titles, let's just log the issue for now.
+               //       See the discussion on T227817.
+
+               // Is this the same title?
+               $talkNS = MediaWikiServices::getInstance()->getNamespaceInfo()->getTalk( $this->mNamespace );
+               if ( $this->mNamespace == $talkNS ) {
+                       return $this;
+               }
+
+               $title = self::makeTitle( $talkNS, $this->mDbkeyform );
+
+               $this->warnIfPageCannotExist( $title, __METHOD__ );
+
+               return $title;
+               // TODO: replace the above with the code below:
+               // return self::castFromLinkTarget(
+               // MediaWikiServices::getInstance()->getNamespaceInfo()->getTalkPage( $this ) );
        }
 
        /**
@@ -1596,8 +1614,51 @@ class Title implements LinkTarget, IDBAccessObject {
         * @return Title The object for the subject page
         */
        public function getSubjectPage() {
-               return self::castFromLinkTarget(
-                       MediaWikiServices::getInstance()->getNamespaceInfo()->getSubjectPage( $this ) );
+               // Is this the same title?
+               $subjectNS = MediaWikiServices::getInstance()->getNamespaceInfo()
+                       ->getSubject( $this->mNamespace );
+               if ( $this->mNamespace == $subjectNS ) {
+                       return $this;
+               }
+               // NOTE: The equivalent code in NamespaceInfo is less lenient about producing invalid titles.
+               //       Instead of failing on invalid titles, let's just log the issue for now.
+               //       See the discussion on T227817.
+               $title = self::makeTitle( $subjectNS, $this->mDbkeyform );
+
+               $this->warnIfPageCannotExist( $title, __METHOD__ );
+
+               return $title;
+               // TODO: replace the above with the code below:
+               // return self::castFromLinkTarget(
+               // MediaWikiServices::getInstance()->getNamespaceInfo()->getSubjectPage( $this ) );
+       }
+
+       /**
+        * @param Title $title
+        * @param string $method
+        *
+        * @return bool whether a warning was issued
+        */
+       private function warnIfPageCannotExist( Title $title, $method ) {
+               if ( $this->getText() == '' ) {
+                       wfLogWarning(
+                               $method . ': called on empty title ' . $this->getFullText() . ', returning '
+                               . $title->getFullText()
+                       );
+
+                       return true;
+               }
+
+               if ( $this->getInterwiki() !== '' ) {
+                       wfLogWarning(
+                               $method . ': called on interwiki title ' . $this->getFullText() . ', returning '
+                               . $title->getFullText()
+                       );
+
+                       return true;
+               }
+
+               return false;
        }
 
        /**
@@ -1610,8 +1671,23 @@ class Title implements LinkTarget, IDBAccessObject {
         * @return Title
         */
        public function getOtherPage() {
-               return self::castFromLinkTarget(
-                       MediaWikiServices::getInstance()->getNamespaceInfo()->getAssociatedPage( $this ) );
+               // NOTE: Depend on the methods in this class instead of their equivalent in NamespaceInfo,
+               //       until their semantics has become exactly the same.
+               //       See the discussion on T227817.
+               if ( $this->isSpecialPage() ) {
+                       throw new MWException( 'Special pages cannot have other pages' );
+               }
+               if ( $this->isTalkPage() ) {
+                       return $this->getSubjectPage();
+               } else {
+                       if ( !$this->canHaveTalkPage() ) {
+                               throw new MWException( "{$this->getPrefixedText()} does not have an other page" );
+                       }
+                       return $this->getTalkPage();
+               }
+               // TODO: replace the above with the code below:
+               // return self::castFromLinkTarget(
+               // MediaWikiServices::getInstance()->getNamespaceInfo()->getAssociatedPage( $this ) );
        }
 
        /**
@@ -4270,12 +4346,21 @@ class Title implements LinkTarget, IDBAccessObject {
         * on the number of links. Typically called on create and delete.
         */
        public function touchLinks() {
-               DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this, 'pagelinks', 'page-touch' ) );
+               $jobs = [];
+               $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+                       $this,
+                       'pagelinks',
+                       [ 'causeAction' => 'page-touch' ]
+               );
                if ( $this->mNamespace == NS_CATEGORY ) {
-                       DeferredUpdates::addUpdate(
-                               new HTMLCacheUpdate( $this, 'categorylinks', 'category-touch' )
+                       $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+                               $this,
+                               'categorylinks',
+                               [ 'causeAction' => 'category-touch' ]
                        );
                }
+
+               JobQueueGroup::singleton()->lazyPush( $jobs );
        }
 
        /**
index a48d032..c94e8d4 100644 (file)
@@ -547,7 +547,7 @@ class WebRequest {
         *
         * @param string $name
         * @param array|null $default Option default (or null)
-        * @return array Array of ints
+        * @return int[]|null
         */
        public function getIntArray( $name, $default = null ) {
                $val = $this->getArray( $name, $default );
index f892c5e..4be2f7d 100644 (file)
@@ -22,7 +22,7 @@
 use MediaWiki\MediaWikiServices;
 
 /**
- * @defgroup Actions Action done on pages
+ * @defgroup Actions Actions
  */
 
 /**
index db874f2..6a61045 100644 (file)
@@ -433,27 +433,30 @@ class HistoryAction extends FormlessAction {
         * @return FeedItem
         */
        function feedItem( $row ) {
-               $rev = new Revision( $row, 0, $this->getTitle() );
-
+               $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
+               $rev = $revisionStore->newRevisionFromRow( $row, 0, $this->getTitle() );
+               $prevRev = $revisionStore->getPreviousRevision( $rev );
+               $revComment = $rev->getComment() === null ? null : $rev->getComment()->text;
                $text = FeedUtils::formatDiffRow(
                        $this->getTitle(),
-                       $this->getTitle()->getPreviousRevisionID( $rev->getId() ),
+                       $prevRev ? $prevRev->getId() : false,
                        $rev->getId(),
                        $rev->getTimestamp(),
-                       $rev->getComment()
+                       $revComment
                );
-               if ( $rev->getComment() == '' ) {
+               $revUserText = $rev->getUser() ? $rev->getUser()->getName() : '';
+               if ( $revComment == '' ) {
                        $contLang = MediaWikiServices::getInstance()->getContentLanguage();
                        $title = $this->msg( 'history-feed-item-nocomment',
-                               $rev->getUserText(),
+                               $revUserText,
                                $contLang->timeanddate( $rev->getTimestamp() ),
                                $contLang->date( $rev->getTimestamp() ),
                                $contLang->time( $rev->getTimestamp() )
                        )->inContentLanguage()->text();
                } else {
-                       $title = $rev->getUserText() .
+                       $title = $revUserText .
                                $this->msg( 'colon-separator' )->inContentLanguage()->text() .
-                               FeedItem::stripComment( $rev->getComment() );
+                               FeedItem::stripComment( $revComment );
                }
 
                return new FeedItem(
@@ -461,7 +464,7 @@ class HistoryAction extends FormlessAction {
                        $text,
                        $this->getTitle()->getFullURL( 'diff=' . $rev->getId() . '&oldid=prev' ),
                        $rev->getTimestamp(),
-                       $rev->getUserText(),
+                       $revUserText,
                        $this->getTitle()->getTalkPage()->getFullURL()
                );
        }
index 7bcfc88..0360fe4 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 use MediaWiki\MediaWikiServices;
-use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Revision\RevisionRecord;
 use Wikimedia\Rdbms\Database;
 
 /**
@@ -280,11 +280,10 @@ class InfoAction extends FormlessAction {
                // Language in which the page content is (supposed to be) written
                $pageLang = $title->getPageLanguage()->getCode();
 
-               $permissionManager = $services->getPermissionManager();
-
                $pageLangHtml = $pageLang . ' - ' .
                        Language::fetchLanguageName( $pageLang, $lang->getCode() );
                // Link to Special:PageLanguage with pre-filled page title if user has permissions
+               $permissionManager = $services->getPermissionManager();
                if ( $config->get( 'PageLanguageUseDB' )
                        && $permissionManager->userCan( 'pagelang', $user, $title )
                ) {
@@ -344,8 +343,7 @@ class InfoAction extends FormlessAction {
                ];
 
                $unwatchedPageThreshold = $config->get( 'UnwatchedPageThreshold' );
-               if (
-                       $services->getPermissionManager()->userHasRight( $user, 'unwatchedpages' ) ||
+               if ( $permissionManager->userHasRight( $user, 'unwatchedpages' ) ||
                        ( $unwatchedPageThreshold !== false &&
                                $pageCounts['watchers'] >= $unwatchedPageThreshold )
                ) {
@@ -360,7 +358,7 @@ class InfoAction extends FormlessAction {
                        ) {
                                $minToDisclose = $config->get( 'UnwatchedPageSecret' );
                                if ( $pageCounts['visitingWatchers'] > $minToDisclose ||
-                                       $services->getPermissionManager()->userHasRight( $user, 'unwatchedpages' ) ) {
+                                       $permissionManager->userHasRight( $user, 'unwatchedpages' ) ) {
                                        $pageInfo['header-basic'][] = [
                                                $this->msg( 'pageinfo-visiting-watchers' ),
                                                $lang->formatNum( $pageCounts['visitingWatchers'] )
@@ -743,8 +741,6 @@ class InfoAction extends FormlessAction {
                        self::getCacheKey( $cache, $page->getTitle(), $page->getLatest() ),
                        WANObjectCache::TTL_WEEK,
                        function ( $oldValue, &$ttl, &$setOpts ) use ( $page, $config, $fname, $services ) {
-                               global $wgActorTableSchemaMigrationStage;
-
                                $title = $page->getTitle();
                                $id = $title->getArticleID();
 
@@ -752,19 +748,11 @@ class InfoAction extends FormlessAction {
                                $dbrWatchlist = wfGetDB( DB_REPLICA, 'watchlist' );
                                $setOpts += Database::getCacheSetOptions( $dbr, $dbrWatchlist );
 
-                               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                                       $tables = [ 'revision_actor_temp' ];
-                                       $field = 'revactor_actor';
-                                       $pageField = 'revactor_page';
-                                       $tsField = 'revactor_timestamp';
-                                       $joins = [];
-                               } else {
-                                       $tables = [ 'revision' ];
-                                       $field = 'rev_user_text';
-                                       $pageField = 'rev_page';
-                                       $tsField = 'rev_timestamp';
-                                       $joins = [];
-                               }
+                               $tables = [ 'revision_actor_temp' ];
+                               $field = 'revactor_actor';
+                               $pageField = 'revactor_page';
+                               $tsField = 'revactor_timestamp';
+                               $joins = [];
 
                                $watchedItemStore = $services->getWatchedItemStore();
 
index 41cd24e..68c0ea1 100644 (file)
@@ -289,8 +289,9 @@ class McrUndoAction extends FormAction {
                                'h2', [ 'id' => 'mw-previewheader' ],
                                $this->context->msg( 'preview' )->text()
                        ) .
-                       $out->parseAsInterface( $note ) .
-                       "<hr />"
+                       Html::rawElement( 'div', [ 'class' => 'warningbox' ],
+                               $out->parseAsInterface( $note )
+                       )
                );
 
                $pageViewLang = $this->getTitle()->getPageViewLanguage();
index 8fd4e0a..0586e09 100644 (file)
@@ -238,23 +238,31 @@ class RawAction extends FormlessAction {
         */
        public function getOldId() {
                $oldid = $this->getRequest()->getInt( 'oldid' );
+               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
                switch ( $this->getRequest()->getText( 'direction' ) ) {
                        case 'next':
                                # output next revision, or nothing if there isn't one
-                               $nextid = 0;
+                               $nextRev = null;
                                if ( $oldid ) {
-                                       $nextid = $this->getTitle()->getNextRevisionID( $oldid );
+                                       $oldRev = $rl->getRevisionById( $oldid );
+                                       if ( $oldRev ) {
+                                               $nextRev = $rl->getNextRevision( $oldRev );
+                                       }
                                }
-                               $oldid = $nextid ?: -1;
+                               $oldid = $nextRev ? $nextRev->getId() : -1;
                                break;
                        case 'prev':
                                # output previous revision, or nothing if there isn't one
+                               $prevRev = null;
                                if ( !$oldid ) {
                                        # get the current revision so we can get the penultimate one
                                        $oldid = $this->page->getLatest();
                                }
-                               $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
-                               $oldid = $previd ?: -1;
+                               $oldRev = $rl->getRevisionById( $oldid );
+                               if ( $oldRev ) {
+                                       $prevRev = $rl->getPreviousRevision( $oldRev );
+                               }
+                               $oldid = $prevRev ? $prevRev->getId() : -1;
                                break;
                        case 'cur':
                                $oldid = 0;
index 519da61..1c9e63b 100644 (file)
@@ -20,7 +20,7 @@
  * @ingroup Actions
  */
 
-use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Revision\RevisionRecord;
 
 /**
  * User interface for the rollback action
index 8a231cb..56be456 100644 (file)
@@ -35,6 +35,9 @@ class SpecialPageAction extends FormlessAction {
                'editchangetags' => 'EditTags',
        ];
 
+       /**
+        * @inheritDoc
+        */
        public function getName() {
                $request = $this->getRequest();
                $actionName = $request->getVal( 'action', 'view' );