summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
Diffstat (limited to 'includes')
-rw-r--r--includes/Action.php62
-rw-r--r--includes/AjaxResponse.php4
-rw-r--r--includes/ArrayUtils.php69
-rw-r--r--includes/Article.php282
-rw-r--r--includes/AuthPlugin.php16
-rw-r--r--includes/AutoLoader.php185
-rw-r--r--includes/Autopromote.php12
-rw-r--r--includes/Block.php146
-rw-r--r--includes/CacheHelper.php2
-rw-r--r--includes/Category.php92
-rw-r--r--includes/CategoryPage.php4
-rw-r--r--includes/CategoryViewer.php85
-rw-r--r--includes/Categoryfinder.php39
-rw-r--r--includes/Cdb.php8
-rw-r--r--includes/Cdb_PHP.php24
-rw-r--r--includes/ChangeTags.php33
-rw-r--r--includes/ChangesFeed.php22
-rw-r--r--includes/ChangesList.php150
-rw-r--r--includes/Collation.php295
-rw-r--r--includes/ConfEditor.php12
-rw-r--r--includes/Cookie.php31
-rw-r--r--includes/CryptRand.php22
-rw-r--r--includes/DataUpdate.php10
-rw-r--r--includes/DefaultSettings.php1266
-rw-r--r--includes/DeferredUpdates.php6
-rw-r--r--includes/Defines.php56
-rw-r--r--includes/DeprecatedGlobal.php2
-rw-r--r--includes/EditPage.php1132
-rw-r--r--includes/Exception.php87
-rw-r--r--includes/Export.php119
-rw-r--r--includes/ExternalEdit.php4
-rw-r--r--includes/ExternalStore.php172
-rw-r--r--includes/ExternalUser.php16
-rw-r--r--includes/FakeTitle.php6
-rw-r--r--includes/Fallback.php27
-rw-r--r--includes/Feed.php28
-rw-r--r--includes/FeedUtils.php90
-rw-r--r--includes/FileDeleteForm.php18
-rw-r--r--includes/ForkController.php4
-rw-r--r--includes/FormOptions.php32
-rw-r--r--includes/GitInfo.php16
-rw-r--r--includes/GlobalFunctions.php448
-rw-r--r--includes/HTMLForm.php286
-rw-r--r--includes/HistoryBlob.php51
-rw-r--r--includes/Hooks.php120
-rw-r--r--includes/Html.php230
-rw-r--r--includes/HttpFunctions.php46
-rw-r--r--includes/IP.php42
-rw-r--r--includes/ImageGallery.php30
-rw-r--r--includes/ImagePage.php190
-rw-r--r--includes/Import.php144
-rw-r--r--includes/Init.php4
-rw-r--r--includes/Licenses.php9
-rw-r--r--includes/LinkFilter.php40
-rw-r--r--includes/Linker.php454
-rw-r--r--includes/LinksUpdate.php100
-rw-r--r--includes/MagicWord.php26
-rw-r--r--includes/MappedIterator.php96
-rw-r--r--includes/Message.php165
-rw-r--r--includes/MessageBlobStore.php33
-rw-r--r--includes/Metadata.php57
-rw-r--r--includes/MimeMagic.php251
-rw-r--r--includes/Namespace.php63
-rw-r--r--includes/OutputHandler.php10
-rw-r--r--includes/OutputPage.php390
-rw-r--r--includes/PHPVersionError.php33
-rw-r--r--includes/Pager.php61
-rw-r--r--includes/PathRouter.php10
-rw-r--r--includes/PoolCounter.php14
-rw-r--r--includes/Preferences.php113
-rw-r--r--includes/PrefixSearch.php10
-rw-r--r--includes/ProtectionForm.php62
-rw-r--r--includes/ProxyTools.php6
-rw-r--r--includes/QueryPage.php86
-rw-r--r--includes/RecentChange.php235
-rw-r--r--includes/Revision.php483
-rw-r--r--includes/RevisionList.php4
-rw-r--r--includes/Sanitizer.php207
-rw-r--r--includes/ScopedCallback.php40
-rw-r--r--includes/SeleniumWebSettings.php27
-rw-r--r--includes/Setup.php36
-rw-r--r--includes/SiteConfiguration.php163
-rw-r--r--includes/SiteStats.php22
-rw-r--r--includes/Skin.php76
-rw-r--r--includes/SkinLegacy.php22
-rw-r--r--includes/SkinTemplate.php154
-rw-r--r--includes/SpecialPage.php177
-rw-r--r--includes/SpecialPageFactory.php59
-rw-r--r--includes/SqlDataUpdate.php14
-rw-r--r--includes/SquidPurgeClient.php47
-rw-r--r--includes/Status.php76
-rw-r--r--includes/StreamFile.php19
-rw-r--r--includes/StringUtils.php73
-rw-r--r--includes/StubObject.php23
-rw-r--r--includes/Timestamp.php42
-rw-r--r--includes/Title.php889
-rw-r--r--includes/TitleArray.php4
-rw-r--r--includes/UIDGenerator.php350
-rw-r--r--includes/User.php903
-rw-r--r--includes/UserMailer.php245
-rw-r--r--includes/UserRightsProxy.php14
-rw-r--r--includes/ViewCountUpdate.php17
-rw-r--r--includes/WatchedItem.php75
-rw-r--r--includes/WebRequest.php121
-rw-r--r--includes/WebResponse.php56
-rw-r--r--includes/WebStart.php19
-rw-r--r--includes/Wiki.php88
-rw-r--r--includes/WikiError.php2
-rw-r--r--includes/WikiFilePage.php9
-rw-r--r--includes/WikiMap.php26
-rw-r--r--includes/WikiPage.php1320
-rw-r--r--includes/Xml.php202
-rw-r--r--includes/XmlTypeCheck.php2
-rw-r--r--includes/ZhClient.php10
-rw-r--r--includes/ZhConversion.php792
-rw-r--r--includes/ZipDirectoryReader.php40
-rw-r--r--includes/actions/CachedAction.php36
-rw-r--r--includes/actions/CreditsAction.php13
-rw-r--r--includes/actions/DeleteAction.php11
-rw-r--r--includes/actions/EditAction.php21
-rw-r--r--includes/actions/HistoryAction.php77
-rw-r--r--includes/actions/InfoAction.php320
-rw-r--r--includes/actions/MarkpatrolledAction.php5
-rw-r--r--includes/actions/ProtectAction.php20
-rw-r--r--includes/actions/PurgeAction.php15
-rw-r--r--includes/actions/RawAction.php35
-rw-r--r--includes/actions/RenderAction.php11
-rw-r--r--includes/actions/RevertAction.php6
-rw-r--r--includes/actions/RevisiondeleteAction.php5
-rw-r--r--includes/actions/RollbackAction.php35
-rw-r--r--includes/actions/ViewAction.php11
-rw-r--r--includes/actions/WatchAction.php10
-rw-r--r--includes/api/ApiBase.php386
-rw-r--r--includes/api/ApiBlock.php29
-rw-r--r--includes/api/ApiComparePages.php22
-rw-r--r--includes/api/ApiCreateAccount.php298
-rw-r--r--includes/api/ApiDelete.php25
-rw-r--r--includes/api/ApiDisabled.php8
-rw-r--r--includes/api/ApiEditPage.php181
-rw-r--r--includes/api/ApiEmailUser.php10
-rw-r--r--includes/api/ApiExpandTemplates.php10
-rw-r--r--includes/api/ApiFeedContributions.php26
-rw-r--r--includes/api/ApiFeedWatchlist.php20
-rw-r--r--includes/api/ApiFileRevert.php16
-rw-r--r--includes/api/ApiFormatBase.php48
-rw-r--r--includes/api/ApiFormatDbg.php8
-rw-r--r--includes/api/ApiFormatDump.php8
-rw-r--r--includes/api/ApiFormatJson.php6
-rw-r--r--includes/api/ApiFormatNone.php (renamed from includes/HttpFunctions.old.php)30
-rw-r--r--includes/api/ApiFormatPhp.php8
-rw-r--r--includes/api/ApiFormatRaw.php4
-rw-r--r--includes/api/ApiFormatTxt.php8
-rw-r--r--includes/api/ApiFormatWddx.php8
-rw-r--r--includes/api/ApiFormatXml.php20
-rw-r--r--includes/api/ApiFormatYaml.php6
-rw-r--r--includes/api/ApiHelp.php91
-rw-r--r--includes/api/ApiImageRotate.php232
-rw-r--r--includes/api/ApiImport.php14
-rw-r--r--includes/api/ApiLogin.php8
-rw-r--r--includes/api/ApiLogout.php8
-rw-r--r--includes/api/ApiMain.php289
-rw-r--r--includes/api/ApiModuleManager.php171
-rw-r--r--includes/api/ApiMove.php25
-rw-r--r--includes/api/ApiOpenSearch.php8
-rw-r--r--includes/api/ApiOptions.php68
-rw-r--r--includes/api/ApiPageSet.php560
-rw-r--r--includes/api/ApiParamInfo.php114
-rw-r--r--includes/api/ApiParse.php132
-rw-r--r--includes/api/ApiPatrol.php8
-rw-r--r--includes/api/ApiProtect.php10
-rw-r--r--includes/api/ApiPurge.php142
-rw-r--r--includes/api/ApiQuery.php649
-rw-r--r--includes/api/ApiQueryAllCategories.php16
-rw-r--r--includes/api/ApiQueryAllImages.php63
-rw-r--r--includes/api/ApiQueryAllLinks.php138
-rw-r--r--includes/api/ApiQueryAllMessages.php21
-rw-r--r--includes/api/ApiQueryAllPages.php20
-rw-r--r--includes/api/ApiQueryAllUsers.php18
-rw-r--r--includes/api/ApiQueryBacklinks.php35
-rw-r--r--includes/api/ApiQueryBase.php138
-rw-r--r--includes/api/ApiQueryBlocks.php18
-rw-r--r--includes/api/ApiQueryCategories.php11
-rw-r--r--includes/api/ApiQueryCategoryInfo.php5
-rw-r--r--includes/api/ApiQueryCategoryMembers.php17
-rw-r--r--includes/api/ApiQueryDeletedrevs.php23
-rw-r--r--includes/api/ApiQueryDisabled.php8
-rw-r--r--includes/api/ApiQueryDuplicateFiles.php19
-rw-r--r--includes/api/ApiQueryExtLinksUsage.php20
-rw-r--r--includes/api/ApiQueryExternalLinks.php16
-rw-r--r--includes/api/ApiQueryFilearchive.php35
-rw-r--r--includes/api/ApiQueryIWBacklinks.php10
-rw-r--r--includes/api/ApiQueryIWLinks.php10
-rw-r--r--includes/api/ApiQueryImageInfo.php122
-rw-r--r--includes/api/ApiQueryImages.php17
-rw-r--r--includes/api/ApiQueryInfo.php149
-rw-r--r--includes/api/ApiQueryLangBacklinks.php10
-rw-r--r--includes/api/ApiQueryLangLinks.php12
-rw-r--r--includes/api/ApiQueryLinks.php17
-rw-r--r--includes/api/ApiQueryLogEvents.php51
-rw-r--r--includes/api/ApiQueryORM.php264
-rw-r--r--includes/api/ApiQueryPagePropNames.php116
-rw-r--r--includes/api/ApiQueryPageProps.php17
-rw-r--r--includes/api/ApiQueryPagesWithProp.php189
-rw-r--r--includes/api/ApiQueryProtectedTitles.php9
-rw-r--r--includes/api/ApiQueryQueryPage.php8
-rw-r--r--includes/api/ApiQueryRandom.php6
-rw-r--r--includes/api/ApiQueryRecentChanges.php63
-rw-r--r--includes/api/ApiQueryRevisions.php180
-rw-r--r--includes/api/ApiQuerySearch.php8
-rw-r--r--includes/api/ApiQuerySiteinfo.php57
-rw-r--r--includes/api/ApiQueryStashImageInfo.php7
-rw-r--r--includes/api/ApiQueryTags.php6
-rw-r--r--includes/api/ApiQueryUserContributions.php13
-rw-r--r--includes/api/ApiQueryUserInfo.php10
-rw-r--r--includes/api/ApiQueryUsers.php76
-rw-r--r--includes/api/ApiQueryWatchlist.php18
-rw-r--r--includes/api/ApiQueryWatchlistRaw.php10
-rw-r--r--includes/api/ApiResult.php99
-rw-r--r--includes/api/ApiRollback.php10
-rw-r--r--includes/api/ApiRsd.php12
-rw-r--r--includes/api/ApiSetNotificationTimestamp.php66
-rw-r--r--includes/api/ApiTokens.php70
-rw-r--r--includes/api/ApiUnblock.php8
-rw-r--r--includes/api/ApiUndelete.php18
-rw-r--r--includes/api/ApiUpload.php275
-rw-r--r--includes/api/ApiUserrights.php8
-rw-r--r--includes/api/ApiWatch.php25
-rw-r--r--includes/cache/BacklinkCache.php (renamed from includes/BacklinkCache.php)89
-rw-r--r--includes/cache/CacheDependency.php12
-rw-r--r--includes/cache/FileCacheBase.php6
-rw-r--r--includes/cache/GenderCache.php8
-rw-r--r--includes/cache/HTMLCacheUpdate.php226
-rw-r--r--includes/cache/HTMLFileCache.php7
-rw-r--r--includes/cache/LinkBatch.php2
-rw-r--r--includes/cache/LinkCache.php32
-rw-r--r--includes/cache/LocalisationCache.php (renamed from includes/LocalisationCache.php)29
-rw-r--r--includes/cache/MessageCache.php243
-rw-r--r--includes/cache/ProcessCacheLRU.php19
-rw-r--r--includes/cache/SquidUpdate.php15
-rw-r--r--includes/cache/UserCache.php12
-rw-r--r--includes/clientpool/RedisConnectionPool.php312
-rw-r--r--includes/content/AbstractContent.php444
-rw-r--r--includes/content/Content.php508
-rw-r--r--includes/content/ContentHandler.php1114
-rw-r--r--includes/content/CssContent.php65
-rw-r--r--includes/content/CssContentHandler.php67
-rw-r--r--includes/content/JavaScriptContent.php66
-rw-r--r--includes/content/JavaScriptContentHandler.php67
-rw-r--r--includes/content/MessageContent.php158
-rw-r--r--includes/content/TextContent.php286
-rw-r--r--includes/content/TextContentHandler.php115
-rw-r--r--includes/content/WikitextContent.php322
-rw-r--r--includes/content/WikitextContentHandler.php98
-rw-r--r--includes/context/ContextSource.php22
-rw-r--r--includes/context/DerivativeContext.php24
-rw-r--r--includes/context/IContextSource.php15
-rw-r--r--includes/context/RequestContext.php137
-rw-r--r--includes/dao/DBAccessBase.php92
-rw-r--r--includes/dao/IDBAccessObject.php4
-rw-r--r--includes/db/CloneDatabase.php23
-rw-r--r--includes/db/Database.php625
-rw-r--r--includes/db/DatabaseError.php22
-rw-r--r--includes/db/DatabaseIbm_db2.php1721
-rw-r--r--includes/db/DatabaseMssql.php105
-rw-r--r--includes/db/DatabaseMysql.php61
-rw-r--r--includes/db/DatabaseOracle.php76
-rw-r--r--includes/db/DatabasePostgres.php156
-rw-r--r--includes/db/DatabaseSqlite.php47
-rw-r--r--includes/db/DatabaseUtility.php13
-rw-r--r--includes/db/IORMRow.php5
-rw-r--r--includes/db/IORMTable.php91
-rw-r--r--includes/db/LBFactory.php22
-rw-r--r--includes/db/LBFactory_Multi.php11
-rw-r--r--includes/db/LBFactory_Single.php2
-rw-r--r--includes/db/LoadBalancer.php150
-rw-r--r--includes/db/LoadMonitor.php9
-rw-r--r--includes/db/ORMIterator.php4
-rw-r--r--includes/db/ORMResult.php2
-rw-r--r--includes/db/ORMRow.php47
-rw-r--r--includes/db/ORMTable.php295
-rw-r--r--includes/debug/Debug.php11
-rw-r--r--includes/diff/DairikiDiff.php79
-rw-r--r--includes/diff/DifferenceEngine.php191
-rw-r--r--includes/diff/WikiDiff3.php5
-rw-r--r--includes/extauth/MediaWiki.php24
-rw-r--r--includes/externalstore/ExternalStore.php178
-rw-r--r--includes/externalstore/ExternalStoreDB.php (renamed from includes/ExternalStoreDB.php)114
-rw-r--r--includes/externalstore/ExternalStoreHttp.php (renamed from includes/ExternalStoreHttp.php)20
-rw-r--r--includes/externalstore/ExternalStoreMedium.php60
-rw-r--r--includes/externalstore/ExternalStoreMwstore.php72
-rw-r--r--includes/filebackend/FSFile.php49
-rw-r--r--includes/filebackend/FSFileBackend.php341
-rw-r--r--includes/filebackend/FileBackend.php370
-rw-r--r--includes/filebackend/FileBackendGroup.php10
-rw-r--r--includes/filebackend/FileBackendMultiWrite.php91
-rw-r--r--includes/filebackend/FileBackendStore.php502
-rw-r--r--includes/filebackend/FileOp.php332
-rw-r--r--includes/filebackend/FileOpBatch.php62
-rw-r--r--includes/filebackend/README208
-rw-r--r--includes/filebackend/SwiftFileBackend.php483
-rw-r--r--includes/filebackend/TempFSFile.php13
-rw-r--r--includes/filebackend/filejournal/DBFileJournal.php32
-rw-r--r--includes/filebackend/filejournal/FileJournal.php65
-rw-r--r--includes/filebackend/lockmanager/DBLockManager.php227
-rw-r--r--includes/filebackend/lockmanager/FSLockManager.php42
-rw-r--r--includes/filebackend/lockmanager/LSLockManager.php8
-rw-r--r--includes/filebackend/lockmanager/LockManager.php324
-rw-r--r--includes/filebackend/lockmanager/LockManagerGroup.php54
-rw-r--r--includes/filebackend/lockmanager/MemcLockManager.php94
-rw-r--r--includes/filebackend/lockmanager/QuorumLockManager.php230
-rw-r--r--includes/filebackend/lockmanager/ScopedLock.php102
-rw-r--r--includes/filerepo/FSRepo.php8
-rw-r--r--includes/filerepo/FileRepo.php253
-rw-r--r--includes/filerepo/ForeignAPIRepo.php18
-rw-r--r--includes/filerepo/ForeignDBRepo.php2
-rw-r--r--includes/filerepo/ForeignDBViaLBRepo.php2
-rw-r--r--includes/filerepo/LocalRepo.php53
-rw-r--r--includes/filerepo/README23
-rw-r--r--includes/filerepo/RepoGroup.php24
-rw-r--r--includes/filerepo/file/ArchivedFile.php152
-rw-r--r--includes/filerepo/file/File.php208
-rw-r--r--includes/filerepo/file/ForeignAPIFile.php8
-rw-r--r--includes/filerepo/file/ForeignDBFile.php15
-rw-r--r--includes/filerepo/file/LocalFile.php281
-rw-r--r--includes/filerepo/file/OldLocalFile.php65
-rw-r--r--includes/filerepo/file/UnregisteredLocalFile.php22
-rw-r--r--includes/installer/CliInstaller.php6
-rw-r--r--includes/installer/DatabaseInstaller.php23
-rw-r--r--includes/installer/DatabaseUpdater.php449
-rw-r--r--includes/installer/Ibm_db2Installer.php270
-rw-r--r--includes/installer/Ibm_db2Updater.php91
-rw-r--r--includes/installer/InstallDocFormatter.php6
-rw-r--r--includes/installer/Installer.i18n.php3294
-rw-r--r--includes/installer/Installer.php67
-rw-r--r--includes/installer/LocalSettingsGenerator.php50
-rw-r--r--includes/installer/MysqlInstaller.php17
-rw-r--r--includes/installer/MysqlUpdater.php106
-rw-r--r--includes/installer/OracleInstaller.php9
-rw-r--r--includes/installer/OracleUpdater.php29
-rw-r--r--includes/installer/PostgresInstaller.php21
-rw-r--r--includes/installer/PostgresUpdater.php96
-rw-r--r--includes/installer/SqliteInstaller.php6
-rw-r--r--includes/installer/SqliteUpdater.php34
-rw-r--r--includes/installer/WebInstaller.php37
-rw-r--r--includes/installer/WebInstallerOutput.php8
-rw-r--r--includes/installer/WebInstallerPage.php49
-rw-r--r--includes/interwiki/Interwiki.php96
-rw-r--r--includes/job/Job.php416
-rw-r--r--includes/job/JobQueue.php435
-rw-r--r--includes/job/JobQueueAggregator.php139
-rw-r--r--includes/job/JobQueueAggregatorMemc.php117
-rw-r--r--includes/job/JobQueueAggregatorRedis.php165
-rw-r--r--includes/job/JobQueueDB.php716
-rw-r--r--includes/job/JobQueueGroup.php351
-rw-r--r--includes/job/README81
-rw-r--r--includes/job/RefreshLinksJob.php202
-rw-r--r--includes/job/jobs/AssembleUploadChunksJob.php118
-rw-r--r--includes/job/jobs/DoubleRedirectJob.php (renamed from includes/job/DoubleRedirectJob.php)65
-rw-r--r--includes/job/jobs/DuplicateJob.php59
-rw-r--r--includes/job/jobs/EmaillingJob.php (renamed from includes/job/EmaillingJob.php)5
-rw-r--r--includes/job/jobs/EnotifNotifyJob.php (renamed from includes/job/EnotifNotifyJob.php)3
-rw-r--r--includes/job/jobs/HTMLCacheUpdateJob.php254
-rw-r--r--includes/job/jobs/NullJob.php60
-rw-r--r--includes/job/jobs/PublishStashedFileJob.php130
-rw-r--r--includes/job/jobs/RefreshLinksJob.php226
-rw-r--r--includes/job/jobs/UploadFromUrlJob.php (renamed from includes/job/UploadFromUrlJob.php)4
-rw-r--r--includes/json/FormatJson.php19
-rw-r--r--includes/json/Services_JSON.php24
-rw-r--r--includes/libs/CSSJanus.php15
-rw-r--r--includes/libs/CSSMin.php14
-rw-r--r--includes/libs/GenericArrayObject.php15
-rw-r--r--includes/libs/IEContentAnalyzer.php13
-rw-r--r--includes/libs/IEUrlExtension.php12
-rw-r--r--includes/libs/JavaScriptMinifier.php20
-rw-r--r--includes/libs/jsminplus.php6
-rw-r--r--includes/limit.sh102
-rw-r--r--includes/logging/LogEntry.php78
-rw-r--r--includes/logging/LogEventsList.php84
-rw-r--r--includes/logging/LogFormatter.php234
-rw-r--r--includes/logging/LogPage.php75
-rw-r--r--includes/logging/LogPager.php44
-rw-r--r--includes/media/BMP.php2
-rw-r--r--includes/media/Bitmap.php84
-rw-r--r--includes/media/BitmapMetadataHandler.php60
-rw-r--r--includes/media/DjVu.php10
-rw-r--r--includes/media/DjVuImage.php27
-rw-r--r--includes/media/Exif.php169
-rw-r--r--includes/media/ExifBitmap.php15
-rw-r--r--includes/media/FormatMetadata.php102
-rw-r--r--includes/media/GIF.php26
-rw-r--r--includes/media/GIFMetadataExtractor.php46
-rw-r--r--includes/media/IPTC.php136
-rw-r--r--includes/media/ImageHandler.php7
-rw-r--r--includes/media/Jpeg.php35
-rw-r--r--includes/media/JpegMetadataExtractor.php57
-rw-r--r--includes/media/MediaHandler.php112
-rw-r--r--includes/media/MediaTransformOutput.php43
-rw-r--r--includes/media/PNG.php24
-rw-r--r--includes/media/PNGMetadataExtractor.php4
-rw-r--r--includes/media/SVG.php67
-rw-r--r--includes/media/SVGMetadataExtractor.php39
-rw-r--r--includes/media/Tiff.php7
-rw-r--r--includes/media/XCF.php4
-rw-r--r--includes/media/XMP.php657
-rw-r--r--includes/media/XMPInfo.php63
-rw-r--r--includes/media/XMPValidate.php193
-rw-r--r--includes/mime.types2
-rw-r--r--includes/mobile/DeviceDetection.php459
-rw-r--r--includes/normal/Makefile2
-rw-r--r--includes/normal/RandomTest.php2
-rw-r--r--includes/normal/Utf8CaseGenerate.php6
-rw-r--r--includes/normal/Utf8Test.php7
-rw-r--r--includes/normal/UtfNormal.php32
-rw-r--r--includes/normal/UtfNormalBench.php12
-rw-r--r--includes/normal/UtfNormalDefines.php4
-rw-r--r--includes/normal/UtfNormalGenerate.php4
-rw-r--r--includes/normal/UtfNormalMemStress.php10
-rw-r--r--includes/normal/UtfNormalTest.php8
-rw-r--r--includes/normal/UtfNormalTest2.php4
-rw-r--r--includes/normal/UtfNormalUtil.php6
-rw-r--r--includes/objectcache/APCBagOStuff.php43
-rw-r--r--includes/objectcache/BagOStuff.php131
-rw-r--r--includes/objectcache/DBABagOStuff.php63
-rw-r--r--includes/objectcache/EhcacheBagOStuff.php72
-rw-r--r--includes/objectcache/EmptyBagOStuff.php25
-rw-r--r--includes/objectcache/HashBagOStuff.php28
-rw-r--r--includes/objectcache/MemcachedBagOStuff.php27
-rw-r--r--includes/objectcache/MemcachedClient.php187
-rw-r--r--includes/objectcache/MemcachedPeclBagOStuff.php27
-rw-r--r--includes/objectcache/MemcachedPhpBagOStuff.php3
-rw-r--r--includes/objectcache/MultiWriteBagOStuff.php29
-rw-r--r--includes/objectcache/ObjectCache.php8
-rw-r--r--includes/objectcache/ObjectCacheSessionHandler.php8
-rw-r--r--includes/objectcache/RedisBagOStuff.php189
-rw-r--r--includes/objectcache/SqlBagOStuff.php528
-rw-r--r--includes/objectcache/WinCacheBagOStuff.php47
-rw-r--r--includes/objectcache/XCacheBagOStuff.php40
-rw-r--r--includes/parser/CacheTime.php2
-rw-r--r--includes/parser/CoreLinkFunctions.php12
-rw-r--r--includes/parser/CoreParserFunctions.php76
-rw-r--r--includes/parser/CoreTagHooks.php1
-rw-r--r--includes/parser/DateFormatter.php54
-rw-r--r--includes/parser/LinkHolderArray.php96
-rw-r--r--includes/parser/Parser.php744
-rw-r--r--includes/parser/ParserCache.php7
-rw-r--r--includes/parser/ParserOptions.php86
-rw-r--r--includes/parser/ParserOutput.php208
-rw-r--r--includes/parser/Parser_LinkHooks.php118
-rw-r--r--includes/parser/Preprocessor.php7
-rw-r--r--includes/parser/Preprocessor_DOM.php77
-rw-r--r--includes/parser/Preprocessor_Hash.php76
-rw-r--r--includes/parser/Preprocessor_HipHop.hphp2013
-rw-r--r--includes/parser/StripState.php7
-rw-r--r--includes/parser/Tidy.php58
-rw-r--r--includes/profiler/Profiler.php174
-rw-r--r--includes/profiler/ProfilerSimple.php26
-rw-r--r--includes/profiler/ProfilerSimpleText.php18
-rw-r--r--includes/profiler/ProfilerSimpleTrace.php22
-rw-r--r--includes/profiler/ProfilerSimpleUDP.php2
-rw-r--r--includes/resourceloader/ResourceLoader.php93
-rw-r--r--includes/resourceloader/ResourceLoaderContext.php18
-rw-r--r--includes/resourceloader/ResourceLoaderFileModule.php139
-rw-r--r--includes/resourceloader/ResourceLoaderLanguageDataModule.php34
-rw-r--r--includes/resourceloader/ResourceLoaderModule.php56
-rw-r--r--includes/resourceloader/ResourceLoaderNoscriptModule.php2
-rw-r--r--includes/resourceloader/ResourceLoaderSiteModule.php6
-rw-r--r--includes/resourceloader/ResourceLoaderStartUpModule.php55
-rw-r--r--includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php2
-rw-r--r--includes/resourceloader/ResourceLoaderUserTokensModule.php3
-rw-r--r--includes/resourceloader/ResourceLoaderWikiModule.php36
-rw-r--r--includes/revisiondelete/RevisionDelete.php13
-rw-r--r--includes/revisiondelete/RevisionDeleteAbstracts.php7
-rw-r--r--includes/revisiondelete/RevisionDeleter.php4
-rw-r--r--includes/search/SearchEngine.php83
-rw-r--r--includes/search/SearchIBM_DB2.php234
-rw-r--r--includes/search/SearchMssql.php19
-rw-r--r--includes/search/SearchMySQL.php8
-rw-r--r--includes/search/SearchOracle.php142
-rw-r--r--includes/search/SearchPostgres.php44
-rw-r--r--includes/search/SearchSqlite.php15
-rw-r--r--includes/search/SearchUpdate.php13
-rw-r--r--includes/site/MediaWikiSite.php352
-rw-r--r--includes/site/Site.php702
-rw-r--r--includes/site/SiteList.php300
-rw-r--r--includes/site/SiteSQLStore.php491
-rw-r--r--includes/site/SiteStore.php85
-rw-r--r--includes/specials/SpecialActiveusers.php37
-rw-r--r--includes/specials/SpecialAllmessages.php46
-rw-r--r--includes/specials/SpecialAllpages.php96
-rw-r--r--includes/specials/SpecialAncientpages.php8
-rw-r--r--includes/specials/SpecialBlankpage.php2
-rw-r--r--includes/specials/SpecialBlock.php100
-rw-r--r--includes/specials/SpecialBlockList.php34
-rw-r--r--includes/specials/SpecialBlockme.php6
-rw-r--r--includes/specials/SpecialBooksources.php42
-rw-r--r--includes/specials/SpecialBrokenRedirects.php63
-rw-r--r--includes/specials/SpecialCachedPage.php4
-rw-r--r--includes/specials/SpecialCategories.php8
-rw-r--r--includes/specials/SpecialChangeEmail.php14
-rw-r--r--includes/specials/SpecialChangePassword.php73
-rw-r--r--includes/specials/SpecialComparePages.php31
-rw-r--r--includes/specials/SpecialConfirmemail.php10
-rw-r--r--includes/specials/SpecialContributions.php89
-rw-r--r--includes/specials/SpecialDeadendpages.php4
-rw-r--r--includes/specials/SpecialDeletedContributions.php19
-rw-r--r--includes/specials/SpecialDisambiguations.php14
-rw-r--r--includes/specials/SpecialDoubleRedirects.php81
-rw-r--r--includes/specials/SpecialEditWatchlist.php57
-rw-r--r--includes/specials/SpecialEmailuser.php13
-rw-r--r--includes/specials/SpecialExport.php17
-rw-r--r--includes/specials/SpecialFewestrevisions.php5
-rw-r--r--includes/specials/SpecialFileDuplicateSearch.php24
-rw-r--r--includes/specials/SpecialFilepath.php6
-rw-r--r--includes/specials/SpecialImport.php36
-rw-r--r--includes/specials/SpecialJavaScriptTest.php19
-rw-r--r--includes/specials/SpecialLinkSearch.php45
-rw-r--r--includes/specials/SpecialListfiles.php12
-rw-r--r--includes/specials/SpecialListgrouprights.php26
-rw-r--r--includes/specials/SpecialListredirects.php20
-rw-r--r--includes/specials/SpecialListusers.php44
-rw-r--r--includes/specials/SpecialLockdb.php4
-rw-r--r--includes/specials/SpecialLog.php4
-rw-r--r--includes/specials/SpecialLonelypages.php9
-rw-r--r--includes/specials/SpecialLongpages.php4
-rw-r--r--includes/specials/SpecialMIMEsearch.php19
-rw-r--r--includes/specials/SpecialMergeHistory.php53
-rw-r--r--includes/specials/SpecialMostcategories.php13
-rw-r--r--includes/specials/SpecialMostimages.php12
-rw-r--r--includes/specials/SpecialMostinterwikis.php13
-rw-r--r--includes/specials/SpecialMostlinked.php15
-rw-r--r--includes/specials/SpecialMostlinkedcategories.php12
-rw-r--r--includes/specials/SpecialMostlinkedtemplates.php5
-rw-r--r--includes/specials/SpecialMostrevisions.php4
-rw-r--r--includes/specials/SpecialMovepage.php65
-rw-r--r--includes/specials/SpecialNewimages.php23
-rw-r--r--includes/specials/SpecialNewpages.php57
-rw-r--r--includes/specials/SpecialPagesWithProp.php138
-rw-r--r--includes/specials/SpecialPasswordReset.php26
-rw-r--r--includes/specials/SpecialPopularpages.php10
-rw-r--r--includes/specials/SpecialPreferences.php6
-rw-r--r--includes/specials/SpecialPrefixindex.php30
-rw-r--r--includes/specials/SpecialProtectedpages.php46
-rw-r--r--includes/specials/SpecialProtectedtitles.php28
-rw-r--r--includes/specials/SpecialRandompage.php10
-rw-r--r--includes/specials/SpecialRandomredirect.php2
-rw-r--r--includes/specials/SpecialRecentchanges.php100
-rw-r--r--includes/specials/SpecialRecentchangeslinked.php46
-rw-r--r--includes/specials/SpecialRevisiondelete.php45
-rw-r--r--includes/specials/SpecialSearch.php131
-rw-r--r--includes/specials/SpecialShortpages.php4
-rw-r--r--includes/specials/SpecialSpecialpages.php17
-rw-r--r--includes/specials/SpecialStatistics.php63
-rw-r--r--includes/specials/SpecialTags.php4
-rw-r--r--includes/specials/SpecialUnblock.php29
-rw-r--r--includes/specials/SpecialUncategorizedcategories.php13
-rw-r--r--includes/specials/SpecialUncategorizedimages.php3
-rw-r--r--includes/specials/SpecialUncategorizedpages.php11
-rw-r--r--includes/specials/SpecialUndelete.php352
-rw-r--r--includes/specials/SpecialUnlockdb.php4
-rw-r--r--includes/specials/SpecialUnusedcategories.php8
-rw-r--r--includes/specials/SpecialUnusedimages.php3
-rw-r--r--includes/specials/SpecialUnusedtemplates.php18
-rw-r--r--includes/specials/SpecialUnwatchedpages.php17
-rw-r--r--includes/specials/SpecialUpload.php98
-rw-r--r--includes/specials/SpecialUploadStash.php34
-rw-r--r--includes/specials/SpecialUserlogin.php330
-rw-r--r--includes/specials/SpecialUserlogout.php9
-rw-r--r--includes/specials/SpecialUserrights.php106
-rw-r--r--includes/specials/SpecialVersion.php137
-rw-r--r--includes/specials/SpecialWantedcategories.php4
-rw-r--r--includes/specials/SpecialWantedfiles.php6
-rw-r--r--includes/specials/SpecialWantedpages.php11
-rw-r--r--includes/specials/SpecialWantedtemplates.php4
-rw-r--r--includes/specials/SpecialWatchlist.php116
-rw-r--r--includes/specials/SpecialWhatlinkshere.php22
-rw-r--r--includes/specials/SpecialWithoutinterwiki.php4
-rw-r--r--includes/templates/NoLocalSettings.php4
-rw-r--r--includes/templates/Usercreate.php58
-rw-r--r--includes/templates/Userlogin.php4
-rw-r--r--includes/tidy.conf5
-rw-r--r--includes/upload/UploadBase.php159
-rw-r--r--includes/upload/UploadFromChunks.php56
-rw-r--r--includes/upload/UploadFromFile.php12
-rw-r--r--includes/upload/UploadFromStash.php17
-rw-r--r--includes/upload/UploadFromUrl.php22
-rw-r--r--includes/upload/UploadStash.php74
-rw-r--r--includes/zhtable/Makefile336
-rw-r--r--includes/zhtable/Makefile.py391
-rw-r--r--includes/zhtable/README33
-rw-r--r--includes/zhtable/printutf8.c99
-rw-r--r--includes/zhtable/simp2trad.manual372
-rw-r--r--includes/zhtable/simp2trad_noconvert.manual139
-rw-r--r--includes/zhtable/simp2trad_supp_set.manual2
-rw-r--r--includes/zhtable/simpphrases.manual2239
-rw-r--r--includes/zhtable/simpphrases_exclude.manual21
-rw-r--r--includes/zhtable/toCN.manual275
-rw-r--r--includes/zhtable/toHK.manual2300
-rw-r--r--includes/zhtable/toSG.manual21
-rw-r--r--includes/zhtable/toSimp.manual165
-rw-r--r--includes/zhtable/toTW.manual411
-rw-r--r--includes/zhtable/toTrad.manual186
-rw-r--r--includes/zhtable/trad2simp.manual150
-rw-r--r--includes/zhtable/trad2simp_noconvert.manual5
-rw-r--r--includes/zhtable/trad2simp_supp_set.manual3
-rw-r--r--includes/zhtable/tradphrases.manual4310
-rw-r--r--includes/zhtable/tradphrases_exclude.manual330
606 files changed, 38571 insertions, 33188 deletions
diff --git a/includes/Action.php b/includes/Action.php
index 51922251..2e0c88ba 100644
--- a/includes/Action.php
+++ b/includes/Action.php
@@ -32,13 +32,13 @@
*
* Actions generally fall into two groups: the show-a-form-then-do-something-with-the-input
* format (protect, delete, move, etc), and the just-do-something format (watch, rollback,
- * patrol, etc). The FormAction and FormlessAction classes respresent these two groups.
+ * patrol, etc). The FormAction and FormlessAction classes represent these two groups.
*/
abstract class Action {
/**
* Page on which we're performing the action
- * @var Page $page
+ * @var WikiPage|Article|ImagePage|CategoryPage|Page $page
*/
protected $page;
@@ -61,7 +61,7 @@ abstract class Action {
* @param $overrides Array
* @return bool|null|string
*/
- private final static function getClass( $action, array $overrides ) {
+ final private static function getClass( $action, array $overrides ) {
global $wgActions;
$action = strtolower( $action );
@@ -88,7 +88,7 @@ abstract class Action {
* @return Action|bool|null false if the action is disabled, null
* if it is not recognised
*/
- public final static function factory( $action, Page $page, IContextSource $context = null ) {
+ final public static function factory( $action, Page $page, IContextSource $context = null ) {
$class = self::getClass( $action, $page->getActionOverrides() );
if ( $class ) {
$obj = new $class( $page, $context );
@@ -106,7 +106,7 @@ abstract class Action {
* @param $context IContextSource
* @return string: action name
*/
- public final static function getActionName( IContextSource $context ) {
+ final public static function getActionName( IContextSource $context ) {
global $wgActions;
$request = $context->getRequest();
@@ -147,10 +147,10 @@ abstract class Action {
/**
* Check if a given action is recognised, even if it's disabled
*
- * @param $name String: name of an action
+ * @param string $name name of an action
* @return Bool
*/
- public final static function exists( $name ) {
+ final public static function exists( $name ) {
return self::getClass( $name, array() ) !== null;
}
@@ -158,7 +158,7 @@ abstract class Action {
* Get the IContextSource in use here
* @return IContextSource
*/
- public final function getContext() {
+ final public function getContext() {
if ( $this->context instanceof IContextSource ) {
return $this->context;
}
@@ -170,7 +170,7 @@ abstract class Action {
*
* @return WebRequest
*/
- public final function getRequest() {
+ final public function getRequest() {
return $this->getContext()->getRequest();
}
@@ -179,7 +179,7 @@ abstract class Action {
*
* @return OutputPage
*/
- public final function getOutput() {
+ final public function getOutput() {
return $this->getContext()->getOutput();
}
@@ -188,7 +188,7 @@ abstract class Action {
*
* @return User
*/
- public final function getUser() {
+ final public function getUser() {
return $this->getContext()->getUser();
}
@@ -197,7 +197,7 @@ abstract class Action {
*
* @return Skin
*/
- public final function getSkin() {
+ final public function getSkin() {
return $this->getContext()->getSkin();
}
@@ -206,7 +206,7 @@ abstract class Action {
*
* @return Language
*/
- public final function getLanguage() {
+ final public function getLanguage() {
return $this->getContext()->getLanguage();
}
@@ -216,7 +216,7 @@ abstract class Action {
* @deprecated 1.19 Use getLanguage instead
* @return Language
*/
- public final function getLang() {
+ final public function getLang() {
wfDeprecated( __METHOD__, '1.19' );
return $this->getLanguage();
}
@@ -225,7 +225,7 @@ abstract class Action {
* Shortcut to get the Title object from the page
* @return Title
*/
- public final function getTitle() {
+ final public function getTitle() {
return $this->page->getTitle();
}
@@ -235,7 +235,7 @@ abstract class Action {
*
* @return Message object
*/
- public final function msg() {
+ final public function msg() {
$params = func_get_args();
return call_user_func_array( array( $this->getContext(), 'msg' ), $params );
}
@@ -255,7 +255,7 @@ abstract class Action {
* Return the name of the action this object responds to
* @return String lowercase
*/
- public abstract function getName();
+ abstract public function getName();
/**
* Get the permission required to perform this action. Often, but not always,
@@ -272,7 +272,7 @@ abstract class Action {
* must throw subclasses of ErrorPageError
*
* @param $user User: the user to check, or null to use the context user
- * @throws ErrorPageError
+ * @throws UserBlockedError|ReadOnlyError|PermissionsError
* @return bool True on success
*/
protected function checkCanExecute( User $user ) {
@@ -350,13 +350,13 @@ abstract class Action {
* $this->getOutput(), etc.
* @throws ErrorPageError
*/
- public abstract function show();
+ abstract public function show();
/**
* Execute the action in a silent fashion: do not display anything or release any errors.
* @return Bool whether execution was successful
*/
- public abstract function execute();
+ abstract public function execute();
}
/**
@@ -368,7 +368,7 @@ abstract class FormAction extends Action {
* Get an HTMLForm descriptor array
* @return Array
*/
- protected abstract function getFormFields();
+ abstract protected function getFormFields();
/**
* Add pre- or post-text to the form
@@ -388,7 +388,7 @@ abstract class FormAction extends Action {
protected function alterForm( HTMLForm $form ) {}
/**
- * Get the HTMLForm to control behaviour
+ * Get the HTMLForm to control behavior
* @return HTMLForm|null
*/
protected function getForm() {
@@ -406,7 +406,7 @@ abstract class FormAction extends Action {
$this->getRequest()->getQueryValues(),
array( 'action' => null, 'title' => null )
);
- $form->addHiddenField( 'redirectparams', wfArrayToCGI( $params ) );
+ $form->addHiddenField( 'redirectparams', wfArrayToCgi( $params ) );
$form->addPreText( $this->preText() );
$form->addPostText( $this->postText() );
@@ -425,21 +425,21 @@ abstract class FormAction extends Action {
* @param $data Array
* @return Bool|Array true for success, false for didn't-try, array of errors on failure
*/
- public abstract function onSubmit( $data );
+ abstract public function onSubmit( $data );
/**
* Do something exciting on successful processing of the form. This might be to show
* a confirmation message (watch, rollback, etc) or to redirect somewhere else (edit,
* protect, etc).
*/
- public abstract function onSuccess();
+ abstract public function onSuccess();
/**
* The basic pattern for actions is to display some sort of HTMLForm UI, maybe with
* some stuff underneath (history etc); to do some processing on submission of that
* form (delete, protect, etc) and to do something exciting on 'success', be that
* display something new or redirect to somewhere. Some actions have more exotic
- * behaviour, but that's what subclassing is for :D
+ * behavior, but that's what subclassing is for :D
*/
public function show() {
$this->setHeaders();
@@ -455,9 +455,10 @@ abstract class FormAction extends Action {
/**
* @see Action::execute()
- * @throws ErrorPageError
+ *
* @param $data array|null
* @param $captureErrors bool
+ * @throws ErrorPageError|Exception
* @return bool
*/
public function execute( array $data = null, $captureErrors = true ) {
@@ -507,7 +508,7 @@ abstract class FormlessAction extends Action {
* @return String|null will be added to the HTMLForm if present, or just added to the
* output if not. Return null to not add anything
*/
- public abstract function onView();
+ abstract public function onView();
/**
* We don't want an HTMLForm
@@ -544,8 +545,9 @@ abstract class FormlessAction extends Action {
/**
* Execute the action silently, not giving any output. Since these actions don't have
* forms, they probably won't have any data, but some (eg rollback) may do
- * @param $data Array values that would normally be in the GET request
- * @param $captureErrors Bool whether to catch exceptions and just return false
+ * @param array $data values that would normally be in the GET request
+ * @param bool $captureErrors whether to catch exceptions and just return false
+ * @throws ErrorPageError|Exception
* @return Bool whether execution was successful
*/
public function execute( array $data = null, $captureErrors = true ) {
diff --git a/includes/AjaxResponse.php b/includes/AjaxResponse.php
index 6bf94ccb..138f808a 100644
--- a/includes/AjaxResponse.php
+++ b/includes/AjaxResponse.php
@@ -172,7 +172,7 @@ class AjaxResponse {
# tell the client to use a cached copy, without a way to purge it.
if ( $wgUseSquid ) {
- # Expect explicite purge of the proxy cache, but require end user agents
+ # Expect explicit purge of the proxy cache, but require end user agents
# to revalidate against the proxy on each visit.
# Surrogate-Control controls our Squid, Cache-Control downstream caches
@@ -204,7 +204,7 @@ class AjaxResponse {
/**
* checkLastModified tells the client to use the client-cached response if
- * possible. If sucessful, the AjaxResponse is disabled so that
+ * possible. If successful, the AjaxResponse is disabled so that
* any future call to AjaxResponse::printText() have no effect.
*
* @param $timestamp string
diff --git a/includes/ArrayUtils.php b/includes/ArrayUtils.php
new file mode 100644
index 00000000..0b74f06a
--- /dev/null
+++ b/includes/ArrayUtils.php
@@ -0,0 +1,69 @@
+<?php
+
+class ArrayUtils {
+ /**
+ * Sort the given array in a pseudo-random order which depends only on the
+ * given key and each element value. This is typically used for load
+ * balancing between servers each with a local cache.
+ *
+ * Keys are preserved. The input array is modified in place.
+ *
+ * Note: Benchmarking on PHP 5.3 and 5.4 indicates that for small
+ * strings, md5() is only 10% slower than hash('joaat',...) etc.,
+ * since the function call overhead dominates. So there's not much
+ * justification for breaking compatibility with installations
+ * compiled with ./configure --disable-hash.
+ *
+ * @param $array The array to sort
+ * @param $key The string key
+ * @param $separator A separator used to delimit the array elements and the
+ * key. This can be chosen to provide backwards compatibility with
+ * various consistent hash implementations that existed before this
+ * function was introduced.
+ */
+ public static function consistentHashSort( &$array, $key, $separator = "\000" ) {
+ $hashes = array();
+ foreach ( $array as $elt ) {
+ $hashes[$elt] = md5( $elt . $separator . $key );
+ }
+ uasort( $array, function ( $a, $b ) use ( $hashes ) {
+ return strcmp( $hashes[$a], $hashes[$b] );
+ } );
+ }
+
+ /**
+ * Given an array of non-normalised probabilities, this function will select
+ * an element and return the appropriate key
+ *
+ * @param $weights array
+ *
+ * @return bool|int|string
+ */
+ public static function pickRandom( $weights ){
+ if ( !is_array( $weights ) || count( $weights ) == 0 ) {
+ return false;
+ }
+
+ $sum = array_sum( $weights );
+ if ( $sum == 0 ) {
+ # No loads on any of them
+ # In previous versions, this triggered an unweighted random selection,
+ # but this feature has been removed as of April 2006 to allow for strict
+ # separation of query groups.
+ return false;
+ }
+ $max = mt_getrandmax();
+ $rand = mt_rand( 0, $max ) / $max * $sum;
+
+ $sum = 0;
+ foreach ( $weights as $i => $w ) {
+ $sum += $w;
+ # Do not return keys if they have 0 weight.
+ # Note that the "all 0 weight" case is handed above
+ if ( $w > 0 && $sum >= $rand ) {
+ break;
+ }
+ }
+ return $i;
+ }
+}
diff --git a/includes/Article.php b/includes/Article.php
index 9ab4b6ba..9b4afe44 100644
--- a/includes/Article.php
+++ b/includes/Article.php
@@ -33,7 +33,7 @@
*
* @internal documentation reviewed 15 Mar 2010
*/
-class Article extends Page {
+class Article implements Page {
/**@{{
* @private
*/
@@ -57,10 +57,17 @@ class Article extends Page {
public $mParserOptions;
/**
- * Content of the revision we are working on
+ * Text of the revision we are working on
* @var string $mContent
*/
- var $mContent; // !<
+ var $mContent; // !< #BC cruft
+
+ /**
+ * Content of the revision we are working on
+ * @var Content
+ * @since 1.21
+ */
+ var $mContentObject; // !<
/**
* Is the content ($mContent) already loaded?
@@ -127,7 +134,7 @@ class Article extends Page {
/**
* Constructor from a page id
- * @param $id Int article ID to load
+ * @param int $id article ID to load
* @return Article|null
*/
public static function newFromID( $id ) {
@@ -231,9 +238,32 @@ class Article extends Page {
* This function has side effects! Do not use this function if you
* only want the real revision text if any.
*
+ * @deprecated in 1.21; use WikiPage::getContent() instead
+ *
* @return string Return the text of this revision
*/
public function getContent() {
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+ $content = $this->getContentObject();
+ return ContentHandler::getContentText( $content );
+ }
+
+ /**
+ * Returns a Content object representing the pages effective display content,
+ * not necessarily the revision's content!
+ *
+ * Note that getContent/loadContent do not follow redirects anymore.
+ * If you need to fetch redirectable content easily, try
+ * the shortcut in WikiPage::getRedirectTarget()
+ *
+ * This function has side effects! Do not use this function if you
+ * only want the real revision text if any.
+ *
+ * @return Content Return the content of this revision
+ *
+ * @since 1.21
+ */
+ protected function getContentObject() {
wfProfileIn( __METHOD__ );
if ( $this->mPage->getID() === 0 ) {
@@ -244,19 +274,19 @@ class Article extends Page {
if ( $text === false ) {
$text = '';
}
+
+ $content = ContentHandler::makeContent( $text, $this->getTitle() );
} else {
$message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
- $text = wfMessage( $message )->text();
+ $content = new MessageContent( $message, null, 'parsemag' );
}
- wfProfileOut( __METHOD__ );
-
- return $text;
} else {
- $this->fetchContent();
- wfProfileOut( __METHOD__ );
-
- return $this->mContent;
+ $this->fetchContentObject();
+ $content = $this->mContentObject;
}
+
+ wfProfileOut( __METHOD__ );
+ return $content;
}
/**
@@ -336,22 +366,60 @@ class Article extends Page {
* Get text of an article from database
* Does *NOT* follow redirects.
*
+ * @protected
+ * @note this is really internal functionality that should really NOT be used by other functions. For accessing
+ * article content, use the WikiPage class, especially WikiBase::getContent(). However, a lot of legacy code
+ * uses this method to retrieve page text from the database, so the function has to remain public for now.
+ *
* @return mixed string containing article contents, or false if null
+ * @deprecated in 1.21, use WikiPage::getContent() instead
*/
- function fetchContent() {
- if ( $this->mContentLoaded ) {
+ function fetchContent() { #BC cruft!
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+
+ if ( $this->mContentLoaded && $this->mContent ) {
return $this->mContent;
}
wfProfileIn( __METHOD__ );
+ $content = $this->fetchContentObject();
+
+ $this->mContent = ContentHandler::getContentText( $content ); #@todo: get rid of mContent everywhere!
+ ContentHandler::runLegacyHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) );
+
+ wfProfileOut( __METHOD__ );
+
+ return $this->mContent;
+ }
+
+ /**
+ * Get text content object
+ * Does *NOT* follow redirects.
+ * TODO: when is this null?
+ *
+ * @note code that wants to retrieve page content from the database should use WikiPage::getContent().
+ *
+ * @return Content|null|boolean false
+ *
+ * @since 1.21
+ */
+ protected function fetchContentObject() {
+ if ( $this->mContentLoaded ) {
+ return $this->mContentObject;
+ }
+
+ wfProfileIn( __METHOD__ );
+
$this->mContentLoaded = true;
+ $this->mContent = null;
$oldid = $this->getOldID();
# Pre-fill content with error message so that if something
# fails we'll have something telling us what we intended.
- $this->mContent = wfMessage( 'missing-revision', $oldid )->plain();
+ //XXX: this isn't page content but a UI message. horrible.
+ $this->mContentObject = new MessageContent( 'missing-revision', array( $oldid ), array() );
if ( $oldid ) {
# $this->mRevision might already be fetched by getOldIDFromRequest()
@@ -371,6 +439,7 @@ class Article extends Page {
}
$this->mRevision = $this->mPage->getRevision();
+
if ( !$this->mRevision ) {
wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n" );
wfProfileOut( __METHOD__ );
@@ -380,14 +449,14 @@ class Article extends Page {
// @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks.
// We should instead work with the Revision object when we need it...
- $this->mContent = $this->mRevision->getText( Revision::FOR_THIS_USER ); // Loads if user is allowed
+ $this->mContentObject = $this->mRevision->getContent( Revision::FOR_THIS_USER, $this->getContext()->getUser() ); // Loads if user is allowed
$this->mRevIdFetched = $this->mRevision->getId();
- wfRunHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) );
+ wfRunHooks( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) );
wfProfileOut( __METHOD__ );
- return $this->mContent;
+ return $this->mContentObject;
}
/**
@@ -420,7 +489,7 @@ class Article extends Page {
* @return Revision|null
*/
public function getRevisionFetched() {
- $this->fetchContent();
+ $this->fetchContentObject();
return $this->mRevision;
}
@@ -443,7 +512,7 @@ class Article extends Page {
* page of the given title.
*/
public function view() {
- global $wgParser, $wgUseFileCache, $wgUseETag, $wgDebugToolbar;
+ global $wgUseFileCache, $wgUseETag, $wgDebugToolbar;
wfProfileIn( __METHOD__ );
@@ -580,7 +649,7 @@ class Article extends Page {
break;
case 3:
# This will set $this->mRevision if needed
- $this->fetchContent();
+ $this->fetchContentObject();
# Are we looking at an old revision
if ( $oldid && $this->mRevision ) {
@@ -604,18 +673,25 @@ class Article extends Page {
wfDebug( __METHOD__ . ": showing CSS/JS source\n" );
$this->showCssOrJsPage();
$outputDone = true;
- } elseif( !wfRunHooks( 'ArticleViewCustom', array( $this->mContent, $this->getTitle(), $outputPage ) ) ) {
+ } elseif( !wfRunHooks( 'ArticleContentViewCustom',
+ array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) {
+
+ # Allow extensions do their own custom view for certain pages
+ $outputDone = true;
+ } elseif( !ContentHandler::runLegacyHooks( 'ArticleViewCustom',
+ array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) {
+
# Allow extensions do their own custom view for certain pages
$outputDone = true;
} else {
- $text = $this->getContent();
- $rt = Title::newFromRedirectArray( $text );
+ $content = $this->getContentObject();
+ $rt = $content ? $content->getRedirectChain() : null;
if ( $rt ) {
wfDebug( __METHOD__ . ": showing redirect=no page\n" );
# Viewing a redirect page (e.g. with parameter redirect=no)
$outputPage->addHTML( $this->viewRedirect( $rt ) );
# Parse just to get categories, displaytitle, etc.
- $this->mParserOutput = $wgParser->parse( $text, $this->getTitle(), $parserOptions );
+ $this->mParserOutput = $content->getParserOutput( $this->getTitle(), $oldid, $parserOptions, false );
$outputPage->addParserOutputNoText( $this->mParserOutput );
$outputDone = true;
}
@@ -625,8 +701,8 @@ class Article extends Page {
# Run the parse, protected by a pool counter
wfDebug( __METHOD__ . ": doing uncached parse\n" );
- $poolArticleView = new PoolWorkArticleView( $this, $parserOptions,
- $this->getRevIdFetched(), $useParserCache, $this->getContent() );
+ $poolArticleView = new PoolWorkArticleView( $this->getPage(), $parserOptions,
+ $this->getRevIdFetched(), $useParserCache, $this->getContentObject() );
if ( !$poolArticleView->execute() ) {
$error = $poolArticleView->getError();
@@ -690,6 +766,8 @@ class Article extends Page {
$this->showViewFooter();
$this->mPage->doViewUpdates( $user );
+ $outputPage->addModules( 'mediawiki.action.view.postEdit' );
+
wfProfileOut( __METHOD__ );
}
@@ -708,6 +786,8 @@ class Article extends Page {
/**
* Show a diff page according to current request variables. For use within
* Article::view() only, other callers should use the DifferenceEngine class.
+ *
+ * @todo: make protected
*/
public function showDiffPage() {
$request = $this->getContext()->getRequest();
@@ -719,7 +799,17 @@ class Article extends Page {
$unhide = $request->getInt( 'unhide' ) == 1;
$oldid = $this->getOldID();
- $de = new DifferenceEngine( $this->getContext(), $oldid, $diff, $rcid, $purge, $unhide );
+ $rev = $this->getRevisionFetched();
+
+ if ( !$rev ) {
+ $this->getContext()->getOutput()->setPageTitle( wfMessage( 'errorpagetitle' ) );
+ $this->getContext()->getOutput()->addWikiMsg( 'difference-missing-revision', $oldid, 1 );
+ return;
+ }
+
+ $contentHandler = $rev->getContentHandler();
+ $de = $contentHandler->createDifferenceEngine( $this->getContext(), $oldid, $diff, $rcid, $purge, $unhide );
+
// DifferenceEngine directly fetched the revision:
$this->mRevIdFetched = $de->mNewid;
$de->showDiffPage( $diffOnly );
@@ -736,29 +826,34 @@ class Article extends Page {
*
* This is hooked by SyntaxHighlight_GeSHi to do syntax highlighting of these
* page views.
+ *
+ * @param bool $showCacheHint whether to show a message telling the user to clear the browser cache (default: true).
*/
- protected function showCssOrJsPage() {
- $dir = $this->getContext()->getLanguage()->getDir();
- $lang = $this->getContext()->getLanguage()->getCode();
-
+ protected function showCssOrJsPage( $showCacheHint = true ) {
$outputPage = $this->getContext()->getOutput();
- $outputPage->wrapWikiMsg( "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
- 'clearyourcache' );
- // Give hooks a chance to customise the output
- if ( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->getTitle(), $outputPage ) ) ) {
- // Wrap the whole lot in a <pre> and don't parse
- $m = array();
- preg_match( '!\.(css|js)$!u', $this->getTitle()->getText(), $m );
- $outputPage->addHTML( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
- $outputPage->addHTML( htmlspecialchars( $this->mContent ) );
- $outputPage->addHTML( "\n</pre>\n" );
+ if ( $showCacheHint ) {
+ $dir = $this->getContext()->getLanguage()->getDir();
+ $lang = $this->getContext()->getLanguage()->getCode();
+
+ $outputPage->wrapWikiMsg( "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
+ 'clearyourcache' );
+ }
+
+ $this->fetchContentObject();
+
+ if ( $this->mContentObject ) {
+ // Give hooks a chance to customise the output
+ if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', array( $this->mContentObject, $this->getTitle(), $outputPage ) ) ) {
+ $po = $this->mContentObject->getParserOutput( $this->getTitle() );
+ $outputPage->addHTML( $po->getText() );
+ }
}
}
/**
* Get the robot policy to be used for the current view
- * @param $action String the action= GET parameter
+ * @param string $action the action= GET parameter
* @param $pOutput ParserOutput
* @return Array the policy that should be set
* TODO: actions other than 'view'
@@ -768,15 +863,21 @@ class Article extends Page {
$ns = $this->getTitle()->getNamespace();
- if ( $ns == NS_USER || $ns == NS_USER_TALK ) {
- # Don't index user and user talk pages for blocked users (bug 11443)
- if ( !$this->getTitle()->isSubpage() ) {
- if ( Block::newFromTarget( null, $this->getTitle()->getText() ) instanceof Block ) {
- return array(
- 'index' => 'noindex',
- 'follow' => 'nofollow'
- );
- }
+ # Don't index user and user talk pages for blocked users (bug 11443)
+ if ( ( $ns == NS_USER || $ns == NS_USER_TALK ) && !$this->getTitle()->isSubpage() ) {
+ $specificTarget = null;
+ $vagueTarget = null;
+ $titleText = $this->getTitle()->getText();
+ if ( IP::isValid( $titleText ) ) {
+ $vagueTarget = $titleText;
+ } else {
+ $specificTarget = $titleText;
+ }
+ if ( Block::newFromTarget( $specificTarget, $vagueTarget ) instanceof Block ) {
+ return array(
+ 'index' => 'noindex',
+ 'follow' => 'nofollow'
+ );
}
}
@@ -892,9 +993,7 @@ class Article extends Page {
}
// Add a <link rel="canonical"> tag
- $outputPage->addLink( array( 'rel' => 'canonical',
- 'href' => $this->getTitle()->getLocalURL() )
- );
+ $outputPage->setCanonicalUrl( $this->getTitle()->getLocalURL() );
// Tell the output object that the user arrived at this article through a redirect
$outputPage->setRedirectedFrom( $this->mRedirectedFrom );
@@ -948,6 +1047,8 @@ class Article extends Page {
* If patrol is possible, output a patrol UI box. This is called from the
* footer section of ordinary page views. If patrol is not possible or not
* desired, does nothing.
+ * Side effect: When the patrol link is build, this method will call
+ * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
*/
public function showPatrolFooter() {
$request = $this->getContext()->getRequest();
@@ -960,7 +1061,9 @@ class Article extends Page {
}
$token = $user->getEditToken( $rcid );
+
$outputPage->preventClickjacking();
+ $outputPage->addModules( 'mediawiki.page.patrol.ajax' );
$link = Linker::linkKnown(
$this->getTitle(),
@@ -987,6 +1090,7 @@ class Article extends Page {
public function showMissingArticle() {
global $wgSend404Code;
$outputPage = $this->getContext()->getOutput();
+ $validUserPage = false;
# Show info in user (talk) namespace. Does the user exist? Is he blocked?
if ( $this->getTitle()->getNamespace() == NS_USER || $this->getTitle()->getNamespace() == NS_USER_TALK ) {
@@ -1013,6 +1117,9 @@ class Article extends Page {
)
)
);
+ $validUserPage = true;
+ } else {
+ $validUserPage = true;
}
}
@@ -1020,13 +1127,13 @@ class Article extends Page {
# Show delete and move logs
LogEventsList::showLogExtract( $outputPage, array( 'delete', 'move' ), $this->getTitle(), '',
- array( 'lim' => 10,
+ array( 'lim' => 10,
'conds' => array( "log_action != 'revision'" ),
'showIfEmpty' => false,
'msgKey' => array( 'moveddeleted-notice' ) )
);
- if ( !$this->mPage->hasViewableContent() && $wgSend404Code ) {
+ if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
// If there's no backing content, send a 404 Not Found
// for better machine handling of broken links.
$this->getContext()->getRequest()->response()->header( "HTTP/1.1 404 Not Found" );
@@ -1104,7 +1211,7 @@ class Article extends Page {
* Revision as of \<date\>; view current revision
* \<- Previous version | Next Version -\>
*
- * @param $oldid int: revision ID of this article revision
+ * @param int $oldid revision ID of this article revision
*/
public function setOldSubtitle( $oldid = 0 ) {
if ( !wfRunHooks( 'DisplayOldSubtitle', array( &$this, &$oldid ) ) ) {
@@ -1166,7 +1273,7 @@ class Article extends Page {
'oldid' => $oldid
) + $extraParams
);
- $prev = $this->getTitle()->getPreviousRevisionID( $oldid ) ;
+ $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
$prevlink = $prev
? Linker::linkKnown(
$this->getTitle(),
@@ -1377,7 +1484,13 @@ class Article extends Page {
// Generate deletion reason
$hasHistory = false;
if ( !$reason ) {
- $reason = $this->generateReason( $hasHistory );
+ try {
+ $reason = $this->generateReason( $hasHistory );
+ } catch ( MWException $e ) {
+ # if a page is horribly broken, we still want to be able to delete it. so be lenient about errors here.
+ wfDebug( "Error while building auto delete summary: $e" );
+ $reason = '';
+ }
}
// If the page has a history, insert a warning
@@ -1406,7 +1519,7 @@ class Article extends Page {
/**
* Output deletion confirmation dialog
* @todo FIXME: Move to another file?
- * @param $reason String: prefilled reason
+ * @param string $reason prefilled reason
*/
public function confirmDelete( $reason ) {
wfDebug( "Article::confirmDelete\n" );
@@ -1614,9 +1727,11 @@ class Article extends Page {
*
* @param $oldid mixed integer Revision ID or null
* @param $user User The relevant user
- * @return ParserOutput or false if the given revsion ID is not found
+ * @return ParserOutput or false if the given revision ID is not found
*/
public function getParserOutput( $oldid = null, User $user = null ) {
+ //XXX: bypasses mParserOptions and thus setParserOptions()
+
if ( $user === null ) {
$parserOptions = $this->getParserOptions();
} else {
@@ -1627,6 +1742,21 @@ class Article extends Page {
}
/**
+ * Override the ParserOptions used to render the primary article wikitext.
+ *
+ * @param ParserOptions $options
+ * @throws MWException if the parser options where already initialized.
+ */
+ public function setParserOptions( ParserOptions $options ) {
+ if ( $this->mParserOptions ) {
+ throw new MWException( "can't change parser options after they have already been set" );
+ }
+
+ // clone, so if $options is modified later, it doesn't confuse the parser cache.
+ $this->mParserOptions = clone $options;
+ }
+
+ /**
* Get parser options suitable for rendering the primary article wikitext
* @return ParserOptions
*/
@@ -1757,15 +1887,16 @@ class Article extends Page {
*
* @deprecated in 1.18; call OutputPage::redirect() directly
* @param $noRedir Boolean: add redirect=no
- * @param $sectionAnchor String: section to redirect to, including "#"
- * @param $extraQuery String: extra query params
+ * @param string $sectionAnchor section to redirect to, including "#"
+ * @param string $extraQuery extra query params
*/
public function doRedirect( $noRedir = false, $sectionAnchor = '', $extraQuery = '' ) {
wfDeprecated( __METHOD__, '1.18' );
if ( $noRedir ) {
$query = 'redirect=no';
- if ( $extraQuery )
+ if ( $extraQuery ) {
$query .= "&$extraQuery";
+ }
} else {
$query = $extraQuery;
}
@@ -1777,7 +1908,7 @@ class Article extends Page {
* Use PHP's magic __get handler to handle accessing of
* raw WikiPage fields for backwards compatibility.
*
- * @param $fname String Field name
+ * @param string $fname Field name
*/
public function __get( $fname ) {
if ( property_exists( $this->mPage, $fname ) ) {
@@ -1791,7 +1922,7 @@ class Article extends Page {
* Use PHP's magic __set handler to handle setting of
* raw WikiPage fields for backwards compatibility.
*
- * @param $fname String Field name
+ * @param string $fname Field name
* @param $fvalue mixed New value
*/
public function __set( $fname, $fvalue ) {
@@ -1810,8 +1941,8 @@ class Article extends Page {
* Use PHP's magic __call handler to transform instance calls to
* WikiPage functions for backwards compatibility.
*
- * @param $fname String Name of called method
- * @param $args Array Arguments to the method
+ * @param string $fname Name of called method
+ * @param array $args Arguments to the method
* @return mixed
*/
public function __call( $fname, $args ) {
@@ -1844,7 +1975,13 @@ class Article extends Page {
* @return bool
*/
public function updateRestrictions( $limit = array(), $reason = '', &$cascade = 0, $expiry = array() ) {
- return $this->mPage->updateRestrictions( $limit, $reason, $cascade, $expiry );
+ return $this->mPage->doUpdateRestrictions(
+ $limit,
+ $expiry,
+ $cascade,
+ $reason,
+ $this->getContext()->getUser()
+ );
}
/**
@@ -1891,7 +2028,9 @@ class Article extends Page {
* @return mixed
*/
public function generateReason( &$hasHistory ) {
- return $this->mPage->getAutoDeleteReason( $hasHistory );
+ $title = $this->mPage->getTitle();
+ $handler = ContentHandler::getForTitle( $title );
+ return $handler->getAutoDeleteReason( $title, $hasHistory );
}
// ****** B/C functions for static methods ( __callStatic is PHP>=5.3 ) ****** //
@@ -1929,6 +2068,7 @@ class Article extends Page {
* @param $newtext
* @param $flags
* @return string
+ * @deprecated since 1.21, use ContentHandler::getAutosummary() instead
*/
public static function getAutosummary( $oldtext, $newtext, $flags ) {
return WikiPage::getAutosummary( $oldtext, $newtext, $flags );
diff --git a/includes/AuthPlugin.php b/includes/AuthPlugin.php
index 2e42439c..a4658176 100644
--- a/includes/AuthPlugin.php
+++ b/includes/AuthPlugin.php
@@ -46,7 +46,7 @@ class AuthPlugin {
* you might need to munge it (for instance, for lowercase initial
* letters).
*
- * @param $username String: username.
+ * @param string $username username.
* @return bool
*/
public function userExists( $username ) {
@@ -60,8 +60,8 @@ class AuthPlugin {
* you might need to munge it (for instance, for lowercase initial
* letters).
*
- * @param $username String: username.
- * @param $password String: user password.
+ * @param string $username username.
+ * @param string $password user password.
* @return bool
*/
public function authenticate( $username, $password ) {
@@ -73,7 +73,7 @@ class AuthPlugin {
* Modify options in the login template.
*
* @param $template UserLoginTemplate object.
- * @param $type String 'signup' or 'login'. Added in 1.16.
+ * @param string $type 'signup' or 'login'. Added in 1.16.
*/
public function modifyUITemplate( &$template, &$type ) {
# Override this!
@@ -83,7 +83,7 @@ class AuthPlugin {
/**
* Set the domain this plugin is supposed to use when authenticating.
*
- * @param $domain String: authentication domain.
+ * @param string $domain authentication domain.
*/
public function setDomain( $domain ) {
$this->domain = $domain;
@@ -105,7 +105,7 @@ class AuthPlugin {
/**
* Check to see if the specific domain is a valid domain.
*
- * @param $domain String: authentication domain.
+ * @param string $domain authentication domain.
* @return bool
*/
public function validDomain( $domain ) {
@@ -194,7 +194,7 @@ class AuthPlugin {
* Return true if successful.
*
* @param $user User object.
- * @param $password String: password.
+ * @param string $password password.
* @return bool
*/
public function setPassword( $user, $password ) {
@@ -251,7 +251,7 @@ class AuthPlugin {
* Check if a user should authenticate locally if the global authentication fails.
* If either this or strict() returns true, local authentication is not used.
*
- * @param $username String: username.
+ * @param string $username username.
* @return Boolean
*/
public function strictUserAuth( $username ) {
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index a8b22027..3555e2c3 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -33,12 +33,12 @@ $wgAutoloadLocalClasses = array(
'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
'AjaxResponse' => 'includes/AjaxResponse.php',
'AlphabeticPager' => 'includes/Pager.php',
+ 'ArrayUtils' => 'includes/ArrayUtils.php',
'Article' => 'includes/Article.php',
'AtomFeed' => 'includes/Feed.php',
'AuthPlugin' => 'includes/AuthPlugin.php',
'AuthPluginUser' => 'includes/AuthPlugin.php',
'Autopromote' => 'includes/Autopromote.php',
- 'BacklinkCache' => 'includes/BacklinkCache.php',
'BadTitleError' => 'includes/Exception.php',
'BaseTemplate' => 'includes/SkinTemplate.php',
'Block' => 'includes/Block.php',
@@ -71,8 +71,6 @@ $wgAutoloadLocalClasses = array(
'DeferredUpdates' => 'includes/DeferredUpdates.php',
'DeprecatedGlobal' => 'includes/DeprecatedGlobal.php',
'DerivativeRequest' => 'includes/WebRequest.php',
- 'DeviceDetection' => 'includes/mobile/DeviceDetection.php',
- 'DeviceProperties' => 'includes/mobile/DeviceDetection.php',
'DiffHistoryBlob' => 'includes/HistoryBlob.php',
'DoubleReplacer' => 'includes/StringUtils.php',
'DummyLinker' => 'includes/Linker.php',
@@ -93,9 +91,11 @@ $wgAutoloadLocalClasses = array(
'ErrorPageError' => 'includes/Exception.php',
'ExplodeIterator' => 'includes/StringUtils.php',
'ExternalEdit' => 'includes/ExternalEdit.php',
- 'ExternalStore' => 'includes/ExternalStore.php',
- 'ExternalStoreDB' => 'includes/ExternalStoreDB.php',
- 'ExternalStoreHttp' => 'includes/ExternalStoreHttp.php',
+ 'ExternalStore' => 'includes/externalstore/ExternalStore.php',
+ 'ExternalStoreDB' => 'includes/externalstore/ExternalStoreDB.php',
+ 'ExternalStoreHttp' => 'includes/externalstore/ExternalStoreHttp.php',
+ 'ExternalStoreMedium' => 'includes/externalstore/ExternalStoreMedium.php',
+ 'ExternalStoreMwstore' => 'includes/externalstore/ExternalStoreMwstore.php',
'ExternalUser' => 'includes/ExternalUser.php',
'FakeTitle' => 'includes/FakeTitle.php',
'Fallback' => 'includes/Fallback.php',
@@ -119,6 +119,7 @@ $wgAutoloadLocalClasses = array(
'Html' => 'includes/Html.php',
'HTMLApiField' => 'includes/HTMLForm.php',
'HTMLCheckField' => 'includes/HTMLForm.php',
+ 'HTMLCheckMatrix' => 'includes/HTMLForm.php',
'HTMLEditTools' => 'includes/HTMLForm.php',
'HTMLFloatField' => 'includes/HTMLForm.php',
'HTMLForm' => 'includes/HTMLForm.php',
@@ -136,11 +137,8 @@ $wgAutoloadLocalClasses = array(
'HTMLTextField' => 'includes/HTMLForm.php',
'Http' => 'includes/HttpFunctions.php',
'HttpError' => 'includes/Exception.php',
- 'HttpRequest' => 'includes/HttpFunctions.old.php',
'ICacheHelper' => 'includes/CacheHelper.php',
'IcuCollation' => 'includes/Collation.php',
- 'IDeviceProperties' => 'includes/mobile/DeviceDetection.php',
- 'IDeviceDetector' => 'includes/mobile/DeviceDetection.php',
'IdentityCollation' => 'includes/Collation.php',
'ImageGallery' => 'includes/ImageGallery.php',
'ImageHistoryList' => 'includes/ImagePage.php',
@@ -153,10 +151,11 @@ $wgAutoloadLocalClasses = array(
'IndexPager' => 'includes/Pager.php',
'Interwiki' => 'includes/interwiki/Interwiki.php',
'IP' => 'includes/IP.php',
- 'LCStore_Accel' => 'includes/LocalisationCache.php',
- 'LCStore_CDB' => 'includes/LocalisationCache.php',
- 'LCStore_DB' => 'includes/LocalisationCache.php',
- 'LCStore_Null' => 'includes/LocalisationCache.php',
+ 'LCStore' => 'includes/cache/LocalisationCache.php',
+ 'LCStore_Accel' => 'includes/cache/LocalisationCache.php',
+ 'LCStore_CDB' => 'includes/cache/LocalisationCache.php',
+ 'LCStore_DB' => 'includes/cache/LocalisationCache.php',
+ 'LCStore_Null' => 'includes/cache/LocalisationCache.php',
'LegacyTemplate' => 'includes/SkinLegacy.php',
'License' => 'includes/Licenses.php',
'Licenses' => 'includes/Licenses.php',
@@ -164,11 +163,12 @@ $wgAutoloadLocalClasses = array(
'LinkFilter' => 'includes/LinkFilter.php',
'LinksUpdate' => 'includes/LinksUpdate.php',
'LinksDeletionUpdate' => 'includes/LinksUpdate.php',
- 'LocalisationCache' => 'includes/LocalisationCache.php',
- 'LocalisationCache_BulkLoad' => 'includes/LocalisationCache.php',
+ 'LocalisationCache' => 'includes/cache/LocalisationCache.php',
+ 'LocalisationCache_BulkLoad' => 'includes/cache/LocalisationCache.php',
'MagicWord' => 'includes/MagicWord.php',
'MagicWordArray' => 'includes/MagicWord.php',
'MailAddress' => 'includes/UserMailer.php',
+ 'MappedIterator' => 'includes/MappedIterator.php',
'MediaWiki' => 'includes/Wiki.php',
'MediaWiki_I18N' => 'includes/SkinTemplate.php',
'Message' => 'includes/Message.php',
@@ -183,7 +183,7 @@ $wgAutoloadLocalClasses = array(
'MWNamespace' => 'includes/Namespace.php',
'OldChangesList' => 'includes/ChangesList.php',
'OutputPage' => 'includes/OutputPage.php',
- 'Page' => 'includes/WikiPage.php',
+ 'Page' => 'includes/WikiPage.php',
'PageQueryPage' => 'includes/PageQueryPage.php',
'Pager' => 'includes/Pager.php',
'PasswordError' => 'includes/User.php',
@@ -201,10 +201,12 @@ $wgAutoloadLocalClasses = array(
'ProtectionForm' => 'includes/ProtectionForm.php',
'QueryPage' => 'includes/QueryPage.php',
'QuickTemplate' => 'includes/SkinTemplate.php',
+ 'RawMessage' => 'includes/Message.php',
'RCCacheEntry' => 'includes/ChangesList.php',
'RdfMetaData' => 'includes/Metadata.php',
'ReadOnlyError' => 'includes/Exception.php',
'RecentChange' => 'includes/RecentChange.php',
+ 'RedirectSpecialArticle' => 'includes/SpecialPage.php',
'RedirectSpecialPage' => 'includes/SpecialPage.php',
'RegexlikeReplacer' => 'includes/StringUtils.php',
'ReplacementArray' => 'includes/StringUtils.php',
@@ -219,6 +221,7 @@ $wgAutoloadLocalClasses = array(
'Sanitizer' => 'includes/Sanitizer.php',
'DataUpdate' => 'includes/DataUpdate.php',
'SqlDataUpdate' => 'includes/SqlDataUpdate.php',
+ 'ScopedCallback' => 'includes/ScopedCallback.php',
'ScopedPHPTimeout' => 'includes/ScopedPHPTimeout.php',
'SiteConfiguration' => 'includes/SiteConfiguration.php',
'SiteStats' => 'includes/SiteStats.php',
@@ -247,10 +250,12 @@ $wgAutoloadLocalClasses = array(
'StubUserLang' => 'includes/StubObject.php',
'TablePager' => 'includes/Pager.php',
'MWTimestamp' => 'includes/Timestamp.php',
+ 'TimestampException' => 'includes/Timestamp.php',
'Title' => 'includes/Title.php',
'TitleArray' => 'includes/TitleArray.php',
'TitleArrayFromResult' => 'includes/TitleArray.php',
'ThrottledError' => 'includes/Exception.php',
+ 'UIDGenerator' => 'includes/UIDGenerator.php',
'UnlistedSpecialPage' => 'includes/SpecialPage.php',
'UploadSourceAdapter' => 'includes/Import.php',
'UppercaseCollation' => 'includes/Collation.php',
@@ -272,9 +277,9 @@ $wgAutoloadLocalClasses = array(
'WikiError' => 'includes/WikiError.php',
'WikiErrorMsg' => 'includes/WikiError.php',
'WikiExporter' => 'includes/Export.php',
- 'WikiFilePage' => 'includes/WikiFilePage.php',
+ 'WikiFilePage' => 'includes/WikiFilePage.php',
'WikiImporter' => 'includes/Import.php',
- 'WikiPage' => 'includes/WikiPage.php',
+ 'WikiPage' => 'includes/WikiPage.php',
'WikiRevision' => 'includes/Import.php',
'WikiMap' => 'includes/WikiMap.php',
'WikiReference' => 'includes/WikiMap.php',
@@ -289,6 +294,21 @@ $wgAutoloadLocalClasses = array(
'ZipDirectoryReader' => 'includes/ZipDirectoryReader.php',
'ZipDirectoryReaderError' => 'includes/ZipDirectoryReader.php',
+ # content handler
+ 'AbstractContent' => 'includes/content/AbstractContent.php',
+ 'ContentHandler' => 'includes/content/ContentHandler.php',
+ 'Content' => 'includes/content/Content.php',
+ 'CssContentHandler' => 'includes/content/CssContentHandler.php',
+ 'CssContent' => 'includes/content/CssContent.php',
+ 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+ 'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
+ 'MessageContent' => 'includes/content/MessageContent.php',
+ 'MWContentSerializationException' => 'includes/content/ContentHandler.php',
+ 'TextContentHandler' => 'includes/content/TextContentHandler.php',
+ 'TextContent' => 'includes/content/TextContent.php',
+ 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
+ 'WikitextContent' => 'includes/content/WikitextContent.php',
+
# includes/actions
'CachedAction' => 'includes/actions/CachedAction.php',
'CreditsAction' => 'includes/actions/CreditsAction.php',
@@ -318,6 +338,7 @@ $wgAutoloadLocalClasses = array(
'ApiBase' => 'includes/api/ApiBase.php',
'ApiBlock' => 'includes/api/ApiBlock.php',
'ApiComparePages' => 'includes/api/ApiComparePages.php',
+ 'ApiCreateAccount' => 'includes/api/ApiCreateAccount.php',
'ApiDelete' => 'includes/api/ApiDelete.php',
'ApiDisabled' => 'includes/api/ApiDisabled.php',
'ApiEditPage' => 'includes/api/ApiEditPage.php',
@@ -331,6 +352,7 @@ $wgAutoloadLocalClasses = array(
'ApiFormatDump' => 'includes/api/ApiFormatDump.php',
'ApiFormatFeedWrapper' => 'includes/api/ApiFormatBase.php',
'ApiFormatJson' => 'includes/api/ApiFormatJson.php',
+ 'ApiFormatNone' => 'includes/api/ApiFormatNone.php',
'ApiFormatPhp' => 'includes/api/ApiFormatPhp.php',
'ApiFormatRaw' => 'includes/api/ApiFormatRaw.php',
'ApiFormatTxt' => 'includes/api/ApiFormatTxt.php',
@@ -339,11 +361,13 @@ $wgAutoloadLocalClasses = array(
'ApiFormatXmlRsd' => 'includes/api/ApiRsd.php',
'ApiFormatYaml' => 'includes/api/ApiFormatYaml.php',
'ApiHelp' => 'includes/api/ApiHelp.php',
+ 'ApiImageRotate' => 'includes/api/ApiImageRotate.php',
'ApiImport' => 'includes/api/ApiImport.php',
'ApiImportReporter' => 'includes/api/ApiImport.php',
'ApiLogin' => 'includes/api/ApiLogin.php',
'ApiLogout' => 'includes/api/ApiLogout.php',
'ApiMain' => 'includes/api/ApiMain.php',
+ 'ApiModuleManager' => 'includes/api/ApiModuleManager.php',
'ApiMove' => 'includes/api/ApiMove.php',
'ApiOpenSearch' => 'includes/api/ApiOpenSearch.php',
'ApiOptions' => 'includes/api/ApiOptions.php',
@@ -383,7 +407,10 @@ $wgAutoloadLocalClasses = array(
'ApiQueryLangLinks' => 'includes/api/ApiQueryLangLinks.php',
'ApiQueryLinks' => 'includes/api/ApiQueryLinks.php',
'ApiQueryLogEvents' => 'includes/api/ApiQueryLogEvents.php',
+ 'ApiQueryORM' => 'includes/api/ApiQueryORM.php',
'ApiQueryPageProps' => 'includes/api/ApiQueryPageProps.php',
+ 'ApiQueryPagesWithProp' => 'includes/api/ApiQueryPagesWithProp.php',
+ 'ApiQueryPagePropNames' => 'includes/api/ApiQueryPagePropNames.php',
'ApiQueryProtectedTitles' => 'includes/api/ApiQueryProtectedTitles.php',
'ApiQueryQueryPage' => 'includes/api/ApiQueryQueryPage.php',
'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
@@ -410,6 +437,7 @@ $wgAutoloadLocalClasses = array(
'UsageException' => 'includes/api/ApiMain.php',
# includes/cache
+ 'BacklinkCache' => 'includes/cache/BacklinkCache.php',
'CacheDependency' => 'includes/cache/CacheDependency.php',
'ConstantDependency' => 'includes/cache/CacheDependency.php',
'DependencyWrapper' => 'includes/cache/CacheDependency.php',
@@ -418,7 +446,6 @@ $wgAutoloadLocalClasses = array(
'GenderCache' => 'includes/cache/GenderCache.php',
'GlobalDependency' => 'includes/cache/CacheDependency.php',
'HTMLCacheUpdate' => 'includes/cache/HTMLCacheUpdate.php',
- 'HTMLCacheUpdateJob' => 'includes/cache/HTMLCacheUpdate.php',
'HTMLFileCache' => 'includes/cache/HTMLFileCache.php',
'LinkBatch' => 'includes/cache/LinkBatch.php',
'LinkCache' => 'includes/cache/LinkCache.php',
@@ -430,6 +457,10 @@ $wgAutoloadLocalClasses = array(
'TitleDependency' => 'includes/cache/CacheDependency.php',
'TitleListDependency' => 'includes/cache/CacheDependency.php',
+ # includes/clientpool
+ 'RedisConnectionPool' => 'includes/clientpool/RedisConnectionPool.php',
+ 'RedisConnRef' => 'includes/clientpool/RedisConnectionPool.php',
+
# includes/context
'ContextSource' => 'includes/context/ContextSource.php',
'DerivativeContext' => 'includes/context/DerivativeContext.php',
@@ -438,14 +469,13 @@ $wgAutoloadLocalClasses = array(
# includes/dao
'IDBAccessObject' => 'includes/dao/IDBAccessObject.php',
+ 'DBAccessBase' => 'includes/dao/DBAccessBase.php',
# includes/db
'Blob' => 'includes/db/DatabaseUtility.php',
'ChronologyProtector' => 'includes/db/LBFactory.php',
'CloneDatabase' => 'includes/db/CloneDatabase.php',
- 'Database' => 'includes/db/DatabaseMysql.php',
'DatabaseBase' => 'includes/db/Database.php',
- 'DatabaseIbm_db2' => 'includes/db/DatabaseIbm_db2.php',
'DatabaseMssql' => 'includes/db/DatabaseMssql.php',
'DatabaseMysql' => 'includes/db/DatabaseMysql.php',
'DatabaseOracle' => 'includes/db/DatabaseOracle.php',
@@ -464,10 +494,6 @@ $wgAutoloadLocalClasses = array(
'DBUnexpectedError' => 'includes/db/DatabaseError.php',
'FakeResultWrapper' => 'includes/db/DatabaseUtility.php',
'Field' => 'includes/db/DatabaseUtility.php',
- 'IBM_DB2Blob' => 'includes/db/DatabaseIbm_db2.php',
- 'IBM_DB2Field' => 'includes/db/DatabaseIbm_db2.php',
- 'IBM_DB2Helper' => 'includes/db/DatabaseIbm_db2.php',
- 'IBM_DB2Result' => 'includes/db/DatabaseIbm_db2.php',
'LBFactory' => 'includes/db/LBFactory.php',
'LBFactory_Fake' => 'includes/db/LBFactory.php',
'LBFactory_Multi' => 'includes/db/LBFactory_Multi.php',
@@ -548,13 +574,14 @@ $wgAutoloadLocalClasses = array(
'NullFileJournal' => 'includes/filebackend/filejournal/FileJournal.php',
'LockManagerGroup' => 'includes/filebackend/lockmanager/LockManagerGroup.php',
'LockManager' => 'includes/filebackend/lockmanager/LockManager.php',
- 'ScopedLock' => 'includes/filebackend/lockmanager/LockManager.php',
+ 'ScopedLock' => 'includes/filebackend/lockmanager/ScopedLock.php',
'FSLockManager' => 'includes/filebackend/lockmanager/FSLockManager.php',
'DBLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php',
'LSLockManager' => 'includes/filebackend/lockmanager/LSLockManager.php',
'MemcLockManager' => 'includes/filebackend/lockmanager/MemcLockManager.php',
- 'QuorumLockManager' => 'includes/filebackend/lockmanager/LockManager.php',
- 'MySqlLockManager'=> 'includes/filebackend/lockmanager/DBLockManager.php',
+ 'QuorumLockManager' => 'includes/filebackend/lockmanager/QuorumLockManager.php',
+ 'MySqlLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php',
+ 'PostgreSqlLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php',
'NullLockManager' => 'includes/filebackend/lockmanager/LockManager.php',
'FileOp' => 'includes/filebackend/FileOp.php',
'FileOpBatch' => 'includes/filebackend/FileOpBatch.php',
@@ -562,8 +589,8 @@ $wgAutoloadLocalClasses = array(
'CopyFileOp' => 'includes/filebackend/FileOp.php',
'MoveFileOp' => 'includes/filebackend/FileOp.php',
'DeleteFileOp' => 'includes/filebackend/FileOp.php',
- 'ConcatenateFileOp' => 'includes/filebackend/FileOp.php',
'CreateFileOp' => 'includes/filebackend/FileOp.php',
+ 'DescribeFileOp' => 'includes/filebackend/FileOp.php',
'NullFileOp' => 'includes/filebackend/FileOp.php',
# includes/filerepo
@@ -594,11 +621,8 @@ $wgAutoloadLocalClasses = array(
'CliInstaller' => 'includes/installer/CliInstaller.php',
'DatabaseInstaller' => 'includes/installer/DatabaseInstaller.php',
'DatabaseUpdater' => 'includes/installer/DatabaseUpdater.php',
- 'Ibm_db2Installer' => 'includes/installer/Ibm_db2Installer.php',
- 'Ibm_db2Updater' => 'includes/installer/Ibm_db2Updater.php',
'InstallDocFormatter' => 'includes/installer/InstallDocFormatter.php',
'Installer' => 'includes/installer/Installer.php',
- 'LBFactory_InstallerFake' => 'includes/installer/Installer.php',
'LocalSettingsGenerator' => 'includes/installer/LocalSettingsGenerator.php',
'MysqlInstaller' => 'includes/installer/MysqlInstaller.php',
'MysqlUpdater' => 'includes/installer/MysqlUpdater.php',
@@ -631,13 +655,26 @@ $wgAutoloadLocalClasses = array(
'WebInstallerPage' => 'includes/installer/WebInstallerPage.php',
# includes/job
- 'DoubleRedirectJob' => 'includes/job/DoubleRedirectJob.php',
- 'EmaillingJob' => 'includes/job/EmaillingJob.php',
- 'EnotifNotifyJob' => 'includes/job/EnotifNotifyJob.php',
'Job' => 'includes/job/Job.php',
- 'RefreshLinksJob' => 'includes/job/RefreshLinksJob.php',
- 'RefreshLinksJob2' => 'includes/job/RefreshLinksJob.php',
- 'UploadFromUrlJob' => 'includes/job/UploadFromUrlJob.php',
+ 'JobQueue' => 'includes/job/JobQueue.php',
+ 'JobQueueAggregator' => 'includes/job/JobQueueAggregator.php',
+ 'JobQueueAggregatorMemc' => 'includes/job/JobQueueAggregatorMemc.php',
+ 'JobQueueAggregatorRedis' => 'includes/job/JobQueueAggregatorRedis.php',
+ 'JobQueueDB' => 'includes/job/JobQueueDB.php',
+ 'JobQueueGroup' => 'includes/job/JobQueueGroup.php',
+
+ # includes/job/jobs
+ 'DoubleRedirectJob' => 'includes/job/jobs/DoubleRedirectJob.php',
+ 'DuplicateJob' => 'includes/job/jobs/DuplicateJob.php',
+ 'EmaillingJob' => 'includes/job/jobs/EmaillingJob.php',
+ 'EnotifNotifyJob' => 'includes/job/jobs/EnotifNotifyJob.php',
+ 'HTMLCacheUpdateJob' => 'includes/job/jobs/HTMLCacheUpdateJob.php',
+ 'NullJob' => 'includes/job/jobs/NullJob.php',
+ 'RefreshLinksJob' => 'includes/job/jobs/RefreshLinksJob.php',
+ 'RefreshLinksJob2' => 'includes/job/jobs/RefreshLinksJob.php',
+ 'UploadFromUrlJob' => 'includes/job/jobs/UploadFromUrlJob.php',
+ 'AssembleUploadChunksJob' => 'includes/job/jobs/AssembleUploadChunksJob.php',
+ 'PublishStashedFileJob' => 'includes/job/jobs/PublishStashedFileJob.php',
# includes/json
'FormatJson' => 'includes/json/FormatJson.php',
@@ -676,6 +713,7 @@ $wgAutoloadLocalClasses = array(
'PatrolLog' => 'includes/logging/PatrolLog.php',
'PatrolLogFormatter' => 'includes/logging/LogFormatter.php',
'RCDatabaseLogEntry' => 'includes/logging/LogEntry.php',
+ 'RightsLogFormatter' => 'includes/logging/LogFormatter.php',
# includes/media
'BitmapHandler' => 'includes/media/Bitmap.php',
@@ -747,35 +785,24 @@ $wgAutoloadLocalClasses = array(
'MWTidyWrapper' => 'includes/parser/Tidy.php',
'PPCustomFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
'PPCustomFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPCustomFrame_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPDAccum_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDAccum_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPDPart' => 'includes/parser/Preprocessor_DOM.php',
'PPDPart_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDPart_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPDStack' => 'includes/parser/Preprocessor_DOM.php',
'PPDStackElement' => 'includes/parser/Preprocessor_DOM.php',
'PPDStackElement_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDStackElement_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPDStack_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDStack_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPFrame' => 'includes/parser/Preprocessor.php',
'PPFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
'PPFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPFrame_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPNode' => 'includes/parser/Preprocessor.php',
'PPNode_DOM' => 'includes/parser/Preprocessor_DOM.php',
'PPNode_Hash_Array' => 'includes/parser/Preprocessor_Hash.php',
'PPNode_Hash_Attr' => 'includes/parser/Preprocessor_Hash.php',
'PPNode_Hash_Text' => 'includes/parser/Preprocessor_Hash.php',
'PPNode_Hash_Tree' => 'includes/parser/Preprocessor_Hash.php',
- 'PPNode_HipHop_Array' => 'includes/parser/Preprocessor_HipHop.hphp',
- 'PPNode_HipHop_Attr' => 'includes/parser/Preprocessor_HipHop.hphp',
- 'PPNode_HipHop_Text' => 'includes/parser/Preprocessor_HipHop.hphp',
- 'PPNode_HipHop_Tree' => 'includes/parser/Preprocessor_HipHop.hphp',
'PPTemplateFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
'PPTemplateFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPTemplateFrame_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'Parser' => 'includes/parser/Parser.php',
'ParserCache' => 'includes/parser/ParserCache.php',
'ParserOptions' => 'includes/parser/ParserOptions.php',
@@ -785,7 +812,6 @@ $wgAutoloadLocalClasses = array(
'Preprocessor' => 'includes/parser/Preprocessor.php',
'Preprocessor_DOM' => 'includes/parser/Preprocessor_DOM.php',
'Preprocessor_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'Preprocessor_HipHop' => 'includes/parser/Preprocessor_HipHop.hphp',
'StripState' => 'includes/parser/StripState.php',
# includes/profiler
@@ -827,7 +853,6 @@ $wgAutoloadLocalClasses = array(
'RevDel_LogList' => 'includes/revisiondelete/RevisionDelete.php',
'RevDel_RevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
'RevDel_RevisionList' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevisionDelete' => 'includes/revisiondelete/RevisionDelete.php',
'RevisionDeleter' => 'includes/revisiondelete/RevisionDeleter.php',
'RevisionDeleteUser' => 'includes/revisiondelete/RevisionDeleteUser.php',
@@ -839,7 +864,6 @@ $wgAutoloadLocalClasses = array(
'SearchEngine' => 'includes/search/SearchEngine.php',
'SearchEngineDummy' => 'includes/search/SearchEngine.php',
'SearchHighlighter' => 'includes/search/SearchEngine.php',
- 'SearchIBM_DB2' => 'includes/search/SearchIBM_DB2.php',
'SearchMssql' => 'includes/search/SearchMssql.php',
'SearchMySQL' => 'includes/search/SearchMySQL.php',
'SearchNearMatchResultSet' => 'includes/search/SearchEngine.php',
@@ -854,6 +878,16 @@ $wgAutoloadLocalClasses = array(
'SqliteSearchResultSet' => 'includes/search/SearchSqlite.php',
'SqlSearchResultSet' => 'includes/search/SearchEngine.php',
+ # includes/site
+ 'MediaWikiSite' => 'includes/site/MediaWikiSite.php',
+ 'Site' => 'includes/site/Site.php',
+ 'SiteObject' => 'includes/site/Site.php',
+ 'SiteArray' => 'includes/site/SiteList.php',
+ 'SiteList' => 'includes/site/SiteList.php',
+ 'SiteSQLStore' => 'includes/site/SiteSQLStore.php',
+ 'Sites' => 'includes/site/SiteSQLStore.php',
+ 'SiteStore' => 'includes/site/SiteStore.php',
+
# includes/specials
'ActiveUsersPager' => 'includes/specials/SpecialActiveusers.php',
'AllmessagesTablePager' => 'includes/specials/SpecialAllmessages.php',
@@ -862,8 +896,6 @@ $wgAutoloadLocalClasses = array(
'BrokenRedirectsPage' => 'includes/specials/SpecialBrokenRedirects.php',
'CategoryPager' => 'includes/specials/SpecialCategories.php',
'ContribsPager' => 'includes/specials/SpecialContributions.php',
- 'DBLockForm' => 'includes/specials/SpecialLockdb.php',
- 'DBUnlockForm' => 'includes/specials/SpecialUnlockdb.php',
'DeadendPagesPage' => 'includes/specials/SpecialDeadendpages.php',
'DeletedContribsPager' => 'includes/specials/SpecialDeletedContributions.php',
'DeletedContributionsPage' => 'includes/specials/SpecialDeletedContributions.php',
@@ -928,10 +960,10 @@ $wgAutoloadLocalClasses = array(
'SpecialLockdb' => 'includes/specials/SpecialLockdb.php',
'SpecialLog' => 'includes/specials/SpecialLog.php',
'SpecialMergeHistory' => 'includes/specials/SpecialMergeHistory.php',
- 'SpecialMostlinkedtemplates' => 'includes/specials/SpecialMostlinkedtemplates.php',
'SpecialNewFiles' => 'includes/specials/SpecialNewimages.php',
'SpecialNewpages' => 'includes/specials/SpecialNewpages.php',
'SpecialPasswordReset' => 'includes/specials/SpecialPasswordReset.php',
+ 'SpecialPagesWithProp' => 'includes/specials/SpecialPagesWithProp.php',
'SpecialPermanentLink' => 'includes/SpecialPage.php',
'SpecialPreferences' => 'includes/specials/SpecialPreferences.php',
'SpecialPrefixindex' => 'includes/specials/SpecialPrefixindex.php',
@@ -989,7 +1021,6 @@ $wgAutoloadLocalClasses = array(
'UploadFromUrl' => 'includes/upload/UploadFromUrl.php',
'UploadStash' => 'includes/upload/UploadStash.php',
'UploadStashBadPathException' => 'includes/upload/UploadStash.php',
- 'UploadStashBadVersionException' => 'includes/upload/UploadStash.php',
'UploadStashFile' => 'includes/upload/UploadStash.php',
'UploadStashFileException' => 'includes/upload/UploadStash.php',
'UploadStashFileNotFoundException' => 'includes/upload/UploadStash.php',
@@ -1004,20 +1035,29 @@ $wgAutoloadLocalClasses = array(
'FakeConverter' => 'languages/Language.php',
'Language' => 'languages/Language.php',
'LanguageConverter' => 'languages/LanguageConverter.php',
+ 'CLDRPluralRuleConverter' => 'languages/utils/CLDRPluralRuleEvaluator.php',
+ 'CLDRPluralRuleConverter_Expression' => 'languages/utils/CLDRPluralRuleEvaluator.php',
+ 'CLDRPluralRuleConverter_Fragment' => 'languages/utils/CLDRPluralRuleEvaluator.php',
+ 'CLDRPluralRuleConverter_Operator' => 'languages/utils/CLDRPluralRuleEvaluator.php',
'CLDRPluralRuleEvaluator' => 'languages/utils/CLDRPluralRuleEvaluator.php',
+ 'CLDRPluralRuleEvaluator_Range' => 'languages/utils/CLDRPluralRuleEvaluator.php',
'CLDRPluralRuleError' => 'languages/utils/CLDRPluralRuleEvaluator.php',
# maintenance
+ 'BackupDumper' => 'maintenance/backup.inc',
'ConvertLinks' => 'maintenance/convertLinks.php',
'DeleteArchivedFilesImplementation' => 'maintenance/deleteArchivedFiles.inc',
'DeleteArchivedRevisionsImplementation' => 'maintenance/deleteArchivedRevisions.inc',
'DeleteDefaultMessages' => 'maintenance/deleteDefaultMessages.php',
+ 'DumpDBZip2Output' => 'maintenance/backup.inc',
+ 'ExportProgressFilter' => 'maintenance/backup.inc',
'FakeMaintenance' => 'maintenance/Maintenance.php',
+ 'FixExtLinksProtocolRelative' => 'maintenance/fixExtLinksProtocolRelative.php',
'LoggedUpdateMaintenance' => 'maintenance/Maintenance.php',
'Maintenance' => 'maintenance/Maintenance.php',
- 'FixExtLinksProtocolRelative' => 'maintenance/fixExtLinksProtocolRelative.php',
'PopulateCategory' => 'maintenance/populateCategory.php',
'PopulateImageSha1' => 'maintenance/populateImageSha1.php',
+ 'PopulateFilearchiveSha1' => 'maintenance/populateFilearchiveSha1.php',
'PopulateLogSearch' => 'maintenance/populateLogSearch.php',
'PopulateLogUsertext' => 'maintenance/populateLogUsertext.php',
'PopulateParentId' => 'maintenance/populateParentId.php',
@@ -1040,40 +1080,13 @@ $wgAutoloadLocalClasses = array(
'wikiStatsOutput' => 'maintenance/language/StatOutputs.php',
# maintenance/term
- 'AnsiTermColorer' => 'maintenance/term/MWTerm.php',
+ 'AnsiTermColorer' => 'maintenance/term/MWTerm.php',
'DummyTermColorer' => 'maintenance/term/MWTerm.php',
# mw-config
'InstallerOverrides' => 'mw-config/overrides.php',
'MyLocalSettingsGenerator' => 'mw-config/overrides.php',
- # tests
- 'DbTestPreviewer' => 'tests/testHelpers.inc',
- 'DbTestRecorder' => 'tests/testHelpers.inc',
- 'DelayedParserTest' => 'tests/testHelpers.inc',
- 'TestFileIterator' => 'tests/testHelpers.inc',
- 'TestRecorder' => 'tests/testHelpers.inc',
-
- # tests/phpunit/includes
- 'GenericArrayObjectTest' => 'tests/phpunit/includes/libs/GenericArrayObjectTest.php',
-
- # tests/phpunit/includes/db
- 'ORMRowTest' => 'tests/phpunit/includes/db/ORMRowTest.php',
-
- # tests/parser
- 'ParserTest' => 'tests/parser/parserTest.inc',
- 'ParserTestParserHook' => 'tests/parser/parserTestsParserHook.php',
-
- # tests/selenium
- 'Selenium' => 'tests/selenium/Selenium.php',
- 'SeleniumLoader' => 'tests/selenium/SeleniumLoader.php',
- 'SeleniumTestCase' => 'tests/selenium/SeleniumTestCase.php',
- 'SeleniumTestConsoleLogger' => 'tests/selenium/SeleniumTestConsoleLogger.php',
- 'SeleniumTestHTMLLogger' => 'tests/selenium/SeleniumTestHTMLLogger.php',
- 'SeleniumTestListener' => 'tests/selenium/SeleniumTestListener.php',
- 'SeleniumTestSuite' => 'tests/selenium/SeleniumTestSuite.php',
- 'SeleniumConfig' => 'tests/selenium/SeleniumConfig.php',
-
# skins
'CologneBlueTemplate' => 'skins/CologneBlue.php',
'ModernTemplate' => 'skins/Modern.php',
@@ -1096,7 +1109,7 @@ class AutoLoader {
/**
* autoload - take a class name and attempt to load it
*
- * @param $className String: name of class we're looking for.
+ * @param string $className name of class we're looking for.
* @return bool Returning false is important on failure as
* it allows Zend to try and look in other registered autoloaders
* as well.
diff --git a/includes/Autopromote.php b/includes/Autopromote.php
index 9c77855d..604b9248 100644
--- a/includes/Autopromote.php
+++ b/includes/Autopromote.php
@@ -54,7 +54,7 @@ class Autopromote {
* Does not return groups the user already belongs to or has once belonged.
*
* @param $user User The user to get the groups for
- * @param $event String key in $wgAutopromoteOnce (each one has groups/criteria)
+ * @param string $event key in $wgAutopromoteOnce (each one has groups/criteria)
*
* @return array Groups the user should be promoted to.
*
@@ -140,8 +140,8 @@ class Autopromote {
return true;
}
}
- # If we got here, the array presumably does not contain other condi-
- # tions; it's not recursive. Pass it off to self::checkCondition.
+ // If we got here, the array presumably does not contain other conditions;
+ // it's not recursive. Pass it off to self::checkCondition.
if ( !is_array( $cond ) ) {
$cond = array( $cond );
}
@@ -152,11 +152,11 @@ class Autopromote {
/**
* As recCheckCondition, but *not* recursive. The only valid conditions
* are those whose first element is APCOND_EMAILCONFIRMED/APCOND_EDITCOUNT/
- * APCOND_AGE. Other types will throw an exception if no extension evalu-
- * ates them.
+ * APCOND_AGE. Other types will throw an exception if no extension evaluates them.
*
- * @param $cond Array: A condition, which must not contain other conditions
+ * @param array $cond A condition, which must not contain other conditions
* @param $user User The user to check the condition against
+ * @throws MWException
* @return bool Whether the condition is true for the user
*/
private static function checkCondition( $cond, User $user ) {
diff --git a/includes/Block.php b/includes/Block.php
index 732699dc..7ee36ce9 100644
--- a/includes/Block.php
+++ b/includes/Block.php
@@ -65,11 +65,11 @@ class Block {
$timestamp = 0, $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
$hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = '' )
{
- if( $timestamp === 0 ){
+ if( $timestamp === 0 ) {
$timestamp = wfTimestampNow();
}
- if( count( func_get_args() ) > 0 ){
+ if( count( func_get_args() ) > 0 ) {
# Soon... :D
# wfDeprecated( __METHOD__ . " with arguments" );
}
@@ -106,7 +106,7 @@ class Block {
* user ID. Tries the user ID first, and if that doesn't work, tries
* the address.
*
- * @param $address String: IP address of user/anon
+ * @param string $address IP address of user/anon
* @param $user Integer: user id of user
* @return Block Object
* @deprecated since 1.18
@@ -164,7 +164,7 @@ class Block {
/**
* Check if two blocks are effectively equal. Doesn't check irrelevant things like
- * the blocking user or the block timestamp, only things which affect the blocked user *
+ * the blocking user or the block timestamp, only things which affect the blocked user
*
* @param $block Block
*
@@ -199,23 +199,23 @@ class Block {
/**
* Get a block from the DB, with either the given address or the given username
*
- * @param $address string The IP address of the user, or blank to skip IP blocks
- * @param $user int The user ID, or zero for anonymous users
+ * @param string $address The IP address of the user, or blank to skip IP blocks
+ * @param int $user The user ID, or zero for anonymous users
* @return Boolean: the user is blocked from editing
* @deprecated since 1.18
*/
public function load( $address = '', $user = 0 ) {
wfDeprecated( __METHOD__, '1.18' );
- if( $user ){
+ if( $user ) {
$username = User::whoIs( $user );
$block = self::newFromTarget( $username, $address );
} else {
$block = self::newFromTarget( null, $address );
}
- if( $block instanceof Block ){
+ if( $block instanceof Block ) {
# This is mildly evil, but hey, it's B/C :D
- foreach( $block as $variable => $value ){
+ foreach( $block as $variable => $value ) {
$this->$variable = $value;
}
return true;
@@ -227,16 +227,17 @@ class Block {
/**
* Load a block from the database which affects the already-set $this->target:
* 1) A block directly on the given user or IP
- * 2) A rangeblock encompasing the given IP (smallest first)
+ * 2) A rangeblock encompassing the given IP (smallest first)
* 3) An autoblock on the given IP
* @param $vagueTarget User|String also search for blocks affecting this target. Doesn't
* make any sense to use TYPE_AUTO / TYPE_ID here. Leave blank to skip IP lookups.
+ * @throws MWException
* @return Bool whether a relevant block was found
*/
protected function newLoad( $vagueTarget = null ) {
$db = wfGetDB( $this->mFromMaster ? DB_MASTER : DB_SLAVE );
- if( $this->type !== null ){
+ if( $this->type !== null ) {
$conds = array(
'ipb_address' => array( (string)$this->target ),
);
@@ -246,11 +247,11 @@ class Block {
# Be aware that the != '' check is explicit, since empty values will be
# passed by some callers (bug 29116)
- if( $vagueTarget != ''){
+ if( $vagueTarget != '' ) {
list( $target, $type ) = self::parseTarget( $vagueTarget );
switch( $type ) {
case self::TYPE_USER:
- # Slightly wierd, but who are we to argue?
+ # Slightly weird, but who are we to argue?
$conds['ipb_address'][] = (string)$target;
break;
@@ -284,20 +285,20 @@ class Block {
# This is begging for $this = $bestBlock, but that's not allowed in PHP :(
$bestBlockPreventsEdit = null;
- foreach( $res as $row ){
+ foreach( $res as $row ) {
$block = self::newFromRow( $row );
# Don't use expired blocks
- if( $block->deleteIfExpired() ){
+ if( $block->deleteIfExpired() ) {
continue;
}
# Don't use anon only blocks on users
- if( $this->type == self::TYPE_USER && !$block->isHardblock() ){
+ if( $this->type == self::TYPE_USER && !$block->isHardblock() ) {
continue;
}
- if( $block->getType() == self::TYPE_RANGE ){
+ if( $block->getType() == self::TYPE_RANGE ) {
# This is the number of bits that are allowed to vary in the block, give
# or take some floating point errors
$end = wfBaseconvert( $block->getRangeEnd(), 16, 10 );
@@ -306,20 +307,20 @@ class Block {
# This has the nice property that a /32 block is ranked equally with a
# single-IP block, which is exactly what it is...
- $score = self::TYPE_RANGE - 1 + ( $size / 128 );
+ $score = self::TYPE_RANGE - 1 + ( $size / 128 );
} else {
$score = $block->getType();
}
- if( $score < $bestBlockScore ){
+ if( $score < $bestBlockScore ) {
$bestBlockScore = $score;
$bestRow = $row;
$bestBlockPreventsEdit = $block->prevents( 'edit' );
}
}
- if( $bestRow !== null ){
+ if( $bestRow !== null ) {
$this->initFromRow( $bestRow );
$this->prevents( 'edit', $bestBlockPreventsEdit );
return true;
@@ -329,9 +330,9 @@ class Block {
}
/**
- * Get a set of SQL conditions which will select rangeblocks encompasing a given range
- * @param $start String Hexadecimal IP representation
- * @param $end String Hexadecimal IP represenation, or null to use $start = $end
+ * Get a set of SQL conditions which will select rangeblocks encompassing a given range
+ * @param string $start Hexadecimal IP representation
+ * @param string $end Hexadecimal IP representation, or null to use $start = $end
* @return String
*/
public static function getRangeCond( $start, $end = null ) {
@@ -370,9 +371,9 @@ class Block {
protected static function getIpFragment( $hex ) {
global $wgBlockCIDRLimit;
if ( substr( $hex, 0, 3 ) == 'v6-' ) {
- return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
+ return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
} else {
- return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
+ return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
}
}
@@ -417,7 +418,7 @@ class Block {
* @param $row ResultWrapper row from the ipblocks table
* @return Block
*/
- public static function newFromRow( $row ){
+ public static function newFromRow( $row ) {
$block = new Block;
$block->initFromRow( $row );
return $block;
@@ -426,6 +427,7 @@ class Block {
/**
* Delete the row from the IP blocks table.
*
+ * @throws MWException
* @return Boolean
*/
public function delete() {
@@ -463,7 +465,7 @@ class Block {
Block::purgeExpired();
$row = $this->getDatabaseArray();
- $row['ipb_id'] = $dbw->nextSequenceValue("ipblocks_ipb_id_seq");
+ $row['ipb_id'] = $dbw->nextSequenceValue( "ipblocks_ipb_id_seq" );
$dbw->insert(
'ipblocks',
@@ -486,7 +488,7 @@ class Block {
* Update a block in the DB with new parameters.
* The ID field needs to be loaded first.
*
- * @return Int number of affected rows, which should probably be 1 or something's
+ * @return Int number of affected rows, which should probably be 1 or something has
* gone slightly awry
*/
public function update() {
@@ -508,8 +510,8 @@ class Block {
* @param $db DatabaseBase
* @return Array
*/
- protected function getDatabaseArray( $db = null ){
- if( !$db ){
+ protected function getDatabaseArray( $db = null ) {
+ if( !$db ) {
$db = wfGetDB( DB_SLAVE );
}
$expiry = $db->encodeExpiry( $this->mExpiry );
@@ -534,10 +536,10 @@ class Block {
'ipb_expiry' => $expiry,
'ipb_range_start' => $this->getRangeStart(),
'ipb_range_end' => $this->getRangeEnd(),
- 'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite
+ 'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite
'ipb_block_email' => $this->prevents( 'sendemail' ),
'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
- 'ipb_parent_block_id' => $this->mParentBlockId
+ 'ipb_parent_block_id' => $this->mParentBlockId
);
return $a;
@@ -570,10 +572,17 @@ class Block {
* blocked by this Block. This will use the recentchanges table.
*
* @param Block $block
- * @param Array &$blockIds
+ * @param array &$blockIds
* @return Array: block IDs of retroactive autoblocks made
*/
protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) {
+ global $wgPutIPinRC;
+
+ // No IPs are in recentchanges table, so nothing to select
+ if( !$wgPutIPinRC ) {
+ return;
+ }
+
$dbr = wfGetDB( DB_SLAVE );
$options = array( 'ORDER BY' => 'rc_timestamp DESC' );
@@ -583,9 +592,9 @@ class Block {
$options['LIMIT'] = 1;
$res = $dbr->select( 'recentchanges', array( 'rc_ip' ), $conds,
- __METHOD__ , $options );
+ __METHOD__, $options );
- if ( !$dbr->numRows( $res ) ) {
+ if ( !$res->numRows() ) {
# No results, don't autoblock anything
wfDebug( "No IP found to retroactively autoblock\n" );
} else {
@@ -602,7 +611,7 @@ class Block {
* Checks whether a given IP is on the autoblock whitelist.
* TODO: this probably belongs somewhere else, but not sure where...
*
- * @param $ip String: The IP to check
+ * @param string $ip The IP to check
* @return Boolean
*/
public static function isWhitelistedFromAutoblocks( $ip ) {
@@ -645,7 +654,7 @@ class Block {
/**
* Autoblocks the given IP, referring to this Block.
*
- * @param $autoblockIP String: the IP to autoblock.
+ * @param string $autoblockIP the IP to autoblock.
* @return mixed: block ID if an autoblock was inserted, false if not.
*/
public function doAutoblock( $autoblockIP ) {
@@ -687,7 +696,7 @@ class Block {
wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" );
$autoblock->setTarget( $autoblockIP );
$autoblock->setBlocker( $this->getBlocker() );
- $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason )->inContentLanguage()->text();
+ $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason )->inContentLanguage()->plain();
$timestamp = wfTimestampNow();
$autoblock->mTimestamp = $timestamp;
$autoblock->mAuto = 1;
@@ -780,6 +789,7 @@ class Block {
/**
* Get the IP address at the start of the range in Hex form
+ * @throws MWException
* @return String IP in Hex form
*/
public function getRangeStart() {
@@ -797,6 +807,7 @@ class Block {
/**
* Get the IP address at the start of the range in Hex form
+ * @throws MWException
* @return String IP in Hex form
*/
public function getRangeEnd() {
@@ -934,7 +945,7 @@ class Block {
/**
* Encode expiry for DB
*
- * @param $expiry String: timestamp for expiry, or
+ * @param string $expiry timestamp for expiry, or
* @param $db DatabaseBase object
* @return String
* @deprecated since 1.18; use $dbw->encodeExpiry() instead
@@ -947,8 +958,8 @@ class Block {
/**
* Decode expiry which has come from the DB
*
- * @param $expiry String: Database expiry format
- * @param $timestampType Int Requested timestamp format
+ * @param string $expiry Database expiry format
+ * @param int $timestampType Requested timestamp format
* @return String
* @deprecated since 1.18; use $wgLang->formatExpiry() instead
*/
@@ -971,9 +982,9 @@ class Block {
}
/**
- * Gets rid of uneeded numbers in quad-dotted/octet IP strings
+ * Gets rid of unneeded numbers in quad-dotted/octet IP strings
* For example, 127.111.113.151/24 -> 127.111.113.0/24
- * @param $range String: IP address to normalize
+ * @param string $range IP address to normalize
* @return string
* @deprecated since 1.18, call IP::sanitizeRange() directly
*/
@@ -986,9 +997,11 @@ class Block {
* Purge expired blocks from the ipblocks table
*/
public static function purgeExpired() {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->delete( 'ipblocks',
- array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ );
+ if ( !wfReadOnly() ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->delete( 'ipblocks',
+ array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ );
+ }
}
/**
@@ -1005,7 +1018,7 @@ class Block {
/**
* Convert a submitted expiry time, which may be relative ("2 weeks", etc) or absolute
* ("24 May 2034"), into an absolute timestamp we can put into the database.
- * @param $expiry String: whatever was typed into the form
+ * @param string $expiry whatever was typed into the form
* @return String: timestamp or "infinity" string for th DB implementation
* @deprecated since 1.18 moved to SpecialBlock::parseExpiryInput()
*/
@@ -1029,7 +1042,7 @@ class Block {
* @param $vagueTarget String|User|Int as above, but we will search for *any* block which
* affects that target (so for an IP address, get ranges containing that IP; and also
* get any relevant autoblocks). Leave empty or blank to skip IP-based lookups.
- * @param $fromMaster Bool whether to use the DB_MASTER database
+ * @param bool $fromMaster whether to use the DB_MASTER database
* @return Block|null (null if no relevant block could be found). The target and type
* of the returned Block will refer to the actual block which was found, which might
* not be the same as the target you gave if you used $vagueTarget!
@@ -1037,24 +1050,24 @@ class Block {
public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
list( $target, $type ) = self::parseTarget( $specificTarget );
- if( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ){
+ if( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ) {
return Block::newFromID( $target );
- } elseif( $target === null && $vagueTarget == '' ){
+ } elseif( $target === null && $vagueTarget == '' ) {
# We're not going to find anything useful here
# Be aware that the == '' check is explicit, since empty values will be
# passed by some callers (bug 29116)
return null;
- } elseif( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE ) ) ) {
+ } elseif( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE, null ) ) ) {
$block = new Block();
$block->fromMaster( $fromMaster );
- if( $type !== null ){
+ if( $type !== null ) {
$block->setTarget( $target );
}
- if( $block->newLoad( $vagueTarget ) ){
+ if( $block->newLoad( $vagueTarget ) ) {
return $block;
}
}
@@ -1062,22 +1075,23 @@ class Block {
}
/**
- * From an existing Block, get the target and the type of target. Note that it is
- * always safe to treat the target as a string; for User objects this will return
- * User::__toString() which in turn gives User::getName().
+ * From an existing Block, get the target and the type of target.
+ * Note that, except for null, it is always safe to treat the target
+ * as a string; for User objects this will return User::__toString()
+ * which in turn gives User::getName().
*
- * @param $target String|Int|User
- * @return array( User|String, Block::TYPE_ constant )
+ * @param $target String|Int|User|null
+ * @return array( User|String|null, Block::TYPE_ constant|null )
*/
public static function parseTarget( $target ) {
# We may have been through this before
- if( $target instanceof User ){
- if( IP::isValid( $target->getName() ) ){
+ if( $target instanceof User ) {
+ if( IP::isValid( $target->getName() ) ) {
return array( $target, self::TYPE_IP );
} else {
return array( $target, self::TYPE_USER );
}
- } elseif( $target === null ){
+ } elseif( $target === null ) {
return array( null, null );
}
@@ -1098,7 +1112,7 @@ class Block {
# Consider the possibility that this is not a username at all
# but actually an old subpage (bug #29797)
- if( strpos( $target, '/' ) !== false ){
+ if( strpos( $target, '/' ) !== false ) {
# An old subpage, drill down to the user behind it
$parts = explode( '/', $target );
$target = $parts[0];
@@ -1165,7 +1179,7 @@ class Block {
* Set the target for this block, and update $this->type accordingly
* @param $target Mixed
*/
- public function setTarget( $target ){
+ public function setTarget( $target ) {
list( $this->target, $this->type ) = self::parseTarget( $target );
}
@@ -1173,15 +1187,15 @@ class Block {
* Get the user who implemented this block
* @return User|string Local User object or string for a foreign user
*/
- public function getBlocker(){
+ public function getBlocker() {
return $this->blocker;
}
/**
* Set the user who implemented (or will implement) this block
- * @param $user User|string Local User object or username string for foriegn users
+ * @param $user User|string Local User object or username string for foreign users
*/
- public function setBlocker( $user ){
+ public function setBlocker( $user ) {
$this->blocker = $user;
}
}
diff --git a/includes/CacheHelper.php b/includes/CacheHelper.php
index ac46fc42..f0ae5a31 100644
--- a/includes/CacheHelper.php
+++ b/includes/CacheHelper.php
@@ -18,7 +18,7 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @licence GNU GPL v2 or later
+ * @license GNU GPL v2 or later
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
diff --git a/includes/Category.php b/includes/Category.php
index b7b12e8a..868d6c46 100644
--- a/includes/Category.php
+++ b/includes/Category.php
@@ -44,6 +44,7 @@ class Category {
/**
* Set up all member variables using a database query.
+ * @throws MWException
* @return bool True on success, false on failure.
*/
protected function initialize() {
@@ -57,6 +58,9 @@ class Category {
# Already initialized
return true;
}
+
+ wfProfileIn( __METHOD__ );
+
$dbr = wfGetDB( DB_SLAVE );
$row = $dbr->selectRow(
'category',
@@ -65,15 +69,17 @@ class Category {
__METHOD__
);
+ wfProfileOut( __METHOD__ );
+
if ( !$row ) {
# Okay, there were no contents. Nothing to initialize.
if ( $this->mTitle ) {
# If there is a title object but no record in the category table, treat this as an empty category
- $this->mID = false;
- $this->mName = $this->mTitle->getDBkey();
- $this->mPages = 0;
+ $this->mID = false;
+ $this->mName = $this->mTitle->getDBkey();
+ $this->mPages = 0;
$this->mSubcats = 0;
- $this->mFiles = 0;
+ $this->mFiles = 0;
return true;
} else {
@@ -81,11 +87,11 @@ class Category {
}
}
- $this->mID = $row->cat_id;
- $this->mName = $row->cat_title;
- $this->mPages = $row->cat_pages;
+ $this->mID = $row->cat_id;
+ $this->mName = $row->cat_title;
+ $this->mPages = $row->cat_pages;
$this->mSubcats = $row->cat_subcats;
- $this->mFiles = $row->cat_files;
+ $this->mFiles = $row->cat_files;
# (bug 13683) If the count is negative, then 1) it's obviously wrong
# and should not be kept, and 2) we *probably* don't have to scan many
@@ -100,7 +106,7 @@ class Category {
/**
* Factory function.
*
- * @param $name Array: A category name (no "Category:" prefix). It need
+ * @param array $name A category name (no "Category:" prefix). It need
* not be normalized, with spaces replaced by underscores.
* @return mixed Category, or false on a totally invalid name
*/
@@ -161,7 +167,7 @@ class Category {
# NOTE: the row often results from a LEFT JOIN on categorylinks. This may result in
# all the cat_xxx fields being null, if the category page exists, but nothing
- # was ever added to the category. This case should be treated linke an empty
+ # was ever added to the category. This case should be treated link an empty
# category, if possible.
if ( $row->cat_title === null ) {
@@ -173,41 +179,53 @@ class Category {
$cat->mName = $title->getDBkey(); # if we have a title object, fetch the category name from there
}
- $cat->mID = false;
+ $cat->mID = false;
$cat->mSubcats = 0;
- $cat->mPages = 0;
- $cat->mFiles = 0;
+ $cat->mPages = 0;
+ $cat->mFiles = 0;
} else {
- $cat->mName = $row->cat_title;
- $cat->mID = $row->cat_id;
+ $cat->mName = $row->cat_title;
+ $cat->mID = $row->cat_id;
$cat->mSubcats = $row->cat_subcats;
- $cat->mPages = $row->cat_pages;
- $cat->mFiles = $row->cat_files;
+ $cat->mPages = $row->cat_pages;
+ $cat->mFiles = $row->cat_files;
}
return $cat;
}
/** @return mixed DB key name, or false on failure */
- public function getName() { return $this->getX( 'mName' ); }
+ public function getName() {
+ return $this->getX( 'mName' );
+ }
/** @return mixed Category ID, or false on failure */
- public function getID() { return $this->getX( 'mID' ); }
+ public function getID() {
+ return $this->getX( 'mID' );
+ }
/** @return mixed Total number of member pages, or false on failure */
- public function getPageCount() { return $this->getX( 'mPages' ); }
+ public function getPageCount() {
+ return $this->getX( 'mPages' );
+ }
/** @return mixed Number of subcategories, or false on failure */
- public function getSubcatCount() { return $this->getX( 'mSubcats' ); }
+ public function getSubcatCount() {
+ return $this->getX( 'mSubcats' );
+ }
/** @return mixed Number of member files, or false on failure */
- public function getFileCount() { return $this->getX( 'mFiles' ); }
+ public function getFileCount() {
+ return $this->getX( 'mFiles' );
+ }
/**
* @return Title|bool Title for this category, or false on failure.
*/
public function getTitle() {
- if ( $this->mTitle ) return $this->mTitle;
+ if ( $this->mTitle ) {
+ return $this->mTitle;
+ }
if ( !$this->initialize() ) {
return false;
@@ -225,20 +243,22 @@ class Category {
* @return TitleArray object for category members.
*/
public function getMembers( $limit = false, $offset = '' ) {
+ wfProfileIn( __METHOD__ );
+
$dbr = wfGetDB( DB_SLAVE );
$conds = array( 'cl_to' => $this->getName(), 'cl_from = page_id' );
$options = array( 'ORDER BY' => 'cl_sortkey' );
if ( $limit ) {
- $options[ 'LIMIT' ] = $limit;
+ $options['LIMIT'] = $limit;
}
if ( $offset !== '' ) {
$conds[] = 'cl_sortkey > ' . $dbr->addQuotes( $offset );
}
- return TitleArray::newFromResult(
+ $result = TitleArray::newFromResult(
$dbr->select(
array( 'page', 'categorylinks' ),
array( 'page_id', 'page_namespace', 'page_title', 'page_len',
@@ -248,6 +268,10 @@ class Category {
$options
)
);
+
+ wfProfileOut( __METHOD__ );
+
+ return $result;
}
/**
@@ -258,7 +282,7 @@ class Category {
if ( !$this->initialize() ) {
return false;
}
- return $this-> { $key } ;
+ return $this->{$key};
}
/**
@@ -278,8 +302,10 @@ class Category {
}
}
+ wfProfileIn( __METHOD__ );
+
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin( __METHOD__ );
+ $dbw->begin( __METHOD__ );
# Insert the row if it doesn't exist yet (e.g., this is being run via
# update.php from a pre-1.16 schema). TODO: This will cause lots and
@@ -302,12 +328,12 @@ class Category {
$result = $dbw->selectRow(
array( 'categorylinks', 'page' ),
array( 'pages' => 'COUNT(*)',
- 'subcats' => "COUNT($cond1)",
- 'files' => "COUNT($cond2)"
+ 'subcats' => "COUNT($cond1)",
+ 'files' => "COUNT($cond2)"
),
array( 'cl_to' => $this->mName, 'page_id = cl_from' ),
__METHOD__,
- 'LOCK IN SHARE MODE'
+ array( 'LOCK IN SHARE MODE' )
);
$ret = $dbw->update(
'category',
@@ -321,10 +347,12 @@ class Category {
);
$dbw->commit( __METHOD__ );
+ wfProfileOut( __METHOD__ );
+
# Now we should update our local counts.
- $this->mPages = $result->pages;
+ $this->mPages = $result->pages;
$this->mSubcats = $result->subcats;
- $this->mFiles = $result->files;
+ $this->mFiles = $result->files;
return $ret;
}
diff --git a/includes/CategoryPage.php b/includes/CategoryPage.php
index 32e270e8..43ab4dbd 100644
--- a/includes/CategoryPage.php
+++ b/includes/CategoryPage.php
@@ -40,7 +40,7 @@ class CategoryPage extends Article {
/**
* Constructor from a page id
- * @param $id Int article ID to load
+ * @param int $id article ID to load
* @return CategoryPage|null
*/
public static function newFromID( $id ) {
@@ -56,7 +56,7 @@ class CategoryPage extends Article {
$diffOnly = $request->getBool( 'diffonly',
$this->getContext()->getUser()->getOption( 'diffonly' ) );
- if ( isset( $diff ) && $diffOnly ) {
+ if ( $diff !== null && $diffOnly ) {
parent::view();
return;
}
diff --git a/includes/CategoryViewer.php b/includes/CategoryViewer.php
index 3bb2bc9b..970adb53 100644
--- a/includes/CategoryViewer.php
+++ b/includes/CategoryViewer.php
@@ -71,11 +71,12 @@ class CategoryViewer extends ContextSource {
* @since 1.19 $context is a second, required parameter
* @param $title Title
* @param $context IContextSource
- * @param $from String
- * @param $until String
+ * @param array $from An array with keys page, subcat,
+ * and file for offset of results of each section (since 1.17)
+ * @param array $until An array with 3 keys for until of each section (since 1.17)
* @param $query Array
*/
- function __construct( $title, IContextSource $context, $from = '', $until = '', $query = array() ) {
+ function __construct( $title, IContextSource $context, $from = array(), $until = array(), $query = array() ) {
global $wgCategoryPagingLimit;
$this->title = $title;
$this->setContext( $context );
@@ -173,7 +174,7 @@ class CategoryViewer extends ContextSource {
/**
* Add a subcategory to the internal lists, using a title object
- * @deprecated since 1.17 kept for compatibility, please use addSubcategoryObject instead
+ * @deprecated since 1.17 kept for compatibility, use addSubcategoryObject instead
*/
function addSubcategory( Title $title, $sortkey, $pageLength ) {
wfDeprecated( __METHOD__, '1.17' );
@@ -181,14 +182,14 @@ class CategoryViewer extends ContextSource {
}
/**
- * Get the character to be used for sorting subcategories.
- * If there's a link from Category:A to Category:B, the sortkey of the resulting
- * entry in the categorylinks table is Category:A, not A, which it SHOULD be.
- * Workaround: If sortkey == "Category:".$title, than use $title for sorting,
- * else use sortkey...
- *
- * @param Title $title
- * @param string $sortkey The human-readable sortkey (before transforming to icu or whatever).
+ * Get the character to be used for sorting subcategories.
+ * If there's a link from Category:A to Category:B, the sortkey of the resulting
+ * entry in the categorylinks table is Category:A, not A, which it SHOULD be.
+ * Workaround: If sortkey == "Category:".$title, than use $title for sorting,
+ * else use sortkey...
+ *
+ * @param Title $title
+ * @param string $sortkey The human-readable sortkey (before transforming to icu or whatever).
* @return string
*/
function getSubcategorySortChar( $title, $sortkey ) {
@@ -248,7 +249,7 @@ class CategoryViewer extends ContextSource {
$link = Linker::link( $title );
if ( $isRedirect ) {
// This seems kind of pointless given 'mw-redirect' class,
- // but keeping for back-compatiability with user css.
+ // but keeping for back-compatibility with user css.
$link = '<span class="redirect-in-category">' . $link . '</span>';
}
$this->articles[] = $link;
@@ -259,15 +260,15 @@ class CategoryViewer extends ContextSource {
function finaliseCategoryState() {
if ( $this->flip['subcat'] ) {
- $this->children = array_reverse( $this->children );
+ $this->children = array_reverse( $this->children );
$this->children_start_char = array_reverse( $this->children_start_char );
}
if ( $this->flip['page'] ) {
- $this->articles = array_reverse( $this->articles );
+ $this->articles = array_reverse( $this->articles );
$this->articles_start_char = array_reverse( $this->articles_start_char );
}
if ( !$this->showGallery && $this->flip['file'] ) {
- $this->imgsNoGallery = array_reverse( $this->imgsNoGallery );
+ $this->imgsNoGallery = array_reverse( $this->imgsNoGallery );
$this->imgsNoGallery_start_char = array_reverse( $this->imgsNoGallery_start_char );
}
}
@@ -287,10 +288,10 @@ class CategoryViewer extends ContextSource {
# the collation in the database differs from the one
# set in $wgCategoryCollation, pagination might go totally haywire.
$extraConds = array( 'cl_type' => $type );
- if ( $this->from[$type] !== null ) {
+ if ( isset( $this->from[$type] ) && $this->from[$type] !== null ) {
$extraConds[] = 'cl_sortkey >= '
. $dbr->addQuotes( $this->collation->getSortKey( $this->from[$type] ) );
- } elseif ( $this->until[$type] !== null ) {
+ } elseif ( isset( $this->until[$type] ) && $this->until[$type] !== null ) {
$extraConds[] = 'cl_sortkey < '
. $dbr->addQuotes( $this->collation->getSortKey( $this->until[$type] ) );
$this->flip[$type] = true;
@@ -302,7 +303,7 @@ class CategoryViewer extends ContextSource {
'page_is_redirect', 'cl_sortkey', 'cat_id', 'cat_title',
'cat_subcats', 'cat_pages', 'cat_files',
'cl_sortkey_prefix', 'cl_collation' ),
- array_merge( array( 'cl_to' => $this->title->getDBkey() ), $extraConds ),
+ array_merge( array( 'cl_to' => $this->title->getDBkey() ), $extraConds ),
__METHOD__,
array(
'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ),
@@ -310,8 +311,11 @@ class CategoryViewer extends ContextSource {
'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey',
),
array(
- 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
- 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY )
+ 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
+ 'category' => array( 'LEFT JOIN', array(
+ 'cat_title = page_title',
+ 'page_namespace' => NS_CATEGORY
+ ))
)
);
@@ -388,7 +392,7 @@ class CategoryViewer extends ContextSource {
$r = '';
# @todo FIXME: Here and in the other two sections: we don't need to bother
- # with this rigamarole if the entire category contents fit on one page
+ # with this rigmarole if the entire category contents fit on one page
# and have already been retrieved. We can just use $rescnt in that
# case and save a query and some logic.
$dbcnt = $this->cat->getPageCount() - $this->cat->getSubcatCount()
@@ -437,13 +441,13 @@ class CategoryViewer extends ContextSource {
* Get the paging links for a section (subcats/pages/files), to go at the top and bottom
* of the output.
*
- * @param $type String: 'page', 'subcat', or 'file'
+ * @param string $type 'page', 'subcat', or 'file'
* @return String: HTML output, possibly empty if there are no other pages
*/
private function getSectionPagingLinks( $type ) {
- if ( $this->until[$type] !== null ) {
+ if ( isset( $this->until[$type] ) && $this->until[$type] !== null ) {
return $this->pagingLinks( $this->nextPage[$type], $this->until[$type], $type );
- } elseif ( $this->nextPage[$type] !== null || $this->from[$type] !== null ) {
+ } elseif ( $this->nextPage[$type] !== null || ( isset( $this->from[$type] ) && $this->from[$type] !== null ) ) {
return $this->pagingLinks( $this->from[$type], $this->nextPage[$type], $type );
} else {
return '';
@@ -469,7 +473,7 @@ class CategoryViewer extends ContextSource {
*/
function formatList( $articles, $articles_start_char, $cutoff = 6 ) {
$list = '';
- if ( count ( $articles ) > $cutoff ) {
+ if ( count( $articles ) > $cutoff ) {
$list = self::columnList( $articles, $articles_start_char );
} elseif ( count( $articles ) > 0 ) {
// for short lists of articles in categories.
@@ -478,7 +482,7 @@ class CategoryViewer extends ContextSource {
$pageLang = $this->title->getPageLanguage();
$attribs = array( 'lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(),
- 'class' => 'mw-content-'.$pageLang->getDir() );
+ 'class' => 'mw-content-' . $pageLang->getDir() );
$list = Html::rawElement( 'div', $attribs, $list );
return $list;
@@ -569,9 +573,9 @@ class CategoryViewer extends ContextSource {
/**
* Create paging links, as a helper method to getSectionPagingLinks().
*
- * @param $first String The 'until' parameter for the generated URL
- * @param $last String The 'from' parameter for the genererated URL
- * @param $type String A prefix for parameters, 'page' or 'subcat' or
+ * @param string $first The 'until' parameter for the generated URL
+ * @param string $last The 'from' parameter for the generated URL
+ * @param string $type A prefix for parameters, 'page' or 'subcat' or
* 'file'
* @return String HTML
*/
@@ -604,7 +608,7 @@ class CategoryViewer extends ContextSource {
);
}
- return $this->msg('categoryviewer-pagedlinks')->rawParams($prevLink, $nextLink)->escaped();
+ return $this->msg( 'categoryviewer-pagedlinks' )->rawParams( $prevLink, $nextLink )->escaped();
}
/**
@@ -612,7 +616,8 @@ class CategoryViewer extends ContextSource {
* corresponds to the correct segment of the category.
*
* @param Title $title: The title (usually $this->title)
- * @param String $section: Which section
+ * @param string $section: Which section
+ * @throws MWException
* @return Title
*/
private function addFragmentToTitle( $title, $section ) {
@@ -634,6 +639,7 @@ class CategoryViewer extends ContextSource {
return Title::makeTitle( $title->getNamespace(),
$title->getDBkey(), $fragment );
}
+
/**
* What to do if the category table conflicts with the number of results
* returned? This function says what. Each type is considered independently
@@ -644,9 +650,9 @@ class CategoryViewer extends ContextSource {
* category-subcat-count-limited, category-file-count,
* category-file-count-limited.
*
- * @param $rescnt Int: The number of items returned by our database query.
- * @param $dbcnt Int: The number of items according to the category table.
- * @param $type String: 'subcat', 'article', or 'file'
+ * @param int $rescnt The number of items returned by our database query.
+ * @param int $dbcnt The number of items according to the category table.
+ * @param string $type 'subcat', 'article', or 'file'
* @return String: A message giving the number of items, to output to HTML.
*/
private function getCountMessage( $rescnt, $dbcnt, $type ) {
@@ -671,12 +677,15 @@ class CategoryViewer extends ContextSource {
}
$fromOrUntil = false;
- if ( $this->from[$pagingType] !== null || $this->until[$pagingType] !== null ) {
+ if ( ( isset( $this->from[$pagingType] ) && $this->from[$pagingType] !== null ) ||
+ ( isset( $this->until[$pagingType] ) && $this->until[$pagingType] !== null )
+ ) {
$fromOrUntil = true;
}
- if ( $dbcnt == $rescnt || ( ( $rescnt == $this->limit || $fromOrUntil )
- && $dbcnt > $rescnt ) ) {
+ if ( $dbcnt == $rescnt ||
+ ( ( $rescnt == $this->limit || $fromOrUntil ) && $dbcnt > $rescnt )
+ ) {
# Case 1: seems sane.
$totalcnt = $dbcnt;
} elseif ( $rescnt < $this->limit && !$fromOrUntil ) {
diff --git a/includes/Categoryfinder.php b/includes/Categoryfinder.php
index e2b6a0ca..6ef224b6 100644
--- a/includes/Categoryfinder.php
+++ b/includes/Categoryfinder.php
@@ -28,17 +28,17 @@
*
* Example use :
* <code>
- * # Determines whether the article with the page_id 12345 is in both
- * # "Category 1" and "Category 2" or their subcategories, respectively
+ * # Determines whether the article with the page_id 12345 is in both
+ * # "Category 1" and "Category 2" or their subcategories, respectively
*
- * $cf = new Categoryfinder;
- * $cf->seed(
- * array( 12345 ),
- * array( 'Category 1', 'Category 2' ),
- * 'AND'
- * );
- * $a = $cf->run();
- * print implode( ',' , $a );
+ * $cf = new Categoryfinder;
+ * $cf->seed(
+ * array( 12345 ),
+ * array( 'Category 1', 'Category 2' ),
+ * 'AND'
+ * );
+ * $a = $cf->run();
+ * print implode( ',' , $a );
* </code>
*
*/
@@ -66,7 +66,7 @@ class Categoryfinder {
* Initializes the instance. Do this prior to calling run().
* @param $article_ids Array of article IDs
* @param $categories FIXME
- * @param $mode String: FIXME, default 'AND'.
+ * @param string $mode FIXME, default 'AND'.
* @todo FIXME: $categories/$mode
*/
function seed( $article_ids, $categories, $mode = 'AND' ) {
@@ -111,9 +111,9 @@ class Categoryfinder {
/**
* This functions recurses through the parent representation, trying to match the conditions
- * @param $id int The article/category to check
- * @param $conds array The array of categories to match
- * @param $path array used to check for recursion loops
+ * @param int $id The article/category to check
+ * @param array $conds The array of categories to match
+ * @param array $path used to check for recursion loops
* @return bool Does this match the conditions?
*/
function check( $id, &$conds, $path = array() ) {
@@ -124,7 +124,7 @@ class Categoryfinder {
$path[] = $id;
- # Shortcut (runtime paranoia): No contitions=all matched
+ # Shortcut (runtime paranoia): No conditions=all matched
if ( count( $conds ) == 0 ) {
return true;
}
@@ -135,7 +135,7 @@ class Categoryfinder {
# iterate through the parents
foreach ( $this->parents[$id] as $p ) {
- $pname = $p->cl_to ;
+ $pname = $p->cl_to;
# Is this a condition?
if ( isset( $conds[$pname] ) ) {
@@ -172,6 +172,8 @@ class Categoryfinder {
* Scans a "parent layer" of the articles/categories in $this->next
*/
function scan_next_layer() {
+ wfProfileIn( __METHOD__ );
+
# Find all parents of the article currently in $this->next
$layer = array();
$res = $this->dbr->select(
@@ -209,7 +211,7 @@ class Categoryfinder {
$res = $this->dbr->select(
/* FROM */ 'page',
/* SELECT */ array( 'page_id', 'page_title' ),
- /* WHERE */ array( 'page_namespace' => NS_CATEGORY , 'page_title' => $layer ),
+ /* WHERE */ array( 'page_namespace' => NS_CATEGORY, 'page_title' => $layer ),
__METHOD__ . '-2'
);
foreach ( $res as $o ) {
@@ -225,6 +227,7 @@ class Categoryfinder {
foreach ( $layer as $v ) {
$this->deadend[$v] = $v;
}
- }
+ wfProfileOut( __METHOD__ );
+ }
}
diff --git a/includes/Cdb.php b/includes/Cdb.php
index ae2e5b18..a142c7cb 100644
--- a/includes/Cdb.php
+++ b/includes/Cdb.php
@@ -133,8 +133,9 @@ class CdbReader_DBA {
}
function close() {
- if( isset($this->handle) )
+ if( isset( $this->handle ) ) {
dba_close( $this->handle );
+ }
unset( $this->handle );
}
@@ -143,7 +144,6 @@ class CdbReader_DBA {
}
}
-
/**
* Writer class which uses the DBA extension
*/
@@ -164,8 +164,9 @@ class CdbWriter_DBA {
}
function close() {
- if( isset($this->handle) )
+ if( isset( $this->handle ) ) {
dba_close( $this->handle );
+ }
if ( wfIsWindows() ) {
unlink( $this->realFileName );
}
@@ -181,4 +182,3 @@ class CdbWriter_DBA {
}
}
}
-
diff --git a/includes/Cdb_PHP.php b/includes/Cdb_PHP.php
index 02be65f3..71b55f87 100644
--- a/includes/Cdb_PHP.php
+++ b/includes/Cdb_PHP.php
@@ -126,6 +126,7 @@ class CdbReader_PHP extends CdbReader {
/**
* @param $fileName string
+ * @throws MWException
*/
function __construct( $fileName ) {
$this->fileName = $fileName;
@@ -179,7 +180,7 @@ class CdbReader_PHP extends CdbReader {
protected function read( $length, $pos ) {
if ( fseek( $this->handle, $pos ) == -1 ) {
// This can easily happen if the internal pointers are incorrect
- throw new MWException(
+ throw new MWException(
'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
}
@@ -198,12 +199,13 @@ class CdbReader_PHP extends CdbReader {
/**
* Unpack an unsigned integer and throw an exception if it needs more than 31 bits
* @param $s
- * @return
+ * @throws MWException
+ * @return mixed
*/
protected function unpack31( $s ) {
$data = unpack( 'V', $s );
if ( $data[1] > 0x7fffffff ) {
- throw new MWException(
+ throw new MWException(
'Error in CDB file "' . $this->fileName . '", integer too big.' );
}
return $data[1];
@@ -330,10 +332,10 @@ class CdbWriter_PHP extends CdbWriter {
*/
public function close() {
$this->finish();
- if( isset($this->handle) ) {
+ if( isset( $this->handle ) ) {
fclose( $this->handle );
}
- if ( wfIsWindows() && file_exists($this->realFileName) ) {
+ if ( wfIsWindows() && file_exists( $this->realFileName ) ) {
unlink( $this->realFileName );
}
if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
@@ -349,7 +351,7 @@ class CdbWriter_PHP extends CdbWriter {
protected function write( $buf ) {
$len = fwrite( $this->handle, $buf );
if ( $len !== strlen( $buf ) ) {
- $this->throwException( 'Error writing to CDB file "'.$this->tmpFileName.'".' );
+ $this->throwException( 'Error writing to CDB file "' . $this->tmpFileName . '".' );
}
}
@@ -361,7 +363,7 @@ class CdbWriter_PHP extends CdbWriter {
$newpos = $this->pos + $len;
if ( $newpos > 0x7fffffff ) {
$this->throwException(
- 'A value in the CDB file "'.$this->tmpFileName.'" is too large.' );
+ 'A value in the CDB file "' . $this->tmpFileName . '" is too large.' );
}
$this->pos = $newpos;
}
@@ -390,10 +392,10 @@ class CdbWriter_PHP extends CdbWriter {
*/
protected function addbegin( $keylen, $datalen ) {
if ( $keylen > 0x7fffffff ) {
- $this->throwException( 'Key length too long in file "'.$this->tmpFileName.'".' );
+ $this->throwException( 'Key length too long in file "' . $this->tmpFileName . '".' );
}
if ( $datalen > 0x7fffffff ) {
- $this->throwException( 'Data length too long in file "'.$this->tmpFileName.'".' );
+ $this->throwException( 'Data length too long in file "' . $this->tmpFileName . '".' );
}
$buf = pack( 'VV', $keylen, $datalen );
$this->write( $buf );
@@ -468,14 +470,14 @@ class CdbWriter_PHP extends CdbWriter {
// Write the pointer array at the start of the file
rewind( $this->handle );
if ( ftell( $this->handle ) != 0 ) {
- $this->throwException( 'Error rewinding to start of file "'.$this->tmpFileName.'".' );
+ $this->throwException( 'Error rewinding to start of file "' . $this->tmpFileName . '".' );
}
$this->write( $final );
}
/**
* Clean up the temp file and throw an exception
- *
+ *
* @param $msg string
* @throws MWException
*/
diff --git a/includes/ChangeTags.php b/includes/ChangeTags.php
index 0ebc926f..3adf58f8 100644
--- a/includes/ChangeTags.php
+++ b/includes/ChangeTags.php
@@ -25,8 +25,8 @@ class ChangeTags {
/**
* Creates HTML for the given tags
*
- * @param $tags String: Comma-separated list of tags
- * @param $page String: A label for the type of action which is being displayed,
+ * @param string $tags Comma-separated list of tags
+ * @param string $page A label for the type of action which is being displayed,
* for example: 'history', 'contributions' or 'newpages'
*
* @return Array with two items: (html, classes)
@@ -62,7 +62,7 @@ class ChangeTags {
/**
* Get a short description for a tag
*
- * @param $tag String: tag
+ * @param string $tag tag
*
* @return String: Short description of the tag from "mediawiki:tag-$tag" if this message exists,
* html-escaped version of $tag otherwise
@@ -75,12 +75,13 @@ class ChangeTags {
/**
* Add tags to a change given its rc_id, rev_id and/or log_id
*
- * @param $tags String|Array: Tags to add to the change
+ * @param string|array $tags Tags to add to the change
* @param $rc_id int: rc_id of the change to add the tags to
* @param $rev_id int: rev_id of the change to add the tags to
* @param $log_id int: log_id of the change to add the tags to
- * @param $params String: params to put in the ct_params field of tabel 'change_tag'
+ * @param string $params params to put in the ct_params field of table 'change_tag'
*
+ * @throws MWException
* @return bool: false if no changes are made, otherwise true
*
* @exception MWException when $rc_id, $rev_id and $log_id are all null
@@ -159,17 +160,16 @@ class ChangeTags {
* Handles selecting tags, and filtering.
* Needs $tables to be set up properly, so we can figure out which join conditions to use.
*
- * @param $tables String|Array: Tabel names, see DatabaseBase::select
- * @param $fields String|Array: Fields used in query, see DatabaseBase::select
- * @param $conds String|Array: conditions used in query, see DatabaseBase::select
+ * @param string|array $tables Table names, see DatabaseBase::select
+ * @param string|array $fields Fields used in query, see DatabaseBase::select
+ * @param string|array $conds conditions used in query, see DatabaseBase::select
* @param $join_conds Array: join conditions, see DatabaseBase::select
- * @param $options Array: options, see Database::select
- * @param $filter_tag String: tag to select on
- *
- * @exception MWException when unable to determine appropriate JOIN condition for tagging
+ * @param array $options options, see Database::select
+ * @param bool|string $filter_tag Tag to select on
*
+ * @throws MWException When unable to determine appropriate JOIN condition for tagging
*/
- static function modifyDisplayQuery( &$tables, &$fields, &$conds,
+ static function modifyDisplayQuery( &$tables, &$fields, &$conds,
&$join_conds, &$options, $filter_tag = false ) {
global $wgRequest, $wgUseTagFilter;
@@ -211,7 +211,7 @@ class ChangeTags {
/**
* Build a text box to select a change tag
*
- * @param $selected String: tag to select by default
+ * @param string $selected tag to select by default
* @param $fullForm Boolean:
* - if false, then it returns an array of (label, form).
* - if true, it returns an entire form around the selector.
@@ -221,11 +221,12 @@ class ChangeTags {
* - if $fullForm is false: Array with
* - if $fullForm is true: String, html fragment
*/
- public static function buildTagFilterSelector( $selected='', $fullForm = false, Title $title = null ) {
+ public static function buildTagFilterSelector( $selected = '', $fullForm = false, Title $title = null ) {
global $wgUseTagFilter;
- if ( !$wgUseTagFilter || !count( self::listDefinedTags() ) )
+ if ( !$wgUseTagFilter || !count( self::listDefinedTags() ) ) {
return $fullForm ? '' : array();
+ }
$data = array( Html::rawElement( 'label', array( 'for' => 'tagfilter' ), wfMessage( 'tag-filter' )->parse() ),
Xml::input( 'tagfilter', 20, $selected, array( 'class' => 'mw-tagfilter-input' ) ) );
diff --git a/includes/ChangesFeed.php b/includes/ChangesFeed.php
index ee4c2d64..476de5bd 100644
--- a/includes/ChangesFeed.php
+++ b/includes/ChangesFeed.php
@@ -31,8 +31,8 @@ class ChangesFeed {
/**
* Constructor
*
- * @param $format String: feed's format (either 'rss' or 'atom')
- * @param $type String: type of feed (for cache keys)
+ * @param string $format feed's format (either 'rss' or 'atom')
+ * @param string $type type of feed (for cache keys)
*/
public function __construct( $format, $type ) {
$this->format = $format;
@@ -42,9 +42,9 @@ class ChangesFeed {
/**
* Get a ChannelFeed subclass object to use
*
- * @param $title String: feed's title
- * @param $description String: feed's description
- * @param $url String: url of origin page
+ * @param string $title feed's title
+ * @param string $description feed's description
+ * @param string $url url of origin page
* @return ChannelFeed subclass or false on failure
*/
public function getFeedObject( $title, $description, $url ) {
@@ -110,9 +110,9 @@ class ChangesFeed {
/**
* Save to feed result to $messageMemc
*
- * @param $feed String: feed's content
- * @param $timekey String: memcached key of the last modification
- * @param $key String: memcached key of the content
+ * @param string $feed feed's content
+ * @param string $timekey memcached key of the last modification
+ * @param string $key memcached key of the content
*/
public function saveToCache( $feed, $timekey, $key ) {
global $messageMemc;
@@ -125,8 +125,8 @@ class ChangesFeed {
* Try to load the feed result from $messageMemc
*
* @param $lastmod Integer: timestamp of the last item in the recentchanges table
- * @param $timekey String: memcached key of the last modification
- * @param $key String: memcached key of the content
+ * @param string $timekey memcached key of the last modification
+ * @param string $key memcached key of the content
* @return string|bool feed's content on cache hit or false on cache miss
*/
public function loadFromCache( $lastmod, $timekey, $key ) {
@@ -135,7 +135,7 @@ class ChangesFeed {
$feedLastmod = $messageMemc->get( $timekey );
if( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
- /**
+ /**
* If the cached feed was rendered very recently, we may
* go ahead and use it even if there have been edits made
* since it was rendered. This keeps a swarm of requests
diff --git a/includes/ChangesList.php b/includes/ChangesList.php
index 84677124..8461001e 100644
--- a/includes/ChangesList.php
+++ b/includes/ChangesList.php
@@ -30,7 +30,7 @@
*/
class RCCacheEntry extends RecentChange {
var $secureName, $link;
- var $curlink , $difflink, $lastlink, $usertalklink, $versionlink;
+ var $curlink, $difflink, $lastlink, $usertalklink, $versionlink;
var $userlink, $timestamp, $watched;
/**
@@ -60,7 +60,7 @@ class ChangesList extends ContextSource {
protected $message;
/**
- * Changeslist contructor
+ * Changeslist constructor
*
* @param $obj Skin or IContextSource
*/
@@ -80,7 +80,7 @@ class ChangesList extends ContextSource {
* This first argument used to be an User object.
*
* @deprecated in 1.18; use newFromContext() instead
- * @param $unused string|User Unused
+ * @param string|User $unused Unused
* @return ChangesList|EnhancedChangesList|OldChangesList derivative
*/
public static function newFromUser( $unused ) {
@@ -130,13 +130,13 @@ class ChangesList extends ContextSource {
/**
* Returns the appropriate flags for new page, minor change and patrolling
- * @param $flags Array Associative array of 'flag' => Bool
- * @param $nothing String to use for empty space
+ * @param array $flags Associative array of 'flag' => Bool
+ * @param string $nothing to use for empty space
* @return String
*/
protected function recentChangesFlags( $flags, $nothing = '&#160;' ) {
$f = '';
- foreach( array( 'newpage', 'minor', 'bot', 'unpatrolled' ) as $flag ){
+ foreach( array( 'newpage', 'minor', 'bot', 'unpatrolled' ) as $flag ) {
$f .= isset( $flags[$flag] ) && $flags[$flag]
? self::flag( $flag )
: $nothing;
@@ -150,7 +150,7 @@ class ChangesList extends ContextSource {
* unpatrolled edit. By default in English it will contain "N", "m", "b",
* "!" respectively, plus it will have an appropriate title and class.
*
- * @param $flag String: 'newpage', 'unpatrolled', 'minor', or 'bot'
+ * @param string $flag 'newpage', 'unpatrolled', 'minor', or 'bot'
* @return String: Raw HTML
*/
public static function flag( $flag ) {
@@ -217,7 +217,7 @@ class ChangesList extends ContextSource {
$lang = $context->getLanguage();
$code = $lang->getCode();
static $fastCharDiff = array();
- if ( !isset($fastCharDiff[$code]) ) {
+ if ( !isset( $fastCharDiff[$code] ) ) {
$fastCharDiff[$code] = $wgMiserMode || $context->msg( 'rc-change-size' )->plain() === '$1';
}
@@ -286,6 +286,10 @@ class ChangesList extends ContextSource {
}
}
+ /**
+ * @param string $s HTML to update
+ * @param $rc_timestamp mixed
+ */
public function insertDateHeader( &$s, $rc_timestamp ) {
# Make date header if necessary
$date = $this->getLanguage()->userDate( $rc_timestamp, $this->getUser() );
@@ -299,6 +303,11 @@ class ChangesList extends ContextSource {
}
}
+ /**
+ * @param string $s HTML to update
+ * @param $title Title
+ * @param $logtype string
+ */
public function insertLog( &$s, $title, $logtype ) {
$page = new LogPage( $logtype );
$logname = $page->getName()->escaped();
@@ -306,7 +315,7 @@ class ChangesList extends ContextSource {
}
/**
- * @param $s
+ * @param string $s HTML to update
* @param $rc RecentChange
* @param $unpatrolled
*/
@@ -319,7 +328,7 @@ class ChangesList extends ContextSource {
} else {
$query = array(
'curid' => $rc->mAttribs['rc_cur_id'],
- 'diff' => $rc->mAttribs['rc_this_oldid'],
+ 'diff' => $rc->mAttribs['rc_this_oldid'],
'oldid' => $rc->mAttribs['rc_last_oldid']
);
@@ -349,7 +358,7 @@ class ChangesList extends ContextSource {
}
/**
- * @param $s
+ * @param string $s HTML to update
* @param $rc RecentChange
* @param $unpatrolled
* @param $watched
@@ -369,7 +378,7 @@ class ChangesList extends ContextSource {
array( 'class' => 'mw-changeslist-title' ),
$params
);
- if( $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
+ if( $this->isDeleted( $rc, Revision::DELETED_TEXT ) ) {
$articlelink = '<span class="history-deleted">' . $articlelink . '</span>';
}
# To allow for boldening pages watched by this user
@@ -378,21 +387,34 @@ class ChangesList extends ContextSource {
$articlelink .= $this->getLanguage()->getDirMark();
wfRunHooks( 'ChangesListInsertArticleLink',
- array(&$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched) );
+ array( &$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched ) );
$s .= " $articlelink";
}
/**
- * @param $s
+ * Get the timestamp from $rc formatted with current user's settings
+ * and a separator
+ *
* @param $rc RecentChange
+ * @return string HTML fragment
*/
- public function insertTimestamp( &$s, $rc ) {
- $s .= $this->message['semicolon-separator'] . '<span class="mw-changeslist-date">' .
+ public function getTimestamp( $rc ) {
+ return $this->message['semicolon-separator'] . '<span class="mw-changeslist-date">' .
$this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() ) . '</span> <span class="mw-changeslist-separator">. .</span> ';
}
/**
+ * Insert time timestamp string from $rc into $s
+ *
+ * @param string $s HTML to update
+ * @param $rc RecentChange
+ */
+ public function insertTimestamp( &$s, $rc ) {
+ $s .= $this->getTimestamp( $rc );
+ }
+
+ /**
* Insert links to user page, user talk page and eventually a blocking link
*
* @param &$s String HTML to update
@@ -435,6 +457,7 @@ class ChangesList extends ContextSource {
return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
}
}
+ return '';
}
/**
@@ -511,15 +534,15 @@ class ChangesList extends ContextSource {
$page = $rc->getTitle();
/** Check for rollback and edit permissions, disallow special pages, and only
* show a link on the top-most revision */
- if ( $this->getUser()->isAllowed('rollback') && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid'] )
+ if ( $this->getUser()->isAllowed( 'rollback' ) && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid'] )
{
$rev = new Revision( array(
- 'id' => $rc->mAttribs['rc_this_oldid'],
- 'user' => $rc->mAttribs['rc_user'],
+ 'title' => $page,
+ 'id' => $rc->mAttribs['rc_this_oldid'],
+ 'user' => $rc->mAttribs['rc_user'],
'user_text' => $rc->mAttribs['rc_user_text'],
- 'deleted' => $rc->mAttribs['rc_deleted']
+ 'deleted' => $rc->mAttribs['rc_deleted']
) );
- $rev->setTitle( $page );
$s .= ' '.Linker::generateRollback( $rev, $this->getContext() );
}
}
@@ -531,16 +554,16 @@ class ChangesList extends ContextSource {
* @param $classes
*/
public function insertTags( &$s, &$rc, &$classes ) {
- if ( empty($rc->mAttribs['ts_tags']) )
+ if ( empty( $rc->mAttribs['ts_tags'] ) )
return;
- list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow( $rc->mAttribs['ts_tags'], 'changeslist' );
+ list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow( $rc->mAttribs['ts_tags'], 'changeslist' );
$classes = array_merge( $classes, $newClasses );
$s .= ' ' . $tagSummary;
}
public function insertExtra( &$s, &$rc, &$classes ) {
- ## Empty, used for subclassers to add anything special.
+ // Empty, used for subclasses to add anything special.
}
protected function showAsUnpatrolled( RecentChange $rc ) {
@@ -556,7 +579,6 @@ class ChangesList extends ContextSource {
}
}
-
/**
* Generate a list of changes using the good old system (no javascript)
*/
@@ -565,9 +587,10 @@ class OldChangesList extends ChangesList {
* Format a line using the old system (aka without any javascript).
*
* @param $rc RecentChange, passed by reference
- * @param $watched Bool (default false)
- * @param $linenumber Int (default null)
- * @return string
+ * @param bool $watched (default false)
+ * @param int $linenumber (default null)
+ *
+ * @return string|bool
*/
public function recentChangesLine( &$rc, $watched = false, $linenumber = null ) {
global $wgRCShowChangedSize;
@@ -655,17 +678,19 @@ class OldChangesList extends ChangesList {
}
if( $this->watchlist ) {
- $classes[] = Sanitizer::escapeClass( 'watchlist-'.$rc->mAttribs['rc_namespace'].'-'.$rc->mAttribs['rc_title'] );
+ $classes[] = Sanitizer::escapeClass( 'watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
}
- wfRunHooks( 'OldChangesListRecentChangesLine', array(&$this, &$s, $rc) );
+ if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$s, $rc, &$classes ) ) ) {
+ wfProfileOut( __METHOD__ );
+ return false;
+ }
wfProfileOut( __METHOD__ );
- return "$dateheader<li class=\"".implode( ' ', $classes )."\">".$s."</li>\n";
+ return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $s . "</li>\n";
}
}
-
/**
* Generate a list of changes using an Enhanced system (uses javascript).
*/
@@ -795,7 +820,7 @@ class EnhancedChangesList extends ChangesList {
$lastLink = $this->message['last'];
} else {
$lastLink = Linker::linkKnown( $rc->getTitle(), $this->message['last'],
- array(), $curIdEq + array('diff' => $thisOldid, 'oldid' => $lastOldid) + $rcIdQuery );
+ array(), $curIdEq + array( 'diff' => $thisOldid, 'oldid' => $lastOldid ) + $rcIdQuery );
}
# Make user links
@@ -807,7 +832,7 @@ class EnhancedChangesList extends ChangesList {
}
$rc->lastlink = $lastLink;
- $rc->curlink = $curLink;
+ $rc->curlink = $curLink;
$rc->difflink = $diffLink;
# Put accumulated information into the cache, for later display
@@ -816,10 +841,10 @@ class EnhancedChangesList extends ChangesList {
$secureName = $title->getPrefixedDBkey();
if( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
# Use an @ character to prevent collision with page names
- $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
+ $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array( $rc );
} else {
# Logs are grouped by type
- if( $type == RC_LOG ){
+ if( $type == RC_LOG ) {
$secureName = SpecialPage::getTitleFor( 'Log', $logType )->getPrefixedDBkey();
}
if( !isset( $this->rc_cache[$secureName] ) ) {
@@ -862,6 +887,8 @@ class EnhancedChangesList extends ChangesList {
# Other properties
$unpatrolled = false;
$isnew = false;
+ $allBots = true;
+ $allMinors = true;
$curId = $currentRevision = 0;
# Some catalyst variables...
$namehidden = true;
@@ -895,7 +922,13 @@ class EnhancedChangesList extends ChangesList {
$currentRevision = $rcObj->mAttribs['rc_this_oldid'];
}
- $bot = $rcObj->mAttribs['rc_bot'];
+ if( !$rcObj->mAttribs['rc_bot'] ) {
+ $allBots = false;
+ }
+ if( !$rcObj->mAttribs['rc_minor'] ) {
+ $allMinors = false;
+ }
+
$userlinks[$u]++;
}
@@ -917,19 +950,19 @@ class EnhancedChangesList extends ChangesList {
implode( $this->message['semicolon-separator'], $users )
)->escaped() . '</span>';
- $tl = '<span class="mw-collapsible-toggle mw-enhancedchanges-arrow"></span>';
+ $tl = '<span class="mw-collapsible-toggle mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>';
$r .= "<td>$tl</td>";
# Main line
$r .= '<td class="mw-enhanced-rc">' . $this->recentChangesFlags( array(
- 'newpage' => $isnew,
- 'minor' => false,
- 'unpatrolled' => $unpatrolled,
- 'bot' => $bot ,
+ 'newpage' => $isnew, # show, when one have this flag
+ 'minor' => $allMinors, # show only, when all have this flag
+ 'unpatrolled' => $unpatrolled, # show, when one have this flag
+ 'bot' => $allBots, # show only, when all have this flag
) );
# Timestamp
- $r .= '&#160;'.$block[0]->timestamp.'&#160;</td><td>';
+ $r .= '&#160;' . $block[0]->timestamp . '&#160;</td><td>';
# Article link
if( $namehidden ) {
@@ -944,7 +977,7 @@ class EnhancedChangesList extends ChangesList {
$queryParams['curid'] = $curId;
# Changes message
- $n = count($block);
+ $n = count( $block );
static $nchanges = array();
if ( !isset( $nchanges[$n] ) ) {
$nchanges[$n] = $this->msg( 'nchanges' )->numParams( $n )->escaped();
@@ -999,7 +1032,7 @@ class EnhancedChangesList extends ChangesList {
# Character difference (does not apply if only log items)
if( $wgRCShowChangedSize && !$allLogs ) {
$last = 0;
- $first = count($block) - 1;
+ $first = count( $block ) - 1;
# Some events (like logs) have an "empty" size, so we need to skip those...
while( $last < $first && $block[$last]->mAttribs['rc_new_len'] === null ) {
$last++;
@@ -1018,7 +1051,7 @@ class EnhancedChangesList extends ChangesList {
}
$r .= $users;
- $r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers);
+ $r .= $this->numberofWatchingusers( $block[0]->numberofWatchingusers );
# Sub-entries
foreach( $block as $rcObj ) {
@@ -1046,7 +1079,7 @@ class EnhancedChangesList extends ChangesList {
$link = $rcObj->timestamp;
# Revision link
} elseif( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ) {
- $link = '<span class="history-deleted">'.$rcObj->timestamp.'</span> ';
+ $link = '<span class="history-deleted">' . $rcObj->timestamp . '</span> ';
} else {
if ( $rcObj->unpatrolled && $type == RC_NEW) {
$params['rcid'] = $rcObj->mAttribs['rc_id'];
@@ -1058,8 +1091,9 @@ class EnhancedChangesList extends ChangesList {
array(),
$params
);
- if( $this->isDeleted($rcObj,Revision::DELETED_TEXT) )
- $link = '<span class="history-deleted">'.$link.'</span> ';
+ if( $this->isDeleted( $rcObj, Revision::DELETED_TEXT ) ) {
+ $link = '<span class="history-deleted">' . $link . '</span> ';
+ }
}
$r .= $link . '</span>';
@@ -1103,12 +1137,12 @@ class EnhancedChangesList extends ChangesList {
/**
* Generate HTML for an arrow or placeholder graphic
- * @param $dir String: one of '', 'd', 'l', 'r'
- * @param $alt String: text
- * @param $title String: text
+ * @param string $dir one of '', 'd', 'l', 'r'
+ * @param string $alt text
+ * @param string $title text
* @return String: HTML "<img>" tag
*/
- protected function arrow( $dir, $alt='', $title='' ) {
+ protected function arrow( $dir, $alt = '', $title = '' ) {
global $wgStylePath;
$encUrl = htmlspecialchars( $wgStylePath . '/common/images/Arr_' . $dir . '.png' );
$encAlt = htmlspecialchars( $alt );
@@ -1170,7 +1204,7 @@ class EnhancedChangesList extends ChangesList {
$r = Html::openElement( 'table', array( 'class' => $classes ) ) .
Html::openElement( 'tr' );
- $r .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>';
+ $r .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>';
# Flag and Timestamp
if( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
$r .= '&#160;&#160;&#160;&#160;'; // 4 flags -> 4 spaces
@@ -1182,7 +1216,7 @@ class EnhancedChangesList extends ChangesList {
'bot' => $rcObj->mAttribs['rc_bot'],
) );
}
- $r .= '&#160;'.$rcObj->timestamp.'&#160;</td><td>';
+ $r .= '&#160;' . $rcObj->timestamp . '&#160;</td><td>';
# Article or log link
if( $logType ) {
$logPage = new LogPage( $logType );
@@ -1214,7 +1248,7 @@ class EnhancedChangesList extends ChangesList {
if ( $type == RC_LOG ) {
$r .= $this->insertLogEntry( $rcObj );
} else {
- $r .= ' '.$rcObj->userlink . $rcObj->usertalklink;
+ $r .= ' ' . $rcObj->userlink . $rcObj->usertalklink;
$r .= $this->insertComment( $rcObj );
$this->insertRollback( $r, $rcObj );
}
@@ -1222,7 +1256,7 @@ class EnhancedChangesList extends ChangesList {
# Tags
$this->insertTags( $r, $rcObj, $classes );
# Show how many people are watching this if enabled
- $r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers);
+ $r .= $this->numberofWatchingusers( $rcObj->numberofWatchingusers );
$r .= "</td></tr></table>\n";
@@ -1255,7 +1289,7 @@ class EnhancedChangesList extends ChangesList {
wfProfileOut( __METHOD__ );
- return '<div>'.$blockOut.'</div>';
+ return '<div>' . $blockOut . '</div>';
}
/**
diff --git a/includes/Collation.php b/includes/Collation.php
index ad2b94b1..6bba019b 100644
--- a/includes/Collation.php
+++ b/includes/Collation.php
@@ -48,8 +48,12 @@ abstract class Collation {
case 'uca-default':
return new IcuCollation( 'root' );
default:
- # Provide a mechanism for extensions to hook in.
+ $match = array();
+ if ( preg_match( '/^uca-([a-z-]+)$/', $collationName, $match ) ) {
+ return new IcuCollation( $match[1] );
+ }
+ # Provide a mechanism for extensions to hook in.
$collationObject = null;
wfRunHooks( 'Collation::factory', array( $collationName, &$collationObject ) );
@@ -144,18 +148,19 @@ class IdentityCollation extends Collation {
}
}
-
class IcuCollation extends Collation {
+ const FIRST_LETTER_VERSION = 1;
+
var $primaryCollator, $mainCollator, $locale;
var $firstLetterData;
/**
* Unified CJK blocks.
*
- * The same definition of a CJK block must be used for both Collation and
- * generateCollationData.php. These blocks are omitted from the first
- * letter data, as an optimisation measure and because the default UCA table
- * is pretty useless for sorting Chinese text anyway. Japanese and Korean
+ * The same definition of a CJK block must be used for both Collation and
+ * generateCollationData.php. These blocks are omitted from the first
+ * letter data, as an optimisation measure and because the default UCA table
+ * is pretty useless for sorting Chinese text anyway. Japanese and Korean
* blocks are not included here, because they are smaller and more useful.
*/
static $cjkBlocks = array(
@@ -176,11 +181,105 @@ class IcuCollation extends Collation {
array( 0x2F800, 0x2FA1F ), // CJK Compatibility Ideographs Supplement
);
+ /**
+ * Additional characters (or character groups) to be considered separate
+ * letters for given languages, or to be removed from the list of such
+ * letters (denoted by keys starting with '-').
+ *
+ * These are additions to (or subtractions from) the data stored in the
+ * first-letters-root.ser file (which among others includes full basic latin,
+ * cyrillic and greek alphabets).
+ *
+ * "Separate letter" is a letter that would have a separate heading/section
+ * for it in a dictionary or a phone book in this language. This data isn't
+ * used for sorting (the ICU library handles that), only for deciding which
+ * characters (or character groups) to use as headings.
+ *
+ * Initially generated based on the primary level of Unicode collation
+ * tailorings available at http://developer.mimer.com/charts/tailorings.htm ,
+ * later modified.
+ *
+ * Empty arrays are intended; this signifies that the data for the language is
+ * available and that there are, in fact, no additional letters to consider.
+ */
+ static $tailoringFirstLetters = array(
+ // Verified by native speakers
+ 'be' => array( "Ё" ),
+ 'be-tarask' => array( "Ё" ),
+ 'en' => array(),
+ 'fi' => array( "Å", "Ä", "Ö" ),
+ 'hu' => array( "Cs", "Dz", "Dzs", "Gy", "Ly", "Ny", "Ö", "Sz", "Ty", "Ü", "Zs" ),
+ 'it' => array(),
+ 'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
+ 'pt' => array(),
+ 'ru' => array(),
+ 'sv' => array( "Å", "Ä", "Ö" ),
+ 'uk' => array( "Ґ", "Ь" ),
+ 'vi' => array( "Ă", "Â", "Đ", "Ê", "Ô", "Ơ", "Ư" ),
+ // Not verified, but likely correct
+ 'af' => array(),
+ 'ast' => array( "Ch", "Ll", "Ñ" ),
+ 'az' => array( "Ç", "Ə", "Ğ", "İ", "Ö", "Ş", "Ü" ),
+ 'bg' => array(),
+ 'br' => array( "Ch", "C'h" ),
+ 'bs' => array( "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ),
+ 'ca' => array(),
+ 'co' => array(),
+ 'cs' => array( "Č", "Ch", "Ř", "Š", "Ž" ),
+ 'cy' => array( "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ),
+ 'da' => array( "Æ", "Ø", "Å" ),
+ 'de' => array(),
+ 'dsb' => array( "Č", "Ć", "Dź", "Ě", "Ch", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ),
+ 'el' => array(),
+ 'eo' => array( "Ĉ", "Ĝ", "Ĥ", "Ĵ", "Ŝ", "Ŭ" ),
+ 'es' => array( "Ñ" ),
+ 'et' => array( "Š", "Ž", "Õ", "Ä", "Ö", "Ü" ),
+ 'eu' => array( "Ñ" ),
+ 'fo' => array( "Á", "Ð", "Í", "Ó", "Ú", "Ý", "Æ", "Ø", "Å" ),
+ 'fr' => array(),
+ 'fur' => array( "À", "Á", "Â", "È", "Ì", "Ò", "Ù" ),
+ 'fy' => array(),
+ 'ga' => array(),
+ 'gd' => array(),
+ 'gl' => array( "Ch", "Ll", "Ñ" ),
+ 'hr' => array( "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ),
+ 'hsb' => array( "Č", "Dź", "Ě", "Ch", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ),
+ 'is' => array( "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ),
+ 'kk' => array( "Ү", "І" ),
+ 'kl' => array( "Æ", "Ø", "Å" ),
+ 'ku' => array( "Ç", "Ê", "Î", "Ş", "Û" ),
+ 'ky' => array( "Ё" ),
+ 'la' => array(),
+ 'lb' => array(),
+ 'lt' => array( "Č", "Š", "Ž" ),
+ 'lv' => array( "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ),
+ 'mk' => array(),
+ 'mo' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
+ 'mt' => array( "Ċ", "Ġ", "Għ", "Ħ", "Ż" ),
+ 'nl' => array(),
+ 'no' => array( "Æ", "Ø", "Å" ),
+ 'oc' => array(),
+ 'rm' => array(),
+ 'ro' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
+ 'rup' => array( "Ă", "Â", "Î", "Ľ", "Ń", "Ş", "Ţ" ),
+ 'sco' => array(),
+ 'sk' => array( "Ä", "Č", "Ch", "Ô", "Š", "Ž" ),
+ 'sl' => array( "Č", "Š", "Ž" ),
+ 'smn' => array( "Á", "Č", "Đ", "Ŋ", "Š", "Ŧ", "Ž", "Æ", "Ø", "Å", "Ä", "Ö" ),
+ 'sq' => array( "Ç", "Dh", "Ë", "Gj", "Ll", "Nj", "Rr", "Sh", "Th", "Xh", "Zh" ),
+ 'sr' => array(),
+ 'tk' => array( "Ç", "Ä", "Ž", "Ň", "Ö", "Ş", "Ü", "Ý" ),
+ 'tl' => array( "Ñ", "Ng" ),
+ 'tr' => array( "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ),
+ 'tt' => array( "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ),
+ 'uz' => array( "Ch", "G'", "Ng", "O'", "Sh" ),
+ );
+
const RECORD_LENGTH = 14;
function __construct( $locale ) {
if ( !extension_loaded( 'intl' ) ) {
- throw new MWException( 'An ICU collation was requested, ' .
+ throw new MWException( 'An ICU collation was requested, ' .
'but the intl extension is not available.' );
}
$this->locale = $locale;
@@ -218,8 +317,8 @@ class IcuCollation extends Collation {
// Check for CJK
$firstChar = mb_substr( $string, 0, 1, 'UTF-8' );
- if ( ord( $firstChar ) > 0x7f
- && self::isCjk( utf8ToCodepoint( $firstChar ) ) )
+ if ( ord( $firstChar ) > 0x7f
+ && self::isCjk( utf8ToCodepoint( $firstChar ) ) )
{
return $firstChar;
}
@@ -249,25 +348,37 @@ class IcuCollation extends Collation {
$cacheKey = wfMemcKey( 'first-letters', $this->locale );
$cacheEntry = $cache->get( $cacheKey );
- if ( $cacheEntry ) {
+ if ( $cacheEntry && isset( $cacheEntry['version'] )
+ && $cacheEntry['version'] == self::FIRST_LETTER_VERSION )
+ {
$this->firstLetterData = $cacheEntry;
return $this->firstLetterData;
}
// Generate data from serialized data file
- $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
- if ( $letters === false ) {
- throw new MWException( "MediaWiki does not support ICU locale " .
- "\"{$this->locale}\"" );
+ if ( isset ( self::$tailoringFirstLetters[$this->locale] ) ) {
+ $letters = wfGetPrecompiledData( "first-letters-root.ser" );
+ // Append additional characters
+ $letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
+ // Remove unnecessary ones, if any
+ if ( isset( self::$tailoringFirstLetters[ '-' . $this->locale ] ) ) {
+ $letters = array_diff( $letters, self::$tailoringFirstLetters[ '-' . $this->locale ] );
+ }
+ } else {
+ $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
+ if ( $letters === false ) {
+ throw new MWException( "MediaWiki does not support ICU locale " .
+ "\"{$this->locale}\"" );
+ }
}
// Sort the letters.
//
// It's impossible to have the precompiled data file properly sorted,
- // because the sort order changes depending on ICU version. If the
- // array is not properly sorted, the binary search will return random
- // results.
+ // because the sort order changes depending on ICU version. If the
+ // array is not properly sorted, the binary search will return random
+ // results.
//
// We also take this opportunity to remove primary collisions.
$letterMap = array();
@@ -284,9 +395,76 @@ class IcuCollation extends Collation {
}
}
ksort( $letterMap, SORT_STRING );
+ // Remove duplicate prefixes. Basically if something has a sortkey
+ // which is a prefix of some other sortkey, then it is an
+ // expansion and probably should not be considered a section
+ // header.
+ //
+ // For example 'þ' is sometimes sorted as if it is the letters
+ // 'th'. Other times it is its own primary element. Another
+ // example is '₨'. Sometimes its a currency symbol. Sometimes it
+ // is an 'R' followed by an 's'.
+ //
+ // Additionally an expanded element should always sort directly
+ // after its first element due to they way sortkeys work.
+ //
+ // UCA sortkey elements are of variable length but no collation
+ // element should be a prefix of some other element, so I think
+ // this is safe. See:
+ // * https://ssl.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm
+ // * http://site.icu-project.org/design/collation/uca-weight-allocation
+ //
+ // Additionally, there is something called primary compression to
+ // worry about. Basically, if you have two primary elements that
+ // are more than one byte and both start with the same byte then
+ // the first byte is dropped on the second primary. Additionally
+ // either \x03 or \xFF may be added to mean that the next primary
+ // does not start with the first byte of the first primary.
+ //
+ // This shouldn't matter much, as the first primary is not
+ // changed, and that is what we are comparing against.
+ //
+ // tl;dr: This makes some assumptions about how icu implements
+ // collations. It seems incredibly unlikely these assumptions
+ // will change, but nonetheless they are assumptions.
+
+ $prev = false;
+ $duplicatePrefixes = array();
+ foreach( $letterMap as $key => $value ) {
+ // Remove terminator byte. Otherwise the prefix
+ // comparison will get hung up on that.
+ $trimmedKey = rtrim( $key, "\0" );
+ if ( $prev === false || $prev === '' ) {
+ $prev = $trimmedKey;
+ // We don't yet have a collation element
+ // to compare against, so continue.
+ continue;
+ }
+
+ // Due to the fact the array is sorted, we only have
+ // to compare with the element directly previous
+ // to the current element (skipping expansions).
+ // An element "X" will always sort directly
+ // before "XZ" (Unless we have "XY", but we
+ // do not update $prev in that case).
+ if ( substr( $trimmedKey, 0, strlen( $prev ) ) === $prev ) {
+ $duplicatePrefixes[] = $key;
+ // If this is an expansion, we don't want to
+ // compare the next element to this element,
+ // but to what is currently $prev
+ continue;
+ }
+ $prev = $trimmedKey;
+ }
+ foreach( $duplicatePrefixes as $badKey ) {
+ wfDebug( "Removing '{$letterMap[$badKey]}' from first letters." );
+ unset( $letterMap[$badKey] );
+ // This code assumes that unsetting does not change sort order.
+ }
$data = array(
'chars' => array_values( $letterMap ),
- 'keys' => array_keys( $letterMap )
+ 'keys' => array_keys( $letterMap ),
+ 'version' => self::FIRST_LETTER_VERSION,
);
// Reduce memory usage before caching
@@ -320,23 +498,27 @@ class IcuCollation extends Collation {
}
/**
- * Do a binary search, and return the index of the largest item that sorts
+ * Do a binary search, and return the index of the largest item that sorts
* less than or equal to the target value.
*
- * @param $valueCallback array A function to call to get the value with
+ * @param array $valueCallback A function to call to get the value with
* a given array index.
- * @param $valueCount int The number of items accessible via $valueCallback,
+ * @param int $valueCount The number of items accessible via $valueCallback,
* indexed from 0 to $valueCount - 1
- * @param $comparisonCallback array A callback to compare two values, returning
+ * @param array $comparisonCallback A callback to compare two values, returning
* -1, 0 or 1 in the style of strcmp().
- * @param $target string The target value to find.
+ * @param string $target The target value to find.
*
* @return int|bool The item index of the lower bound, or false if the target value
* sorts before all items.
*/
function findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target ) {
+ if ( $valueCount === 0 ) {
+ return false;
+ }
+
$min = 0;
- $max = $valueCount - 1;
+ $max = $valueCount;
do {
$mid = $min + ( ( $max - $min ) >> 1 );
$item = call_user_func( $valueCallback, $mid );
@@ -351,12 +533,15 @@ class IcuCollation extends Collation {
}
} while ( $min < $max - 1 );
- if ( $min == 0 && $max == 0 && $comparison > 0 ) {
- // Before the first item
- return false;
- } else {
- return $min;
+ if ( $min == 0 ) {
+ $item = call_user_func( $valueCallback, $min );
+ $comparison = call_user_func( $comparisonCallback, $target, $item );
+ if ( $comparison < 0 ) {
+ // Before the first item
+ return false;
+ }
}
+ return $min;
}
static function isCjk( $codepoint ) {
@@ -367,5 +552,55 @@ class IcuCollation extends Collation {
}
return false;
}
-}
+ /**
+ * Return the version of ICU library used by PHP's intl extension,
+ * or false when the extension is not installed of the version
+ * can't be determined.
+ *
+ * The constant INTL_ICU_VERSION this function refers to isn't really
+ * documented. It is available since PHP 5.3.7 (see PHP bug 54561).
+ * This function will return false on older PHPs.
+ *
+ * @since 1.21
+ * @return string|false
+ */
+ static function getICUVersion() {
+ return defined( 'INTL_ICU_VERSION' ) ? INTL_ICU_VERSION : false;
+ }
+
+ /**
+ * Return the version of Unicode appropriate for the version of ICU library
+ * currently in use, or false when it can't be determined.
+ *
+ * @since 1.21
+ * @return string|false
+ */
+ static function getUnicodeVersionForICU() {
+ $icuVersion = IcuCollation::getICUVersion();
+ if ( !$icuVersion ) {
+ return false;
+ }
+
+ $versionPrefix = substr( $icuVersion, 0, 3 );
+ // Source: http://site.icu-project.org/download
+ $map = array(
+ '50.' => '6.2',
+ '49.' => '6.1',
+ '4.8' => '6.0',
+ '4.6' => '6.0',
+ '4.4' => '5.2',
+ '4.2' => '5.1',
+ '4.0' => '5.1',
+ '3.8' => '5.0',
+ '3.6' => '5.0',
+ '3.4' => '4.1',
+ );
+
+ if ( isset( $map[$versionPrefix] ) ) {
+ return $map[$versionPrefix];
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/includes/ConfEditor.php b/includes/ConfEditor.php
index b68fc762..1d9ca921 100644
--- a/includes/ConfEditor.php
+++ b/includes/ConfEditor.php
@@ -66,7 +66,6 @@ class ConfEditor {
*/
var $stateStack;
-
/**
* The path stack is a stack of associative arrays with the following elements:
* name The name of top level of the path
@@ -128,7 +127,7 @@ class ConfEditor {
/**
* Edit the text. Returns the edited text.
- * @param $ops Array of operations.
+ * @param array $ops of operations.
*
* Operations are given as an associative array, with members:
* type: One of delete, set, append or insert (required)
@@ -159,6 +158,7 @@ class ConfEditor {
* insert
* Insert a new element at the start of the array.
*
+ * @throws MWException
* @return string
*/
public function edit( $ops ) {
@@ -306,7 +306,7 @@ class ConfEditor {
* setVar( $arr, 'foo/bar', 'baz', 3 ); will set
* $arr['foo']['bar']['baz'] = 3;
* @param $array array
- * @param $path string slash-delimited path
+ * @param string $path slash-delimited path
* @param $key mixed Key
* @param $value mixed Value
*/
@@ -392,6 +392,8 @@ class ConfEditor {
* Finds the source byte region which you would want to delete, if $pathName
* was to be deleted. Includes the leading spaces and tabs, the trailing line
* break, and any comments in between.
+ * @param $pathName
+ * @throws MWException
* @return array
*/
function findDeletionRegion( $pathName ) {
@@ -450,6 +452,8 @@ class ConfEditor {
* or semicolon.
*
* The end position is the past-the-end (end + 1) value as per convention.
+ * @param $pathName
+ * @throws MWException
* @return array
*/
function findValueRegion( $pathName ) {
@@ -1055,6 +1059,7 @@ class ConfEditorParseError extends MWException {
return "$line\n" .str_repeat( ' ', $this->colNum - 1 ) . "^\n";
}
}
+ return '';
}
}
@@ -1089,4 +1094,3 @@ class ConfEditorToken {
return $this->type == 'END';
}
}
-
diff --git a/includes/Cookie.php b/includes/Cookie.php
index 7984d63e..27a85072 100644
--- a/includes/Cookie.php
+++ b/includes/Cookie.php
@@ -40,14 +40,15 @@ class Cookie {
/**
* Sets a cookie. Used before a request to set up any individual
- * cookies. Used internally after a request to parse the
+ * cookies. Used internally after a request to parse the
* Set-Cookie headers.
*
- * @param $value String: the value of the cookie
- * @param $attr Array: possible key/values:
- * expires A date string
- * path The path this cookie is used on
- * domain Domain this cookie is used on
+ * @param string $value the value of the cookie
+ * @param array $attr possible key/values:
+ * expires A date string
+ * path The path this cookie is used on
+ * domain Domain this cookie is used on
+ * @throws MWException
*/
public function set( $value, $attr ) {
$this->value = $value;
@@ -83,8 +84,8 @@ class Cookie {
* @todo fixme fails to detect 3-letter top-level domains
* @todo fixme fails to detect 2-letter top-level domains for single-domain use (probably not a big problem in practice, but there are test cases)
*
- * @param $domain String: the domain to validate
- * @param $originDomain String: (optional) the domain the cookie originates from
+ * @param string $domain the domain to validate
+ * @param string $originDomain (optional) the domain the cookie originates from
* @return Boolean
*/
public static function validateCookieDomain( $domain, $originDomain = null ) {
@@ -112,7 +113,7 @@ class Cookie {
}
// Don't allow cookies for "co.uk" or "gov.uk", etc, but allow "supermarket.uk"
- if ( strrpos( $domain, "." ) - strlen( $domain ) == -3 ) {
+ if ( strrpos( $domain, "." ) - strlen( $domain ) == -3 ) {
if ( ( count( $dc ) == 2 && strlen( $dc[0] ) <= 2 )
|| ( count( $dc ) == 3 && strlen( $dc[0] ) == "" && strlen( $dc[1] ) <= 2 ) ) {
return false;
@@ -141,8 +142,8 @@ class Cookie {
/**
* Serialize the cookie jar into a format useful for HTTP Request headers.
*
- * @param $path String: the path that will be used. Required.
- * @param $domain String: the domain that will be used. Required.
+ * @param string $path the path that will be used. Required.
+ * @param string $domain the domain that will be used. Required.
* @return String
*/
public function serializeToHttpRequest( $path, $domain ) {
@@ -164,8 +165,8 @@ class Cookie {
protected function canServeDomain( $domain ) {
if ( $domain == $this->domain
|| ( strlen( $domain ) > strlen( $this->domain )
- && substr( $this->domain, 0, 1 ) == '.'
- && substr_compare( $domain, $this->domain, -strlen( $this->domain ),
+ && substr( $this->domain, 0, 1 ) == '.'
+ && substr_compare( $domain, $this->domain, -strlen( $this->domain ),
strlen( $this->domain ), true ) == 0 ) ) {
return true;
}
@@ -193,7 +194,7 @@ class CookieJar {
private $cookie = array();
/**
- * Set a cookie in the cookie jar. Make sure only one cookie per-name exists.
+ * Set a cookie in the cookie jar. Make sure only one cookie per-name exists.
* @see Cookie::set()
*/
public function setCookie ( $name, $value, $attr ) {
@@ -231,7 +232,7 @@ class CookieJar {
* Parse the content of an Set-Cookie HTTP Response header.
*
* @param $cookie String
- * @param $domain String: cookie's domain
+ * @param string $domain cookie's domain
* @return null
*/
public function parseCookieResponseHeader ( $cookie, $domain ) {
diff --git a/includes/CryptRand.php b/includes/CryptRand.php
index 858eebf2..d0305d8b 100644
--- a/includes/CryptRand.php
+++ b/includes/CryptRand.php
@@ -79,7 +79,7 @@ class MWCryptRand {
// Include some information about the filesystem's current state in the random state
$files = array();
- // We know this file is here so grab some info about ourself
+ // We know this file is here so grab some info about ourselves
$files[] = __FILE__;
// We must also have a parent folder, and with the usual file structure, a grandparent
@@ -106,7 +106,11 @@ class MWCryptRand {
}
}
// The absolute filename itself will differ from install to install so don't leave it out
- $state .= realpath( $file );
+ if( ( $path = realpath( $file ) ) !== false ) {
+ $state .= $path;
+ } else {
+ $state .= $file;
+ }
$state .= implode( '', $stat );
} else {
// The fact that the file isn't there is worth at least a
@@ -144,7 +148,7 @@ class MWCryptRand {
/**
* Randomly hash data while mixing in clock drift data for randomness
*
- * @param $data string The data to randomly hash.
+ * @param string $data The data to randomly hash.
* @return String The hashed bytes
* @author Tim Starling
*/
@@ -158,7 +162,7 @@ class MWCryptRand {
$buffer = str_repeat( ' ', $bufLength );
$bufPos = 0;
- // Iterate for $duration seconds or at least $minIerations number of iterations
+ // Iterate for $duration seconds or at least $minIterations number of iterations
$iterations = 0;
$startTime = microtime( true );
$currentTime = $startTime;
@@ -391,7 +395,7 @@ class MWCryptRand {
// We hash the random state with more salt to avoid the state from leaking
// out and being used to predict the /randomness/ that follows.
if ( strlen( $buffer ) < $bytes ) {
- wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
+ wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
}
while ( strlen( $buffer ) < $bytes ) {
wfProfileIn( __METHOD__ . '-fallback' );
@@ -464,8 +468,8 @@ class MWCryptRand {
* You can use MWCryptRand::wasStrong() if you wish to know if the source used
* was cryptographically strong.
*
- * @param $bytes int the number of bytes of random data to generate
- * @param $forceStrong bool Pass true if you want generate to prefer cryptographically
+ * @param int $bytes the number of bytes of random data to generate
+ * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
* strong sources of entropy even if reading from them may steal
* more entropy from the system than optimal.
* @return String Raw binary random data
@@ -480,8 +484,8 @@ class MWCryptRand {
* You can use MWCryptRand::wasStrong() if you wish to know if the source used
* was cryptographically strong.
*
- * @param $chars int the number of hex chars of random data to generate
- * @param $forceStrong bool Pass true if you want generate to prefer cryptographically
+ * @param int $chars the number of hex chars of random data to generate
+ * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
* strong sources of entropy even if reading from them may steal
* more entropy from the system than optimal.
* @return String Hexadecimal random data
diff --git a/includes/DataUpdate.php b/includes/DataUpdate.php
index 377b64c0..c1076b23 100644
--- a/includes/DataUpdate.php
+++ b/includes/DataUpdate.php
@@ -34,7 +34,7 @@ abstract class DataUpdate implements DeferrableUpdate {
/**
* Constructor
*/
- public function __construct( ) {
+ public function __construct() {
# noop
}
@@ -67,15 +67,15 @@ abstract class DataUpdate implements DeferrableUpdate {
*
* This methods supports transactions logic by first calling beginTransaction()
* on all updates in the array, then calling doUpdate() on each, and, if all goes well,
- * then calling commitTransaction() on each update. If an error occurrs,
- * rollbackTransaction() will be called on any update object that had beginTranscation()
+ * then calling commitTransaction() on each update. If an error occurs,
+ * rollbackTransaction() will be called on any update object that had beginTransaction()
* called but not yet commitTransaction().
*
* This allows for limited transactional logic across multiple backends for storing
* secondary data.
*
- * @static
- * @param $updates array a list of DataUpdate instances
+ * @param array $updates a list of DataUpdate instances
+ * @throws Exception|null
*/
public static function runUpdates( $updates ) {
if ( empty( $updates ) ) return; # nothing to do
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 710605ad..9d024c86 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -47,7 +47,7 @@
* This is not a valid entry point, perform no further processing unless
* MEDIAWIKI is defined
*/
-if( !defined( 'MEDIAWIKI' ) ) {
+if ( !defined( 'MEDIAWIKI' ) ) {
echo "This file is part of MediaWiki and is not a valid entry point\n";
die( 1 );
}
@@ -55,13 +55,19 @@ if( !defined( 'MEDIAWIKI' ) ) {
/**
* wgConf hold the site configuration.
* Not used for much in a default install.
+ * @since 1.5
*/
$wgConf = new SiteConfiguration;
-/** MediaWiki version number */
-$wgVersion = '1.20.6';
+/**
+ * MediaWiki version number
+ * @since 1.2
+ */
+$wgVersion = '1.21.1';
-/** Name of the site. It must be changed in LocalSettings.php */
+/**
+ * Name of the site. It must be changed in LocalSettings.php
+ */
$wgSitename = 'MediaWiki';
/**
@@ -87,6 +93,7 @@ $wgServer = WebRequest::detectServer();
* Must be fully qualified, even if $wgServer is protocol-relative.
*
* Defaults to $wgServer, expanded to a fully qualified http:// URL if needed.
+ * @since 1.18
*/
$wgCanonicalServer = false;
@@ -104,7 +111,7 @@ $wgCanonicalServer = false;
* Other paths will be set to defaults based on it unless they are directly
* set in LocalSettings.php
*/
-$wgScriptPath = '/wiki';
+$wgScriptPath = '/wiki';
/**
* Whether to support URLs like index.php/Page_title These often break when PHP
@@ -121,11 +128,11 @@ $wgScriptPath = '/wiki';
* The default $wgArticlePath will be set based on this value at runtime, but if
* you have customized it, having this incorrectly set to true can cause
* redirect loops when "pretty URLs" are used.
+ * @since 1.2.1
*/
-$wgUsePathInfo =
- ( strpos( php_sapi_name(), 'cgi' ) === false ) &&
- ( strpos( php_sapi_name(), 'apache2filter' ) === false ) &&
- ( strpos( php_sapi_name(), 'isapi' ) === false );
+$wgUsePathInfo = ( strpos( PHP_SAPI, 'cgi' ) === false ) &&
+ ( strpos( PHP_SAPI, 'apache2filter' ) === false ) &&
+ ( strpos( PHP_SAPI, 'isapi' ) === false );
/**
* The extension to append to script names by default. This can either be .php
@@ -133,9 +140,9 @@ $wgUsePathInfo =
*
* Some hosting providers use PHP 4 for *.php files, and PHP 5 for *.php5. This
* variable is provided to support those providers.
+ * @since 1.11
*/
-$wgScriptExtension = '.php';
-
+$wgScriptExtension = '.php';
/**@}*/
@@ -176,12 +183,14 @@ $wgRedirectScript = false;
* The URL path to load.php.
*
* Defaults to "{$wgScriptPath}/load{$wgScriptExtension}".
+ * @since 1.17
*/
$wgLoadScript = false;
/**
* The URL path of the skins directory.
* Defaults to "{$wgScriptPath}/skins".
+ * @since 1.3
*/
$wgStylePath = false;
$wgStyleSheetPath = &$wgStylePath;
@@ -189,6 +198,7 @@ $wgStyleSheetPath = &$wgStylePath;
/**
* The URL path of the skins directory. Should not point to an external domain.
* Defaults to "{$wgScriptPath}/skins".
+ * @since 1.17
*/
$wgLocalStylePath = false;
@@ -202,6 +212,7 @@ $wgExtensionAssetsPath = false;
/**
* Filesystem stylesheets directory.
* Defaults to "{$IP}/skins".
+ * @since 1.3
*/
$wgStyleDirectory = false;
@@ -239,12 +250,14 @@ $wgLogo = false;
/**
* The URL path of the shortcut icon.
+ * @since 1.6
*/
$wgFavicon = '/favicon.ico';
/**
* The URL path of the icon for iPhone and iPod Touch web app bookmarks.
* Defaults to no icon.
+ * @since 1.12
*/
$wgAppleTouchIcon = false;
@@ -268,6 +281,7 @@ $wgTmpDirectory = false;
/**
* If set, this URL is added to the start of $wgUploadPath to form a complete
* upload URL.
+ * @since 1.4
*/
$wgUploadBaseUrl = '';
@@ -276,6 +290,7 @@ $wgUploadBaseUrl = '';
* Full thumbnail URL will be like $wgUploadStashScalerBaseUrl/e/e6/Foo.jpg/123px-Foo.jpg
* where 'e6' are the first two characters of the MD5 hash of the file name.
* If $wgUploadStashScalerBaseUrl is set to false, thumbs are rendered locally as needed.
+ * @since 1.17
*/
$wgUploadStashScalerBaseUrl = false;
@@ -291,6 +306,7 @@ $wgUploadStashScalerBaseUrl = false;
*
* There must be an appropriate script or rewrite rule in place to handle these
* URLs.
+ * @since 1.5
*/
$wgActionPaths = array();
@@ -313,6 +329,20 @@ $wgUploadStashMaxAge = 6 * 3600; // 6 hours
$wgAllowImageMoving = true;
/**
+ * Enable deferred upload tasks that use the job queue.
+ * Only enable this if job runners are set up for both the
+ * 'AssembleUploadChunks' and 'PublishStashedFile' job types.
+ */
+$wgEnableAsyncUploads = false;
+
+/**
+ * Allow chunked uploads. This should only really be needed if you
+ * use the UploadWizard extension or allow huge file uploads.
+ * https://www.mediawiki.org/wiki/API:Upload#Chunked_uploading
+ */
+$wgAllowChunkedUploads = false;
+
+/**
* These are additional characters that should be replaced with '-' in filenames
*/
$wgIllegalFileChars = ":";
@@ -353,7 +383,7 @@ $wgImgAuthPublicTest = true;
* FSRepo is also supported for backwards compatibility.
*
* - name A unique name for the repository (but $wgLocalFileRepo should be 'local').
- * The name should consist of alpha-numberic characters.
+ * The name should consist of alpha-numeric characters.
* - backend A file backend name (see $wgFileBackends).
*
* For most core repos:
@@ -361,7 +391,9 @@ $wgImgAuthPublicTest = true;
* container : backend container name the zone is in
* directory : root path within container for the zone
* url : base URL to the root of the zone
- * handlerUrl : base script handled URL to the root of the zone
+ * urlsByExt : map of file extension types to base URLs
+ * (useful for using a different cache for videos)
+ * handlerUrl : base script-handled URL to the root of the zone
* (see FileRepo::getZoneHandlerUrl() function)
* Zones default to using "<repo name>-<zone name>" as the container name
* and default to using the container root as the zone's root directory.
@@ -405,7 +437,7 @@ $wgImgAuthPublicTest = true;
*
* ForeignDBRepo:
* - dbType, dbServer, dbUser, dbPassword, dbName, dbFlags
- * equivalent to the corresponding member of $wgDBservers
+ * equivalent to the corresponding member of $wgDBservers
* - tablePrefix Table prefix, the foreign wiki's $wgDBprefix
* - hasSharedCache True if the wiki's shared cache is accessible via the local $wgMemc
*
@@ -416,7 +448,7 @@ $wgImgAuthPublicTest = true;
* If you leave $wgLocalFileRepo set to false, Setup will fill in appropriate values.
* Otherwise, set $wgLocalFileRepo to a repository structure as described above.
* If you set $wgUseInstantCommons to true, it will add an entry for Commons.
- * If you set $wgForeignFileRepos to an array of repostory structures, those will
+ * If you set $wgForeignFileRepos to an array of repository structures, those will
* be searched after the local file repo.
* Otherwise, you will only have access to local media files.
*
@@ -436,14 +468,34 @@ $wgUseInstantCommons = false;
/**
* File backend structure configuration.
+ *
* This is an array of file backend configuration arrays.
* Each backend configuration has the following parameters:
- * - 'name' : A unique name for the backend
- * - 'class' : The file backend class to use
- * - 'wikiId' : A unique string that identifies the wiki (container prefix)
- * - 'lockManager' : The name of a lock manager (see $wgLockManagers)
- *
- * Additional parameters are specific to the class used.
+ * - 'name' : A unique name for the backend
+ * - 'class' : The file backend class to use
+ * - 'wikiId' : A unique string that identifies the wiki (container prefix)
+ * - 'lockManager' : The name of a lock manager (see $wgLockManagers)
+ *
+ * See FileBackend::__construct() for more details.
+ * Additional parameters are specific to the file backend class used.
+ * These settings should be global to all wikis when possible.
+ *
+ * There are two particularly important aspects about each backend:
+ * - a) Whether it is fully qualified or wiki-relative.
+ * By default, the paths of files are relative to the current wiki,
+ * which works via prefixing them with the current wiki ID when accessed.
+ * Setting 'wikiId' forces the backend to be fully qualified by prefixing
+ * all paths with the specified value instead. This can be useful if
+ * multiple wikis need to share the same data. Note that 'name' is *not*
+ * part of any prefix and thus should not be relied upon for namespacing.
+ * - b) Whether it is only defined for some wikis or is defined on all
+ * wikis in the wiki farm. Defining a backend globally is useful
+ * if multiple wikis need to share the same data.
+ * One should be aware of these aspects when configuring a backend for use with
+ * any basic feature or plugin. For example, suppose an extension stores data for
+ * different wikis in different directories and sometimes needs to access data from
+ * a foreign wiki's directory in order to render a page on given wiki. The extension
+ * would need a fully qualified backend that is defined on all wikis in the wiki farm.
*/
$wgFileBackends = array();
@@ -452,7 +504,10 @@ $wgFileBackends = array();
* Each backend configuration has the following parameters:
* - 'name' : A unique name for the lock manager
* - 'class' : The lock manger class to use
- * Additional parameters are specific to the class used.
+ *
+ * See LockManager::__construct() for more details.
+ * Additional parameters are specific to the lock manager class used.
+ * These settings should be global to all wikis.
*/
$wgLockManagers = array();
@@ -531,6 +586,13 @@ $wgAllowAsyncCopyUploads = false;
$wgCopyUploadsDomains = array();
/**
+ * Enable copy uploads from Special:Upload. $wgAllowCopyUploads must also be
+ * true. If $wgAllowCopyUploads is true, but this is false, you will only be
+ * able to perform copy uploads from the API or extensions (e.g. UploadWizard).
+ */
+$wgCopyUploadsFromSpecialUpload = false;
+
+/**
* Proxy to use for copy upload requests.
* @since 1.20
*/
@@ -553,7 +615,7 @@ $wgCopyUploadProxy = false;
* will have a maximum of 500 kB.
*
*/
-$wgMaxUploadSize = 1024*1024*100; # 100MB
+$wgMaxUploadSize = 1024 * 1024 * 100; # 100MB
/**
* Point the upload navigation link to an external URL
@@ -654,7 +716,7 @@ $wgFileBlacklist = array(
*/
$wgMimeTypeBlacklist = array(
# HTML may contain cookie-stealing JavaScript and web bugs
- 'text/html', 'text/javascript', 'text/x-javascript', 'application/x-shellscript',
+ 'text/html', 'text/javascript', 'text/x-javascript', 'application/x-shellscript',
# PHP scripts may execute arbitrary code on the server
'application/x-php', 'text/x-php',
# Other types that may be interpreted by some servers
@@ -712,10 +774,10 @@ $wgUploadSizeWarning = false;
*/
$wgTrustedMediaFormats = array(
MEDIATYPE_BITMAP, //all bitmap formats
- MEDIATYPE_AUDIO, //all audio formats
- MEDIATYPE_VIDEO, //all plain video formats
- "image/svg+xml", //svg (only needed if inline rendering of svg is not supported)
- "application/pdf", //PDF files
+ MEDIATYPE_AUDIO, //all audio formats
+ MEDIATYPE_VIDEO, //all plain video formats
+ "image/svg+xml", //svg (only needed if inline rendering of svg is not supported)
+ "application/pdf", //PDF files
#"application/x-shockwave-flash", //flash/shockwave movie
);
@@ -724,18 +786,35 @@ $wgTrustedMediaFormats = array(
* Each entry in the array maps a MIME type to a class name
*/
$wgMediaHandlers = array(
- 'image/jpeg' => 'JpegHandler',
- 'image/png' => 'PNGHandler',
- 'image/gif' => 'GIFHandler',
- 'image/tiff' => 'TiffHandler',
+ 'image/jpeg' => 'JpegHandler',
+ 'image/png' => 'PNGHandler',
+ 'image/gif' => 'GIFHandler',
+ 'image/tiff' => 'TiffHandler',
'image/x-ms-bmp' => 'BmpHandler',
- 'image/x-bmp' => 'BmpHandler',
- 'image/x-xcf' => 'XCFHandler',
- 'image/svg+xml' => 'SvgHandler', // official
- 'image/svg' => 'SvgHandler', // compat
+ 'image/x-bmp' => 'BmpHandler',
+ 'image/x-xcf' => 'XCFHandler',
+ 'image/svg+xml' => 'SvgHandler', // official
+ 'image/svg' => 'SvgHandler', // compat
'image/vnd.djvu' => 'DjVuHandler', // official
- 'image/x.djvu' => 'DjVuHandler', // compat
- 'image/x-djvu' => 'DjVuHandler', // compat
+ 'image/x.djvu' => 'DjVuHandler', // compat
+ 'image/x-djvu' => 'DjVuHandler', // compat
+);
+
+/**
+ * Plugins for page content model handling.
+ * Each entry in the array maps a model id to a class name.
+ *
+ * @since 1.21
+ */
+$wgContentHandlers = array(
+ // the usual case
+ CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
+ // dumb version, no syntax highlighting
+ CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
+ // dumb version, no syntax highlighting
+ CONTENT_MODEL_CSS => 'CssContentHandler',
+ // plain text, for use by extensions etc
+ CONTENT_MODEL_TEXT => 'TextContentHandler',
);
/**
@@ -778,6 +857,13 @@ $wgImageMagickTempDir = false;
*/
$wgCustomConvertCommand = false;
+/** used for lossless jpeg rotation
+ *
+ * @since 1.21
+ * **/
+$wgJpegTran = '/usr/bin/jpegtran';
+
+
/**
* Some tests and extensions use exiv2 to manipulate the EXIF metadata in some
* image formats.
@@ -798,10 +884,10 @@ $wgSVGConverters = array(
'sodipodi' => '$path/sodipodi -z -w $width -f $input -e $output',
'inkscape' => '$path/inkscape -z -w $width -f $input -e $output',
'batik' => 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input',
- 'rsvg' => '$path/rsvg -w$width -h$height $input $output',
+ 'rsvg' => '$path/rsvg -w $width -h $height $input $output',
'imgserv' => '$path/imgserv-wrapper -i svg -o png -w$width $input $output',
'ImagickExt' => array( 'SvgHandler::rasterizeImagickExt' ),
- );
+);
/** Pick a converter defined in $wgSVGConverters */
$wgSVGConverter = 'ImageMagick';
@@ -864,7 +950,7 @@ $wgMaxAnimatedGifArea = 1.25e7;
* $wgTiffThumbnailType = array( 'jpg', 'image/jpeg' );
* @endcode
*/
- $wgTiffThumbnailType = false;
+$wgTiffThumbnailType = false;
/**
* If rendered thumbnail files are older than this timestamp, they
@@ -897,8 +983,8 @@ $wgIgnoreImageErrors = false;
$wgGenerateThumbnailOnParse = true;
/**
-* Show thumbnails for old images on the image description page
-*/
+ * Show thumbnails for old images on the image description page
+ */
$wgShowArchiveThumbnails = true;
/** Obsolete, always true, kept for compatibility with extensions */
@@ -912,7 +998,7 @@ $wgUseImageResize = true;
$wgEnableAutoRotation = null;
/**
- * Internal name of virus scanner. This servers as a key to the
+ * Internal name of virus scanner. This serves as a key to the
* $wgAntivirusSetup array. Set this to NULL to disable virus scanning. If not
* null, every file uploaded will be scanned for viruses.
*/
@@ -930,7 +1016,7 @@ $wgAntivirus = null;
* "command" is the full command to call the virus scanner - %f will be
* replaced with the name of the file to scan. If not present, the filename
* will be appended to the command. Note that this must be overwritten if the
- * scanner is not in the system path; in that case, plase set
+ * scanner is not in the system path; in that case, please set
* $wgAntivirusSetup[$wgAntivirus]['command'] to the desired command with full
* path.
*
@@ -940,8 +1026,8 @@ $wgAntivirus = null;
* the scan to be failed. This will pass the file if $wgAntivirusRequired
* is not set.
* - An exit code mapped to AV_SCAN_ABORTED causes the function to consider
- * the file to have an usupported format, which is probably imune to
- * virusses. This causes the file to pass.
+ * the file to have an unsupported format, which is probably immune to
+ * viruses. This causes the file to pass.
* - An exit code mapped to AV_NO_VIRUS will cause the file to pass, meaning
* no virus was found.
* - All other codes (like AV_VIRUS_FOUND) will cause the function to report
@@ -955,21 +1041,18 @@ $wgAntivirus = null;
$wgAntivirusSetup = array(
#setup for clamav
- 'clamav' => array (
- 'command' => "clamscan --no-summary ",
-
- 'codemap' => array (
- "0" => AV_NO_VIRUS, # no virus
- "1" => AV_VIRUS_FOUND, # virus found
- "52" => AV_SCAN_ABORTED, # unsupported file format (probably imune)
- "*" => AV_SCAN_FAILED, # else scan failed
+ 'clamav' => array(
+ 'command' => 'clamscan --no-summary ',
+ 'codemap' => array(
+ "0" => AV_NO_VIRUS, # no virus
+ "1" => AV_VIRUS_FOUND, # virus found
+ "52" => AV_SCAN_ABORTED, # unsupported file format (probably immune)
+ "*" => AV_SCAN_FAILED, # else scan failed
),
-
'messagepattern' => '/.*?:(.*)/sim',
),
);
-
/** Determines if a failed virus scan (AV_SCAN_FAILED) will cause the file to be rejected. */
$wgAntivirusRequired = true;
@@ -977,13 +1060,13 @@ $wgAntivirusRequired = true;
$wgVerifyMimeType = true;
/** Sets the mime type definition file to use by MimeMagic.php. */
-$wgMimeTypeFile = "includes/mime.types";
-#$wgMimeTypeFile= "/etc/mime.types";
-#$wgMimeTypeFile= null; #use built-in defaults only.
+$wgMimeTypeFile = 'includes/mime.types';
+#$wgMimeTypeFile = '/etc/mime.types';
+#$wgMimeTypeFile = null; #use built-in defaults only.
/** Sets the mime type info file to use by MimeMagic.php. */
-$wgMimeInfoFile= "includes/mime.info";
-#$wgMimeInfoFile= null; #use built-in defaults only.
+$wgMimeInfoFile = 'includes/mime.info';
+#$wgMimeInfoFile = null; #use built-in defaults only.
/**
* Switch for loading the FileInfo extension by PECL at runtime.
@@ -1016,11 +1099,11 @@ $wgTrivialMimeDetection = false;
* array = ( 'rootElement' => 'associatedMimeType' )
*/
$wgXMLMimeTypes = array(
- 'http://www.w3.org/2000/svg:svg' => 'image/svg+xml',
- 'svg' => 'image/svg+xml',
+ 'http://www.w3.org/2000/svg:svg' => 'image/svg+xml',
+ 'svg' => 'image/svg+xml',
'http://www.lysator.liu.se/~alla/dia/:diagram' => 'application/x-dia-diagram',
- 'http://www.w3.org/1999/xhtml:html' => 'text/html', // application/xhtml+xml?
- 'html' => 'text/html', // application/xhtml+xml?
+ 'http://www.w3.org/1999/xhtml:html' => 'text/html', // application/xhtml+xml?
+ 'html' => 'text/html', // application/xhtml+xml?
);
/**
@@ -1056,7 +1139,7 @@ $wgThumbLimits = array(
/**
* Default parameters for the "<gallery>" tag
*/
-$wgGalleryOptions = array (
+$wgGalleryOptions = array(
'imagesPerRow' => 0, // Default number of images per-row in the gallery. 0 -> Adapt to screensize
'imageWidth' => 120, // Width of the cells containing images in galleries (in "px")
'imageHeight' => 120, // Height of the cells containing images in galleries (in "px")
@@ -1077,6 +1160,16 @@ $wgThumbUpright = 0.75;
$wgDirectoryMode = 0777;
/**
+ * Generate and use thumbnails suitable for screens with 1.5 and 2.0 pixel densities.
+ *
+ * This means a 320x240 use of an image on the wiki will also generate 480x360 and 640x480
+ * thumbnails, output via data-src-1-5 and data-src-2-0. Runtime JavaScript switches the
+ * images in after loading the original low-resolution versions depending on the reported
+ * window.devicePixelRatio.
+ */
+$wgResponsiveImages = true;
+
+/**
* @name DJVU settings
* @{
*/
@@ -1182,7 +1275,7 @@ $wgEnableUserEmail = true;
* instead of From. ($wgEmergencyContact will be used as From.)
*
* Some mailers (eg sSMTP) set the SMTP envelope sender to the From value,
- * which can cause problems with SPF validation and leak recipient addressses
+ * which can cause problems with SPF validation and leak recipient addresses
* when bounces are sent to the sender.
*/
$wgUserEmailUseReplyTo = false;
@@ -1211,12 +1304,12 @@ $wgUserEmailConfirmationTokenExpiry = 7 * 24 * 60 * 60;
*
* @code
* $wgSMTP = array(
- * 'host' => 'SMTP domain',
- * 'IDHost' => 'domain for MessageID',
- * 'port' => '25',
- * 'auth' => [true|false],
- * 'username' => [SMTP username],
- * 'password' => [SMTP password],
+ * 'host' => 'SMTP domain',
+ * 'IDHost' => 'domain for MessageID',
+ * 'port' => '25',
+ * 'auth' => [true|false],
+ * 'username' => [SMTP username],
+ * 'password' => [SMTP password],
* );
* @endcode
*/
@@ -1229,6 +1322,12 @@ $wgSMTP = false;
$wgAdditionalMailParams = null;
/**
+ * For parts of the system that have been updated to provide HTML email content, send
+ * both text and HTML parts as the body of the email
+ */
+$wgAllowHTMLEmail = false;
+
+/**
* True: from page editor if s/he opted-in. False: Enotif mails appear to come
* from $wgEmergencyContact
*/
@@ -1375,12 +1474,16 @@ $wgAllDBsAreLocalhost = false;
* preferences shared (preferences were stored in the user table prior to 1.16)
*
* $wgSharedTables may be customized with a list of tables to share in the shared
- * datbase. However it is advised to limit what tables you do share as many of
+ * database. However it is advised to limit what tables you do share as many of
* MediaWiki's tables may have side effects if you try to share them.
- * EXPERIMENTAL
*
* $wgSharedPrefix is the table prefix for the shared database. It defaults to
* $wgDBprefix.
+ *
+ * @deprecated In new code, use the $wiki parameter to wfGetLB() to access
+ * remote databases. Using wfGetLB() allows the shared database to reside on
+ * separate servers to the wiki's own database, with suitable configuration
+ * of $wgLBFactoryConf.
*/
$wgSharedDB = null;
@@ -1459,7 +1562,7 @@ $wgDBerrorLog = false;
* Timezone to use in the error log.
* Defaults to the wiki timezone ($wgLocaltimezone).
*
- * A list of useable timezones can found at:
+ * A list of usable timezones can found at:
* http://php.net/manual/en/timezones.php
*
* @par Examples:
@@ -1526,7 +1629,6 @@ $wgOldChangeTagsIndex = false;
/**@}*/ # End of DB settings }
-
/************************************************************************//**
* @name Text storage
* @{
@@ -1560,7 +1662,7 @@ $wgExternalStores = false;
* Create a cluster named 'cluster1' containing three servers:
* @code
* $wgExternalServers = array(
- * 'cluster1' => array( 'srv28', 'srv29', 'srv30' )
+ * 'cluster1' => array( 'srv28', 'srv29', 'srv30' )
* );
* @endcode
*
@@ -1758,13 +1860,13 @@ $wgDBAhandler = 'db3';
/**
* Deprecated alias for $wgSessionsInObjectCache.
*
- * @deprecated Use $wgSessionsInObjectCache
+ * @deprecated since 1.20; Use $wgSessionsInObjectCache
*/
$wgSessionsInMemcached = false;
/**
* Store sessions in an object cache, configured by $wgSessionCacheType. This
- * can be useful to improve performance, or to avoid the locking behaviour of
+ * can be useful to improve performance, or to avoid the locking behavior of
* PHP's default session handler, which tends to prevent multiple requests for
* the same user from acting concurrently.
*/
@@ -1815,9 +1917,10 @@ $wgUseLocalMessageCache = false;
$wgLocalMessageCacheSerialized = true;
/**
- * Instead of caching everything, keep track which messages are requested and
- * load only most used messages. This only makes sense if there is lots of
- * interface messages customised in the wiki (like hundreds in many languages).
+ * Instead of caching everything, only cache those messages which have
+ * been customised in the site content language. This means that
+ * MediaWiki:Foo/ja is ignored if MediaWiki:Foo doesn't exist.
+ * This option is probably only useful for translatewiki.net.
*/
$wgAdaptiveMessageCache = false;
@@ -2032,6 +2135,27 @@ $wgSquidServersNoPurge = array();
$wgMaxSquidPurgeTitles = 400;
/**
+ * Whether to use a Host header in purge requests sent to the proxy servers
+ * configured in $wgSquidServers. Set this to false to support Squid
+ * configured in forward-proxy mode.
+ *
+ * If this is set to true, a Host header will be sent, and only the path
+ * component of the URL will appear on the request line, as if the request
+ * were a non-proxy HTTP 1.1 request. Varnish only supports this style of
+ * request. Squid supports this style of request only if reverse-proxy mode
+ * (http_port ... accel) is enabled.
+ *
+ * If this is set to false, no Host header will be sent, and the absolute URL
+ * will be sent in the request line, as is the standard for an HTTP proxy
+ * request in both HTTP 1.0 and 1.1. This style of request is not supported
+ * by Varnish, but is supported by Squid in either configuration (forward or
+ * reverse).
+ *
+ * @since 1.21
+ */
+$wgSquidPurgeUseHostHeader = true;
+
+/**
* Routing configuration for HTCP multicast purging. Add elements here to
* enable HTCP and determine which purges are sent where. If set to an empty
* array, HTCP is disabled.
@@ -2073,13 +2197,13 @@ $wgHTCPMulticastRouting = array();
* setting is ignored. If $wgHTCPMulticastRouting is not set and this setting
* is, it is used to populate $wgHTCPMulticastRouting.
*
- * @deprecated in favor of $wgHTCPMulticastRouting
+ * @deprecated since 1.20 in favor of $wgHTCPMulticastRouting
*/
$wgHTCPMulticastAddress = false;
/**
* HTCP multicast port.
- * @deprecated in favor of $wgHTCPMulticastRouting
+ * @deprecated since 1.20 in favor of $wgHTCPMulticastRouting
* @see $wgHTCPMulticastAddress
*/
$wgHTCPPort = 4827;
@@ -2100,10 +2224,30 @@ $wgUsePrivateIPs = false;
* @{
*/
-/** Site language code, should be one of ./languages/Language(.*).php */
+/**
+ * Site language code. See languages/Names.php for languages supported by
+ * MediaWiki out of the box. Not all languages listed there have translations,
+ * see languages/messages/ for the list of languages with some localisation.
+ *
+ * Warning: Don't use language codes listed in $wgDummyLanguageCodes like "no"
+ * for Norwegian (use "nb" instead), or things will break unexpectedly.
+ *
+ * This defines the default interface language for all users, but users can
+ * change it in their preferences.
+ *
+ * This also defines the language of pages in the wiki. The content is wrapped
+ * in a html element with lang=XX attribute. This behavior can be overridden
+ * via hooks, see Title::getPageLanguage.
+ */
$wgLanguageCode = 'en';
/**
+ * Language cache size, or really how many languages can we handle
+ * simultaneously without degrading to crawl speed.
+ */
+$wgLangObjCacheSize = 10;
+
+/**
* Some languages need different word forms, usually for different cases.
* Used in Language::convertGrammar().
*
@@ -2125,7 +2269,7 @@ $wgExtraLanguageNames = array();
/**
* List of language codes that don't correspond to an actual language.
- * These codes are mostly leftoffs from renames, or other legacy things.
+ * These codes are mostly left-offs from renames, or other legacy things.
* This array makes them not appear as a selectable language on the installer,
* and excludes them when running the transstat.php script.
*/
@@ -2249,24 +2393,16 @@ $wgBrowserBlackList = array(
* requires that the cur table be kept around for those revisions
* to remain viewable.
*
- * maintenance/migrateCurStubs.php can be used to complete the
- * migration in the background once the wiki is back online.
- *
* This option affects the updaters *only*. Any present cur stub
* revisions will be readable at runtime regardless of this setting.
*/
$wgLegacySchemaConversion = false;
/**
- * Enable to allow rewriting dates in page text.
- * DOES NOT FORMAT CORRECTLY FOR MOST LANGUAGES.
- */
-$wgUseDynamicDates = false;
-/**
* Enable dates like 'May 12' instead of '12 May', this only takes effect if
* the interface is set to English.
*/
-$wgAmericanDates = false;
+$wgAmericanDates = false;
/**
* For Hindi and Arabic use local numerals instead of Western style (0-9)
* numerals in interface.
@@ -2295,7 +2431,7 @@ $wgDisableLangConversion = false;
/** Whether to enable language variant conversion for links. */
$wgDisableTitleConversion = false;
-/** Whether to enable cononical language links in meta data. */
+/** Whether to enable canonical language links in meta data. */
$wgCanonicalLanguageLinks = true;
/** Default variant code, if false, the default will be the language code */
@@ -2319,9 +2455,9 @@ $wgDisabledVariants = array();
*
* @par Example:
* @code
- * $wgLanguageCode = 'sr';
- * $wgVariantArticlePath = '/$2/$1';
- * $wgArticlePath = '/wiki/$1';
+ * $wgLanguageCode = 'sr';
+ * $wgVariantArticlePath = '/$2/$1';
+ * $wgArticlePath = '/wiki/$1';
* @endcode
*
* A link to /wiki/ would be redirected to /sr/Главна_страна
@@ -2354,7 +2490,7 @@ $wgLoginLanguageSelector = false;
* To allow language-specific main page and community
* portal:
* @code
- * $wgForceUIMsgAsContentMsg = array( 'mainpage', 'portal-url' );
+ * $wgForceUIMsgAsContentMsg = array( 'mainpage', 'portal-url' );
* @endcode
*/
$wgForceUIMsgAsContentMsg = array();
@@ -2370,7 +2506,7 @@ $wgForceUIMsgAsContentMsg = array();
* Timezones can be translated by editing MediaWiki messages of type
* timezone-nameinlowercase like timezone-utc.
*
- * A list of useable timezones can found at:
+ * A list of usable timezones can found at:
* http://php.net/manual/en/timezones.php
*
* @par Examples:
@@ -2389,23 +2525,12 @@ $wgLocaltimezone = null;
* for anonymous users and new user accounts.
*
* This setting is used for most date/time displays in the software, and is
- * overrideable in user preferences. It is *not* used for signature timestamps.
+ * overridable in user preferences. It is *not* used for signature timestamps.
*
* By default, this will be set to match $wgLocaltimezone.
*/
$wgLocalTZoffset = null;
-/**
- * If set to true, this will roll back a few bug fixes introduced in 1.19,
- * emulating the 1.18 behaviour, to avoid introducing bug 34832. In 1.19,
- * language variant conversion is disabled in interface messages. Setting this
- * to true re-enables it.
- *
- * @todo This variable should be removed (implicitly false) in 1.20 or earlier.
- */
-$wgBug34832TransitionalRollback = true;
-
-
/** @} */ # End of language/charset settings
/*************************************************************************//**
@@ -2499,7 +2624,7 @@ $wgWellFormedXml = true;
* @par Example:
* @code
* $wgXhtmlNamespaces['svg'] = 'http://www.w3.org/2000/svg';
- * @endCode
+ * @endcode
* Normally we wouldn't have to define this in the root "<html>"
* element, but IE needs it there in some circumstances.
*
@@ -2527,12 +2652,12 @@ $wgSiteNotice = '';
/**
* A subtitle to add to the tagline, for skins that have it/
*/
-$wgExtraSubtitle = '';
+$wgExtraSubtitle = '';
/**
* If this is set, a "donate" link will appear in the sidebar. Set it to a URL.
*/
-$wgSiteSupportPage = '';
+$wgSiteSupportPage = '';
/**
* Validate the overall output using tidy and refuse
@@ -2684,7 +2809,7 @@ $wgExperimentalHtmlIds = false;
* for the icon, the following keys are used:
* - src: An absolute url to the image to use for the icon, this is recommended
* but not required, however some skins will ignore icons without an image
- * - url: The url to use in the a element arround the text or icon, if not set an a element will not be outputted
+ * - url: The url to use in the a element around the text or icon, if not set an a element will not be outputted
* - alt: This is the text form of the icon, it will be displayed without an image in
* skins like Modern or if src is not set, and will otherwise be used as
* the alt="" for the image. This key is required.
@@ -2719,7 +2844,7 @@ $wgUseCombinedLoginLink = false;
* - true = use an icon search button
* - false = use Go & Search buttons
*/
-$wgVectorUseSimpleSearch = false;
+$wgVectorUseSimpleSearch = true;
/**
* Watch and unwatch as an icon rather than a link for Vector skin only.
@@ -2754,16 +2879,24 @@ $wgBetterDirectionality = true;
*/
$wgSend404Code = true;
-
/**
* The $wgShowRollbackEditCount variable is used to show how many edits will be
- * rollback. The numeric value of the varible are the limit up to are counted.
- * If the value is false or 0, the edits are not counted.
+ * rollback. The numeric value of the variable are the limit up to are counted.
+ * If the value is false or 0, the edits are not counted. Disabling this will
+ * furthermore prevent MediaWiki from hiding some useless rollback links.
*
* @since 1.20
*/
$wgShowRollbackEditCount = 10;
+/**
+ * Output a <link rel="canonical"> tag on every page indicating the canonical
+ * server which should be used, i.e. $wgServer or $wgCanonicalServer. Since
+ * detection of the current server is unreliable, the link is sent
+ * unconditionally.
+ */
+$wgEnableCanonicalServerLink = false;
+
/** @} */ # End of output format settings }
/*************************************************************************//**
@@ -2890,21 +3023,21 @@ $wgPreloadJavaScriptMwUtil = false;
*
* @par Example of legacy code:
* @code{,js}
- * if ( window.wgRestrictionEdit ) { ... }
+ * if ( window.wgRestrictionEdit ) { ... }
* @endcode
* or:
* @code{,js}
- * if ( wgIsArticle ) { ... }
+ * if ( wgIsArticle ) { ... }
* @endcode
*
* Instead, one needs to use mw.config.
* @par Example using mw.config global configuration:
* @code{,js}
- * if ( mw.config.exists('wgRestrictionEdit') ) { ... }
+ * if ( mw.config.exists('wgRestrictionEdit') ) { ... }
* @endcode
* or:
* @code{,js}
- * if ( mw.config.get('wgIsArticle') ) { ... }
+ * if ( mw.config.get('wgIsArticle') ) { ... }
* @endcode
*/
$wgLegacyJavaScriptGlobals = true;
@@ -2950,7 +3083,6 @@ $wgResourceLoaderExperimentalAsyncLoading = false;
/** @} */ # End of resource loader settings }
-
/*************************************************************************//**
* @name Page title and interwiki link settings
* @{
@@ -3085,13 +3217,13 @@ $wgInterwikiExpiry = 10800;
$wgInterwikiCache = false;
/**
* Specify number of domains to check for messages.
- * - 1: Just wiki(db)-level
- * - 2: wiki and global levels
- * - 3: site levels
+ * - 1: Just wiki(db)-level
+ * - 2: wiki and global levels
+ * - 3: site levels
*/
$wgInterwikiScopes = 3;
/**
- * $wgInterwikiFallbackSite - if unable to resolve from cache
+ * $wgInterwikiFallbackSite - if unable to resolve from cache
*/
$wgInterwikiFallbackSite = 'wiki';
/** @} */ # end of Interwiki caching settings.
@@ -3133,7 +3265,7 @@ $wgCapitalLinks = true;
*
* @par Example:
* @code
- * $wgCapitalLinkOverrides[ NS_FILE ] = false;
+ * $wgCapitalLinkOverrides[ NS_FILE ] = false;
* @endcode
*/
$wgCapitalLinkOverrides = array();
@@ -3142,16 +3274,18 @@ $wgCapitalLinkOverrides = array();
* See Language.php for a list of namespaces.
*/
$wgNamespacesWithSubpages = array(
- NS_TALK => true,
- NS_USER => true,
- NS_USER_TALK => true,
- NS_PROJECT_TALK => true,
- NS_FILE_TALK => true,
- NS_MEDIAWIKI => true,
+ NS_TALK => true,
+ NS_USER => true,
+ NS_USER_TALK => true,
+ NS_PROJECT => true,
+ NS_PROJECT_TALK => true,
+ NS_FILE_TALK => true,
+ NS_MEDIAWIKI => true,
NS_MEDIAWIKI_TALK => true,
- NS_TEMPLATE_TALK => true,
- NS_HELP_TALK => true,
- NS_CATEGORY_TALK => true
+ NS_TEMPLATE_TALK => true,
+ NS_HELP => true,
+ NS_HELP_TALK => true,
+ NS_CATEGORY_TALK => true
);
/**
@@ -3195,7 +3329,7 @@ $wgInvalidRedirectTargets = array( 'Filepath', 'Mypage', 'Mytalk' );
* class The class name
*
* preprocessorClass The preprocessor class. Two classes are currently available:
- * Preprocessor_Hash, which uses plain PHP arrays for tempoarary
+ * Preprocessor_Hash, which uses plain PHP arrays for temporary
* storage, and Preprocessor_DOM, which uses the DOM module for
* temporary storage. Preprocessor_DOM generally uses less memory;
* the speed of the two is roughly the same.
@@ -3225,12 +3359,16 @@ $wgMaxTocLevel = 999;
$wgMaxPPNodeCount = 1000000;
/**
- * A complexity limit on template expansion: the maximum number of nodes
- * generated by Preprocessor::preprocessToObj()
+ * A complexity limit on template expansion: the maximum number of elements
+ * generated by Preprocessor::preprocessToObj(). This allows you to limit the
+ * amount of memory used by the Preprocessor_DOM node cache: testing indicates
+ * that each element uses about 160 bytes of memory on a 64-bit processor, so
+ * this default corresponds to about 155 MB.
+ *
+ * When the limit is exceeded, an exception is thrown.
*/
$wgMaxGeneratedPPNodeCount = 1000000;
-
/**
* Maximum recursion depth for templates within templates.
* The current parser adds two levels to the PHP call stack for each template,
@@ -3248,7 +3386,7 @@ $wgUrlProtocols = array(
'https://',
'ftp://',
'irc://',
- 'ircs://', // @bug 28503
+ 'ircs://', // @bug 28503
'gopher://',
'telnet://', // Well if we're going to support the above.. -ævar
'nntp://', // @bug 3808 RFC 1738
@@ -3324,7 +3462,7 @@ $wgAlwaysUseTidy = false;
/** @see $wgUseTidy */
$wgTidyBin = 'tidy';
/** @see $wgUseTidy */
-$wgTidyConf = $IP.'/includes/tidy.conf';
+$wgTidyConf = $IP . '/includes/tidy.conf';
/** @see $wgUseTidy */
$wgTidyOpts = '';
/** @see $wgUseTidy */
@@ -3520,77 +3658,70 @@ $wgReservedUsernames = array(
*
*/
$wgDefaultUserOptions = array(
- 'ccmeonemails' => 0,
- 'cols' => 80,
- 'date' => 'default',
- 'diffonly' => 0,
- 'disablemail' => 0,
- 'disablesuggest' => 0,
- 'editfont' => 'default',
- 'editondblclick' => 0,
- 'editsection' => 1,
+ 'ccmeonemails' => 0,
+ 'cols' => 80,
+ 'date' => 'default',
+ 'diffonly' => 0,
+ 'disablemail' => 0,
+ 'disablesuggest' => 0,
+ 'editfont' => 'default',
+ 'editondblclick' => 0,
+ 'editsection' => 1,
'editsectiononrightclick' => 0,
- 'enotifminoredits' => 0,
- 'enotifrevealaddr' => 0,
- 'enotifusertalkpages' => 1,
- 'enotifwatchlistpages' => 0,
- 'extendwatchlist' => 0,
- 'externaldiff' => 0,
- 'externaleditor' => 0,
- 'fancysig' => 0,
- 'forceeditsummary' => 0,
- 'gender' => 'unknown',
- 'hideminor' => 0,
- 'hidepatrolled' => 0,
- 'imagesize' => 2,
- 'justify' => 0,
- 'math' => 1,
- 'minordefault' => 0,
- 'newpageshidepatrolled' => 0,
- 'nocache' => 0,
- 'noconvertlink' => 0,
- 'norollbackdiff' => 0,
- 'numberheadings' => 0,
- 'previewonfirst' => 0,
- 'previewontop' => 1,
- 'quickbar' => 5,
- 'rcdays' => 7,
- 'rclimit' => 50,
- 'rememberpassword' => 0,
- 'rows' => 25,
- 'searchlimit' => 20,
- 'showhiddencats' => 0,
- 'showjumplinks' => 1,
- 'shownumberswatching' => 1,
- 'showtoc' => 1,
- 'showtoolbar' => 1,
- 'skin' => false,
- 'stubthreshold' => 0,
- 'thumbsize' => 2,
- 'underline' => 2,
- 'uselivepreview' => 0,
- 'usenewrc' => 0,
- 'watchcreations' => 0,
- 'watchdefault' => 0,
- 'watchdeletion' => 0,
- 'watchlistdays' => 3.0,
- 'watchlisthideanons' => 0,
- 'watchlisthidebots' => 0,
- 'watchlisthideliu' => 0,
- 'watchlisthideminor' => 0,
- 'watchlisthideown' => 0,
- 'watchlisthidepatrolled' => 0,
- 'watchmoves' => 0,
- 'wllimit' => 250,
+ 'enotifminoredits' => 0,
+ 'enotifrevealaddr' => 0,
+ 'enotifusertalkpages' => 1,
+ 'enotifwatchlistpages' => 0,
+ 'extendwatchlist' => 0,
+ 'externaldiff' => 0,
+ 'externaleditor' => 0,
+ 'fancysig' => 0,
+ 'forceeditsummary' => 0,
+ 'gender' => 'unknown',
+ 'hideminor' => 0,
+ 'hidepatrolled' => 0,
+ 'imagesize' => 2,
+ 'justify' => 0,
+ 'math' => 1,
+ 'minordefault' => 0,
+ 'newpageshidepatrolled' => 0,
+ 'nocache' => 0,
+ 'noconvertlink' => 0,
+ 'norollbackdiff' => 0,
+ 'numberheadings' => 0,
+ 'previewonfirst' => 0,
+ 'previewontop' => 1,
+ 'quickbar' => 5,
+ 'rcdays' => 7,
+ 'rclimit' => 50,
+ 'rememberpassword' => 0,
+ 'rows' => 25,
+ 'searchlimit' => 20,
+ 'showhiddencats' => 0,
+ 'showjumplinks' => 1,
+ 'shownumberswatching' => 1,
+ 'showtoc' => 1,
+ 'showtoolbar' => 1,
+ 'skin' => false,
+ 'stubthreshold' => 0,
+ 'thumbsize' => 2,
+ 'underline' => 2,
+ 'uselivepreview' => 0,
+ 'usenewrc' => 0,
+ 'watchcreations' => 0,
+ 'watchdefault' => 0,
+ 'watchdeletion' => 0,
+ 'watchlistdays' => 3.0,
+ 'watchlisthideanons' => 0,
+ 'watchlisthidebots' => 0,
+ 'watchlisthideliu' => 0,
+ 'watchlisthideminor' => 0,
+ 'watchlisthideown' => 0,
+ 'watchlisthidepatrolled' => 0,
+ 'watchmoves' => 0,
+ 'wllimit' => 250,
);
-/**
- * Whether or not to allow and use real name fields.
- * @deprecated since 1.16, use $wgHiddenPrefs[] = 'realname' below to disable real
- * names
- */
-$wgAllowRealName = true;
-
/** An array of preferences to not show for the user */
$wgHiddenPrefs = array();
@@ -3672,11 +3803,18 @@ $wgAllowPrefChange = array();
/**
* This is to let user authenticate using https when they come from http.
* Based on an idea by George Herbert on wikitech-l:
- * http://lists.wikimedia.org/pipermail/wikitech-l/2010-October/050065.html
+ * http://lists.wikimedia.org/pipermail/wikitech-l/2010-October/050039.html
* @since 1.17
*/
$wgSecureLogin = false;
+/**
+ * By default, keep users logged in via HTTPS when $wgSecureLogin is also
+ * true. Users opt-out of HTTPS when they login by de-selecting the checkbox.
+ * @since 1.21
+ */
+$wgSecureLoginDefaultHTTPS = true;
+
/** @} */ # end user accounts }
/************************************************************************//**
@@ -3745,6 +3883,34 @@ $wgBlockDisablesLogin = false;
$wgWhitelistRead = false;
/**
+ * Pages anonymous user may see, set as an array of regular expressions.
+ *
+ * This function will match the regexp against the title name, which
+ * is without underscore.
+ *
+ * @par Example:
+ * To whitelist [[Main Page]]:
+ * @code
+ * $wgWhitelistReadRegexp = array( "/Main Page/" );
+ * @endcode
+ *
+ * @note Unless ^ and/or $ is specified, a regular expression might match
+ * pages not intended to be whitelisted. The above example will also
+ * whitelist a page named 'Security Main Page'.
+ *
+ * @par Example:
+ * To allow reading any page starting with 'User' regardless of the case:
+ * @code
+ * $wgWhitelistReadRegexp = array( "@^UsEr.*@i" );
+ * @endcode
+ * Will allow both [[User is banned]] and [[User:JohnDoe]]
+ *
+ * @note This will only work if $wgGroupPermissions['*']['read'] is false --
+ * see below. Otherwise, ALL pages are accessible, regardless of this setting.
+ */
+$wgWhitelistReadRegexp = false;
+
+/**
* Should editors be required to have a validated e-mail
* address before being allowed to edit?
*/
@@ -3778,93 +3944,93 @@ $wgGroupPermissions = array();
/** @cond file_level_code */
// Implicit group for all visitors
-$wgGroupPermissions['*']['createaccount'] = true;
-$wgGroupPermissions['*']['read'] = true;
-$wgGroupPermissions['*']['edit'] = true;
-$wgGroupPermissions['*']['createpage'] = true;
-$wgGroupPermissions['*']['createtalk'] = true;
-$wgGroupPermissions['*']['writeapi'] = true;
-//$wgGroupPermissions['*']['patrolmarks'] = false; // let anons see what was patrolled
+$wgGroupPermissions['*']['createaccount'] = true;
+$wgGroupPermissions['*']['read'] = true;
+$wgGroupPermissions['*']['edit'] = true;
+$wgGroupPermissions['*']['createpage'] = true;
+$wgGroupPermissions['*']['createtalk'] = true;
+$wgGroupPermissions['*']['writeapi'] = true;
+#$wgGroupPermissions['*']['patrolmarks'] = false; // let anons see what was patrolled
// Implicit group for all logged-in accounts
-$wgGroupPermissions['user']['move'] = true;
-$wgGroupPermissions['user']['move-subpages'] = true;
+$wgGroupPermissions['user']['move'] = true;
+$wgGroupPermissions['user']['move-subpages'] = true;
$wgGroupPermissions['user']['move-rootuserpages'] = true; // can move root userpages
-$wgGroupPermissions['user']['movefile'] = true;
-$wgGroupPermissions['user']['read'] = true;
-$wgGroupPermissions['user']['edit'] = true;
-$wgGroupPermissions['user']['createpage'] = true;
-$wgGroupPermissions['user']['createtalk'] = true;
-$wgGroupPermissions['user']['writeapi'] = true;
-$wgGroupPermissions['user']['upload'] = true;
-$wgGroupPermissions['user']['reupload'] = true;
-$wgGroupPermissions['user']['reupload-shared'] = true;
-$wgGroupPermissions['user']['minoredit'] = true;
-$wgGroupPermissions['user']['purge'] = true; // can use ?action=purge without clicking "ok"
-$wgGroupPermissions['user']['sendemail'] = true;
+$wgGroupPermissions['user']['movefile'] = true;
+$wgGroupPermissions['user']['read'] = true;
+$wgGroupPermissions['user']['edit'] = true;
+$wgGroupPermissions['user']['createpage'] = true;
+$wgGroupPermissions['user']['createtalk'] = true;
+$wgGroupPermissions['user']['writeapi'] = true;
+$wgGroupPermissions['user']['upload'] = true;
+$wgGroupPermissions['user']['reupload'] = true;
+$wgGroupPermissions['user']['reupload-shared'] = true;
+$wgGroupPermissions['user']['minoredit'] = true;
+$wgGroupPermissions['user']['purge'] = true; // can use ?action=purge without clicking "ok"
+$wgGroupPermissions['user']['sendemail'] = true;
// Implicit group for accounts that pass $wgAutoConfirmAge
$wgGroupPermissions['autoconfirmed']['autoconfirmed'] = true;
// Users with bot privilege can have their edits hidden
// from various log pages by default
-$wgGroupPermissions['bot']['bot'] = true;
-$wgGroupPermissions['bot']['autoconfirmed'] = true;
-$wgGroupPermissions['bot']['nominornewtalk'] = true;
-$wgGroupPermissions['bot']['autopatrol'] = true;
+$wgGroupPermissions['bot']['bot'] = true;
+$wgGroupPermissions['bot']['autoconfirmed'] = true;
+$wgGroupPermissions['bot']['nominornewtalk'] = true;
+$wgGroupPermissions['bot']['autopatrol'] = true;
$wgGroupPermissions['bot']['suppressredirect'] = true;
-$wgGroupPermissions['bot']['apihighlimits'] = true;
-$wgGroupPermissions['bot']['writeapi'] = true;
-#$wgGroupPermissions['bot']['editprotected'] = true; // can edit all protected pages without cascade protection enabled
+$wgGroupPermissions['bot']['apihighlimits'] = true;
+$wgGroupPermissions['bot']['writeapi'] = true;
+#$wgGroupPermissions['bot']['editprotected'] = true; // can edit all protected pages without cascade protection enabled
// Most extra permission abilities go to this group
-$wgGroupPermissions['sysop']['block'] = true;
-$wgGroupPermissions['sysop']['createaccount'] = true;
-$wgGroupPermissions['sysop']['delete'] = true;
-$wgGroupPermissions['sysop']['bigdelete'] = true; // can be separately configured for pages with > $wgDeleteRevisionsLimit revs
-$wgGroupPermissions['sysop']['deletedhistory'] = true; // can view deleted history entries, but not see or restore the text
-$wgGroupPermissions['sysop']['deletedtext'] = true; // can view deleted revision text
-$wgGroupPermissions['sysop']['undelete'] = true;
-$wgGroupPermissions['sysop']['editinterface'] = true;
-$wgGroupPermissions['sysop']['editusercss'] = true;
-$wgGroupPermissions['sysop']['edituserjs'] = true;
-$wgGroupPermissions['sysop']['import'] = true;
-$wgGroupPermissions['sysop']['importupload'] = true;
-$wgGroupPermissions['sysop']['move'] = true;
-$wgGroupPermissions['sysop']['move-subpages'] = true;
+$wgGroupPermissions['sysop']['block'] = true;
+$wgGroupPermissions['sysop']['createaccount'] = true;
+$wgGroupPermissions['sysop']['delete'] = true;
+$wgGroupPermissions['sysop']['bigdelete'] = true; // can be separately configured for pages with > $wgDeleteRevisionsLimit revs
+$wgGroupPermissions['sysop']['deletedhistory'] = true; // can view deleted history entries, but not see or restore the text
+$wgGroupPermissions['sysop']['deletedtext'] = true; // can view deleted revision text
+$wgGroupPermissions['sysop']['undelete'] = true;
+$wgGroupPermissions['sysop']['editinterface'] = true;
+$wgGroupPermissions['sysop']['editusercss'] = true;
+$wgGroupPermissions['sysop']['edituserjs'] = true;
+$wgGroupPermissions['sysop']['import'] = true;
+$wgGroupPermissions['sysop']['importupload'] = true;
+$wgGroupPermissions['sysop']['move'] = true;
+$wgGroupPermissions['sysop']['move-subpages'] = true;
$wgGroupPermissions['sysop']['move-rootuserpages'] = true;
-$wgGroupPermissions['sysop']['patrol'] = true;
-$wgGroupPermissions['sysop']['autopatrol'] = true;
-$wgGroupPermissions['sysop']['protect'] = true;
-$wgGroupPermissions['sysop']['proxyunbannable'] = true;
-$wgGroupPermissions['sysop']['rollback'] = true;
-$wgGroupPermissions['sysop']['upload'] = true;
-$wgGroupPermissions['sysop']['reupload'] = true;
-$wgGroupPermissions['sysop']['reupload-shared'] = true;
-$wgGroupPermissions['sysop']['unwatchedpages'] = true;
-$wgGroupPermissions['sysop']['autoconfirmed'] = true;
-$wgGroupPermissions['sysop']['ipblock-exempt'] = true;
-$wgGroupPermissions['sysop']['blockemail'] = true;
-$wgGroupPermissions['sysop']['markbotedits'] = true;
-$wgGroupPermissions['sysop']['apihighlimits'] = true;
-$wgGroupPermissions['sysop']['browsearchive'] = true;
-$wgGroupPermissions['sysop']['noratelimit'] = true;
-$wgGroupPermissions['sysop']['movefile'] = true;
-$wgGroupPermissions['sysop']['unblockself'] = true;
+$wgGroupPermissions['sysop']['patrol'] = true;
+$wgGroupPermissions['sysop']['autopatrol'] = true;
+$wgGroupPermissions['sysop']['protect'] = true;
+$wgGroupPermissions['sysop']['proxyunbannable'] = true;
+$wgGroupPermissions['sysop']['rollback'] = true;
+$wgGroupPermissions['sysop']['upload'] = true;
+$wgGroupPermissions['sysop']['reupload'] = true;
+$wgGroupPermissions['sysop']['reupload-shared'] = true;
+$wgGroupPermissions['sysop']['unwatchedpages'] = true;
+$wgGroupPermissions['sysop']['autoconfirmed'] = true;
+$wgGroupPermissions['sysop']['ipblock-exempt'] = true;
+$wgGroupPermissions['sysop']['blockemail'] = true;
+$wgGroupPermissions['sysop']['markbotedits'] = true;
+$wgGroupPermissions['sysop']['apihighlimits'] = true;
+$wgGroupPermissions['sysop']['browsearchive'] = true;
+$wgGroupPermissions['sysop']['noratelimit'] = true;
+$wgGroupPermissions['sysop']['movefile'] = true;
+$wgGroupPermissions['sysop']['unblockself'] = true;
$wgGroupPermissions['sysop']['suppressredirect'] = true;
-#$wgGroupPermissions['sysop']['upload_by_url'] = true;
-#$wgGroupPermissions['sysop']['mergehistory'] = true;
+#$wgGroupPermissions['sysop']['upload_by_url'] = true;
+#$wgGroupPermissions['sysop']['mergehistory'] = true;
// Permission to change users' group assignments
-$wgGroupPermissions['bureaucrat']['userrights'] = true;
+$wgGroupPermissions['bureaucrat']['userrights'] = true;
$wgGroupPermissions['bureaucrat']['noratelimit'] = true;
// Permission to change users' groups assignments across wikis
#$wgGroupPermissions['bureaucrat']['userrights-interwiki'] = true;
// Permission to export pages including linked pages regardless of $wgExportMaxLinkDepth
#$wgGroupPermissions['bureaucrat']['override-export-depth'] = true;
-#$wgGroupPermissions['sysop']['deletelogentry'] = true;
-#$wgGroupPermissions['sysop']['deleterevision'] = true;
+#$wgGroupPermissions['sysop']['deletelogentry'] = true;
+#$wgGroupPermissions['sysop']['deleterevision'] = true;
// To hide usernames from users and Sysops
#$wgGroupPermissions['suppress']['hideuser'] = true;
// To hide revisions/log items from users and Sysops
@@ -3962,7 +4128,7 @@ $wgNamespaceProtection = array();
* namespaces constants (NS_USER, NS_MAIN...).
*
* Among other things, this may be useful to enforce read-restrictions
- * which may otherwise be bypassed by using the template machanism.
+ * which may otherwise be bypassed by using the template mechanism.
*/
$wgNonincludableNamespaces = array();
@@ -4037,11 +4203,11 @@ $wgAutopromote = array(
*
* The format is:
* @code
- * array( event => criteria, ... )
+ * array( event => criteria, ... )
* @endcode
* Where event is either:
- * - 'onEdit' (when user edits)
- * - 'onView' (when user views the wiki)
+ * - 'onEdit' (when user edits)
+ * - 'onView' (when user views the wiki)
*
* Criteria has the same format as $wgAutopromote
*
@@ -4100,7 +4266,8 @@ $wgDeleteRevisionsLimit = 0;
/**
* Number of accounts each IP address may create, 0 to disable.
*
- * @warning Requires memcached */
+ * @warning Requires memcached
+ */
$wgAccountCreationThrottle = 0;
/**
@@ -4191,25 +4358,25 @@ $wgProxyWhitelist = array();
*/
$wgRateLimits = array(
'edit' => array(
- 'anon' => null, // for any and all anonymous edits (aggregate)
- 'user' => null, // for each logged-in user
+ 'anon' => null, // for any and all anonymous edits (aggregate)
+ 'user' => null, // for each logged-in user
'newbie' => null, // for each recent (autoconfirmed) account; overrides 'user'
- 'ip' => null, // for each anon and recent account
+ 'ip' => null, // for each anon and recent account
'subnet' => null, // ... with final octet removed
- ),
+ ),
'move' => array(
- 'user' => null,
+ 'user' => null,
'newbie' => null,
- 'ip' => null,
+ 'ip' => null,
'subnet' => null,
- ),
+ ),
'mailpassword' => array(
'anon' => null,
- ),
+ ),
'emailuser' => array(
'user' => null,
- ),
- );
+ ),
+);
/**
* Set to a filename to log rate limiter hits.
@@ -4225,6 +4392,7 @@ $wgRateLimitsExcludedIPs = array();
/**
* Log IP addresses in the recentchanges table; can be accessed only by
* extensions (e.g. CheckUser) or a DB admin
+ * Used for retroactive autoblocks
*/
$wgPutIPinRC = true;
@@ -4261,14 +4429,26 @@ $wgBlockOpenProxies = false;
/** Port we want to scan for a proxy */
$wgProxyPorts = array( 80, 81, 1080, 3128, 6588, 8000, 8080, 8888, 65506 );
/** Script used to scan */
-$wgProxyScriptPath = "$IP/maintenance/proxy_check.php";
+$wgProxyScriptPath = "$IP/maintenance/proxyCheck.php";
/** */
$wgProxyMemcExpiry = 86400;
/** This should always be customised in LocalSettings.php */
$wgSecretKey = false;
-/** big list of banned IP addresses, in the keys not the values */
+
+/**
+ * Big list of banned IP addresses.
+ *
+ * This can have the following formats:
+ * - An array of addresses, either in the values
+ * or the keys (for backward compatibility)
+ * - A string, in that case this is the path to a file
+ * containing the list of IP addresses, one per line
+ */
$wgProxyList = array();
-/** deprecated */
+
+/**
+ * @deprecated since 1.14
+ */
$wgProxyKey = false;
/** @} */ # end of proxy scanner settings
@@ -4281,7 +4461,7 @@ $wgProxyKey = false;
/**
* Default cookie expiration time. Setting to 0 makes all cookies session-only.
*/
-$wgCookieExpiration = 180*86400;
+$wgCookieExpiration = 180 * 86400;
/**
* Set to set an explicit domain on the login cookies eg, "justthis.domain.org"
@@ -4289,7 +4469,6 @@ $wgCookieExpiration = 180*86400;
*/
$wgCookieDomain = '';
-
/**
* Set this variable if you want to restrict cookies to a certain path within
* the domain specified by $wgCookieDomain.
@@ -4343,7 +4522,7 @@ $wgCacheVaryCookies = array();
/** Override to customise the session name */
$wgSessionName = false;
-/** @} */ # end of cookie settings }
+/** @} */ # end of cookie settings }
/************************************************************************//**
* @name LaTeX (mathematical formulas)
@@ -4507,7 +4686,9 @@ $wgProfileOnly = false;
* Log sums from profiling into "profiling" table in db.
*
* You have to create a 'profiling' table in your database before using
- * this feature, see maintenance/archives/patch-profiling.sql
+ * this feature. Run set $wgProfileToDatabase to true in
+ * LocalSettings.php and run maintenance/update.php or otherwise
+ * manually add patch-profiling.sql to your database.
*
* To enable profiling, edit StartProfiler.php
*/
@@ -4561,6 +4742,13 @@ $wgAggregateStatsID = false;
$wgDisableCounters = false;
/**
+ * InfoAction retrieves a list of transclusion links (both to and from).
+ * This number puts a limit on that query in the case of highly transcluded
+ * templates.
+ */
+$wgPageInfoTransclusionLimit = 50;
+
+/**
* Set this to an integer to only do synchronous site_stats updates
* one every *this many* updates. The other requests go into pending
* delta values in $wgMemc. Make sure that $wgMemc is a global cache.
@@ -4621,7 +4809,6 @@ $wgJavaScriptTestConfig = array(
),
);
-
/**
* Overwrite the caching key prefix with custom value.
* @since 1.19
@@ -4650,7 +4837,7 @@ $wgDebugToolbar = false;
$wgDisableTextSearch = false;
/**
- * Set to true to have nicer highligted text in search results,
+ * Set to true to have nicer highlighted text in search results,
* by default off due to execution overhead
*/
$wgAdvancedSearchHighlighting = false;
@@ -4676,7 +4863,7 @@ $wgCountTotalSearchHits = false;
/**
* Template for OpenSearch suggestions, defaults to API action=opensearch
*
- * Sites with heavy load would tipically have these point to a custom
+ * Sites with heavy load would typically have these point to a custom
* PHP wrapper to avoid firing up mediawiki for every keystroke
*
* Placeholders: {searchTerms}
@@ -4724,7 +4911,7 @@ $wgNamespacesToBeSearchedDefault = array(
*/
$wgNamespacesToBeSearchedHelp = array(
NS_PROJECT => true,
- NS_HELP => true,
+ NS_HELP => true,
);
/**
@@ -4751,10 +4938,10 @@ $wgDisableInternalSearch = false;
* To forward to Google you'd have something like:
* @code
* $wgSearchForwardUrl =
- * 'http://www.google.com/search?q=$1' .
- * '&domains=http://example.com' .
- * '&sitesearch=http://example.com' .
- * '&ie=utf-8&oe=utf-8';
+ * 'http://www.google.com/search?q=$1' .
+ * '&domains=http://example.com' .
+ * '&sitesearch=http://example.com' .
+ * '&ie=utf-8&oe=utf-8';
* @endcode
*/
$wgSearchForwardUrl = null;
@@ -4768,14 +4955,14 @@ $wgUseTwoButtonsSearchForm = true;
/**
* Array of namespaces to generate a Google sitemap for when the
- * maintenance/generateSitemap.php script is run, or false if one is to be ge-
- * nerated for all namespaces.
+ * maintenance/generateSitemap.php script is run, or false if one is to be
+ * generated for all namespaces.
*/
$wgSitemapNamespaces = false;
/**
* Custom namespace priorities for sitemaps. Setting this will allow you to
- * set custom priorities to namsepaces when sitemaps are generated using the
+ * set custom priorities to namespaces when sitemaps are generated using the
* maintenance/generateSitemap.php script.
*
* This should be a map of namespace IDs to priority
@@ -4805,7 +4992,7 @@ $wgEnableSearchContributorsByIP = true;
/**
* Path to the GNU diff3 utility. If the file doesn't exist, edit conflicts will
- * fall back to the old behaviour (no merging).
+ * fall back to the old behavior (no merging).
*/
$wgDiff3 = '/usr/bin/diff3';
@@ -4816,7 +5003,7 @@ $wgDiff = '/usr/bin/diff';
/**
* Which namespaces have special treatment where they should be preview-on-open
- * Internaly only Category: pages apply, but using this extensions (e.g. Semantic MediaWiki)
+ * Internally only Category: pages apply, but using this extensions (e.g. Semantic MediaWiki)
* can specify namespaces of pages they have special treatment for
*/
$wgPreviewOnOpenNamespaces = array(
@@ -4858,7 +5045,7 @@ $wgUseAutomaticEditSummaries = true;
* @cond file_level_code
* Set $wgCommandLineMode if it's not set already, to avoid notices
*/
-if( !isset( $wgCommandLineMode ) ) {
+if ( !isset( $wgCommandLineMode ) ) {
$wgCommandLineMode = false;
}
/** @endcond */
@@ -5032,7 +5219,7 @@ $wgOverrideSiteFeed = array();
* $wgOut->isSyndicated() is true.
*/
$wgFeedClasses = array(
- 'rss' => 'RSSFeed',
+ 'rss' => 'RSSFeed',
'atom' => 'AtomFeed',
);
@@ -5078,6 +5265,15 @@ $wgAllowCategorizedRecentChanges = false;
*/
$wgUseTagFilter = true;
+/**
+ * If set to an integer, pages that are watched by this many users or more
+ * will not require the unwatchedpages permission to view the number of
+ * watchers.
+ *
+ * @since 1.21
+ */
+$wgUnwatchedPageThreshold = false;
+
/** @} */ # end RC/watchlist }
/************************************************************************//**
@@ -5180,8 +5376,8 @@ $wgExportAllowHistory = true;
$wgExportMaxHistory = 0;
/**
-* Return distinct author list (when not returning full history)
-*/
+ * Return distinct author list (when not returning full history)
+ */
$wgExportAllowListContributors = false;
/**
@@ -5198,13 +5394,13 @@ $wgExportAllowListContributors = false;
$wgExportMaxLinkDepth = 0;
/**
-* Whether to allow the "export all pages in namespace" option
-*/
+ * Whether to allow the "export all pages in namespace" option
+ */
$wgExportFromNamespaces = false;
/**
-* Whether to allow exporting the entire wiki into a single file
-*/
+ * Whether to allow exporting the entire wiki into a single file
+ */
$wgExportAllowAll = false;
/** @} */ # end of import/export }
@@ -5287,7 +5483,7 @@ $wgAutoloadClasses = array();
* 'version' => 1.9,
* 'path' => __FILE__,
* 'author' => 'Foo Barstein',
- * 'url' => 'http://wwww.example.com/Example%20Extension/',
+ * 'url' => 'http://www.example.com/Example%20Extension/',
* 'description' => 'An example extension',
* 'descriptionmsg' => 'exampleextension-desc',
* );
@@ -5296,6 +5492,11 @@ $wgAutoloadClasses = array();
* Where $type is 'specialpage', 'parserhook', 'variable', 'media' or 'other'.
* Where 'descriptionmsg' can be an array with message key and parameters:
* 'descriptionmsg' => array( 'exampleextension-desc', param1, param2, ... ),
+ *
+ * author can be a string or an array of strings. Authors can be linked using
+ * the regular wikitext link syntax. To have an internationalized version of
+ * "and others" show, add an element "...". This element can also be linked,
+ * for instance "[http://example ...]".
*/
$wgExtensionCredits = array();
@@ -5347,11 +5548,14 @@ $wgJobClasses = array(
'enotifNotify' => 'EnotifNotifyJob',
'fixDoubleRedirect' => 'DoubleRedirectJob',
'uploadFromUrl' => 'UploadFromUrlJob',
+ 'AssembleUploadChunks' => 'AssembleUploadChunksJob',
+ 'PublishStashedFile' => 'PublishStashedFileJob',
+ 'null' => 'NullJob'
);
/**
-
- * Jobs that must be explicitly requested, i.e. aren't run by job runners unless special flags are set.
+ * Jobs that must be explicitly requested, i.e. aren't run by job runners unless
+ * special flags are set. The values here are keys of $wgJobClasses.
*
* These can be:
* - Very long-running jobs.
@@ -5359,7 +5563,25 @@ $wgJobClasses = array(
* - Jobs that you want to run on specialized machines ( like transcoding, or a particular
* machine on your cluster has 'outside' web access you could restrict uploadFromUrl )
*/
-$wgJobTypesExcludedFromDefaultQueue = array();
+$wgJobTypesExcludedFromDefaultQueue = array( 'AssembleUploadChunks', 'PublishStashedFile' );
+
+/**
+ * Map of job types to configuration arrays.
+ * This determines which queue class and storage system is used for each job type.
+ * Job types that do not have explicit configuration will use the 'default' config.
+ * These settings should be global to all wikis.
+ */
+$wgJobTypeConf = array(
+ 'default' => array( 'class' => 'JobQueueDB', 'order' => 'random' ),
+);
+
+/**
+ * Which aggregator to use for tracking which queues have jobs.
+ * These settings should be global to all wikis.
+ */
+$wgJobQueueAggregator = array(
+ 'class' => 'JobQueueAggregatorMemc'
+);
/**
* Additional functions to be performed with updateSpecialPages.
@@ -5486,7 +5708,7 @@ $wgLogRestrictions = array(
*
* @par Example:
* @code
- * $wgFilterLogTypes => array(
+ * $wgFilterLogTypes = array(
* 'move' => true,
* 'import' => false,
* );
@@ -5513,16 +5735,16 @@ $wgFilterLogTypes = array(
* where TYPE is your log type, yoy don't need to use this array.
*/
$wgLogNames = array(
- '' => 'all-logs-page',
- 'block' => 'blocklogpage',
+ '' => 'all-logs-page',
+ 'block' => 'blocklogpage',
'protect' => 'protectlogpage',
- 'rights' => 'rightslog',
- 'delete' => 'dellogpage',
- 'upload' => 'uploadlogpage',
- 'move' => 'movelogpage',
- 'import' => 'importlogpage',
- 'patrol' => 'patrol-log-page',
- 'merge' => 'mergelog',
+ 'rights' => 'rightslog',
+ 'delete' => 'dellogpage',
+ 'upload' => 'uploadlogpage',
+ 'move' => 'movelogpage',
+ 'import' => 'importlogpage',
+ 'patrol' => 'patrol-log-page',
+ 'merge' => 'mergelog',
'suppress' => 'suppressionlog',
);
@@ -5536,16 +5758,16 @@ $wgLogNames = array(
* where TYPE is your log type, yoy don't need to use this array.
*/
$wgLogHeaders = array(
- '' => 'alllogstext',
- 'block' => 'blocklogtext',
+ '' => 'alllogstext',
+ 'block' => 'blocklogtext',
'protect' => 'protectlogtext',
- 'rights' => 'rightslogtext',
- 'delete' => 'dellogpagetext',
- 'upload' => 'uploadlogpagetext',
- 'move' => 'movelogpagetext',
- 'import' => 'importlogpagetext',
- 'patrol' => 'patrol-log-header',
- 'merge' => 'mergelogpagetext',
+ 'rights' => 'rightslogtext',
+ 'delete' => 'dellogpagetext',
+ 'upload' => 'uploadlogpagetext',
+ 'move' => 'movelogpagetext',
+ 'import' => 'importlogpagetext',
+ 'patrol' => 'patrol-log-header',
+ 'merge' => 'mergelogpagetext',
'suppress' => 'suppressionlogtext',
);
@@ -5556,23 +5778,21 @@ $wgLogHeaders = array(
* Extensions with custom log types may add to this array.
*/
$wgLogActions = array(
- 'block/block' => 'blocklogentry',
- 'block/unblock' => 'unblocklogentry',
- 'block/reblock' => 'reblock-logentry',
- 'protect/protect' => 'protectedarticle',
- 'protect/modify' => 'modifiedarticleprotection',
- 'protect/unprotect' => 'unprotectedarticle',
- 'protect/move_prot' => 'movedarticleprotection',
- 'rights/rights' => 'rightslogentry',
- 'rights/autopromote' => 'rightslogentry-autopromote',
- 'upload/upload' => 'uploadedimage',
- 'upload/overwrite' => 'overwroteimage',
- 'upload/revert' => 'uploadedimage',
- 'import/upload' => 'import-logentry-upload',
- 'import/interwiki' => 'import-logentry-interwiki',
- 'merge/merge' => 'pagemerge-logentry',
- 'suppress/block' => 'blocklogentry',
- 'suppress/reblock' => 'reblock-logentry',
+ 'block/block' => 'blocklogentry',
+ 'block/unblock' => 'unblocklogentry',
+ 'block/reblock' => 'reblock-logentry',
+ 'protect/protect' => 'protectedarticle',
+ 'protect/modify' => 'modifiedarticleprotection',
+ 'protect/unprotect' => 'unprotectedarticle',
+ 'protect/move_prot' => 'movedarticleprotection',
+ 'upload/upload' => 'uploadedimage',
+ 'upload/overwrite' => 'overwroteimage',
+ 'upload/revert' => 'uploadedimage',
+ 'import/upload' => 'import-logentry-upload',
+ 'import/interwiki' => 'import-logentry-interwiki',
+ 'merge/merge' => 'pagemerge-logentry',
+ 'suppress/block' => 'blocklogentry',
+ 'suppress/reblock' => 'reblock-logentry',
);
/**
@@ -5582,16 +5802,18 @@ $wgLogActions = array(
* @see LogFormatter
*/
$wgLogActionsHandlers = array(
- 'move/move' => 'MoveLogFormatter',
- 'move/move_redir' => 'MoveLogFormatter',
- 'delete/delete' => 'DeleteLogFormatter',
- 'delete/restore' => 'DeleteLogFormatter',
- 'delete/revision' => 'DeleteLogFormatter',
- 'delete/event' => 'DeleteLogFormatter',
+ 'move/move' => 'MoveLogFormatter',
+ 'move/move_redir' => 'MoveLogFormatter',
+ 'delete/delete' => 'DeleteLogFormatter',
+ 'delete/restore' => 'DeleteLogFormatter',
+ 'delete/revision' => 'DeleteLogFormatter',
+ 'delete/event' => 'DeleteLogFormatter',
'suppress/revision' => 'DeleteLogFormatter',
- 'suppress/event' => 'DeleteLogFormatter',
- 'suppress/delete' => 'DeleteLogFormatter',
- 'patrol/patrol' => 'PatrolLogFormatter',
+ 'suppress/event' => 'DeleteLogFormatter',
+ 'suppress/delete' => 'DeleteLogFormatter',
+ 'patrol/patrol' => 'PatrolLogFormatter',
+ 'rights/rights' => 'RightsLogFormatter',
+ 'rights/autopromote' => 'RightsLogFormatter',
);
/**
@@ -5620,110 +5842,10 @@ $wgDisableQueryPageUpdate = false;
/**
* List of special pages, followed by what subtitle they should go under
* at Special:SpecialPages
+ *
+ * @deprecated 1.21 Override SpecialPage::getGroupName instead
*/
-$wgSpecialPageGroups = array(
- 'DoubleRedirects' => 'maintenance',
- 'BrokenRedirects' => 'maintenance',
- 'Lonelypages' => 'maintenance',
- 'Uncategorizedpages' => 'maintenance',
- 'Uncategorizedcategories' => 'maintenance',
- 'Uncategorizedimages' => 'maintenance',
- 'Uncategorizedtemplates' => 'maintenance',
- 'Unusedcategories' => 'maintenance',
- 'Unusedimages' => 'maintenance',
- 'Protectedpages' => 'maintenance',
- 'Protectedtitles' => 'maintenance',
- 'Unusedtemplates' => 'maintenance',
- 'Withoutinterwiki' => 'maintenance',
- 'Longpages' => 'maintenance',
- 'Shortpages' => 'maintenance',
- 'Ancientpages' => 'maintenance',
- 'Deadendpages' => 'maintenance',
- 'Wantedpages' => 'maintenance',
- 'Wantedcategories' => 'maintenance',
- 'Wantedfiles' => 'maintenance',
- 'Wantedtemplates' => 'maintenance',
- 'Unwatchedpages' => 'maintenance',
- 'Fewestrevisions' => 'maintenance',
-
- 'Userlogin' => 'login',
- 'Userlogout' => 'login',
- 'CreateAccount' => 'login',
-
- 'Recentchanges' => 'changes',
- 'Recentchangeslinked' => 'changes',
- 'Watchlist' => 'changes',
- 'Newimages' => 'changes',
- 'Newpages' => 'changes',
- 'Log' => 'changes',
- 'Tags' => 'changes',
-
- 'Upload' => 'media',
- 'Listfiles' => 'media',
- 'MIMEsearch' => 'media',
- 'FileDuplicateSearch' => 'media',
- 'Filepath' => 'media',
-
- 'Listusers' => 'users',
- 'Activeusers' => 'users',
- 'Listgrouprights' => 'users',
- 'BlockList' => 'users',
- 'Contributions' => 'users',
- 'Emailuser' => 'users',
- 'Listadmins' => 'users',
- 'Listbots' => 'users',
- 'Userrights' => 'users',
- 'Block' => 'users',
- 'Unblock' => 'users',
- 'Preferences' => 'users',
- 'ChangeEmail' => 'users',
- 'ChangePassword' => 'users',
- 'DeletedContributions' => 'users',
- 'PasswordReset' => 'users',
-
- 'Mostlinked' => 'highuse',
- 'Mostlinkedcategories' => 'highuse',
- 'Mostlinkedtemplates' => 'highuse',
- 'Mostcategories' => 'highuse',
- 'Mostimages' => 'highuse',
- 'Mostinterwikis' => 'highuse',
- 'Mostrevisions' => 'highuse',
-
- 'Allpages' => 'pages',
- 'Prefixindex' => 'pages',
- 'Listredirects' => 'pages',
- 'Categories' => 'pages',
- 'Disambiguations' => 'pages',
-
- 'Randompage' => 'redirects',
- 'Randomredirect' => 'redirects',
- 'Mypage' => 'redirects',
- 'Mytalk' => 'redirects',
- 'Mycontributions' => 'redirects',
- 'Search' => 'redirects',
- 'LinkSearch' => 'redirects',
-
- 'ComparePages' => 'pagetools',
- 'Movepage' => 'pagetools',
- 'MergeHistory' => 'pagetools',
- 'Revisiondelete' => 'pagetools',
- 'Undelete' => 'pagetools',
- 'Export' => 'pagetools',
- 'Import' => 'pagetools',
- 'Whatlinkshere' => 'pagetools',
-
- 'Statistics' => 'wiki',
- 'Version' => 'wiki',
- 'Lockdb' => 'wiki',
- 'Unlockdb' => 'wiki',
- 'Allmessages' => 'wiki',
- 'Popularpages' => 'wiki',
-
- 'Specialpages' => 'other',
- 'Blockme' => 'other',
- 'Booksources' => 'other',
- 'JavaScriptTest' => 'other',
-);
+$wgSpecialPageGroups = array();
/** Whether or not to sort special pages in Special:Specialpages */
@@ -5759,24 +5881,24 @@ $wgMaxRedirectLinksRetrieved = 500;
* Unsetting core actions will probably cause things to complain loudly.
*/
$wgActions = array(
- 'credits' => true,
- 'delete' => true,
- 'edit' => true,
- 'history' => true,
- 'info' => true,
- 'markpatrolled' => true,
- 'protect' => true,
- 'purge' => true,
- 'raw' => true,
- 'render' => true,
- 'revert' => true,
+ 'credits' => true,
+ 'delete' => true,
+ 'edit' => true,
+ 'history' => true,
+ 'info' => true,
+ 'markpatrolled' => true,
+ 'protect' => true,
+ 'purge' => true,
+ 'raw' => true,
+ 'render' => true,
+ 'revert' => true,
'revisiondelete' => true,
- 'rollback' => true,
- 'submit' => true,
- 'unprotect' => true,
- 'unwatch' => true,
- 'view' => true,
- 'watch' => true,
+ 'rollback' => true,
+ 'submit' => true,
+ 'unprotect' => true,
+ 'unwatch' => true,
+ 'view' => true,
+ 'watch' => true,
);
/**
@@ -5818,14 +5940,14 @@ $wgNamespaceRobotPolicies = array();
/**
* Robot policies per article. These override the per-namespace robot policies.
- * Must be in the form of an array where the key part is a properly canonical-
- * ised text form title and the value is a robot policy.
+ * Must be in the form of an array where the key part is a properly canonicalised
+ * text form title and the value is a robot policy.
*
* @par Example:
* @code
* $wgArticleRobotPolicies = array(
- * 'Main Page' => 'noindex,follow',
- * 'User:Bob' => 'index,follow',
+ * 'Main Page' => 'noindex,follow',
+ * 'User:Bob' => 'index,follow',
* );
* @endcode
*
@@ -5882,6 +6004,22 @@ $wgEnableAPI = true;
$wgEnableWriteAPI = true;
/**
+ *
+ * WARNING: SECURITY THREAT - debug use only
+ *
+ * Disables many security checks in the API for debugging purposes.
+ * This flag should never be used on the production servers, as it introduces
+ * a number of potential security holes. Even when enabled, the validation
+ * will still be performed, but instead of failing, API will return a warning.
+ * Also, there will always be a warning notifying that this flag is set.
+ * At this point, the flag allows GET requests to go through for modules
+ * requiring POST.
+ *
+ * @since 1.21
+ */
+$wgDebugAPI = false;
+
+/**
* API module extensions.
* Associative array mapping module name to class name.
* Extension modules may override the core modules.
@@ -5893,6 +6031,12 @@ $wgAPIPropModules = array();
$wgAPIListModules = array();
/**
+ * This variable is ignored. To add your module to the API, please add it to $wgAPI*Modules
+ * @deprecated since 1.21
+ */
+$wgAPIGeneratorModules = array();
+
+/**
* Maximum amount of rows to scan in a DB query in the API
* The default value is generally fine
*/
@@ -5919,7 +6063,7 @@ $wgAPIRequestLog = false;
/**
* Set the timeout for the API help text cache. If set to 0, caching disabled
*/
-$wgAPICacheHelpTimeout = 60*60;
+$wgAPICacheHelpTimeout = 60 * 60;
/**
* Enable AJAX framework
@@ -5961,10 +6105,10 @@ $wgAjaxLicensePreview = true;
* @par Example:
* @code
* $wgCrossSiteAJAXdomains = array(
- * 'www.mediawiki.org',
- * '*.wikipedia.org',
- * '*.wikimedia.org',
- * '*.wiktionary.org',
+ * 'www.mediawiki.org',
+ * '*.wikipedia.org',
+ * '*.wikimedia.org',
+ * '*.wiktionary.org',
* );
* @endcode
*/
@@ -5997,11 +6141,42 @@ $wgMaxShellMemory = 102400;
$wgMaxShellFileSize = 102400;
/**
- * Maximum CPU time in seconds for shell processes under linux
+ * Maximum CPU time in seconds for shell processes under Linux
*/
$wgMaxShellTime = 180;
/**
+ * Maximum wall clock time (i.e. real time, of the kind the clock on the wall
+ * would measure) in seconds for shell processes under Linux
+ */
+$wgMaxShellWallClockTime = 180;
+
+/**
+ * Under Linux: a cgroup directory used to constrain memory usage of shell
+ * commands. The directory must be writable by the user which runs MediaWiki.
+ *
+ * If specified, this is used instead of ulimit, which is inaccurate, and
+ * causes malloc() to return NULL, which exposes bugs in C applications, making
+ * them segfault or deadlock.
+ *
+ * A wrapper script will create a cgroup for each shell command that runs, as
+ * a subgroup of the specified cgroup. If the memory limit is exceeded, the
+ * kernel will send a SIGKILL signal to a process in the subgroup.
+ *
+ * @par Example:
+ * @code
+ * mkdir -p /sys/fs/cgroup/memory/mediawiki
+ * mkdir -m 0777 /sys/fs/cgroup/memory/mediawiki/job
+ * echo '$wgShellCgroup = "/sys/fs/cgroup/memory/mediawiki/job";' >> LocalSettings.php
+ * @endcode
+ *
+ * The reliability of cgroup cleanup can be improved by installing a
+ * notify_on_release script in the root cgroup, see e.g.
+ * https://gerrit.wikimedia.org/r/#/c/40784
+ */
+$wgShellCgroup = false;
+
+/**
* Executable path of the PHP cli binary (php/php5). Should be set up on install.
*/
$wgPhpCli = '/usr/bin/php';
@@ -6061,6 +6236,15 @@ $wgUpdateRowsPerJob = 500;
*/
$wgUpdateRowsPerQuery = 100;
+/**
+ * Do not purge all the pages that use a page when it is edited
+ * if there are more than this many such pages. This is used to
+ * avoid invalidating a large portion of the squid/parser cache.
+ *
+ * This setting should factor in any squid/parser cache expiry settings.
+ */
+$wgMaxBacklinksInvalidate = false;
+
/** @} */ # End job queue }
/************************************************************************//**
@@ -6113,20 +6297,6 @@ $wgCompiledFiles = array();
/** @} */ # End of HipHop compilation }
-
-/************************************************************************//**
- * @name Mobile support
- * @{
- */
-
-/**
- * Name of the class used for mobile device detection, must be inherited from
- * IDeviceDetector.
- */
-$wgDeviceDetectionClass = 'DeviceDetection';
-
-/** @} */ # End of Mobile support }
-
/************************************************************************//**
* @name Miscellaneous
* @{
@@ -6211,6 +6381,57 @@ $wgDBtestuser = ''; //db user that has permission to create and drop the test da
$wgDBtestpassword = '';
/**
+ * Associative array mapping namespace IDs to the name of the content model pages in that namespace should have by
+ * default (use the CONTENT_MODEL_XXX constants). If no special content type is defined for a given namespace,
+ * pages in that namespace will use the CONTENT_MODEL_WIKITEXT (except for the special case of JS and CS pages).
+ *
+ * @since 1.21
+ */
+$wgNamespaceContentModels = array();
+
+/**
+ * How to react if a plain text version of a non-text Content object is requested using ContentHandler::getContentText():
+ *
+ * * 'ignore': return null
+ * * 'fail': throw an MWException
+ * * 'serialize': serialize to default format
+ *
+ * @since 1.21
+ */
+$wgContentHandlerTextFallback = 'ignore';
+
+/**
+ * Set to false to disable use of the database fields introduced by the ContentHandler facility.
+ * This way, the ContentHandler facility can be used without any additional information in the database.
+ * A page's content model is then derived solely from the page's title. This however means that changing
+ * a page's default model (e.g. using $wgNamespaceContentModels) will break the page and/or make the content
+ * inaccessible. This also means that pages can not be moved to a title that would default to a different
+ * content model.
+ *
+ * Overall, with $wgContentHandlerUseDB = false, no database updates are needed, but content handling
+ * is less robust and less flexible.
+ *
+ * @since 1.21
+ */
+$wgContentHandlerUseDB = true;
+
+/**
+ * Determines which types of text are parsed as wikitext. This does not imply that these kinds
+ * of texts are also rendered as wikitext, it only means that links, magic words, etc will have
+ * the effect on the database they would have on a wikitext page.
+ *
+ * @todo: On the long run, it would be nice to put categories etc into a separate structure,
+ * or at least parse only the contents of comments in the scripts.
+ *
+ * @since 1.21
+ */
+$wgTextModelsToParse = array(
+ CONTENT_MODEL_WIKITEXT, // Just for completeness, wikitext will always be parsed.
+ CONTENT_MODEL_JAVASCRIPT, // Make categories etc work, people put them into comments.
+ CONTENT_MODEL_CSS, // Make categories etc work, people put them into comments.
+);
+
+/**
* Whether the user must enter their password to change their e-mail address
*
* @since 1.20
@@ -6218,6 +6439,15 @@ $wgDBtestpassword = '';
$wgRequirePasswordforEmailChange = true;
/**
+ * Register handlers for specific types of sites.
+ *
+ * @since 1.20
+ */
+$wgSiteTypes = array(
+ 'mediawiki' => 'MediaWikiSite',
+);
+
+/**
* For really cool vim folding this needs to be at the end:
* vim: foldmarker=@{,@} foldmethod=marker
* @}
diff --git a/includes/DeferredUpdates.php b/includes/DeferredUpdates.php
index b4989a69..89c4df68 100644
--- a/includes/DeferredUpdates.php
+++ b/includes/DeferredUpdates.php
@@ -34,7 +34,7 @@ interface DeferrableUpdate {
}
/**
- * Class for mananging the deferred updates.
+ * Class for managing the deferred updates.
*
* @since 1.19
*/
@@ -66,7 +66,7 @@ class DeferredUpdates {
/**
* Do any deferred updates and clear the list
*
- * @param $commit String: set to 'commit' to commit after every update to
+ * @param string $commit set to 'commit' to commit after every update to
* prevent lock contention
*/
public static function doUpdates( $commit = '' ) {
@@ -92,7 +92,7 @@ class DeferredUpdates {
$update->doUpdate();
if ( $doCommit && $dbw->trxLevel() ) {
- $dbw->commit( __METHOD__ );
+ $dbw->commit( __METHOD__, 'flush' );
}
} catch ( MWException $e ) {
// We don't want exceptions thrown during deferred updates to
diff --git a/includes/Defines.php b/includes/Defines.php
index be9f9816..c4a86335 100644
--- a/includes/Defines.php
+++ b/includes/Defines.php
@@ -39,7 +39,7 @@ define( 'MW_SPECIALPAGE_VERSION', 2 );
define( 'DBO_DEBUG', 1 );
define( 'DBO_NOBUFFER', 2 );
define( 'DBO_IGNORE', 4 );
-define( 'DBO_TRX', 8 );
+define( 'DBO_TRX', 8 ); // automatically start transaction on first query
define( 'DBO_DEFAULT', 16 );
define( 'DBO_PERSISTENT', 32 );
define( 'DBO_SYSDBA', 64 ); //for oracle maintenance
@@ -54,13 +54,12 @@ define( 'DBO_COMPRESS', 512 );
*/
define( 'DB_SLAVE', -1 ); # Read from the slave (or only server)
define( 'DB_MASTER', -2 ); # Write to master (or only server)
-define( 'DB_LAST', -3 ); # Whatever database was used last
/**@}*/
# Obsolete aliases
define( 'DB_READ', -1 );
define( 'DB_WRITE', -2 );
-
+define( 'DB_LAST', -3 ); # deprecated since 2008, usage throws exception
/**@{
* Virtual namespaces; don't appear in the page database
@@ -138,7 +137,7 @@ define( 'MEDIATYPE_ARCHIVE', 'ARCHIVE' ); // archive file (zip, tar, etc)
*/
define( 'AV_NO_VIRUS', 0 ); #scan ok, no virus found
define( 'AV_VIRUS_FOUND', 1 ); #virus found!
-define( 'AV_SCAN_ABORTED', -1 ); #scan aborted, the file is probably imune
+define( 'AV_SCAN_ABORTED', -1 ); #scan aborted, the file is probably immune
define( 'AV_SCAN_FAILED', false ); #scan failed (scanner not found or error in scanner)
/**@}*/
@@ -171,11 +170,12 @@ define( 'MW_DATE_ISO', 'ISO 8601' );
/**@{
* RecentChange type identifiers
*/
-define( 'RC_EDIT', 0);
-define( 'RC_NEW', 1);
-define( 'RC_MOVE', 2); // obsolete
-define( 'RC_LOG', 3);
-define( 'RC_MOVE_OVER_REDIRECT', 4); // obsolete
+define( 'RC_EDIT', 0 );
+define( 'RC_NEW', 1 );
+define( 'RC_MOVE', 2 ); // obsolete
+define( 'RC_LOG', 3 );
+define( 'RC_MOVE_OVER_REDIRECT', 4 ); // obsolete
+define( 'RC_EXTERNAL', 5 );
/**@}*/
/**@{
@@ -199,7 +199,6 @@ define( 'LIST_AND', 1 );
define( 'LIST_SET', 2 );
define( 'LIST_NAMES', 3);
define( 'LIST_OR', 4);
-define( 'LIST_SET_PREPARED', 8); // List of (?, ?, ?) for DatabaseIbm_db2
/**@}*/
/**
@@ -213,6 +212,7 @@ require_once __DIR__.'/normal/UtfNormalDefines.php';
define( 'MW_SUPPORTS_EDITFILTERMERGED', 1 );
define( 'MW_SUPPORTS_PARSERFIRSTCALLINIT', 1 );
define( 'MW_SUPPORTS_LOCALISATIONCACHE', 1 );
+define( 'MW_SUPPORTS_CONTENTHANDLER', 1 );
/**@}*/
/** Support for $wgResourceModules */
@@ -225,7 +225,7 @@ define( 'MW_SUPPORTS_RESOURCE_MODULES', 1 );
define( 'OT_HTML', 1 );
define( 'OT_WIKI', 2 );
define( 'OT_PREPROCESS', 3 );
-define( 'OT_MSG' , 3 ); // b/c alias for OT_PREPROCESS
+define( 'OT_MSG', 3 ); // b/c alias for OT_PREPROCESS
define( 'OT_PLAIN', 4 );
/**@}*/
@@ -261,7 +261,7 @@ define( 'APCOND_BLOCKED', 8 );
define( 'APCOND_ISBOT', 9 );
/**@}*/
-/**
+/** @{
* Protocol constants for wfExpandUrl()
*/
define( 'PROTO_HTTP', 'http://' );
@@ -270,3 +270,35 @@ define( 'PROTO_RELATIVE', '//' );
define( 'PROTO_CURRENT', null );
define( 'PROTO_CANONICAL', 1 );
define( 'PROTO_INTERNAL', 2 );
+/**@}*/
+
+/**@{
+ * Content model ids, used by Content and ContentHandler.
+ * These IDs will be exposed in the API and XML dumps.
+ *
+ * Extensions that define their own content model IDs should take
+ * care to avoid conflicts. Using the extension name as a prefix is recommended,
+ * for example 'myextension-somecontent'.
+ */
+define( 'CONTENT_MODEL_WIKITEXT', 'wikitext' );
+define( 'CONTENT_MODEL_JAVASCRIPT', 'javascript' );
+define( 'CONTENT_MODEL_CSS', 'css' );
+define( 'CONTENT_MODEL_TEXT', 'text' );
+/**@}*/
+
+/**@{
+ * Content formats, used by Content and ContentHandler.
+ * These should be MIME types, and will be exposed in the API and XML dumps.
+ *
+ * Extensions are free to use the below formats, or define their own.
+ * It is recommended to stick with the conventions for MIME types.
+ */
+define( 'CONTENT_FORMAT_WIKITEXT', 'text/x-wiki' ); // wikitext
+define( 'CONTENT_FORMAT_JAVASCRIPT', 'text/javascript' ); // for js pages
+define( 'CONTENT_FORMAT_CSS', 'text/css' ); // for css pages
+define( 'CONTENT_FORMAT_TEXT', 'text/plain' ); // for future use, e.g. with some plain-html messages.
+define( 'CONTENT_FORMAT_HTML', 'text/html' ); // for future use, e.g. with some plain-html messages.
+define( 'CONTENT_FORMAT_SERIALIZED', 'application/vnd.php.serialized' ); // for future use with the api and for extensions
+define( 'CONTENT_FORMAT_JSON', 'application/json' ); // for future use with the api, and for use by extensions
+define( 'CONTENT_FORMAT_XML', 'application/xml' ); // for future use with the api, and for use by extensions
+/**@}*/
diff --git a/includes/DeprecatedGlobal.php b/includes/DeprecatedGlobal.php
index 4d7b9689..d48bd0b0 100644
--- a/includes/DeprecatedGlobal.php
+++ b/includes/DeprecatedGlobal.php
@@ -27,7 +27,7 @@
*/
class DeprecatedGlobal extends StubObject {
- // The m's are to stay consistent with parent class.
+ // The m's are to stay consistent with parent class.
protected $mRealValue, $mVersion;
function __construct( $name, $realValue, $version = false ) {
diff --git a/includes/EditPage.php b/includes/EditPage.php
index b762cad1..8b2dbb5f 100644
--- a/includes/EditPage.php
+++ b/includes/EditPage.php
@@ -40,90 +40,90 @@ class EditPage {
/**
* Status: Article successfully updated
*/
- const AS_SUCCESS_UPDATE = 200;
+ const AS_SUCCESS_UPDATE = 200;
/**
* Status: Article successfully created
*/
- const AS_SUCCESS_NEW_ARTICLE = 201;
+ const AS_SUCCESS_NEW_ARTICLE = 201;
/**
* Status: Article update aborted by a hook function
*/
- const AS_HOOK_ERROR = 210;
+ const AS_HOOK_ERROR = 210;
/**
* Status: A hook function returned an error
*/
- const AS_HOOK_ERROR_EXPECTED = 212;
+ const AS_HOOK_ERROR_EXPECTED = 212;
/**
- * Status: User is blocked from editting this page
+ * Status: User is blocked from editing this page
*/
- const AS_BLOCKED_PAGE_FOR_USER = 215;
+ const AS_BLOCKED_PAGE_FOR_USER = 215;
/**
* Status: Content too big (> $wgMaxArticleSize)
*/
- const AS_CONTENT_TOO_BIG = 216;
+ const AS_CONTENT_TOO_BIG = 216;
/**
* Status: User cannot edit? (not used)
*/
- const AS_USER_CANNOT_EDIT = 217;
+ const AS_USER_CANNOT_EDIT = 217;
/**
* Status: this anonymous user is not allowed to edit this page
*/
- const AS_READ_ONLY_PAGE_ANON = 218;
+ const AS_READ_ONLY_PAGE_ANON = 218;
/**
* Status: this logged in user is not allowed to edit this page
*/
- const AS_READ_ONLY_PAGE_LOGGED = 219;
+ const AS_READ_ONLY_PAGE_LOGGED = 219;
/**
* Status: wiki is in readonly mode (wfReadOnly() == true)
*/
- const AS_READ_ONLY_PAGE = 220;
+ const AS_READ_ONLY_PAGE = 220;
/**
* Status: rate limiter for action 'edit' was tripped
*/
- const AS_RATE_LIMITED = 221;
+ const AS_RATE_LIMITED = 221;
/**
- * Status: article was deleted while editting and param wpRecreate == false or form
+ * Status: article was deleted while editing and param wpRecreate == false or form
* was not posted
*/
- const AS_ARTICLE_WAS_DELETED = 222;
+ const AS_ARTICLE_WAS_DELETED = 222;
/**
* Status: user tried to create this page, but is not allowed to do that
* ( Title->usercan('create') == false )
*/
- const AS_NO_CREATE_PERMISSION = 223;
+ const AS_NO_CREATE_PERMISSION = 223;
/**
* Status: user tried to create a blank page
*/
- const AS_BLANK_ARTICLE = 224;
+ const AS_BLANK_ARTICLE = 224;
/**
* Status: (non-resolvable) edit conflict
*/
- const AS_CONFLICT_DETECTED = 225;
+ const AS_CONFLICT_DETECTED = 225;
/**
* Status: no edit summary given and the user has forceeditsummary set and the user is not
- * editting in his own userspace or talkspace and wpIgnoreBlankSummary == false
+ * editing in his own userspace or talkspace and wpIgnoreBlankSummary == false
*/
- const AS_SUMMARY_NEEDED = 226;
+ const AS_SUMMARY_NEEDED = 226;
/**
* Status: user tried to create a new section without content
*/
- const AS_TEXTBOX_EMPTY = 228;
+ const AS_TEXTBOX_EMPTY = 228;
/**
* Status: article is too big (> $wgMaxArticleSize), after merging in the new section
@@ -133,32 +133,57 @@ class EditPage {
/**
* not used
*/
- const AS_OK = 230;
+ const AS_OK = 230;
/**
- * Status: WikiPage::doEdit() was unsuccessfull
+ * Status: WikiPage::doEdit() was unsuccessful
*/
- const AS_END = 231;
+ const AS_END = 231;
/**
* Status: summary contained spam according to one of the regexes in $wgSummarySpamRegex
*/
- const AS_SPAM_ERROR = 232;
+ const AS_SPAM_ERROR = 232;
/**
* Status: anonymous user is not allowed to upload (User::isAllowed('upload') == false)
*/
- const AS_IMAGE_REDIRECT_ANON = 233;
+ const AS_IMAGE_REDIRECT_ANON = 233;
/**
* Status: logged in user is not allowed to upload (User::isAllowed('upload') == false)
*/
- const AS_IMAGE_REDIRECT_LOGGED = 234;
+ const AS_IMAGE_REDIRECT_LOGGED = 234;
+
+ /**
+ * Status: can't parse content
+ */
+ const AS_PARSE_ERROR = 240;
/**
* HTML id and name for the beginning of the edit form.
*/
- const EDITFORM_ID = 'editform';
+ const EDITFORM_ID = 'editform';
+
+ /**
+ * Prefix of key for cookie used to pass post-edit state.
+ * The revision id edited is added after this
+ */
+ const POST_EDIT_COOKIE_KEY_PREFIX = 'PostEditRevision';
+
+ /**
+ * Duration of PostEdit cookie, in seconds.
+ * The cookie will be removed instantly if the JavaScript runs.
+ *
+ * Otherwise, though, we don't want the cookies to accumulate.
+ * RFC 2109 ( https://www.ietf.org/rfc/rfc2109.txt ) specifies a possible limit of only 20 cookies per domain.
+ * This still applies at least to some versions of IE without full updates:
+ * https://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx
+ *
+ * A value of 20 minutes should be enough to take into account slow loads and minor
+ * clock skew while still avoiding cookie accumulation when JavaScript is turned off.
+ */
+ const POST_EDIT_COOKIE_DURATION = 1200;
/**
* @var Article
@@ -214,6 +239,7 @@ class EditPage {
var $textbox1 = '', $textbox2 = '', $summary = '', $nosummary = false;
var $edittime = '', $section = '', $sectiontitle = '', $starttime = '';
var $oldid = 0, $editintro = '', $scrolltop = null, $bot = true;
+ var $contentModel = null, $contentFormat = null;
# Placeholders for text injection by hooks (must be HTML)
# extensions should take care to _append_ to the present value
@@ -225,20 +251,32 @@ class EditPage {
public $editFormTextBottom = '';
public $editFormTextAfterContent = '';
public $previewTextAfterContent = '';
- public $mPreloadText = '';
+ public $mPreloadContent = null;
- /* $didSave should be set to true whenever an article was succesfully altered. */
+ /* $didSave should be set to true whenever an article was successfully altered. */
public $didSave = false;
public $undidRev = 0;
public $suppressIntro = false;
/**
+ * Set to true to allow editing of non-text content types.
+ *
+ * @var bool
+ */
+ public $allowNonTextContent = false;
+
+ /**
* @param $article Article
*/
public function __construct( Article $article ) {
$this->mArticle = $article;
$this->mTitle = $article->getTitle();
+
+ $this->contentModel = $this->mTitle->getContentModel();
+
+ $handler = ContentHandler::getForModelID( $this->contentModel );
+ $this->contentFormat = $handler->getDefaultFormat();
}
/**
@@ -267,7 +305,7 @@ class EditPage {
/**
* Get the context title object.
- * If not set, $wgTitle will be returned. This behavior might changed in
+ * If not set, $wgTitle will be returned. This behavior might change in
* the future to return $this->mTitle instead.
*
* @return Title object
@@ -359,11 +397,10 @@ class EditPage {
$this->isConflict = false;
// css / js subpages of user pages get a special treatment
- $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
- $this->isCssSubpage = $this->mTitle->isCssSubpage();
- $this->isJsSubpage = $this->mTitle->isJsSubpage();
+ $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
+ $this->isCssSubpage = $this->mTitle->isCssSubpage();
+ $this->isJsSubpage = $this->mTitle->isJsSubpage();
$this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage();
- $this->isNew = !$this->mTitle->exists() || $this->section == 'new';
# Show applicable editing introductions
if ( $this->formtype == 'initial' || $this->firsttime ) {
@@ -392,10 +429,13 @@ class EditPage {
wfProfileOut( __METHOD__ );
return;
}
- if ( !$this->mTitle->getArticleID() )
+
+ if ( !$this->mTitle->getArticleID() ) {
wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
- else
+ } else {
wfRunHooks( 'EditFormInitialText', array( $this ) );
+ }
+
}
$this->showEditForm();
@@ -436,8 +476,9 @@ class EditPage {
* "View source for ..." page displaying the source code after the error message.
*
* @since 1.19
- * @param $permErrors Array of permissions errors, as returned by
+ * @param array $permErrors of permissions errors, as returned by
* Title::getUserPermissionsErrors().
+ * @throws PermissionsError
*/
protected function displayPermissionsError( array $permErrors ) {
global $wgRequest, $wgOut;
@@ -450,15 +491,16 @@ class EditPage {
return;
}
- $content = $this->getContent();
+ $content = $this->getContentObject();
# Use the normal message if there's nothing to display
- if ( $this->firsttime && $content === '' ) {
+ if ( $this->firsttime && ( !$content || $content->isEmpty() ) ) {
$action = $this->mTitle->exists() ? 'edit' :
( $this->mTitle->isTalkPage() ? 'createtalk' : 'createpage' );
throw new PermissionsError( $action, $permErrors );
}
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setPageTitle( wfMessage( 'viewsource-title', $this->getContextTitle()->getPrefixedText() ) );
$wgOut->addBacklinkSubtitle( $this->getContextTitle() );
$wgOut->addWikiText( $wgOut->formatPermissionsErrorMessage( $permErrors, 'edit' ) );
@@ -467,13 +509,14 @@ class EditPage {
# If the user made changes, preserve them when showing the markup
# (This happens when a user is blocked during edit, for instance)
if ( !$this->firsttime ) {
- $content = $this->textbox1;
+ $text = $this->textbox1;
$wgOut->addWikiMsg( 'viewyourtext' );
} else {
+ $text = $this->toEditText( $content );
$wgOut->addWikiMsg( 'viewsourcetext' );
}
- $this->showTextbox( $content, 'wpTextbox1', array( 'readonly' ) );
+ $this->showTextbox( $text, 'wpTextbox1', array( 'readonly' ) );
$wgOut->addHTML( Html::rawElement( 'div', array( 'class' => 'templatesUsed' ),
Linker::formatTemplates( $this->getTemplates() ) ) );
@@ -520,11 +563,11 @@ class EditPage {
// Nothing *to* preview for new sections
return false;
} elseif ( ( $wgRequest->getVal( 'preload' ) !== null || $this->mTitle->exists() ) && $wgUser->getOption( 'previewonfirst' ) ) {
- // Standard preference behaviour
+ // Standard preference behavior
return true;
} elseif ( !$this->mTitle->exists() &&
- isset( $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] ) &&
- $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] )
+ isset( $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] ) &&
+ $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] )
{
// Categories are special
return true;
@@ -554,13 +597,15 @@ class EditPage {
}
/**
- * Does this EditPage class support section editing?
- * This is used by EditPage subclasses to indicate their ui cannot handle section edits
+ * Returns whether section editing is supported for the current page.
+ * Subclasses may override this to replace the default behavior, which is
+ * to check ContentHandler::supportsSections.
*
- * @return bool
+ * @return bool true if this edit page supports sections, false otherwise.
*/
protected function isSectionEditSupported() {
- return true;
+ $contentHandler = ContentHandler::getForTitle( $this->mTitle );
+ return $contentHandler->supportsSections();
}
/**
@@ -568,13 +613,19 @@ class EditPage {
* @param $request WebRequest
*/
function importFormData( &$request ) {
- global $wgLang, $wgUser;
+ global $wgContLang, $wgUser;
wfProfileIn( __METHOD__ );
# Section edit can come from either the form or a link
$this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
+ if ( $this->section !== null && $this->section !== '' && !$this->isSectionEditSupported() ) {
+ throw new ErrorPageError( 'sectioneditnotsupported-title', 'sectioneditnotsupported-text' );
+ }
+
+ $this->isNew = !$this->mTitle->exists() || $this->section == 'new';
+
if ( $request->wasPosted() ) {
# These fields need to be checked for encoding.
# Also remove trailing whitespace, but don't remove _initial_
@@ -586,13 +637,15 @@ class EditPage {
// modified by subclasses
wfProfileIn( get_class( $this ) . "::importContentFormData" );
$textbox1 = $this->importContentFormData( $request );
- if ( isset( $textbox1 ) )
+ if ( $textbox1 !== null ) {
$this->textbox1 = $textbox1;
+ }
+
wfProfileOut( get_class( $this ) . "::importContentFormData" );
}
# Truncate for whole multibyte characters
- $this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 255 );
+ $this->summary = $wgContLang->truncate( $request->getText( 'wpSummary' ), 255 );
# If the summary consists of a heading, e.g. '==Foobar==', extract the title from the
# header syntax, e.g. 'Foobar'. This is mainly an issue when we are using wpSummary for
@@ -604,7 +657,7 @@ class EditPage {
# currently doing double duty as both edit summary and section title. Right now this
# is just to allow API edits to work around this limitation, but this should be
# incorporated into the actual edit form when EditPage is rewritten (Bugs 18654, 26312).
- $this->sectiontitle = $wgLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
+ $this->sectiontitle = $wgContLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
$this->sectiontitle = preg_replace( '/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->sectiontitle );
$this->edittime = $request->getVal( 'wpEdittime' );
@@ -661,7 +714,7 @@ class EditPage {
$this->starttime = null;
}
- $this->recreate = $request->getCheck( 'wpRecreate' );
+ $this->recreate = $request->getCheck( 'wpRecreate' );
$this->minoredit = $request->getCheck( 'wpMinoredit' );
$this->watchthis = $request->getCheck( 'wpWatchthis' );
@@ -679,18 +732,18 @@ class EditPage {
} else {
# Not a posted form? Start with nothing.
wfDebug( __METHOD__ . ": Not a posted form.\n" );
- $this->textbox1 = '';
- $this->summary = '';
+ $this->textbox1 = '';
+ $this->summary = '';
$this->sectiontitle = '';
- $this->edittime = '';
- $this->starttime = wfTimestampNow();
- $this->edit = false;
- $this->preview = false;
- $this->save = false;
- $this->diff = false;
- $this->minoredit = false;
- $this->watchthis = $request->getBool( 'watchthis', false ); // Watch may be overriden by request parameters
- $this->recreate = false;
+ $this->edittime = '';
+ $this->starttime = wfTimestampNow();
+ $this->edit = false;
+ $this->preview = false;
+ $this->save = false;
+ $this->diff = false;
+ $this->minoredit = false;
+ $this->watchthis = $request->getBool( 'watchthis', false ); // Watch may be overridden by request parameters
+ $this->recreate = false;
// When creating a new section, we can preload a section title by passing it as the
// preloadtitle parameter in the URL (Bug 13100)
@@ -711,10 +764,17 @@ class EditPage {
}
}
+ $this->oldid = $request->getInt( 'oldid' );
+
$this->bot = $request->getBool( 'bot', true );
$this->nosummary = $request->getBool( 'nosummary' );
- $this->oldid = $request->getInt( 'oldid' );
+ $content_handler = ContentHandler::getForTitle( $this->mTitle );
+ $this->contentModel = $request->getText( 'model', $content_handler->getModelID() ); #may be overridden by revision
+ $this->contentFormat = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision
+
+ #TODO: check if the desired model is allowed in this namespace, and if a transition from the page's current model to the new model is allowed
+ #TODO: check if the desired content model supports the given content format!
$this->live = $request->getCheck( 'live' );
$this->editintro = $request->getText( 'editintro',
@@ -730,7 +790,7 @@ class EditPage {
/**
* Subpage overridable method for extracting the page content data from the
* posted form to be placed in $this->textbox1, if using customized input
- * this method should be overrided and return the page text that will be used
+ * this method should be overridden and return the page text that will be used
* for saving, preview parsing and so on...
*
* @param $request WebRequest
@@ -747,7 +807,13 @@ class EditPage {
function initialiseForm() {
global $wgUser;
$this->edittime = $this->mArticle->getTimestamp();
- $this->textbox1 = $this->getContent( false );
+
+ $content = $this->getContentObject( false ); #TODO: track content object?!
+ if ( $content === false ) {
+ return false;
+ }
+ $this->textbox1 = $this->toEditText( $content );
+
// activate checkboxes if user wants them to be always active
# Sort out the "watch" checkbox
if ( $wgUser->getOption( 'watchdefault' ) ) {
@@ -773,36 +839,65 @@ class EditPage {
/**
* Fetch initial editing page content.
*
- * @param $def_text string
+ * @param $def_text string|bool
* @return mixed string on success, $def_text for invalid sections
* @private
+ * @deprecated since 1.21, get WikiPage::getContent() instead.
*/
- function getContent( $def_text = '' ) {
- global $wgOut, $wgRequest, $wgParser;
+ function getContent( $def_text = false ) {
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+
+ if ( $def_text !== null && $def_text !== false && $def_text !== '' ) {
+ $def_content = $this->toEditContent( $def_text );
+ } else {
+ $def_content = false;
+ }
+
+ $content = $this->getContentObject( $def_content );
+
+ // Note: EditPage should only be used with text based content anyway.
+ return $this->toEditText( $content );
+ }
+
+ /**
+ * @param Content|null $def_content The default value to return
+ *
+ * @return mixed Content on success, $def_content for invalid sections
+ *
+ * @since 1.21
+ */
+ protected function getContentObject( $def_content = null ) {
+ global $wgOut, $wgRequest;
wfProfileIn( __METHOD__ );
- $text = false;
+ $content = false;
// For message page not locally set, use the i18n message.
// For other non-existent articles, use preload text if any.
if ( !$this->mTitle->exists() || $this->section == 'new' ) {
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI && $this->section != 'new' ) {
# If this is a system message, get the default text.
- $text = $this->mTitle->getDefaultMessageText();
+ $msg = $this->mTitle->getDefaultMessageText();
+
+ $content = $this->toEditContent( $msg );
}
- if ( $text === false ) {
+ if ( $content === false ) {
# If requested, preload some text.
$preload = $wgRequest->getVal( 'preload',
// Custom preload text for new sections
$this->section === 'new' ? 'MediaWiki:addsection-preload' : '' );
- $text = $this->getPreloadedText( $preload );
+
+ $content = $this->getPreloadedContent( $preload );
}
// For existing pages, get text based on "undo" or section parameters.
} else {
if ( $this->section != '' ) {
// Get section edit text (returns $def_text for invalid sections)
- $text = $wgParser->getSection( $this->getOriginalContent(), $this->section, $def_text );
+ $orig = $this->getOriginalContent();
+ $content = $orig ? $orig->getSection( $this->section ) : null;
+
+ if ( !$content ) $content = $def_content;
} else {
$undoafter = $wgRequest->getInt( 'undoafter' );
$undo = $wgRequest->getInt( 'undo' );
@@ -818,15 +913,16 @@ class EditPage {
# Sanity check, make sure it's the right page,
# the revisions exist and they were not deleted.
- # Otherwise, $text will be left as-is.
+ # Otherwise, $content will be left as-is.
if ( !is_null( $undorev ) && !is_null( $oldrev ) &&
$undorev->getPage() == $oldrev->getPage() &&
$undorev->getPage() == $this->mTitle->getArticleID() &&
!$undorev->isDeleted( Revision::DELETED_TEXT ) &&
!$oldrev->isDeleted( Revision::DELETED_TEXT ) ) {
- $text = $this->mArticle->getUndoText( $undorev, $oldrev );
- if ( $text === false ) {
+ $content = $this->mArticle->getUndoContent( $undorev, $oldrev );
+
+ if ( $content === false ) {
# Warn the user that something went wrong
$undoMsg = 'failure';
} else {
@@ -859,14 +955,14 @@ class EditPage {
wfMessage( 'undo-' . $undoMsg )->plain() . '</div>', true, /* interface */true );
}
- if ( $text === false ) {
- $text = $this->getOriginalContent();
+ if ( $content === false ) {
+ $content = $this->getOriginalContent();
}
}
}
wfProfileOut( __METHOD__ );
- return $text;
+ return $content;
}
/**
@@ -876,38 +972,51 @@ class EditPage {
* section replaced in its context (using WikiPage::replaceSection())
* to the original text of the edit.
*
- * This difers from Article::getContent() that when a missing revision is
- * encountered the result will be an empty string and not the
+ * This differs from Article::getContent() that when a missing revision is
+ * encountered the result will be null and not the
* 'missing-revision' message.
*
* @since 1.19
- * @return string
+ * @return Content|null
*/
private function getOriginalContent() {
if ( $this->section == 'new' ) {
- return $this->getCurrentText();
+ return $this->getCurrentContent();
}
$revision = $this->mArticle->getRevisionFetched();
if ( $revision === null ) {
- return '';
+ if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
+ $handler = ContentHandler::getForModelID( $this->contentModel );
+
+ return $handler->makeEmptyContent();
}
- return $this->mArticle->getContent();
+ $content = $revision->getContent();
+ return $content;
}
/**
- * Get the actual text of the page. This is basically similar to
- * WikiPage::getRawText() except that when the page doesn't exist an empty
- * string is returned instead of false.
+ * Get the current content of the page. This is basically similar to
+ * WikiPage::getContent( Revision::RAW ) except that when the page doesn't exist an empty
+ * content object is returned instead of null.
*
- * @since 1.19
- * @return string
+ * @since 1.21
+ * @return Content
*/
- private function getCurrentText() {
- $text = $this->mArticle->getRawText();
- if ( $text === false ) {
- return '';
+ protected function getCurrentContent() {
+ $rev = $this->mArticle->getRevision();
+ $content = $rev ? $rev->getContent( Revision::RAW ) : null;
+
+ if ( $content === false || $content === null ) {
+ if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
+ $handler = ContentHandler::getForModelID( $this->contentModel );
+
+ return $handler->makeEmptyContent();
} else {
- return $text;
+ # nasty side-effect, but needed for consistency
+ $this->contentModel = $rev->getContentModel();
+ $this->contentFormat = $rev->getContentFormat();
+
+ return $content;
}
}
@@ -915,47 +1024,111 @@ class EditPage {
* Use this method before edit() to preload some text into the edit box
*
* @param $text string
+ * @deprecated since 1.21, use setPreloadedContent() instead.
*/
public function setPreloadedText( $text ) {
- $this->mPreloadText = $text;
+ ContentHandler::deprecated( __METHOD__, "1.21" );
+
+ $content = $this->toEditContent( $text );
+
+ $this->setPreloadedContent( $content );
+ }
+
+ /**
+ * Use this method before edit() to preload some content into the edit box
+ *
+ * @param $content Content
+ *
+ * @since 1.21
+ */
+ public function setPreloadedContent( Content $content ) {
+ $this->mPreloadContent = $content;
}
/**
* Get the contents to be preloaded into the box, either set by
* an earlier setPreloadText() or by loading the given page.
*
- * @param $preload String: representing the title to preload from.
+ * @param string $preload representing the title to preload from.
+ *
* @return String
+ *
+ * @deprecated since 1.21, use getPreloadedContent() instead
*/
protected function getPreloadedText( $preload ) {
- global $wgUser, $wgParser;
+ ContentHandler::deprecated( __METHOD__, "1.21" );
+
+ $content = $this->getPreloadedContent( $preload );
+ $text = $this->toEditText( $content );
- if ( !empty( $this->mPreloadText ) ) {
- return $this->mPreloadText;
+ return $text;
+ }
+
+ /**
+ * Get the contents to be preloaded into the box, either set by
+ * an earlier setPreloadText() or by loading the given page.
+ *
+ * @param string $preload representing the title to preload from.
+ *
+ * @return Content
+ *
+ * @since 1.21
+ */
+ protected function getPreloadedContent( $preload ) {
+ global $wgUser;
+
+ if ( !empty( $this->mPreloadContent ) ) {
+ return $this->mPreloadContent;
}
+ $handler = ContentHandler::getForTitle( $this->getTitle() );
+
if ( $preload === '' ) {
- return '';
+ return $handler->makeEmptyContent();
}
$title = Title::newFromText( $preload );
# Check for existence to avoid getting MediaWiki:Noarticletext
- if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
- return '';
+ if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
+ //TODO: somehow show a warning to the user!
+ return $handler->makeEmptyContent();
}
$page = WikiPage::factory( $title );
if ( $page->isRedirect() ) {
$title = $page->getRedirectTarget();
# Same as before
- if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
- return '';
+ if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
+ //TODO: somehow show a warning to the user!
+ return $handler->makeEmptyContent();
}
$page = WikiPage::factory( $title );
}
$parserOptions = ParserOptions::newFromUser( $wgUser );
- return $wgParser->getPreloadText( $page->getRawText(), $title, $parserOptions );
+ $content = $page->getContent( Revision::RAW );
+
+ if ( !$content ) {
+ //TODO: somehow show a warning to the user!
+ return $handler->makeEmptyContent();
+ }
+
+ if ( $content->getModel() !== $handler->getModelID() ) {
+ $converted = $content->convert( $handler->getModelID() );
+
+ if ( !$converted ) {
+ //TODO: somehow show a warning to the user!
+ wfDebug( "Attempt to preload incompatible content: "
+ . "can't convert " . $content->getModel()
+ . " to " . $handler->getModelID() );
+
+ return $handler->makeEmptyContent();
+ }
+
+ $content = $converted;
+ }
+
+ return $content->preloadTransform( $title, $parserOptions );
}
/**
@@ -974,7 +1147,35 @@ class EditPage {
}
/**
+ * Sets post-edit cookie indicating the user just saved a particular revision.
+ *
+ * This uses a temporary cookie for each revision ID so separate saves will never
+ * interfere with each other.
+ *
+ * The cookie is deleted in the mediawiki.action.view.postEdit JS module after
+ * the redirect. It must be clearable by JavaScript code, so it must not be
+ * marked HttpOnly. The JavaScript code converts the cookie to a wgPostEdit config
+ * variable.
+ *
+ * Since WebResponse::setcookie does not allow forcing HttpOnly for a single
+ * cookie, we have to use PHP's setcookie() directly.
+ *
+ * We use a path of '/' since wgCookiePath is not exposed to JS
+ *
+ * If the variable were set on the server, it would be cached, which is unwanted
+ * since the post-edit state should only apply to the load right after the save.
+ */
+ protected function setPostEditCookie() {
+ global $wgCookiePrefix, $wgCookieDomain;
+ $revisionId = $this->mArticle->getLatest();
+ $postEditKey = self::POST_EDIT_COOKIE_KEY_PREFIX . $revisionId;
+
+ setcookie( $wgCookiePrefix . $postEditKey, '1', time() + self::POST_EDIT_COOKIE_DURATION, '/', $wgCookieDomain );
+ }
+
+ /**
* Attempt submission
+ * @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
* @return bool false if output is done, true if the rest of the form should be displayed
*/
function attemptSave() {
@@ -987,6 +1188,9 @@ class EditPage {
// FIXME: once the interface for internalAttemptSave() is made nicer, this should use the message in $status
if ( $status->value == self::AS_SUCCESS_UPDATE || $status->value == self::AS_SUCCESS_NEW_ARTICLE ) {
$this->didSave = true;
+ if ( !$resultDetails['nullEdit'] ) {
+ $this->setPostEditCookie();
+ }
}
switch ( $status->value ) {
@@ -1003,6 +1207,10 @@ class EditPage {
case self::AS_HOOK_ERROR:
return false;
+ case self::AS_PARSE_ERROR:
+ $wgOut->addWikiText( '<div class="error">' . $status->getWikiText() . '</div>' );
+ return true;
+
case self::AS_SUCCESS_NEW_ARTICLE:
$query = $resultDetails['redirect'] ? 'redirect=no' : '';
$anchor = isset ( $resultDetails['sectionanchor'] ) ? $resultDetails['sectionanchor'] : '';
@@ -1067,10 +1275,62 @@ class EditPage {
}
/**
+ * Run hooks that can filter edits just before they get saved.
+ *
+ * @param Content $content the Content to filter.
+ * @param Status $status for reporting the outcome to the caller
+ * @param User $user the user performing the edit
+ *
+ * @return bool
+ */
+ protected function runPostMergeFilters( Content $content, Status $status, User $user ) {
+ // Run old style post-section-merge edit filter
+ if ( !ContentHandler::runLegacyHooks( 'EditFilterMerged',
+ array( $this, $content, &$this->hookError, $this->summary ) ) ) {
+
+ # Error messages etc. could be handled within the hook...
+ $status->fatal( 'hookaborted' );
+ $status->value = self::AS_HOOK_ERROR;
+ return false;
+ } elseif ( $this->hookError != '' ) {
+ # ...or the hook could be expecting us to produce an error
+ $status->fatal( 'hookaborted' );
+ $status->value = self::AS_HOOK_ERROR_EXPECTED;
+ return false;
+ }
+
+ // Run new style post-section-merge edit filter
+ if ( !wfRunHooks( 'EditFilterMergedContent',
+ array( $this->mArticle->getContext(), $content, $status, $this->summary,
+ $user, $this->minoredit ) ) ) {
+
+ # Error messages etc. could be handled within the hook...
+ // XXX: $status->value may already be something informative...
+ $this->hookError = $status->getWikiText();
+ $status->fatal( 'hookaborted' );
+ $status->value = self::AS_HOOK_ERROR;
+ return false;
+ } elseif ( !$status->isOK() ) {
+ # ...or the hook could be expecting us to produce an error
+ // FIXME this sucks, we should just use the Status object throughout
+ $this->hookError = $status->getWikiText();
+ $status->fatal( 'hookaborted' );
+ $status->value = self::AS_HOOK_ERROR_EXPECTED;
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* Attempt submission (no UI)
*
- * @param $result
- * @param $bot bool
+ * @param array $result array to add statuses to, currently with the possible keys:
+ * spam - string - Spam string from content if any spam is detected by matchSpamRegex
+ * sectionanchor - string - Section anchor for a section save
+ * nullEdit - boolean - Set if doEditContent is OK. True if null edit, false otherwise.
+ * redirect - boolean - Set if doEditContent is OK. True if resulting revision is a redirect
+ * @param bool $bot True if edit is being made under the bot right.
*
* @return Status object, possibly with a message, but always with one of the AS_* constants in $status->value,
*
@@ -1083,7 +1343,7 @@ class EditPage {
$status = Status::newGood();
- wfProfileIn( __METHOD__ );
+ wfProfileIn( __METHOD__ );
wfProfileIn( __METHOD__ . '-checks' );
if ( !wfRunHooks( 'EditPage::attemptSave', array( $this ) ) ) {
@@ -1091,19 +1351,30 @@ class EditPage {
$status->fatal( 'hookaborted' );
$status->value = self::AS_HOOK_ERROR;
wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
+ wfProfileOut( __METHOD__ );
+ return $status;
+ }
+
+ try {
+ # Construct Content object
+ $textbox_content = $this->toEditContent( $this->textbox1 );
+ } catch ( MWContentSerializationException $ex ) {
+ $status->fatal( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
+ $status->value = self::AS_PARSE_ERROR;
+ wfProfileOut( __METHOD__ . '-checks' );
+ wfProfileOut( __METHOD__ );
return $status;
}
# Check image redirect
if ( $this->mTitle->getNamespace() == NS_FILE &&
- Title::newFromRedirect( $this->textbox1 ) instanceof Title &&
+ $textbox_content->isRedirect() &&
!$wgUser->isAllowed( 'upload' ) ) {
$code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED;
$status->setResult( false, $code );
wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
+ wfProfileOut( __METHOD__ );
return $status;
}
@@ -1209,7 +1480,7 @@ class EditPage {
if ( $new ) {
// Late check for create permission, just in case *PARANOIA*
- if ( !$this->mTitle->userCan( 'create' ) ) {
+ if ( !$this->mTitle->userCan( 'create', $wgUser ) ) {
$status->fatal( 'nocreatetext' );
$status->value = self::AS_NO_CREATE_PERMISSION;
wfDebug( __METHOD__ . ": no create permission\n" );
@@ -1224,28 +1495,18 @@ class EditPage {
return $status;
}
- // Run post-section-merge edit filter
- if ( !wfRunHooks( 'EditFilterMerged', array( $this, $this->textbox1, &$this->hookError, $this->summary ) ) ) {
- # Error messages etc. could be handled within the hook...
- $status->fatal( 'hookaborted' );
- $status->value = self::AS_HOOK_ERROR;
- wfProfileOut( __METHOD__ );
- return $status;
- } elseif ( $this->hookError != '' ) {
- # ...or the hook could be expecting us to produce an error
- $status->fatal( 'hookaborted' );
- $status->value = self::AS_HOOK_ERROR_EXPECTED;
+ if ( !$this->runPostMergeFilters( $textbox_content, $status, $wgUser ) ) {
wfProfileOut( __METHOD__ );
return $status;
}
- $text = $this->textbox1;
+ $content = $textbox_content;
+
$result['sectionanchor'] = '';
if ( $this->section == 'new' ) {
if ( $this->sectiontitle !== '' ) {
// Insert the section title above the content.
- $text = wfMessage( 'newsectionheaderdefaultlevel', $this->sectiontitle )
- ->inContentLanguage()->text() . "\n\n" . $text;
+ $content = $content->addSectionHeader( $this->sectiontitle );
// Jump to the new section
$result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
@@ -1260,8 +1521,7 @@ class EditPage {
}
} elseif ( $this->summary !== '' ) {
// Insert the section title above the content.
- $text = wfMessage( 'newsectionheaderdefaultlevel', $this->summary )
- ->inContentLanguage()->text() . "\n\n" . $text;
+ $content = $content->addSectionHeader( $this->summary );
// Jump to the new section
$result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
@@ -1275,10 +1535,13 @@ class EditPage {
$status->value = self::AS_SUCCESS_NEW_ARTICLE;
- } else {
+ } else { # not $new
# Article exists. Check for edit conflict.
+
+ $this->mArticle->clear(); # Force reload of dates, etc.
$timestamp = $this->mArticle->getTimestamp();
+
wfDebug( "timestamp: {$timestamp}, edittime: {$this->edittime}\n" );
if ( $timestamp != $this->edittime ) {
@@ -1295,7 +1558,8 @@ class EditPage {
$this->isConflict = false;
wfDebug( __METHOD__ . ": conflict suppressed; new section\n" );
}
- } elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER, $this->mTitle->getArticleID(), $wgUser->getId(), $this->edittime ) ) {
+ } elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER, $this->mTitle->getArticleID(),
+ $wgUser->getId(), $this->edittime ) ) {
# Suppress edit conflict with self, except for section edits where merging is required.
wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
$this->isConflict = false;
@@ -1310,26 +1574,31 @@ class EditPage {
$sectionTitle = $this->summary;
}
+ $content = null;
+
if ( $this->isConflict ) {
- wfDebug( __METHOD__ . ": conflict! getting section '$this->section' for time '$this->edittime' (article time '{$timestamp}')\n" );
- $text = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle, $this->edittime );
+ wfDebug( __METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
+ . " (article time '{$timestamp}')\n" );
+
+ $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle, $this->edittime );
} else {
- wfDebug( __METHOD__ . ": getting section '$this->section'\n" );
- $text = $this->mArticle->replaceSection( $this->section, $this->textbox1, $sectionTitle );
+ wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
+ $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle );
}
- if ( is_null( $text ) ) {
+
+ if ( is_null( $content ) ) {
wfDebug( __METHOD__ . ": activating conflict; section replace failed.\n" );
$this->isConflict = true;
- $text = $this->textbox1; // do not try to merge here!
+ $content = $textbox_content; // do not try to merge here!
} elseif ( $this->isConflict ) {
# Attempt merge
- if ( $this->mergeChangesInto( $text ) ) {
+ if ( $this->mergeChangesIntoContent( $content ) ) {
// Successful merge! Maybe we should tell the user the good news?
$this->isConflict = false;
wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" );
} else {
$this->section = '';
- $this->textbox1 = $text;
+ $this->textbox1 = ContentHandler::getContentText( $content );
wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" );
}
}
@@ -1340,58 +1609,45 @@ class EditPage {
return $status;
}
- // Run post-section-merge edit filter
- if ( !wfRunHooks( 'EditFilterMerged', array( $this, $text, &$this->hookError, $this->summary ) ) ) {
- # Error messages etc. could be handled within the hook...
- $status->fatal( 'hookaborted' );
- $status->value = self::AS_HOOK_ERROR;
- wfProfileOut( __METHOD__ );
- return $status;
- } elseif ( $this->hookError != '' ) {
- # ...or the hook could be expecting us to produce an error
- $status->fatal( 'hookaborted' );
- $status->value = self::AS_HOOK_ERROR_EXPECTED;
+ if ( !$this->runPostMergeFilters( $content, $status, $wgUser ) ) {
wfProfileOut( __METHOD__ );
return $status;
}
- # Handle the user preference to force summaries here, but not for null edits
- if ( $this->section != 'new' && !$this->allowBlankSummary
- && $this->getOriginalContent() != $text
- && !Title::newFromRedirect( $text ) ) # check if it's not a redirect
- {
- if ( md5( $this->summary ) == $this->autoSumm ) {
+ if ( $this->section == 'new' ) {
+ // Handle the user preference to force summaries here
+ if ( !$this->allowBlankSummary && trim( $this->summary ) == '' ) {
$this->missingSummary = true;
- $status->fatal( 'missingsummary' );
+ $status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
$status->value = self::AS_SUMMARY_NEEDED;
wfProfileOut( __METHOD__ );
return $status;
}
- }
- # And a similar thing for new sections
- if ( $this->section == 'new' && !$this->allowBlankSummary ) {
- if ( trim( $this->summary ) == '' ) {
- $this->missingSummary = true;
- $status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
- $status->value = self::AS_SUMMARY_NEEDED;
+ // Do not allow the user to post an empty comment
+ if ( $this->textbox1 == '' ) {
+ $this->missingComment = true;
+ $status->fatal( 'missingcommenttext' );
+ $status->value = self::AS_TEXTBOX_EMPTY;
wfProfileOut( __METHOD__ );
return $status;
}
+ } elseif ( !$this->allowBlankSummary
+ && !$content->equals( $this->getOriginalContent() )
+ && !$content->isRedirect()
+ && md5( $this->summary ) == $this->autoSumm
+ ) {
+ $this->missingSummary = true;
+ $status->fatal( 'missingsummary' );
+ $status->value = self::AS_SUMMARY_NEEDED;
+ wfProfileOut( __METHOD__ );
+ return $status;
}
# All's well
wfProfileIn( __METHOD__ . '-sectionanchor' );
$sectionanchor = '';
if ( $this->section == 'new' ) {
- if ( $this->textbox1 == '' ) {
- $this->missingComment = true;
- $status->fatal( 'missingcommenttext' );
- $status->value = self::AS_TEXTBOX_EMPTY;
- wfProfileOut( __METHOD__ . '-sectionanchor' );
- wfProfileOut( __METHOD__ );
- return $status;
- }
if ( $this->sectiontitle !== '' ) {
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
// If no edit summary was specified, create one automatically from the section
@@ -1428,14 +1684,14 @@ class EditPage {
// merged the section into full text. Clear the section field
// so that later submission of conflict forms won't try to
// replace that into a duplicated mess.
- $this->textbox1 = $text;
+ $this->textbox1 = $this->toEditText( $content );
$this->section = '';
$status->value = self::AS_SUCCESS_UPDATE;
}
// Check for length errors again now that the section is merged in
- $this->kblength = (int)( strlen( $text ) / 1024 );
+ $this->kblength = (int)( strlen( $this->toEditText( $content ) ) / 1024 );
if ( $this->kblength > $wgMaxArticleSize ) {
$this->tooBig = true;
$status->setResult( false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED );
@@ -1448,14 +1704,10 @@ class EditPage {
( ( $this->minoredit && !$this->isNew ) ? EDIT_MINOR : 0 ) |
( $bot ? EDIT_FORCE_BOT : 0 );
- $doEditStatus = $this->mArticle->doEdit( $text, $this->summary, $flags );
+ $doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags,
+ false, null, $this->contentFormat );
- if ( $doEditStatus->isOK() ) {
- $result['redirect'] = Title::newFromRedirect( $text ) !== null;
- $this->commitWatch();
- wfProfileOut( __METHOD__ );
- return $status;
- } else {
+ if ( !$doEditStatus->isOK() ) {
// Failure from doEdit()
// Show the edit conflict page for certain recognized errors from doEdit(),
// but don't show it for errors from extension hooks
@@ -1470,63 +1722,107 @@ class EditPage {
wfProfileOut( __METHOD__ );
return $doEditStatus;
}
+
+ $result['nullEdit'] = $doEditStatus->hasMessage( 'edit-no-change' );
+ $result['redirect'] = $content->isRedirect();
+ $this->updateWatchlist();
+ wfProfileOut( __METHOD__ );
+ return $status;
}
/**
- * Commit the change of watch status
+ * Register the change of watch status
*/
- protected function commitWatch() {
+ protected function updateWatchlist() {
global $wgUser;
+
if ( $wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched( $this->mTitle ) ) {
+ $fname = __METHOD__;
+ $title = $this->mTitle;
+ $watch = $this->watchthis;
+
+ // Do this in its own transaction to reduce contention...
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin( __METHOD__ );
- if ( $this->watchthis ) {
- WatchAction::doWatch( $this->mTitle, $wgUser );
- } else {
- WatchAction::doUnwatch( $this->mTitle, $wgUser );
- }
- $dbw->commit( __METHOD__ );
+ $dbw->onTransactionIdle( function() use ( $dbw, $title, $watch, $wgUser, $fname ) {
+ $dbw->begin( $fname );
+ if ( $watch ) {
+ WatchAction::doWatch( $title, $wgUser );
+ } else {
+ WatchAction::doUnwatch( $title, $wgUser );
+ }
+ $dbw->commit( $fname );
+ } );
}
}
/**
- * @private
- * @todo document
+ * Attempts to merge text content with base and current revisions
*
* @param $editText string
*
* @return bool
+ * @deprecated since 1.21, use mergeChangesIntoContent() instead
*/
function mergeChangesInto( &$editText ) {
+ ContentHandler::deprecated( __METHOD__, "1.21" );
+
+ $editContent = $this->toEditContent( $editText );
+
+ $ok = $this->mergeChangesIntoContent( $editContent );
+
+ if ( $ok ) {
+ $editText = $this->toEditText( $editContent );
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to do 3-way merge of edit content with a base revision
+ * and current content, in case of edit conflict, in whichever way appropriate
+ * for the content type.
+ *
+ * @since 1.21
+ *
+ * @param $editContent
+ *
+ * @return bool
+ */
+ private function mergeChangesIntoContent( &$editContent ) {
wfProfileIn( __METHOD__ );
$db = wfGetDB( DB_MASTER );
// This is the revision the editor started from
$baseRevision = $this->getBaseRevision();
- if ( is_null( $baseRevision ) ) {
+ $baseContent = $baseRevision ? $baseRevision->getContent() : null;
+
+ if ( is_null( $baseContent ) ) {
wfProfileOut( __METHOD__ );
return false;
}
- $baseText = $baseRevision->getText();
// The current state, we want to merge updates into it
$currentRevision = Revision::loadFromTitle( $db, $this->mTitle );
- if ( is_null( $currentRevision ) ) {
+ $currentContent = $currentRevision ? $currentRevision->getContent() : null;
+
+ if ( is_null( $currentContent ) ) {
wfProfileOut( __METHOD__ );
return false;
}
- $currentText = $currentRevision->getText();
- $result = '';
- if ( wfMerge( $baseText, $editText, $currentText, $result ) ) {
- $editText = $result;
+ $handler = ContentHandler::getForModelID( $baseContent->getModel() );
+
+ $result = $handler->merge3( $baseContent, $editContent, $currentContent );
+
+ if ( $result ) {
+ $editContent = $result;
wfProfileOut( __METHOD__ );
return true;
- } else {
- wfProfileOut( __METHOD__ );
- return false;
}
+
+ wfProfileOut( __METHOD__ );
+ return false;
}
/**
@@ -1690,10 +1986,13 @@ class EditPage {
# Give a notice if the user is editing a deleted/moved page...
if ( !$this->mTitle->exists() ) {
LogEventsList::showLogExtract( $wgOut, array( 'delete', 'move' ), $this->mTitle,
- '', array( 'lim' => 10,
- 'conds' => array( "log_action != 'revision'" ),
- 'showIfEmpty' => false,
- 'msgKey' => array( 'recreate-moveddeleted-warn' ) )
+ '',
+ array(
+ 'lim' => 10,
+ 'conds' => array( "log_action != 'revision'" ),
+ 'showIfEmpty' => false,
+ 'msgKey' => array( 'recreate-moveddeleted-warn' )
+ )
);
}
}
@@ -1711,17 +2010,77 @@ class EditPage {
// Added using template syntax, to take <noinclude>'s into account.
$wgOut->addWikiTextTitleTidy( '{{:' . $title->getFullText() . '}}', $this->mTitle );
return true;
- } else {
- return false;
}
- } else {
- return false;
}
+ return false;
+ }
+
+ /**
+ * Gets an editable textual representation of $content.
+ * The textual representation can be turned by into a Content object by the
+ * toEditContent() method.
+ *
+ * If $content is null or false or a string, $content is returned unchanged.
+ *
+ * If the given Content object is not of a type that can be edited using the text base EditPage,
+ * an exception will be raised. Set $this->allowNonTextContent to true to allow editing of non-textual
+ * content.
+ *
+ * @param Content|null|bool|string $content
+ * @return String the editable text form of the content.
+ *
+ * @throws MWException if $content is not an instance of TextContent and $this->allowNonTextContent is not true.
+ */
+ protected function toEditText( $content ) {
+ if ( $content === null || $content === false ) {
+ return $content;
+ }
+
+ if ( is_string( $content ) ) {
+ return $content;
+ }
+
+ if ( !$this->allowNonTextContent && !( $content instanceof TextContent ) ) {
+ throw new MWException( "This content model can not be edited as text: "
+ . ContentHandler::getLocalizedName( $content->getModel() ) );
+ }
+
+ return $content->serialize( $this->contentFormat );
+ }
+
+ /**
+ * Turns the given text into a Content object by unserializing it.
+ *
+ * If the resulting Content object is not of a type that can be edited using the text base EditPage,
+ * an exception will be raised. Set $this->allowNonTextContent to true to allow editing of non-textual
+ * content.
+ *
+ * @param string|null|bool $text Text to unserialize
+ * @return Content The content object created from $text. If $text was false or null, false resp. null will be
+ * returned instead.
+ *
+ * @throws MWException if unserializing the text results in a Content object that is not an instance of TextContent
+ * and $this->allowNonTextContent is not true.
+ */
+ protected function toEditContent( $text ) {
+ if ( $text === false || $text === null ) {
+ return $text;
+ }
+
+ $content = ContentHandler::makeContent( $text, $this->getTitle(),
+ $this->contentModel, $this->contentFormat );
+
+ if ( !$this->allowNonTextContent && !( $content instanceof TextContent ) ) {
+ throw new MWException( "This content model can not be edited as text: "
+ . ContentHandler::getLocalizedName( $content->getModel() ) );
+ }
+
+ return $content;
}
/**
* Send the edit form and related headers to $wgOut
- * @param $formCallback Callback that takes an OutputPage parameter; will be called
+ * @param $formCallback Callback|null that takes an OutputPage parameter; will be called
* during form output near the top, for captchas and the like.
*/
function showEditForm( $formCallback = null ) {
@@ -1767,6 +2126,8 @@ class EditPage {
}
}
+ //@todo: add EditForm plugin interface and use it here!
+ // search for textarea1 and textares2, and allow EditForm to override all uses.
$wgOut->addHTML( Html::openElement( 'form', array( 'id' => self::EDITFORM_ID, 'name' => self::EDITFORM_ID,
'method' => 'post', 'action' => $this->getActionURL( $this->getContextTitle() ),
'enctype' => 'multipart/form-data' ) ) );
@@ -1820,7 +2181,7 @@ class EditPage {
}
if ( $this->hasPresetSummary ) {
- // If a summary has been preset using &summary= we dont want to prompt for
+ // If a summary has been preset using &summary= we don't want to prompt for
// a different summary. Only prompt for a summary if the summary is blanked.
// (Bug 17416)
$this->autoSumm = md5( '' );
@@ -1831,6 +2192,9 @@ class EditPage {
$wgOut->addHTML( Html::hidden( 'oldid', $this->oldid ) );
+ $wgOut->addHTML( Html::hidden( 'format', $this->contentFormat ) );
+ $wgOut->addHTML( Html::hidden( 'model', $this->contentModel ) );
+
if ( $this->section == 'new' ) {
$this->showSummaryInput( true, $this->summary );
$wgOut->addHTML( $this->getSummaryPreview( true, $this->summary ) );
@@ -1843,12 +2207,14 @@ class EditPage {
}
if ( $this->isConflict ) {
- // In an edit conflict bypass the overrideable content form method
+ // In an edit conflict bypass the overridable content form method
// and fallback to the raw wpTextbox1 since editconflicts can't be
// resolved between page source edits and custom ui edits using the
// custom edit ui.
$this->textbox2 = $this->textbox1;
- $this->textbox1 = $this->getCurrentText();
+
+ $content = $this->getCurrentContent();
+ $this->textbox1 = $this->toEditText( $content );
$this->showTextbox1();
} else {
@@ -1874,7 +2240,13 @@ class EditPage {
Linker::formatHiddenCategories( $this->mArticle->getHiddenCategories() ) ) );
if ( $this->isConflict ) {
- $this->showConflict();
+ try {
+ $this->showConflict();
+ } catch ( MWContentSerializationException $ex ) {
+ // this can't really happen, but be nice if it does.
+ $msg = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
+ $wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>' );
+ }
}
$wgOut->addHTML( $this->editFormTextBottom . "\n</form>\n" );
@@ -1909,30 +2281,8 @@ class EditPage {
$wgOut->addWikiMsg( 'talkpagetext' );
}
- # Optional notices on a per-namespace and per-page basis
- $editnotice_ns = 'editnotice-' . $this->mTitle->getNamespace();
- $editnotice_ns_message = wfMessage( $editnotice_ns );
- if ( $editnotice_ns_message->exists() ) {
- $wgOut->addWikiText( $editnotice_ns_message->plain() );
- }
- if ( MWNamespace::hasSubpages( $this->mTitle->getNamespace() ) ) {
- $parts = explode( '/', $this->mTitle->getDBkey() );
- $editnotice_base = $editnotice_ns;
- while ( count( $parts ) > 0 ) {
- $editnotice_base .= '-' . array_shift( $parts );
- $editnotice_base_msg = wfMessage( $editnotice_base );
- if ( $editnotice_base_msg->exists() ) {
- $wgOut->addWikiText( $editnotice_base_msg->plain() );
- }
- }
- } else {
- # Even if there are no subpages in namespace, we still don't want / in MW ns.
- $editnoticeText = $editnotice_ns . '-' . str_replace( '/', '-', $this->mTitle->getDBkey() );
- $editnoticeMsg = wfMessage( $editnoticeText );
- if ( $editnoticeMsg->exists() ) {
- $wgOut->addWikiText( $editnoticeMsg->plain() );
- }
- }
+ // Add edit notices
+ $wgOut->addHTML( implode( "\n", $this->mTitle->getEditNotices() ) );
if ( $this->isConflict ) {
$wgOut->wrapWikiMsg( "<div class='mw-explainconflict'>\n$1\n</div>", 'explainconflict' );
@@ -1948,7 +2298,7 @@ class EditPage {
if ( $this->section != '' && $this->section != 'new' ) {
if ( !$this->summary && !$this->preview && !$this->diff ) {
- $sectionTitle = self::extractSectionTitle( $this->textbox1 );
+ $sectionTitle = self::extractSectionTitle( $this->textbox1 ); //FIXME: use Content object
if ( $sectionTitle !== false ) {
$this->summary = "/* $sectionTitle */ ";
}
@@ -1980,7 +2330,7 @@ class EditPage {
if ( $revision ) {
// Let sysop know that this will make private content public if saved
- if ( !$revision->userCan( Revision::DELETED_TEXT ) ) {
+ if ( !$revision->userCan( Revision::DELETED_TEXT, $wgUser ) ) {
$wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-permission' );
} elseif ( $revision->isDeleted( Revision::DELETED_TEXT ) ) {
$wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-view' );
@@ -2014,10 +2364,13 @@ class EditPage {
$wgOut->wrapWikiMsg( "<div class='error' id='mw-userinvalidcssjstitle'>\n$1\n</div>", array( 'userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage() ) );
}
if ( $this->formtype !== 'preview' ) {
- if ( $this->isCssSubpage )
+ if ( $this->isCssSubpage ) {
$wgOut->wrapWikiMsg( "<div id='mw-usercssyoucanpreview'>\n$1\n</div>", array( 'usercssyoucanpreview' ) );
- if ( $this->isJsSubpage )
+ }
+
+ if ( $this->isJsSubpage ) {
$wgOut->wrapWikiMsg( "<div id='mw-userjsyoucanpreview'>\n$1\n</div>", array( 'userjsyoucanpreview' ) );
+ }
}
}
}
@@ -2073,7 +2426,6 @@ class EditPage {
$this->showHeaderCopyrightWarning();
}
-
/**
* Standard summary input and label (wgSummary), abstracted so EditPage
* subclasses may reorganize the form.
@@ -2081,15 +2433,15 @@ class EditPage {
* inferred by the id given to the input. You can remove them both by
* passing array( 'id' => false ) to $userInputAttrs.
*
- * @param $summary string The value of the summary input
- * @param $labelText string The html to place inside the label
- * @param $inputAttrs array of attrs to use on the input
- * @param $spanLabelAttrs array of attrs to use on the span inside the label
+ * @param string $summary The value of the summary input
+ * @param string $labelText The html to place inside the label
+ * @param array $inputAttrs of attrs to use on the input
+ * @param array $spanLabelAttrs of attrs to use on the span inside the label
*
* @return array An array in the format array( $label, $input )
*/
function getSummaryInput( $summary = "", $labelText = null, $inputAttrs = null, $spanLabelAttrs = null ) {
- // Note: the maxlength is overriden in JS to 255 and to make it use UTF-8 bytes, not characters.
+ // Note: the maxlength is overridden in JS to 255 and to make it use UTF-8 bytes, not characters.
$inputAttrs = ( is_array( $inputAttrs ) ? $inputAttrs : array() ) + array(
'id' => 'wpSummary',
'maxlength' => '200',
@@ -2118,7 +2470,7 @@ class EditPage {
* @param $isSubjectPreview Boolean: true if this is the section subject/title
* up top, or false if this is the comment summary
* down below the textarea
- * @param $summary String: The text of the summary to display
+ * @param string $summary The text of the summary to display
* @return String
*/
protected function showSummaryInput( $isSubjectPreview, $summary = "" ) {
@@ -2144,18 +2496,22 @@ class EditPage {
* @param $isSubjectPreview Boolean: true if this is the section subject/title
* up top, or false if this is the comment summary
* down below the textarea
- * @param $summary String: the text of the summary to display
+ * @param string $summary the text of the summary to display
* @return String
*/
protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
- if ( !$summary || ( !$this->preview && !$this->diff ) )
+ // avoid spaces in preview, gets always trimmed on save
+ $summary = trim( $summary );
+ if ( !$summary || ( !$this->preview && !$this->diff ) ) {
return "";
+ }
global $wgParser;
- if ( $isSubjectPreview )
+ if ( $isSubjectPreview ) {
$summary = wfMessage( 'newsectionsummary', $wgParser->stripSectionName( $summary ) )
->inContentLanguage()->text();
+ }
$message = $isSubjectPreview ? 'subject-preview' : 'summary-preview';
@@ -2174,8 +2530,9 @@ class EditPage {
HTML
);
- if ( !$this->checkUnicodeCompliantBrowser() )
+ if ( !$this->checkUnicodeCompliantBrowser() ) {
$wgOut->addHTML( Html::hidden( 'safemode', '1' ) );
+ }
}
protected function showFormAfterText() {
@@ -2212,8 +2569,8 @@ HTML
* The $textoverride method can be used by subclasses overriding showContentForm
* to pass back to this method.
*
- * @param $customAttribs array of html attributes to use in the textarea
- * @param $textoverride String: optional text to override $this->textarea1 with
+ * @param array $customAttribs of html attributes to use in the textarea
+ * @param string $textoverride optional text to override $this->textarea1 with
*/
protected function showTextbox1( $customAttribs = null, $textoverride = null ) {
if ( $this->wasDeletedSinceLastEdit() && $this->formtype == 'save' ) {
@@ -2255,10 +2612,10 @@ HTML
$this->showTextbox( $this->textbox2, 'wpTextbox2', array( 'tabindex' => 6, 'readonly' ) );
}
- protected function showTextbox( $content, $name, $customAttribs = array() ) {
+ protected function showTextbox( $text, $name, $customAttribs = array() ) {
global $wgOut, $wgUser;
- $wikitext = $this->safeUnicodeOutput( $content );
+ $wikitext = $this->safeUnicodeOutput( $text );
if ( strval( $wikitext ) !== '' ) {
// Ensure there's a newline at the end, otherwise adding lines
// is awkward.
@@ -2285,13 +2642,15 @@ HTML
protected function displayPreviewArea( $previewOutput, $isOnTop = false ) {
global $wgOut;
$classes = array();
- if ( $isOnTop )
+ if ( $isOnTop ) {
$classes[] = 'ontop';
+ }
$attribs = array( 'id' => 'wikiPreview', 'class' => implode( ' ', $classes ) );
- if ( $this->formtype != 'preview' )
+ if ( $this->formtype != 'preview' ) {
$attribs['style'] = 'display: none;';
+ }
$wgOut->addHTML( Xml::openElement( 'div', $attribs ) );
@@ -2302,7 +2661,12 @@ HTML
$wgOut->addHTML( '</div>' );
if ( $this->formtype == 'diff' ) {
- $this->showDiff();
+ try {
+ $this->showDiff();
+ } catch ( MWContentSerializationException $ex ) {
+ $msg = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
+ $wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>' );
+ }
}
}
@@ -2310,7 +2674,7 @@ HTML
* Append preview output to $wgOut.
* Includes category rendering if this is a category page.
*
- * @param $text String: the HTML to be output for the preview.
+ * @param string $text the HTML to be output for the preview.
*/
protected function showPreview( $text ) {
global $wgOut;
@@ -2334,7 +2698,7 @@ HTML
* save and then make a comparison.
*/
function showDiff() {
- global $wgUser, $wgContLang, $wgParser, $wgOut;
+ global $wgUser, $wgContLang, $wgOut;
$oldtitlemsg = 'currentrev';
# if message does not exist, show diff against the preloaded default
@@ -2342,24 +2706,43 @@ HTML
$oldtext = $this->mTitle->getDefaultMessageText();
if( $oldtext !== false ) {
$oldtitlemsg = 'defaultmessagetext';
+ $oldContent = $this->toEditContent( $oldtext );
+ } else {
+ $oldContent = null;
}
} else {
- $oldtext = $this->mArticle->getRawText();
+ $oldContent = $this->getCurrentContent();
}
- $newtext = $this->mArticle->replaceSection(
- $this->section, $this->textbox1, $this->summary, $this->edittime );
- wfRunHooks( 'EditPageGetDiffText', array( $this, &$newtext ) );
+ $textboxContent = $this->toEditContent( $this->textbox1 );
+
+ $newContent = $this->mArticle->replaceSectionContent(
+ $this->section, $textboxContent,
+ $this->summary, $this->edittime );
- $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
- $newtext = $wgParser->preSaveTransform( $newtext, $this->mTitle, $wgUser, $popts );
+ if ( $newContent ) {
+ ContentHandler::runLegacyHooks( 'EditPageGetDiffText', array( $this, &$newContent ) );
+ wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) );
+
+ $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
+ $newContent = $newContent->preSaveTransform( $this->mTitle, $wgUser, $popts );
+ }
- if ( $oldtext !== false || $newtext != '' ) {
+ if ( ( $oldContent && !$oldContent->isEmpty() ) || ( $newContent && !$newContent->isEmpty() ) ) {
$oldtitle = wfMessage( $oldtitlemsg )->parse();
$newtitle = wfMessage( 'yourtext' )->parse();
- $de = new DifferenceEngine( $this->mArticle->getContext() );
- $de->setText( $oldtext, $newtext );
+ if ( !$oldContent ) {
+ $oldContent = $newContent->getContentHandler()->makeEmptyContent();
+ }
+
+ if ( !$newContent ) {
+ $newContent = $oldContent->getContentHandler()->makeEmptyContent();
+ }
+
+ $de = $oldContent->getContentHandler()->createDifferenceEngine( $this->mArticle->getContext() );
+ $de->setContent( $oldContent, $newContent );
+
$difftext = $de->getDiff( $oldtitle, $newtitle );
$de->showDiffStyle();
} else {
@@ -2463,7 +2846,9 @@ HTML
wfMessage( 'newwindow' )->parse();
$wgOut->addHTML( " <span class='cancelLink'>{$cancel}</span>\n" );
$wgOut->addHTML( " <span class='editHelp'>{$edithelp}</span>\n" );
- $wgOut->addHTML( "</div><!-- editButtons -->\n</div><!-- editOptions -->\n" );
+ $wgOut->addHTML( "</div><!-- editButtons -->\n" );
+ wfRunHooks( 'EditPage::showStandardInputs:options', array( $this, $wgOut, &$tabindex ) );
+ $wgOut->addHTML( "</div><!-- editOptions -->\n" );
}
/**
@@ -2476,8 +2861,12 @@ HTML
if ( wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
$wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
- $de = new DifferenceEngine( $this->mArticle->getContext() );
- $de->setText( $this->textbox2, $this->textbox1 );
+ $content1 = $this->toEditContent( $this->textbox1 );
+ $content2 = $this->toEditContent( $this->textbox2 );
+
+ $handler = ContentHandler::getForModelID( $this->contentModel );
+ $de = $handler->createDifferenceEngine( $this->mArticle->getContext() );
+ $de->setContent( $content2, $content1 );
$de->showDiff(
wfMessage( 'yourtext' )->parse(),
wfMessage( 'storedversion' )->text()
@@ -2548,40 +2937,47 @@ HTML
$dbr = wfGetDB( DB_SLAVE );
$data = $dbr->selectRow(
array( 'logging', 'user' ),
- array( 'log_type',
- 'log_action',
- 'log_timestamp',
- 'log_user',
- 'log_namespace',
- 'log_title',
- 'log_comment',
- 'log_params',
- 'log_deleted',
- 'user_name' ),
- array( 'log_namespace' => $this->mTitle->getNamespace(),
- 'log_title' => $this->mTitle->getDBkey(),
- 'log_type' => 'delete',
- 'log_action' => 'delete',
- 'user_id=log_user' ),
+ array(
+ 'log_type',
+ 'log_action',
+ 'log_timestamp',
+ 'log_user',
+ 'log_namespace',
+ 'log_title',
+ 'log_comment',
+ 'log_params',
+ 'log_deleted',
+ 'user_name'
+ ), array(
+ 'log_namespace' => $this->mTitle->getNamespace(),
+ 'log_title' => $this->mTitle->getDBkey(),
+ 'log_type' => 'delete',
+ 'log_action' => 'delete',
+ 'user_id=log_user'
+ ),
__METHOD__,
array( 'LIMIT' => 1, 'ORDER BY' => 'log_timestamp DESC' )
);
// Quick paranoid permission checks...
if ( is_object( $data ) ) {
- if ( $data->log_deleted & LogPage::DELETED_USER )
+ if ( $data->log_deleted & LogPage::DELETED_USER ) {
$data->user_name = wfMessage( 'rev-deleted-user' )->escaped();
- if ( $data->log_deleted & LogPage::DELETED_COMMENT )
+ }
+
+ if ( $data->log_deleted & LogPage::DELETED_COMMENT ) {
$data->log_comment = wfMessage( 'rev-deleted-comment' )->escaped();
+ }
}
return $data;
}
/**
* Get the rendered text for previewing.
+ * @throws MWException
* @return string
*/
function getPreviewText() {
- global $wgOut, $wgUser, $wgParser, $wgRawHtml, $wgLang;
+ global $wgOut, $wgUser, $wgRawHtml, $wgLang;
wfProfileIn( __METHOD__ );
@@ -2600,82 +2996,96 @@ HTML
return $parsedNote;
}
- if ( $this->mTriedSave && !$this->mTokenOk ) {
- if ( $this->mTokenOkExceptSuffix ) {
- $note = wfMessage( 'token_suffix_mismatch' )->plain();
- } else {
- $note = wfMessage( 'session_fail_preview' )->plain();
- }
- } elseif ( $this->incompleteForm ) {
- $note = wfMessage( 'edit_form_incomplete' )->plain();
- } else {
- $note = wfMessage( 'previewnote' )->plain() .
- ' [[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' . wfMessage( 'continue-editing' )->text() . ']]';
- }
+ $note = '';
- $parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
+ try {
+ $content = $this->toEditContent( $this->textbox1 );
- $parserOptions->setEditSection( false );
- $parserOptions->setIsPreview( true );
- $parserOptions->setIsSectionPreview( !is_null( $this->section ) && $this->section !== '' );
+ $previewHTML = '';
+ if ( !wfRunHooks( 'AlternateEditPreview', array( $this, &$content, &$previewHTML, &$this->mParserOutput ) ) ) {
+ wfProfileOut( __METHOD__ );
+ return $previewHTML;
+ }
+
+ if ( $this->mTriedSave && !$this->mTokenOk ) {
+ if ( $this->mTokenOkExceptSuffix ) {
+ $note = wfMessage( 'token_suffix_mismatch' )->plain();
- # don't parse non-wikitext pages, show message about preview
- if ( $this->mTitle->isCssJsSubpage() || !$this->mTitle->isWikitextPage() ) {
- if ( $this->mTitle->isCssJsSubpage() ) {
- $level = 'user';
- } elseif ( $this->mTitle->isCssOrJsPage() ) {
- $level = 'site';
- } else {
- $level = false;
- }
-
- # Used messages to make sure grep find them:
- # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
- $class = 'mw-code';
- if ( $level ) {
- if ( preg_match( "/\\.css$/", $this->mTitle->getText() ) ) {
- $previewtext = "<div id='mw-{$level}csspreview'>\n" . wfMessage( "{$level}csspreview" )->text() . "\n</div>";
- $class .= " mw-css";
- } elseif ( preg_match( "/\\.js$/", $this->mTitle->getText() ) ) {
- $previewtext = "<div id='mw-{$level}jspreview'>\n" . wfMessage( "{$level}jspreview" )->text() . "\n</div>";
- $class .= " mw-js";
} else {
- throw new MWException( 'A CSS/JS (sub)page but which is not css nor js!' );
+ $note = wfMessage( 'session_fail_preview' )->plain();
}
- $parserOutput = $wgParser->parse( $previewtext, $this->mTitle, $parserOptions );
- $previewHTML = $parserOutput->getText();
+ } elseif ( $this->incompleteForm ) {
+ $note = wfMessage( 'edit_form_incomplete' )->plain();
} else {
- $previewHTML = '';
+ $note = wfMessage( 'previewnote' )->plain() .
+ ' [[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' . wfMessage( 'continue-editing' )->text() . ']]';
}
- $previewHTML .= "<pre class=\"$class\" dir=\"ltr\">\n" . htmlspecialchars( $this->textbox1 ) . "\n</pre>\n";
- } else {
- $toparse = $this->textbox1;
+ $parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
+ $parserOptions->setEditSection( false );
+ $parserOptions->setIsPreview( true );
+ $parserOptions->setIsSectionPreview( !is_null( $this->section ) && $this->section !== '' );
- # If we're adding a comment, we need to show the
- # summary as the headline
- if ( $this->section == "new" && $this->summary != "" ) {
- $toparse = wfMessage( 'newsectionheaderdefaultlevel', $this->summary )->inContentLanguage()->text() . "\n\n" . $toparse;
- }
+ # don't parse non-wikitext pages, show message about preview
+ if ( $this->mTitle->isCssJsSubpage() || $this->mTitle->isCssOrJsPage() ) {
+ if( $this->mTitle->isCssJsSubpage() ) {
+ $level = 'user';
+ } elseif( $this->mTitle->isCssOrJsPage() ) {
+ $level = 'site';
+ } else {
+ $level = false;
+ }
- wfRunHooks( 'EditPageGetPreviewText', array( $this, &$toparse ) );
+ if ( $content->getModel() == CONTENT_MODEL_CSS ) {
+ $format = 'css';
+ } elseif ( $content->getModel() == CONTENT_MODEL_JAVASCRIPT ) {
+ $format = 'js';
+ } else {
+ $format = false;
+ }
- $toparse = $wgParser->preSaveTransform( $toparse, $this->mTitle, $wgUser, $parserOptions );
- $parserOutput = $wgParser->parse( $toparse, $this->mTitle, $parserOptions );
+ # Used messages to make sure grep find them:
+ # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
+ if( $level && $format ) {
+ $note = "<div id='mw-{$level}{$format}preview'>" . wfMessage( "{$level}{$format}preview" )->text() . "</div>";
+ }
+ }
- $rt = Title::newFromRedirectArray( $this->textbox1 );
+ $rt = $content->getRedirectChain();
if ( $rt ) {
$previewHTML = $this->mArticle->viewRedirect( $rt, false );
} else {
- $previewHTML = $parserOutput->getText();
- }
- $this->mParserOutput = $parserOutput;
- $wgOut->addParserOutputNoText( $parserOutput );
+ # If we're adding a comment, we need to show the
+ # summary as the headline
+ if ( $this->section === "new" && $this->summary !== "" ) {
+ $content = $content->addSectionHeader( $this->summary );
+ }
+
+ $hook_args = array( $this, &$content );
+ ContentHandler::runLegacyHooks( 'EditPageGetPreviewText', $hook_args );
+ wfRunHooks( 'EditPageGetPreviewContent', $hook_args );
+
+ $parserOptions->enableLimitReport();
+
+ # For CSS/JS pages, we should have called the ShowRawCssJs hook here.
+ # But it's now deprecated, so never mind
- if ( count( $parserOutput->getWarnings() ) ) {
- $note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() );
+ $content = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
+ $parserOutput = $content->getParserOutput( $this->getArticle()->getTitle(), null, $parserOptions );
+
+ $previewHTML = $parserOutput->getText();
+ $this->mParserOutput = $parserOutput;
+ $wgOut->addParserOutputNoText( $parserOutput );
+
+ if ( count( $parserOutput->getWarnings() ) ) {
+ $note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() );
+ }
}
+ } catch ( MWContentSerializationException $ex ) {
+ $m = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
+ $note .= "\n\n" . $m->parse();
+ $previewHTML = '';
}
if ( $this->isConflict ) {
@@ -2887,8 +3297,8 @@ HTML
* Returns an array of html code of the following checkboxes:
* minor and watch
*
- * @param $tabindex int Current tabindex
- * @param $checked Array of checkbox => bool, where bool indicates the checked
+ * @param int $tabindex Current tabindex
+ * @param array $checked of checkbox => bool, where bool indicates the checked
* status of the checkbox
*
* @return array
@@ -2938,7 +3348,7 @@ HTML
* Returns an array of html code of the following buttons:
* save, diff, preview and live
*
- * @param $tabindex int Current tabindex
+ * @param int $tabindex Current tabindex
*
* @return array
*/
@@ -3067,7 +3477,7 @@ HTML
/**
* Produce the stock "your edit contains spam" page
*
- * @param $match string Text which triggered one or more filters
+ * @param string|bool $match Text which triggered one or more filters
* @deprecated since 1.17 Use method spamPageWithContent() instead
*/
static function spamPage( $match = false ) {
@@ -3096,7 +3506,7 @@ HTML
global $wgOut, $wgLang;
$this->textbox2 = $this->textbox1;
- if( is_array( $match ) ){
+ if( is_array( $match ) ) {
$match = $wgLang->listToText( $match );
}
$wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) );
@@ -3210,7 +3620,7 @@ HTML
* @private
*/
function makesafe( $invalue ) {
- // Armor existing references for reversability.
+ // Armor existing references for reversibility.
$invalue = strtr( $invalue, array( "&#x" => "&#x0" ) );
$bytesleft = 0;
@@ -3262,7 +3672,7 @@ HTML
$i++;
} while ( ctype_xdigit( $invalue[$i] ) && ( $i < strlen( $invalue ) ) );
- // Do some sanity checks. These aren't needed for reversability,
+ // Do some sanity checks. These aren't needed for reversibility,
// but should help keep the breakage down if the editor
// breaks one of the entities whilst editing.
if ( ( substr( $invalue, $i, 1 ) == ";" ) and ( strlen( $hexstring ) <= 6 ) ) {
@@ -3275,7 +3685,7 @@ HTML
$result .= substr( $invalue, $i, 1 );
}
}
- // reverse the transform that we made for reversability reasons.
+ // reverse the transform that we made for reversibility reasons.
return strtr( $result, array( "&#x0" => "&#x" ) );
}
}
diff --git a/includes/Exception.php b/includes/Exception.php
index 714f73e8..0bd7a2a7 100644
--- a/includes/Exception.php
+++ b/includes/Exception.php
@@ -64,8 +64,8 @@ class MWException extends Exception {
/**
* Run hook to allow extensions to modify the text of the exception
*
- * @param $name string: class name of the exception
- * @param $args array: arguments to pass to the callback functions
+ * @param string $name class name of the exception
+ * @param array $args arguments to pass to the callback functions
* @return string|null string to output or null if any hook has been called
*/
function runHooks( $name, $args = array() ) {
@@ -83,7 +83,7 @@ class MWException extends Exception {
$callargs = array_merge( array( $this ), $args );
foreach ( $hooks as $hook ) {
- if ( is_string( $hook ) || ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) ) ) { // 'function' or array( 'class', hook' )
+ if ( is_string( $hook ) || ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) ) ) { // 'function' or array( 'class', hook' )
$result = call_user_func_array( $hook, $callargs );
} else {
$result = null;
@@ -99,8 +99,8 @@ class MWException extends Exception {
/**
* Get a message from i18n
*
- * @param $key string: message name
- * @param $fallback string: default message if the message cache can't be
+ * @param string $key message name
+ * @param string $fallback default message if the message cache can't be
* called by the exception
* The function also has other parameters that are arguments for the message
* @return string message with arguments replaced
@@ -171,7 +171,7 @@ class MWException extends Exception {
/**
* Get a random ID for this error.
- * This allows to link the exception to its correspoding log entry when
+ * This allows to link the exception to its corresponding log entry when
* $wgShowExceptionDetails is set to false.
*
* @return string
@@ -262,7 +262,7 @@ class MWException extends Exception {
if ( defined( 'MW_API' ) ) {
// Unhandled API exception, we can't be sure that format printer is alive
header( 'MediaWiki-API-Error: internal_api_error_' . get_class( $this ) );
- wfHttpError(500, 'Internal Server Error', $this->getText() );
+ wfHttpError( 500, 'Internal Server Error', $this->getText() );
} elseif ( self::isCommandLine() ) {
MWExceptionHandler::printError( $this->getText() );
} else {
@@ -320,16 +320,16 @@ class ErrorPageError extends MWException {
/**
* Note: these arguments are keys into wfMessage(), not text!
*
- * @param $title string|Message Message key (string) for page title, or a Message object
- * @param $msg string|Message Message key (string) for error text, or a Message object
- * @param $params array with parameters to wfMessage()
+ * @param string|Message $title Message key (string) for page title, or a Message object
+ * @param string|Message $msg Message key (string) for error text, or a Message object
+ * @param array $params with parameters to wfMessage()
*/
function __construct( $title, $msg, $params = null ) {
$this->title = $title;
$this->msg = $msg;
$this->params = $params;
- if( $msg instanceof Message ){
+ if( $msg instanceof Message ) {
parent::__construct( $msg );
} else {
parent::__construct( wfMessage( $msg )->text() );
@@ -354,8 +354,8 @@ class ErrorPageError extends MWException {
*/
class BadTitleError extends ErrorPageError {
/**
- * @param $msg string|Message A message key (default: 'badtitletext')
- * @param $params Array parameter to wfMessage()
+ * @param string|Message $msg A message key (default: 'badtitletext')
+ * @param array $params parameter to wfMessage()
*/
function __construct( $msg = 'badtitletext', $params = null ) {
parent::__construct( 'badtitle', $msg, $params );
@@ -423,7 +423,7 @@ class PermissionsError extends ErrorPageError {
* @ingroup Exception
*/
class ReadOnlyError extends ErrorPageError {
- public function __construct(){
+ public function __construct() {
parent::__construct(
'readonly',
'readonlytext',
@@ -439,14 +439,14 @@ class ReadOnlyError extends ErrorPageError {
* @ingroup Exception
*/
class ThrottledError extends ErrorPageError {
- public function __construct(){
+ public function __construct() {
parent::__construct(
'actionthrottled',
'actionthrottledtext'
);
}
- public function report(){
+ public function report() {
global $wgOut;
$wgOut->setStatusCode( 503 );
parent::report();
@@ -460,7 +460,7 @@ class ThrottledError extends ErrorPageError {
* @ingroup Exception
*/
class UserBlockedError extends ErrorPageError {
- public function __construct( Block $block ){
+ public function __construct( Block $block ) {
global $wgLang, $wgRequest;
$blocker = $block->getBlocker();
@@ -500,25 +500,24 @@ class UserBlockedError extends ErrorPageError {
/**
* Shows a generic "user is not logged in" error page.
*
- * This is essentially an ErrorPageError exception which by default use the
+ * This is essentially an ErrorPageError exception which by default uses the
* 'exception-nologin' as a title and 'exception-nologin-text' for the message.
* @see bug 37627
* @since 1.20
*
* @par Example:
* @code
- * if( $user->isAnon ) {
+ * if( $user->isAnon() ) {
* throw new UserNotLoggedIn();
* }
* @endcode
*
- * Please note the parameters are mixed up compared to ErrorPageError, this
- * is done to be able to simply specify a reason whitout overriding the default
- * title.
+ * Note the parameter order differs from ErrorPageError, this allows you to
+ * simply specify a reason without overriding the default title.
*
* @par Example:
* @code
- * if( $user->isAnon ) {
+ * if( $user->isAnon() ) {
* throw new UserNotLoggedIn( 'action-require-loggedin' );
* }
* @endcode
@@ -533,11 +532,11 @@ class UserNotLoggedIn extends ErrorPageError {
* @param $titleMsg A message key to set the page title.
* Optional, default: 'exception-nologin'
* @param $params Parameters to wfMessage().
- * Optiona, default: null
+ * Optional, default: null
*/
public function __construct(
$reasonMsg = 'exception-nologin-text',
- $titleMsg = 'exception-nologin',
+ $titleMsg = 'exception-nologin',
$params = null
) {
parent::__construct( $titleMsg, $reasonMsg, $params );
@@ -558,24 +557,48 @@ class HttpError extends MWException {
* Constructor
*
* @param $httpCode Integer: HTTP status code to send to the client
- * @param $content String|Message: content of the message
- * @param $header String|Message: content of the header (\<title\> and \<h1\>)
+ * @param string|Message $content content of the message
+ * @param string|Message $header content of the header (\<title\> and \<h1\>)
*/
- public function __construct( $httpCode, $content, $header = null ){
+ public function __construct( $httpCode, $content, $header = null ) {
parent::__construct( $content );
$this->httpCode = (int)$httpCode;
$this->header = $header;
$this->content = $content;
}
+ /**
+ * Returns the HTTP status code supplied to the constructor.
+ *
+ * @return int
+ */
+ public function getStatusCode() {
+ return $this->httpCode;
+ }
+
+ /**
+ * Report the HTTP error.
+ * Sends the appropriate HTTP status code and outputs an
+ * HTML page with an error message.
+ */
public function report() {
$httpMessage = HttpStatus::getMessage( $this->httpCode );
- header( "Status: {$this->httpCode} {$httpMessage}" );
+ header( "Status: {$this->httpCode} {$httpMessage}", true, $this->httpCode );
header( 'Content-type: text/html; charset=utf-8' );
+ print $this->getHTML();
+ }
+
+ /**
+ * Returns HTML for reporting the HTTP error.
+ * This will be a minimal but complete HTML document.
+ *
+ * @return string HTML
+ */
+ public function getHTML() {
if ( $this->header === null ) {
- $header = $httpMessage;
+ $header = HttpStatus::getMessage( $this->httpCode );
} elseif ( $this->header instanceof Message ) {
$header = $this->header->escaped();
} else {
@@ -588,7 +611,7 @@ class HttpError extends MWException {
$content = htmlspecialchars( $this->content );
}
- print "<!DOCTYPE html>\n".
+ return "<!DOCTYPE html>\n".
"<html><head><title>$header</title></head>\n" .
"<body><h1>$header</h1><p>$content</p></body></html>\n";
}
@@ -661,7 +684,7 @@ class MWExceptionHandler {
* Print a message, if possible to STDERR.
* Use this in command line mode only (see isCommandLine)
*
- * @param $message string Failure text
+ * @param string $message Failure text
*/
public static function printError( $message ) {
# NOTE: STDERR may not be available, especially if php-cgi is used from the command line (bug #15602).
diff --git a/includes/Export.php b/includes/Export.php
index f01fb237..d8cc0242 100644
--- a/includes/Export.php
+++ b/includes/Export.php
@@ -31,8 +31,8 @@
* @ingroup SpecialPage Dump
*/
class WikiExporter {
- var $list_authors = false ; # Return distinct author list (when not returning full history)
- var $author_list = "" ;
+ var $list_authors = false; # Return distinct author list (when not returning full history)
+ var $author_list = "";
var $dumpUploads = false;
var $dumpUploadFileContents = false;
@@ -63,7 +63,7 @@ class WikiExporter {
* @return string
*/
public static function schemaVersion() {
- return "0.7";
+ return "0.8";
}
/**
@@ -80,17 +80,17 @@ class WikiExporter {
* offset: non-inclusive offset at which to start the query
* limit: maximum number of rows to return
* dir: "asc" or "desc" timestamp order
- * @param $buffer Int: one of WikiExporter::BUFFER or WikiExporter::STREAM
- * @param $text Int: one of WikiExporter::TEXT or WikiExporter::STUB
+ * @param int $buffer one of WikiExporter::BUFFER or WikiExporter::STREAM
+ * @param int $text one of WikiExporter::TEXT or WikiExporter::STUB
*/
- function __construct( &$db, $history = WikiExporter::CURRENT,
+ function __construct( $db, $history = WikiExporter::CURRENT,
$buffer = WikiExporter::BUFFER, $text = WikiExporter::TEXT ) {
- $this->db =& $db;
+ $this->db = $db;
$this->history = $history;
- $this->buffer = $buffer;
- $this->writer = new XmlDumpWriter();
- $this->sink = new DumpOutput();
- $this->text = $text;
+ $this->buffer = $buffer;
+ $this->writer = new XmlDumpWriter();
+ $this->sink = new DumpOutput();
+ $this->text = $text;
}
/**
@@ -126,7 +126,7 @@ class WikiExporter {
/**
* Dumps a series of page and revision records for those pages
* in the database falling within the page_id range given.
- * @param $start Int: inclusive lower limit (this id is included)
+ * @param int $start inclusive lower limit (this id is included)
* @param $end Int: Exclusive upper limit (this id is not included)
* If 0, no upper limit.
*/
@@ -141,7 +141,7 @@ class WikiExporter {
/**
* Dumps a series of page and revision records for those pages
* in the database with revisions falling within the rev_id range given.
- * @param $start Int: inclusive lower limit (this id is included)
+ * @param int $start inclusive lower limit (this id is included)
* @param $end Int: Exclusive upper limit (this id is not included)
* If 0, no upper limit.
*/
@@ -226,7 +226,7 @@ class WikiExporter {
foreach ( $res as $row ) {
$this->author_list .= "<contributor>" .
"<username>" .
- htmlentities( $row->rev_user_text ) .
+ htmlentities( $row->rev_user_text ) .
"</username>" .
"<id>" .
$row->rev_user .
@@ -330,7 +330,7 @@ class WikiExporter {
$join['revision'] = array( 'INNER JOIN', 'page_id=rev_page' );
} elseif ( $this->history & WikiExporter::CURRENT ) {
# Latest revision dumps...
- if ( $this->list_authors && $cond != '' ) { // List authors, if so desired
+ if ( $this->list_authors && $cond != '' ) { // List authors, if so desired
$this->do_list_authors( $cond );
}
$join['revision'] = array( 'INNER JOIN', 'page_id=rev_page AND page_latest=rev_id' );
@@ -348,7 +348,7 @@ class WikiExporter {
$join['revision'] = array( 'INNER JOIN', 'page_id=rev_page' );
$opts['ORDER BY'] = array( 'rev_page ASC', 'rev_id ASC' );
} else {
- # Uknown history specification parameter?
+ # Unknown history specification parameter?
wfProfileOut( __METHOD__ );
throw new MWException( __METHOD__ . " given invalid history dump type." );
}
@@ -427,10 +427,10 @@ class WikiExporter {
protected function outputPageStream( $resultset ) {
$last = null;
foreach ( $resultset as $row ) {
- if ( is_null( $last ) ||
+ if ( $last === null ||
$last->page_namespace != $row->page_namespace ||
- $last->page_title != $row->page_title ) {
- if ( isset( $last ) ) {
+ $last->page_title != $row->page_title ) {
+ if ( $last !== null ) {
$output = '';
if ( $this->dumpUploads ) {
$output .= $this->writer->writeUploads( $last, $this->dumpUploadFileContents );
@@ -445,7 +445,7 @@ class WikiExporter {
$output = $this->writer->writeRevision( $row );
$this->sink->writeRevision( $row, $output );
}
- if ( isset( $last ) ) {
+ if ( $last !== null ) {
$output = '';
if ( $this->dumpUploads ) {
$output .= $this->writer->writeUploads( $last, $this->dumpUploadFileContents );
@@ -498,7 +498,7 @@ class XmlDumpWriter {
'xmlns' => "http://www.mediawiki.org/xml/export-$ver/",
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
'xsi:schemaLocation' => "http://www.mediawiki.org/xml/export-$ver/ " .
- "http://www.mediawiki.org/xml/export-$ver.xsd",
+ "http://www.mediawiki.org/xml/export-$ver.xsd", #TODO: how do we get a new version up there?
'version' => $ver,
'xml:lang' => $wgLanguageCode ),
null ) .
@@ -634,37 +634,31 @@ class XmlDumpWriter {
function writeRevision( $row ) {
wfProfileIn( __METHOD__ );
- $out = " <revision>\n";
+ $out = " <revision>\n";
$out .= " " . Xml::element( 'id', null, strval( $row->rev_id ) ) . "\n";
- if( $row->rev_parent_id ) {
+ if( isset( $row->rev_parent_id ) && $row->rev_parent_id ) {
$out .= " " . Xml::element( 'parentid', null, strval( $row->rev_parent_id ) ) . "\n";
}
$out .= $this->writeTimestamp( $row->rev_timestamp );
- if ( $row->rev_deleted & Revision::DELETED_USER ) {
+ if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_USER ) ) {
$out .= " " . Xml::element( 'contributor', array( 'deleted' => 'deleted' ) ) . "\n";
} else {
$out .= $this->writeContributor( $row->rev_user, $row->rev_user_text );
}
- if ( $row->rev_minor_edit ) {
- $out .= " <minor/>\n";
+ if ( isset( $row->rev_minor_edit ) && $row->rev_minor_edit ) {
+ $out .= " <minor/>\n";
}
- if ( $row->rev_deleted & Revision::DELETED_COMMENT ) {
+ if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_COMMENT ) ) {
$out .= " " . Xml::element( 'comment', array( 'deleted' => 'deleted' ) ) . "\n";
} elseif ( $row->rev_comment != '' ) {
$out .= " " . Xml::elementClean( 'comment', array(), strval( $row->rev_comment ) ) . "\n";
}
- if ( $row->rev_sha1 && !( $row->rev_deleted & Revision::DELETED_TEXT ) ) {
- $out .= " " . Xml::element('sha1', null, strval( $row->rev_sha1 ) ) . "\n";
- } else {
- $out .= " <sha1/>\n";
- }
-
$text = '';
- if ( $row->rev_deleted & Revision::DELETED_TEXT ) {
+ if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_TEXT ) ) {
$out .= " " . Xml::element( 'text', array( 'deleted' => 'deleted' ) ) . "\n";
} elseif ( isset( $row->old_text ) ) {
// Raw text from the database may have invalid chars
@@ -679,6 +673,34 @@ class XmlDumpWriter {
"" ) . "\n";
}
+ if ( isset( $row->rev_sha1 ) && $row->rev_sha1 && !( $row->rev_deleted & Revision::DELETED_TEXT ) ) {
+ $out .= " " . Xml::element( 'sha1', null, strval( $row->rev_sha1 ) ) . "\n";
+ } else {
+ $out .= " <sha1/>\n";
+ }
+
+ if ( isset( $row->rev_content_model ) && !is_null( $row->rev_content_model ) ) {
+ $content_model = strval( $row->rev_content_model );
+ } else {
+ // probably using $wgContentHandlerUseDB = false;
+ // @todo: test!
+ $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+ $content_model = ContentHandler::getDefaultModelFor( $title );
+ }
+
+ $out .= " " . Xml::element( 'model', null, strval( $content_model ) ) . "\n";
+
+ if ( isset( $row->rev_content_format ) && !is_null( $row->rev_content_format ) ) {
+ $content_format = strval( $row->rev_content_format );
+ } else {
+ // probably using $wgContentHandlerUseDB = false;
+ // @todo: test!
+ $content_handler = ContentHandler::getForModelID( $content_model );
+ $content_format = $content_handler->getDefaultFormat();
+ }
+
+ $out .= " " . Xml::element( 'format', null, strval( $content_format ) ) . "\n";
+
wfRunHooks( 'XmlDumpWriterWriteRevision', array( &$this, &$out, $row, $text ) );
$out .= " </revision>\n";
@@ -698,7 +720,7 @@ class XmlDumpWriter {
function writeLogItem( $row ) {
wfProfileIn( __METHOD__ );
- $out = " <logitem>\n";
+ $out = " <logitem>\n";
$out .= " " . Xml::element( 'id', null, strval( $row->log_id ) ) . "\n";
$out .= $this->writeTimestamp( $row->log_timestamp, " " );
@@ -736,7 +758,7 @@ class XmlDumpWriter {
/**
* @param $timestamp string
- * @param $indent string Default to six spaces
+ * @param string $indent Default to six spaces
* @return string
*/
function writeTimestamp( $timestamp, $indent = " " ) {
@@ -747,7 +769,7 @@ class XmlDumpWriter {
/**
* @param $id
* @param $text string
- * @param $indent string Default to six spaces
+ * @param string $indent Default to six spaces
* @return string
*/
function writeContributor( $id, $text, $indent = " " ) {
@@ -849,9 +871,8 @@ class XmlDumpWriter {
}
}
-
/**
- * Base class for output stream; prints to stdout or buffer or whereever.
+ * Base class for output stream; prints to stdout or buffer or wherever.
* @ingroup Dump
*/
class DumpOutput {
@@ -918,7 +939,6 @@ class DumpOutput {
* @param $newname mixed File name. May be a string or an array with one element
*/
function closeRenameAndReopen( $newname ) {
- return;
}
/**
@@ -926,10 +946,9 @@ class DumpOutput {
* Use this for the last piece of a file written out
* at specified checkpoints (e.g. every n hours).
* @param $newname mixed File name. May be a string or an array with one element
- * @param $open bool If true, a new file with the old filename will be opened again for writing (default: false)
+ * @param bool $open If true, a new file with the old filename will be opened again for writing (default: false)
*/
function closeAndRename( $newname, $open = false ) {
- return;
}
/**
@@ -938,7 +957,7 @@ class DumpOutput {
* @return null
*/
function getFilenames() {
- return NULL;
+ return null;
}
}
@@ -987,7 +1006,7 @@ class DumpFileOutput extends DumpOutput {
* @throws MWException
*/
function renameOrException( $newname ) {
- if (! rename( $this->filename, $newname ) ) {
+ if ( !rename( $this->filename, $newname ) ) {
throw new MWException( __METHOD__ . ": rename of file {$this->filename} to $newname failed\n" );
}
}
@@ -1050,7 +1069,7 @@ class DumpPipeOutput extends DumpFileOutput {
*/
function __construct( $command, $file = null ) {
if ( !is_null( $file ) ) {
- $command .= " > " . wfEscapeShellArg( $file );
+ $command .= " > " . wfEscapeShellArg( $file );
}
$this->startCommand( $command );
@@ -1106,7 +1125,7 @@ class DumpPipeOutput extends DumpFileOutput {
$this->renameOrException( $newname );
if ( $open ) {
$command = $this->command;
- $command .= " > " . wfEscapeShellArg( $this->filename );
+ $command .= " > " . wfEscapeShellArg( $this->filename );
$this->startCommand( $command );
}
}
@@ -1325,6 +1344,7 @@ class DumpNamespaceFilter extends DumpFilter {
/**
* @param $sink DumpOutput
* @param $param
+ * @throws MWException
*/
function __construct( &$sink, $param ) {
parent::__construct( $sink );
@@ -1338,7 +1358,7 @@ class DumpNamespaceFilter extends DumpFilter {
"NS_PROJECT_TALK" => NS_PROJECT_TALK,
"NS_FILE" => NS_FILE,
"NS_FILE_TALK" => NS_FILE_TALK,
- "NS_IMAGE" => NS_IMAGE, // NS_IMAGE is an alias for NS_FILE
+ "NS_IMAGE" => NS_IMAGE, // NS_IMAGE is an alias for NS_FILE
"NS_IMAGE_TALK" => NS_IMAGE_TALK,
"NS_MEDIAWIKI" => NS_MEDIAWIKI,
"NS_MEDIAWIKI_TALK" => NS_MEDIAWIKI_TALK,
@@ -1378,7 +1398,6 @@ class DumpNamespaceFilter extends DumpFilter {
}
}
-
/**
* Dump output filter to include only the last revision in each page sequence.
* @ingroup Dump
@@ -1423,7 +1442,7 @@ class DumpLatestFilter extends DumpFilter {
}
/**
- * Base class for output stream; prints to stdout or buffer or whereever.
+ * Base class for output stream; prints to stdout or buffer or wherever.
* @ingroup Dump
*/
class DumpMultiWriter {
@@ -1506,7 +1525,7 @@ class DumpMultiWriter {
function getFilenames() {
$filenames = array();
for ( $i = 0; $i < $this->count; $i++ ) {
- $filenames[] = $this->sinks[$i]->getFilenames();
+ $filenames[] = $this->sinks[$i]->getFilenames();
}
return $filenames;
}
diff --git a/includes/ExternalEdit.php b/includes/ExternalEdit.php
index 34683253..11e94230 100644
--- a/includes/ExternalEdit.php
+++ b/includes/ExternalEdit.php
@@ -40,7 +40,7 @@ class ExternalEdit extends ContextSource {
* Check whether external edit or diff should be used.
*
* @param $context IContextSource context to use
- * @param $type String can be either 'edit' or 'diff'
+ * @param string $type can be either 'edit' or 'diff'
* @return Bool
*/
public static function useExternalEngine( IContextSource $context, $type ) {
@@ -87,7 +87,7 @@ class ExternalEdit extends ContextSource {
'URL' => $image->getCanonicalURL()
)
);
- } else{
+ } else {
$urls = array();
}
} else {
diff --git a/includes/ExternalStore.php b/includes/ExternalStore.php
deleted file mode 100644
index 61d4ef7c..00000000
--- a/includes/ExternalStore.php
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-/**
- * Data storage in external repositories.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * @defgroup ExternalStorage ExternalStorage
- */
-
-/**
- * Constructor class for data kept in external repositories
- *
- * External repositories might be populated by maintenance/async
- * scripts, thus partial moving of data may be possible, as well
- * as possibility to have any storage format (i.e. for archives)
- *
- * @ingroup ExternalStorage
- */
-class ExternalStore {
- var $mParams;
-
- function __construct( $params = array() ) {
- $this->mParams = $params;
- }
-
- /**
- * Fetch data from given URL
- *
- * @param $url String: The URL of the text to get
- * @param $params Array: associative array of parameters for the ExternalStore object.
- * @return string|bool The text stored or false on error
- */
- static function fetchFromURL( $url, $params = array() ) {
- global $wgExternalStores;
-
- if( !$wgExternalStores )
- return false;
-
- $parts = explode( '://', $url, 2 );
-
- if ( count( $parts ) != 2 ) {
- return false;
- }
-
- list( $proto, $path ) = $parts;
-
- if ( $path == '' ) { // Bad URL
- return false;
- }
-
- $store = self::getStoreObject( $proto, $params );
- if ( $store === false )
- return false;
- return $store->fetchFromURL( $url );
- }
-
- /**
- * Get an external store object of the given type, with the given parameters
- *
- * @param $proto String: type of external storage, should be a value in $wgExternalStores
- * @param $params Array: associative array of parameters for the ExternalStore object.
- * @return ExternalStore subclass or false on error
- */
- static function getStoreObject( $proto, $params = array() ) {
- global $wgExternalStores;
- if( !$wgExternalStores )
- return false;
- /* Protocol not enabled */
- if( !in_array( $proto, $wgExternalStores ) )
- return false;
-
- $class = 'ExternalStore' . ucfirst( $proto );
- /* Any custom modules should be added to $wgAutoLoadClasses for on-demand loading */
- if( !MWInit::classExists( $class ) ) {
- return false;
- }
-
- return new $class($params);
- }
-
- /**
- * Store a data item to an external store, identified by a partial URL
- * The protocol part is used to identify the class, the rest is passed to the
- * class itself as a parameter.
- * @param $url
- * @param $data
- * @param $params array
- * @return string|bool The URL of the stored data item, or false on error
- */
- static function insert( $url, $data, $params = array() ) {
- list( $proto, $params ) = explode( '://', $url, 2 );
- $store = self::getStoreObject( $proto, $params );
- if ( $store === false ) {
- return false;
- } else {
- return $store->store( $params, $data );
- }
- }
-
- /**
- * Like insert() above, but does more of the work for us.
- * This function does not need a url param, it builds it by
- * itself. It also fails-over to the next possible clusters.
- *
- * @param $data String
- * @param $storageParams Array: associative array of parameters for the ExternalStore object.
- * @return string The URL of the stored data item, or false on error
- */
- public static function insertToDefault( $data, $storageParams = array() ) {
- global $wgDefaultExternalStore;
- $tryStores = (array)$wgDefaultExternalStore;
- $error = false;
- while ( count( $tryStores ) > 0 ) {
- $index = mt_rand(0, count( $tryStores ) - 1);
- $storeUrl = $tryStores[$index];
- wfDebug( __METHOD__.": trying $storeUrl\n" );
- list( $proto, $params ) = explode( '://', $storeUrl, 2 );
- $store = self::getStoreObject( $proto, $storageParams );
- if ( $store === false ) {
- throw new MWException( "Invalid external storage protocol - $storeUrl" );
- }
- try {
- $url = $store->store( $params, $data ); // Try to save the object
- } catch ( DBConnectionError $error ) {
- $url = false;
- } catch( DBQueryError $error ) {
- $url = false;
- }
- if ( $url ) {
- return $url; // Done!
- } else {
- unset( $tryStores[$index] ); // Don't try this one again!
- $tryStores = array_values( $tryStores ); // Must have consecutive keys
- wfDebugLog( 'ExternalStorage', "Unable to store text to external storage $storeUrl" );
- }
- }
- // All stores failed
- if ( $error ) {
- // Rethrow the last connection error
- throw $error;
- } else {
- throw new MWException( "Unable to store text to external storage" );
- }
- }
-
- /**
- * @param $data
- * @param $wiki
- *
- * @return string
- */
- public static function insertToForeignDefault( $data, $wiki ) {
- return self::insertToDefault( $data, array( 'wiki' => $wiki ) );
- }
-}
diff --git a/includes/ExternalUser.php b/includes/ExternalUser.php
index 9a01deb7..580b9896 100644
--- a/includes/ExternalUser.php
+++ b/includes/ExternalUser.php
@@ -128,7 +128,7 @@ abstract class ExternalUser {
* @param $name string
* @return bool Success?
*/
- protected abstract function initFromName( $name );
+ abstract protected function initFromName( $name );
/**
* Given an id, which was at some previous point in history returned by
@@ -138,7 +138,7 @@ abstract class ExternalUser {
* @param $id string
* @return bool Success?
*/
- protected abstract function initFromId( $id );
+ abstract protected function initFromId( $id );
/**
* Try to magically initialize the user from cookies or similar information
@@ -278,23 +278,23 @@ abstract class ExternalUser {
* This is part of the core code and is not overridable by specific
* plugins. It's in this class only for convenience.
*
- * @param $id int user_id
+ * @param int $id user_id
*/
- public final function linkToLocal( $id ) {
+ final public function linkToLocal( $id ) {
$dbw = wfGetDB( DB_MASTER );
$dbw->replace( 'external_user',
array( 'eu_local_id', 'eu_external_id' ),
array( 'eu_local_id' => $id,
- 'eu_external_id' => $this->getId() ),
+ 'eu_external_id' => $this->getId() ),
__METHOD__ );
}
-
+
/**
* Check whether this external user id is already linked with
* a local user.
* @return Mixed User if the account is linked, Null otherwise.
*/
- public final function getLocalUser(){
+ final public function getLocalUser() {
$dbr = wfGetDB( DB_SLAVE );
$row = $dbr->selectRow(
'external_user',
@@ -305,5 +305,5 @@ abstract class ExternalUser {
? User::newFromId( $row->eu_local_id )
: null;
}
-
+
}
diff --git a/includes/FakeTitle.php b/includes/FakeTitle.php
index 60f7600d..efa213fb 100644
--- a/includes/FakeTitle.php
+++ b/includes/FakeTitle.php
@@ -114,9 +114,9 @@ class FakeTitle extends Title {
function getParentCategories() { $this->error(); }
function getParentCategoryTree( $children = array() ) { $this->error(); }
function pageCond() { $this->error(); }
- function getPreviousRevisionID( $revId, $flags=0 ) { $this->error(); }
- function getNextRevisionID( $revId, $flags=0 ) { $this->error(); }
- function getFirstRevision( $flags=0 ) { $this->error(); }
+ function getPreviousRevisionID( $revId, $flags = 0 ) { $this->error(); }
+ function getNextRevisionID( $revId, $flags = 0 ) { $this->error(); }
+ function getFirstRevision( $flags = 0 ) { $this->error(); }
function isNewPage() { $this->error(); }
function getEarliestRevTime( $flags = 0 ) { $this->error(); }
function countRevisionsBetween( $old, $new ) { $this->error(); }
diff --git a/includes/Fallback.php b/includes/Fallback.php
index 4b138c11..2e19a095 100644
--- a/includes/Fallback.php
+++ b/includes/Fallback.php
@@ -149,13 +149,12 @@ class Fallback {
return $total;
}
-
/**
* Fallback implementation of mb_strpos, hardcoded to UTF-8.
* @param $haystack String
* @param $needle String
- * @param $offset String: optional start position
- * @param $encoding String: optional encoding; ignored
+ * @param string $offset optional start position
+ * @param string $encoding optional encoding; ignored
* @return int
*/
public static function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
@@ -175,8 +174,8 @@ class Fallback {
* Fallback implementation of mb_strrpos, hardcoded to UTF-8.
* @param $haystack String
* @param $needle String
- * @param $offset String: optional start position
- * @param $encoding String: optional encoding; ignored
+ * @param string $offset optional start position
+ * @param string $encoding optional encoding; ignored
* @return int
*/
public static function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
@@ -192,22 +191,4 @@ class Fallback {
return false;
}
}
-
- /**
- * Fallback implementation of stream_resolve_include_path()
- * Native stream_resolve_include_path is available for PHP 5 >= 5.3.2
- * @param $filename String
- * @return String
- */
- public static function stream_resolve_include_path( $filename ) {
- $pathArray = explode( PATH_SEPARATOR, get_include_path() );
- foreach ( $pathArray as $path ) {
- $fullFilename = $path . DIRECTORY_SEPARATOR . $filename;
- if ( file_exists( $fullFilename ) ) {
- return $fullFilename;
- }
- }
- return false;
- }
-
}
diff --git a/includes/Feed.php b/includes/Feed.php
index f9dbf5ba..caf2e571 100644
--- a/includes/Feed.php
+++ b/includes/Feed.php
@@ -52,11 +52,11 @@ class FeedItem {
/**
* Constructor
*
- * @param $title String|Title Item's title
+ * @param string|Title $title Item's title
* @param $description String
- * @param $url String: URL uniquely designating the item.
- * @param $date String: Item's date
- * @param $author String: Author's user name
+ * @param string $url URL uniquely designating the item.
+ * @param string $date Item's date
+ * @param string $author Author's user name
* @param $comments String
*/
function __construct( $title, $description, $url, $date = '', $author = '', $comments = '' ) {
@@ -72,7 +72,7 @@ class FeedItem {
/**
* Encode $string so that it can be safely embedded in a XML document
*
- * @param $string String: string to encode
+ * @param string $string string to encode
* @return String
*/
public function xmlEncode( $string ) {
@@ -95,7 +95,7 @@ class FeedItem {
/**
* set the unique id of an item
*
- * @param $uniqueId String: unique id for the item
+ * @param string $uniqueId unique id for the item
* @param $rssIsPermalink Boolean: set to true if the guid (unique id) is a permalink (RSS feeds only)
*/
public function setUniqueId( $uniqueId, $rssIsPermalink = false ) {
@@ -170,7 +170,7 @@ class FeedItem {
/**
* Quickie hack... strip out wikilinks to more legible form from the comment.
*
- * @param $text String: wikitext
+ * @param string $text wikitext
* @return String
*/
public static function stripComment( $text ) {
@@ -243,9 +243,9 @@ abstract class ChannelFeed extends FeedItem {
*/
function contentType() {
global $wgRequest;
- $ctype = $wgRequest->getVal('ctype','application/xml');
- $allowedctypes = array('application/xml','text/xml','application/rss+xml','application/atom+xml');
- return (in_array($ctype, $allowedctypes) ? $ctype : 'application/xml');
+ $ctype = $wgRequest->getVal( 'ctype', 'application/xml' );
+ $allowedctypes = array( 'application/xml', 'text/xml', 'application/rss+xml', 'application/atom+xml' );
+ return (in_array( $ctype, $allowedctypes ) ? $ctype : 'application/xml');
}
/**
@@ -282,7 +282,7 @@ class RSSFeed extends ChannelFeed {
}
/**
- * Ouput an RSS 2.0 header
+ * Output an RSS 2.0 header
*/
function outHeader() {
global $wgVersion;
@@ -318,7 +318,7 @@ class RSSFeed extends ChannelFeed {
}
/**
- * Ouput an RSS 2.0 footer
+ * Output an RSS 2.0 footer
*/
function outFooter() {
?>
@@ -362,7 +362,7 @@ class AtomFeed extends ChannelFeed {
}
/**
- * Atom 1.0 requires a unique, opaque IRI as a unique indentifier
+ * Atom 1.0 requires a unique, opaque IRI as a unique identifier
* for every feed we create. For now just use the URL, but who
* can tell if that's right? If we put options on the feed, do we
* have to change the id? Maybe? Maybe not.
@@ -409,7 +409,7 @@ class AtomFeed extends ChannelFeed {
}
/**
- * Outputs the footer for Atom 1.0 feed (basicly '\</feed\>').
+ * Outputs the footer for Atom 1.0 feed (basically '\</feed\>').
*/
function outFooter() {?>
</feed><?php
diff --git a/includes/FeedUtils.php b/includes/FeedUtils.php
index 11b2675d..adc1f781 100644
--- a/includes/FeedUtils.php
+++ b/includes/FeedUtils.php
@@ -33,13 +33,13 @@ class FeedUtils {
* If the feed should be purged; $timekey and $key will be removed from
* $messageMemc
*
- * @param $timekey String: cache key of the timestamp of the last item
- * @param $key String: cache key of feed's content
+ * @param string $timekey cache key of the timestamp of the last item
+ * @param string $key cache key of feed's content
*/
public static function checkPurge( $timekey, $key ) {
global $wgRequest, $wgUser, $messageMemc;
$purge = $wgRequest->getVal( 'action' ) === 'purge';
- if ( $purge && $wgUser->isAllowed('purge') ) {
+ if ( $purge && $wgUser->isAllowed( 'purge' ) ) {
$messageMemc->delete( $timekey );
$messageMemc->delete( $key );
}
@@ -48,7 +48,7 @@ class FeedUtils {
/**
* Check whether feeds can be used and that $type is a valid feed type
*
- * @param $type String: feed type, as requested by the user
+ * @param string $type feed type, as requested by the user
* @return Boolean
*/
public static function checkFeedOutput( $type ) {
@@ -85,9 +85,9 @@ class FeedUtils {
$row->rc_last_oldid, $row->rc_this_oldid,
$timestamp,
($row->rc_deleted & Revision::DELETED_COMMENT)
- ? wfMessage('rev-deleted-comment')->escaped()
+ ? wfMessage( 'rev-deleted-comment' )->escaped()
: $row->rc_comment,
- $actiontext
+ $actiontext
);
}
@@ -98,15 +98,15 @@ class FeedUtils {
* @param $oldid Integer: old revision's id
* @param $newid Integer: new revision's id
* @param $timestamp Integer: new revision's timestamp
- * @param $comment String: new revision's comment
- * @param $actiontext String: text of the action; in case of log event
+ * @param string $comment new revision's comment
+ * @param string $actiontext text of the action; in case of log event
* @return String
*/
- public static function formatDiffRow( $title, $oldid, $newid, $timestamp, $comment, $actiontext='' ) {
+ public static function formatDiffRow( $title, $oldid, $newid, $timestamp, $comment, $actiontext = '' ) {
global $wgFeedDiffCutoff, $wgLang;
wfProfileIn( __METHOD__ );
- # log enties
+ // log entries
$completeText = '<p>' . implode( ' ',
array_filter(
array(
@@ -115,7 +115,7 @@ class FeedUtils {
// NOTE: Check permissions for anonymous users, not current user.
// No "privileged" version should end up in the cache.
- // Most feed readers will not log in anway.
+ // Most feed readers will not log in anyway.
$anon = new User();
$accErrors = $title->getUserPermissionsErrors( 'read', $anon, true );
@@ -138,13 +138,23 @@ class FeedUtils {
$diffText = '';
// Don't bother generating the diff if we won't be able to show it
if ( $wgFeedDiffCutoff > 0 ) {
- $de = new DifferenceEngine( $title, $oldid, $newid );
- $diffText = $de->getDiff(
- wfMessage( 'previousrevision' )->text(), // hack
- wfMessage( 'revisionasof',
- $wgLang->timeanddate( $timestamp ),
- $wgLang->date( $timestamp ),
- $wgLang->time( $timestamp ) )->text() );
+ $rev = Revision::newFromId( $oldid );
+
+ if ( !$rev ) {
+ $diffText = false;
+ } else {
+ $context = clone RequestContext::getMain();
+ $context->setTitle( $title );
+
+ $contentHandler = $rev->getContentHandler();
+ $de = $contentHandler->createDifferenceEngine( $context, $oldid, $newid );
+ $diffText = $de->getDiff(
+ wfMessage( 'previousrevision' )->text(), // hack
+ wfMessage( 'revisionasof',
+ $wgLang->timeanddate( $timestamp ),
+ $wgLang->date( $timestamp ),
+ $wgLang->time( $timestamp ) )->text() );
+ }
}
if ( $wgFeedDiffCutoff <= 0 || ( strlen( $diffText ) > $wgFeedDiffCutoff ) ) {
@@ -162,16 +172,36 @@ class FeedUtils {
} else {
$rev = Revision::newFromId( $newid );
if( $wgFeedDiffCutoff <= 0 || is_null( $rev ) ) {
- $newtext = '';
+ $newContent = ContentHandler::getForTitle( $title )->makeEmptyContent();
+ } else {
+ $newContent = $rev->getContent();
+ }
+
+ if ( $newContent instanceof TextContent ) {
+ // only textual content has a "source view".
+ $text = $newContent->getNativeData();
+
+ if ( $wgFeedDiffCutoff <= 0 || strlen( $text ) > $wgFeedDiffCutoff ) {
+ $html = null;
+ } else {
+ $html = nl2br( htmlspecialchars( $text ) );
+ }
} else {
- $newtext = $rev->getText();
+ //XXX: we could get an HTML representation of the content via getParserOutput, but that may
+ // contain JS magic and generally may not be suitable for inclusion in a feed.
+ // Perhaps Content should have a getDescriptiveHtml method and/or a getSourceText method.
+ //Compare also ApiFeedContributions::feedItemDesc
+ $html = null;
}
- if ( $wgFeedDiffCutoff <= 0 || strlen( $newtext ) > $wgFeedDiffCutoff ) {
+
+ if ( $html === null ) {
+
// Omit large new page diffs, bug 29110
+ // Also use diff link for non-textual content
$diffText = self::getDiffLink( $title, $newid );
} else {
$diffText = '<p><b>' . wfMessage( 'newpage' )->text() . '</b></p>' .
- '<div>' . nl2br( htmlspecialchars( $newtext ) ) . '</div>';
+ '<div>' . $html . '</div>';
}
}
$completeText .= $diffText;
@@ -192,7 +222,7 @@ class FeedUtils {
protected static function getDiffLink( Title $title, $newid, $oldid = null ) {
$queryParameters = ($oldid == null)
? "diff={$newid}"
- : "diff={$newid}&oldid={$oldid}" ;
+ : "diff={$newid}&oldid={$oldid}";
$diffUrl = $title->getFullUrl( $queryParameters );
$diffLink = Html::element( 'a', array( 'href' => $diffUrl ),
@@ -206,18 +236,18 @@ class FeedUtils {
* Might be 'cleaner' to use DOM or XSLT or something,
* but *gack* it's a pain in the ass.
*
- * @param $text String: diff's HTML output
+ * @param string $text diff's HTML output
* @return String: modified HTML
*/
public static function applyDiffStyle( $text ) {
$styles = array(
'diff' => 'background-color: white; color:black;',
- 'diff-otitle' => 'background-color: white; color:black;',
- 'diff-ntitle' => 'background-color: white; color:black;',
- 'diff-addedline' => 'background: #cfc; color:black; font-size: smaller;',
- 'diff-deletedline' => 'background: #ffa; color:black; font-size: smaller;',
- 'diff-context' => 'background: #eee; color:black; font-size: smaller;',
- 'diffchange' => 'color: red; font-weight: bold; text-decoration: none;',
+ 'diff-otitle' => 'background-color: white; color:black; text-align: center;',
+ 'diff-ntitle' => 'background-color: white; color:black; text-align: center;',
+ 'diff-addedline' => 'color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;',
+ 'diff-deletedline' => 'color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;',
+ 'diff-context' => 'background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;',
+ 'diffchange' => 'font-weight: bold; text-decoration: none;',
);
foreach( $styles as $class => $style ) {
diff --git a/includes/FileDeleteForm.php b/includes/FileDeleteForm.php
index e75ad729..28403cca 100644
--- a/includes/FileDeleteForm.php
+++ b/includes/FileDeleteForm.php
@@ -80,13 +80,13 @@ class FileDeleteForm {
$this->oldimage = $wgRequest->getText( 'oldimage', false );
$token = $wgRequest->getText( 'wpEditToken' );
# Flag to hide all contents of the archived revisions
- $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('suppressrevision');
+ $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed( 'suppressrevision' );
if( $this->oldimage ) {
$this->oldfile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->title, $this->oldimage );
}
- if( !self::haveDeletableFile($this->file, $this->oldfile, $this->oldimage) ) {
+ if( !self::haveDeletableFile( $this->file, $this->oldfile, $this->oldimage ) ) {
$wgOut->addHTML( $this->prepareMessage( 'filedelete-nofile' ) );
$wgOut->addReturnTo( $this->title );
return;
@@ -140,10 +140,11 @@ class FileDeleteForm {
*
* @param $title Title object
* @param File $file: file object
- * @param $oldimage String: archive name
- * @param $reason String: reason of the deletion
+ * @param string $oldimage archive name
+ * @param string $reason reason of the deletion
* @param $suppress Boolean: whether to mark all deleted versions as restricted
* @param $user User object performing the request
+ * @throws MWException
* @return bool|Status
*/
public static function doDelete( &$title, &$file, &$oldimage, $reason, $suppress, User $user = null ) {
@@ -308,7 +309,7 @@ class FileDeleteForm {
* showing an appropriate message depending upon whether
* it's a current file or an old version
*
- * @param $message String: message base
+ * @param string $message message base
* @return String
*/
private function prepareMessage( $message ) {
@@ -343,7 +344,7 @@ class FileDeleteForm {
*
* @return bool
*/
- public static function isValidOldSpec($oldimage) {
+ public static function isValidOldSpec( $oldimage ) {
return strlen( $oldimage ) >= 16
&& strpos( $oldimage, '/' ) === false
&& strpos( $oldimage, '\\' ) === false;
@@ -359,7 +360,7 @@ class FileDeleteForm {
* @param $oldimage File
* @return bool
*/
- public static function haveDeletableFile(&$file, &$oldfile, $oldimage) {
+ public static function haveDeletableFile( &$file, &$oldfile, $oldimage ) {
return $oldimage
? $oldfile && $oldfile->exists() && $oldfile->isLocal()
: $file && $file->exists() && $file->isLocal();
@@ -374,8 +375,9 @@ class FileDeleteForm {
$q = array();
$q['action'] = 'delete';
- if( $this->oldimage )
+ if( $this->oldimage ) {
$q['oldimage'] = $this->oldimage;
+ }
return $this->title->getLocalUrl( $q );
}
diff --git a/includes/ForkController.php b/includes/ForkController.php
index 448bc03b..89ad9553 100644
--- a/includes/ForkController.php
+++ b/includes/ForkController.php
@@ -53,7 +53,7 @@ class ForkController {
const RESTART_ON_ERROR = 1;
public function __construct( $numProcs, $flags = 0 ) {
- if ( php_sapi_name() != 'cli' ) {
+ if ( PHP_SAPI != 'cli' ) {
throw new MWException( "ForkController cannot be used from the web." );
}
$this->procsToStart = $numProcs;
@@ -140,7 +140,7 @@ class ForkController {
// Don't share DB, storage, or memcached connections
wfGetLBFactory()->destroyInstance();
FileBackendGroup::destroySingleton();
- LockManagerGroup::destroySingleton();
+ LockManagerGroup::destroySingletons();
ObjectCache::clear();
$wgMemc = null;
}
diff --git a/includes/FormOptions.php b/includes/FormOptions.php
index 33bbd86a..8477ed98 100644
--- a/includes/FormOptions.php
+++ b/includes/FormOptions.php
@@ -2,7 +2,7 @@
/**
* Helper class to keep track of options when mixing links and form elements.
*
- * Copyright © 2008, Niklas Laxstiröm
+ * Copyright © 2008, Niklas Laxström
* Copyright © 2011, Antoine Musso
*
* This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
*
* @file
* @author Niklas Laxström
- * @author Antoine Musso
+ * @author Antoine Musso
*/
/**
@@ -83,6 +83,7 @@ class FormOptions implements ArrayAccess {
* which will be assumed as INT if the data is an integer.
*
* @param $data Mixed: value to guess type for
+ * @throws MWException
* @exception MWException Unsupported datatype
* @return int Type constant
*/
@@ -103,8 +104,9 @@ class FormOptions implements ArrayAccess {
/**
* Verify the given option name exist.
*
- * @param $name String: option name
+ * @param string $name option name
* @param $strict Boolean: throw an exception when the option does not exist (default false)
+ * @throws MWException
* @return Boolean: true if option exist, false otherwise
*/
public function validateName( $name, $strict = false ) {
@@ -121,7 +123,7 @@ class FormOptions implements ArrayAccess {
/**
* Use to set the value of an option.
*
- * @param $name String: option name
+ * @param string $name option name
* @param $value Mixed: value for the option
* @param $force Boolean: whether to set the value when it is equivalent to the default value for this option (default false).
* @return null
@@ -141,7 +143,7 @@ class FormOptions implements ArrayAccess {
* Get the value for the given option name.
* Internally use getValueReal()
*
- * @param $name String: option name
+ * @param string $name option name
* @return Mixed
*/
public function getValue( $name ) {
@@ -152,7 +154,7 @@ class FormOptions implements ArrayAccess {
/**
* @todo Document
- * @param $option Array: array structure describing the option
+ * @param array $option array structure describing the option
* @return Mixed. Value or the default value if it is null
*/
protected function getValueReal( $option ) {
@@ -166,7 +168,7 @@ class FormOptions implements ArrayAccess {
/**
* Delete the option value.
* This will make future calls to getValue() return the default value.
- * @param $name String: option name
+ * @param string $name option name
* @return null
*/
public function reset( $name ) {
@@ -176,8 +178,9 @@ class FormOptions implements ArrayAccess {
/**
* @todo Document
- * @param $name String: option name
- * @return null
+ * @param string $name Option name
+ * @throws MWException If option does not exist.
+ * @return mixed Value or the default value if it is null.
*/
public function consumeValue( $name ) {
$this->validateName( $name, true );
@@ -188,7 +191,7 @@ class FormOptions implements ArrayAccess {
/**
* @todo Document
- * @param $names Array: array of option names
+ * @param array $names array of option names
* @return null
*/
public function consumeValues( /*Array*/ $names ) {
@@ -205,11 +208,12 @@ class FormOptions implements ArrayAccess {
/**
* Validate and set an option integer value
- * The value will be altered to fit in the range.
+ * The value will be altered to fit in the range.
*
- * @param $name String: option name
- * @param $min Int: minimum value
- * @param $max Int: maximum value
+ * @param string $name option name
+ * @param int $min minimum value
+ * @param int $max maximum value
+ * @throws MWException
* @exception MWException Option is not of type int
* @return null
*/
diff --git a/includes/GitInfo.php b/includes/GitInfo.php
index c3c30733..6f7f8020 100644
--- a/includes/GitInfo.php
+++ b/includes/GitInfo.php
@@ -41,10 +41,18 @@ class GitInfo {
private static $viewers = false;
/**
- * @param $dir string The root directory of the repo where the .git dir can be found
+ * @param string $dir The root directory of the repo where the .git dir can be found
*/
public function __construct( $dir ) {
- $this->basedir = "{$dir}/.git/";
+ $this->basedir = "{$dir}/.git";
+ if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
+ $GITfile = file_get_contents( $this->basedir );
+ if ( strlen( $GITfile ) > 8 && substr( $GITfile, 0, 8 ) === 'gitdir: ' ) {
+ $path = rtrim( substr( $GITfile, 8 ), "\r\n" );
+ $isAbsolute = $path[0] === '/' || substr( $path, 1, 1 ) === ':';
+ $this->basedir = $isAbsolute ? $path : "{$dir}/{$path}";
+ }
+ }
}
/**
@@ -62,7 +70,7 @@ class GitInfo {
/**
* Check if a string looks like a hex encoded SHA1 hash
*
- * @param $str string The string to check
+ * @param string $str The string to check
* @return bool Whether or not the string looks like a SHA1
*/
public static function isSHA1( $str ) {
@@ -102,7 +110,7 @@ class GitInfo {
}
// If not a SHA1 it may be a ref:
- $REFfile = "{$this->basedir}{$HEAD}";
+ $REFfile = "{$this->basedir}/{$HEAD}";
if ( !is_readable( $REFfile ) ) {
return false;
}
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
index 50758c89..016736f4 100644
--- a/includes/GlobalFunctions.php
+++ b/includes/GlobalFunctions.php
@@ -50,7 +50,7 @@ if ( !function_exists( 'mb_substr' ) ) {
* @codeCoverageIgnore
* @return string
*/
- function mb_substr( $str, $start, $count='end' ) {
+ function mb_substr( $str, $start, $count = 'end' ) {
return Fallback::mb_substr( $str, $start, $count );
}
@@ -94,7 +94,6 @@ if( !function_exists( 'mb_strrpos' ) ) {
}
}
-
// Support for Wietse Venema's taint feature
if ( !function_exists( 'istainted' ) ) {
/**
@@ -168,7 +167,8 @@ function wfArrayLookup( $a, $b ) {
* @param $key String|Int
* @param $value Mixed
* @param $default Mixed
- * @param $changed Array to alter
+ * @param array $changed to alter
+ * @throws MWException
*/
function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
if ( is_null( $changed ) ) {
@@ -232,8 +232,8 @@ function wfMergeErrorArrays( /*...*/ ) {
/**
* Insert array into another array after the specified *KEY*
*
- * @param $array Array: The array.
- * @param $insert Array: The array to insert.
+ * @param array $array The array.
+ * @param array $insert The array to insert.
* @param $after Mixed: The key to insert after
* @return Array
*/
@@ -311,12 +311,12 @@ function wfRandom() {
}
/**
- * Get a random string containing a number of pesudo-random hex
+ * Get a random string containing a number of pseudo-random hex
* characters.
* @note This is not secure, if you are trying to generate some sort
* of token please use MWCryptRand instead.
*
- * @param $length int The length of the string to generate
+ * @param int $length The length of the string to generate
* @return String
* @since 1.20
*/
@@ -349,7 +349,7 @@ function wfRandomString( $length = 32 ) {
*
* @param $s String:
* @return string
-*/
+ */
function wfUrlencode( $s ) {
static $needle;
if ( is_null( $s ) ) {
@@ -379,8 +379,8 @@ function wfUrlencode( $s ) {
* "days=7&limit=100". Options in the first array override options in the second.
* Options set to null or false will not be output.
*
- * @param $array1 Array ( String|Array )
- * @param $array2 Array ( String|Array )
+ * @param array $array1 ( String|Array )
+ * @param array $array2 ( String|Array )
* @param $prefix String
* @return String
*/
@@ -391,7 +391,7 @@ function wfArrayToCgi( $array1, $array2 = null, $prefix = '' ) {
$cgi = '';
foreach ( $array1 as $key => $value ) {
- if ( !is_null($value) && $value !== false ) {
+ if ( !is_null( $value ) && $value !== false ) {
if ( $cgi != '' ) {
$cgi .= '&';
}
@@ -422,11 +422,11 @@ function wfArrayToCgi( $array1, $array2 = null, $prefix = '' ) {
/**
* This is the logical opposite of wfArrayToCgi(): it accepts a query string as
- * its argument and returns the same string in array form. This allows compa-
- * tibility with legacy functions that accept raw query strings instead of nice
+ * its argument and returns the same string in array form. This allows compatibility
+ * with legacy functions that accept raw query strings instead of nice
* arrays. Of course, keys and values are urldecode()d.
*
- * @param $query String: query string
+ * @param string $query query string
* @return array Array version of input
*/
function wfCgiToArray( $query ) {
@@ -506,7 +506,7 @@ function wfAppendQuery( $url, $query ) {
* @todo this won't work with current-path-relative URLs
* like "subdir/foo.html", etc.
*
- * @param $url String: either fully-qualified or a local path + query
+ * @param string $url either fully-qualified or a local path + query
* @param $defaultProto Mixed: one of the PROTO_* constants. Determines the
* protocol to use if $url or $wgServer is
* protocol-relative
@@ -576,7 +576,7 @@ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
* @todo Need to integrate this into wfExpandUrl (bug 32168)
*
* @since 1.19
- * @param $urlParts Array URL parts, as output from wfParseUrl
+ * @param array $urlParts URL parts, as output from wfParseUrl
* @return string URL assembled from its component parts
*/
function wfAssembleUrl( $urlParts ) {
@@ -628,7 +628,7 @@ function wfAssembleUrl( $urlParts ) {
*
* @todo Need to integrate this into wfExpandUrl (bug 32168)
*
- * @param $urlPath String URL path, potentially containing dot-segments
+ * @param string $urlPath URL path, potentially containing dot-segments
* @return string URL path with all dot-segments removed
*/
function wfRemoveDotSegments( $urlPath ) {
@@ -705,7 +705,7 @@ function wfRemoveDotSegments( $urlPath ) {
/**
* Returns a regular expression of url protocols
*
- * @param $includeProtocolRelative bool If false, remove '//' from the returned protocol list.
+ * @param bool $includeProtocolRelative If false, remove '//' from the returned protocol list.
* DO NOT USE this directly, use wfUrlProtocolsWithoutProtRel() instead
* @return String
*/
@@ -765,7 +765,7 @@ function wfUrlProtocolsWithoutProtRel() {
* 2) Handles protocols that don't use :// (e.g., mailto: and news: , as well as protocol-relative URLs) correctly
* 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2))
*
- * @param $url String: a URL to parse
+ * @param string $url a URL to parse
* @return Array: bits of the URL in an associative array, per PHP docs
*/
function wfParseUrl( $url ) {
@@ -808,9 +808,14 @@ function wfParseUrl( $url ) {
if ( !isset( $bits['host'] ) ) {
$bits['host'] = '';
- /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
- if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
- $bits['path'] = '/' . $bits['path'];
+ // bug 45069
+ if ( isset( $bits['path'] ) ) {
+ /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
+ if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
+ $bits['path'] = '/' . $bits['path'];
+ }
+ } else {
+ $bits['path'] = '';
}
}
@@ -845,8 +850,6 @@ function wfExpandIRI_callback( $matches ) {
return urldecode( $matches[1] );
}
-
-
/**
* Make URL indexes, appropriate for the el_index field of externallinks.
*
@@ -903,8 +906,8 @@ function wfMakeUrlIndexes( $url ) {
/**
* Check whether a given URL has a domain that occurs in a given set of domains
- * @param $url string URL
- * @param $domains array Array of domains (strings)
+ * @param string $url URL
+ * @param array $domains Array of domains (strings)
* @return bool True if the host part of $url ends in one of the strings in $domains
*/
function wfMatchesDomainList( $url, $domains ) {
@@ -932,7 +935,7 @@ function wfMatchesDomainList( $url, $domains ) {
* $wgDebugComments - if on, some debug items may appear in comments in the HTML output.
*
* @param $text String
- * @param $logonly Bool: set true to avoid appearing in HTML when $wgDebugComments is set
+ * @param bool $logonly set true to avoid appearing in HTML when $wgDebugComments is set
*/
function wfDebug( $text, $logonly = false ) {
global $wgDebugLogFile, $wgProfileOnly, $wgDebugRawPage, $wgDebugLogPrefix;
@@ -1004,7 +1007,7 @@ function wfDebugTimer() {
/**
* Send a line giving PHP memory usage.
*
- * @param $exact Bool: print exact values instead of kilobytes (default: false)
+ * @param bool $exact print exact values instead of kilobytes (default: false)
*/
function wfDebugMem( $exact = false ) {
$mem = memory_get_usage();
@@ -1022,7 +1025,7 @@ function wfDebugMem( $exact = false ) {
*
* @param $logGroup String
* @param $text String
- * @param $public Bool: whether to log the event in the public log if no private
+ * @param bool $public whether to log the event in the public log if no private
* log file is specified, (default true)
*/
function wfDebugLog( $logGroup, $text, $public = true ) {
@@ -1036,14 +1039,14 @@ function wfDebugLog( $logGroup, $text, $public = true ) {
wfErrorLog( "$time $host $wiki: $text", $wgDebugLogGroups[$logGroup] );
}
} elseif ( $public === true ) {
- wfDebug( $text, true );
+ wfDebug( "[$logGroup] $text", true );
}
}
/**
* Log for database errors
*
- * @param $text String: database error message.
+ * @param string $text database error message.
*/
function wfLogDBError( $text ) {
global $wgDBerrorLog, $wgDBerrorLogTZ;
@@ -1076,9 +1079,9 @@ function wfLogDBError( $text ) {
* Throws a warning that $function is deprecated
*
* @param $function String
- * @param $version String|bool: Version of MediaWiki that the function was deprecated in (Added in 1.19).
- * @param $component String|bool: Added in 1.19.
- * @param $callerOffset integer: How far up the callstack is the original
+ * @param string|bool $version Version of MediaWiki that the function was deprecated in (Added in 1.19).
+ * @param string|bool $component Added in 1.19.
+ * @param $callerOffset integer: How far up the call stack is the original
* caller. 2 = function that called the function that called
* wfDeprecated (Added in 1.20)
*
@@ -1092,7 +1095,7 @@ function wfDeprecated( $function, $version = false, $component = false, $callerO
* Send a warning either to the debug log or in a PHP error depending on
* $wgDevelopmentWarnings
*
- * @param $msg String: message to send
+ * @param string $msg message to send
* @param $callerOffset Integer: number of items to go back in the backtrace to
* find the correct caller (1 = function calling wfWarn, ...)
* @param $level Integer: PHP error level; only used when $wgDevelopmentWarnings
@@ -1109,7 +1112,8 @@ function wfWarn( $msg, $callerOffset = 1, $level = E_USER_NOTICE ) {
* send lines to the specified port, prefixed by the specified prefix and a space.
*
* @param $text String
- * @param $file String filename
+ * @param string $file filename
+ * @throws MWException
*/
function wfErrorLog( $text, $file ) {
if ( substr( $file, 0, 4 ) == 'udp:' ) {
@@ -1212,9 +1216,18 @@ function wfLogProfilingData() {
if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
$forward .= ' anon';
}
+
+ // Command line script uses a FauxRequest object which does not have
+ // any knowledge about an URL and throw an exception instead.
+ try {
+ $requestUrl = $wgRequest->getRequestURL();
+ } catch ( MWException $e ) {
+ $requestUrl = 'n/a';
+ }
+
$log = sprintf( "%s\t%04.3f\t%s\n",
gmdate( 'YmdHis' ), $elapsed,
- urldecode( $wgRequest->getRequestURL() . $forward ) );
+ urldecode( $requestUrl . $forward ) );
wfErrorLog( $log . $profiler->getOutput(), $wgDebugLogFile );
}
@@ -1224,17 +1237,21 @@ function wfLogProfilingData() {
*
* @param $key String
* @param $count Int
+ * @return void
*/
function wfIncrStats( $key, $count = 1 ) {
global $wgStatsMethod;
$count = intval( $count );
+ if ( $count == 0 ) {
+ return;
+ }
if( $wgStatsMethod == 'udp' ) {
- global $wgUDPProfilerHost, $wgUDPProfilerPort, $wgDBname, $wgAggregateStatsID;
+ global $wgUDPProfilerHost, $wgUDPProfilerPort, $wgAggregateStatsID;
static $socket;
- $id = $wgAggregateStatsID !== false ? $wgAggregateStatsID : $wgDBname;
+ $id = $wgAggregateStatsID !== false ? $wgAggregateStatsID : wfWikiID();
if ( !$socket ) {
$socket = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
@@ -1366,9 +1383,13 @@ function wfUILang() {
}
/**
- * This is the new function for getting translated interface messages.
- * See the Message class for documentation how to use them.
- * The intention is that this function replaces all old wfMsg* functions.
+ * This is the function for getting translated interface messages.
+ *
+ * @see Message class for documentation how to use them.
+ * @see https://www.mediawiki.org/wiki/Manual:Messages_API
+ *
+ * This function replaces all old wfMsg* functions.
+ *
* @param $key \string Message key.
* Varargs: normal message parameters.
* @return Message
@@ -1404,7 +1425,7 @@ function wfMessageFallback( /*...*/ ) {
*
* @deprecated since 1.18
*
- * @param $key String: lookup key for the message, usually
+ * @param string $key lookup key for the message, usually
* defined in languages/Language.php
*
* Parameters to the message, which can be used to insert variable text into
@@ -1416,6 +1437,8 @@ function wfMessageFallback( /*...*/ ) {
* @return String
*/
function wfMsg( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
$args = func_get_args();
array_shift( $args );
return wfMsgReal( $key, $args );
@@ -1430,6 +1453,8 @@ function wfMsg( $key ) {
* @return String
*/
function wfMsgNoTrans( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
$args = func_get_args();
array_shift( $args );
return wfMsgReal( $key, $args, true, false, false );
@@ -1456,11 +1481,13 @@ function wfMsgNoTrans( $key ) {
*
* @deprecated since 1.18
*
- * @param $key String: lookup key for the message, usually
+ * @param string $key lookup key for the message, usually
* defined in languages/Language.php
* @return String
*/
function wfMsgForContent( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
global $wgForceUIMsgAsContentMsg;
$args = func_get_args();
array_shift( $args );
@@ -1482,6 +1509,8 @@ function wfMsgForContent( $key ) {
* @return String
*/
function wfMsgForContentNoTrans( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
global $wgForceUIMsgAsContentMsg;
$args = func_get_args();
array_shift( $args );
@@ -1499,7 +1528,7 @@ function wfMsgForContentNoTrans( $key ) {
*
* @deprecated since 1.18
*
- * @param $key String: key to get.
+ * @param string $key key to get.
* @param $args
* @param $useDB Boolean
* @param $forContent Mixed: Language code, or false for user lang, true for content lang.
@@ -1507,6 +1536,8 @@ function wfMsgForContentNoTrans( $key ) {
* @return String: the requested message.
*/
function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
wfProfileIn( __METHOD__ );
$message = wfMsgGetKey( $key, $useDB, $forContent, $transform );
$message = wfMsgReplaceArgs( $message, $args );
@@ -1521,12 +1552,14 @@ function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform
*
* @param $key String
* @param $useDB Bool
- * @param $langCode String: Code of the language to get the message for, or
+ * @param string $langCode Code of the language to get the message for, or
* behaves as a content language switch if it is a boolean.
* @param $transform Boolean: whether to parse magic words, etc.
* @return string
*/
function wfMsgGetKey( $key, $useDB = true, $langCode = false, $transform = true ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
wfRunHooks( 'NormalizeMessageKey', array( &$key, &$useDB, &$langCode, &$transform ) );
$cache = MessageCache::singleton();
@@ -1581,6 +1614,8 @@ function wfMsgReplaceArgs( $message, $args ) {
* @return string
*/
function wfMsgHtml( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
$args = func_get_args();
array_shift( $args );
return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key ) ), $args );
@@ -1600,6 +1635,8 @@ function wfMsgHtml( $key ) {
* @return string
*/
function wfMsgWikiHtml( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
$args = func_get_args();
array_shift( $args );
return wfMsgReplaceArgs(
@@ -1613,8 +1650,8 @@ function wfMsgWikiHtml( $key ) {
*
* @deprecated since 1.18
*
- * @param $key String: key of the message
- * @param $options Array: processing rules. Can take the following options:
+ * @param string $key key of the message
+ * @param array $options processing rules. Can take the following options:
* <i>parse</i>: parses wikitext to HTML
* <i>parseinline</i>: parses wikitext to HTML and removes the surrounding
* p's added by parser or tidy
@@ -1625,12 +1662,14 @@ function wfMsgWikiHtml( $key ) {
* <i>content</i>: fetch message for content language instead of interface
* Also can accept a single associative argument, of the form 'language' => 'xx':
* <i>language</i>: Language object or language code to fetch message for
- * (overriden by <i>content</i>).
+ * (overridden by <i>content</i>).
* Behavior for conflicting options (e.g., parse+parseinline) is undefined.
*
* @return String
*/
function wfMsgExt( $key, $options ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
$args = func_get_args();
array_shift( $args );
array_shift( $args );
@@ -1703,7 +1742,7 @@ function wfMsgExt( $key, $options ) {
/**
* Since wfMsg() and co suck, they don't return false if the message key they
* looked up didn't exist but a XHTML string, this function checks for the
- * nonexistance of messages by checking the MessageCache::get() result directly.
+ * nonexistence of messages by checking the MessageCache::get() result directly.
*
* @deprecated since 1.18. Use Message::isDisabled().
*
@@ -1711,6 +1750,8 @@ function wfMsgExt( $key, $options ) {
* @return Boolean True if the message *doesn't* exist.
*/
function wfEmptyMsg( $key ) {
+ wfDeprecated( __METHOD__, '1.21' );
+
return MessageCache::singleton()->get( $key, /*useDB*/true, /*content*/false ) === false;
}
@@ -1718,7 +1759,8 @@ function wfEmptyMsg( $key ) {
* Throw a debugging exception. This function previously once exited the process,
* but now throws an exception instead, with similar results.
*
- * @param $msg String: message shown when dying.
+ * @param string $msg message shown when dying.
+ * @throws MWException
*/
function wfDebugDieBacktrace( $msg = '' ) {
throw new MWException( $msg );
@@ -1783,13 +1825,13 @@ function wfReportTime() {
*
* With Zend Optimizer 3.2.0 loaded, this causes segfaults under somewhat
* murky circumstances, which may be triggered in part by stub objects
- * or other fancy talkin'.
+ * or other fancy talking'.
*
* Will return an empty array if Zend Optimizer is detected or if
* debug_backtrace is disabled, otherwise the output from
* debug_backtrace() (trimmed).
*
- * @param $limit int This parameter can be used to limit the number of stack frames returned
+ * @param int $limit This parameter can be used to limit the number of stack frames returned
*
* @return array of backtrace information
*/
@@ -1895,7 +1937,7 @@ function wfGetCaller( $level = 2 ) {
* Return a string consisting of callers in the stack. Useful sometimes
* for profiling specific points.
*
- * @param $limit int The maximum depth of the stack frame to return, or false for
+ * @param int $limit The maximum depth of the stack frame to return, or false for
* the entire stack.
* @return String
*/
@@ -1920,10 +1962,8 @@ function wfFormatStackFrame( $frame ) {
$frame['function'];
}
-
/* Some generic result counters, pulled out of SearchEngine */
-
/**
* @todo document
*
@@ -1941,8 +1981,8 @@ function wfShowingResults( $offset, $limit ) {
* @param $offset String
* @param $limit Integer
* @param $link String
- * @param $query String: optional URL query parameter string
- * @param $atend Bool: optional param for specified if this is the last page
+ * @param string $query optional URL query parameter string
+ * @param bool $atend optional param for specified if this is the last page
* @return String
* @deprecated in 1.19; use Language::viewPrevNext() instead
*/
@@ -1968,8 +2008,8 @@ function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
/**
* Make a list item, used by various special pages
*
- * @param $page String Page link
- * @param $details String Text between brackets
+ * @param string $page Page link
+ * @param string $details Text between brackets
* @param $oppositedm Boolean Add the direction mark opposite to your
* language, to display text properly
* @return String
@@ -2018,8 +2058,8 @@ function wfClientAcceptsGzip( $force = false ) {
* Obtain the offset and limit values from the request string;
* used in special pages
*
- * @param $deflimit Int default limit if none supplied
- * @param $optionname String Name of a user preference to check against
+ * @param int $deflimit default limit if none supplied
+ * @param string $optionname Name of a user preference to check against
* @return array
*
*/
@@ -2034,7 +2074,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
* is achieved by substituting certain characters with HTML entities.
* As required by the callers, "<nowiki>" is not used.
*
- * @param $text String: text to be escaped
+ * @param string $text text to be escaped
* @return String
*/
function wfEscapeWikiText( $text ) {
@@ -2050,7 +2090,7 @@ function wfEscapeWikiText( $text ) {
}
/**
- * Get the current unix timetstamp with microseconds. Useful for profiling
+ * Get the current unix timestamp with microseconds. Useful for profiling
* @return Float
*/
function wfTime() {
@@ -2207,7 +2247,7 @@ function wfClearOutputBuffers() {
* factors
*
* @param $accept String
- * @param $def String default
+ * @param string $def default
* @return Array
*/
function wfAcceptToPrefs( $accept, $def = '*/*' ) {
@@ -2267,8 +2307,8 @@ function mimeTypeMatch( $type, $avail ) {
* array of type to preference (preference is a float between 0.0 and 1.0).
* Wildcards in the types are acceptable.
*
- * @param $cprefs Array: client's acceptable type list
- * @param $sprefs Array: server's offered types
+ * @param array $cprefs client's acceptable type list
+ * @param array $sprefs server's offered types
* @return string
*
* @todo FIXME: Doesn't handle params like 'text/plain; charset=UTF-8'
@@ -2390,11 +2430,6 @@ define( 'TS_ORACLE', 6 );
define( 'TS_POSTGRES', 7 );
/**
- * DB2 format time
- */
-define( 'TS_DB2', 8 );
-
-/**
* ISO 8601 basic format with no timezone: 19860209T200000Z. This is used by ResourceLoader
*/
define( 'TS_ISO_8601_BASIC', 9 );
@@ -2405,7 +2440,7 @@ define( 'TS_ISO_8601_BASIC', 9 );
* @param $outputtype Mixed: A timestamp in one of the supported formats, the
* function will autodetect which format is supplied and act
* accordingly.
- * @param $ts Mixed: the timestamp to convert or 0 for the current timestamp
+ * @param $ts Mixed: optional timestamp to convert, default 0 for the current time
* @return Mixed: String / false The same date in the format specified in $outputtype or false
*/
function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
@@ -2413,7 +2448,7 @@ function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
$timestamp = new MWTimestamp( $ts );
return $timestamp->getTimestamp( $outputtype );
} catch( TimestampException $e ) {
- wfDebug("wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n");
+ wfDebug( "wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n" );
return false;
}
}
@@ -2509,9 +2544,10 @@ function wfTempDir() {
/**
* Make directory, and make all parent directories if they don't exist
*
- * @param $dir String: full path to directory to create
+ * @param string $dir full path to directory to create
* @param $mode Integer: chmod value to use, default is $wgDirectoryMode
- * @param $caller String: optional caller param for debugging.
+ * @param string $caller optional caller param for debugging.
+ * @throws MWException
* @return bool
*/
function wfMkdirParents( $dir, $mode = null, $caller = null ) {
@@ -2585,12 +2621,14 @@ function wfPercent( $nr, $acc = 2, $round = true ) {
/**
* Find out whether or not a mixed variable exists in a string
*
+ * @deprecated Just use str(i)pos
* @param $needle String
* @param $str String
* @param $insensitive Boolean
* @return Boolean
*/
function in_string( $needle, $str, $insensitive = false ) {
+ wfDeprecated( __METHOD__, '1.21' );
$func = 'strpos';
if( $insensitive ) $func = 'stripos';
@@ -2633,9 +2671,9 @@ function wfIniGetBool( $setting ) {
* Wrapper function for PHP's dl(). This doesn't work in most situations from
* PHP 5.3 onward, and is usually disabled in shared environments anyway.
*
- * @param $extension String A PHP extension. The file suffix (.so or .dll)
+ * @param string $extension A PHP extension. The file suffix (.so or .dll)
* should be omitted
- * @param $fileName String Name of the library, if not $extension.suffix
+ * @param string $fileName Name of the library, if not $extension.suffix
* @return Bool - Whether or not the extension is loaded
*/
function wfDl( $extension, $fileName = null ) {
@@ -2644,8 +2682,7 @@ function wfDl( $extension, $fileName = null ) {
}
$canDl = false;
- $sapi = php_sapi_name();
- if( $sapi == 'cli' || $sapi == 'cgi' || $sapi == 'embed' ) {
+ if( PHP_SAPI == 'cli' || PHP_SAPI == 'cgi' || PHP_SAPI == 'embed' ) {
$canDl = ( function_exists( 'dl' ) && is_callable( 'dl' )
&& wfIniGetBool( 'enable_dl' ) && !wfIniGetBool( 'safe_mode' ) );
}
@@ -2673,7 +2710,7 @@ function wfDl( $extension, $fileName = null ) {
* @param varargs
* @return String
*/
-function wfEscapeShellArg( ) {
+function wfEscapeShellArg() {
wfInitShellLocale();
$args = func_get_args();
@@ -2729,17 +2766,18 @@ function wfEscapeShellArg( ) {
/**
* Execute a shell command, with time and memory limits mirrored from the PHP
* configuration if supported.
- * @param $cmd String Command line, properly escaped for shell.
+ * @param string $cmd Command line, properly escaped for shell.
* @param &$retval null|Mixed optional, will receive the program's exit code.
* (non-zero is usually failure)
- * @param $environ Array optional environment variables which should be
+ * @param array $environ optional environment variables which should be
* added to the executed command environment.
- * @param $limits Array optional array with limits(filesize, memory, time)
+ * @param array $limits optional array with limits(filesize, memory, time, walltime)
* this overwrites the global wgShellMax* limits.
* @return string collected stdout as a string (trailing newlines stripped)
*/
function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
- global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime;
+ global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
+ $wgMaxShellWallClockTime, $wgShellCgroup;
static $disabled;
if ( is_null( $disabled ) ) {
@@ -2786,15 +2824,27 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array
$cmd = $envcmd . $cmd;
if ( php_uname( 's' ) == 'Linux' ) {
- $time = intval ( isset($limits['time']) ? $limits['time'] : $wgMaxShellTime );
- $mem = intval ( isset($limits['memory']) ? $limits['memory'] : $wgMaxShellMemory );
- $filesize = intval ( isset($limits['filesize']) ? $limits['filesize'] : $wgMaxShellFileSize );
-
- if ( $time > 0 && $mem > 0 ) {
- $script = "$IP/bin/ulimit4.sh";
- if ( is_executable( $script ) ) {
- $cmd = '/bin/bash ' . escapeshellarg( $script ) . " $time $mem $filesize " . escapeshellarg( $cmd );
- }
+ $time = intval ( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
+ if ( isset( $limits['walltime'] ) ) {
+ $wallTime = intval( $limits['walltime'] );
+ } elseif ( isset( $limits['time'] ) ) {
+ $wallTime = $time;
+ } else {
+ $wallTime = intval( $wgMaxShellWallClockTime );
+ }
+ $mem = intval ( isset( $limits['memory'] ) ? $limits['memory'] : $wgMaxShellMemory );
+ $filesize = intval ( isset( $limits['filesize'] ) ? $limits['filesize'] : $wgMaxShellFileSize );
+
+ if ( $time > 0 || $mem > 0 || $filesize > 0 || $wallTime > 0 ) {
+ $cmd = '/bin/bash ' . escapeshellarg( "$IP/includes/limit.sh" ) . ' ' .
+ escapeshellarg( $cmd ) . ' ' .
+ escapeshellarg(
+ "MW_CPU_LIMIT=$time; " .
+ 'MW_CGROUP=' . escapeshellarg( $wgShellCgroup ) . '; ' .
+ "MW_MEM_LIMIT=$mem; " .
+ "MW_FILE_SIZE_LIMIT=$filesize; " .
+ "MW_WALL_CLOCK_LIMIT=$wallTime"
+ );
}
}
wfDebug( "wfShellExec: $cmd\n" );
@@ -2840,9 +2890,9 @@ function wfShellMaintenanceCmd( $script, array $parameters = array(), array $opt
* Generate a shell-escaped command line string to run a MediaWiki cli script.
* Note that $parameters should be a flat array and an option with an argument
* should consist of two consecutive items in the array (do not use "--option value").
- * @param $script string MediaWiki cli script path
- * @param $parameters Array Arguments and options to the script
- * @param $options Array Associative array of options:
+ * @param string $script MediaWiki cli script path
+ * @param array $parameters Arguments and options to the script
+ * @param array $options Associative array of options:
* 'php': The path to the php executable
* 'wrapper': Path to a PHP wrapper to handle the maintenance script
* @return Array
@@ -2891,15 +2941,19 @@ function wfMerge( $old, $mine, $yours, &$result ) {
$mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
$yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
- fwrite( $oldtextFile, $old );
+ # NOTE: diff3 issues a warning to stderr if any of the files does not end with
+ # a newline character. To avoid this, we normalize the trailing whitespace before
+ # creating the diff.
+
+ fwrite( $oldtextFile, rtrim( $old ) . "\n" );
fclose( $oldtextFile );
- fwrite( $mytextFile, $mine );
+ fwrite( $mytextFile, rtrim( $mine ) . "\n" );
fclose( $mytextFile );
- fwrite( $yourtextFile, $yours );
+ fwrite( $yourtextFile, rtrim( $yours ) . "\n" );
fclose( $yourtextFile );
# Check for a conflict
- $cmd = $wgDiff3 . ' -a --overlap-only ' .
+ $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a --overlap-only ' .
wfEscapeShellArg( $mytextName ) . ' ' .
wfEscapeShellArg( $oldtextName ) . ' ' .
wfEscapeShellArg( $yourtextName );
@@ -2913,7 +2967,7 @@ function wfMerge( $old, $mine, $yours, &$result ) {
pclose( $handle );
# Merge differences
- $cmd = $wgDiff3 . ' -a -e --merge ' .
+ $cmd = wfEscapeShellArg( $wgDiff3 ) . ' -a -e --merge ' .
wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
$handle = popen( $cmd, 'r' );
$result = '';
@@ -2940,9 +2994,9 @@ function wfMerge( $old, $mine, $yours, &$result ) {
* Returns unified plain-text diff of two texts.
* Useful for machine processing of diffs.
*
- * @param $before String: the text before the changes.
- * @param $after String: the text after the changes.
- * @param $params String: command-line options for the diff command.
+ * @param string $before the text before the changes.
+ * @param string $after the text after the changes.
+ * @param string $params command-line options for the diff command.
* @return String: unified diff of $before and $after
*/
function wfDiff( $before, $after, $params = '-u' ) {
@@ -3022,6 +3076,7 @@ function wfDiff( $before, $after, $params = '-u' ) {
*
* @param $req_ver Mixed: the version to check, can be a string, an integer, or
* a float
+ * @throws MWException
*/
function wfUsePHP( $req_ver ) {
$php_ver = PHP_VERSION;
@@ -3043,6 +3098,7 @@ function wfUsePHP( $req_ver ) {
*
* @param $req_ver Mixed: the version to check, can be a string, an integer, or
* a float
+ * @throws MWException
*/
function wfUseMW( $req_ver ) {
global $wgVersion;
@@ -3061,7 +3117,7 @@ function wfUseMW( $req_ver ) {
* We'll consider it so always, as we don't want '\s' in our Unix paths either.
*
* @param $path String
- * @param $suffix String: to remove if present
+ * @param string $suffix to remove if present
* @return String
*/
function wfBaseName( $path, $suffix = '' ) {
@@ -3081,8 +3137,8 @@ function wfBaseName( $path, $suffix = '' ) {
* May explode on non-matching case-insensitive paths,
* funky symlinks, etc.
*
- * @param $path String: absolute destination path including target filename
- * @param $from String: Absolute source path, directory only
+ * @param string $path absolute destination path including target filename
+ * @param string $from Absolute source path, directory only
* @return String
*/
function wfRelativePath( $path, $from ) {
@@ -3140,91 +3196,105 @@ function wfDoUpdates( $commit = '' ) {
* Supports base 2 through 36; digit values 10-36 are represented
* as lowercase letters a-z. Input is case-insensitive.
*
- * @param $input String: of digits
- * @param $sourceBase Integer: 2-36
- * @param $destBase Integer: 2-36
- * @param $pad Integer: 1 or greater
- * @param $lowercase Boolean
- * @return String or false on invalid input
- */
-function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = true ) {
- $input = strval( $input );
- if( $sourceBase < 2 ||
+ * @param string $input Input number
+ * @param int $sourceBase Base of the input number
+ * @param int $destBase Desired base of the output
+ * @param int $pad Minimum number of digits in the output (pad with zeroes)
+ * @param bool $lowercase Whether to output in lowercase or uppercase
+ * @param string $engine Either "gmp", "bcmath", or "php"
+ * @return string|bool The output number as a string, or false on error
+ */
+function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = true, $engine = 'auto' ) {
+ $input = (string)$input;
+ if(
+ $sourceBase < 2 ||
$sourceBase > 36 ||
$destBase < 2 ||
$destBase > 36 ||
- $pad < 1 ||
- $sourceBase != intval( $sourceBase ) ||
- $destBase != intval( $destBase ) ||
- $pad != intval( $pad ) ||
- !is_string( $input ) ||
- $input == '' ) {
+ $sourceBase != (int) $sourceBase ||
+ $destBase != (int) $destBase ||
+ $pad != (int) $pad ||
+ !preg_match( "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i", $input )
+ ) {
return false;
}
- $digitChars = ( $lowercase ) ? '0123456789abcdefghijklmnopqrstuvwxyz' : '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- $inDigits = array();
- $outChars = '';
- // Decode and validate input string
- $input = strtolower( $input );
- for( $i = 0; $i < strlen( $input ); $i++ ) {
- $n = strpos( $digitChars, $input[$i] );
- if( $n === false || $n > $sourceBase ) {
- return false;
+ static $baseChars = array (
+ 10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f',
+ 16 => 'g', 17 => 'h', 18 => 'i', 19 => 'j', 20 => 'k', 21 => 'l',
+ 22 => 'm', 23 => 'n', 24 => 'o', 25 => 'p', 26 => 'q', 27 => 'r',
+ 28 => 's', 29 => 't', 30 => 'u', 31 => 'v', 32 => 'w', 33 => 'x',
+ 34 => 'y', 35 => 'z',
+
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5,
+ '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'a' => 10, 'b' => 11,
+ 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17,
+ 'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23,
+ 'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29,
+ 'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35
+ );
+
+ if( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) {
+ $result = gmp_strval( gmp_init( $input, $sourceBase ), $destBase );
+ } elseif( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) {
+ $decimal = '0';
+ foreach( str_split( strtolower( $input ) ) as $char ) {
+ $decimal = bcmul( $decimal, $sourceBase );
+ $decimal = bcadd( $decimal, $baseChars[$char] );
}
- $inDigits[] = $n;
- }
- // Iterate over the input, modulo-ing out an output digit
- // at a time until input is gone.
- while( count( $inDigits ) ) {
- $work = 0;
- $workDigits = array();
+ for( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) {
+ $result .= $baseChars[bcmod( $decimal, $destBase )];
+ }
- // Long division...
- foreach( $inDigits as $digit ) {
- $work *= $sourceBase;
- $work += $digit;
+ $result = strrev( $result );
+ } else {
+ $inDigits = array();
+ foreach( str_split( strtolower( $input ) ) as $char ) {
+ $inDigits[] = $baseChars[$char];
+ }
- if( $work < $destBase ) {
- // Gonna need to pull another digit.
- if( count( $workDigits ) ) {
- // Avoid zero-padding; this lets us find
- // the end of the input very easily when
- // length drops to zero.
- $workDigits[] = 0;
- }
- } else {
- // Finally! Actual division!
- $workDigits[] = intval( $work / $destBase );
+ // Iterate over the input, modulo-ing out an output digit
+ // at a time until input is gone.
+ $result = '';
+ while( $inDigits ) {
+ $work = 0;
+ $workDigits = array();
+
+ // Long division...
+ foreach( $inDigits as $digit ) {
+ $work *= $sourceBase;
+ $work += $digit;
- // Isn't it annoying that most programming languages
- // don't have a single divide-and-remainder operator,
- // even though the CPU implements it that way?
- $work = $work % $destBase;
+ if( $workDigits || $work >= $destBase ) {
+ $workDigits[] = (int) ( $work / $destBase );
+ }
+ $work %= $destBase;
}
- }
- // All that division leaves us with a remainder,
- // which is conveniently our next output digit.
- $outChars .= $digitChars[$work];
+ // All that division leaves us with a remainder,
+ // which is conveniently our next output digit.
+ $result .= $baseChars[$work];
+
+ // And we continue!
+ $inDigits = $workDigits;
+ }
- // And we continue!
- $inDigits = $workDigits;
+ $result = strrev( $result );
}
- while( strlen( $outChars ) < $pad ) {
- $outChars .= '0';
+ if( !$lowercase ) {
+ $result = strtoupper( $result );
}
- return strrev( $outChars );
+ return str_pad( $result, $pad, '0', STR_PAD_LEFT );
}
/**
* Create an object with a given name and an array of construct parameters
*
* @param $name String
- * @param $p Array: parameters
+ * @param array $p parameters
* @return object
* @deprecated since 1.18, warnings in 1.18, removal in 1.20
*/
@@ -3251,7 +3321,7 @@ function wfHttpOnlySafe() {
}
/**
- * Check if there is sufficent entropy in php's built-in session generation
+ * Check if there is sufficient entropy in php's built-in session generation
* @return bool true = there is sufficient entropy
*/
function wfCheckEntropy() {
@@ -3414,7 +3484,7 @@ function wfSplitWikiID( $wiki ) {
* belongs to. May contain a single string if the query is only
* in one group.
*
- * @param $wiki String: the wiki ID, or false for the current wiki
+ * @param string $wiki the wiki ID, or false for the current wiki
*
* Note: multiple calls to wfGetDB(DB_SLAVE) during the course of one request
* will always return the same object, unless the underlying connection or load
@@ -3432,7 +3502,7 @@ function &wfGetDB( $db, $groups = array(), $wiki = false ) {
/**
* Get a load balancer object.
*
- * @param $wiki String: wiki ID, or false for the current wiki
+ * @param string $wiki wiki ID, or false for the current wiki
* @return LoadBalancer
*/
function wfGetLB( $wiki = false ) {
@@ -3452,8 +3522,8 @@ function &wfGetLBFactory() {
* Find a file.
* Shortcut for RepoGroup::singleton()->findFile()
*
- * @param $title String or Title object
- * @param $options array Associative array of options:
+ * @param string $title or Title object
+ * @param array $options Associative array of options:
* time: requested time for an archived image, or false for the
* current version. An image object will be returned which was
* created at the specified time.
@@ -3511,7 +3581,7 @@ function wfQueriesMustScale() {
* extensions; this is a wrapper around $wgScriptExtension etc.
* except for 'index' and 'load' which use $wgScript/$wgLoadScript
*
- * @param $script String: script filename, sans extension
+ * @param string $script script filename, sans extension
* @return String
*/
function wfScript( $script = 'index' ) {
@@ -3560,16 +3630,6 @@ function wfBoolToStr( $value ) {
}
/**
- * Load an extension messages file
- *
- * @deprecated since 1.16, warnings in 1.18, remove in 1.20
- * @codeCoverageIgnore
- */
-function wfLoadExtensionMessages() {
- wfDeprecated( __FUNCTION__, '1.16' );
-}
-
-/**
* Get a platform-independent path to the null file, e.g. /dev/null
*
* @return string
@@ -3642,8 +3702,8 @@ function wfCountDown( $n ) {
* characters before hashing.
* @return string
* @codeCoverageIgnore
- * @deprecated since 1.20; Please use MWCryptRand for security purposes and wfRandomString for pesudo-random strings
- * @warning This method is NOT secure. Additionally it has many callers that use it for pesudo-random purposes.
+ * @deprecated since 1.20; Please use MWCryptRand for security purposes and wfRandomString for pseudo-random strings
+ * @warning This method is NOT secure. Additionally it has many callers that use it for pseudo-random purposes.
*/
function wfGenerateToken( $salt = '' ) {
wfDeprecated( __METHOD__, '1.20' );
@@ -3732,7 +3792,7 @@ function wfShorthandToInteger( $string = '' ) {
* Get the normalised IETF language tag
* See unit test for examples.
*
- * @param $code String: The language code.
+ * @param string $code The language code.
* @return String: The language code which complying with BCP 47 standards.
*/
function wfBCP47( $code ) {
@@ -3815,8 +3875,8 @@ function wfGetLangConverterCacheStorage() {
/**
* Call hook functions defined in $wgHooks
*
- * @param $event String: event name
- * @param $args Array: parameters passed to hook functions
+ * @param string $event event name
+ * @param array $args parameters passed to hook functions
* @return Boolean True if no handler aborted the hook
*/
function wfRunHooks( $event, $args = array() ) {
@@ -3826,9 +3886,9 @@ function wfRunHooks( $event, $args = array() ) {
/**
* Wrapper around php's unpack.
*
- * @param $format String: The format string (See php's docs)
+ * @param string $format The format string (See php's docs)
* @param $data: A binary string of binary data
- * @param $length integer or false: The minimun length of $data. This is to
+ * @param $length integer or false: The minimum length of $data. This is to
* prevent reading beyond the end of $data. false to disable the check.
*
* Also be careful when using this function to read unsigned 32 bit integer
@@ -3868,9 +3928,9 @@ function wfUnpack( $format, $data, $length=false ) {
* * Any subsequent links on the same line are considered to be exceptions,
* i.e. articles where the image may occur inline.
*
- * @param $name string the image name to check
+ * @param string $name the image name to check
* @param $contextTitle Title|bool the page on which the image occurs, if known
- * @param $blacklist string wikitext of a file blacklist
+ * @param string $blacklist wikitext of a file blacklist
* @return bool
*/
function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
diff --git a/includes/HTMLForm.php b/includes/HTMLForm.php
index 6f89d5b8..68639739 100644
--- a/includes/HTMLForm.php
+++ b/includes/HTMLForm.php
@@ -112,6 +112,7 @@ class HTMLForm extends ContextSource {
'submit' => 'HTMLSubmitField',
'hidden' => 'HTMLHiddenField',
'edittools' => 'HTMLEditTools',
+ 'checkmatrix' => 'HTMLCheckMatrix',
// HTMLTextField will output the correct type="" attribute automagically.
// There are about four zillion other HTML5 input types, like url, but
@@ -189,10 +190,10 @@ class HTMLForm extends ContextSource {
/**
* Build a new HTMLForm from an array of field attributes
- * @param $descriptor Array of Field constructs, as described above
+ * @param array $descriptor of Field constructs, as described above
* @param $context IContextSource available since 1.18, will become compulsory in 1.18.
* Obviates the need to call $form->setTitle()
- * @param $messagePrefix String a prefix to go in front of default messages
+ * @param string $messagePrefix a prefix to go in front of default messages
*/
public function __construct( $descriptor, /*IContextSource*/ $context = null, $messagePrefix = '' ) {
if ( $context instanceof IContextSource ) {
@@ -247,8 +248,9 @@ class HTMLForm extends ContextSource {
/**
* Set format in which to display the form
- * @param $format String the name of the format to use, must be one of
+ * @param string $format the name of the format to use, must be one of
* $this->availableDisplayFormats
+ * @throws MWException
* @since 1.20
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -279,7 +281,8 @@ class HTMLForm extends ContextSource {
/**
* Initialise a new Object for the field
* @param $fieldname string
- * @param $descriptor string input Descriptor, as described above
+ * @param string $descriptor input Descriptor, as described above
+ * @throws MWException
* @return HTMLFormField subclass
*/
static function loadInputFromParameters( $fieldname, $descriptor ) {
@@ -313,6 +316,7 @@ class HTMLForm extends ContextSource {
* @attention When doing method chaining, that should be the very last
* method call before displayForm().
*
+ * @throws MWException
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function prepareForm() {
@@ -374,11 +378,12 @@ class HTMLForm extends ContextSource {
}
/**
- * Validate all the fields, and call the submision callback
+ * Validate all the fields, and call the submission callback
* function if everything is kosher.
+ * @throws MWException
* @return Mixed Bool true == Successful submission, Bool false
- * == No submission attempted, anything else == Error to
- * display.
+ * == No submission attempted, anything else == Error to
+ * display.
*/
function trySubmit() {
# Check for validation
@@ -412,7 +417,7 @@ class HTMLForm extends ContextSource {
/**
* Set a callback to a function to do something with the form
* once it's been successfully validated.
- * @param $cb String function name. The function will be passed
+ * @param string $cb function name. The function will be passed
* the output from HTMLForm::filterDataForSubmit, and must
* return Bool true on success, Bool false if no submission
* was attempted, or String HTML output to display on error.
@@ -436,7 +441,7 @@ class HTMLForm extends ContextSource {
/**
* Set the introductory message, overwriting any existing message.
- * @param $msg String complete text of message to display
+ * @param string $msg complete text of message to display
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function setIntro( $msg ) {
@@ -447,7 +452,7 @@ class HTMLForm extends ContextSource {
/**
* Set the introductory message, overwriting any existing message.
* @since 1.19
- * @param $msg String complete text of message to display
+ * @param string $msg complete text of message to display
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function setPreText( $msg ) {
@@ -457,7 +462,7 @@ class HTMLForm extends ContextSource {
/**
* Add introductory text.
- * @param $msg String complete text of message to display
+ * @param string $msg complete text of message to display
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function addPreText( $msg ) {
@@ -467,8 +472,8 @@ class HTMLForm extends ContextSource {
/**
* Add header text, inside the form.
- * @param $msg String complete text of message to display
- * @param $section string The section to add the header to
+ * @param string $msg complete text of message to display
+ * @param string $section The section to add the header to
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function addHeaderText( $msg, $section = null ) {
@@ -486,7 +491,7 @@ class HTMLForm extends ContextSource {
/**
* Set header text, inside the form.
* @since 1.19
- * @param $msg String complete text of message to display
+ * @param string $msg complete text of message to display
* @param $section The section to add the header to
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -501,8 +506,8 @@ class HTMLForm extends ContextSource {
/**
* Add footer text, inside the form.
- * @param $msg String complete text of message to display
- * @param $section string The section to add the footer text to
+ * @param string $msg complete text of message to display
+ * @param string $section The section to add the footer text to
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function addFooterText( $msg, $section = null ) {
@@ -520,8 +525,8 @@ class HTMLForm extends ContextSource {
/**
* Set footer text, inside the form.
* @since 1.19
- * @param $msg String complete text of message to display
- * @param $section string The section to add the footer text to
+ * @param string $msg complete text of message to display
+ * @param string $section The section to add the footer text to
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function setFooterText( $msg, $section = null ) {
@@ -535,7 +540,7 @@ class HTMLForm extends ContextSource {
/**
* Add text to the end of the display.
- * @param $msg String complete text of message to display
+ * @param string $msg complete text of message to display
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function addPostText( $msg ) {
@@ -545,7 +550,7 @@ class HTMLForm extends ContextSource {
/**
* Set text at the end of the display.
- * @param $msg String complete text of message to display
+ * @param string $msg complete text of message to display
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function setPostText( $msg ) {
@@ -555,8 +560,8 @@ class HTMLForm extends ContextSource {
/**
* Add a hidden field to the output
- * @param $name String field name. This will be used exactly as entered
- * @param $value String field value
+ * @param string $name field name. This will be used exactly as entered
+ * @param string $value field value
* @param $attribs Array
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -568,9 +573,9 @@ class HTMLForm extends ContextSource {
/**
* Add a button to the form
- * @param $name String field name.
- * @param $value String field value
- * @param $id String DOM id for the button (default: null)
+ * @param string $name field name.
+ * @param string $value field value
+ * @param string $id DOM id for the button (default: null)
* @param $attribs Array
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -620,7 +625,7 @@ class HTMLForm extends ContextSource {
/**
* Wrap the form innards in an actual "<form>" element
- * @param $html String HTML contents to wrap.
+ * @param string $html HTML contents to wrap.
* @return String wrapped HTML.
*/
function wrapForm( $html ) {
@@ -635,9 +640,9 @@ class HTMLForm extends ContextSource {
: 'application/x-www-form-urlencoded';
# Attributes
$attribs = array(
- 'action' => $this->mAction === false ? $this->getTitle()->getFullURL() : $this->mAction,
- 'method' => $this->mMethod,
- 'class' => 'visualClear',
+ 'action' => $this->mAction === false ? $this->getTitle()->getFullURL() : $this->mAction,
+ 'method' => $this->mMethod,
+ 'class' => 'visualClear',
'enctype' => $encType,
);
if ( !empty( $this->mId ) ) {
@@ -708,8 +713,8 @@ class HTMLForm extends ContextSource {
foreach ( $this->mButtons as $button ) {
$attrs = array(
- 'type' => 'submit',
- 'name' => $button['name'],
+ 'type' => 'submit',
+ 'name' => $button['name'],
'value' => $button['value']
);
@@ -760,7 +765,7 @@ class HTMLForm extends ContextSource {
/**
* Format a stack of error messages into a single HTML string
- * @param $errors Array of message keys/values
+ * @param array $errors of message keys/values
* @return String HTML, a "<ul>" list of errors
*/
public static function formatErrors( $errors ) {
@@ -788,7 +793,7 @@ class HTMLForm extends ContextSource {
/**
* Set the text for the submit button
- * @param $t String plaintext.
+ * @param string $t plaintext.
* @return HTMLForm $this for chaining calls (since 1.20)
*/
function setSubmitText( $t ) {
@@ -799,7 +804,7 @@ class HTMLForm extends ContextSource {
/**
* Set the text for the submit button to a message
* @since 1.19
- * @param $msg String message key
+ * @param string $msg message key
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setSubmitTextMsg( $msg ) {
@@ -818,7 +823,7 @@ class HTMLForm extends ContextSource {
}
/**
- * @param $name String Submit button name
+ * @param string $name Submit button name
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setSubmitName( $name ) {
@@ -827,7 +832,7 @@ class HTMLForm extends ContextSource {
}
/**
- * @param $name String Tooltip for the submit button
+ * @param string $name Tooltip for the submit button
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setSubmitTooltip( $name ) {
@@ -847,7 +852,7 @@ class HTMLForm extends ContextSource {
}
/**
- * @param $id String DOM id for the form
+ * @param string $id DOM id for the form
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setId( $id ) {
@@ -857,7 +862,7 @@ class HTMLForm extends ContextSource {
/**
* Prompt the whole form to be wrapped in a "<fieldset>", with
* this text as its "<legend>" element.
- * @param $legend String HTML to go inside the "<legend>" element.
+ * @param string $legend HTML to go inside the "<legend>" element.
* Will be escaped
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -870,7 +875,7 @@ class HTMLForm extends ContextSource {
* Prompt the whole form to be wrapped in a "<fieldset>", with
* this message as its "<legend>" element.
* @since 1.19
- * @param $msg String message key
+ * @param string $msg message key
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setWrapperLegendMsg( $msg ) {
@@ -881,7 +886,7 @@ class HTMLForm extends ContextSource {
/**
* Set the prefix for various default messages
* @todo currently only used for the "<fieldset>" legend on forms
- * with multiple sections; should be used elsewhre?
+ * with multiple sections; should be used elsewhere?
* @param $p String
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -927,8 +932,8 @@ class HTMLForm extends ContextSource {
/**
* @todo Document
* @param $fields array[]|HTMLFormField[] array of fields (either arrays or objects)
- * @param $sectionName string ID attribute of the "<table>" tag for this section, ignored if empty
- * @param $fieldsetIDPrefix string ID prefix for the "<fieldset>" tag of each subsection, ignored if empty
+ * @param string $sectionName ID attribute of the "<table>" tag for this section, ignored if empty
+ * @param string $fieldsetIDPrefix ID prefix for the "<fieldset>" tag of each subsection, ignored if empty
* @return String
*/
public function displaySection( $fields, $sectionName = '', $fieldsetIDPrefix = '' ) {
@@ -952,7 +957,7 @@ class HTMLForm extends ContextSource {
$hasLabel = true;
}
} elseif ( is_array( $value ) ) {
- $section = $this->displaySection( $value, $key );
+ $section = $this->displaySection( $value, $key, "$fieldsetIDPrefix$key-" );
$legend = $this->getLegend( $key );
if ( isset( $this->mSectionHeaders[$key] ) ) {
$section = $this->mSectionHeaders[$key] . $section;
@@ -1025,7 +1030,7 @@ class HTMLForm extends ContextSource {
/**
* Stop a reset button being shown for this form
- * @param $suppressReset Bool set to false to re-enable the
+ * @param bool $suppressReset set to false to re-enable the
* button again
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -1095,7 +1100,7 @@ abstract class HTMLFormField {
* This function must be implemented to return the HTML to generate
* the input object itself. It should not implement the surrounding
* table cells/rows, or labels/help messages.
- * @param $value String the value to set the input to; eg a default
+ * @param string $value the value to set the input to; eg a default
* text for a text input.
* @return String valid HTML.
*/
@@ -1104,7 +1109,7 @@ abstract class HTMLFormField {
/**
* Get a translated interface message
*
- * This is a wrapper arround $this->mParent->msg() if $this->mParent is set
+ * This is a wrapper around $this->mParent->msg() if $this->mParent is set
* and wfMessage() otherwise.
*
* Parameters are the same as wfMessage().
@@ -1127,8 +1132,8 @@ abstract class HTMLFormField {
* Override this function to add specific validation checks on the
* field input. Don't forget to call parent::validate() to ensure
* that the user-defined callback mValidationCallback is still run
- * @param $value String the value the field was submitted with
- * @param $alldata Array the data collected from the form
+ * @param string $value the value the field was submitted with
+ * @param array $alldata the data collected from the form
* @return Mixed Bool true on success, or String error to display.
*/
function validate( $value, $alldata ) {
@@ -1177,7 +1182,8 @@ abstract class HTMLFormField {
/**
* Initialise the object
- * @param $params array Associative Array. See HTMLForm doc for syntax.
+ * @param array $params Associative Array. See HTMLForm doc for syntax.
+ * @throws MWException
*/
function __construct( $params ) {
$this->mParams = $params;
@@ -1245,7 +1251,7 @@ abstract class HTMLFormField {
/**
* Get the complete table row for the input, including help text,
* labels, and whatever.
- * @param $value String the value to set the input to.
+ * @param string $value the value to set the input to.
* @return String complete HTML table row.
*/
function getTableRow( $value ) {
@@ -1289,7 +1295,7 @@ abstract class HTMLFormField {
* Get the complete div for the input, including help text,
* labels, and whatever.
* @since 1.20
- * @param $value String the value to set the input to.
+ * @param string $value the value to set the input to.
* @return String complete HTML table row.
*/
public function getDiv( $value ) {
@@ -1316,13 +1322,12 @@ abstract class HTMLFormField {
* Get the complete raw fields for the input, including help text,
* labels, and whatever.
* @since 1.20
- * @param $value String the value to set the input to.
+ * @param string $value the value to set the input to.
* @return String complete HTML table row.
*/
public function getRaw( $value ) {
- list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
+ list( $errors, ) = $this->getErrorsAndErrorClass( $value );
$inputHtml = $this->getInputHTML( $value );
- $fieldType = get_class( $this );
$helptext = $this->getHelpTextHtmlRaw( $this->getHelpText() );
$cellAttributes = array();
$label = $this->getLabelHtml( $cellAttributes );
@@ -1415,7 +1420,7 @@ abstract class HTMLFormField {
/**
* Determine form errors to display and their classes
* @since 1.20
- * @param $value String the value of the input
+ * @param string $value the value of the input
* @return Array
*/
public function getErrorsAndErrorClass( $value ) {
@@ -1483,7 +1488,7 @@ abstract class HTMLFormField {
/**
* flatten an array of options to a single array, for instance,
* a set of "<options>" inside "<optgroups>".
- * @param $options array Associative Array with values either Strings
+ * @param array $options Associative Array with values either Strings
* or Arrays
* @return Array flattened input
*/
@@ -1778,6 +1783,170 @@ class HTMLCheckField extends HTMLFormField {
}
/**
+ * A checkbox matrix
+ * Operates similarly to HTMLMultiSelectField, but instead of using an array of
+ * options, uses an array of rows and an array of columns to dynamically
+ * construct a matrix of options.
+ */
+class HTMLCheckMatrix extends HTMLFormField {
+
+ function validate( $value, $alldata ) {
+ $rows = $this->mParams['rows'];
+ $columns = $this->mParams['columns'];
+
+ // Make sure user-defined validation callback is run
+ $p = parent::validate( $value, $alldata );
+ if ( $p !== true ) {
+ return $p;
+ }
+
+ // Make sure submitted value is an array
+ if ( !is_array( $value ) ) {
+ return false;
+ }
+
+ // If all options are valid, array_intersect of the valid options
+ // and the provided options will return the provided options.
+ $validOptions = array();
+ foreach ( $rows as $rowTag ) {
+ foreach ( $columns as $columnTag ) {
+ $validOptions[] = $columnTag . '-' . $rowTag;
+ }
+ }
+ $validValues = array_intersect( $value, $validOptions );
+ if ( count( $validValues ) == count( $value ) ) {
+ return true;
+ } else {
+ return $this->msg( 'htmlform-select-badoption' )->parse();
+ }
+ }
+
+ /**
+ * Build a table containing a matrix of checkbox options.
+ * The value of each option is a combination of the row tag and column tag.
+ * mParams['rows'] is an array with row labels as keys and row tags as values.
+ * mParams['columns'] is an array with column labels as keys and column tags as values.
+ * @param array $value of the options that should be checked
+ * @return String
+ */
+ function getInputHTML( $value ) {
+ $html = '';
+ $tableContents = '';
+ $attribs = array();
+ $rows = $this->mParams['rows'];
+ $columns = $this->mParams['columns'];
+
+ // If the disabled param is set, disable all the options
+ if ( !empty( $this->mParams['disabled'] ) ) {
+ $attribs['disabled'] = 'disabled';
+ }
+
+ // Build the column headers
+ $headerContents = Html::rawElement( 'td', array(), '&#160;' );
+ foreach ( $columns as $columnLabel => $columnTag ) {
+ $headerContents .= Html::rawElement( 'td', array(), $columnLabel );
+ }
+ $tableContents .= Html::rawElement( 'tr', array(), "\n$headerContents\n" );
+
+ // Build the options matrix
+ foreach ( $rows as $rowLabel => $rowTag ) {
+ $rowContents = Html::rawElement( 'td', array(), $rowLabel );
+ foreach ( $columns as $columnTag ) {
+ // Knock out any options that are not wanted
+ if ( isset( $this->mParams['remove-options'] )
+ && in_array( "$columnTag-$rowTag", $this->mParams['remove-options'] ) )
+ {
+ $rowContents .= Html::rawElement( 'td', array(), '&#160;' );
+ } else {
+ // Construct the checkbox
+ $thisAttribs = array(
+ 'id' => "{$this->mID}-$columnTag-$rowTag",
+ 'value' => $columnTag . '-' . $rowTag
+ );
+ $checkbox = Xml::check(
+ $this->mName . '[]',
+ in_array( $columnTag . '-' . $rowTag, (array)$value, true ),
+ $attribs + $thisAttribs );
+ $rowContents .= Html::rawElement( 'td', array(), $checkbox );
+ }
+ }
+ $tableContents .= Html::rawElement( 'tr', array(), "\n$rowContents\n" );
+ }
+
+ // Put it all in a table
+ $html .= Html::rawElement( 'table', array( 'class' => 'mw-htmlform-matrix' ),
+ Html::rawElement( 'tbody', array(), "\n$tableContents\n" ) ) . "\n";
+
+ return $html;
+ }
+
+ /**
+ * Get the complete table row for the input, including help text,
+ * labels, and whatever.
+ * We override this function since the label should always be on a separate
+ * line above the options in the case of a checkbox matrix, i.e. it's always
+ * a "vertical-label".
+ * @param string $value the value to set the input to
+ * @return String complete HTML table row
+ */
+ function getTableRow( $value ) {
+ list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
+ $inputHtml = $this->getInputHTML( $value );
+ $fieldType = get_class( $this );
+ $helptext = $this->getHelpTextHtmlTable( $this->getHelpText() );
+ $cellAttributes = array( 'colspan' => 2 );
+
+ $label = $this->getLabelHtml( $cellAttributes );
+
+ $field = Html::rawElement(
+ 'td',
+ array( 'class' => 'mw-input' ) + $cellAttributes,
+ $inputHtml . "\n$errors"
+ );
+
+ $html = Html::rawElement( 'tr',
+ array( 'class' => 'mw-htmlform-vertical-label' ), $label );
+ $html .= Html::rawElement( 'tr',
+ array( 'class' => "mw-htmlform-field-$fieldType {$this->mClass} $errorClass" ),
+ $field );
+
+ return $html . $helptext;
+ }
+
+ /**
+ * @param $request WebRequest
+ * @return Array
+ */
+ function loadDataFromRequest( $request ) {
+ if ( $this->mParent->getMethod() == 'post' ) {
+ if ( $request->wasPosted() ) {
+ // Checkboxes are not added to the request arrays if they're not checked,
+ // so it's perfectly possible for there not to be an entry at all
+ return $request->getArray( $this->mName, array() );
+ } else {
+ // That's ok, the user has not yet submitted the form, so show the defaults
+ return $this->getDefault();
+ }
+ } else {
+ // This is the impossible case: if we look at $_GET and see no data for our
+ // field, is it because the user has not yet submitted the form, or that they
+ // have submitted it with all the options unchecked. We will have to assume the
+ // latter, which basically means that you can't specify 'positive' defaults
+ // for GET forms.
+ return $request->getArray( $this->mName, array() );
+ }
+ }
+
+ function getDefault() {
+ if ( isset( $this->mDefault ) ) {
+ return $this->mDefault;
+ } else {
+ return array();
+ }
+ }
+}
+
+/**
* A select dropdown field. Basically a wrapper for Xmlselect class
*/
class HTMLSelectField extends HTMLFormField {
@@ -2053,8 +2222,8 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
/**
* Build a drop-down box from a textual list.
- * @param $string String message text
- * @param $otherName String name of "other reason" option
+ * @param string $string message text
+ * @param string $otherName name of "other reason" option
* @return Array
* TODO: this is copied from Xml::listDropDown(), deprecate/avoid duplication?
*/
@@ -2188,7 +2357,6 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
*/
class HTMLRadioField extends HTMLFormField {
-
function validate( $value, $alldata ) {
$p = parent::validate( $value, $alldata );
diff --git a/includes/HistoryBlob.php b/includes/HistoryBlob.php
index bb8ec5e3..1af733a2 100644
--- a/includes/HistoryBlob.php
+++ b/includes/HistoryBlob.php
@@ -19,10 +19,10 @@
*
* @file
*/
-
+
/**
- * Base class for general text storage via the "object" flag in old_flags, or
- * two-part external storage URLs. Used for represent efficient concatenated
+ * Base class for general text storage via the "object" flag in old_flags, or
+ * two-part external storage URLs. Used for represent efficient concatenated
* storage, and migration-related pointer objects.
*/
interface HistoryBlob
@@ -178,12 +178,11 @@ class ConcatenatedGzipHistoryBlob implements HistoryBlob
* @return bool
*/
public function isHappy() {
- return $this->mSize < $this->mMaxSize
+ return $this->mSize < $this->mMaxSize
&& count( $this->mItems ) < $this->mMaxCount;
}
}
-
/**
* Pointer object for an item within a CGZ blob stored in the text table.
*/
@@ -199,7 +198,7 @@ class HistoryBlobStub {
var $mOldId, $mHash, $mRef;
/**
- * @param $hash string the content hash of the text
+ * @param string $hash the content hash of the text
* @param $oldid Integer the old_id for the CGZ object
*/
function __construct( $hash = '', $oldid = 0 ) {
@@ -232,8 +231,6 @@ class HistoryBlobStub {
* @return string
*/
function getText() {
- $fname = 'HistoryBlobStub::getText';
-
if( isset( self::$blobCache[$this->mOldId] ) ) {
$obj = self::$blobCache[$this->mOldId];
} else {
@@ -244,13 +241,12 @@ class HistoryBlobStub {
}
$flags = explode( ',', $row->old_flags );
if( in_array( 'external', $flags ) ) {
- $url=$row->old_text;
+ $url = $row->old_text;
$parts = explode( '://', $url, 2 );
if ( !isset( $parts[1] ) || $parts[1] == '' ) {
- wfProfileOut( $fname );
return false;
}
- $row->old_text = ExternalStore::fetchFromUrl($url);
+ $row->old_text = ExternalStore::fetchFromUrl( $url );
}
if( !in_array( 'object', $flags ) ) {
@@ -288,7 +284,6 @@ class HistoryBlobStub {
}
}
-
/**
* To speed up conversion from 1.4 to 1.5 schema, text rows can refer to the
* leftover cur table as the backend. This avoids expensively copying hundreds
@@ -341,12 +336,12 @@ class DiffHistoryBlob implements HistoryBlob {
/** Total uncompressed size */
var $mSize = 0;
- /**
- * Array of diffs. If a diff D from A to B is notated D = B - A, and Z is
+ /**
+ * Array of diffs. If a diff D from A to B is notated D = B - A, and Z is
* an empty string:
*
* { item[map[i]] - item[map[i-1]] where i > 0
- * diff[i] = {
+ * diff[i] = {
* { item[map[i]] - Z where i = 0
*/
var $mDiffs;
@@ -379,7 +374,7 @@ class DiffHistoryBlob implements HistoryBlob {
* The maximum number of text items before the object becomes sad
*/
var $mMaxCount = 100;
-
+
/** Constants from xdiff.h */
const XDL_BDOP_INS = 1;
const XDL_BDOP_CPY = 2;
@@ -398,7 +393,7 @@ class DiffHistoryBlob implements HistoryBlob {
*/
function addItem( $text ) {
if ( $this->mFrozen ) {
- throw new MWException( __METHOD__.": Cannot add more items after sleep/wakeup" );
+ throw new MWException( __METHOD__ . ": Cannot add more items after sleep/wakeup" );
}
$this->mItems[] = $text;
@@ -433,7 +428,7 @@ class DiffHistoryBlob implements HistoryBlob {
* @throws MWException
*/
function compress() {
- if ( !function_exists( 'xdiff_string_rabdiff' ) ){
+ if ( !function_exists( 'xdiff_string_rabdiff' ) ) {
throw new MWException( "Need xdiff 1.5+ support to write DiffHistoryBlob\n" );
}
if ( isset( $this->mDiffs ) ) {
@@ -534,18 +529,18 @@ class DiffHistoryBlob implements HistoryBlob {
# Pure PHP implementation
$header = unpack( 'Vofp/Vcsize', substr( $diff, 0, 8 ) );
-
+
# Check the checksum if hash/mhash is available
$ofp = $this->xdiffAdler32( $base );
if ( $ofp !== false && $ofp !== substr( $diff, 0, 4 ) ) {
- wfDebug( __METHOD__. ": incorrect base checksum\n" );
+ wfDebug( __METHOD__ . ": incorrect base checksum\n" );
return false;
}
if ( $header['csize'] != strlen( $base ) ) {
- wfDebug( __METHOD__. ": incorrect base length\n" );
+ wfDebug( __METHOD__ . ": incorrect base length\n" );
return false;
}
-
+
$p = 8;
$out = '';
while ( $p < strlen( $diff ) ) {
@@ -571,7 +566,7 @@ class DiffHistoryBlob implements HistoryBlob {
$out .= substr( $base, $x['off'], $x['csize'] );
break;
default:
- wfDebug( __METHOD__.": invalid op\n" );
+ wfDebug( __METHOD__ . ": invalid op\n" );
return false;
}
}
@@ -579,7 +574,7 @@ class DiffHistoryBlob implements HistoryBlob {
}
/**
- * Compute a binary "Adler-32" checksum as defined by LibXDiff, i.e. with
+ * Compute a binary "Adler-32" checksum as defined by LibXDiff, i.e. with
* the bytes backwards and initialised with 0 instead of 1. See bug 34428.
*
* Returns false if no hashing library is available
@@ -589,8 +584,8 @@ class DiffHistoryBlob implements HistoryBlob {
if ( $init === null ) {
$init = str_repeat( "\xf0", 205 ) . "\xee" . str_repeat( "\xf0", 67 ) . "\x02";
}
- // The real Adler-32 checksum of $init is zero, so it initialises the
- // state to zero, as it is at the start of LibXDiff's checksum
+ // The real Adler-32 checksum of $init is zero, so it initialises the
+ // state to zero, as it is at the start of LibXDiff's checksum
// algorithm. Appending the subject string then simulates LibXDiff.
if ( function_exists( 'hash' ) ) {
$hash = hash( 'adler32', $init . $s, true );
@@ -664,7 +659,7 @@ class DiffHistoryBlob implements HistoryBlob {
if ( isset( $info['base'] ) ) {
// Old format
$this->mDiffMap = range( 0, count( $this->mDiffs ) - 1 );
- array_unshift( $this->mDiffs,
+ array_unshift( $this->mDiffs,
pack( 'VVCV', 0, 0, self::XDL_BDOP_INSB, strlen( $info['base'] ) ) .
$info['base'] );
} else {
@@ -687,7 +682,7 @@ class DiffHistoryBlob implements HistoryBlob {
* @return bool
*/
function isHappy() {
- return $this->mSize < $this->mMaxSize
+ return $this->mSize < $this->mMaxSize
&& count( $this->mItems ) < $this->mMaxCount;
}
diff --git a/includes/Hooks.php b/includes/Hooks.php
index bc39f2fc..8cc7acea 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -23,23 +23,47 @@
* @file
*/
+/**
+ * @since 1.18
+ */
class MWHookException extends MWException {}
/**
* Hooks class.
*
* Used to supersede $wgHooks, because globals are EVIL.
+ *
+ * @since 1.18
*/
class Hooks {
protected static $handlers = array();
/**
+ * Clears hooks registered via Hooks::register(). Does not touch $wgHooks.
+ * This is intended for use while testing and will fail if MW_PHPUNIT_TEST is not defined.
+ *
+ * @since 1.21
+ *
+ * @param string $name the name of the hook to clear.
+ *
+ * @throws MWException if not in testing mode.
+ */
+ public static function clear( $name ) {
+ if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+ throw new MWException( 'can not reset hooks in operation.' );
+ }
+
+ unset( self::$handlers[$name] );
+ }
+
+ /**
* Attach an event handler to a given hook
*
- * @param $name Mixed: name of hook
+ * @since 1.18
+ *
+ * @param string $name name of hook
* @param $callback Mixed: callback function to attach
- * @return void
*/
public static function register( $name, $callback ) {
if( !isset( self::$handlers[$name] ) ) {
@@ -51,69 +75,84 @@ class Hooks {
/**
* Returns true if a hook has a function registered to it.
+ * The function may have been registered either via Hooks::register or in $wgHooks.
+ *
+ * @since 1.18
*
- * @param $name Mixed: name of hook
- * @return Boolean: true if a hook has a function registered to it
+ * @param string $name name of hook
+ * @return Boolean: true if the hook has a function registered to it
*/
public static function isRegistered( $name ) {
- if( !isset( self::$handlers[$name] ) ) {
- self::$handlers[$name] = array();
- }
+ global $wgHooks;
- return ( count( self::$handlers[$name] ) != 0 );
+ return !empty( $wgHooks[$name] ) || !empty( self::$handlers[$name] );
}
/**
* Returns an array of all the event functions attached to a hook
+ * This combines functions registered via Hooks::register and with $wgHooks.
+ * @since 1.18
+ *
+ * @throws MWException
+ * @throws FatalError
+ * @param string $name name of the hook
*
- * @param $name Mixed: name of the hook
* @return array
*/
public static function getHandlers( $name ) {
- if( !isset( self::$handlers[$name] ) ) {
+ global $wgHooks;
+
+ // Return quickly in the most common case
+ if ( empty( self::$handlers[$name] ) && empty( $wgHooks[$name] ) ) {
return array();
}
- return self::$handlers[$name];
+ if ( !is_array( self::$handlers ) ) {
+ throw new MWException( "Local hooks array is not an array!\n" );
+ }
+
+ if ( !is_array( $wgHooks ) ) {
+ throw new MWException( "Global hooks array is not an array!\n" );
+ }
+
+ if ( empty( Hooks::$handlers[$name] ) ) {
+ $hooks = $wgHooks[$name];
+ } elseif ( empty( $wgHooks[$name] ) ) {
+ $hooks = Hooks::$handlers[$name];
+ } else {
+ // so they are both not empty...
+ $hooks = array_merge( Hooks::$handlers[$name], $wgHooks[$name] );
+ }
+
+ if ( !is_array( $hooks ) ) {
+ throw new MWException( "Hooks array for event '$name' is not an array!\n" );
+ }
+
+ return $hooks;
}
/**
* Call hook functions defined in Hooks::register
*
- * Because programmers assign to $wgHooks, we need to be very
- * careful about its contents. So, there's a lot more error-checking
- * in here than would normally be necessary.
+ * @param string $event event name
+ * @param $args Array: parameters passed to hook functions
*
- * @param $event String: event name
- * @param $args Array: parameters passed to hook functions
+ * @throws MWException
+ * @throws FatalError
* @return Boolean True if no handler aborted the hook
*/
public static function run( $event, $args = array() ) {
global $wgHooks;
// Return quickly in the most common case
- if ( !isset( self::$handlers[$event] ) && !isset( $wgHooks[$event] ) ) {
+ if ( empty( self::$handlers[$event] ) && empty( $wgHooks[$event] ) ) {
return true;
}
- if ( !is_array( self::$handlers ) ) {
- throw new MWException( "Local hooks array is not an array!\n" );
- }
-
- if ( !is_array( $wgHooks ) ) {
- throw new MWException( "Global hooks array is not an array!\n" );
- }
+ wfProfileIn( 'hook: ' . $event );
+ $hooks = self::getHandlers( $event );
- $new_handlers = (array) self::$handlers;
- $old_handlers = (array) $wgHooks;
-
- $hook_array = array_merge( $new_handlers, $old_handlers );
-
- if ( !is_array( $hook_array[$event] ) ) {
- throw new MWException( "Hooks array for event '$event' is not an array!\n" );
- }
-
- foreach ( $hook_array[$event] as $index => $hook ) {
+ foreach ( $hooks as $hook ) {
$object = null;
$method = null;
$func = null;
@@ -131,7 +170,7 @@ class Hooks {
if ( count( $hook ) < 1 ) {
throw new MWException( 'Empty array in hooks for ' . $event . "\n" );
} elseif ( is_object( $hook[0] ) ) {
- $object = $hook_array[$event][$index][0];
+ $object = $hook[0];
if ( $object instanceof Closure ) {
$closure = true;
if ( count( $hook ) > 1 ) {
@@ -161,7 +200,7 @@ class Hooks {
} elseif ( is_string( $hook ) ) { # functions look like strings, too
$func = $hook;
} elseif ( is_object( $hook ) ) {
- $object = $hook_array[$event][$index];
+ $object = $hook;
if ( $object instanceof Closure ) {
$closure = true;
} else {
@@ -249,18 +288,23 @@ class Hooks {
);
}
} elseif ( !$retval ) {
+ wfProfileOut( 'hook: ' . $event );
return false;
}
}
+ wfProfileOut( 'hook: ' . $event );
return true;
}
/**
* This REALLY should be protected... but it's public for compatibility
*
- * @param $errno int Unused
- * @param $errstr String: error message
+ * @since 1.18
+ *
+ * @param int $errno Unused
+ * @param string $errstr error message
+ * @throws MWHookException
* @return Boolean: false
*/
public static function hookErrorHandler( $errno, $errstr ) {
diff --git a/includes/Html.php b/includes/Html.php
index b33d6fbb..af4b4bbf 100644
--- a/includes/Html.php
+++ b/includes/Html.php
@@ -48,7 +48,7 @@
* @since 1.16
*/
class Html {
- # List of void elements from HTML5, section 8.1.2 as of 2011-08-12
+ // List of void elements from HTML5, section 8.1.2 as of 2011-08-12
private static $voidElements = array(
'area',
'base',
@@ -68,8 +68,8 @@ class Html {
'wbr',
);
- # Boolean attributes, which may have the value omitted entirely. Manually
- # collected from the HTML5 spec as of 2011-08-12.
+ // Boolean attributes, which may have the value omitted entirely. Manually
+ // collected from the HTML5 spec as of 2011-08-12.
private static $boolAttribs = array(
'async',
'autofocus',
@@ -97,7 +97,7 @@ class Html {
'selected',
'truespeed',
'typemustmatch',
- # HTML5 Microdata
+ // HTML5 Microdata
'itemscope',
);
@@ -126,11 +126,11 @@ class Html {
* content model. If $wgWellFormedXml is false, then a few bytes will be
* shaved off the HTML output as well.
*
- * @param $element string The element's name, e.g., 'a'
- * @param $attribs array Associative array of attributes, e.g., array(
+ * @param string $element The element's name, e.g., 'a'
+ * @param array $attribs Associative array of attributes, e.g., array(
* 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
* further documentation.
- * @param $contents string The raw HTML contents of the element: *not*
+ * @param string $contents The raw HTML contents of the element: *not*
* escaped!
* @return string Raw HTML
*/
@@ -139,7 +139,7 @@ class Html {
$start = self::openElement( $element, $attribs );
if ( in_array( $element, self::$voidElements ) ) {
if ( $wgWellFormedXml ) {
- # Silly XML.
+ // Silly XML.
return substr( $start, 0, -1 ) . ' />';
}
return $start;
@@ -160,8 +160,8 @@ class Html {
*/