From 4ac9fa081a7c045f6a9f1cfc529d82423f485b2e Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Sun, 8 Dec 2013 09:55:49 +0100 Subject: Update to MediaWiki 1.22.0 --- includes/Action.php | 57 +- includes/AjaxDispatcher.php | 10 +- includes/AjaxResponse.php | 2 +- includes/ArrayUtils.php | 2 +- includes/Article.php | 147 +- includes/AuthPlugin.php | 13 + includes/AutoLoader.php | 147 +- includes/Autopromote.php | 5 +- includes/Block.php | 308 +- includes/CallableUpdate.php | 30 + includes/Category.php | 3 +- includes/CategoryPage.php | 8 +- includes/CategoryViewer.php | 60 +- includes/Cdb.php | 4 +- includes/Cdb_PHP.php | 16 +- includes/ChangeTags.php | 75 +- includes/ChangesFeed.php | 37 +- includes/ChangesList.php | 1304 ------- includes/Collation.php | 22 +- includes/ConfEditor.php | 55 +- includes/Cookie.php | 7 +- includes/CryptRand.php | 497 --- includes/DataUpdate.php | 4 +- includes/DefaultSettings.php | 1309 ++++--- includes/DeferredUpdates.php | 12 +- includes/Defines.php | 11 +- includes/EditPage.php | 290 +- includes/Exception.php | 275 +- includes/Export.php | 33 +- includes/ExternalEdit.php | 132 - includes/ExternalUser.php | 309 -- includes/Fallback.php | 28 +- includes/Feed.php | 26 +- includes/FeedUtils.php | 27 +- includes/FileDeleteForm.php | 36 +- includes/ForkController.php | 4 +- includes/FormOptions.php | 163 +- includes/GitInfo.php | 39 +- includes/GlobalFunctions.php | 675 ++-- includes/HTMLForm.php | 541 ++- includes/HashRing.php | 142 + includes/HistoryBlob.php | 35 +- includes/Hooks.php | 282 +- includes/Html.php | 179 +- includes/HtmlFormatter.php | 356 ++ includes/HttpFunctions.php | 118 +- includes/IP.php | 32 +- includes/ImageGallery.php | 416 --- includes/ImagePage.php | 49 +- includes/ImageQueryPage.php | 25 +- includes/Import.php | 135 +- includes/Init.php | 150 +- includes/Licenses.php | 2 +- includes/LinkFilter.php | 4 +- includes/Linker.php | 103 +- includes/LinksUpdate.php | 154 +- includes/MWCryptRand.php | 497 +++ includes/MWFunction.php | 34 +- includes/MagicWord.php | 23 +- includes/MappedIterator.php | 88 +- includes/Message.php | 212 +- includes/Metadata.php | 28 +- includes/MimeMagic.php | 88 +- includes/Namespace.php | 6 +- includes/OutputHandler.php | 80 +- includes/OutputPage.php | 476 ++- includes/PHPVersionError.php | 12 +- includes/PageQueryPage.php | 5 +- includes/Pager.php | 140 +- includes/PathRouter.php | 10 +- includes/PoolCounter.php | 221 +- includes/Preferences.php | 541 +-- includes/PrefixSearch.php | 40 +- includes/ProtectionForm.php | 110 +- includes/ProxyTools.php | 40 - includes/QueryPage.php | 92 +- includes/RecentChange.php | 840 ----- includes/Revision.php | 265 +- includes/RevisionList.php | 5 +- includes/Sanitizer.php | 361 +- includes/ScopedCallback.php | 41 +- includes/SeleniumWebSettings.php | 221 -- includes/Setup.php | 153 +- includes/SiteConfiguration.php | 58 +- includes/SiteStats.php | 126 +- includes/Skin.php | 202 +- includes/SkinLegacy.php | 882 ----- includes/SkinTemplate.php | 346 +- includes/SpecialPage.php | 160 +- includes/SpecialPageFactory.php | 15 +- includes/SqlDataUpdate.php | 2 +- includes/StatCounter.php | 150 + includes/Status.php | 91 +- includes/StreamFile.php | 1 + includes/StringUtils.php | 135 +- includes/StubObject.php | 25 +- includes/Timestamp.php | 267 +- includes/Title.php | 528 +-- includes/UIDGenerator.php | 35 +- includes/User.php | 1151 +++--- includes/UserArray.php | 2 +- includes/UserMailer.php | 53 +- includes/UserRightsProxy.php | 10 +- includes/WatchedItem.php | 65 +- includes/WebRequest.php | 187 +- includes/WebResponse.php | 121 +- includes/WebStart.php | 52 +- includes/Wiki.php | 145 +- includes/WikiError.php | 2 +- includes/WikiFilePage.php | 4 + includes/WikiMap.php | 20 +- includes/WikiPage.php | 632 ++-- includes/Xml.php | 221 +- includes/XmlTypeCheck.php | 86 +- includes/ZhClient.php | 6 +- includes/ZipDirectoryReader.php | 2 +- includes/actions/CreditsAction.php | 15 +- includes/actions/EditAction.php | 14 +- includes/actions/HistoryAction.php | 51 +- includes/actions/InfoAction.php | 69 +- includes/actions/PurgeAction.php | 4 +- includes/actions/RawAction.php | 29 +- includes/actions/WatchAction.php | 62 +- includes/api/ApiBase.php | 119 +- includes/api/ApiBlock.php | 2 +- includes/api/ApiComparePages.php | 8 +- includes/api/ApiCreateAccount.php | 52 +- includes/api/ApiDelete.php | 3 +- includes/api/ApiEditPage.php | 59 +- includes/api/ApiExpandTemplates.php | 4 +- includes/api/ApiFeedContributions.php | 15 +- includes/api/ApiFeedWatchlist.php | 90 +- includes/api/ApiFormatBase.php | 8 +- includes/api/ApiFormatJson.php | 24 +- includes/api/ApiFormatWddx.php | 75 +- includes/api/ApiFormatXml.php | 137 +- includes/api/ApiImageRotate.php | 32 +- includes/api/ApiImport.php | 6 +- includes/api/ApiMain.php | 36 +- includes/api/ApiMove.php | 4 +- includes/api/ApiOpenSearch.php | 21 +- includes/api/ApiOptions.php | 8 +- includes/api/ApiPageSet.php | 18 +- includes/api/ApiParamInfo.php | 6 +- includes/api/ApiParse.php | 157 +- includes/api/ApiPatrol.php | 46 +- includes/api/ApiProtect.php | 3 +- includes/api/ApiPurge.php | 29 +- includes/api/ApiQuery.php | 10 +- includes/api/ApiQueryAllCategories.php | 4 +- includes/api/ApiQueryAllImages.php | 4 +- includes/api/ApiQueryAllLinks.php | 116 +- includes/api/ApiQueryAllMessages.php | 2 +- includes/api/ApiQueryAllPages.php | 7 +- includes/api/ApiQueryAllUsers.php | 4 +- includes/api/ApiQueryBacklinks.php | 15 +- includes/api/ApiQueryBase.php | 4 +- includes/api/ApiQueryBlocks.php | 61 +- includes/api/ApiQueryCategories.php | 5 +- includes/api/ApiQueryCategoryMembers.php | 6 +- includes/api/ApiQueryDeletedrevs.php | 6 +- includes/api/ApiQueryDuplicateFiles.php | 23 +- includes/api/ApiQueryExtLinksUsage.php | 6 +- includes/api/ApiQueryExternalLinks.php | 8 +- includes/api/ApiQueryFileRepoInfo.php | 115 + includes/api/ApiQueryFilearchive.php | 8 +- includes/api/ApiQueryIWBacklinks.php | 4 + includes/api/ApiQueryIWLinks.php | 13 +- includes/api/ApiQueryImageInfo.php | 80 +- includes/api/ApiQueryInfo.php | 20 +- includes/api/ApiQueryLangBacklinks.php | 9 +- includes/api/ApiQueryLangLinks.php | 17 +- includes/api/ApiQueryLogEvents.php | 24 +- includes/api/ApiQueryORM.php | 4 +- includes/api/ApiQueryPagesWithProp.php | 2 +- includes/api/ApiQueryProtectedTitles.php | 2 +- includes/api/ApiQueryQueryPage.php | 19 +- includes/api/ApiQueryRandom.php | 4 + includes/api/ApiQueryRecentChanges.php | 43 +- includes/api/ApiQueryRevisions.php | 29 +- includes/api/ApiQuerySearch.php | 39 +- includes/api/ApiQuerySiteinfo.php | 62 +- includes/api/ApiQueryTags.php | 7 +- includes/api/ApiQueryUserContributions.php | 21 +- includes/api/ApiQueryUserInfo.php | 20 +- includes/api/ApiQueryUsers.php | 6 +- includes/api/ApiQueryWatchlist.php | 95 +- includes/api/ApiQueryWatchlistRaw.php | 4 + includes/api/ApiRsd.php | 2 +- includes/api/ApiSetNotificationTimestamp.php | 7 +- includes/api/ApiUpload.php | 84 +- includes/api/ApiUserrights.php | 7 +- includes/api/ApiWatch.php | 11 +- includes/cache/BacklinkCache.php | 134 +- includes/cache/CacheDependency.php | 2 +- includes/cache/FileCacheBase.php | 6 +- includes/cache/GenderCache.php | 14 +- includes/cache/HTMLCacheUpdate.php | 11 +- includes/cache/HTMLFileCache.php | 4 +- includes/cache/LinkBatch.php | 4 +- includes/cache/LinkCache.php | 68 +- includes/cache/LocalisationCache.php | 96 +- includes/cache/MessageCache.php | 729 ++-- includes/cache/ResourceFileCache.php | 2 +- includes/cache/SquidUpdate.php | 197 +- includes/cache/UserCache.php | 13 + includes/changes/ChangesList.php | 552 +++ includes/changes/EnhancedChangesList.php | 662 ++++ includes/changes/OldChangesList.php | 130 + includes/changes/RCCacheEntry.php | 35 + includes/changes/RecentChange.php | 846 +++++ includes/clientpool/RedisConnectionPool.php | 90 +- includes/content/Content.php | 14 +- includes/content/ContentHandler.php | 19 +- includes/content/CssContent.php | 2 +- includes/content/JavaScriptContent.php | 2 +- includes/content/TextContent.php | 2 +- includes/content/WikitextContent.php | 3 +- includes/content/WikitextContentHandler.php | 19 +- includes/context/ContextSource.php | 2 +- includes/context/DerivativeContext.php | 25 +- includes/context/IContextSource.php | 2 +- includes/context/RequestContext.php | 19 +- includes/db/ChronologyProtector.php | 106 + includes/db/CloneDatabase.php | 18 +- includes/db/Database.php | 517 ++- includes/db/DatabaseError.php | 202 +- includes/db/DatabaseMssql.php | 190 +- includes/db/DatabaseMysql.php | 933 +---- includes/db/DatabaseMysqlBase.php | 1154 ++++++ includes/db/DatabaseMysqli.php | 194 + includes/db/DatabaseOracle.php | 92 +- includes/db/DatabasePostgres.php | 98 +- includes/db/DatabaseSqlite.php | 49 +- includes/db/DatabaseUtility.php | 3 +- includes/db/IORMRow.php | 24 +- includes/db/LBFactory.php | 94 +- includes/db/LBFactory_Multi.php | 6 +- includes/db/LoadBalancer.php | 104 +- includes/db/LoadMonitor.php | 27 +- includes/db/ORMRow.php | 182 +- includes/db/ORMTable.php | 211 +- includes/debug/Debug.php | 74 +- includes/diff/DairikiDiff.php | 40 +- includes/diff/DifferenceEngine.php | 205 +- includes/extauth/Hardcoded.php | 84 - includes/extauth/MediaWiki.php | 168 - includes/extauth/vB.php | 146 - includes/externalstore/ExternalStore.php | 57 +- includes/externalstore/ExternalStoreDB.php | 142 +- includes/externalstore/ExternalStoreMedium.php | 19 + includes/externalstore/ExternalStoreMwstore.php | 23 + includes/filebackend/FSFile.php | 29 +- includes/filebackend/FSFileBackend.php | 117 +- includes/filebackend/FileBackend.php | 143 +- includes/filebackend/FileBackendGroup.php | 28 +- includes/filebackend/FileBackendMultiWrite.php | 179 +- includes/filebackend/FileBackendStore.php | 576 +-- includes/filebackend/FileOp.php | 193 +- includes/filebackend/FileOpBatch.php | 6 +- includes/filebackend/README | 2 +- includes/filebackend/SwiftFileBackend.php | 262 +- includes/filebackend/TempFSFile.php | 6 +- includes/filebackend/filejournal/DBFileJournal.php | 10 +- includes/filebackend/lockmanager/DBLockManager.php | 37 +- includes/filebackend/lockmanager/LockManager.php | 125 +- .../filebackend/lockmanager/LockManagerGroup.php | 4 +- .../filebackend/lockmanager/MemcLockManager.php | 41 +- .../filebackend/lockmanager/QuorumLockManager.php | 140 +- .../filebackend/lockmanager/RedisLockManager.php | 288 ++ includes/filebackend/lockmanager/ScopedLock.php | 44 +- includes/filerepo/FSRepo.php | 14 +- includes/filerepo/FileRepo.php | 108 +- includes/filerepo/ForeignAPIRepo.php | 226 +- includes/filerepo/ForeignDBRepo.php | 5 +- includes/filerepo/LocalRepo.php | 42 +- includes/filerepo/RepoGroup.php | 12 +- includes/filerepo/file/ArchivedFile.php | 23 +- includes/filerepo/file/File.php | 37 +- includes/filerepo/file/ForeignAPIFile.php | 49 +- includes/filerepo/file/ForeignDBFile.php | 5 +- includes/filerepo/file/LocalFile.php | 234 +- includes/filerepo/file/OldLocalFile.php | 3 +- includes/gallery/ImageGalleryBase.php | 331 ++ includes/gallery/NolinesImageGallery.php | 38 + includes/gallery/PackedImageGallery.php | 105 + includes/gallery/PackedOverlayImageGallery.php | 60 + includes/gallery/TraditionalImageGallery.php | 328 ++ includes/installer/CliInstaller.php | 9 +- includes/installer/DatabaseInstaller.php | 64 +- includes/installer/DatabaseUpdater.php | 156 +- includes/installer/InstallDocFormatter.php | 12 +- includes/installer/Installer.i18n.php | 1959 ++++++---- includes/installer/Installer.php | 298 +- includes/installer/LocalSettingsGenerator.php | 59 +- includes/installer/MysqlInstaller.php | 135 +- includes/installer/MysqlUpdater.php | 516 ++- includes/installer/OracleInstaller.php | 61 +- includes/installer/OracleUpdater.php | 72 +- includes/installer/PhpBugTests.php | 2 + includes/installer/PostgresInstaller.php | 62 +- includes/installer/PostgresUpdater.php | 575 +-- includes/installer/SqliteInstaller.php | 38 +- includes/installer/SqliteUpdater.php | 121 +- includes/installer/WebInstaller.php | 208 +- includes/installer/WebInstallerOutput.php | 112 +- includes/installer/WebInstallerPage.php | 259 +- includes/job/Job.php | 56 +- includes/job/JobQueue.php | 355 +- includes/job/JobQueueAggregator.php | 139 - includes/job/JobQueueAggregatorMemc.php | 117 - includes/job/JobQueueAggregatorRedis.php | 165 - includes/job/JobQueueDB.php | 688 ++-- includes/job/JobQueueFederated.php | 473 +++ includes/job/JobQueueGroup.php | 90 +- includes/job/JobQueueRedis.php | 856 +++++ includes/job/aggregator/JobQueueAggregator.php | 156 + includes/job/aggregator/JobQueueAggregatorMemc.php | 124 + .../job/aggregator/JobQueueAggregatorRedis.php | 193 + includes/job/jobs/AssembleUploadChunksJob.php | 19 +- includes/job/jobs/DoubleRedirectJob.php | 29 +- includes/job/jobs/DuplicateJob.php | 2 +- includes/job/jobs/EnotifNotifyJob.php | 2 +- includes/job/jobs/HTMLCacheUpdateJob.php | 25 +- includes/job/jobs/NullJob.php | 16 + includes/job/jobs/PublishStashedFileJob.php | 22 +- includes/job/jobs/RefreshLinksJob.php | 28 +- includes/job/jobs/UploadFromUrlJob.php | 7 +- includes/json/FormatJson.php | 217 +- includes/json/Services_JSON.php | 882 ----- includes/libs/CSSJanus.php | 72 +- includes/libs/CSSMin.php | 47 +- includes/libs/HttpStatus.php | 2 +- includes/libs/lessc.inc.php | 3742 ++++++++++++++++++++ includes/limit.sh | 9 +- includes/logging/DeleteLogFormatter.php | 196 + includes/logging/LogEntry.php | 55 +- includes/logging/LogEventsList.php | 82 +- includes/logging/LogFormatter.php | 412 +-- includes/logging/LogPage.php | 62 +- includes/logging/LogPager.php | 77 +- includes/logging/MoveLogFormatter.php | 82 + includes/logging/NewUsersLogFormatter.php | 65 + includes/logging/PatrolLog.php | 7 + includes/logging/PatrolLogFormatter.php | 63 + includes/logging/RightsLogFormatter.php | 112 + includes/media/BMP.php | 6 +- includes/media/Bitmap.php | 47 +- includes/media/BitmapMetadataHandler.php | 24 +- includes/media/DjVu.php | 21 +- includes/media/DjVuImage.php | 44 +- includes/media/Exif.php | 76 +- includes/media/ExifBitmap.php | 8 +- includes/media/FormatMetadata.php | 101 +- includes/media/GIF.php | 8 +- includes/media/GIFMetadataExtractor.php | 46 +- includes/media/IPTC.php | 8 +- includes/media/ImageHandler.php | 23 +- includes/media/Jpeg.php | 20 +- includes/media/JpegMetadataExtractor.php | 22 +- includes/media/MediaHandler.php | 149 +- includes/media/MediaTransformOutput.php | 53 +- includes/media/PNG.php | 13 +- includes/media/PNGMetadataExtractor.php | 30 +- includes/media/SVG.php | 92 +- includes/media/SVGMetadataExtractor.php | 64 +- includes/media/Tiff.php | 2 +- includes/media/XCF.php | 6 +- includes/media/XMP.php | 26 +- includes/media/XMPInfo.php | 6 +- includes/media/XMPValidate.php | 12 +- includes/mime.info | 4 + includes/mime.types | 5 + includes/normal/README | 10 +- includes/normal/RandomTest.php | 6 +- includes/normal/UtfNormal.php | 4 +- includes/normal/UtfNormalTest.php | 8 +- includes/normal/UtfNormalTest2.php | 2 +- includes/normal/UtfNormalUtil.php | 8 +- includes/objectcache/BagOStuff.php | 8 +- includes/objectcache/MemcachedBagOStuff.php | 2 +- includes/objectcache/MemcachedClient.php | 24 +- includes/objectcache/MemcachedPeclBagOStuff.php | 14 +- includes/objectcache/MultiWriteBagOStuff.php | 2 +- includes/objectcache/ObjectCache.php | 14 +- includes/objectcache/ObjectCacheSessionHandler.php | 2 +- includes/objectcache/RedisBagOStuff.php | 40 +- includes/objectcache/SqlBagOStuff.php | 22 +- includes/parser/CacheTime.php | 2 +- includes/parser/CoreLinkFunctions.php | 92 - includes/parser/CoreParserFunctions.php | 197 +- includes/parser/CoreTagHooks.php | 2 +- includes/parser/DateFormatter.php | 24 +- includes/parser/LinkHolderArray.php | 216 +- includes/parser/Parser.php | 848 +++-- includes/parser/ParserCache.php | 20 +- includes/parser/ParserOptions.php | 21 +- includes/parser/ParserOutput.php | 111 +- includes/parser/Parser_DiffTest.php | 2 +- includes/parser/Parser_LinkHooks.php | 326 -- includes/parser/Preprocessor_DOM.php | 99 +- includes/parser/Preprocessor_Hash.php | 61 +- includes/parser/Tidy.php | 11 +- includes/profiler/Profiler.php | 264 +- includes/profiler/ProfilerSimple.php | 5 +- includes/profiler/ProfilerSimpleText.php | 12 +- includes/profiler/ProfilerSimpleTrace.php | 2 + includes/profiler/ProfilerSimpleUDP.php | 12 +- includes/profiler/ProfilerStub.php | 2 + includes/rcfeed/IRCColourfulRCFeedFormatter.php | 99 + includes/rcfeed/JSONRCFeedFormatter.php | 90 + includes/rcfeed/RCFeedEngine.php | 12 + includes/rcfeed/RCFeedFormatter.php | 13 + includes/rcfeed/RedisPubSubFeedEngine.php | 41 + includes/rcfeed/UDPRCFeedEngine.php | 10 + includes/resourceloader/ResourceLoader.php | 181 +- includes/resourceloader/ResourceLoaderContext.php | 2 +- .../resourceloader/ResourceLoaderFileModule.php | 176 +- .../resourceloader/ResourceLoaderLESSFunctions.php | 67 + .../ResourceLoaderLanguageDataModule.php | 31 +- includes/resourceloader/ResourceLoaderModule.php | 102 +- .../resourceloader/ResourceLoaderSiteModule.php | 23 +- .../resourceloader/ResourceLoaderStartUpModule.php | 10 +- .../ResourceLoaderUserCSSPrefsModule.php | 67 +- .../ResourceLoaderUserGroupsModule.php | 15 +- .../resourceloader/ResourceLoaderUserModule.php | 21 +- .../ResourceLoaderUserOptionsModule.php | 4 +- .../ResourceLoaderUserTokensModule.php | 9 +- .../resourceloader/ResourceLoaderWikiModule.php | 4 +- includes/revisiondelete/RevisionDelete.php | 86 +- .../revisiondelete/RevisionDeleteAbstracts.php | 50 +- includes/revisiondelete/RevisionDeleteUser.php | 2 +- includes/revisiondelete/RevisionDeleter.php | 149 +- includes/search/SearchEngine.php | 169 +- includes/search/SearchMssql.php | 6 +- includes/search/SearchMySQL.php | 66 +- includes/search/SearchOracle.php | 86 +- includes/search/SearchPostgres.php | 43 +- includes/search/SearchSqlite.php | 39 +- includes/search/SearchUpdate.php | 123 +- includes/site/MediaWikiSite.php | 8 +- includes/site/SiteSQLStore.php | 52 +- includes/specials/SpecialActiveusers.php | 74 +- includes/specials/SpecialAllmessages.php | 143 +- includes/specials/SpecialAllpages.php | 174 +- includes/specials/SpecialAncientpages.php | 22 +- includes/specials/SpecialBlankpage.php | 1 + includes/specials/SpecialBlock.php | 49 +- includes/specials/SpecialBlockList.php | 52 +- includes/specials/SpecialBlockme.php | 66 - includes/specials/SpecialBooksources.php | 49 +- includes/specials/SpecialBrokenRedirects.php | 12 +- includes/specials/SpecialCachedPage.php | 1 - includes/specials/SpecialCategories.php | 38 +- includes/specials/SpecialChangeEmail.php | 67 +- includes/specials/SpecialChangePassword.php | 134 +- includes/specials/SpecialComparePages.php | 11 +- includes/specials/SpecialConfirmemail.php | 101 +- includes/specials/SpecialContributions.php | 380 +- includes/specials/SpecialDeadendpages.php | 25 +- includes/specials/SpecialDeletedContributions.php | 179 +- includes/specials/SpecialDisambiguations.php | 165 - includes/specials/SpecialDoubleRedirects.php | 31 +- includes/specials/SpecialEditWatchlist.php | 174 +- includes/specials/SpecialEmailuser.php | 82 +- includes/specials/SpecialExport.php | 143 +- includes/specials/SpecialFewestrevisions.php | 53 +- includes/specials/SpecialFileDuplicateSearch.php | 51 +- includes/specials/SpecialFilepath.php | 62 +- includes/specials/SpecialImport.php | 245 +- includes/specials/SpecialJavaScriptTest.php | 56 +- includes/specials/SpecialLinkSearch.php | 71 +- includes/specials/SpecialListfiles.php | 301 +- includes/specials/SpecialListgrouprights.php | 51 +- includes/specials/SpecialListredirects.php | 34 +- includes/specials/SpecialListusers.php | 113 +- includes/specials/SpecialLog.php | 79 +- includes/specials/SpecialLonelypages.php | 48 +- includes/specials/SpecialLongpages.php | 1 - includes/specials/SpecialMIMEsearch.php | 97 +- includes/specials/SpecialMergeHistory.php | 118 +- includes/specials/SpecialMostcategories.php | 48 +- includes/specials/SpecialMostimages.php | 19 +- includes/specials/SpecialMostinterwikis.php | 32 +- includes/specials/SpecialMostlinked.php | 69 +- includes/specials/SpecialMostlinkedcategories.php | 32 +- includes/specials/SpecialMostlinkedtemplates.php | 39 +- includes/specials/SpecialMovepage.php | 263 +- includes/specials/SpecialNewimages.php | 40 +- includes/specials/SpecialNewpages.php | 156 +- includes/specials/SpecialPagesWithProp.php | 32 +- includes/specials/SpecialPasswordReset.php | 94 +- includes/specials/SpecialPopularpages.php | 34 +- includes/specials/SpecialPreferences.php | 26 +- includes/specials/SpecialPrefixindex.php | 147 +- includes/specials/SpecialProtectedpages.php | 169 +- includes/specials/SpecialProtectedtitles.php | 80 +- includes/specials/SpecialRandomInCategory.php | 291 ++ includes/specials/SpecialRandompage.php | 31 +- includes/specials/SpecialRandomredirect.php | 1 - includes/specials/SpecialRecentchanges.php | 410 +-- includes/specials/SpecialRecentchangeslinked.php | 63 +- includes/specials/SpecialRedirect.php | 235 ++ includes/specials/SpecialResetTokens.php | 145 + includes/specials/SpecialRevisiondelete.php | 170 +- includes/specials/SpecialSearch.php | 198 +- includes/specials/SpecialShortpages.php | 18 +- includes/specials/SpecialSpecialpages.php | 17 +- includes/specials/SpecialStatistics.php | 37 +- includes/specials/SpecialTags.php | 69 +- includes/specials/SpecialUnblock.php | 22 +- .../specials/SpecialUncategorizedcategories.php | 6 +- includes/specials/SpecialUncategorizedimages.php | 2 +- includes/specials/SpecialUncategorizedpages.php | 13 +- includes/specials/SpecialUndelete.php | 680 ++-- includes/specials/SpecialUnusedcategories.php | 15 +- includes/specials/SpecialUnusedimages.php | 16 +- includes/specials/SpecialUnusedtemplates.php | 16 +- includes/specials/SpecialUnwatchedpages.php | 16 +- includes/specials/SpecialUpload.php | 126 +- includes/specials/SpecialUploadStash.php | 29 +- includes/specials/SpecialUserlogin.php | 369 +- includes/specials/SpecialUserrights.php | 162 +- includes/specials/SpecialVersion.php | 203 +- includes/specials/SpecialWantedcategories.php | 18 +- includes/specials/SpecialWantedfiles.php | 16 +- includes/specials/SpecialWantedtemplates.php | 14 +- includes/specials/SpecialWatchlist.php | 192 +- includes/specials/SpecialWhatlinkshere.php | 69 +- includes/specials/SpecialWithoutinterwiki.php | 28 +- includes/templates/NoLocalSettings.php | 14 +- includes/templates/Usercreate.php | 445 +-- includes/templates/Userlogin.php | 278 +- includes/tidy.conf | 2 +- includes/upload/UploadBase.php | 202 +- includes/upload/UploadFromChunks.php | 26 +- includes/upload/UploadFromFile.php | 2 +- includes/upload/UploadFromStash.php | 6 +- includes/upload/UploadFromUrl.php | 49 +- includes/upload/UploadStash.php | 29 +- 540 files changed, 39154 insertions(+), 24437 deletions(-) create mode 100644 includes/CallableUpdate.php delete mode 100644 includes/ChangesList.php delete mode 100644 includes/CryptRand.php delete mode 100644 includes/ExternalEdit.php delete mode 100644 includes/ExternalUser.php create mode 100644 includes/HashRing.php create mode 100644 includes/HtmlFormatter.php delete mode 100644 includes/ImageGallery.php create mode 100644 includes/MWCryptRand.php delete mode 100644 includes/RecentChange.php delete mode 100644 includes/SeleniumWebSettings.php delete mode 100644 includes/SkinLegacy.php create mode 100644 includes/StatCounter.php create mode 100644 includes/api/ApiQueryFileRepoInfo.php create mode 100644 includes/changes/ChangesList.php create mode 100644 includes/changes/EnhancedChangesList.php create mode 100644 includes/changes/OldChangesList.php create mode 100644 includes/changes/RCCacheEntry.php create mode 100644 includes/changes/RecentChange.php create mode 100644 includes/db/ChronologyProtector.php create mode 100644 includes/db/DatabaseMysqlBase.php create mode 100644 includes/db/DatabaseMysqli.php delete mode 100644 includes/extauth/Hardcoded.php delete mode 100644 includes/extauth/MediaWiki.php delete mode 100644 includes/extauth/vB.php create mode 100644 includes/filebackend/lockmanager/RedisLockManager.php create mode 100644 includes/gallery/ImageGalleryBase.php create mode 100644 includes/gallery/NolinesImageGallery.php create mode 100644 includes/gallery/PackedImageGallery.php create mode 100644 includes/gallery/PackedOverlayImageGallery.php create mode 100644 includes/gallery/TraditionalImageGallery.php delete mode 100644 includes/job/JobQueueAggregator.php delete mode 100644 includes/job/JobQueueAggregatorMemc.php delete mode 100644 includes/job/JobQueueAggregatorRedis.php create mode 100644 includes/job/JobQueueFederated.php create mode 100644 includes/job/JobQueueRedis.php create mode 100644 includes/job/aggregator/JobQueueAggregator.php create mode 100644 includes/job/aggregator/JobQueueAggregatorMemc.php create mode 100644 includes/job/aggregator/JobQueueAggregatorRedis.php delete mode 100644 includes/json/Services_JSON.php create mode 100644 includes/libs/lessc.inc.php create mode 100644 includes/logging/DeleteLogFormatter.php create mode 100644 includes/logging/MoveLogFormatter.php create mode 100644 includes/logging/NewUsersLogFormatter.php create mode 100644 includes/logging/PatrolLogFormatter.php create mode 100644 includes/logging/RightsLogFormatter.php delete mode 100644 includes/parser/CoreLinkFunctions.php delete mode 100644 includes/parser/Parser_LinkHooks.php create mode 100644 includes/rcfeed/IRCColourfulRCFeedFormatter.php create mode 100644 includes/rcfeed/JSONRCFeedFormatter.php create mode 100644 includes/rcfeed/RCFeedEngine.php create mode 100644 includes/rcfeed/RCFeedFormatter.php create mode 100644 includes/rcfeed/RedisPubSubFeedEngine.php create mode 100644 includes/rcfeed/UDPRCFeedEngine.php create mode 100644 includes/resourceloader/ResourceLoaderLESSFunctions.php delete mode 100644 includes/specials/SpecialBlockme.php delete mode 100644 includes/specials/SpecialDisambiguations.php create mode 100644 includes/specials/SpecialRandomInCategory.php create mode 100644 includes/specials/SpecialRedirect.php create mode 100644 includes/specials/SpecialResetTokens.php (limited to 'includes') diff --git a/includes/Action.php b/includes/Action.php index 2e0c88ba..4b6e4468 100644 --- a/includes/Action.php +++ b/includes/Action.php @@ -59,7 +59,7 @@ abstract class Action { * the action is disabled, or null if it's not recognised * @param $action String * @param $overrides Array - * @return bool|null|string + * @return bool|null|string|callable */ final private static function getClass( $action, array $overrides ) { global $wgActions; @@ -89,12 +89,18 @@ abstract class Action { * if it is not recognised */ final public static function factory( $action, Page $page, IContextSource $context = null ) { - $class = self::getClass( $action, $page->getActionOverrides() ); - if ( $class ) { - $obj = new $class( $page, $context ); + $classOrCallable = self::getClass( $action, $page->getActionOverrides() ); + + if ( is_string( $classOrCallable ) ) { + $obj = new $classOrCallable( $page, $context ); return $obj; } - return $class; + + if ( is_callable( $classOrCallable ) ) { + return call_user_func_array( $classOrCallable, array( $page, $context ) ); + } + + return $classOrCallable; } /** @@ -136,7 +142,7 @@ abstract class Action { return 'view'; } - $action = Action::factory( $actionName, $context->getWikiPage() ); + $action = Action::factory( $actionName, $context->getWikiPage(), $context ); if ( $action instanceof Action ) { return $action->getName(); } @@ -161,8 +167,14 @@ abstract class Action { final public function getContext() { if ( $this->context instanceof IContextSource ) { return $this->context; + } else if ( $this->page instanceof Article ) { + // NOTE: $this->page can be a WikiPage, which does not have a context. + wfDebug( __METHOD__ . ': no context known, falling back to Article\'s context.' ); + return $this->page->getContext(); } - return $this->page->getContext(); + + wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' ); + return RequestContext::getMain(); } /** @@ -213,7 +225,7 @@ abstract class Action { /** * Shortcut to get the user Language being used for this instance * - * @deprecated 1.19 Use getLanguage instead + * @deprecated since 1.19 Use getLanguage instead * @return Language */ final public function getLang() { @@ -241,12 +253,20 @@ abstract class Action { } /** - * Protected constructor: use Action::factory( $action, $page ) to actually build - * these things in the real world + * Constructor. + * + * Only public since 1.21 + * * @param $page Page * @param $context IContextSource */ - protected function __construct( Page $page, IContextSource $context = null ) { + public function __construct( Page $page, IContextSource $context = null ) { + if ( $context === null ) { + wfWarn( __METHOD__ . ' called without providing a Context object.' ); + // NOTE: We could try to initialize $context using $page->getContext(), + // if $page is an Article. That however seems to not work seamlessly. + } + $this->page = $page; $this->context = $context; } @@ -374,18 +394,23 @@ abstract class FormAction extends Action { * Add pre- or post-text to the form * @return String HTML which will be sent to $form->addPreText() */ - protected function preText() { return ''; } + protected function preText() { + return ''; + } /** * @return string */ - protected function postText() { return ''; } + protected function postText() { + return ''; + } /** * Play with the HTMLForm if you need to more substantially * @param $form HTMLForm */ - protected function alterForm( HTMLForm $form ) {} + protected function alterForm( HTMLForm $form ) { + } /** * Get the HTMLForm to control behavior @@ -464,7 +489,7 @@ abstract class FormAction extends Action { public function execute( array $data = null, $captureErrors = true ) { try { // Set a new context so output doesn't leak. - $this->context = clone $this->page->getContext(); + $this->context = clone $this->getContext(); // This will throw exceptions if there's a problem $this->checkCanExecute( $this->getUser() ); @@ -553,7 +578,7 @@ abstract class FormlessAction extends Action { public function execute( array $data = null, $captureErrors = true ) { try { // Set a new context so output doesn't leak. - $this->context = clone $this->page->getContext(); + $this->context = clone $this->getContext(); if ( is_array( $data ) ) { $this->context->setRequest( new FauxRequest( $data, false ) ); } diff --git a/includes/AjaxDispatcher.php b/includes/AjaxDispatcher.php index b00cf309..c9ca1283 100644 --- a/includes/AjaxDispatcher.php +++ b/includes/AjaxDispatcher.php @@ -63,7 +63,7 @@ class AjaxDispatcher { $this->mode = "post"; } - switch( $this->mode ) { + switch ( $this->mode ) { case 'get': $this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : ''; if ( ! empty( $_GET["rsargs"] ) ) { @@ -111,15 +111,13 @@ class AjaxDispatcher { wfHttpError( 400, 'Bad Request', - "unknown function " . (string) $this->func_name + "unknown function " . $this->func_name ); - } elseif ( !in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) - && !$wgUser->isAllowed( 'read' ) ) - { + } elseif ( !User::isEveryoneAllowed( 'read' ) && !$wgUser->isAllowed( 'read' ) ) { wfHttpError( 403, 'Forbidden', - 'You must log in to view pages.' ); + 'You are not allowed to view pages.' ); } else { wfDebug( __METHOD__ . ' dispatching ' . $this->func_name . "\n" ); diff --git a/includes/AjaxResponse.php b/includes/AjaxResponse.php index 138f808a..d5536529 100644 --- a/includes/AjaxResponse.php +++ b/includes/AjaxResponse.php @@ -210,7 +210,7 @@ class AjaxResponse { * @param $timestamp string * @return bool Returns true if the response code was set to 304 Not Modified. */ - function checkLastModified ( $timestamp ) { + function checkLastModified( $timestamp ) { global $wgCachePages, $wgCacheEpoch, $wgUser; $fname = 'AjaxResponse::checkLastModified'; diff --git a/includes/ArrayUtils.php b/includes/ArrayUtils.php index 0b74f06a..985271f7 100644 --- a/includes/ArrayUtils.php +++ b/includes/ArrayUtils.php @@ -39,7 +39,7 @@ class ArrayUtils { * * @return bool|int|string */ - public static function pickRandom( $weights ){ + public static function pickRandom( $weights ) { if ( !is_array( $weights ) || count( $weights ) == 0 ) { return false; } diff --git a/includes/Article.php b/includes/Article.php index 9b4afe44..0b18221a 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -25,7 +25,7 @@ * * This maintains WikiPage functions for backwards compatibility. * - * @todo move and rewrite code to an Action class + * @todo Move and rewrite code to an Action class * * See design.txt for an overview. * Note: edit user interface and cache support functions have been @@ -160,7 +160,7 @@ class Article implements Page { $page = null; wfRunHooks( 'ArticleFromTitle', array( &$title, &$page ) ); if ( !$page ) { - switch( $title->getNamespace() ) { + switch ( $title->getNamespace() ) { case NS_FILE: $page = new ImagePage( $title ); break; @@ -385,7 +385,8 @@ class Article implements Page { $content = $this->fetchContentObject(); - $this->mContent = ContentHandler::getContentText( $content ); #@todo: get rid of mContent everywhere! + // @todo Get rid of mContent everywhere! + $this->mContent = ContentHandler::getContentText( $content ); ContentHandler::runLegacyHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) ); wfProfileOut( __METHOD__ ); @@ -609,7 +610,7 @@ class Article implements Page { $this->mParserOutput = false; while ( !$outputDone && ++$pass ) { - switch( $pass ) { + switch ( $pass ) { case 1: wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) ); break; @@ -673,12 +674,12 @@ class Article implements Page { wfDebug( __METHOD__ . ": showing CSS/JS source\n" ); $this->showCssOrJsPage(); $outputDone = true; - } elseif( !wfRunHooks( 'ArticleContentViewCustom', + } 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', + } elseif ( !ContentHandler::runLegacyHooks( 'ArticleViewCustom', array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) { # Allow extensions do their own custom view for certain pages @@ -787,7 +788,7 @@ class Article implements 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 + * @todo Make protected */ public function showDiffPage() { $request = $this->getContext()->getRequest(); @@ -854,11 +855,11 @@ class Article implements Page { /** * Get the robot policy to be used for the current view * @param string $action the action= GET parameter - * @param $pOutput ParserOutput + * @param $pOutput ParserOutput|null * @return Array the policy that should be set * TODO: actions other than 'view' */ - public function getRobotPolicy( $action, $pOutput ) { + public function getRobotPolicy( $action, $pOutput = null ) { global $wgArticleRobotPolicies, $wgNamespaceRobotPolicies, $wgDefaultRobotPolicy; $ns = $this->getTitle()->getNamespace(); @@ -875,7 +876,7 @@ class Article implements Page { } if ( Block::newFromTarget( $specificTarget, $vagueTarget ) instanceof Block ) { return array( - 'index' => 'noindex', + 'index' => 'noindex', 'follow' => 'nofollow' ); } @@ -884,19 +885,19 @@ class Article implements Page { if ( $this->mPage->getID() === 0 || $this->getOldID() ) { # Non-articles (special pages etc), and old revisions return array( - 'index' => 'noindex', + 'index' => 'noindex', 'follow' => 'nofollow' ); } elseif ( $this->getContext()->getOutput()->isPrintable() ) { # Discourage indexing of printable versions, but encourage following return array( - 'index' => 'noindex', + 'index' => 'noindex', 'follow' => 'follow' ); } elseif ( $this->getContext()->getRequest()->getInt( 'curid' ) ) { # For ?curid=x urls, disallow indexing return array( - 'index' => 'noindex', + 'index' => 'noindex', 'follow' => 'follow' ); } @@ -988,8 +989,9 @@ class Article implements Page { // Set the fragment if one was specified in the redirect if ( strval( $this->getTitle()->getFragment() ) != '' ) { - $fragment = Xml::escapeJsString( $this->getTitle()->getFragmentForURL() ); - $outputPage->addInlineScript( "redirectToFragment(\"$fragment\");" ); + $outputPage->addInlineScript( Xml::encodeJsCall( + 'redirectToFragment', array( $this->getTitle()->getFragmentForURL() ) + ) ); } // Add a tag @@ -1035,11 +1037,10 @@ class Article implements Page { $this->getContext()->getOutput()->addWikiMsg( 'anontalkpagetext' ); } - # If we have been passed an &rcid= parameter, we want to give the user a - # chance to mark this new article as patrolled. - $this->showPatrolFooter(); + // Show a footer allowing the user to patrol the shown revision or page if possible + $patrolFooterShown = $this->showPatrolFooter(); - wfRunHooks( 'ArticleViewFooter', array( $this ) ); + wfRunHooks( 'ArticleViewFooter', array( $this, $patrolFooterShown ) ); } @@ -1049,21 +1050,92 @@ class Article implements Page { * desired, does nothing. * Side effect: When the patrol link is build, this method will call * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax. + * + * @return bool */ public function showPatrolFooter() { - $request = $this->getContext()->getRequest(); + global $wgUseNPPatrol, $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI; + $outputPage = $this->getContext()->getOutput(); $user = $this->getContext()->getUser(); - $rcid = $request->getVal( 'rcid' ); + $cache = wfGetMainCache(); + $rc = false; - if ( !$rcid || !$this->getTitle()->quickUserCan( 'patrol', $user ) ) { - return; + if ( !$this->getTitle()->quickUserCan( 'patrol', $user ) || !( $wgUseRCPatrol || $wgUseNPPatrol ) ) { + // Patrolling is disabled or the user isn't allowed to + return false; + } + + wfProfileIn( __METHOD__ ); + + // New page patrol: Get the timestamp of the oldest revison which + // the revision table holds for the given page. Then we look + // whether it's within the RC lifespan and if it is, we try + // to get the recentchanges row belonging to that entry + // (with rc_new = 1). + + // Check for cached results + if ( $cache->get( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ) ) ) { + wfProfileOut( __METHOD__ ); + return false; } + if ( $this->mRevision && !RecentChange::isInRCLifespan( $this->mRevision->getTimestamp(), 21600 ) ) { + // The current revision is already older than what could be in the RC table + // 6h tolerance because the RC might not be cleaned out regularly + wfProfileOut( __METHOD__ ); + return false; + } + + $dbr = wfGetDB( DB_SLAVE ); + $oldestRevisionTimestamp = $dbr->selectField( + 'revision', + 'MIN( rev_timestamp )', + array( 'rev_page' => $this->getTitle()->getArticleID() ), + __METHOD__ + ); + + if ( $oldestRevisionTimestamp && RecentChange::isInRCLifespan( $oldestRevisionTimestamp, 21600 ) ) { + // 6h tolerance because the RC might not be cleaned out regularly + $rc = RecentChange::newFromConds( + array( + 'rc_new' => 1, + 'rc_timestamp' => $oldestRevisionTimestamp, + 'rc_namespace' => $this->getTitle()->getNamespace(), + 'rc_cur_id' => $this->getTitle()->getArticleID(), + 'rc_patrolled' => 0 + ), + __METHOD__, + array( 'USE INDEX' => 'new_name_timestamp' ) + ); + } + + if ( !$rc ) { + // No RC entry around + + // Cache the information we gathered above in case we can't patrol + // Don't cache in case we can patrol as this could change + $cache->set( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ), '1' ); + + wfProfileOut( __METHOD__ ); + return false; + } + + if ( $rc->getPerformer()->getName() == $user->getName() ) { + // Don't show a patrol link for own creations. If the user could + // patrol them, they already would be patrolled + wfProfileOut( __METHOD__ ); + return false; + } + + $rcid = $rc->getAttribute( 'rc_id' ); + $token = $user->getEditToken( $rcid ); $outputPage->preventClickjacking(); - $outputPage->addModules( 'mediawiki.page.patrol.ajax' ); + if ( $wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed( 'writeapi' ) ) { + $outputPage->addModules( 'mediawiki.page.patrol.ajax' ); + } $link = Linker::linkKnown( $this->getTitle(), @@ -1081,6 +1153,9 @@ class Article implements Page { wfMessage( 'markaspatrolledlink' )->rawParams( $link )->escaped() . '' ); + + wfProfileOut( __METHOD__ ); + return true; } /** @@ -1090,6 +1165,7 @@ class Article implements Page { public function showMissingArticle() { global $wgSend404Code; $outputPage = $this->getContext()->getOutput(); + // Whether the page is a root user page of an existing user (but not a subpage) $validUserPage = false; # Show info in user (talk) namespace. Does the user exist? Is he blocked? @@ -1099,7 +1175,7 @@ class Article implements Page { $user = User::newFromName( $rootPart, false /* allow IP users*/ ); $ip = User::isIP( $rootPart ); - if ( !($user && $user->isLoggedIn()) && !$ip ) { # User does not exist + if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist $outputPage->wrapWikiMsg( "
\n\$1\n
", array( 'userpage-userdoesnotexist-view', wfEscapeWikiText( $rootPart ) ) ); } elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked @@ -1117,9 +1193,9 @@ class Article implements Page { ) ) ); - $validUserPage = true; + $validUserPage = !$this->getTitle()->isSubpage(); } else { - $validUserPage = true; + $validUserPage = !$this->getTitle()->isSubpage(); } } @@ -1139,6 +1215,13 @@ class Article implements Page { $this->getContext()->getRequest()->response()->header( "HTTP/1.1 404 Not Found" ); } + if ( $validUserPage ) { + // Also apply the robot policy for nonexisting user pages (as those aren't served as 404) + $policy = $this->getRobotPolicy( 'view' ); + $outputPage->setIndexPolicy( $policy['index'] ); + $outputPage->setFollowPolicy( $policy['follow'] ); + } + $hookResult = wfRunHooks( 'BeforeDisplayNoArticleText', array( $this ) ); if ( ! $hookResult ) { @@ -1188,7 +1271,7 @@ class Article implements Page { } elseif ( $this->getContext()->getRequest()->getInt( 'unhide' ) != 1 ) { # Give explanation and add a link to view the revision... $oldid = intval( $this->getOldID() ); - $link = $this->getTitle()->getFullUrl( "oldid={$oldid}&unhide=1" ); + $link = $this->getTitle()->getFullURL( "oldid={$oldid}&unhide=1" ); $msg = $this->mRevision->isDeleted( Revision::DELETED_RESTRICTED ) ? 'rev-suppressed-text-unhide' : 'rev-deleted-text-unhide'; $outputPage->wrapWikiMsg( "\n", @@ -1470,13 +1553,7 @@ class Article implements Page { $this->doDelete( $reason, $suppress ); - if ( $user->isLoggedIn() && $request->getCheck( 'wpWatch' ) != $user->isWatched( $title ) ) { - if ( $request->getCheck( 'wpWatch' ) ) { - WatchAction::doWatch( $title, $user ); - } else { - WatchAction::doUnwatch( $title, $user ); - } - } + WatchAction::doWatchOrUnwatch( $request->getCheck( 'wpWatch' ), $title, $user ); return; } diff --git a/includes/AuthPlugin.php b/includes/AuthPlugin.php index a4658176..84cf3d5e 100644 --- a/includes/AuthPlugin.php +++ b/includes/AuthPlugin.php @@ -212,6 +212,19 @@ class AuthPlugin { return true; } + /** + * Update user groups in the external authentication database. + * Return true if successful. + * + * @param $user User object. + * @param $addgroups Groups to add. + * @param $delgroups Groups to remove. + * @return Boolean + */ + public function updateExternalDBGroups( $user, $addgroups, $delgroups = array() ) { + return true; + } + /** * Check to see if external accounts can be created. * Return true if external accounts can be created. diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 3555e2c3..0706fe3f 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -55,7 +55,6 @@ $wgAutoloadLocalClasses = array( 'CdbWriter_DBA' => 'includes/Cdb.php', 'CdbWriter_PHP' => 'includes/Cdb_PHP.php', 'ChangesFeed' => 'includes/ChangesFeed.php', - 'ChangesList' => 'includes/ChangesList.php', 'ChangeTags' => 'includes/ChangeTags.php', 'ChannelFeed' => 'includes/Feed.php', 'Collation' => 'includes/Collation.php', @@ -65,10 +64,10 @@ $wgAutoloadLocalClasses = array( 'ConfEditorToken' => 'includes/ConfEditor.php', 'Cookie' => 'includes/Cookie.php', 'CookieJar' => 'includes/Cookie.php', - 'MWCryptRand' => 'includes/CryptRand.php', 'CurlHttpRequest' => 'includes/HttpFunctions.php', 'DeferrableUpdate' => 'includes/DeferredUpdates.php', 'DeferredUpdates' => 'includes/DeferredUpdates.php', + 'MWCallableUpdate' => 'includes/CallableUpdate.php', 'DeprecatedGlobal' => 'includes/DeprecatedGlobal.php', 'DerivativeRequest' => 'includes/WebRequest.php', 'DiffHistoryBlob' => 'includes/HistoryBlob.php', @@ -87,16 +86,8 @@ $wgAutoloadLocalClasses = array( 'DumpPipeOutput' => 'includes/Export.php', 'EditPage' => 'includes/EditPage.php', 'EmailNotification' => 'includes/UserMailer.php', - 'EnhancedChangesList' => 'includes/ChangesList.php', 'ErrorPageError' => 'includes/Exception.php', 'ExplodeIterator' => 'includes/StringUtils.php', - 'ExternalEdit' => 'includes/ExternalEdit.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', 'FatalError' => 'includes/Exception.php', @@ -111,22 +102,27 @@ $wgAutoloadLocalClasses = array( 'FormOptions' => 'includes/FormOptions.php', 'FormSpecialPage' => 'includes/SpecialPage.php', 'GitInfo' => 'includes/GitInfo.php', + 'HashRing' => 'includes/HashRing.php', 'HashtableReplacer' => 'includes/StringUtils.php', 'HistoryBlob' => 'includes/HistoryBlob.php', 'HistoryBlobCurStub' => 'includes/HistoryBlob.php', 'HistoryBlobStub' => 'includes/HistoryBlob.php', 'Hooks' => 'includes/Hooks.php', 'Html' => 'includes/Html.php', + 'HtmlFormatter' => 'includes/HtmlFormatter.php', 'HTMLApiField' => 'includes/HTMLForm.php', + 'HTMLButtonField' => 'includes/HTMLForm.php', 'HTMLCheckField' => 'includes/HTMLForm.php', 'HTMLCheckMatrix' => 'includes/HTMLForm.php', 'HTMLEditTools' => 'includes/HTMLForm.php', 'HTMLFloatField' => 'includes/HTMLForm.php', 'HTMLForm' => 'includes/HTMLForm.php', 'HTMLFormField' => 'includes/HTMLForm.php', + 'HTMLFormFieldRequiredOptionsException' => 'includes/HTMLForm.php', 'HTMLHiddenField' => 'includes/HTMLForm.php', 'HTMLInfoField' => 'includes/HTMLForm.php', 'HTMLIntField' => 'includes/HTMLForm.php', + 'HTMLNestedFilterable' => 'includes/HTMLForm.php', 'HTMLMultiSelectField' => 'includes/HTMLForm.php', 'HTMLRadioField' => 'includes/HTMLForm.php', 'HTMLSelectAndOtherField' => 'includes/HTMLForm.php', @@ -140,7 +136,6 @@ $wgAutoloadLocalClasses = array( 'ICacheHelper' => 'includes/CacheHelper.php', 'IcuCollation' => 'includes/Collation.php', 'IdentityCollation' => 'includes/Collation.php', - 'ImageGallery' => 'includes/ImageGallery.php', 'ImageHistoryList' => 'includes/ImagePage.php', 'ImageHistoryPseudoPager' => 'includes/ImagePage.php', 'ImagePage' => 'includes/ImagePage.php', @@ -156,7 +151,6 @@ $wgAutoloadLocalClasses = array( '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', 'Linker' => 'includes/Linker.php', @@ -174,6 +168,7 @@ $wgAutoloadLocalClasses = array( 'Message' => 'includes/Message.php', 'MessageBlobStore' => 'includes/MessageBlobStore.php', 'MimeMagic' => 'includes/MimeMagic.php', + 'MWCryptRand' => 'includes/MWCryptRand.php', 'MWException' => 'includes/Exception.php', 'MWExceptionHandler' => 'includes/Exception.php', 'MWFunction' => 'includes/MWFunction.php', @@ -181,7 +176,6 @@ $wgAutoloadLocalClasses = array( 'MWHttpRequest' => 'includes/HttpFunctions.php', 'MWInit' => 'includes/Init.php', 'MWNamespace' => 'includes/Namespace.php', - 'OldChangesList' => 'includes/ChangesList.php', 'OutputPage' => 'includes/OutputPage.php', 'Page' => 'includes/WikiPage.php', 'PageQueryPage' => 'includes/PageQueryPage.php', @@ -194,6 +188,7 @@ $wgAutoloadLocalClasses = array( 'PoolCounter' => 'includes/PoolCounter.php', 'PoolCounter_Stub' => 'includes/PoolCounter.php', 'PoolCounterWork' => 'includes/PoolCounter.php', + 'PoolCounterWorkViaCallback' => 'includes/PoolCounter.php', 'PoolWorkArticleView' => 'includes/WikiPage.php', 'Preferences' => 'includes/Preferences.php', 'PreferencesForm' => 'includes/Preferences.php', @@ -202,10 +197,8 @@ $wgAutoloadLocalClasses = array( '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', @@ -228,7 +221,6 @@ $wgAutoloadLocalClasses = array( 'SiteStatsInit' => 'includes/SiteStats.php', 'SiteStatsUpdate' => 'includes/SiteStats.php', 'Skin' => 'includes/Skin.php', - 'SkinLegacy' => 'includes/SkinLegacy.php', 'SkinTemplate' => 'includes/SkinTemplate.php', 'SpecialCreateAccount' => 'includes/SpecialPage.php', 'SpecialListAdmins' => 'includes/SpecialPage.php', @@ -237,11 +229,13 @@ $wgAutoloadLocalClasses = array( 'SpecialMypage' => 'includes/SpecialPage.php', 'SpecialMytalk' => 'includes/SpecialPage.php', 'SpecialMyuploads' => 'includes/SpecialPage.php', + 'SpecialAllMyUploads' => 'includes/SpecialPage.php', 'SpecialPage' => 'includes/SpecialPage.php', 'SpecialPageFactory' => 'includes/SpecialPageFactory.php', 'SpecialRedirectToSpecial' => 'includes/SpecialPage.php', 'SquidPurgeClient' => 'includes/SquidPurgeClient.php', 'SquidPurgeClientPool' => 'includes/SquidPurgeClient.php', + 'StatCounter' => 'includes/StatCounter.php', 'Status' => 'includes/Status.php', 'StreamFile' => 'includes/StreamFile.php', 'StringUtils' => 'includes/StringUtils.php', @@ -415,6 +409,7 @@ $wgAutoloadLocalClasses = array( 'ApiQueryQueryPage' => 'includes/api/ApiQueryQueryPage.php', 'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php', 'ApiQueryRecentChanges' => 'includes/api/ApiQueryRecentChanges.php', + 'ApiQueryFileRepoInfo' => 'includes/api/ApiQueryFileRepoInfo.php', 'ApiQueryRevisions' => 'includes/api/ApiQueryRevisions.php', 'ApiQuerySearch' => 'includes/api/ApiQuerySearch.php', 'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php', @@ -457,6 +452,13 @@ $wgAutoloadLocalClasses = array( 'TitleDependency' => 'includes/cache/CacheDependency.php', 'TitleListDependency' => 'includes/cache/CacheDependency.php', + # includes/changes + 'ChangesList' => 'includes/changes/ChangesList.php', + 'EnhancedChangesList' => 'includes/changes/EnhancedChangesList.php', + 'OldChangesList' => 'includes/changes/OldChangesList.php', + 'RCCacheEntry' => 'includes/changes/RCCacheEntry.php', + 'RecentChange' => 'includes/changes/RecentChange.php', + # includes/clientpool 'RedisConnectionPool' => 'includes/clientpool/RedisConnectionPool.php', 'RedisConnRef' => 'includes/clientpool/RedisConnectionPool.php', @@ -473,11 +475,13 @@ $wgAutoloadLocalClasses = array( # includes/db 'Blob' => 'includes/db/DatabaseUtility.php', - 'ChronologyProtector' => 'includes/db/LBFactory.php', + 'ChronologyProtector' => 'includes/db/ChronologyProtector.php', 'CloneDatabase' => 'includes/db/CloneDatabase.php', 'DatabaseBase' => 'includes/db/Database.php', 'DatabaseMssql' => 'includes/db/DatabaseMssql.php', 'DatabaseMysql' => 'includes/db/DatabaseMysql.php', + 'DatabaseMysqlBase' => 'includes/db/DatabaseMysqlBase.php', + 'DatabaseMysqli' => 'includes/db/DatabaseMysqli.php', 'DatabaseOracle' => 'includes/db/DatabaseOracle.php', 'DatabasePostgres' => 'includes/db/DatabasePostgres.php', 'DatabaseSqlite' => 'includes/db/DatabaseSqlite.php', @@ -485,8 +489,10 @@ $wgAutoloadLocalClasses = array( 'DatabaseType' => 'includes/db/Database.php', 'DBAccessError' => 'includes/db/LBFactory.php', 'DBConnectionError' => 'includes/db/DatabaseError.php', + 'DBConnRef' => 'includes/db/LoadBalancer.php', 'DBError' => 'includes/db/DatabaseError.php', 'DBObject' => 'includes/db/DatabaseUtility.php', + 'IDatabase' => 'includes/db/Database.php', 'IORMRow' => 'includes/db/IORMRow.php', 'IORMTable' => 'includes/db/IORMTable.php', 'DBMasterPos' => 'includes/db/DatabaseUtility.php', @@ -507,8 +513,8 @@ $wgAutoloadLocalClasses = array( 'LoadMonitor_Null' => 'includes/db/LoadMonitor.php', 'MssqlField' => 'includes/db/DatabaseMssql.php', 'MssqlResult' => 'includes/db/DatabaseMssql.php', - 'MySQLField' => 'includes/db/DatabaseMysql.php', - 'MySQLMasterPos' => 'includes/db/DatabaseMysql.php', + 'MySQLField' => 'includes/db/DatabaseMysqlBase.php', + 'MySQLMasterPos' => 'includes/db/DatabaseMysqlBase.php', 'ORAField' => 'includes/db/DatabaseOracle.php', 'ORAResult' => 'includes/db/DatabaseOracle.php', 'ORMIterator' => 'includes/db/ORMIterator.php', @@ -543,14 +549,17 @@ $wgAutoloadLocalClasses = array( 'WikiDiff3' => 'includes/diff/WikiDiff3.php', 'WordLevelDiff' => 'includes/diff/DairikiDiff.php', - # includes/extauth - 'ExternalUser_Hardcoded' => 'includes/extauth/Hardcoded.php', - 'ExternalUser_MediaWiki' => 'includes/extauth/MediaWiki.php', - 'ExternalUser_vB' => 'includes/extauth/vB.php', + # includes/externalstore + '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', # includes/filebackend 'FileBackendGroup' => 'includes/filebackend/FileBackendGroup.php', 'FileBackend' => 'includes/filebackend/FileBackend.php', + 'FileBackendError' => 'includes/filebackend/FileBackend.php', 'FileBackendStore' => 'includes/filebackend/FileBackendStore.php', 'FileBackendStoreShardListIterator' => 'includes/filebackend/FileBackendStore.php', 'FileBackendStoreShardDirIterator' => 'includes/filebackend/FileBackendStore.php', @@ -582,6 +591,7 @@ $wgAutoloadLocalClasses = array( 'QuorumLockManager' => 'includes/filebackend/lockmanager/QuorumLockManager.php', 'MySqlLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php', 'PostgreSqlLockManager' => 'includes/filebackend/lockmanager/DBLockManager.php', + 'RedisLockManager' => 'includes/filebackend/lockmanager/RedisLockManager.php', 'NullLockManager' => 'includes/filebackend/lockmanager/LockManager.php', 'FileOp' => 'includes/filebackend/FileOp.php', 'FileOpBatch' => 'includes/filebackend/FileOpBatch.php', @@ -657,11 +667,15 @@ $wgAutoloadLocalClasses = array( # includes/job 'Job' => 'includes/job/Job.php', 'JobQueue' => 'includes/job/JobQueue.php', - 'JobQueueAggregator' => 'includes/job/JobQueueAggregator.php', - 'JobQueueAggregatorMemc' => 'includes/job/JobQueueAggregatorMemc.php', - 'JobQueueAggregatorRedis' => 'includes/job/JobQueueAggregatorRedis.php', + 'JobQueueAggregator' => 'includes/job/aggregator/JobQueueAggregator.php', + 'JobQueueAggregatorMemc' => 'includes/job/aggregator/JobQueueAggregatorMemc.php', + 'JobQueueAggregatorRedis' => 'includes/job/aggregator/JobQueueAggregatorRedis.php', 'JobQueueDB' => 'includes/job/JobQueueDB.php', + 'JobQueueConnectionError' => 'includes/job/JobQueue.php', + 'JobQueueError' => 'includes/job/JobQueue.php', 'JobQueueGroup' => 'includes/job/JobQueueGroup.php', + 'JobQueueFederated' => 'includes/job/JobQueueFederated.php', + 'JobQueueRedis' => 'includes/job/JobQueueRedis.php', # includes/job/jobs 'DoubleRedirectJob' => 'includes/job/jobs/DoubleRedirectJob.php', @@ -678,8 +692,6 @@ $wgAutoloadLocalClasses = array( # includes/json 'FormatJson' => 'includes/json/FormatJson.php', - 'Services_JSON' => 'includes/json/Services_JSON.php', - 'Services_JSON_Error' => 'includes/json/Services_JSON.php', # includes/libs 'CSSJanus' => 'includes/libs/CSSJanus.php', @@ -697,9 +709,16 @@ $wgAutoloadLocalClasses = array( 'JSToken' => 'includes/libs/jsminplus.php', 'JSTokenizer' => 'includes/libs/jsminplus.php', + # includes/libs/lessphp + 'lessc' => 'includes/libs/lessc.inc.php', + 'lessc_parser' => 'includes/libs/lessc.inc.php', + 'lessc_formatter_classic' => 'includes/libs/lessc.inc.php', + 'lessc_formatter_compressed' => 'includes/libs/lessc.inc.php', + 'lessc_formatter_lessjs' => 'includes/libs/lessc.inc.php', + # includes/logging 'DatabaseLogEntry' => 'includes/logging/LogEntry.php', - 'DeleteLogFormatter' => 'includes/logging/LogFormatter.php', + 'DeleteLogFormatter' => 'includes/logging/DeleteLogFormatter.php', 'LegacyLogFormatter' => 'includes/logging/LogFormatter.php', 'LogEntry' => 'includes/logging/LogEntry.php', 'LogEventsList' => 'includes/logging/LogEventsList.php', @@ -708,12 +727,22 @@ $wgAutoloadLocalClasses = array( 'LogPage' => 'includes/logging/LogPage.php', 'LogPager' => 'includes/logging/LogPager.php', 'ManualLogEntry' => 'includes/logging/LogEntry.php', - 'MoveLogFormatter' => 'includes/logging/LogFormatter.php', - 'NewUsersLogFormatter' => 'includes/logging/LogFormatter.php', + 'MoveLogFormatter' => 'includes/logging/MoveLogFormatter.php', + 'NewUsersLogFormatter' => 'includes/logging/NewUsersLogFormatter.php', 'PatrolLog' => 'includes/logging/PatrolLog.php', - 'PatrolLogFormatter' => 'includes/logging/LogFormatter.php', + 'PatrolLogFormatter' => 'includes/logging/PatrolLogFormatter.php', 'RCDatabaseLogEntry' => 'includes/logging/LogEntry.php', - 'RightsLogFormatter' => 'includes/logging/LogFormatter.php', + 'RightsLogFormatter' => 'includes/logging/RightsLogFormatter.php', + + # Image gallery + + 'ImageGallery' => 'includes/gallery/TraditionalImageGallery.php', + 'ImageGalleryBase' => 'includes/gallery/ImageGalleryBase.php', + 'NolinesImageGallery' => 'includes/gallery/NolinesImageGallery.php', + 'TraditionalImageGallery' => 'includes/gallery/TraditionalImageGallery.php', + 'PackedImageGallery' => 'includes/gallery/PackedImageGallery.php', + 'PackedHoverImageGallery' => 'includes/gallery/PackedOverlayImageGallery.php', + 'PackedOverlayImageGallery' => 'includes/gallery/PackedOverlayImageGallery.php', # includes/media 'BitmapHandler' => 'includes/media/Bitmap.php', @@ -775,12 +804,10 @@ $wgAutoloadLocalClasses = array( # includes/parser 'CacheTime' => 'includes/parser/CacheTime.php', - 'CoreLinkFunctions' => 'includes/parser/CoreLinkFunctions.php', 'CoreParserFunctions' => 'includes/parser/CoreParserFunctions.php', 'CoreTagHooks' => 'includes/parser/CoreTagHooks.php', 'DateFormatter' => 'includes/parser/DateFormatter.php', 'LinkHolderArray' => 'includes/parser/LinkHolderArray.php', - 'LinkMarkerReplacer' => 'includes/parser/Parser_LinkHooks.php', 'MWTidy' => 'includes/parser/Tidy.php', 'MWTidyWrapper' => 'includes/parser/Tidy.php', 'PPCustomFrame_DOM' => 'includes/parser/Preprocessor_DOM.php', @@ -808,7 +835,6 @@ $wgAutoloadLocalClasses = array( 'ParserOptions' => 'includes/parser/ParserOptions.php', 'ParserOutput' => 'includes/parser/ParserOutput.php', 'Parser_DiffTest' => 'includes/parser/Parser_DiffTest.php', - 'Parser_LinkHooks' => 'includes/parser/Parser_LinkHooks.php', 'Preprocessor' => 'includes/parser/Preprocessor.php', 'Preprocessor_DOM' => 'includes/parser/Preprocessor_DOM.php', 'Preprocessor_Hash' => 'includes/parser/Preprocessor_Hash.php', @@ -821,12 +847,22 @@ $wgAutoloadLocalClasses = array( 'ProfilerSimpleTrace' => 'includes/profiler/ProfilerSimpleTrace.php', 'ProfilerSimpleUDP' => 'includes/profiler/ProfilerSimpleUDP.php', 'ProfilerStub' => 'includes/profiler/ProfilerStub.php', + 'ProfileSection' => 'includes/profiler/Profiler.php', + + # includes/rcfeed + 'RCFeedEngine' => 'includes/rcfeed/RCFeedEngine.php', + 'RedisPubSubFeedEngine' => 'includes/rcfeed/RedisPubSubFeedEngine.php', + 'UDPRCFeedEngine' => 'includes/rcfeed/UDPRCFeedEngine.php', + 'RCFeedFormatter' => 'includes/rcfeed/RCFeedFormatter.php', + 'IRCColourfulRCFeedFormatter' => 'includes/rcfeed/IRCColourfulRCFeedFormatter.php', + 'JSONRCFeedFormatter' => 'includes/rcfeed/JSONRCFeedFormatter.php', # includes/resourceloader 'ResourceLoader' => 'includes/resourceloader/ResourceLoader.php', 'ResourceLoaderContext' => 'includes/resourceloader/ResourceLoaderContext.php', 'ResourceLoaderFileModule' => 'includes/resourceloader/ResourceLoaderFileModule.php', 'ResourceLoaderFilePageModule' => 'includes/resourceloader/ResourceLoaderFilePageModule.php', + 'ResourceLoaderLESSFunctions' => 'includes/resourceloader/ResourceLoaderLESSFunctions.php', 'ResourceLoaderModule' => 'includes/resourceloader/ResourceLoaderModule.php', 'ResourceLoaderNoscriptModule' => 'includes/resourceloader/ResourceLoaderNoscriptModule.php', 'ResourceLoaderSiteModule' => 'includes/resourceloader/ResourceLoaderSiteModule.php', @@ -874,7 +910,6 @@ $wgAutoloadLocalClasses = array( 'SearchResultTooMany' => 'includes/search/SearchEngine.php', 'SearchSqlite' => 'includes/search/SearchSqlite.php', 'SearchUpdate' => 'includes/search/SearchUpdate.php', - 'SearchUpdateMyISAM' => 'includes/search/SearchUpdate.php', 'SqliteSearchResultSet' => 'includes/search/SearchSqlite.php', 'SqlSearchResultSet' => 'includes/search/SearchEngine.php', @@ -899,7 +934,6 @@ $wgAutoloadLocalClasses = array( 'DeadendPagesPage' => 'includes/specials/SpecialDeadendpages.php', 'DeletedContribsPager' => 'includes/specials/SpecialDeletedContributions.php', 'DeletedContributionsPage' => 'includes/specials/SpecialDeletedContributions.php', - 'DisambiguationsPage' => 'includes/specials/SpecialDisambiguations.php', 'DoubleRedirectsPage' => 'includes/specials/SpecialDoubleRedirects.php', 'EditWatchlistCheckboxSeriesField' => 'includes/specials/SpecialEditWatchlist.php', 'EditWatchlistNormalHTMLForm' => 'includes/specials/SpecialEditWatchlist.php', @@ -940,7 +974,6 @@ $wgAutoloadLocalClasses = array( 'SpecialBlankpage' => 'includes/specials/SpecialBlankpage.php', 'SpecialBlock' => 'includes/specials/SpecialBlock.php', 'SpecialBlockList' => 'includes/specials/SpecialBlockList.php', - 'SpecialBlockme' => 'includes/specials/SpecialBlockme.php', 'SpecialBookSources' => 'includes/specials/SpecialBooksources.php', 'SpecialCachedPage' => 'includes/specials/SpecialCachedPage.php', 'SpecialCategories' => 'includes/specials/SpecialCategories.php', @@ -969,9 +1002,12 @@ $wgAutoloadLocalClasses = array( 'SpecialPrefixindex' => 'includes/specials/SpecialPrefixindex.php', 'SpecialProtectedpages' => 'includes/specials/SpecialProtectedpages.php', 'SpecialProtectedtitles' => 'includes/specials/SpecialProtectedtitles.php', + 'SpecialRandomInCategory' => 'includes/specials/SpecialRandomInCategory.php', 'SpecialRandomredirect' => 'includes/specials/SpecialRandomredirect.php', 'SpecialRecentChanges' => 'includes/specials/SpecialRecentchanges.php', 'SpecialRecentchangeslinked' => 'includes/specials/SpecialRecentchangeslinked.php', + 'SpecialRedirect' => 'includes/specials/SpecialRedirect.php', + 'SpecialResetTokens' => 'includes/specials/SpecialResetTokens.php', 'SpecialRevisionDelete' => 'includes/specials/SpecialRevisiondelete.php', 'SpecialSearch' => 'includes/specials/SpecialSearch.php', 'SpecialSpecialpages' => 'includes/specials/SpecialSpecialpages.php', @@ -1021,6 +1057,7 @@ $wgAutoloadLocalClasses = array( 'UploadFromUrl' => 'includes/upload/UploadFromUrl.php', 'UploadStash' => 'includes/upload/UploadStash.php', 'UploadStashBadPathException' => 'includes/upload/UploadStash.php', + 'UploadStashException' => 'includes/upload/UploadStash.php', 'UploadStashFile' => 'includes/upload/UploadStash.php', 'UploadStashFileException' => 'includes/upload/UploadStash.php', 'UploadStashFileNotFoundException' => 'includes/upload/UploadStash.php', @@ -1091,17 +1128,10 @@ $wgAutoloadLocalClasses = array( 'CologneBlueTemplate' => 'skins/CologneBlue.php', 'ModernTemplate' => 'skins/Modern.php', 'MonoBookTemplate' => 'skins/MonoBook.php', - 'NostalgiaTemplate' => 'skins/Nostalgia.php', - 'SkinChick' => 'skins/Chick.php', 'SkinCologneBlue' => 'skins/CologneBlue.php', 'SkinModern' => 'skins/Modern.php', 'SkinMonoBook' => 'skins/MonoBook.php', - 'SkinMySkin' => 'skins/MySkin.php', - 'SkinNostalgia' => 'skins/Nostalgia.php', - 'SkinSimple' => 'skins/Simple.php', - 'SkinStandard' => 'skins/Standard.php', 'SkinVector' => 'skins/Vector.php', - 'StandardTemplate' => 'skins/Standard.php', 'VectorTemplate' => 'skins/Vector.php', ); @@ -1117,12 +1147,13 @@ class AutoLoader { static function autoload( $className ) { global $wgAutoloadClasses, $wgAutoloadLocalClasses; - // Workaround for PHP bug (5.3.2. is broken, it's fixed in 5.3.6). - // Strip leading backslashes from class names. When namespaces are used, leading backslashes are used to indicate - // the top-level namespace, e.g. \foo\Bar. When used like this in the code, the leading backslash isn't passed to - // the auto-loader ($className would be 'foo\Bar'). However, if a class is accessed using a string instead of a - // class literal (e.g. $class = '\foo\Bar'; new $class()), then some versions of PHP do not strip the leading - // backlash in this case, causing autoloading to fail. + // Workaround for PHP bug (5.3.2. is broken, it's + // fixed in 5.3.6). Strip leading backslashes from class names. When namespaces are used, + // leading backslashes are used to indicate the top-level namespace, e.g. \foo\Bar. When + // used like this in the code, the leading backslash isn't passed to the auto-loader + // ($className would be 'foo\Bar'). However, if a class is accessed using a string instead + // of a class literal (e.g. $class = '\foo\Bar'; new $class()), then some versions of PHP + // do not strip the leading backlash in this case, causing autoloading to fail. $className = ltrim( $className, '\\' ); if ( isset( $wgAutoloadLocalClasses[$className] ) ) { @@ -1157,7 +1188,7 @@ class AutoLoader { $filename = "$IP/$filename"; } - require( $filename ); + require $filename; return true; } @@ -1175,12 +1206,4 @@ class AutoLoader { } } -if ( function_exists( 'spl_autoload_register' ) ) { - spl_autoload_register( array( 'AutoLoader', 'autoload' ) ); -} else { - function __autoload( $class ) { - AutoLoader::autoload( $class ); - } - - ini_set( 'unserialize_callback_func', '__autoload' ); -} +spl_autoload_register( array( 'AutoLoader', 'autoload' ) ); diff --git a/includes/Autopromote.php b/includes/Autopromote.php index 604b9248..170d7abf 100644 --- a/includes/Autopromote.php +++ b/includes/Autopromote.php @@ -126,7 +126,8 @@ class Autopromote { return false; } elseif ( $cond[0] == '^' ) { // XOR (exactly one cond passes) if ( count( $cond ) > 3 ) { - wfWarn( 'recCheckCondition() given XOR ("^") condition on three or more conditions. Check your $wgAutopromote and $wgAutopromoteOnce settings.' ); + wfWarn( 'recCheckCondition() given XOR ("^") condition on three or more conditions.' . + ' Check your $wgAutopromote and $wgAutopromoteOnce settings.' ); } return self::recCheckCondition( $cond[1], $user ) xor self::recCheckCondition( $cond[2], $user ); @@ -165,7 +166,7 @@ class Autopromote { return false; } - switch( $cond[0] ) { + switch ( $cond[0] ) { case APCOND_EMAILCONFIRMED: if ( Sanitizer::validateEmail( $user->getEmail() ) ) { if ( $wgEmailAuthentication ) { diff --git a/includes/Block.php b/includes/Block.php index 7ee36ce9..34b89e73 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" ); } @@ -206,16 +206,16 @@ class Block { */ 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; @@ -237,7 +237,7 @@ class Block { 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 ), ); @@ -247,9 +247,9 @@ 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 ) { + switch ( $type ) { case self::TYPE_USER: # Slightly weird, but who are we to argue? $conds['ipb_address'][] = (string)$target; @@ -285,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 ); @@ -313,14 +313,14 @@ class Block { $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; @@ -511,7 +511,7 @@ class Block { * @return Array */ protected function getDatabaseArray( $db = null ) { - if( !$db ) { + if ( !$db ) { $db = wfGetDB( DB_SLAVE ); } $expiry = $db->encodeExpiry( $this->mExpiry ); @@ -579,7 +579,7 @@ class Block { global $wgPutIPinRC; // No IPs are in recentchanges table, so nothing to select - if( !$wgPutIPinRC ) { + if ( !$wgPutIPinRC ) { return; } @@ -601,7 +601,9 @@ class Block { foreach ( $res as $row ) { if ( $row->rc_ip ) { $id = $block->doAutoblock( $row->rc_ip ); - if ( $id ) $blockIds[] = $id; + if ( $id ) { + $blockIds[] = $id; + } } } } @@ -681,7 +683,7 @@ class Block { if ( $ipblock ) { # Check if the block is an autoblock and would exceed the user block # if renewed. If so, do nothing, otherwise prolong the block time... - if ( $ipblock->mAuto && // @TODO: why not compare $ipblock->mExpiry? + if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry? $this->mExpiry > Block::getAutoblockExpiry( $ipblock->mTimestamp ) ) { # Reset block timestamp to now and its expiry to @@ -793,7 +795,7 @@ class Block { * @return String IP in Hex form */ public function getRangeStart() { - switch( $this->type ) { + switch ( $this->type ) { case self::TYPE_USER: return ''; case self::TYPE_IP: @@ -801,17 +803,18 @@ class Block { case self::TYPE_RANGE: list( $start, /*...*/ ) = IP::parseRange( $this->target ); return $start; - default: throw new MWException( "Block with invalid type" ); + default: + throw new MWException( "Block with invalid type" ); } } /** - * Get the IP address at the start of the range in Hex form + * Get the IP address at the end of the range in Hex form * @throws MWException * @return String IP in Hex form */ public function getRangeEnd() { - switch( $this->type ) { + switch ( $this->type ) { case self::TYPE_USER: return ''; case self::TYPE_IP: @@ -819,7 +822,8 @@ class Block { case self::TYPE_RANGE: list( /*...*/, $end ) = IP::parseRange( $this->target ); return $end; - default: throw new MWException( "Block with invalid type" ); + default: + throw new MWException( "Block with invalid type" ); } } @@ -907,7 +911,7 @@ class Block { * @return Bool */ public function prevents( $action, $x = null ) { - switch( $action ) { + switch ( $action ) { case 'edit': # For now... return true; @@ -997,11 +1001,16 @@ class Block { * Purge expired blocks from the ipblocks table */ public static function purgeExpired() { - if ( !wfReadOnly() ) { - $dbw = wfGetDB( DB_MASTER ); - $dbw->delete( 'ipblocks', - array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ ); + if ( wfReadOnly() ) { + return; } + + $method = __METHOD__; + $dbw = wfGetDB( DB_MASTER ); + $dbw->onTransactionIdle( function() use ( $dbw, $method ) { + $dbw->delete( 'ipblocks', + array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), $method ); + } ); } /** @@ -1050,30 +1059,216 @@ 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, null ) ) ) { + } 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; } } return null; } + + /** + * Get all blocks that match any IP from an array of IP addresses + * + * @param Array $ipChain list of IPs (strings), usually retrieved from the + * X-Forwarded-For header of the request + * @param Bool $isAnon Exclude anonymous-only blocks if false + * @param Bool $fromMaster Whether to query the master or slave database + * @return Array of Blocks + * @since 1.22 + */ + public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) { + if ( !count( $ipChain ) ) { + return array(); + } + + wfProfileIn( __METHOD__ ); + $conds = array(); + foreach ( array_unique( $ipChain ) as $ipaddr ) { + # Discard invalid IP addresses. Since XFF can be spoofed and we do not + # necessarily trust the header given to us, make sure that we are only + # checking for blocks on well-formatted IP addresses (IPv4 and IPv6). + # Do not treat private IP spaces as special as it may be desirable for wikis + # to block those IP ranges in order to stop misbehaving proxies that spoof XFF. + if ( !IP::isValid( $ipaddr ) ) { + continue; + } + # Don't check trusted IPs (includes local squids which will be in every request) + if ( wfIsTrustedProxy( $ipaddr ) ) { + continue; + } + # Check both the original IP (to check against single blocks), as well as build + # the clause to check for rangeblocks for the given IP. + $conds['ipb_address'][] = $ipaddr; + $conds[] = self::getRangeCond( IP::toHex( $ipaddr ) ); + } + + if ( !count( $conds ) ) { + wfProfileOut( __METHOD__ ); + return array(); + } + + if ( $fromMaster ) { + $db = wfGetDB( DB_MASTER ); + } else { + $db = wfGetDB( DB_SLAVE ); + } + $conds = $db->makeList( $conds, LIST_OR ); + if ( !$isAnon ) { + $conds = array( $conds, 'ipb_anon_only' => 0 ); + } + $selectFields = array_merge( + array( 'ipb_range_start', 'ipb_range_end' ), + Block::selectFields() + ); + $rows = $db->select( 'ipblocks', + $selectFields, + $conds, + __METHOD__ + ); + + $blocks = array(); + foreach ( $rows as $row ) { + $block = self::newFromRow( $row ); + if ( !$block->deleteIfExpired() ) { + $blocks[] = $block; + } + } + + wfProfileOut( __METHOD__ ); + return $blocks; + } + + /** + * From a list of multiple blocks, find the most exact and strongest Block. + * The logic for finding the "best" block is: + * - Blocks that match the block's target IP are preferred over ones in a range + * - Hardblocks are chosen over softblocks that prevent account creation + * - Softblocks that prevent account creation are chosen over other softblocks + * - Other softblocks are chosen over autoblocks + * - If there are multiple exact or range blocks at the same level, the one chosen + * is random + + * @param Array $ipChain list of IPs (strings). This is used to determine how "close" + * a block is to the server, and if a block matches exactly, or is in a range. + * The order is furthest from the server to nearest e.g., (Browser, proxy1, proxy2, + * local-squid, ...) + * @param Array $block Array of blocks + * @return Block|null the "best" block from the list + */ + public static function chooseBlock( array $blocks, array $ipChain ) { + if ( !count( $blocks ) ) { + return null; + } elseif ( count( $blocks ) == 1 ) { + return $blocks[0]; + } + + wfProfileIn( __METHOD__ ); + + // Sort hard blocks before soft ones and secondarily sort blocks + // that disable account creation before those that don't. + usort( $blocks, function( Block $a, Block $b ) { + $aWeight = (int)$a->isHardblock() . (int)$a->prevents( 'createaccount' ); + $bWeight = (int)$b->isHardblock() . (int)$b->prevents( 'createaccount' ); + return strcmp( $bWeight, $aWeight ); // highest weight first + } ); + + $blocksListExact = array( + 'hard' => false, + 'disable_create' => false, + 'other' => false, + 'auto' => false + ); + $blocksListRange = array( + 'hard' => false, + 'disable_create' => false, + 'other' => false, + 'auto' => false + ); + $ipChain = array_reverse( $ipChain ); + + foreach ( $blocks as $block ) { + // Stop searching if we have already have a "better" block. This + // is why the order of the blocks matters + if ( !$block->isHardblock() && $blocksListExact['hard'] ) { + break; + } elseif ( !$block->prevents( 'createaccount' ) && $blocksListExact['disable_create'] ) { + break; + } + + foreach ( $ipChain as $checkip ) { + $checkipHex = IP::toHex( $checkip ); + if ( (string)$block->getTarget() === $checkip ) { + if ( $block->isHardblock() ) { + $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block; + } elseif ( $block->prevents( 'createaccount' ) ) { + $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block; + } elseif ( $block->mAuto ) { + $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block; + } else { + $blocksListExact['other'] = $blocksListExact['other'] ?: $block; + } + // We found closest exact match in the ip list, so go to the next Block + break; + } elseif ( array_filter( $blocksListExact ) == array() + && $block->getRangeStart() <= $checkipHex + && $block->getRangeEnd() >= $checkipHex + ) { + if ( $block->isHardblock() ) { + $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block; + } elseif ( $block->prevents( 'createaccount' ) ) { + $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block; + } elseif ( $block->mAuto ) { + $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block; + } else { + $blocksListRange['other'] = $blocksListRange['other'] ?: $block; + } + break; + } + } + } + + if ( array_filter( $blocksListExact ) == array() ) { + $blocksList = &$blocksListRange; + } else { + $blocksList = &$blocksListExact; + } + + $chosenBlock = null; + if ( $blocksList['hard'] ) { + $chosenBlock = $blocksList['hard']; + } elseif ( $blocksList['disable_create'] ) { + $chosenBlock = $blocksList['disable_create']; + } elseif ( $blocksList['other'] ) { + $chosenBlock = $blocksList['other']; + } elseif ( $blocksList['auto'] ) { + $chosenBlock = $blocksList['auto']; + } else { + wfProfileOut( __METHOD__ ); + throw new MWException( "Proxy block found, but couldn't be classified." ); + } + + wfProfileOut( __METHOD__ ); + return $chosenBlock; + } + /** * 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 @@ -1085,13 +1280,13 @@ class Block { */ 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 ); } @@ -1112,7 +1307,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]; @@ -1198,4 +1393,43 @@ class Block { public function setBlocker( $user ) { $this->blocker = $user; } + + /** + * Get the key and parameters for the corresponding error message. + * + * @since 1.22 + * @param IContextSource $context + * @return array + */ + public function getPermissionsError( IContextSource $context ) { + $blocker = $this->getBlocker(); + if ( $blocker instanceof User ) { // local user + $blockerUserpage = $blocker->getUserPage(); + $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]"; + } else { // foreign user + $link = $blocker; + } + + $reason = $this->mReason; + if ( $reason == '' ) { + $reason = $context->msg( 'blockednoreason' )->text(); + } + + /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked. + * This could be a username, an IP range, or a single IP. */ + $intended = $this->getTarget(); + + $lang = $context->getLanguage(); + return array( + $this->mAuto ? 'autoblockedtext' : 'blockedtext', + $link, + $reason, + $context->getRequest()->getIP(), + $this->getByName(), + $this->getId(), + $lang->formatExpiry( $this->mExpiry ), + (string)$intended, + $lang->timeanddate( wfTimestamp( TS_MW, $this->mTimestamp ), true ), + ); + } } diff --git a/includes/CallableUpdate.php b/includes/CallableUpdate.php new file mode 100644 index 00000000..6eb55413 --- /dev/null +++ b/includes/CallableUpdate.php @@ -0,0 +1,30 @@ +callback = $callback; + } + + /** + * Run the update + */ + public function doUpdate() { + call_user_func( $this->callback ); + } + +} diff --git a/includes/Category.php b/includes/Category.php index 868d6c46..126b8fee 100644 --- a/includes/Category.php +++ b/includes/Category.php @@ -40,7 +40,8 @@ class Category { /** Counts of membership (cat_pages, cat_subcats, cat_files) */ private $mPages = null, $mSubcats = null, $mFiles = null; - private function __construct() { } + private function __construct() { + } /** * Set up all member variables using a database query. diff --git a/includes/CategoryPage.php b/includes/CategoryPage.php index 43ab4dbd..ba71aa01 100644 --- a/includes/CategoryPage.php +++ b/includes/CategoryPage.php @@ -106,7 +106,13 @@ class CategoryPage extends Article { unset( $reqArray["from"] ); unset( $reqArray["to"] ); - $viewer = new $this->mCategoryViewerClass( $this->getContext()->getTitle(), $this->getContext(), $from, $until, $reqArray ); + $viewer = new $this->mCategoryViewerClass( + $this->getContext()->getTitle(), + $this->getContext(), + $from, + $until, + $reqArray + ); $this->getContext()->getOutput()->addHTML( $viewer->getHTML() ); } } diff --git a/includes/CategoryViewer.php b/includes/CategoryViewer.php index 970adb53..55d9c1e5 100644 --- a/includes/CategoryViewer.php +++ b/includes/CategoryViewer.php @@ -141,8 +141,17 @@ class CategoryViewer extends ContextSource { $this->children = array(); $this->children_start_char = array(); if ( $this->showGallery ) { - $this->gallery = new ImageGallery(); + // Note that null for mode is taken to mean use default. + $mode = $this->getRequest()->getVal( 'gallerymode', null ); + try { + $this->gallery = ImageGalleryBase::factory( $mode ); + } catch ( MWException $e ) { + // User specified something invalid, fallback to default. + $this->gallery = ImageGalleryBase::factory(); + } + $this->gallery->setHideBadImages(); + $this->gallery->setContext( $this->getContext() ); } else { $this->imgsNoGallery = array(); $this->imgsNoGallery_start_char = array(); @@ -526,7 +535,10 @@ class CategoryViewer extends ContextSource { $first = true; foreach ( $colContents as $char => $articles ) { - $ret .= '

' . htmlspecialchars( $char ); + # Change space to non-breaking space to keep headers aligned + $h3char = $char === ' ' ? ' ' : htmlspecialchars( $char ); + + $ret .= '

' . $h3char; if ( $first && $char === $prevchar ) { # We're continuing a previous chunk at the top of a new # column, so add " cont." after the letter. @@ -645,28 +657,23 @@ class CategoryViewer extends ContextSource { * returned? This function says what. Each type is considered independently * of the other types. * - * Note for grepping: uses the messages category-article-count, - * category-article-count-limited, category-subcat-count, - * category-subcat-count-limited, category-file-count, - * category-file-count-limited. - * * @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. + * @return string: A message giving the number of items, to output to HTML. */ private function getCountMessage( $rescnt, $dbcnt, $type ) { - # There are three cases: - # 1) The category table figure seems sane. It might be wrong, but - # we can't do anything about it if we don't recalculate it on ev- - # ery category view. - # 2) The category table figure isn't sane, like it's smaller than the - # number of actual results, *but* the number of results is less - # than $this->limit and there's no offset. In this case we still - # know the right figure. - # 3) We have no idea. - - # Check if there's a "from" or "until" for anything + // There are three cases: + // 1) The category table figure seems sane. It might be wrong, but + // we can't do anything about it if we don't recalculate it on ev- + // ery category view. + // 2) The category table figure isn't sane, like it's smaller than the + // number of actual results, *but* the number of results is less + // than $this->limit and there's no offset. In this case we still + // know the right figure. + // 3) We have no idea. + + // Check if there's a "from" or "until" for anything // This is a little ugly, but we seem to use different names // for the paging types then for the messages. @@ -686,19 +693,22 @@ class CategoryViewer extends ContextSource { if ( $dbcnt == $rescnt || ( ( $rescnt == $this->limit || $fromOrUntil ) && $dbcnt > $rescnt ) ) { - # Case 1: seems sane. + // Case 1: seems sane. $totalcnt = $dbcnt; } elseif ( $rescnt < $this->limit && !$fromOrUntil ) { - # Case 2: not sane, but salvageable. Use the number of results. - # Since there are fewer than 200, we can also take this opportunity - # to refresh the incorrect category table entry -- which should be - # quick due to the small number of entries. + // Case 2: not sane, but salvageable. Use the number of results. + // Since there are fewer than 200, we can also take this opportunity + // to refresh the incorrect category table entry -- which should be + // quick due to the small number of entries. $totalcnt = $rescnt; $this->cat->refreshCounts(); } else { - # Case 3: hopeless. Don't give a total count at all. + // Case 3: hopeless. Don't give a total count at all. + // Messages: category-subcat-count-limited, category-article-count-limited, + // category-file-count-limited return $this->msg( "category-$type-count-limited" )->numParams( $rescnt )->parseAsBlock(); } + // Messages: category-subcat-count, category-article-count, category-file-count return $this->msg( "category-$type-count" )->numParams( $rescnt, $totalcnt )->parseAsBlock(); } } diff --git a/includes/Cdb.php b/includes/Cdb.php index a142c7cb..81c0afe1 100644 --- a/includes/Cdb.php +++ b/includes/Cdb.php @@ -133,7 +133,7 @@ class CdbReader_DBA { } function close() { - if( isset( $this->handle ) ) { + if ( isset( $this->handle ) ) { dba_close( $this->handle ); } unset( $this->handle ); @@ -164,7 +164,7 @@ class CdbWriter_DBA { } function close() { - if( isset( $this->handle ) ) { + if ( isset( $this->handle ) ) { dba_close( $this->handle ); } if ( wfIsWindows() ) { diff --git a/includes/Cdb_PHP.php b/includes/Cdb_PHP.php index 71b55f87..a38b9a86 100644 --- a/includes/Cdb_PHP.php +++ b/includes/Cdb_PHP.php @@ -73,10 +73,10 @@ class CdbFunctions { public static function hash( $s ) { $h = 5381; for ( $i = 0; $i < strlen( $s ); $i++ ) { - $h5 = ($h << 5) & 0xffffffff; + $h5 = ( $h << 5 ) & 0xffffffff; // Do a 32-bit sum // Inlined here for speed - $sum = ($h & 0x3fffffff) + ($h5 & 0x3fffffff); + $sum = ( $h & 0x3fffffff ) + ( $h5 & 0x3fffffff ); $h = ( ( $sum & 0x40000000 ? 1 : 0 ) @@ -138,7 +138,7 @@ class CdbReader_PHP extends CdbReader { } function close() { - if( isset( $this->handle ) ) { + if ( isset( $this->handle ) ) { fclose( $this->handle ); } unset( $this->handle ); @@ -332,7 +332,7 @@ 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 ) ) { @@ -411,7 +411,7 @@ class CdbWriter_PHP extends CdbWriter { // Calculate the number of items that will be in each hashtable $counts = array_fill( 0, 256, 0 ); foreach ( $this->hplist as $item ) { - ++ $counts[ 255 & $item['h'] ]; + ++ $counts[255 & $item['h']]; } // Fill in $starts with the *end* indexes @@ -450,9 +450,11 @@ class CdbWriter_PHP extends CdbWriter { $hp = $packedTables[$starts[$i] + $u]; $where = CdbFunctions::unsignedMod( CdbFunctions::unsignedShiftRight( $hp['h'], 8 ), $len ); - while ( $hashtable[$where]['p'] ) - if ( ++$where == $len ) + while ( $hashtable[$where]['p'] ) { + if ( ++$where == $len ) { $where = 0; + } + } $hashtable[$where] = $hp; } diff --git a/includes/ChangeTags.php b/includes/ChangeTags.php index 3adf58f8..3fc27f9a 100644 --- a/includes/ChangeTags.php +++ b/includes/ChangeTags.php @@ -34,17 +34,18 @@ class ChangeTags { * - classes: Array of strings: CSS classes used in the generated html, one class for each tag * */ - static function formatSummaryRow( $tags, $page ) { + public static function formatSummaryRow( $tags, $page ) { global $wgLang; - if( !$tags ) + if ( !$tags ) { return array( '', array() ); + } $classes = array(); $tags = explode( ',', $tags ); $displayTags = array(); - foreach( $tags as $tag ) { + foreach ( $tags as $tag ) { $displayTags[] = Xml::tags( 'span', array( 'class' => 'mw-tag-marker ' . @@ -53,7 +54,10 @@ class ChangeTags { ); $classes[] = Sanitizer::escapeClass( "mw-tag-$tag" ); } - $markers = wfMessage( 'parentheses' )->rawParams( $wgLang->commaList( $displayTags ) )->text(); + $markers = wfMessage( 'tag-list-wrapper' ) + ->numParams( count( $displayTags ) ) + ->rawParams( $wgLang->commaList( $displayTags ) ) + ->parse(); $markers = Xml::tags( 'span', array( 'class' => 'mw-tag-markers' ), $markers ); return array( $markers, $classes ); @@ -67,7 +71,7 @@ class ChangeTags { * @return String: Short description of the tag from "mediawiki:tag-$tag" if this message exists, * html-escaped version of $tag otherwise */ - static function tagDescription( $tag ) { + public static function tagDescription( $tag ) { $msg = wfMessage( "tag-$tag" ); return $msg->exists() ? $msg->parse() : htmlspecialchars( $tag ); } @@ -86,28 +90,29 @@ class ChangeTags { * * @exception MWException when $rc_id, $rev_id and $log_id are all null */ - static function addTags( $tags, $rc_id = null, $rev_id = null, $log_id = null, $params = null ) { + public static function addTags( $tags, $rc_id = null, $rev_id = null, $log_id = null, $params = null ) { if ( !is_array( $tags ) ) { $tags = array( $tags ); } $tags = array_filter( $tags ); // Make sure we're submitting all tags... - if( !$rc_id && !$rev_id && !$log_id ) { - throw new MWException( "At least one of: RCID, revision ID, and log ID MUST be specified when adding a tag to a change!" ); + if ( !$rc_id && !$rev_id && !$log_id ) { + throw new MWException( 'At least one of: RCID, revision ID, and log ID MUST be ' . + 'specified when adding a tag to a change!' ); } $dbr = wfGetDB( DB_SLAVE ); // Might as well look for rcids and so on. - if( !$rc_id ) { + if ( !$rc_id ) { $dbr = wfGetDB( DB_MASTER ); // Info might be out of date, somewhat fractionally, on slave. - if( $log_id ) { + if ( $log_id ) { $rc_id = $dbr->selectField( 'recentchanges', 'rc_id', array( 'rc_logid' => $log_id ), __METHOD__ ); - } elseif( $rev_id ) { + } elseif ( $rev_id ) { $rc_id = $dbr->selectField( 'recentchanges', 'rc_id', array( 'rc_this_oldid' => $rev_id ), __METHOD__ ); } - } elseif( !$log_id && !$rev_id ) { + } elseif ( !$log_id && !$rev_id ) { $dbr = wfGetDB( DB_MASTER ); // Info might be out of date, somewhat fractionally, on slave. $log_id = $dbr->selectField( 'recentchanges', 'rc_logid', array( 'rc_id' => $rc_id ), __METHOD__ ); $rev_id = $dbr->selectField( 'recentchanges', 'rc_this_oldid', array( 'rc_id' => $rc_id ), __METHOD__ ); @@ -138,7 +143,7 @@ class ChangeTags { // Insert the tags rows. $tagsRows = array(); - foreach( $tags as $tag ) { // Filter so we don't insert NULLs as zero accidentally. + foreach ( $tags as $tag ) { // Filter so we don't insert NULLs as zero accidentally. $tagsRows[] = array_filter( array( 'ct_tag' => $tag, @@ -169,18 +174,18 @@ class ChangeTags { * * @throws MWException When unable to determine appropriate JOIN condition for tagging */ - static function modifyDisplayQuery( &$tables, &$fields, &$conds, + public static function modifyDisplayQuery( &$tables, &$fields, &$conds, &$join_conds, &$options, $filter_tag = false ) { global $wgRequest, $wgUseTagFilter; - if( $filter_tag === false ) { + if ( $filter_tag === false ) { $filter_tag = $wgRequest->getVal( 'tagfilter' ); } // Figure out which conditions can be done. if ( in_array( 'recentchanges', $tables ) ) { $join_cond = 'rc_id'; - } elseif( in_array( 'logging', $tables ) ) { + } elseif ( in_array( 'logging', $tables ) ) { $join_cond = 'log_id'; } elseif ( in_array( 'revision', $tables ) ) { $join_cond = 'rev_id'; @@ -193,14 +198,12 @@ class ChangeTags { $join_conds['tag_summary'] = array( 'LEFT JOIN', "ts_$join_cond=$join_cond" ); $fields[] = 'ts_tags'; - if( $wgUseTagFilter && $filter_tag ) { + if ( $wgUseTagFilter && $filter_tag ) { // Somebody wants to filter on a tag. // Add an INNER JOIN on change_tag // FORCE INDEX -- change_tags will almost ALWAYS be the correct query plan. - global $wgOldChangeTagsIndex; - $index = $wgOldChangeTagsIndex ? 'ct_tag' : 'change_tag_tag_id'; - $options['USE INDEX'] = array( 'change_tag' => $index ); + $options['USE INDEX'] = array( 'change_tag' => 'change_tag_tag_id' ); unset( $options['FORCE INDEX'] ); $tables[] = 'change_tag'; $join_conds['change_tag'] = array( 'INNER JOIN', "ct_$join_cond=$join_cond" ); @@ -252,7 +255,7 @@ class ChangeTags { * * @return Array of strings: tags */ - static function listDefinedTags() { + public static function listDefinedTags() { // Caching... global $wgMemc; $key = wfMemcKey( 'valid-tags' ); @@ -278,4 +281,34 @@ class ChangeTags { $wgMemc->set( $key, $emptyTags, 300 ); return $emptyTags; } + + /** + * Returns a map of any tags used on the wiki to number of edits + * tagged with them, ordered descending by the hitcount. + * + * @return array Array of string => int + */ + public static function tagUsageStatistics() { + $out = array(); + + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( + 'change_tag', + array( 'ct_tag', 'hitcount' => 'count(*)' ), + array(), + __METHOD__, + array( 'GROUP BY' => 'ct_tag', 'ORDER BY' => 'hitcount DESC' ) + ); + + foreach ( $res as $row ) { + $out[$row->ct_tag] = $row->hitcount; + } + foreach ( self::listDefinedTags() as $tag ) { + if ( !isset( $out[$tag] ) ) { + $out[$tag] = 0; + } + } + + return $out; + } } diff --git a/includes/ChangesFeed.php b/includes/ChangesFeed.php index 476de5bd..0736c507 100644 --- a/includes/ChangesFeed.php +++ b/includes/ChangesFeed.php @@ -54,7 +54,7 @@ class ChangesFeed { return false; } - if( !array_key_exists( $this->format, $wgFeedClasses ) ) { + if ( !array_key_exists( $this->format, $wgFeedClasses ) ) { // falling back to atom $this->format = 'atom'; } @@ -92,7 +92,7 @@ class ChangesFeed { * gets it quick too. */ $cachedFeed = $this->loadFromCache( $lastmod, $timekey, $key ); - if( is_string( $cachedFeed ) ) { + if ( is_string( $cachedFeed ) ) { wfDebug( "RC: Outputting cached feed\n" ); $feed->httpHeaders(); echo $cachedFeed; @@ -134,7 +134,7 @@ class ChangesFeed { $feedLastmod = $messageMemc->get( $timekey ); - if( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) { + 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 @@ -146,7 +146,7 @@ class ChangesFeed { $feedLastmodUnix = wfTimestamp( TS_UNIX, $feedLastmod ); $lastmodUnix = wfTimestamp( TS_UNIX, $lastmod ); - if( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix) { + if ( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix ) { wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" ); if ( $feedLastmodUnix < $lastmodUnix ) { $wgOut->setLastModified( $feedLastmod ); // bug 21916 @@ -172,30 +172,32 @@ class ChangesFeed { # Merge adjacent edits by one user $sorted = array(); $n = 0; - foreach( $rows as $obj ) { - if( $n > 0 && + foreach ( $rows as $obj ) { + if ( $n > 0 && $obj->rc_type == RC_EDIT && $obj->rc_namespace >= 0 && - $obj->rc_cur_id == $sorted[$n-1]->rc_cur_id && - $obj->rc_user_text == $sorted[$n-1]->rc_user_text ) { - $sorted[$n-1]->rc_last_oldid = $obj->rc_last_oldid; + $obj->rc_cur_id == $sorted[$n - 1]->rc_cur_id && + $obj->rc_user_text == $sorted[$n - 1]->rc_user_text ) { + $sorted[$n - 1]->rc_last_oldid = $obj->rc_last_oldid; } else { $sorted[$n] = $obj; $n++; } } - foreach( $sorted as $obj ) { + foreach ( $sorted as $obj ) { $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title ); - $talkpage = MWNamespace::canTalk( $obj->rc_namespace ) ? $title->getTalkPage()->getFullUrl() : ''; + $talkpage = MWNamespace::canTalk( $obj->rc_namespace ) ? $title->getTalkPage()->getFullURL() : ''; // Skip items with deleted content (avoids partially complete/inconsistent output) - if( $obj->rc_deleted ) continue; + if ( $obj->rc_deleted ) { + continue; + } if ( $obj->rc_this_oldid ) { - $url = $title->getFullURL( - 'diff=' . $obj->rc_this_oldid . - '&oldid=' . $obj->rc_last_oldid - ); + $url = $title->getFullURL( array( + 'diff' => $obj->rc_this_oldid, + 'oldid' => $obj->rc_last_oldid, + ) ); } else { // log entry or something like that. $url = $title->getFullURL(); @@ -206,7 +208,8 @@ class ChangesFeed { FeedUtils::formatDiff( $obj ), $url, $obj->rc_timestamp, - ( $obj->rc_deleted & Revision::DELETED_USER ) ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text, + ( $obj->rc_deleted & Revision::DELETED_USER ) + ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text, $talkpage ); $feed->outItem( $item ); diff --git a/includes/ChangesList.php b/includes/ChangesList.php deleted file mode 100644 index 8461001e..00000000 --- a/includes/ChangesList.php +++ /dev/null @@ -1,1304 +0,0 @@ -mAttribs = $rc->mAttribs; - $rc2->mExtra = $rc->mExtra; - return $rc2; - } -} - -/** - * Base class for all changes lists - */ -class ChangesList extends ContextSource { - - /** - * @var Skin - */ - public $skin; - - protected $watchlist = false; - - protected $message; - - /** - * Changeslist constructor - * - * @param $obj Skin or IContextSource - */ - public function __construct( $obj ) { - if ( $obj instanceof IContextSource ) { - $this->setContext( $obj ); - $this->skin = $obj->getSkin(); - } else { - $this->setContext( $obj->getContext() ); - $this->skin = $obj; - } - $this->preCacheMessages(); - } - - /** - * Fetch an appropriate changes list class for the main context - * This first argument used to be an User object. - * - * @deprecated in 1.18; use newFromContext() instead - * @param string|User $unused Unused - * @return ChangesList|EnhancedChangesList|OldChangesList derivative - */ - public static function newFromUser( $unused ) { - wfDeprecated( __METHOD__, '1.18' ); - return self::newFromContext( RequestContext::getMain() ); - } - - /** - * Fetch an appropriate changes list class for the specified context - * Some users might want to use an enhanced list format, for instance - * - * @param $context IContextSource to use - * @return ChangesList|EnhancedChangesList|OldChangesList derivative - */ - public static function newFromContext( IContextSource $context ) { - $user = $context->getUser(); - $sk = $context->getSkin(); - $list = null; - if( wfRunHooks( 'FetchChangesList', array( $user, &$sk, &$list ) ) ) { - $new = $context->getRequest()->getBool( 'enhanced', $user->getOption( 'usenewrc' ) ); - return $new ? new EnhancedChangesList( $context ) : new OldChangesList( $context ); - } else { - return $list; - } - } - - /** - * Sets the list to use a "
  • " tag - * @param $value Boolean - */ - public function setWatchlistDivs( $value = true ) { - $this->watchlist = $value; - } - - /** - * As we use the same small set of messages in various methods and that - * they are called often, we call them once and save them in $this->message - */ - private function preCacheMessages() { - if( !isset( $this->message ) ) { - foreach ( explode( ' ', 'cur diff hist last blocklink history ' . - 'semicolon-separator pipe-separator' ) as $msg ) { - $this->message[$msg] = $this->msg( $msg )->escaped(); - } - } - } - - /** - * Returns the appropriate flags for new page, minor change and patrolling - * @param array $flags Associative array of 'flag' => Bool - * @param string $nothing to use for empty space - * @return String - */ - protected function recentChangesFlags( $flags, $nothing = ' ' ) { - $f = ''; - foreach( array( 'newpage', 'minor', 'bot', 'unpatrolled' ) as $flag ) { - $f .= isset( $flags[$flag] ) && $flags[$flag] - ? self::flag( $flag ) - : $nothing; - } - return $f; - } - - /** - * Provide the "" element appropriate to a given abbreviated flag, - * namely the flag indicating a new page, a minor edit, a bot edit, or an - * unpatrolled edit. By default in English it will contain "N", "m", "b", - * "!" respectively, plus it will have an appropriate title and class. - * - * @param string $flag 'newpage', 'unpatrolled', 'minor', or 'bot' - * @return String: Raw HTML - */ - public static function flag( $flag ) { - static $messages = null; - if ( is_null( $messages ) ) { - $messages = array( - 'newpage' => array( 'newpageletter', 'recentchanges-label-newpage' ), - 'minoredit' => array( 'minoreditletter', 'recentchanges-label-minor' ), - 'botedit' => array( 'boteditletter', 'recentchanges-label-bot' ), - 'unpatrolled' => array( 'unpatrolledletter', 'recentchanges-label-unpatrolled' ), - ); - foreach( $messages as &$value ) { - $value[0] = wfMessage( $value[0] )->escaped(); - $value[1] = wfMessage( $value[1] )->escaped(); - } - } - - # Inconsistent naming, bleh - $map = array( - 'newpage' => 'newpage', - 'minor' => 'minoredit', - 'bot' => 'botedit', - 'unpatrolled' => 'unpatrolled', - 'minoredit' => 'minoredit', - 'botedit' => 'botedit', - ); - $flag = $map[$flag]; - - return "" . $messages[$flag][0] . ''; - } - - /** - * Returns text for the start of the tabular part of RC - * @return String - */ - public function beginRecentChangesList() { - $this->rc_cache = array(); - $this->rcMoveIndex = 0; - $this->rcCacheIndex = 0; - $this->lastdate = ''; - $this->rclistOpen = false; - $this->getOutput()->addModuleStyles( 'mediawiki.special.changeslist' ); - return ''; - } - - /** - * Show formatted char difference - * @param $old Integer: bytes - * @param $new Integer: bytes - * @param $context IContextSource context to use - * @return String - */ - public static function showCharacterDifference( $old, $new, IContextSource $context = null ) { - global $wgRCChangedSizeThreshold, $wgMiserMode; - - if ( !$context ) { - $context = RequestContext::getMain(); - } - - $new = (int)$new; - $old = (int)$old; - $szdiff = $new - $old; - - $lang = $context->getLanguage(); - $code = $lang->getCode(); - static $fastCharDiff = array(); - if ( !isset( $fastCharDiff[$code] ) ) { - $fastCharDiff[$code] = $wgMiserMode || $context->msg( 'rc-change-size' )->plain() === '$1'; - } - - $formattedSize = $lang->formatNum( $szdiff ); - - if ( !$fastCharDiff[$code] ) { - $formattedSize = $context->msg( 'rc-change-size', $formattedSize )->text(); - } - - if( abs( $szdiff ) > abs( $wgRCChangedSizeThreshold ) ) { - $tag = 'strong'; - } else { - $tag = 'span'; - } - - if ( $szdiff === 0 ) { - $formattedSizeClass = 'mw-plusminus-null'; - } - if ( $szdiff > 0 ) { - $formattedSize = '+' . $formattedSize; - $formattedSizeClass = 'mw-plusminus-pos'; - } - if ( $szdiff < 0 ) { - $formattedSizeClass = 'mw-plusminus-neg'; - } - - $formattedTotalSize = $context->msg( 'rc-change-size-new' )->numParams( $new )->text(); - - return Html::element( $tag, - array( 'dir' => 'ltr', 'class' => $formattedSizeClass, 'title' => $formattedTotalSize ), - $context->msg( 'parentheses', $formattedSize )->plain() ) . $lang->getDirMark(); - } - - /** - * Format the character difference of one or several changes. - * - * @param $old RecentChange - * @param $new RecentChange last change to use, if not provided, $old will be used - * @return string HTML fragment - */ - public function formatCharacterDifference( RecentChange $old, RecentChange $new = null ) { - $oldlen = $old->mAttribs['rc_old_len']; - - if ( $new ) { - $newlen = $new->mAttribs['rc_new_len']; - } else { - $newlen = $old->mAttribs['rc_new_len']; - } - - if( $oldlen === null || $newlen === null ) { - return ''; - } - - return self::showCharacterDifference( $oldlen, $newlen, $this->getContext() ); - } - - /** - * Returns text for the end of RC - * @return String - */ - public function endRecentChangesList() { - if( $this->rclistOpen ) { - return "\n"; - } else { - return ''; - } - } - - /** - * @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() ); - if( $date != $this->lastdate ) { - if( $this->lastdate != '' ) { - $s .= "\n"; - } - $s .= Xml::element( 'h4', null, $date ) . "\n