summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2009-02-22 13:37:51 +0100
committerPierre Schmitz <pierre@archlinux.de>2009-02-22 13:37:51 +0100
commitb9b85843572bf283f48285001e276ba7e61b63f6 (patch)
tree4c6f4571552ada9ccfb4030481dcf77308f8b254
parentd9a20acc4e789cca747ad360d87ee3f3e7aa58c1 (diff)
updated to MediaWiki 1.14.0
-rw-r--r--CREDITS90
-rw-r--r--HISTORY651
-rw-r--r--README58
-rw-r--r--RELEASE-NOTES1284
-rw-r--r--UPGRADE5
-rw-r--r--api.php2
-rw-r--r--config/index.php55
-rw-r--r--docs/database.txt4
-rw-r--r--docs/hooks.txt226
-rw-r--r--docs/memcached.txt7
-rw-r--r--docs/php-memcached/Documentation2
-rw-r--r--docs/upload.txt40
-rw-r--r--extensions/LLAuthPlugin.php34
-rw-r--r--img_auth.php2
-rw-r--r--includes/AjaxFunctions.php126
-rw-r--r--includes/AjaxResponse.php6
-rw-r--r--includes/Article.php1829
-rw-r--r--includes/AuthPlugin.php82
-rw-r--r--includes/AutoLoader.php982
-rw-r--r--includes/Autopromote.php9
-rw-r--r--includes/BagOStuff.php13
-rw-r--r--includes/Block.php480
-rw-r--r--includes/Category.php41
-rw-r--r--includes/CategoryPage.php82
-rw-r--r--includes/Categoryfinder.php10
-rw-r--r--includes/ChangesFeed.php7
-rw-r--r--includes/ChangesList.php381
-rw-r--r--includes/Credits.php300
-rw-r--r--includes/DatabaseFunctions.php26
-rw-r--r--includes/DefaultSettings.php563
-rw-r--r--includes/Defines.php20
-rw-r--r--includes/EditPage.php958
-rw-r--r--includes/Exception.php34
-rw-r--r--includes/Exif.php25
-rw-r--r--includes/Export.php288
-rw-r--r--includes/ExternalStore.php47
-rw-r--r--includes/ExternalStoreDB.php11
-rw-r--r--includes/FakeTitle.php23
-rw-r--r--includes/Feed.php44
-rw-r--r--includes/FeedUtils.php17
-rw-r--r--includes/FileDeleteForm.php66
-rw-r--r--includes/FileRevertForm.php6
-rw-r--r--includes/FileStore.php27
-rw-r--r--includes/FormOptions.php4
-rw-r--r--includes/GlobalFunctions.php445
-rw-r--r--includes/HTMLCacheUpdate.php28
-rw-r--r--includes/HTMLFileCache.php116
-rw-r--r--includes/HistoryBlob.php444
-rw-r--r--includes/HttpFunctions.php86
-rw-r--r--includes/IEContentAnalyzer.php7
-rw-r--r--includes/IP.php53
-rw-r--r--includes/ImageFunctions.php100
-rw-r--r--includes/ImageGallery.php2
-rw-r--r--includes/ImagePage.php395
-rw-r--r--includes/ImageQueryPage.php6
-rw-r--r--includes/Import.php1133
-rw-r--r--includes/Interwiki.php207
-rw-r--r--includes/JobQueue.php2
-rw-r--r--includes/Licenses.php2
-rw-r--r--includes/LinkBatch.php2
-rw-r--r--includes/LinkCache.php70
-rw-r--r--includes/Linker.php783
-rw-r--r--includes/LinksUpdate.php73
-rw-r--r--includes/LogEventsList.php468
-rw-r--r--includes/LogPage.php140
-rw-r--r--includes/MagicWord.php8
-rw-r--r--includes/Math.php48
-rw-r--r--includes/MediaTransformOutput.php20
-rw-r--r--includes/MessageCache.php93
-rw-r--r--includes/Metadata.php528
-rw-r--r--includes/MimeMagic.php90
-rw-r--r--includes/Namespace.php14
-rw-r--r--includes/ObjectCache.php23
-rw-r--r--includes/OutputPage.php575
-rw-r--r--includes/PageHistory.php374
-rw-r--r--includes/PageQueryPage.php6
-rw-r--r--includes/Pager.php82
-rw-r--r--includes/PrefixSearch.php19
-rw-r--r--includes/Profiler.php5
-rw-r--r--includes/ProtectionForm.php409
-rw-r--r--includes/ProxyTools.php58
-rw-r--r--includes/QueryPage.php23
-rw-r--r--includes/RawPage.php62
-rw-r--r--includes/RecentChange.php327
-rw-r--r--includes/RefreshLinksJob.php84
-rw-r--r--includes/Revision.php174
-rw-r--r--includes/Sanitizer.php121
-rw-r--r--includes/SearchEngine.php138
-rw-r--r--includes/SearchMySQL.php16
-rw-r--r--includes/SearchOracle.php14
-rw-r--r--includes/SearchPostgres.php10
-rw-r--r--includes/Setup.php42
-rw-r--r--includes/SiteConfiguration.php341
-rw-r--r--includes/SiteStats.php88
-rw-r--r--includes/Skin.php483
-rw-r--r--includes/SkinTemplate.php242
-rw-r--r--includes/SpecialPage.php33
-rw-r--r--includes/SquidUpdate.php2
-rw-r--r--includes/StringUtils.php99
-rw-r--r--includes/StubObject.php2
-rw-r--r--includes/Title.php1366
-rw-r--r--includes/TitleArray.php81
-rw-r--r--includes/UploadBase.php867
-rw-r--r--includes/UploadFromStash.php58
-rw-r--r--includes/UploadFromUpload.php20
-rw-r--r--includes/UploadFromUrl.php92
-rw-r--r--includes/User.php1059
-rw-r--r--includes/UserArray.php4
-rw-r--r--includes/UserMailer.php57
-rw-r--r--includes/WatchedItem.php37
-rw-r--r--includes/WatchlistEditor.php76
-rw-r--r--includes/WebRequest.php52
-rw-r--r--includes/WebResponse.php54
-rw-r--r--includes/WebStart.php55
-rw-r--r--includes/Wiki.php139
-rw-r--r--includes/WikiError.php3
-rw-r--r--includes/Xml.php70
-rw-r--r--includes/XmlFunctions.php24
-rw-r--r--includes/XmlTypeCheck.php7
-rw-r--r--includes/ZhConversion.php196
-rw-r--r--includes/api/ApiBase.php148
-rw-r--r--includes/api/ApiBlock.php22
-rw-r--r--includes/api/ApiDelete.php46
-rw-r--r--includes/api/ApiDisabled.php72
-rw-r--r--includes/api/ApiEditPage.php39
-rw-r--r--includes/api/ApiEmailUser.php14
-rw-r--r--includes/api/ApiExpandTemplates.php17
-rw-r--r--includes/api/ApiFormatBase.php10
-rw-r--r--includes/api/ApiFormatJson.php7
-rw-r--r--includes/api/ApiFormatJson_json.php76
-rw-r--r--includes/api/ApiFormatWddx.php58
-rw-r--r--includes/api/ApiFormatXml.php31
-rw-r--r--includes/api/ApiFormatYaml_spyc.php1115
-rw-r--r--includes/api/ApiLogin.php135
-rw-r--r--includes/api/ApiLogout.php5
-rw-r--r--includes/api/ApiMain.php72
-rw-r--r--includes/api/ApiMove.php51
-rw-r--r--includes/api/ApiPageSet.php54
-rw-r--r--includes/api/ApiParamInfo.php16
-rw-r--r--includes/api/ApiParse.php60
-rw-r--r--includes/api/ApiPatrol.php99
-rw-r--r--includes/api/ApiProtect.php83
-rw-r--r--includes/api/ApiPurge.php106
-rw-r--r--includes/api/ApiQuery.php29
-rw-r--r--includes/api/ApiQueryAllCategories.php23
-rw-r--r--includes/api/ApiQueryAllLinks.php29
-rw-r--r--includes/api/ApiQueryAllUsers.php4
-rw-r--r--includes/api/ApiQueryAllimages.php18
-rw-r--r--includes/api/ApiQueryAllpages.php50
-rw-r--r--includes/api/ApiQueryBacklinks.php56
-rw-r--r--includes/api/ApiQueryBase.php48
-rw-r--r--includes/api/ApiQueryBlocks.php42
-rw-r--r--includes/api/ApiQueryCategories.php35
-rw-r--r--includes/api/ApiQueryCategoryInfo.php21
-rw-r--r--includes/api/ApiQueryCategoryMembers.php36
-rw-r--r--includes/api/ApiQueryDeletedrevs.php4
-rw-r--r--includes/api/ApiQueryDisabled.php72
-rw-r--r--includes/api/ApiQueryDuplicateFiles.php164
-rw-r--r--includes/api/ApiQueryExtLinksUsage.php6
-rw-r--r--includes/api/ApiQueryImageInfo.php30
-rw-r--r--includes/api/ApiQueryImages.php8
-rw-r--r--includes/api/ApiQueryInfo.php149
-rw-r--r--includes/api/ApiQueryLangLinks.php4
-rw-r--r--includes/api/ApiQueryLinks.php10
-rw-r--r--includes/api/ApiQueryLogEvents.php103
-rw-r--r--includes/api/ApiQueryRandom.php13
-rw-r--r--includes/api/ApiQueryRecentChanges.php129
-rw-r--r--includes/api/ApiQueryRevisions.php90
-rw-r--r--includes/api/ApiQuerySearch.php37
-rw-r--r--includes/api/ApiQuerySiteinfo.php82
-rw-r--r--includes/api/ApiQueryUserContributions.php39
-rw-r--r--includes/api/ApiQueryUserInfo.php10
-rw-r--r--includes/api/ApiQueryUsers.php39
-rw-r--r--includes/api/ApiQueryWatchlist.php51
-rw-r--r--includes/api/ApiQueryWatchlistRaw.php179
-rw-r--r--includes/api/ApiResult.php17
-rw-r--r--includes/api/ApiRollback.php27
-rw-r--r--includes/api/ApiUnblock.php8
-rw-r--r--includes/api/ApiUndelete.php6
-rw-r--r--includes/api/ApiWatch.php99
-rw-r--r--includes/db/Database.php308
-rw-r--r--includes/db/DatabaseMssql.php59
-rw-r--r--includes/db/DatabaseOracle.php14
-rw-r--r--includes/db/DatabasePostgres.php89
-rw-r--r--includes/db/DatabaseSqlite.php43
-rw-r--r--includes/db/LBFactory_Multi.php14
-rw-r--r--includes/db/LoadBalancer.php77
-rw-r--r--includes/db/LoadMonitor.php3
-rw-r--r--includes/diff/Diff.php580
-rw-r--r--includes/diff/DifferenceEngine.php (renamed from includes/DifferenceEngine.php)666
-rw-r--r--includes/diff/HTMLDiff.php1005
-rw-r--r--includes/diff/Nodes.php439
-rw-r--r--includes/filerepo/ArchivedFile.php44
-rw-r--r--includes/filerepo/FSRepo.php10
-rw-r--r--includes/filerepo/File.php26
-rw-r--r--includes/filerepo/FileCache.php156
-rw-r--r--includes/filerepo/FileRepo.php80
-rw-r--r--includes/filerepo/ForeignAPIFile.php83
-rw-r--r--includes/filerepo/ForeignAPIRepo.php77
-rw-r--r--includes/filerepo/ForeignDBFile.php2
-rw-r--r--includes/filerepo/Image.php2
-rw-r--r--includes/filerepo/LocalFile.php99
-rw-r--r--includes/filerepo/LocalRepo.php7
-rw-r--r--includes/filerepo/OldLocalFile.php3
-rw-r--r--includes/filerepo/RepoGroup.php24
-rw-r--r--includes/filerepo/UnregisteredLocalFile.php2
-rw-r--r--includes/media/BMP.php9
-rw-r--r--includes/media/Bitmap.php36
-rw-r--r--includes/media/Bitmap_ClientOnly.php15
-rw-r--r--includes/media/Generic.php15
-rw-r--r--includes/media/SVG.php40
-rw-r--r--includes/memcached-client.php6
-rw-r--r--includes/mime.types1
-rw-r--r--includes/parser/CoreLinkFunctions.php47
-rw-r--r--includes/parser/CoreParserFunctions.php75
-rw-r--r--includes/parser/LinkHolderArray.php438
-rw-r--r--includes/parser/Parser.php1471
-rw-r--r--includes/parser/ParserCache.php4
-rw-r--r--includes/parser/ParserOptions.php16
-rw-r--r--includes/parser/ParserOutput.php63
-rw-r--r--includes/parser/Parser_DiffTest.php34
-rw-r--r--includes/parser/Parser_LinkHooks.php315
-rw-r--r--includes/parser/Parser_OldPP.php4944
-rw-r--r--includes/parser/Preprocessor_DOM.php41
-rw-r--r--includes/parser/Preprocessor_Hash.php37
-rw-r--r--includes/specials/SpecialAllmessages.php85
-rw-r--r--includes/specials/SpecialAllpages.php717
-rw-r--r--includes/specials/SpecialBlockip.php195
-rw-r--r--includes/specials/SpecialBooksources.php56
-rw-r--r--includes/specials/SpecialCategories.php4
-rw-r--r--includes/specials/SpecialConfirmemail.php22
-rw-r--r--includes/specials/SpecialContributions.php682
-rw-r--r--includes/specials/SpecialDeletedContributions.php369
-rw-r--r--includes/specials/SpecialDisambiguations.php8
-rw-r--r--includes/specials/SpecialEmailuser.php142
-rw-r--r--includes/specials/SpecialExport.php38
-rw-r--r--includes/specials/SpecialFileDuplicateSearch.php6
-rw-r--r--includes/specials/SpecialFilepath.php4
-rw-r--r--includes/specials/SpecialImport.php1202
-rw-r--r--includes/specials/SpecialIpblocklist.php118
-rw-r--r--includes/specials/SpecialLinkSearch.php185
-rw-r--r--includes/specials/SpecialListUserRestrictions.php161
-rw-r--r--includes/specials/SpecialListfiles.php (renamed from includes/specials/SpecialImagelist.php)51
-rw-r--r--includes/specials/SpecialListgrouprights.php25
-rw-r--r--includes/specials/SpecialListredirects.php3
-rw-r--r--includes/specials/SpecialListusers.php68
-rw-r--r--includes/specials/SpecialLockdb.php2
-rw-r--r--includes/specials/SpecialLog.php22
-rw-r--r--includes/specials/SpecialLonelypages.php7
-rw-r--r--includes/specials/SpecialMIMEsearch.php2
-rw-r--r--includes/specials/SpecialMergeHistory.php22
-rw-r--r--includes/specials/SpecialMostcategories.php4
-rw-r--r--includes/specials/SpecialMostimages.php2
-rw-r--r--includes/specials/SpecialMostlinkedtemplates.php19
-rw-r--r--includes/specials/SpecialMovepage.php136
-rw-r--r--includes/specials/SpecialNewimages.php127
-rw-r--r--includes/specials/SpecialNewpages.php57
-rw-r--r--includes/specials/SpecialPreferences.php461
-rw-r--r--includes/specials/SpecialPrefixindex.php139
-rw-r--r--includes/specials/SpecialProtectedpages.php32
-rw-r--r--includes/specials/SpecialProtectedtitles.php13
-rw-r--r--includes/specials/SpecialRandompage.php22
-rw-r--r--includes/specials/SpecialRecentchanges.php263
-rw-r--r--includes/specials/SpecialRecentchangeslinked.php30
-rw-r--r--includes/specials/SpecialRemoveRestrictions.php60
-rw-r--r--includes/specials/SpecialResetpass.php178
-rw-r--r--includes/specials/SpecialRestrictUser.php189
-rw-r--r--includes/specials/SpecialRevisiondelete.php72
-rw-r--r--includes/specials/SpecialSearch.php984
-rw-r--r--includes/specials/SpecialSpecialpages.php2
-rw-r--r--includes/specials/SpecialStatistics.php277
-rw-r--r--includes/specials/SpecialUncategorizedimages.php2
-rw-r--r--includes/specials/SpecialUndelete.php197
-rw-r--r--includes/specials/SpecialUnusedimages.php2
-rw-r--r--includes/specials/SpecialUpload.php69
-rw-r--r--includes/specials/SpecialUserlogin.php249
-rw-r--r--includes/specials/SpecialUserlogout.php2
-rw-r--r--includes/specials/SpecialUserrights.php88
-rw-r--r--includes/specials/SpecialVersion.php74
-rw-r--r--includes/specials/SpecialWantedfiles.php90
-rw-r--r--includes/specials/SpecialWantedtemplates.php110
-rw-r--r--includes/specials/SpecialWatchlist.php266
-rw-r--r--includes/specials/SpecialWhatlinkshere.php20
-rw-r--r--includes/templates/NoLocalSettings.php29
-rw-r--r--includes/templates/PHP4.php100
-rw-r--r--includes/templates/Userlogin.php14
-rw-r--r--includes/zhtable/simpphrases.manual18
-rw-r--r--includes/zhtable/toCN.manual73
-rw-r--r--includes/zhtable/toHK.manual80
-rw-r--r--includes/zhtable/toSG.manual2
-rw-r--r--includes/zhtable/toTW.manual15
-rw-r--r--includes/zhtable/tradphrases.manual7
-rw-r--r--includes/zhtable/tradphrases_exclude.manual2
-rw-r--r--index.php37
-rw-r--r--languages/Language.php320
-rw-r--r--languages/LanguageConverter.php40
-rw-r--r--languages/Names.php8
-rw-r--r--languages/classes/LanguageBe.php57
-rw-r--r--languages/classes/LanguageBe_tarask.php57
-rw-r--r--languages/classes/LanguageBs.php92
-rw-r--r--languages/classes/LanguageCs.php116
-rw-r--r--languages/classes/LanguageDsb.php82
-rw-r--r--languages/classes/LanguageGa.php11
-rw-r--r--languages/classes/LanguageGsw.php65
-rw-r--r--languages/classes/LanguageHsb.php77
-rw-r--r--languages/classes/LanguageHu.php27
-rw-r--r--languages/classes/LanguageKk.php8
-rw-r--r--languages/classes/LanguageKu.php28
-rw-r--r--languages/classes/LanguageKu_ku.php11
-rw-r--r--languages/classes/LanguageLv.php27
-rw-r--r--languages/classes/LanguageMy.php18
-rw-r--r--languages/classes/LanguageRmy.php73
-rw-r--r--languages/classes/LanguageRu.php11
-rw-r--r--languages/classes/LanguageSk.php72
-rw-r--r--languages/classes/LanguageSl.php49
-rw-r--r--languages/classes/LanguageSr.php6
-rw-r--r--languages/classes/LanguageYue.php28
-rw-r--r--languages/classes/LanguageZh.php10
-rw-r--r--languages/messages/MessagesAce.php131
-rw-r--r--languages/messages/MessagesAf.php673
-rw-r--r--languages/messages/MessagesAln.php55
-rw-r--r--languages/messages/MessagesAm.php953
-rw-r--r--languages/messages/MessagesAn.php1166
-rw-r--r--languages/messages/MessagesAng.php155
-rw-r--r--languages/messages/MessagesAr.php1494
-rw-r--r--languages/messages/MessagesArc.php12
-rw-r--r--languages/messages/MessagesArn.php148
-rw-r--r--languages/messages/MessagesArz.php1477
-rw-r--r--languages/messages/MessagesAs.php243
-rw-r--r--languages/messages/MessagesAst.php1100
-rw-r--r--languages/messages/MessagesAv.php6
-rw-r--r--languages/messages/MessagesAvk.php616
-rw-r--r--languages/messages/MessagesAy.php51
-rw-r--r--languages/messages/MessagesAz.php154
-rw-r--r--languages/messages/MessagesBa.php24
-rw-r--r--languages/messages/MessagesBar.php149
-rw-r--r--languages/messages/MessagesBat_smg.php501
-rw-r--r--languages/messages/MessagesBcc.php1293
-rw-r--r--languages/messages/MessagesBcl.php351
-rw-r--r--languages/messages/MessagesBe.php1089
-rw-r--r--languages/messages/MessagesBe_tarask.php1154
-rw-r--r--languages/messages/MessagesBg.php1201
-rw-r--r--languages/messages/MessagesBi.php8
-rw-r--r--languages/messages/MessagesBm.php4
-rw-r--r--languages/messages/MessagesBn.php356
-rw-r--r--languages/messages/MessagesBo.php5
-rw-r--r--languages/messages/MessagesBpy.php135
-rw-r--r--languages/messages/MessagesBqi.php108
-rw-r--r--languages/messages/MessagesBr.php651
-rw-r--r--languages/messages/MessagesBs.php1393
-rw-r--r--languages/messages/MessagesBug.php75
-rw-r--r--languages/messages/MessagesCa.php1238
-rw-r--r--languages/messages/MessagesCbk_zam.php5
-rw-r--r--languages/messages/MessagesCdo.php165
-rw-r--r--languages/messages/MessagesCe.php36
-rw-r--r--languages/messages/MessagesCeb.php87
-rw-r--r--languages/messages/MessagesCh.php147
-rw-r--r--languages/messages/MessagesChr.php22
-rw-r--r--languages/messages/MessagesCo.php64
-rw-r--r--languages/messages/MessagesCrh_cyrl.php472
-rw-r--r--languages/messages/MessagesCrh_latn.php492
-rw-r--r--languages/messages/MessagesCs.php1080
-rw-r--r--languages/messages/MessagesCsb.php700
-rw-r--r--languages/messages/MessagesCu.php150
-rw-r--r--languages/messages/MessagesCv.php164
-rw-r--r--languages/messages/MessagesCy.php1255
-rw-r--r--languages/messages/MessagesDa.php611
-rw-r--r--languages/messages/MessagesDe.php1305
-rw-r--r--languages/messages/MessagesDe_formal.php187
-rw-r--r--languages/messages/MessagesDiq.php167
-rw-r--r--languages/messages/MessagesDsb.php1227
-rw-r--r--languages/messages/MessagesDv.php88
-rw-r--r--languages/messages/MessagesDz.php107
-rw-r--r--languages/messages/MessagesEe.php107
-rw-r--r--languages/messages/MessagesEl.php1460
-rw-r--r--languages/messages/MessagesEml.php19
-rw-r--r--languages/messages/MessagesEn.php1307
-rw-r--r--languages/messages/MessagesEn_gb.php2
-rw-r--r--languages/messages/MessagesEo.php1238
-rw-r--r--languages/messages/MessagesEs.php1238
-rw-r--r--languages/messages/MessagesEt.php715
-rw-r--r--languages/messages/MessagesEu.php1317
-rw-r--r--languages/messages/MessagesExt.php431
-rw-r--r--languages/messages/MessagesFa.php1539
-rw-r--r--languages/messages/MessagesFf.php2
-rw-r--r--languages/messages/MessagesFi.php1241
-rw-r--r--languages/messages/MessagesFiu_vro.php293
-rw-r--r--languages/messages/MessagesFj.php4
-rw-r--r--languages/messages/MessagesFo.php301
-rw-r--r--languages/messages/MessagesFr.php2188
-rw-r--r--languages/messages/MessagesFrc.php55
-rw-r--r--languages/messages/MessagesFrp.php343
-rw-r--r--languages/messages/MessagesFur.php706
-rw-r--r--languages/messages/MessagesFy.php1023
-rw-r--r--languages/messages/MessagesGa.php654
-rw-r--r--languages/messages/MessagesGag.php111
-rw-r--r--languages/messages/MessagesGan.php314
-rw-r--r--languages/messages/MessagesGd.php139
-rw-r--r--languages/messages/MessagesGl.php1406
-rw-r--r--languages/messages/MessagesGlk.php38
-rw-r--r--languages/messages/MessagesGn.php52
-rw-r--r--languages/messages/MessagesGot.php71
-rw-r--r--languages/messages/MessagesGrc.php1243
-rw-r--r--languages/messages/MessagesGsw.php2181
-rw-r--r--languages/messages/MessagesGu.php140
-rw-r--r--languages/messages/MessagesGv.php324
-rw-r--r--languages/messages/MessagesHak.php258
-rw-r--r--languages/messages/MessagesHaw.php203
-rw-r--r--languages/messages/MessagesHe.php1167
-rw-r--r--languages/messages/MessagesHi.php360
-rw-r--r--languages/messages/MessagesHif_deva.php14
-rw-r--r--languages/messages/MessagesHif_latn.php1016
-rw-r--r--languages/messages/MessagesHil.php21
-rw-r--r--languages/messages/MessagesHr.php1350
-rw-r--r--languages/messages/MessagesHsb.php1241
-rw-r--r--languages/messages/MessagesHt.php301
-rw-r--r--languages/messages/MessagesHu.php1740
-rw-r--r--languages/messages/MessagesHy.php279
-rw-r--r--languages/messages/MessagesIa.php1371
-rw-r--r--languages/messages/MessagesId.php1153
-rw-r--r--languages/messages/MessagesIe.php53
-rw-r--r--languages/messages/MessagesIi.php3
-rw-r--r--languages/messages/MessagesIk.php3
-rw-r--r--languages/messages/MessagesIke_cans.php28
-rw-r--r--languages/messages/MessagesIke_latn.php27
-rw-r--r--languages/messages/MessagesIlo.php262
-rw-r--r--languages/messages/MessagesInh.php12
-rw-r--r--languages/messages/MessagesIo.php671
-rw-r--r--languages/messages/MessagesIs.php911
-rw-r--r--languages/messages/MessagesIt.php1256
-rw-r--r--languages/messages/MessagesIu.php1
-rw-r--r--languages/messages/MessagesJa.php1576
-rw-r--r--languages/messages/MessagesJbo.php39
-rw-r--r--languages/messages/MessagesJut.php131
-rw-r--r--languages/messages/MessagesJv.php973
-rw-r--r--languages/messages/MessagesKa.php623
-rw-r--r--languages/messages/MessagesKaa.php898
-rw-r--r--languages/messages/MessagesKab.php225
-rw-r--r--languages/messages/MessagesKk_arab.php357
-rw-r--r--languages/messages/MessagesKk_cn.php12
-rw-r--r--languages/messages/MessagesKk_cyrl.php412
-rw-r--r--languages/messages/MessagesKk_latn.php372
-rw-r--r--languages/messages/MessagesKk_tr.php4
-rw-r--r--languages/messages/MessagesKl.php9
-rw-r--r--languages/messages/MessagesKm.php1397
-rw-r--r--languages/messages/MessagesKn.php294
-rw-r--r--languages/messages/MessagesKo.php1831
-rw-r--r--languages/messages/MessagesKri.php407
-rw-r--r--languages/messages/MessagesKrj.php17
-rw-r--r--languages/messages/MessagesKs.php3
-rw-r--r--languages/messages/MessagesKsh.php1342
-rw-r--r--languages/messages/MessagesKu.php4
-rw-r--r--languages/messages/MessagesKu_arab.php824
-rw-r--r--languages/messages/MessagesKu_latn.php486
-rw-r--r--languages/messages/MessagesKv.php8
-rw-r--r--languages/messages/MessagesKw.php5
-rw-r--r--languages/messages/MessagesKy.php24
-rw-r--r--languages/messages/MessagesLa.php1565
-rw-r--r--languages/messages/MessagesLad.php33
-rw-r--r--languages/messages/MessagesLb.php1371
-rw-r--r--languages/messages/MessagesLbe.php6
-rw-r--r--languages/messages/MessagesLez.php209
-rw-r--r--languages/messages/MessagesLfn.php287
-rw-r--r--languages/messages/MessagesLg.php41
-rw-r--r--languages/messages/MessagesLi.php857
-rw-r--r--languages/messages/MessagesLij.php238
-rw-r--r--languages/messages/MessagesLld.php1
-rw-r--r--languages/messages/MessagesLmo.php61
-rw-r--r--languages/messages/MessagesLn.php71
-rw-r--r--languages/messages/MessagesLo.php223
-rw-r--r--languages/messages/MessagesLoz.php158
-rw-r--r--languages/messages/MessagesLt.php1392
-rw-r--r--languages/messages/MessagesLv.php520
-rw-r--r--languages/messages/MessagesLzz.php55
-rw-r--r--languages/messages/MessagesMai.php16
-rw-r--r--languages/messages/MessagesMdf.php1160
-rw-r--r--languages/messages/MessagesMg.php353
-rw-r--r--languages/messages/MessagesMhr.php81
-rw-r--r--languages/messages/MessagesMk.php1500
-rw-r--r--languages/messages/MessagesMl.php524
-rw-r--r--languages/messages/MessagesMn.php410
-rw-r--r--languages/messages/MessagesMo.php10
-rw-r--r--languages/messages/MessagesMr.php479
-rw-r--r--languages/messages/MessagesMs.php1277
-rw-r--r--languages/messages/MessagesMt.php932
-rw-r--r--languages/messages/MessagesMwl.php203
-rw-r--r--languages/messages/MessagesMy.php46
-rw-r--r--languages/messages/MessagesMyv.php612
-rw-r--r--languages/messages/MessagesMzn.php6
-rw-r--r--languages/messages/MessagesNa.php9
-rw-r--r--languages/messages/MessagesNah.php487
-rw-r--r--languages/messages/MessagesNan.php160
-rw-r--r--languages/messages/MessagesNap.php68
-rw-r--r--languages/messages/MessagesNb.php2
-rw-r--r--languages/messages/MessagesNds.php1210
-rw-r--r--languages/messages/MessagesNds_nl.php1191
-rw-r--r--languages/messages/MessagesNe.php69
-rw-r--r--languages/messages/MessagesNew.php71
-rw-r--r--languages/messages/MessagesNiu.php236
-rw-r--r--languages/messages/MessagesNl.php1590
-rw-r--r--languages/messages/MessagesNn.php1211
-rw-r--r--languages/messages/MessagesNo.php1214
-rw-r--r--languages/messages/MessagesNov.php81
-rw-r--r--languages/messages/MessagesNso.php166
-rw-r--r--languages/messages/MessagesNv.php11
-rw-r--r--languages/messages/MessagesOc.php1265
-rw-r--r--languages/messages/MessagesOm.php44
-rw-r--r--languages/messages/MessagesOr.php66
-rw-r--r--languages/messages/MessagesOs.php333
-rw-r--r--languages/messages/MessagesPa.php158
-rw-r--r--languages/messages/MessagesPag.php53
-rw-r--r--languages/messages/MessagesPam.php297
-rw-r--r--languages/messages/MessagesPap.php19
-rw-r--r--languages/messages/MessagesPdc.php3
-rw-r--r--languages/messages/MessagesPdt.php111
-rw-r--r--languages/messages/MessagesPfl.php4
-rw-r--r--languages/messages/MessagesPih.php3
-rw-r--r--languages/messages/MessagesPl.php1438
-rw-r--r--languages/messages/MessagesPms.php284
-rw-r--r--languages/messages/MessagesPnb.php194
-rw-r--r--languages/messages/MessagesPnt.php528
-rw-r--r--languages/messages/MessagesPs.php580
-rw-r--r--languages/messages/MessagesPt.php1386
-rw-r--r--languages/messages/MessagesPt_br.php1340
-rw-r--r--languages/messages/MessagesQqq.php2548
-rw-r--r--languages/messages/MessagesQu.php1126
-rw-r--r--languages/messages/MessagesRif.php142
-rw-r--r--languages/messages/MessagesRm.php445
-rw-r--r--languages/messages/MessagesRmy.php44
-rw-r--r--languages/messages/MessagesRo.php1067
-rw-r--r--languages/messages/MessagesRoa_rup.php12
-rw-r--r--languages/messages/MessagesRoa_tara.php1645
-rw-r--r--languages/messages/MessagesRu.php1357
-rw-r--r--languages/messages/MessagesRuq.php3
-rw-r--r--languages/messages/MessagesRuq_cyrl.php24
-rw-r--r--languages/messages/MessagesRuq_grek.php1
-rw-r--r--languages/messages/MessagesRuq_latn.php24
-rw-r--r--languages/messages/MessagesSa.php138
-rw-r--r--languages/messages/MessagesSah.php1135
-rw-r--r--languages/messages/MessagesSc.php80
-rw-r--r--languages/messages/MessagesScn.php1135
-rw-r--r--languages/messages/MessagesSco.php468
-rw-r--r--languages/messages/MessagesSd.php196
-rw-r--r--languages/messages/MessagesSdc.php329
-rw-r--r--languages/messages/MessagesSe.php156
-rw-r--r--languages/messages/MessagesSei.php140
-rw-r--r--languages/messages/MessagesSh.php132
-rw-r--r--languages/messages/MessagesShi.php6
-rw-r--r--languages/messages/MessagesSi.php1206
-rw-r--r--languages/messages/MessagesSk.php1135
-rw-r--r--languages/messages/MessagesSl.php869
-rw-r--r--languages/messages/MessagesSm.php5
-rw-r--r--languages/messages/MessagesSma.php131
-rw-r--r--languages/messages/MessagesSn.php5
-rw-r--r--languages/messages/MessagesSo.php63
-rw-r--r--languages/messages/MessagesSq.php1323
-rw-r--r--languages/messages/MessagesSr.php17
-rw-r--r--languages/messages/MessagesSr_ec.php728
-rw-r--r--languages/messages/MessagesSr_el.php283
-rw-r--r--languages/messages/MessagesSrn.php246
-rw-r--r--languages/messages/MessagesSs.php16
-rw-r--r--languages/messages/MessagesSt.php10
-rw-r--r--languages/messages/MessagesStq.php1093
-rw-r--r--languages/messages/MessagesSu.php470
-rw-r--r--languages/messages/MessagesSv.php1361
-rw-r--r--languages/messages/MessagesSw.php441
-rw-r--r--languages/messages/MessagesSzl.php1243
-rw-r--r--languages/messages/MessagesTa.php650
-rw-r--r--languages/messages/MessagesTcy.php331
-rw-r--r--languages/messages/MessagesTe.php1071
-rw-r--r--languages/messages/MessagesTet.php446
-rw-r--r--languages/messages/MessagesTg.php2
-rw-r--r--languages/messages/MessagesTg_cyrl.php574
-rw-r--r--languages/messages/MessagesTh.php1203
-rw-r--r--languages/messages/MessagesTi.php14
-rw-r--r--languages/messages/MessagesTk.php47
-rw-r--r--languages/messages/MessagesTl.php1149
-rw-r--r--languages/messages/MessagesTlh.php5
-rw-r--r--languages/messages/MessagesTn.php6
-rw-r--r--languages/messages/MessagesTo.php351
-rw-r--r--languages/messages/MessagesTokipona.php6
-rw-r--r--languages/messages/MessagesTpi.php38
-rw-r--r--languages/messages/MessagesTr.php1848
-rw-r--r--languages/messages/MessagesTs.php65
-rw-r--r--languages/messages/MessagesTt.php3
-rw-r--r--languages/messages/MessagesTt_cyrl.php186
-rw-r--r--languages/messages/MessagesTt_latn.php81
-rw-r--r--languages/messages/MessagesTy.php12
-rw-r--r--languages/messages/MessagesTyv.php107
-rw-r--r--languages/messages/MessagesUdm.php7
-rw-r--r--languages/messages/MessagesUg.php20
-rw-r--r--languages/messages/MessagesUk.php1410
-rw-r--r--languages/messages/MessagesUr.php336
-rw-r--r--languages/messages/MessagesUz.php229
-rw-r--r--languages/messages/MessagesVec.php1153
-rw-r--r--languages/messages/MessagesVi.php1209
-rw-r--r--languages/messages/MessagesVls.php10
-rw-r--r--languages/messages/MessagesVo.php1860
-rw-r--r--languages/messages/MessagesWa.php193
-rw-r--r--languages/messages/MessagesWar.php47
-rw-r--r--languages/messages/MessagesWo.php365
-rw-r--r--languages/messages/MessagesWuu.php148
-rw-r--r--languages/messages/MessagesXal.php6
-rw-r--r--languages/messages/MessagesXh.php49
-rw-r--r--languages/messages/MessagesXmf.php81
-rw-r--r--languages/messages/MessagesYdd.php1
-rw-r--r--languages/messages/MessagesYi.php1251
-rw-r--r--languages/messages/MessagesYo.php210
-rw-r--r--languages/messages/MessagesYue.php1073
-rw-r--r--languages/messages/MessagesZa.php11
-rw-r--r--languages/messages/MessagesZea.php142
-rw-r--r--languages/messages/MessagesZh.php15
-rw-r--r--languages/messages/MessagesZh_classical.php899
-rw-r--r--languages/messages/MessagesZh_cn.php4
-rw-r--r--languages/messages/MessagesZh_hans.php1142
-rw-r--r--languages/messages/MessagesZh_hant.php1142
-rw-r--r--languages/messages/MessagesZh_hk.php48
-rw-r--r--languages/messages/MessagesZh_min_nan.php4
-rw-r--r--languages/messages/MessagesZh_mo.php4
-rw-r--r--languages/messages/MessagesZh_my.php4
-rw-r--r--languages/messages/MessagesZh_sg.php4
-rw-r--r--languages/messages/MessagesZh_tw.php356
-rw-r--r--languages/messages/MessagesZh_yue.php4
-rw-r--r--languages/messages/MessagesZu.php31
-rw-r--r--locale/README1
-rw-r--r--maintenance/Doxyfile39
-rw-r--r--maintenance/FiveUpgrade.inc47
-rw-r--r--maintenance/addwiki.php1
-rw-r--r--maintenance/archives/patch-ipb_allow_usertalk.sql3
-rw-r--r--maintenance/archives/patch-linktables.sql2
-rw-r--r--maintenance/archives/patch-log_user_text.sql5
-rw-r--r--maintenance/archives/patch-ss_active_users.sql3
-rw-r--r--maintenance/backup.inc14
-rw-r--r--maintenance/benchmarkPurge.php22
-rw-r--r--maintenance/checkAutoLoader.php19
-rw-r--r--maintenance/checkBadRedirects.php30
-rw-r--r--maintenance/checkImages.php45
-rw-r--r--maintenance/cleanupImages.php26
-rw-r--r--maintenance/cleanupTitles.php21
-rw-r--r--maintenance/deleteBatch.php7
-rw-r--r--maintenance/dumpBackup.php3
-rw-r--r--maintenance/dumpTextPass.php2
-rw-r--r--maintenance/edit.php11
-rw-r--r--maintenance/findhooks.php1
-rw-r--r--maintenance/generateSitemap.php6
-rw-r--r--maintenance/importDump.php22
-rw-r--r--maintenance/importImages.inc.php39
-rw-r--r--maintenance/importImages.php61
-rw-r--r--maintenance/importTextFile.php4
-rw-r--r--maintenance/interwiki.sql11
-rw-r--r--maintenance/language/checkLanguage.inc376
-rw-r--r--maintenance/language/checkLanguage.php7
-rw-r--r--maintenance/language/countMessages.php40
-rw-r--r--maintenance/language/diffLanguage.php1
-rw-r--r--maintenance/language/languages.inc336
-rw-r--r--maintenance/language/messageTypes.inc39
-rw-r--r--maintenance/language/messages.inc412
-rw-r--r--maintenance/language/transstat.php4
-rw-r--r--maintenance/moveBatch.php7
-rw-r--r--maintenance/namespaceDupes.php2
-rw-r--r--maintenance/nukePage.inc19
-rw-r--r--maintenance/ourusers.php48
-rw-r--r--maintenance/parserTests.inc220
-rw-r--r--maintenance/parserTests.php22
-rw-r--r--maintenance/parserTests.txt640
-rw-r--r--maintenance/parserTestsStaticParserHook.php23
-rw-r--r--maintenance/postgres/archives/patch-ipb_address_unique.sql1
-rw-r--r--maintenance/postgres/compare_schemas.pl3
-rw-r--r--maintenance/postgres/mediawiki_mysql2postgres.pl6
-rw-r--r--maintenance/postgres/tables.sql13
-rw-r--r--maintenance/rebuildFileCache.php91
-rw-r--r--maintenance/refreshLinks.inc8
-rw-r--r--maintenance/removeUnusedAccounts.inc4
-rw-r--r--maintenance/removeUnusedAccounts.php31
-rw-r--r--maintenance/renameDbPrefix.php68
-rw-r--r--maintenance/runJobs.php2
-rw-r--r--maintenance/sql.php6
-rw-r--r--maintenance/stats.php6
-rw-r--r--maintenance/storage/blob_tracking.sql57
-rw-r--r--maintenance/storage/compressOld.inc10
-rw-r--r--maintenance/storage/compressOld.php6
-rw-r--r--maintenance/storage/dumpRev.php50
-rw-r--r--maintenance/storage/orphanStats.php46
-rw-r--r--maintenance/storage/recompressTracked.php742
-rw-r--r--maintenance/storage/testCompression.php81
-rw-r--r--maintenance/storage/trackBlobs.php316
-rw-r--r--maintenance/tables.sql14
-rw-r--r--maintenance/updateArticleCount.inc.php15
-rw-r--r--maintenance/updateRestrictions.php23
-rw-r--r--maintenance/updateSpecialPages.php93
-rw-r--r--maintenance/updaters.inc74
-rw-r--r--math/texutil.ml8
-rw-r--r--php5.php511
-rw-r--r--profileinfo.php19
-rw-r--r--skins/ArchLinux.php69
-rw-r--r--skins/Chick.php12
-rw-r--r--skins/CologneBlue.php8
-rw-r--r--skins/Modern.php38
-rw-r--r--skins/MonoBook.php86
-rw-r--r--skins/MySkin.php9
-rw-r--r--skins/Nostalgia.php42
-rw-r--r--skins/Simple.php11
-rw-r--r--skins/Standard.php36
-rw-r--r--skins/archlinux/IE50Fixes.css2
-rw-r--r--skins/archlinux/main.css27
-rw-r--r--skins/archlinux/rtl.css5
-rw-r--r--skins/chick/IE50Fixes.css2
-rw-r--r--skins/chick/main.css23
-rw-r--r--skins/common/ajax.js11
-rw-r--r--skins/common/ajaxsearch.js103
-rw-r--r--skins/common/ajaxwatch.js15
-rw-r--r--skins/common/block.js2
-rw-r--r--skins/common/cologneblue.css13
-rw-r--r--skins/common/common_rtl.css5
-rw-r--r--skins/common/diff.css67
-rw-r--r--skins/common/diff.js2
-rw-r--r--skins/common/enhancedchanges.js40
-rw-r--r--skins/common/mwsuggest.js248
-rw-r--r--skins/common/oldshared.css15
-rw-r--r--skins/common/prefs.js45
-rw-r--r--skins/common/preview.js1
-rw-r--r--skins/common/protect.js527
-rw-r--r--skins/common/shared.css76
-rw-r--r--skins/common/wikibits.js281
-rw-r--r--skins/common/wikiprintable.css2
-rw-r--r--skins/common/wikistandard.css2
-rw-r--r--skins/disabled/MonoBookCBT.php2
-rw-r--r--skins/modern/main.css18
-rw-r--r--skins/modern/print.css3
-rw-r--r--skins/modern/rtl.css13
-rw-r--r--skins/monobook/IE50Fixes.css2
-rw-r--r--skins/monobook/main.css27
-rw-r--r--skins/monobook/rtl.css5
-rw-r--r--skins/simple/main.css13
-rw-r--r--skins/simple/rtl.css5
-rw-r--r--t/Search.inc14
-rw-r--r--t/inc/Database.t10
-rw-r--r--t/inc/Global.t10
-rw-r--r--tests/MediaWiki_TestCase.php2
-rw-r--r--thumb.php23
-rw-r--r--trackback.php28
741 files changed, 126835 insertions, 77949 deletions
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 00000000..0b456c48
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,90 @@
+MediaWiki 1.14 is a collaborative project released under the
+GNU General Public License v2. We would like to recognize the
+following names for their contribution to the product.
+
+== Developers ==
+* Aaron Schulz
+* Alex Z.
+* Alexandre Emsenhuber
+* Andrew Garrett
+* Aryeh Gregor
+* Ashar Voultoiz
+* Bertrand Grondin
+* Brion Vibber
+* Bryan Tong Minh
+* Chad Horohoe
+* Charles Melbye
+* Daniel Friesen
+* Daniel Kinzler
+* Danny B.
+* David McCabe
+* Derk-Jan Hartman
+* Domas Mituzas
+* Fran Rogers
+* Greg Sabino Mullane
+* Guy Van den Broeck
+* Hojjat
+* Ilmari Karonen
+* Jack D. Pond
+* Jack Phoenix
+* Jason Richey
+* Jon Harald Søby
+* Leon Weber
+* Marco Schuster
+* Matt Johnston
+* Meno25
+* MinuteElectron
+* Mohamed Magdy
+* Nathaniel Herman
+* Nicolas Dumazet
+* Niklas Laxström
+* Platonides
+* Purodha Blissenbach
+* Raimond Spekking
+* Roan Kattouw
+* Robert Stojnić
+* Rotem Liss
+* Ryan Lane
+* Ryan Schmidt
+* Shinjiman
+* Siebrand Mazeland
+* SQL
+* Soxred93
+* Thomas Bleher
+* Tim Starling
+* Victor Vasiliev
+
+== Patch Contributors ==
+* Agbad
+* Brad Jorsch
+* Brent G
+* Daniel Arnold
+* Danny B.
+* FunPika
+* Happy-melon
+* Jeremy Baron
+* Juliano F. Ravasi
+* Lucas Garczewski
+* Louperivois
+* Marooned
+* Max Semenik
+* Michael De La Rue
+* Mike Horvath
+* Mormegil
+* Nakon
+* Nathan Larson
+* Nikolaos S. Karastathis
+* Olaf Lenz
+* Paul Copperman
+* RememberTheDot
+* René Kijewski
+* ST47
+* Stefano
+
+== Translators ==
+* Anders Wegge Jakobsen
+* Hk kng
+* Hojjat
+* Meno25
+* Rotem Liss
+* Shinjiman
diff --git a/HISTORY b/HISTORY
index 8e89f410..f9e3692a 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,5 +1,650 @@
Change notes from older releases. For current info see RELEASE-NOTES.
+== MediaWiki 1.13 ==
+
+== Changes since 1.13.2 ==
+
+David Remahl of Apple's Product Security team has identified a number of
+security issues in previous releases of MediaWiki. Subsequent analysis by the
+MediaWiki development team expanded the scope of these vulnerabilities. The
+issues with a significant impact are as follows:
+
+* An XSS vulnerability affecting all MediaWiki installations between 1.13.0 and
+ 1.13.2. [CVE-2008-5249]
+* A local script injection vulnerability affecting Internet Explorer clients for
+ all MediaWiki installations with uploads enabled. [CVE-2008-5250]
+* A local script injection vulnerability affecting clients with SVG scripting
+ capability (such as Firefox 1.5+), for all MediaWiki installations with SVG
+ uploads enabled. [CVE-2008-5250]
+* A CSRF vulnerability affecting the Special:Import feature, for all MediaWiki
+ installations since the feature was introduced in 1.3.0. [CVE-2008-5252]
+
+XSS (cross-site scripting) vulnerabilities allow an attacker to steal an
+authorised user's login session, and to act as that user on the wiki. The
+authorised user must visit a web page controlled by the attacker in order to
+activate the attack. Intranet wikis are vulnerable if the attacker can
+determine the intranet URL.
+
+Local script injection vulnerabilities are like XSS vulnerabilities, except
+that the attacker must have an account on the local wiki, and there is no
+external site involved. The attacker uploads a script to the wiki, which another
+user is tricked into executing, with the effect that the attacker is able to act
+as the privileged user.
+
+CSRF vulnerabilities allow an attacker to act as an authorised user on the wiki,
+but unlike an XSS vulnerability, the attacker can only act as the user in a
+specific and restricted way. The present CSRF vulnerability allows pages to be
+edited, with forged revision histories. Like an XSS vulnerability, the
+authorised user must visit the malicious web page to activate the attack.
+
+These four vulnerabilities are all fixed in this release.
+
+David Remahl also reminded us of some security-related configuration issues:
+
+* By default, MediaWiki stores a backup of deleted images in the images/deleted
+ directory. If you do not want these images to be publically accessible, make
+ sure this directory is not accessible from the web. MediaWiki takes some steps
+ to avoid leaking these images, but these measures are not perfect.
+* Set display_errors=off in your php.ini to avoid path disclosure via PHP fatal
+ errors. This is the default on most shared web hosts.
+* Enabling MediaWiki's debugging features, such as $wgShowExceptionDetails, may
+ lead to path disclosure.
+
+Other changes in this release:
+
+* Avoid fatal error in profileinfo.php when not configured.
+* Add a .htaccess to deleted images directory for additional protection against
+ exposure of deleted files with known SHA-1 hashes on default installations.
+* Avoid streaming uploaded files to the user via index.php. This allows
+ security-conscious users to serve uploaded files via a different domain, and
+ thus client-side scripts executed from that domain cannot access the login
+ cookies. Affects Special:Undelete, img_auth.php and thumb.php.
+* When streaming files via index.php, use the MIME type detected from the
+ file extension, not from the data. This reduces the XSS attack surface.
+* Blacklist redirects via Special:Filepath. Such redirects exacerbate any
+ XSS vulnerabilities involving uploads of files containing scripts.
+* Internationalisation updates.
+
+== Changes since 1.13.1 ==
+
+* Security: Work around misconfiguration by requiring strict comparisons for
+ in_array in User::isAllowed().
+* (bug 14944) Added $wgShellLocale for configuration of an appropriate locale
+ to use for LC_CTYPE during shell invocation. For servers that don't have
+ en_US.utf8. Also added locale detection during install.
+* Localisation updates
+* Security: Fixed XSS vulnerability in useskin parameter.
+
+== Changes since 1.13.0 ==
+
+* (bug 15460) Fixed intermittent deadlock errors and poor concurrent
+ performance for installations without memcached.
+* (bug 13770) Fixed DOM module detection for installations with both dom
+ and domxml.
+* (bug 15148) Fixed Special:BlockIP for PostgreSQL
+* Fixed SQLite support for non-memcached installations
+* Localisation updates, Achinese (ace) added.
+
+== Changes since 1.13.0rc2 ==
+
+* (bug 13770) Fixed incorrect detection of PHP's DOM module
+* Fix regression from r37834: accesskey tooltip hint should be given for the
+ minor edit and watch labels on the edit page.
+* Updated Chinese simplified/traditional conversion tables
+
+== Changes since 1.13.0rc1 ==
+
+* $wgForwardSearchUrl has been removed entirely. Documented setting since 1.4
+ has been $wgSearchForwardUrl.
+* (bug 14907) DatabasePostgres::fieldType now defined.
+* (bug 14966) Fix SearchEngineDummy class for silently non-functional search
+ on Sqlite instead of horribly fatal error breaky one.
+* (bug 14987) Only fix double redirects on page move when the checkbox is
+ checked
+* (bug 13376) Use $wgPasswordSender, not $wgEmergencyContact, as return
+ address for page update notification mails.
+* API: Registration time of users registered before the DB field was created is now
+ shown as empty instead of the current time.
+* (bug 14904): fragments were lost when redirects were fixed.
+* Added magic word __STATICREDIRECT__ to suppress the redirect fixer
+* (bug 15035) Revert English linkTrail to /^([a-z]+)(.*)$/sD, as it was before
+ r36253. Multiple reports of breakage due to old (pre-5.0) PCRE libraries,
+ both bundled with PHP and packaged with distros such as RHEL.
+* (bug 14944) Shell invocation of external programs such as ImageMagick convert
+ was broken in PHP 5.2.6, if the server had a non-UTF-8 locale.
+
+=== Configuration changes in 1.13 ===
+
+* New option $wgFeed can be set false to turn off syndication feeds
+* (bug 5745) Special:Whatlinkshere now shows up to $wgMaxRedirectLinksRetrieved
+ links through each redirect instead of hardcoded 500
+* Set $wgUploadSizeWarning to false by default
+* Added $wgLBFactoryConf, for generic configuration of multi-master wiki farms
+* Removed $wgAlternateMaster, use $wgLBFactoryConf
+* (bug 13562) Misspelled option $wgUserNotifedOnAllChanges changed to
+ $wgUserNotifiedOnAllChanges
+* (bug 12860) New option $wgSitemapNamespaces allows sitemaps to be generated
+ for only some namespaces
+* Removed the emailconfirmed implicit group by default. To re-add it, use:
+ $wgAutopromote['emailconfirmed'] = APCOND_EMAILCONFIRMED;
+ in your LocalSettings.php.
+* (bug 2396) New shared database configuration variables. $wgSharedPrefix allows
+ you to use a shared database with a different prefix. Or you can now use a local
+ database and use prefixes to separate wiki and the shared tables. And the new
+ $wgSharedTables variable allows you to specify a list of tables to share.
+* Automatic edit summaries can be disabled with $wgUseAutomaticEditSummaries
+* Duplicates of images are now shown on the image page
+* $wgRCFilterByAge allows for the list of dates in recent changes special pages to
+ be filtered to only those within the range of $wgRCMaxAge
+* $wgRCLinkLimits and $wgRCLinkDays allow for customization of the list and limits
+ displayed on the recent changes special pages
+* The "createpage" permission is no longer required when uploading if the target
+ image page already exists
+* $wgMaximumMovedPages restricts the number of pages that can be moved at once
+ (default 100) with the new subpage-move functionality of Special:Movepage
+* Hooks display in Special:Version is now disabled by default, use
+ $wgSpecialVersionShowHooks = true; to enable it.
+* $wgActiveUserEditCount sets the number of edits that must be performed over
+ a certain number of days to be considered active
+* $wgActiveUserDays is that number of days
+* $wgRateLimitsExcludedGroups has been deprecated in favor of
+ $wgGroupPermissions[]['noratelimit']. The former still works, however.
+* New $wgGroupPermissions option 'move-subpages' added to control bulk-moving
+ subpages along with pages. Assigned to 'user' and 'sysop' by default.
+* New $wgRC2UDPOmitBots allows user to omit bot edits from UDP output.
+ Default: false
+* Removed $wgEnableCascadingProtection option. Disabling cascading protection
+ is no longer possible.
+* $wgMessageCacheType defines now the type of cache used by the MessageCache class,
+ previously it was choosen based on $wgParserCacheType
+* $wgExtensionAliasesFiles option to simplify adding aliases to special pages
+ provided by extensions, in a similar way to $wgExtensionMessagesFiles
+* Added $wgXMLMimeTypes, an array of XML mimetypes we can check for
+ with MimeMagic.
+* Added $wgDirectoryMode, which allows for setting the default CHMOD value when
+ creating new directories.
+* (bug 14843) $wgCookiePrefix can be set by LocalSettings now, false defaults
+ current behavior.
+
+=== New features in 1.13 ===
+
+* __HIDDENCAT__ on a category page causes the category to be hidden on the
+ article page
+* Do not show edit permissions errors on a red link click, just redirect to the
+ article. This is so that readers who don't know what a red link is are not
+ confused when they are told they are range-blocked.
+* Add a new hook ImageBeforeProduceHTML to allow extensions to modify wikitext
+ image syntax output
+* (bug 13100) Added 'preloadtitle' parameter to action=edit&section=new that
+ pre-fills the section title field
+* (bug 13112) Added Special:RelatedChanges alias to Special:RecentChangesLinked
+* (bug 13130) Moved edit token and autosummary fields above edit tools to
+ reduce broken form submissions
+* Add --old-redirects-only option to maintenance/refreshLinks.php, to add old
+ redirects to the redirect table
+* Add links to page and file deletion forms to edit predefined delete reasons
+* (bug 13269) Added MediaWiki:Uploadfooter to the bottom of Special:Upload
+* (bug 2815) Search results for media now use thumbnail instead of text extract
+* When a page doesn't exist, the tab should say "create", not "edit"
+* (bug 12882) Added a span with class "patrollink" around "Mark as patrolled"
+ link on diffs
+* Magic word formatnum can now take raw suffix to undo formatting
+* Add updatelog table to reliably permit updates that don't change the schema
+* Add category table to allow better tracking of category membership counts
+** (bug 1212) Give correct membership counts on the pages of large categories
+** Use category table for more efficient display of Special:Categories
+* (bug 1459) Search for duplicate files by hash: Special:FileDuplicateSearch
+* (bug 9447) Added hooks for search result headings
+* Image redirects are now enabled by default
+* (bug 13450) Email confirmation can now be canceled before the expiration
+* (bug 13490) Show upload/file size limit on upload form
+* Redesign of Special:UserRights
+* Make rev_deleted log entries more intelligible
+* (bug 6943) Added PAGESINCATEGORY: magic word
+* (bug 13604) Added Special:ListGroupRights
+* (bug 6332, 8617) Added message 'mainpage-description' as duplicate of
+ 'mainpage' and added it to message 'sidebar'
+* Automatically add old redirects to the redirect table when needed
+* (bug 6934) Allow inclusions, links, redirects to be separately toggled on or
+ off on Special:WhatLinksHere
+* Cache image redirects
+* (bug 10457) Organize Special:SpecialPages into sections
+* Add a new hook EditPageBeforeConflictDiff to allow extensions like FCKeditor
+ to modify the output for edit conflicts
+* Add class="nested" for <fieldset>s so fieldsets inside fieldsets get
+ a slightly less huge margin and padding
+* (bug 13527) Use sitemaps.org format 0.9 instead of a Google-specific format
+* Allow \C and \Q as TeX commands to match \R, \N, \Z
+* On Special:UserRights, when you can add a group you can't remove or remove
+ one you can't add, a notice is printed to warn you
+* (bug 12698) Create PAGESIZE parser function, to return the size of a page
+* Allow the "log in / create account" link in the toolbar to have different
+ text from Special:UserLogin title (new message 'nav-login-createaccount')
+* Say "log in / create account" if an anonymous user can create an account,
+ otherwise just "log in", consistently across skins
+* Special:Shortpages and Special:Longpages now returns pages in all content
+ namespaces, not just NS_MAIN.
+* (bug 889) Improve conflict-handling between shared upload repository
+ and local one
+* Update documentation links in auto-generated LocalSettings.php
+* (bug 13584) The new hook SkinTemplateToolboxEnd was added.
+* (bug 709) Cannot rename/move images and other media files [EXPERIMENTAL]
+* Custom rollback summaries now accept the same arguments as the default message
+* (bug 12542) Added hooks for expansion of Special:Listusers
+* Drop-down AJAX search suggestions (turn on $wgEnableMWSuggest)
+* More relevant search snippets (turn on $wgAdvancedSearchHighlighting)
+* (bug 13950) Allow users to watch the user/talk pages of users they block.
+* (bug 13970) Allow MonoBook-based skins to specify their own print stylesheet
+* Show image links on Special:Whatlinkshere
+* Use rel="start", "prev", "next" appropriately on Pager-based pages
+* Add support for SQLite
+* AutoAuthenticate hook renamed to UserLoadFromSession
+* (bug 13232) importScript(), importStylesheet() funcs available to custom JS
+* (bug 13095) Search by first letters or digits in [[Special:Categories]]
+* Users moving a page can now move all subpages automatically as well
+* (bug 14259) Localisation message for upload button on Special:Import is now
+ 'import-upload' instead of 'upload'
+* Add information about user group membership to Special:Preferences
+* (bug 14146) Wrap usage section on imagepages into <div>s.
+* New layout for Special:Specialpages. Restricted pages are marked but not separated
+ from other pages in their group.
+* (bug 14263) Show a diff of the revert on rollback notification page.
+* (bug 13434) Show a warning when hash identical files exist
+* Sidebar is now cached for all languages
+* The User class now contains a public function called isActiveEditor. Figures
+ out if a user is active based on at least $wgActiveUserEditCount number of
+ edits in the last $wgActiveUserDays days.
+* SpecialSearchResults hook now passes results by reference, so they can be
+ changed by extensions.
+* Add a new hook LinkerMakeExternalLink to allow extensions to modify the output of
+ external links.
+* (bug 14132) Allow user to disable bot edits from being output to UDP.
+* (bug 14328) jsMsg() within Wikibits now accepts a DOM object, not just a string
+* (bug 14558) New system message (emailuserfooter) is now added to the footer of
+ e-mails sent with Special:Emailuser
+* Add support for Hijri (Islamic) calendar
+* Add a new hook LinkerMakeExternalImage to allow extensions to modify the output
+ of external (hotlinked) images.
+* (bug 14604) Introduced the following features for the LanguageConverter:
+ Multi-tag support, single conversion flag, remove conversion flag on a single
+ page, description flag, variant name, multi-variant fallbacks.
+* Add zh-mo and zh-my variants for the zh language
+* (bugs 4832, 9481, 12890) Special:Recentchangeslinked now has all options that
+ are in Special:Recentchanges
+* Allow an $error message to be passed to ArticleDelete hook
+* Allow extensions to modify the user creation form by calling addInputItem();
+* Add meta generator tag to HTML output
+* MediawikiPerformAction hook is now passed the Mediawiki object
+* Added blank special page Special:BlankPage for benchmarking, etc.
+* Foreign repo file descriptions and thumbnails are now cached.
+* (bug 11732) Allow localisation of edit button images
+* Allow the search box, toolbox and languages box in the Monobook sidebar to be
+ moved around arbitrarily using special sections in [[MediaWiki:Sidebar]]:
+ SEARCH, TOOLBOX and LANGUAGES
+* Add a new hook NormalizeMessageKey to allow extensions to replace messages before
+ the database is potentially queried
+* (bug 9736) Redirects on Special:Fewestrevisions are now marked as such.
+* New date/time formats in Cs localization according to ČSN and PČP.
+* Special:Recentchangeslinked now includes changes to transcluded pages and
+ displayed images; also, the "Show changes to pages linked" checkbox now works on
+ category pages too, showing all links that are not categorizations
+* (bug 4578) Automatically fix redirects broken by a page move
+
+=== Bug fixes in 1.13 ===
+
+* (bug 10677) Add link to the file description page on the shared repository
+* (bug 13084) Increase size of source/destination filename fields in upload form
+* (bug 13115) rebuildrecentchanges should print the current value of $wgRCMaxAge
+* (bug 13140) Show parent categories in category namespace
+* (bug 13149) Correctly format 'fileexists' message on Upload page
+* Make the default filepageexists message accurate
+* (bug 12988) $wgMinimalPasswordLength no longer breaks create user by email
+* (bug 13022) Fix upload from URL on PHP 5.0.x
+* (bug 13132) Unable to unprotect pages protected with earlier versions of MediaWiki
+* (bug 12723) OpenSearch description name now uses more compact language code
+ to avoid passing the length limit as often, is customizable per site via
+ 'opensearch-desc' message.
+* (bug 13135) Special:Userrights now passes IDs through form submission
+ to allow functionality on not-quite-right usernames
+* (bug 12575) Prevent duplicate patrol log entries from being created
+* (bug 13174) __HIDDENCAT__ now applies only to category pages
+* (bug 13031) Add links to user pages in e-mail form
+* (bug 13147) Description for categoriespagetext (used in Special:Categories) reworded
+* (bug 11561) Fix fatal error when calling action=revert to non-image page
+* (bug 12430) Fix call to private method LinkFilter::makeRegex fatal error in
+ maintenance/cleanupSpam.php
+* All skins should have the "mediawiki" class on the body element
+* (bug 13019) Message cache for some extensions not loaded at time of editing
+* (bug 13247) Prettified ISBN links
+* maintenance/refreshLinks.php did not fix page_id 1 with the --new-only option
+* (bug 13110) Don't show "Permission error" page if the edit is already rolled
+ back when using rollback
+* (bug 13012) Use content messages for block options when generating the
+ recentchanges entry
+* (bug 13274) Change links for messages to ucfirst
+* (bug 13273) Un-hardcode some punctuation (add new messages colon-separator,
+ autocomment-prefix)
+* Parse MediaWiki message translations with a correct language setting on preview
+* (bug 13281) Treat X-Forwarded-For, Client-ip and User-Agent headers as
+ case-insensitive names.
+* Adding the fix for lists in RTL wikis to more skins, and fixing the image toc
+* (bug 8157) Remove redirects from Special:Unusedtemplates. Patch by WebBoy.
+* (bug 10721) Duplicate section anchors with differing case now disambiguated
+ for Internet Explorer's sake and standards compliance
+* (bug 13298) Tighter limits on Special:Newpages limits when embedding
+* Email subject in content language instead of sending user's UI language
+* (bug 13251) Allow maintenance rebuild scripts to work with Postgres
+* (bug 2084) Fixed incorrect regex to match redirects
+* (bug 3131) Manually-specified upload destination filename is no longer
+ overwritten by browsing for a file after you wrote it.
+* (bug 7251) Sidebars generated by MediaWiki:Sidebar now have the class
+ 'generated-sidebar'.
+* (bug 13265) Media handler is missing 'image/x-bmp'
+* (bug 13407) MediaWiki:Powersearch is used in two places
+* (bug 13403) Fix cache invalidation of history pages when old revisions change
+* (bug 11563) Deprecated SearchMySQL4 class; merged code to SearchMySQL
+* (bug 12801) Fix link in subtitle message in AJAX search
+* (bug 13428) Fix regression in protection form layout HTML validity
+* (bug 9403) Sanitize newlines from search term input
+* (bug 13429) Separate date and time in message sp-newimages-showfrom
+* (bug 13137) Allow setting 'editprotected' right separately from 'protect',
+ so groups may optionally edit protected pages without having 'protect' perms
+* Disallow deletion of big pages by means of moving a page to its title and
+ using the "delete and move" option.
+* (bug 13466, 13632) White space differences not shown in diffs
+* (bug 1953) Search form now honors namespace selections more reliably
+* (bug 12294) Namespace class renamed to MWNamespace for PHP 5.3 compatibility
+* PHP 5.3 compatibility fix for wfRunHooks() called with no parameters
+* (bug 6447) Trackbacks now work with transactional tables, if enabled
+* (bug 6892, 7147) Trackback error handling, optional fields more robust
+* (bug 6813) Don't break HTML validator when using trackbacks
+* Fix for size checks on SVG images with global 'stroke-width' attribute
+* (bug 11874) Inline CSS with !important no longer borken
+* (bug 1600) Strip extra == section markup == in new-comment field
+* (bug 11325) Wrapped page titles in MonoBook skin spaced more nicely
+* (bug 12077) Fix HTML nesting for TOC
+* (bug 344) Purge cache for talk/article pages when deleting the other tab
+* (bug 13436) Treat image captions correctly when they include option keywords
+ (like ending with "px" or starting with "upright")
+* Trackback display formatting fixed
+* Don't die when single-element arrays are passed to SQL query constructors
+ that have an array index other than 0
+* (bug 13522) Fix fatal error in Parser::extractTagsAndParams
+* (bug 13532) Use proper timestamp call when reverting images
+* (bug 13543) Updated FAQ link in the installer sidebar
+* (bug 13540) Date format in confirmation e-mail now matches message language
+* (bug 13554) PHP Notice in old pre-processor when list item is empty.
+* (bug 13556) Don't show a blank form if no image is attached in Special:Upload
+* (bug 13576) maintenance/rebuildrecentchanges.php fails
+* (bug 13441) Allow Special:Recentchanges to show bots only
+* (bug 13431) Show true message source in Special:Allmessages&ot=php / xml
+* (bug 13463) Login successful page doesn't use user's preferred interface language
+* (bug 13630) Fixed warnings for pass by reference at call time in
+ Special:Revisiondelete when generating the log entry.
+* (bug 12064) BeforePageDisplay hook is now called for all skins
+* (bug 13624) Fix regression with manual thumb= parameter on images
+* (bug 11039) Add missing labels on protection form
+* (bug 13458) Preview/edit toolbar spacing now works consistently
+* (bug 13433) Fix action=render on Image: pages
+* (bug 13678) Fix CSS validation for Monobook
+* (bug 13684) Links in Special:ListGroupRights should be in content language
+* (bug 13690) Fix PHP notice on accessing some URLs
+* Hide (undo) link if user isn't able to edit page
+* Invalidate cache of pages that includes images via redirects on upload
+* (bug 13705) Don't show rollback link in page history on incorrect revisions
+* (bug 13708) Don't set "Search results" title when loading Special:Search
+ without query
+* (bug 13736) Don't show MediaWiki:Anontalkpagetext on non-existant IP addresses
+* (bug 13728) Don't trim initial whitespace during section edits
+* (bug 13727) Don't delete log entries from recentchanges on page deletion
+* (bug 13752) Redirects to sections now work again
+* (bug 13725) Upload form watch checkbox state set correctly with wpDestFile
+* (bug 13756) Don't show the form and navigation links of Special:Newpages if
+ the page is included
+* When hiding things on WhatLinksHere, generated URLs should hide them too
+* Properly escape search terms with regex chars so they appear highlighted in
+ search results
+* (bug 13768) pt_title field encoding fixed
+* Do not display empty columns on Special:UserRights if all groups are
+ changeable or all unchangeable
+* Fix fatal error on calling PAGESINCATEGORY with invalid category name
+* (bug 13793) Special:Whatlinkshere filters wrong - after paginating instead of before
+* (bug 13796) Show links to parent pages even if some of them are missing
+* (bug 13816) Filter by main namespace doesn't work on WhatLinksHere
+* (bug 13822) Fatal error on some pages when calculating subpage subtitle
+* (bug 13824) AJAX search suggestion now works with non-SkinTemplate skins
+* Added 'application/x-dia-diagram' MediaWiki's known MIME types
+* (bug 13866) skins/common/shared.css - invalid attribute fixing
+* Hide edit section links on Special:Undelete
+* (bug 13860) Fix "Justify paragraphs" option for Modern skin
+* (bug 13168) accessibility links in Modern skin link to wrong anchor id
+* (bug 13185) No line break after 'subpages' class in Modern skin
+* (bug 13583) No "poweredby" in Modern skin
+* (bug 13880) "Printable" link in Modern skin now formats as print mode
+* (bug 13885) Bump default $wgSVGMaxSize from 1024 to 2048 pixels
+* (bug 13891) Show categories box even if all categories are hidden and user has
+ "show hidden categories" option on
+* (bug 13915) Undefined variable $wltsfield in includes/SpecialWatchlist.php
+* (bug 13913) Special:Whatlinkshere now has correct HTML markup
+* (bug 13905) Blacklist Mac IE from HttpOnly cookies; it eats them sometimes
+* (bug 13922) Fix bad HTML on empty Special:Prefixindex and Special:Allpages
+* (bug 13924) Fix bad HTML on power search form
+* (bug 13820) Fix updater for rev_parent_id population
+* (bug 13925) Fix bad HTML on search results list
+* (bug 13934) Fixing the link to GNU General Public License Version 2
+* Show correct accesskey prefix for Firefox 3 beta (Alt-Shift-, not Alt-)
+* (bug 13949) Special:PrefixIndex/AllPages paging links contain invalid XML
+* (bug 13770) Use Preprocessor_Hash by default to avoid missing DOM module errors
+* (bug 13982) Disable ccmeonemails preference when user-to-user mails disabled
+* (bug 13615) Update case mappings and normalization to Unicode 5.1.0
+ Note that case mappings will only be used if mbstring extension is not present.
+* (bug 14044) Don't increment page view counters on views from bot users
+* (bug 14042) Calling Database::limitResult() misplaced the comment in the log file
+* (bug 14047) Fix regression in installer which hid DB-specific options
+ Also makes SQLite path configurable in the installer.
+* (bug 13546) Follow image redirects on image page
+* (bug 12644) Template list on edit page now sorted on preview
+* (bug 14058) Support pipe trick for namespaces and interwikis with "-"
+* Message name filter on Special:Allmessages now case-insensitive
+* (bug 13943) Fix image redirect behaviour on image pages
+* (bug 14093) Do 'sysop' => 'protect' magic in Title::isValidMoveOperation
+* (bug 14063) Power search form missing <label> for redirects check
+* (bug 14111) Similar filename warning links now lead to correct page
+* (bug 14082) Fix for complex text input vs AJAX suggestions on some browsers
+* (bug 13693) Categories sometimes claim to have a negative number of members
+* (bug 1701) Korean Hangul syllables now broken down properly in Category lists
+ even if the wiki's overall content language is not Korean
+* (bug 12773) addOnloadHook() now calls functions immediately when scripts are
+ loaded after the primary page completion, instead of dropping them
+* (bug 14199) Fix deletion form for image redirect pages
+* (bug 14220) Disabling $wgCheckFileExtensions now works without also
+ disabling $wgStrictFileExtensions
+* (bug 14241) Pages can no longer be protected to levels you are not in
+* (bug 14296) Fix local name of ang: (Anglo-Saxon)
+* (bug 4871) Hardcoded superscript in time zone preferences moved to message
+* (bug 6957) E-mail confirmation links now using English special page name
+ for better compatibility and keeping the links shorter. Avoids problem
+ with corrupt links in Gmail on IE 6.
+* (bug 14273) Fix for HTTP Accept header parsing with spaces as from Konqueror
+* (bug 14312) Update LanguageKaa.php for handling transform issues with i to İ
+ and I to ı
+* (bug 13826) MediaWiki:Defaultns accepts Wikicode
+* (bug 14324) Creating an account is again possible with $wgEmailConfirmToEdit
+ set to true
+* (bug 13034) Interwiki pages can now be reached using Go search button
+* (bug 14362) Change interwiki names of Erzya and Moksha Wikipedias
+* (bug 14370) When a grouppage-x message does not exist the entry on the
+ ListGroupRights special page now links to the project namespace page for it,
+ not the main namespace page.
+* (bug 11659) Urldecode image names in galleries
+* (bug 14258, 14368) Fix for subpage renames in replication environments
+* (bug 14367) Failed block no longer adds phantom watchlist entry
+* (bug 14385) "Move subpages" option no longer tries to move to invalid titles
+* (bug 14386) Fix subpage namespace oddity when moving a talk page
+* (bug 11771) Signup form now not shown if in read-only mode.
+* (bug 12859) $wgRateLimitsExcludedGroups has been deprecated in favor of
+ $wgGroupPermissions[]['noratelimit'].
+* (Bug 13828) Split parameter $1 of MediaWiki:Missingarticle into $1 (=title)
+ and $2 (=revision numbers)
+* (bug 14401) Fix Safari access key tooltips for Windows and >3.1 Mac versions
+* (bug 14432) Fix notice regression in Special:Newpages feed mode
+* (bug 11951) EditPage::getEditToolbar() is now static.
+* (bug 14392) Fix regression breaking table prefix in installer
+* (bug 11084) $wgDBprefix replacement for updater SQL will now work for
+ extension tables using uppercase letters or digits in their names.
+* (bug 12311) Fix regression with lists at start of undeletion preview
+* (bug 14496) Fix regression with parseinline on Special:Upload.
+* We no longer just give up on a missing upload base directory; it's now
+ created automatically if we have sufficient permissions!
+* (bug 14479) MediaWiki:upload-maxfilesize should have a div id wrapper
+* (bug 14497) Throw visible errors in installer scripts when SQL files
+ fail due to database permission or other error
+* (bug 14500) Site feed (Recentchanges) no longer shows up on the actual
+ recent changes page.
+* (bug 14511) MediaWiki:Delete-legend is no longer double escaped
+* Generate correct section anchors for numeric headers
+* (bug 14520) Don't load nonexistent CSS files for Chick/Myskin/Simple skins
+* (bug 14551) Cancel upload no longer automatically suppresses warnings
+* (bug 13878) Deprecate Article::getDB() in favor of direct wfGetDB() calls
+* (bug 4977) Fix for possible squid purging errors when using HTTP purges
+ and multiple servers
+* (bug 14572) Redirects listed on file links on image pages no longer redirect.
+* (bug 14537) Change interwiki name for Old Church Slavonic (cu)
+* (bug 14583) Fix regression in recent changes "limit to certain categories."
+* (bug 14515) HTML nesting cleanup on edit form
+* (bug 14647) Removed unused 'townBox' CSS classes
+* (bug 14687) OutputPage::addStyle() now adds type="text/css" like it should.
+* OpenSearch cleanup; Firefox now sends you to the search page for empty
+ searches instead of the domain root (which may not even be a wiki).
+* (bug 3481) Pages moved shortly after creation are shown at their new title
+ on Special:Newpages.
+* (bug 12716) Trying to unprotect a title that isn't protected no longer
+ generates a log entry.
+* (bug 14088) Excessively long block expiry times are rejected as invalid,
+ keeps the log page from being distorted.
+* (bug 14708) Emulate INSERT...IGNORE with standard SQL for Postgres backend.
+* (bug 14646) Fix some double-escaping of HTML in feed output
+* (bug 14709) Fix login success message formatting when using cookie check
+* (bug 14710) Remove "donate" link from default sidebar
+* (bug 14745) Image moving works on sites that transform thumbnails via 404
+* (bug 2186) Document.write() in wikibits caused failures when using
+ application/xhtml+xml. The calls to this have been removed.
+* (bug 14764) Fix regression in from Article::lastModified(), failed to work
+ on non-mySQL schemas.
+* (bug 14763) Child classes of Database (DatabasePostgres and DatabaseOracle)
+ had stict standards issues with setFakeSlaveLag() and setFakeMaster().
+* (bug 451) Improve the phrase mappings of the Chinese converter arrays.
+* (bug 12487) Rights log is not fully internationalized
+* (bug 10837) Language variants no longer override other languages than base
+* (bug 14778) 'limit' parameter now applies to history feeds as well as
+ history pages
+* (bug 14845) Bug in prefs javascript: Calling an array item without checking
+ its existance.
+* Accesskeys for minor edit/watch checkboxes on edit now work in Firefox 3
+* (bug 12384) Comments in maintenance/*php
+* (bug 12441) ./maintenance/generateSitemap.php fix -fspath requiring
+ a trailing slash.
+* (bug 12568) configuration script now produce valid XHTML.
+* The accesskey to edit a page is now disabled when editing the page, to pre-
+ vent conflicts with Safari shortcuts.
+
+=== API changes in 1.13 ===
+
+* Fixing main page display in meta=siteinfo
+* (bug 13128) Added patrolled flag to list=recentchanges
+* Implemented {bl,ei,iu}redirect (lists links through redirects as well)
+* (bug 13154) Introduced subpages flag to meta=siteinfo&siprop=namespaces
+* (bug 13157) Added ucuserprefix parameter to list=usercontibs
+* (bug 12394) Added rctitles parameter to list=recentchanges, making rcid
+ retrieval easier
+* (bug 13218) Fix inclusion of " character in hyperlinks
+* Added watch and unwatch parameters to action=delete and action=move
+* Added action=edit
+* (bug 11401) Added xmldoublequote to xml formatter
+* Added rvsection parameter to prop=revisions to allow fetching the content of
+ a certain section only
+* Introduced list=allimages
+* (bug 13371) Build page set from image hashes
+* Mark non-existent messages in meta=allmessages as missing
+* (bug 13390) One invalid title no longer kills an entire API query
+* (bug 13419) Fix gblredirect so it actually works
+* (bug 13418) Disable eiredirect because it's useless
+* (bug 13395) list=allcategories should use category table
+* (bug 13442) Missing pages in prop=langlinks and prop=extlinks are now
+ handled properly.
+* (bug 13444) Add description to list=watchlist
+* (bug 13482) Disabled search types handled properly
+* Added inprop=talkid,subjectid to prop=info
+* Added help text message that specifies whether a module is POST-only
+* Added createonly parameter to action=edit
+* Replaced $wgAPIUCUserPrefixMinLength by the more generic $wgAPIMaxDBRows
+* (bug 11719) Remove trailing blanks in YAML output.
+* (bug 13541) Added siprop=specialpagealiases to meta=siteinfo
+* Added fallback8bitEncoding and readonly fields to
+ meta=siteinfo&siprop=general output
+* (bug 13544) Added prop=revid to action=parse
+* (bug 13603) Added siprop=usergroups to meta=siteinfo
+* Cleaned up redirect resolution
+* Added possibility to obtain all external links through list=exturlusage
+* (bug 13606) Added archivename to iiprop
+* (bug 11633) Explicitly convert redirect titles to strings due to PHP's
+ very weak typing on array keys.
+* (bug 12136) Extend allowed characters in JSON callback to ][.'"_A-Za-z0-9
+* (bug 11673) Return error 'unknown_action' in specified format
+* (bug 13618) Added rcprop=redirect and rcshow=redirect to list=recentchanges
+* (bug 13544) Added oldid parameter to action=parse to allow for parsing of old
+ revisions
+* (bug 13718) Return the proper continue parameter for cmsort=timestamp
+* action=login now returns the correct waiting time in the details property
+* (bug 13792) Broken titles are now silently skipped in search results.
+* (bug 13819) exturlusage paging skipped an item
+* Fixed handling of usernames containing spaces in list=block
+* (bug 13836) Fixed fatal errors resulting from combining iiprop=metadata with
+ format=xml
+* (bug 13735) Added prop=categoryinfo module
+* (bug 13945) Retrieve cascading protection sources via inprop=protection
+* (bug 13965) Hardcoded 51 limit on titles is too limiting
+* (bug 13993) apfrom doesn't work with apdir=descending
+* (bug 14018) Introduced alcontinue to list=alllinks to improve paging
+* (bug 14013) Added rcshow=patrolled to list=recentchanges
+* (bug 14028) Added language attribute to interwiki map in meta=siteinfo
+* (bug 14022) Added usprop=registration and auprop=blockinfo
+* (bug 14021) Removed titles= support from list=backlinks (has been obsolete
+ for ages)
+* (bug 13829) Expose parse tree via action=expandtemplates
+* (bug 13606) Allow deletion of images
+* Added iiprop=mime and aiprop=metadata
+* Handled unrecognized values for parameters more gracefully
+* Handled requesting disallowed tokens more gracefully
+* (bug 14140) URL-encoded page titles are now decoded in edit summaries
+* (bug 14243) Only accept post requests in action=edit; patch by HardDisk
+* action=block now returns an ISO8601 timestamp, like all other modules do
+* Added md5 parameter to action=edit
+* (bug 14335) Logging in to unified account using API not possible
+* Added action=emailuser to send an email to a user
+* (bug 14471) Use HTMLTidy and generate limit report in action=parse
+* (bug 14459) Added prependtext and appendtext parameters to action=edit
+* (bug 14526) Unescaped SQL in list=backlinks
+* Added 'hidden' flag to list=allcategories and prop=categoryinfo output
+* Added nocreate parameter to action=edit
+* (bug 14402) Added maxage and smaxage parameters to api.php
+* Added bkip parameter to list=blocks
+* (bug 14651) apprefix and similar parameters are now canonicalized
+* Added clprop=timestamp to prop=categories
+* (bug 14678) API errors now respects $wgShowExceptionDetails and
+ $wgShowSQLErrors
+* (bug 14723) Added time zone and writing direction to meta=siteinfo
+* Added APIQueryInfoTokens and APIQueryRevisionsTokens hooks so extensions
+ can add their own tokens
+* Added block and unblock tokens to prop=info as well
+* Added paging (limit and continue parameters) to
+ prop={links,templatelinks,langlinks,extlinks,categories,images}
+* Added flag "top" to list=usercontribs if the user is the last contributor to
+ the page
+* list=exturlusage in "list all links" mode can now filter by protocol
+
+
+
== MediaWiki 1.12 ==
This is the Winter 2007 quarterly release.
@@ -30,7 +675,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
remove the groups specified in $wgAddGroups and $wgRemoveGroups for
any groups they are in.
* New permission userrights-interwiki for changing user rights on foreign wikis.
-* $wgImplictGroups for groups that are hidden from Special:Listusers, etc.
+* $wgImplicitGroups for groups that are hidden from Special:Listusers, etc.
* $wgAutopromote: automatically promote users who match specified criteria
* $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf: allow users to add or remove
themselves from specified groups via Special:Userrights.
@@ -2511,7 +3156,7 @@ they will be run along with the main tests by maintenance/parserTests.php
* (bug 6701) Kazakh language variants in MessagesEn.php
* (bug 7335) SVN revision check in Special:Version fails on SVN 1.4 working copy
* (bug 6518) Replaced 'lastmodified' with 'lastmodifiedat' and 'lastmodifiedby' with 'lastmodifiedatby'
- with seperated parameters for date and time to allow better localisation. Updated all message files
+ with separated parameters for date and time to allow better localisation. Updated all message files
to display the old format for compatibility.
* (bug 7357) Make supposedly static methods of Skin actually static
* Added info text to Special:Deadendpages and Special:Lonelypages
@@ -4584,7 +5229,7 @@ Various bugfixes, small features, and a few experimental things:
* Fixed a bug in Special:Contributions that caused the namespace selection to
be forgotten between submits
* Special:Watchlist/edit now has namespace subheadings
-* (bug 1714) the "Save page" button now has right margin to seperate it from
+* (bug 1714) the "Save page" button now has right margin to separate it from
"Show preview" and "Show changes"
* Special:Statistics now supports action=raw, useful for bots designed to
harwest e.g. article counts from multiple wikis.
diff --git a/README b/README
index 5f659df5..7c3651e0 100644
--- a/README
+++ b/README
@@ -1,15 +1,15 @@
-2007-09-15
+2008-11-11
-For system requirements, installation and upgrade details, see the files RELEASE-NOTES,
-INSTALL, and UPGRADE.
+For system requirements, installation and upgrade details, see the files
+RELEASE-NOTES, INSTALL, and UPGRADE.
== MediaWiki ==
MediaWiki is the software used for Wikipedia [http://www.wikipedia.org/] and the
other Wikimedia Foundation websites. Compared to other wikis, it has an
excellent range of features and support for high-traffic websites using
-multiple servers (Wikimedia sites peak in the 50000+ requests per second range
-as of January 2008).
+multiple servers (Wikimedia sites peak in the 60000+ requests per second range
+as of November 2008).
While quite usable on smaller sites, you may find you have to "roll your own"
local documentation, and some aspects of configuration may seem overcomplicated
@@ -33,21 +33,24 @@ The MediaWiki software was written by:
* Domas Mituzas
* Rob Church
* Jens Frank
-* Several others
-
-The contributors hold the copyright to this work, and it is licensed
-under the terms of the GNU General Public License, version 2 or later[1]
-(see http://www.fsf.org/licenses/gpl.html). Derivative works and later
-versions of the code must be free software licensed under the same
-terms. This includes "extensions" that use MediaWiki functions or
-variables; see http://www.gnu.org/licenses/gpl-faq.html#GPLAndPlugins
-for details.
+* Yuri Astrakhan
+* Aryeh Gregor
+* Aaron Schulz
+* Several others (view CREDITS for a more complete list)
+
+The contributors hold the copyright to this work, and it is licensed under the
+terms of the GNU General Public License, version 2 or later[1] (see
+http://www.fsf.org/licensing/licenses/gpl.html). Derivative works and later
+versions of the code must be free software licensed under the same or a
+compatible license. This includes "extensions" that use MediaWiki functions or
+variables; see http://www.gnu.org/licenses/gpl-faq.html#GPLAndPlugins for
+details.
The Wikimedia Foundation currently has no legal rights to the software.
-[1] Sections of code written exclusively by Lee Crocker or Erik Moeller are
-also released into the public domain, which does not impair the obligations of
-users under the GPL for use of the whole code or other sections thereof.
+[1] Sections of code written exclusively by Lee Crocker or Erik Moeller are also
+released into the public domain, which does not impair the obligations of users
+under the GPL for use of the whole code or other sections thereof.
[2] MediaWiki makes use of the Sajax Toolkit by modernmethod,
http://www.modernmethod.com/sajax/
@@ -65,13 +68,12 @@ The official website for MediaWiki is located at:
http://www.mediawiki.org/
-The code is currently maintained in a Subversion repository
-at svn.wikimedia.org. See http://www.mediawiki.org/wiki/Subversion
-for details.
+The code is currently maintained in a Subversion repository at
+svn.wikimedia.org. See http://www.mediawiki.org/wiki/Subversion for details.
Please report bugs and make feature requests in our Bugzilla system:
- http://bugzilla.wikimedia.org/
+ https://bugzilla.wikimedia.org/
Documentation and discussion on new features may be found at:
@@ -86,18 +88,18 @@ Extensions are listed at:
If you are setting up your own wiki based on this software, it is highly
recommended that you subscribe to mediawiki-announce:
- http://lists.wikimedia.org/mailman/listinfo/mediawiki-announce
+ https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce
-The mailing list is very low volume, and is intended primarily for
-announcements of new versions, bug fixes, and security issues.
+The mailing list is very low volume, and is intended primarily for announcements
+of new versions, bug fixes, and security issues.
A higher volume support mailing list can be found at:
- http://lists.wikimedia.org/mailman/listinfo/mediawiki-l
+ https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
Developer discussion takes place at:
- http://lists.wikimedia.org/mailman/listinfo/wikitech-l
+ https://lists.wikimedia.org/mailman/listinfo/wikitech-l
-There is also a development and support channel #mediawiki on
-irc.freenode.net, and an unoffical support forum at www.mwusers.com.
+There is also a development and support channel #mediawiki on irc.freenode.net,
+and an unoffical support forum at www.mwusers.com.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 1071830b..7ce61f90 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,12 +1,13 @@
= MediaWiki release notes =
-For upgrade instructions please see the UPGRADE file in this directory.
+Security reminder: MediaWiki does not require PHP's register_globals
+setting since version 1.2.0. If you have it on, turn it *off* if you can.
-== MediaWiki 1.13.4 ==
+== MediaWiki 1.14.0 ==
-February 7, 2009
+February 22, 2009
-This is a security update to the Summer 2008 snapshot release of MediaWiki.
+This is the first stable release of the 2009 Q1 branch of MediaWiki.
MediaWiki is now using a "continuous integration" development model with
quarterly snapshot releases. The latest development code is always kept
@@ -19,687 +20,616 @@ will be made on the development trunk and appear in the next quarterly release.
Those wishing to use the latest code instead of a branch release can obtain
it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
-== Changes since 1.13.3 ==
-
-A number of cross-site scripting (XSS) security vulnerabilities were discovered
-in the web-based installer (config/index.php). These vulnerabilities all
-require a live installer -- once the installer has been used to install a wiki,
-it is deactivated.
-
-Note that cross-site scripting vulnerabilities can be used to attack any website
-in the same cookie domain. So if you have an uninstalled copy of MediaWiki on
-the same site as an active web service, MediaWiki could be used to attack the
-active service.
-
-If you are hosting an old copy of MediaWiki that you have never installed, you
-are advised to remove it from the web.
-
-== Changes since 1.13.2 ==
-
-David Remahl of Apple's Product Security team has identified a number of
-security issues in previous releases of MediaWiki. Subsequent analysis by the
-MediaWiki development team expanded the scope of these vulnerabilities. The
-issues with a significant impact are as follows:
-
-* An XSS vulnerability affecting all MediaWiki installations between 1.13.0 and
- 1.13.2. [CVE-2008-5249]
-* A local script injection vulnerability affecting Internet Explorer clients for
- all MediaWiki installations with uploads enabled. [CVE-2008-5250]
-* A local script injection vulnerability affecting clients with SVG scripting
- capability (such as Firefox 1.5+), for all MediaWiki installations with SVG
- uploads enabled. [CVE-2008-5250]
-* A CSRF vulnerability affecting the Special:Import feature, for all MediaWiki
- installations since the feature was introduced in 1.3.0. [CVE-2008-5252]
-
-XSS (cross-site scripting) vulnerabilities allow an attacker to steal an
-authorised user's login session, and to act as that user on the wiki. The
-authorised user must visit a web page controlled by the attacker in order to
-activate the attack. Intranet wikis are vulnerable if the attacker can
-determine the intranet URL.
-
-Local script injection vulnerabilities are like XSS vulnerabilities, except
-that the attacker must have an account on the local wiki, and there is no
-external site involved. The attacker uploads a script to the wiki, which another
-user is tricked into executing, with the effect that the attacker is able to act
-as the privileged user.
-
-CSRF vulnerabilities allow an attacker to act as an authorised user on the wiki,
-but unlike an XSS vulnerability, the attacker can only act as the user in a
-specific and restricted way. The present CSRF vulnerability allows pages to be
-edited, with forged revision histories. Like an XSS vulnerability, the
-authorised user must visit the malicious web page to activate the attack.
-
-These four vulnerabilities are all fixed in this release.
-
-David Remahl also reminded us of some security-related configuration issues:
-
-* By default, MediaWiki stores a backup of deleted images in the images/deleted
- directory. If you do not want these images to be publically accessible, make
- sure this directory is not accessible from the web. MediaWiki takes some steps
- to avoid leaking these images, but these measures are not perfect.
-* Set display_errors=off in your php.ini to avoid path disclosure via PHP fatal
- errors. This is the default on most shared web hosts.
-* Enabling MediaWiki's debugging features, such as $wgShowExceptionDetails, may
- lead to path disclosure.
-
-Other changes in this release:
-
-* Avoid fatal error in profileinfo.php when not configured.
-* Add a .htaccess to deleted images directory for additional protection against
- exposure of deleted files with known SHA-1 hashes on default installations.
-* Avoid streaming uploaded files to the user via index.php. This allows
- security-conscious users to serve uploaded files via a different domain, and
- thus client-side scripts executed from that domain cannot access the login
- cookies. Affects Special:Undelete, img_auth.php and thumb.php.
-* When streaming files via index.php, use the MIME type detected from the
- file extension, not from the data. This reduces the XSS attack surface.
-* Blacklist redirects via Special:Filepath. Such redirects exacerbate any
- XSS vulnerabilities involving uploads of files containing scripts.
-* Internationalisation updates.
-
-== Changes since 1.13.1 ==
-
-* Security: Work around misconfiguration by requiring strict comparisons for
- in_array in User::isAllowed().
-* (bug 14944) Added $wgShellLocale for configuration of an appropriate locale
- to use for LC_CTYPE during shell invocation. For servers that don't have
- en_US.utf8. Also added locale detection during install.
-* Localisation updates
-* Security: Fixed XSS vulnerability in useskin parameter.
-
-== Changes since 1.13.0 ==
-
-* (bug 15460) Fixed intermittent deadlock errors and poor concurrent
- performance for installations without memcached.
-* (bug 13770) Fixed DOM module detection for installations with both dom
- and domxml.
-* (bug 15148) Fixed Special:BlockIP for PostgreSQL
-* Fixed SQLite support for non-memcached installations
-* Localisation updates, Achinese (ace) added.
-
-== Changes since 1.13.0rc2 ==
+NOTE: Installation of MediaWiki on SQLite has been temporarily disabled in this
+release due to the discovery of serious problems with the schema. We expect to
+fix this problem for the release of 1.15.0.
-* (bug 13770) Fixed incorrect detection of PHP's DOM module
-* Fix regression from r37834: accesskey tooltip hint should be given for the
- minor edit and watch labels on the edit page.
-* Updated Chinese simplified/traditional conversion tables
+== Changes since 1.14.0rc1 ==
+
+* Fixed the performance of the backlinks API module
+* (bug 17420) Send the correct content type from action=raw when the HTML file
+ cache is enabled.
+* (bug 17437) Fixed incorrect link to web-based installer
+* (bug 17527) Fixed missing MySQL-specific options in installer
-== Changes since 1.13.0rc1 ==
+=== Configuration changes in 1.14 ===
+* $wgExemptFromUserRobotsControl is an array of namespaces to be exempt from
+ the effect of the new __INDEX__/__NOINDEX__ magic words. (Default: null, ex-
+ empt all content namespaces.)
* $wgForwardSearchUrl has been removed entirely. Documented setting since 1.4
has been $wgSearchForwardUrl.
+* (bug 15080) $wgOverrideSiteFeed has been added. Setting either
+ $wgSiteFeed['rss'] or 'atom' to a URL will override the default Recent
+ Changes feed that appears on all pages.
+* $wgSQLiteDataDirMode has been introduced as the default directory mode for
+ SQLite data directories on creation. Note that this setting is separate from
+ $wgDirectoryMode, which applies to all normal dirs created by MediaWiki.
+* $wgGroupsAddToSelf and $wgGroupsRemoveFromSelf now work more like
+ $wgAddGroups and $wgRemoveGroups, where the user must belong to a specified
+ group in order to add or remove those groups from themselves.
+ Backwards compatibility is maintained.
+* $wgRestrictDisplayTitle controls if the use of the {{DISPLAYTITLE}} magic
+ word is restricted to titles equivalent to the actual page title. This
+ is true per default, but can be set to false to allow any title.
+* $wgSpamRegex may now be an array of multiple regular expressions.
+* $wgAjaxSearch has been removed; use $wgEnableMWSuggest instead.
+* Editing the MediaWiki namespace is now unconditionally restricted to people
+ with the editinterface right, configuring this in $wgNamespaceProtection
+ is not required.
+* $wgAllowExternalImagesFrom may now be an array of multiple strings.
+* Introduced $wgEnableImageWhitelist to toggle the on-wiki external image
+ whitelist on or off.
+* Added $wgRenderHashAppend to append some string to the parser cache and the
+ sitenotice cache keys.
+* $wgRCChangedSizeThreshold is now a positive integer by default,
+* (bug 16006) $wgEnableWriteAPI is now true by default. Authorized can perform
+ write actions using the API.
+* Added $wgRC2UDPInterwikiPrefix which adds an interwiki prefix
+ ($wgLocalInterwiki) onto the page names in the UDP feed.
+* Added $wgAllowUserSkin to let the wiki's owner disable user selectable skins
+ on the wiki. If it's set to true, then the skin used will *always* be
+ $wgDefaultSkin.
+* Added $wgEnotifUseRealName, which allows UserMailer to send out e-mails based
+ on the user's real name if one is set. Defaults to false (use the username)
+* Removed the 'apiThumbCacheDir' option from $wgForeignFileRepos (only used in
+ ForeignAPIRepo)
+* (bug 44) Image namespace and accompanying talk namespace renamed to File.
+ For backward compatibility purposes, Image still works. External tools may
+ need to be updated.
+* The constants NS_FILE and NS_FILE_TALK can now be used instead of NS_IMAGE and
+ NS_IMAGE_TALK. The old constants are retained as aliases for compatibility,
+ and should still be used in code meant to be compatible with v1.13 or older.
+* MediaWiki can be forced to use private IPs forwarded by a proxy server by
+ using $wgUsePrivateIPs.
+* The 'BeforeWatchlist' hook has been removed due to internal changes in
+ Special:Watchlist. 'SpecialWatchlistQuery' should now be used by extensions
+ to customize the watchlist database query.
+
+
+=== Migrated extensions ===
+The following extensions are migrated into MediaWiki 1.14:
+
+* Special:DeletedContributions to show deleted user contributions (was
+ extension DeletedContributions)
+* Special:Log/newusers recording new users (was extension Newuserlog)
+* Special:LinkSearch to search for external links (was extension LinkSearch)
+* RenderHash
+* NoMoveUserPages
+* UniversalEditButton
+
+=== New features in 1.14 ===
+
+* New URL syntaxes for Special:ListUsers - 'Special:ListUsers/USER' and
+ 'Special:ListUsers/GROUP/USER', in addition to the older syntax
+ 'Special:ListUsers/GROUP' where GROUP is a valid group name.
+* Configurable per-namespace and per-page notices for the edit form,
+ respectively MediaWiki:Editnotice-# where # is the namespace number, and
+ MediaWiki:Editnotice-#-PAGENAME where # is the page's namespace number and
+ PAGENAME is the page name minus the namespace prefix.
+* (bug 8068) New __INDEX__ and __NOINDEX__ magic words allow user control of
+ search engine indexing on a per-article basis.
+* Handheld stylesheet options
+* Added 'DoEditSectionLink' hook as a cleaner unified version of the old
+ 'EditSectionLink' and 'EditSectionLinkForOther' hooks. Note that the
+ 'EditSectionLinkForOther' hook has been removed, but 'EditSectionLink' is
+ run in all cases instead, so extensions using the old hooks should still work
+ if they ran roughly the same code for both hooks (as is almost certain).
+* Signature (~~~~) "cleaning", i.e. template removal, can be disabled with
+ $wgCleanSignatures=false
+* Extensions can use the SkinBuildSidebar hook to modify the content of the
+ sidebar and add custom portlets to it
+* Added 'MakeGlobalVariablesScript' hook for extensions to be able to add vari-
+ ables into into the output of Skin::makeVariablesScript
+* (bug 13846) Added $wgAddGroups and $wgRemoveGroups display on
+ Special:ListGroupRights
+* (bug 14377) Add a date selector to history pages
+* (bug 15007) New 'pagetitle-view-mainpage' message allows the HTML <title> of
+ the main page to be customized
+* Added $wgDisableTitleConversion to disabling the conversion for all pages on
+ the wiki
+* Added 'noconvertlink' toggle that can be set per user preferences, also
+ added 'convertlink=no|yes' on GET requests whether have the link titles
+ being converted or not
+* (bug 14921) Special:Contributions/: add user name to <title>
+ Patch by Emufarmers
+* Unescape more "safe" characters when producing URLs, for added prettiness
+* Introduced a new hook 'SkinAfterContent' that allows extensions to add text
+ after the page content and article metadata. Updated all skins and skin
+ templates to work with that hook.
+* (bug 14929) removeUnusedAccounts.php now supports 'ignore-touched' and
+ 'ignore-groups'. Patch by Louperivois
+* (bug 15127) Work around minor display glitch in Opera.
+* By default, reject file uploads that look like ZIP files, to avoid the
+ so-called GIFAR vulnerability.
+* (bug 15141) Give ability to only list protected pages with the cascading
+ option enabled on Special:ProtectedPages
+* (bug 15157) Special:Watchlist has the same options as Special:Watchlist:
+ Show/Hide logged in users, Show/Hide anonymous, Invert namespace selection
+* Added hook 'UserrightsChangeableGroups' to allow modification of what
+ groups may be added or removed via the Special:UserRights interface.
+* HTML entities like &nbsp; now work (are not escaped) in edit summaries.
+* (bug 13815) In the comment for page moves, use the colon-separator message
+ instead of a hardcoded colon.
+* Allow <gallery> to accept image names without an Image: prefix
+* Add tooltips to rollback and undo links
+* BMP images are now displayed as PNG
+* (bug 13471) Added NUMBERINGROUP magic word
+* (bug 11884) Now support Flash EXIF attribute
+* Show thumbnails in the file history list, patch by User:Agbad
+* Added support of piped wikilinks using double-width brackets
+* Added an on-wiki external image whitelist. Items in this whitelist are
+ treated as regular expression fragments to match for when possibly
+ displaying an external image inline.
+* (bugs 15405, 15436) Sort more currency types correctly in sortable tables
+* (bug 15422) Sort more different types of numbers in sortable tables
+* (bug 2889) MediaWiki:Print.css applies to the printable version
+* Category counts (e.g. from {{PAGESINCATEGORY:}}) should be more accurate for
+ small categories
+* After logging in, automatically redirect to wherever you logged in from
+* (bug 5619) Break messages used in Special:Statistics down further
+* (bug 11029) Add link to Special:Listusers?group=sysop etc at
+ Special:Statistics
+* (bug 15514) Setting $wgRightsText without $wgRightsUrl now produces a
+ plaintext copyright notice. Patch by Juliano F. Ravasi.
+* (bug 15551) Deletion log excerpt is now shown whenever a user vists a
+ deleted page, even if they are unable to edit it.
+* Added Wantedfiles special pages, allowing users to find image links with no
+ image.
+* (bug 12650) It is now possible to set different expiration times for
+ different restriction types on the protection form.
+* (bug 8440) Allow preventing blocked users from editing their talk pages
+* Improved upload file type detection for OpenDocument formats
+* Added the ability to set the target attribute on external links with
+ $wgExternalLinkTarget
+* api.php now sends "Retry-After" and "X-Database-Lag" HTTP headers if the
+ maxlag check fails, just like index.php does
+* Added "link" parameter to image links, to allow images to link to an
+ arbitrary title or URL. This should replace inaccessible and incomplete
+ solutions such as CSS-based overlays and ImageMap.
+* (bug 368) Don't use caption for alt attribute; allow manual specification
+ using new "alt=" parameter for images
+* (bug 44) The {{ns:}} core parser function now also accepts localized
+ namespace names and aliases; also, its output now uses spaces instead of
+ underscores to match the behavior of the {{NAMESPACE}} magic word
+* Added the ability to display user edit counts in Special:ListUsers. Off by
+ default, enabled with $wgEdititis = true (named after the medical condition
+ marked by unhealthy obsession with edit counts).
+* Added a file cache to the parser to improve page rendering time on pages with
+ several uses of the same image.
+* (bug 1250) Users can still use "show preview" and "show changes" even if the
+ wiki is set to read-only mode.
+* Added a call to the 'UnwatchArticleComplete' hook to the watchlist editor.
+ This should make it so that ALL user-accessible methods of removing a page
+ from a watchlist lead to this hook being called (it was previously only
+ called from within Article.php
+* Maximum execution time for shell processes on linux is now configured with
+ $wgMaxShellTime (180 seconds by default)
+* (bug 1306) 'Email user' link no longer shown on user page when emailing
+ is not available due to lack of confirmed address or disabled preference
+* Special:Wanted templates special page added to display missing templates
+ linked from articles
+* Make search matches bold only, not red as well
+* (bug 10080) Blocks can be modified without unblocking first
+* (bug 15820) Special:BlockIP shows a notice if the user being blocked is
+ already directly blocked
+* (bug 13710) Allow to force "watch this" checkbox via URL using parameter
+ "watchthis"
+* (bug 15125) Add Public Domain to default options when installing. Patch by
+ Nathan Larson.
+* Set a special temporary directory for ImageMagick with $wgImageMagickTempDir
+* (bug 16113) Show/hide for redirects in Special:NewPages
+* (bug 15903) Upload link was added to Nostalgia skin
+* (bug 15761) Add user toggle to omit diff after rollback
+* Added the BitmapHandler_ClientOnly media handler, which allows server-side
+ image scaling to be completely disabled for specific media types, via the
+ $wgMediaHandlers configuration variable.
+* New 'AbortDiffCache' hook can be used to cancel the caching of a diff
+* (bug 15835) Added Content-Style-Type meta tag
+* (bug 11027) Add parameter to MW:Randompage-nopages so that user can see the
+ namespace.
+* Add id="mw-user-domain-section" to <tr> tag in Userlogin.php template so that
+ admins with a single domain can hide the domain section using CSS
+* Dropped old Paser_OldPP class. Only new parser with preprocessor is used.
+* Moved password reset form from Special:Preferences to Special:ResetPass
+* Added Special:ChangePassword as a special page alias for Special:ResetPass
+* Added complimentary function for addHandler() called removeHandler() for removing events
+* Improved security of file uploads for IE clients, using a reverse-engineered
+ algorithm very similar to IE's content detection algorithm.
+* Cascading protection no longer requires that both edit and move are restricted
+ to sysop, just edit=sysop is enough
+* (bug 2391) A warning is now shown for invalid ISBN numbers on Special:Booksources.
+* Installer has been updated to reflect the release of the GFDL 1.3. The URL for 1.2
+ has been updated, and the 1.3 URL has been given. 1.2 is still Wikipedia-compatible.
+ RightsCode was changed from 'gfdl' to 'gfdl1_2', so we can now support 1.2 as well
+ as 1.3 (gfdl1_3).
+* (bug 16293) PD URL was changed to the CreativeCommons site on PD (which auto-detects
+ your language) instead of Wikipedia.
+* (bug 16635) The "view and edit watchlist" page (Special:Watchlist/edit) now
+ includes a table of contents
+* File objects returned by wfFindFile() are now cached by default
+* (bug 7492) Rights can now be assigned to specific IP addresses and ranges by
+ using $wgAutopromote (new defines: APCOND_ISIP and APCOND_IPINRANGE)
+* Add a 'change block' link to Special:IPBlockList and Special:Log
+* (bug 16459) Use native getElementsByClassName where possible, for better
+ performance in modern browsers
+* Enable \cancel and \cancelto in texvc (recompile required)
+* Added 'UserCryptPassword' and 'UserComparePasswords' hooks to allow extensions to implement
+ their own password hashing methods.
+* (bug 16760) Add CSS-class to action links of Special:Log
+* (bug 505) Time zones can now be specified by location in user preferences,
+ avoiding the need to manually update for DST. Patch by Brad Jorsch.
+* (bug 2585) HTTP 404 return code is now given for a page view if the page
+ does not exist, allowing spiders and link checkers to detect broken links.
+* Special:Log: Add 'change protection' link for unprotected pages too
+* Special:Log: Add log type specific CSS classes 'mw-logline-$logtype' to
+ 'li' elements
+* (bug 16754) Making arbitrary rows of sortable tables sticky:
+ |- class="unsortable"
+* Show subversion too even if a "normal" version number is available
+* (bug 16121) Add a note that a page move was without creating a redirect in the
+ move log
+* Image moving is now enabled for sysops by default
+* Make "Did you mean" search feature more noticeable
+* (bug 16720) Transcluded Special:NewPages processes "/username="
+
+=== Bug fixes in 1.14 ===
+
* (bug 14907) DatabasePostgres::fieldType now defined.
-* (bug 14966) Fix SearchEngineDummy class for silently non-functional search
- on Sqlite instead of horribly fatal error breaky one.
-* (bug 14987) Only fix double redirects on page move when the checkbox is
- checked
-* (bug 13376) Use $wgPasswordSender, not $wgEmergencyContact, as return
- address for page update notification mails.
-* API: Registration time of users registered before the DB field was created is now
+* (bug 14659) Passing the default limit param to Special:Recentchanges no more
+ falls back to the user option
+* (bug 14954) Fix regression in Modern and Simple skins
+* Recursion loop check added to Categoryfinder class
+* Fixed few performance troubles of large job queue processing
+* Not setting various parameters in Foreign Repos now fails more gracefully
+* (bug 2333) Redirects are properly rendered when previewing an edit.
+* (bug 14972) Use localized alias of Special:Search on all search forms
+* (bug 11035) Special:Search should have descriptive <title>
+* Special pages are now not subject to special handling for "self-links"
+* (bug 15053) Syntactically incorrect redirects with another link in them
+ no longer redirect to the second link
+* (bug 15049) Fix for CheckUser extension's log search: usernames containing
+ a "-" were incorrectly turned into bogus IP range searches.
+ Patch by Max Semenik.
+* (bug 15055) Talk page notifications no longer attempt to send mail when
+ user's e-mail address is invalid or unconfirmed
+* (bug 12370) Add throttle on password attempts. Defaults to max 5 attempts in
+ 5 minutes.
+* (bug 15016) 'Templates used on this page' list in view source should be
+ wrapped in a div with class "templatesUsed"
+* (bug 14868) Setting $wgFeedDiffCutoff to 0 now disables generation of the
+ diff entirely, not just the display of it.
+* (bug 6387) Introduced new setting $wgCategoryPrefixedDefaultSortkey which
+ allows having the unprefixed page title as the default category sortkey
+* (bug 15079) Add class="ns-talk" / "ns-subject" to <body>. Also added
+ ns-special to special pages.
+* (bug 15052) Skins should add their name as a class in <body>
+* (bug 14165, bug 14294) Wikimedia specific configuration in convertGrammar()
+ for several languages was removed. The settings have been put in extension
+ WikimediaMessages. Patch for Czech by Danny B.
+* (bug 15101) Displaying only bots edits in Special:Recentchanges now works
+ again
+* (bug 13770) Fixed incorrect detection of PHP's DOM module
+* (bug 14790) Export of category pages when using Category: prefix now actually
+ gives results
+* Avoid recursive crazy expansions in section edit comments for pages which
+ contain '/*' in the title
+* Fix excessive memory usage when parsing pages with lots of links
+* $wgSpamRegex now matches the edit summary and page move descriptions in
+ addition to body text.
+* Navigation links to images available from a shared repository (like Commons)
+ from their local talk pages no longer appear as redlinks
+* Action=purge on ForeignApiFiles now works (purges their thumbnails and
+ description pages).
+* (bug 15303) Title conversion for templates wasn't working in some cases.
+* (bug 15264) Underscores in Special:Search/Foo_bar parameters were taken
+ literally; now converting them to spaces per expectation.
+* (bug 15342) "Invert" checkbox now works correctly when selecting main
+ namespace in Special:Watchlist
+* (bug 15172) 'Go' button of Special:Recentchanges now on the same line as the
+ last input element (like Special:Watchlist too)
+* (bug 15351) Fix fatal error for invalid section fragments in autocomments
+* Fixed intermittent deadlock errors involving objectcache table queries.
+ Use a separate database connection for the objectcache table to avoid
+ long-lasting locks on that table.
+* Respect file restrictions in the file history list
+* (bug 15399) Odd/even classes on sortable tables' rows could be slow for large
+ tables, and have been disabled by default.
+* (bug 15482) Special:Recentchangeslinked has no longer two submit buttons
+* (bug 15292) New message notification for unregistred users now works again
+* (bug 14398) mwsuggest.js: Let width of container be configurable
+* (bug 15543) Only include user touched timestamp to generated CSS
+* (bug 15497) Removed encoding attribute from <?xml ?> tag
+* (bug 12284) Special:Preferences now sets a returnto parameter on the link to
+ Special:UserLogin. Patch by Marooned.
+* Fixed the HTTP accept language string detection length in
+ LanguageConverter.php, instead of the fixed length language codes.
+* Special:RecentChangesLinked no longer shows outgoing links for nonexistent
+ pages even if there are broken link records with source article id 0 in the
+ database
+* (bug 15598) Special:Newpages default limit uses user preference for
+ recentchanges limit instead of hardcoded 50.
+* (bug 15617) $wgFeedClassesOutputPage::getHeadLinks() respects $wgFeedClasses,
+ instead of hardcoding rss and atom. Patch by Juliano F. Ravasi.
+* (bug 14638) Special:Blockip now provides a link to the block log if the user
+ has been blocked more than 10 times. Patch by Matt Johnston.
+* (bug 12678) Skins don't show Upload link if the user isn't allowed to upload.
+* Fixed incorrect usage of DB_LAST in Special:Export. Deprecated DB_LAST.
+* (bug 15642) Blocked sysops can no longer block other users
+* Http::request() now respects $wgHTTPtimeout when not using cURL
+* (bug 15158) Userinvalidcssjstitle not shown on preview
+* (bug 15196) Free external links should be numbered in a localised manner
+* (bug 15388) Title of Special:PrefixIndex
+* Links with no title but a curid parameter now use the curid to pick a page
+* (bug 10323) Special:Undelete should have "inverse selection" button
+* (bug 15831) Modern skin RTL support is bugous
+* (bug 15869) Nostalgia skin does not show page title in printable mode
+* (bug 15795) Special:Userrights is now listed on Special:SpecialPages when the
+ user can only change his rights
+* (bug 15846) Categories "leak" from older revisions in certain circumstances
+* (bug 15928) Special pages dropdown should be inline in non-MonoBook skins
+* (bug 14178) Some uses of UserLoadFromSession hook cause segfault
+* (bug 15925) Postitive bytes added on recentchanges and watchlists are now
+ bolded if above the threshold, previously it only worked for negatives
+* Specify apple-touch-icon before favicon in HTML head section to make the
+ Konqueror browser correctly use the latter
+* (bug 15717) Set $separatorTransformTable for language 'eu'
+* (bug 15605) Enabled $datePreferences for language 'hr'. Added standard date
+ preferences.
+* (bug 13701) {{NUMBEROFVIEWS}} magic word to show number of total views.
+* (bug 5101) Image from Commons doesn't show up when searched in Wikipedia
+ search box
+* (bug 14609) User's namespaces to be searched default not updated after adding
+ new namespace
+* Purge form uses valid XHTML
+* (bug 12764) Special:LonelyPages shows transcluded pages
+* (bug 16073) Enhanced RecentChanges uses onclick handler with better fallback
+ if JavaScript is disabled
+* (bug 4253) Recentchanges IRC messages no longer include title in diff URLs
+* Allow '0' to be an accesskey.
+* (bug 8063) Use language-dependent sorting in client-side sortable tables
+* (bug 16160) Suggestions box should be resized from left for RTL wikis
+* (bug 11533) Fixed insane slowdown when in read-only mode for long periods
+ of time with CACHE_NONE (default objectcache table configuration).
+* Trying to set two different default category sort keys for one page now
+ produces a warning
+* (bug 16143) Fix redirect loop on special pages starting with lower case
+ letters
+* (bug 15737) Fix notices while expanding using PPCustomFrame
+* (bug 15544) Non-index entry points cause the "Wiki not set up" message to
+ have corrupt URLs
+* (bug 5101) Image from Commons doesn't show up when searched in Wikipedia
+ search box
+* (bug 4362) [[MediaWiki:History copyright]] no more used with most recent
+ revision when passing oldid parameter in the url
+* (bug 16265) When caching thumbs with the ForeignApiRepo, we now use the same
+ filename as the remote site.
+* (bug 8345) Don't autosummarize where a redirect was left unchanged
+* Made thumb caching in ForeignApiFile objects integrated with normal thumb
+ path naming (/thumbs/hash/file), retired 'apiThumbCacheDir' as a result.
+* (bug 5530) Consistency between character encoding in {{PAGENAMEE}},
+ {{SUBPAGENAMEE}} and {{FULLPAGENAMEE}}
+* Safer handling of non-MediaWiki exceptions -- now obeys our settings for
+ formatting and path exposure.
+* Less verbose errors from profileinfo.php when not configured
+* Blacklist redirects via Special:Filepath, hard to use.
+* Improved input validation on Special:Import form
+* Add a .htaccess to deleted images directory for additional protection
+ against exposure of deleted files with known SHA-1 hashes on default
+ installations.
+* Improved scripting safety heuristics for IE 5/6 content-type detection.
+* Improved scripting safety heuristics on SVG uploads.
+* (bug 11728) Unify layout of enhanced watchlist/recent changes
+* (bug 8702) Properly update stats when running nukePage maintenance script
+* (bug 7726) Searches for words less than 4 characters now work without
+ requiring customization of MySQL server settings
+* Honour unchecked "Leave a redirect behind" for moved subpages
+* (bug 16440) Broken 0-byte math renderings are now deleted and re-rendered
+ when page is re-parsed.
+* (bug 6100) Unicode BiDi embedding/override characters (U+202A - U+202E) are
+ now automatically removed from titles; these characters can accidentally end
+ up in copy-and-pasted titles, and, by overriding normal bidirectional text
+ handling, can lead to annoying behavior such as text rendering backwards
+* Fixed minor bug where the memcached value for how many accounts an IP had
+ created that day would be increased even if $wgAccountCreationThrottle was
+ hit. This meant if an IP hit the throttle and then the throttle was raised
+ later that day, the IP still couldn't create another account, because it
+ had marked them as having created another account, when their last account
+ creation had actually failed.
+* (bug 12647) Allow autogenerated edit summary messages to be blanked with '-'
+* (bug 16026) 'Revision-info' and 'revision-info-current' both accept wiki
+ markup now.
+* (bug 16529) Fix for search suggestions with some third-party JS libraries
+* (bug 13342) importScript() generates more consistent URI encoding
+* (bug 16577) When a blocked user tries to rollback a page, the block message
+ is now only displayed once
+* (bug 14268) SVG image sizes now extracted with proper XML parser
+* (bug 14365) RepoGroup::findFiles() no longer crashes if passed an invalid
+ title via the API
+* (bug 4253, bug 16586) Revision ID is now given instead of title in URLs for
+ new pages in the recent changes IRC feed
+* Ugly tooltips in Special:Statistics were phased out in favor of more direct
+ information. Went ahead and rewrote SpecialStatistics to subclass SpecialPage
+* (bug 5506) Links to files on foreign repositories are now shown consistently
+ as bluelinks e.g. in logs and edit summaries
+* (bug 16623) Add missing </p> tag in Special:LockDB
+* (bug 15849) Special:Movepage now throws a more specific error when trying to
+ move a title to an interwiki target
+* (bug 16638) 8-bit URL fallback encoding now set on additional languages using
+ Arabic script (Persian, Urdu, Sindhi, Punjabi)
+* (bug 16656) cleanupTitles and friends should now work in load-balanced
+ DB environments when $wgDBserver isn't set.
+* (bug 3691) Aspect ratio from viewBox attribute is now preserved for SVG
+ images which do not specify width and height attributes.
+* (bug 15027) Internet domain names and IP addresses can now be indexed and
+ searched sensibly with the default MySQL search backend.
+* (bug 11733) Fixed parameter validation in importTextFile.php
+* (bug 16712) Special:NewFiles updated to use "newer"/"older" paging messages
+ for clarity over "previous/next"
+* (bug 16612) Fixed "noprint" class for Modern skin print style
+* Section anchors now have an "id" attribute as well as a "name" attribute,
+ even when Tidy is not used
+* (bug 16026) revision-info, revision-info-current, cannotdelete,
+ redirectedfrom, historywarning and difference messages now use Wiki text
+ rather than raw HTML markup
+* (bug 13835) Fix rendering of {{filepath:Wiki.png|nowiki}}
+* (bug 16772) Special:Upload now correctly rejects files with spaces in the
+ file extension (e.g. Foo. jpg).
+* Image moving over an existing file no longer throws a database error
+* (bug 16786) Restored "redundant" links recently removed from Classic sidebar
+* (bug 16850) $wgActionPaths can have query strings now, previously, this broke
+ local URLs
+* (bug 16376) Mention in deleteBatch.php and moveBatch.php maintenance scripts
+ that STDIN can be used for page list
+* (bug 16560) Special:Random returns a page from ContentNamespaces, and no
+ longer from NS_MAIN
+* (bug 16123) Fixed Special:Import on SQLite.
+* (bug 16937) Show appropriate error message for attempted installs on
+ PostgreSQL 7.3 or earlier.
+* Disabled SQLite support in the installer.
+* Fixed XSS vulnerabilities in the web-based installer.
+* Added a meta robots tag to the installer to prevent indexing of potentially
+ sensitive configuration data.
+* (bug 16483) Prevented a filesort in ApiQueryBacklinks caused by missing parentheses.
+ Building query properly now using makeList()
+
+=== API changes in 1.14 ===
+
+* Registration time of users registered before the DB field was created is now
shown as empty instead of the current time.
-* (bug 14904): fragments were lost when redirects were fixed.
-* Added magic word __STATICREDIRECT__ to suppress the redirect fixer
-* (bug 15035) Revert English linkTrail to /^([a-z]+)(.*)$/sD, as it was before
- r36253. Multiple reports of breakage due to old (pre-5.0) PCRE libraries,
- both bundled with PHP and packaged with distros such as RHEL.
-* (bug 14944) Shell invocation of external programs such as ImageMagick convert
- was broken in PHP 5.2.6, if the server had a non-UTF-8 locale.
-
-== Changes since 1.12 ==
-
-=== Configuration changes in 1.13 ===
-
-* New option $wgFeed can be set false to turn off syndication feeds
-* (bug 5745) Special:Whatlinkshere now shows up to $wgMaxRedirectLinksRetrieved
- links through each redirect instead of hardcoded 500
-* Set $wgUploadSizeWarning to false by default
-* Added $wgLBFactoryConf, for generic configuration of multi-master wiki farms
-* Removed $wgAlternateMaster, use $wgLBFactoryConf
-* (bug 13562) Misspelled option $wgUserNotifedOnAllChanges changed to
- $wgUserNotifiedOnAllChanges
-* (bug 12860) New option $wgSitemapNamespaces allows sitemaps to be generated
- for only some namespaces
-* Removed the emailconfirmed implicit group by default. To re-add it, use:
- $wgAutopromote['emailconfirmed'] = APCOND_EMAILCONFIRMED;
- in your LocalSettings.php.
-* (bug 2396) New shared database configuration variables. $wgSharedPrefix allows
- you to use a shared database with a different prefix. Or you can now use a local
- database and use prefixes to separate wiki and the shared tables. And the new
- $wgSharedTables variable allows you to specify a list of tables to share.
-* Automatic edit summaries can be disabled with $wgUseAutomaticEditSummaries
-* Duplicates of images are now shown on the image page
-* $wgRCFilterByAge allows for the list of dates in recent changes special pages to
- be filtered to only those within the range of $wgRCMaxAge
-* $wgRCLinkLimits and $wgRCLinkDays allow for customization of the list and limits
- displayed on the recent changes special pages
-* The "createpage" permission is no longer required when uploading if the target
- image page already exists
-* $wgMaximumMovedPages restricts the number of pages that can be moved at once
- (default 100) with the new subpage-move functionality of Special:Movepage
-* Hooks display in Special:Version is now disabled by default, use
- $wgSpecialVersionShowHooks = true; to enable it.
-* $wgActiveUserEditCount sets the number of edits that must be performed over
- a certain number of days to be considered active
-* $wgActiveUserDays is that number of days
-* $wgRateLimitsExcludedGroups has been deprecated in favor of
- $wgGroupPermissions[]['noratelimit']. The former still works, however.
-* New $wgGroupPermissions option 'move-subpages' added to control bulk-moving
- subpages along with pages. Assigned to 'user' and 'sysop' by default.
-* New $wgRC2UDPOmitBots allows user to omit bot edits from UDP output.
- Default: false
-* Removed $wgEnableCascadingProtection option. Disabling cascading protection
- is no longer possible.
-* $wgMessageCacheType defines now the type of cache used by the MessageCache class,
- previously it was choosen based on $wgParserCacheType
-* $wgExtensionAliasesFiles option to simplify adding aliases to special pages
- provided by extensions, in a similar way to $wgExtensionMessagesFiles
-* Added $wgXMLMimeTypes, an array of XML mimetypes we can check for
- with MimeMagic.
-* Added $wgDirectoryMode, which allows for setting the default CHMOD value when
- creating new directories.
-* (bug 14843) $wgCookiePrefix can be set by LocalSettings now, false defaults
- current behavior.
-
-=== New features in 1.13 ===
-
-* __HIDDENCAT__ on a category page causes the category to be hidden on the
- article page
-* Do not show edit permissions errors on a red link click, just redirect to the
- article. This is so that readers who don't know what a red link is are not
- confused when they are told they are range-blocked.
-* Add a new hook ImageBeforeProduceHTML to allow extensions to modify wikitext
- image syntax output
-* (bug 13100) Added 'preloadtitle' parameter to action=edit&section=new that
- pre-fills the section title field
-* (bug 13112) Added Special:RelatedChanges alias to Special:RecentChangesLinked
-* (bug 13130) Moved edit token and autosummary fields above edit tools to
- reduce broken form submissions
-* Add --old-redirects-only option to maintenance/refreshLinks.php, to add old
- redirects to the redirect table
-* Add links to page and file deletion forms to edit predefined delete reasons
-* (bug 13269) Added MediaWiki:Uploadfooter to the bottom of Special:Upload
-* (bug 2815) Search results for media now use thumbnail instead of text extract
-* When a page doesn't exist, the tab should say "create", not "edit"
-* (bug 12882) Added a span with class "patrollink" around "Mark as patrolled"
- link on diffs
-* Magic word formatnum can now take raw suffix to undo formatting
-* Add updatelog table to reliably permit updates that don't change the schema
-* Add category table to allow better tracking of category membership counts
-** (bug 1212) Give correct membership counts on the pages of large categories
-** Use category table for more efficient display of Special:Categories
-* (bug 1459) Search for duplicate files by hash: Special:FileDuplicateSearch
-* (bug 9447) Added hooks for search result headings
-* Image redirects are now enabled by default
-* (bug 13450) Email confirmation can now be canceled before the expiration
-* (bug 13490) Show upload/file size limit on upload form
-* Redesign of Special:UserRights
-* Make rev_deleted log entries more intelligible
-* (bug 6943) Added PAGESINCATEGORY: magic word
-* (bug 13604) Added Special:ListGroupRights
-* (bug 6332, 8617) Added message 'mainpage-description' as duplicate of
- 'mainpage' and added it to message 'sidebar'
-* Automatically add old redirects to the redirect table when needed
-* (bug 6934) Allow inclusions, links, redirects to be separately toggled on or
- off on Special:WhatLinksHere
-* Cache image redirects
-* (bug 10457) Organize Special:SpecialPages into sections
-* Add a new hook EditPageBeforeConflictDiff to allow extensions like FCKeditor
- to modify the output for edit conflicts
-* Add class="nested" for <fieldset>s so fieldsets inside fieldsets get
- a slightly less huge margin and padding
-* (bug 13527) Use sitemaps.org format 0.9 instead of a Google-specific format
-* Allow \C and \Q as TeX commands to match \R, \N, \Z
-* On Special:UserRights, when you can add a group you can't remove or remove
- one you can't add, a notice is printed to warn you
-* (bug 12698) Create PAGESIZE parser function, to return the size of a page
-* Allow the "log in / create account" link in the toolbar to have different
- text from Special:UserLogin title (new message 'nav-login-createaccount')
-* Say "log in / create account" if an anonymous user can create an account,
- otherwise just "log in", consistently across skins
-* Special:Shortpages and Special:Longpages now returns pages in all content
- namespaces, not just NS_MAIN.
-* (bug 889) Improve conflict-handling between shared upload repository
- and local one
-* Update documentation links in auto-generated LocalSettings.php
-* (bug 13584) The new hook SkinTemplateToolboxEnd was added.
-* (bug 709) Cannot rename/move images and other media files [EXPERIMENTAL]
-* Custom rollback summaries now accept the same arguments as the default message
-* (bug 12542) Added hooks for expansion of Special:Listusers
-* Drop-down AJAX search suggestions (turn on $wgEnableMWSuggest)
-* More relevant search snippets (turn on $wgAdvancedSearchHighlighting)
-* (bug 13950) Allow users to watch the user/talk pages of users they block.
-* (bug 13970) Allow MonoBook-based skins to specify their own print stylesheet
-* Show image links on Special:Whatlinkshere
-* Use rel="start", "prev", "next" appropriately on Pager-based pages
-* Add support for SQLite
-* AutoAuthenticate hook renamed to UserLoadFromSession
-* (bug 13232) importScript(), importStylesheet() funcs available to custom JS
-* (bug 13095) Search by first letters or digits in [[Special:Categories]]
-* Users moving a page can now move all subpages automatically as well
-* (bug 14259) Localisation message for upload button on Special:Import is now
- 'import-upload' instead of 'upload'
-* Add information about user group membership to Special:Preferences
-* (bug 14146) Wrap usage section on imagepages into <div>s.
-* New layout for Special:Specialpages. Restricted pages are marked but not separated
- from other pages in their group.
-* (bug 14263) Show a diff of the revert on rollback notification page.
-* (bug 13434) Show a warning when hash identical files exist
-* Sidebar is now cached for all languages
-* The User class now contains a public function called isActiveEditor. Figures
- out if a user is active based on at least $wgActiveUserEditCount number of
- edits in the last $wgActiveUserDays days.
-* SpecialSearchResults hook now passes results by reference, so they can be
- changed by extensions.
-* Add a new hook LinkerMakeExternalLink to allow extensions to modify the output of
- external links.
-* (bug 14132) Allow user to disable bot edits from being output to UDP.
-* (bug 14328) jsMsg() within Wikibits now accepts a DOM object, not just a string
-* (bug 14558) New system message (emailuserfooter) is now added to the footer of
- e-mails sent with Special:Emailuser
-* Add support for Hijri (Islamic) calendar
-* Add a new hook LinkerMakeExternalImage to allow extensions to modify the output
- of external (hotlinked) images.
-* (bug 14604) Introduced the following features for the LanguageConverter:
- Multi-tag support, single conversion flag, remove conversion flag on a single
- page, description flag, variant name, multi-variant fallbacks.
-* Add zh-mo and zh-my variants for the zh language
-* (bugs 4832, 9481, 12890) Special:Recentchangeslinked now has all options that
- are in Special:Recentchanges
-* Allow an $error message to be passed to ArticleDelete hook
-* Allow extensions to modify the user creation form by calling addInputItem();
-* Add meta generator tag to HTML output
-* MediawikiPerformAction hook is now passed the Mediawiki object
-* Added blank special page Special:BlankPage for benchmarking, etc.
-* Foreign repo file descriptions and thumbnails are now cached.
-* (bug 11732) Allow localisation of edit button images
-* Allow the search box, toolbox and languages box in the Monobook sidebar to be
- moved around arbitrarily using special sections in [[MediaWiki:Sidebar]]:
- SEARCH, TOOLBOX and LANGUAGES
-* Add a new hook NormalizeMessageKey to allow extensions to replace messages before
- the database is potentially queried
-* (bug 9736) Redirects on Special:Fewestrevisions are now marked as such.
-* New date/time formats in Cs localization according to ČSN and PČP.
-* Special:Recentchangeslinked now includes changes to transcluded pages and
- displayed images; also, the "Show changes to pages linked" checkbox now works on
- category pages too, showing all links that are not categorizations
-* (bug 4578) Automatically fix redirects broken by a page move
-
-=== Bug fixes in 1.13 ===
-
-* (bug 10677) Add link to the file description page on the shared repository
-* (bug 13084) Increase size of source/destination filename fields in upload form
-* (bug 13115) rebuildrecentchanges should print the current value of $wgRCMaxAge
-* (bug 13140) Show parent categories in category namespace
-* (bug 13149) Correctly format 'fileexists' message on Upload page
-* Make the default filepageexists message accurate
-* (bug 12988) $wgMinimalPasswordLength no longer breaks create user by email
-* (bug 13022) Fix upload from URL on PHP 5.0.x
-* (bug 13132) Unable to unprotect pages protected with earlier versions of MediaWiki
-* (bug 12723) OpenSearch description name now uses more compact language code
- to avoid passing the length limit as often, is customizable per site via
- 'opensearch-desc' message.
-* (bug 13135) Special:Userrights now passes IDs through form submission
- to allow functionality on not-quite-right usernames
-* (bug 12575) Prevent duplicate patrol log entries from being created
-* (bug 13174) __HIDDENCAT__ now applies only to category pages
-* (bug 13031) Add links to user pages in e-mail form
-* (bug 13147) Description for categoriespagetext (used in Special:Categories) reworded
-* (bug 11561) Fix fatal error when calling action=revert to non-image page
-* (bug 12430) Fix call to private method LinkFilter::makeRegex fatal error in
- maintenance/cleanupSpam.php
-* All skins should have the "mediawiki" class on the body element
-* (bug 13019) Message cache for some extensions not loaded at time of editing
-* (bug 13247) Prettified ISBN links
-* maintenance/refreshLinks.php did not fix page_id 1 with the --new-only option
-* (bug 13110) Don't show "Permission error" page if the edit is already rolled
- back when using rollback
-* (bug 13012) Use content messages for block options when generating the
- recentchanges entry
-* (bug 13274) Change links for messages to ucfirst
-* (bug 13273) Un-hardcode some punctuation (add new messages colon-separator,
- autocomment-prefix)
-* Parse MediaWiki message translations with a correct language setting on preview
-* (bug 13281) Treat X-Forwarded-For, Client-ip and User-Agent headers as
- case-insensitive names.
-* Adding the fix for lists in RTL wikis to more skins, and fixing the image toc
-* (bug 8157) Remove redirects from Special:Unusedtemplates. Patch by WebBoy.
-* (bug 10721) Duplicate section anchors with differing case now disambiguated
- for Internet Explorer's sake and standards compliance
-* (bug 13298) Tighter limits on Special:Newpages limits when embedding
-* Email subject in content language instead of sending user's UI language
-* (bug 13251) Allow maintenance rebuild scripts to work with Postgres
-* (bug 2084) Fixed incorrect regex to match redirects
-* (bug 3131) Manually-specified upload destination filename is no longer
- overwritten by browsing for a file after you wrote it.
-* (bug 7251) Sidebars generated by MediaWiki:Sidebar now have the class
- 'generated-sidebar'.
-* (bug 13265) Media handler is missing 'image/x-bmp'
-* (bug 13407) MediaWiki:Powersearch is used in two places
-* (bug 13403) Fix cache invalidation of history pages when old revisions change
-* (bug 11563) Deprecated SearchMySQL4 class; merged code to SearchMySQL
-* (bug 12801) Fix link in subtitle message in AJAX search
-* (bug 13428) Fix regression in protection form layout HTML validity
-* (bug 9403) Sanitize newlines from search term input
-* (bug 13429) Separate date and time in message sp-newimages-showfrom
-* (bug 13137) Allow setting 'editprotected' right separately from 'protect',
- so groups may optionally edit protected pages without having 'protect' perms
-* Disallow deletion of big pages by means of moving a page to its title and
- using the "delete and move" option.
-* (bug 13466, 13632) White space differences not shown in diffs
-* (bug 1953) Search form now honors namespace selections more reliably
-* (bug 12294) Namespace class renamed to MWNamespace for PHP 5.3 compatibility
-* PHP 5.3 compatibility fix for wfRunHooks() called with no parameters
-* (bug 6447) Trackbacks now work with transactional tables, if enabled
-* (bug 6892, 7147) Trackback error handling, optional fields more robust
-* (bug 6813) Don't break HTML validator when using trackbacks
-* Fix for size checks on SVG images with global 'stroke-width' attribute
-* (bug 11874) Inline CSS with !important no longer borken
-* (bug 1600) Strip extra == section markup == in new-comment field
-* (bug 11325) Wrapped page titles in MonoBook skin spaced more nicely
-* (bug 12077) Fix HTML nesting for TOC
-* (bug 344) Purge cache for talk/article pages when deleting the other tab
-* (bug 13436) Treat image captions correctly when they include option keywords
- (like ending with "px" or starting with "upright")
-* Trackback display formatting fixed
-* Don't die when single-element arrays are passed to SQL query constructors
- that have an array index other than 0
-* (bug 13522) Fix fatal error in Parser::extractTagsAndParams
-* (bug 13532) Use proper timestamp call when reverting images
-* (bug 13543) Updated FAQ link in the installer sidebar
-* (bug 13540) Date format in confirmation e-mail now matches message language
-* (bug 13554) PHP Notice in old pre-processor when list item is empty.
-* (bug 13556) Don't show a blank form if no image is attached in Special:Upload
-* (bug 13576) maintenance/rebuildrecentchanges.php fails
-* (bug 13441) Allow Special:Recentchanges to show bots only
-* (bug 13431) Show true message source in Special:Allmessages&ot=php / xml
-* (bug 13463) Login successful page doesn't use user's preferred interface language
-* (bug 13630) Fixed warnings for pass by reference at call time in
- Special:Revisiondelete when generating the log entry.
-* (bug 12064) BeforePageDisplay hook is now called for all skins
-* (bug 13624) Fix regression with manual thumb= parameter on images
-* (bug 11039) Add missing labels on protection form
-* (bug 13458) Preview/edit toolbar spacing now works consistently
-* (bug 13433) Fix action=render on Image: pages
-* (bug 13678) Fix CSS validation for Monobook
-* (bug 13684) Links in Special:ListGroupRights should be in content language
-* (bug 13690) Fix PHP notice on accessing some URLs
-* Hide (undo) link if user isn't able to edit page
-* Invalidate cache of pages that includes images via redirects on upload
-* (bug 13705) Don't show rollback link in page history on incorrect revisions
-* (bug 13708) Don't set "Search results" title when loading Special:Search
- without query
-* (bug 13736) Don't show MediaWiki:Anontalkpagetext on non-existant IP addresses
-* (bug 13728) Don't trim initial whitespace during section edits
-* (bug 13727) Don't delete log entries from recentchanges on page deletion
-* (bug 13752) Redirects to sections now work again
-* (bug 13725) Upload form watch checkbox state set correctly with wpDestFile
-* (bug 13756) Don't show the form and navigation links of Special:Newpages if
- the page is included
-* When hiding things on WhatLinksHere, generated URLs should hide them too
-* Properly escape search terms with regex chars so they appear highlighted in
- search results
-* (bug 13768) pt_title field encoding fixed
-* Do not display empty columns on Special:UserRights if all groups are
- changeable or all unchangeable
-* Fix fatal error on calling PAGESINCATEGORY with invalid category name
-* (bug 13793) Special:Whatlinkshere filters wrong - after paginating instead of before
-* (bug 13796) Show links to parent pages even if some of them are missing
-* (bug 13816) Filter by main namespace doesn't work on WhatLinksHere
-* (bug 13822) Fatal error on some pages when calculating subpage subtitle
-* (bug 13824) AJAX search suggestion now works with non-SkinTemplate skins
-* Added 'application/x-dia-diagram' MediaWiki's known MIME types
-* (bug 13866) skins/common/shared.css - invalid attribute fixing
-* Hide edit section links on Special:Undelete
-* (bug 13860) Fix "Justify paragraphs" option for Modern skin
-* (bug 13168) accessibility links in Modern skin link to wrong anchor id
-* (bug 13185) No line break after 'subpages' class in Modern skin
-* (bug 13583) No "poweredby" in Modern skin
-* (bug 13880) "Printable" link in Modern skin now formats as print mode
-* (bug 13885) Bump default $wgSVGMaxSize from 1024 to 2048 pixels
-* (bug 13891) Show categories box even if all categories are hidden and user has
- "show hidden categories" option on
-* (bug 13915) Undefined variable $wltsfield in includes/SpecialWatchlist.php
-* (bug 13913) Special:Whatlinkshere now has correct HTML markup
-* (bug 13905) Blacklist Mac IE from HttpOnly cookies; it eats them sometimes
-* (bug 13922) Fix bad HTML on empty Special:Prefixindex and Special:Allpages
-* (bug 13924) Fix bad HTML on power search form
-* (bug 13820) Fix updater for rev_parent_id population
-* (bug 13925) Fix bad HTML on search results list
-* (bug 13934) Fixing the link to GNU General Public License Version 2
-* Show correct accesskey prefix for Firefox 3 beta (Alt-Shift-, not Alt-)
-* (bug 13949) Special:PrefixIndex/AllPages paging links contain invalid XML
-* (bug 13770) Use Preprocessor_Hash by default to avoid missing DOM module errors
-* (bug 13982) Disable ccmeonemails preference when user-to-user mails disabled
-* (bug 13615) Update case mappings and normalization to Unicode 5.1.0
- Note that case mappings will only be used if mbstring extension is not present.
-* (bug 14044) Don't increment page view counters on views from bot users
-* (bug 14042) Calling Database::limitResult() misplaced the comment in the log file
-* (bug 14047) Fix regression in installer which hid DB-specific options
- Also makes SQLite path configurable in the installer.
-* (bug 13546) Follow image redirects on image page
-* (bug 12644) Template list on edit page now sorted on preview
-* (bug 14058) Support pipe trick for namespaces and interwikis with "-"
-* Message name filter on Special:Allmessages now case-insensitive
-* (bug 13943) Fix image redirect behaviour on image pages
-* (bug 14093) Do 'sysop' => 'protect' magic in Title::isValidMoveOperation
-* (bug 14063) Power search form missing <label> for redirects check
-* (bug 14111) Similar filename warning links now lead to correct page
-* (bug 14082) Fix for complex text input vs AJAX suggestions on some browsers
-* (bug 13693) Categories sometimes claim to have a negative number of members
-* (bug 1701) Korean Hangul syllables now broken down properly in Category lists
- even if the wiki's overall content language is not Korean
-* (bug 12773) addOnloadHook() now calls functions immediately when scripts are
- loaded after the primary page completion, instead of dropping them
-* (bug 14199) Fix deletion form for image redirect pages
-* (bug 14220) Disabling $wgCheckFileExtensions now works without also
- disabling $wgStrictFileExtensions
-* (bug 14241) Pages can no longer be protected to levels you are not in
-* (bug 14296) Fix local name of ang: (Anglo-Saxon)
-* (bug 4871) Hardcoded superscript in time zone preferences moved to message
-* (bug 6957) E-mail confirmation links now using English special page name
- for better compatibility and keeping the links shorter. Avoids problem
- with corrupt links in Gmail on IE 6.
-* (bug 14273) Fix for HTTP Accept header parsing with spaces as from Konqueror
-* (bug 14312) Update LanguageKaa.php for handling transform issues with i to İ
- and I to ı
-* (bug 13826) MediaWiki:Defaultns accepts Wikicode
-* (bug 14324) Creating an account is again possible with $wgEmailConfirmToEdit
- set to true
-* (bug 13034) Interwiki pages can now be reached using Go search button
-* (bug 14362) Change interwiki names of Erzya and Moksha Wikipedias
-* (bug 14370) When a grouppage-x message does not exist the entry on the
- ListGroupRights special page now links to the project namespace page for it,
- not the main namespace page.
-* (bug 11659) Urldecode image names in galleries
-* (bug 14258, 14368) Fix for subpage renames in replication environments
-* (bug 14367) Failed block no longer adds phantom watchlist entry
-* (bug 14385) "Move subpages" option no longer tries to move to invalid titles
-* (bug 14386) Fix subpage namespace oddity when moving a talk page
-* (bug 11771) Signup form now not shown if in read-only mode.
-* (bug 12859) $wgRateLimitsExcludedGroups has been deprecated in favor of
- $wgGroupPermissions[]['noratelimit'].
-* (Bug 13828) Split parameter $1 of MediaWiki:Missingarticle into $1 (=title)
- and $2 (=revision numbers)
-* (bug 14401) Fix Safari access key tooltips for Windows and >3.1 Mac versions
-* (bug 14432) Fix notice regression in Special:Newpages feed mode
-* (bug 11951) EditPage::getEditToolbar() is now static.
-* (bug 14392) Fix regression breaking table prefix in installer
-* (bug 11084) $wgDBprefix replacement for updater SQL will now work for
- extension tables using uppercase letters or digits in their names.
-* (bug 12311) Fix regression with lists at start of undeletion preview
-* (bug 14496) Fix regression with parseinline on Special:Upload.
-* We no longer just give up on a missing upload base directory; it's now
- created automatically if we have sufficient permissions!
-* (bug 14479) MediaWiki:upload-maxfilesize should have a div id wrapper
-* (bug 14497) Throw visible errors in installer scripts when SQL files
- fail due to database permission or other error
-* (bug 14500) Site feed (Recentchanges) no longer shows up on the actual
- recent changes page.
-* (bug 14511) MediaWiki:Delete-legend is no longer double escaped
-* Generate correct section anchors for numeric headers
-* (bug 14520) Don't load nonexistent CSS files for Chick/Myskin/Simple skins
-* (bug 14551) Cancel upload no longer automatically suppresses warnings
-* (bug 13878) Deprecate Article::getDB() in favor of direct wfGetDB() calls
-* (bug 4977) Fix for possible squid purging errors when using HTTP purges
- and multiple servers
-* (bug 14572) Redirects listed on file links on image pages no longer redirect.
-* (bug 14537) Change interwiki name for Old Church Slavonic (cu)
-* (bug 14583) Fix regression in recent changes "limit to certain categories."
-* (bug 14515) HTML nesting cleanup on edit form
-* (bug 14647) Removed unused 'townBox' CSS classes
-* (bug 14687) OutputPage::addStyle() now adds type="text/css" like it should.
-* OpenSearch cleanup; Firefox now sends you to the search page for empty
- searches instead of the domain root (which may not even be a wiki).
-* (bug 3481) Pages moved shortly after creation are shown at their new title
- on Special:Newpages.
-* (bug 12716) Trying to unprotect a title that isn't protected no longer
- generates a log entry.
-* (bug 14088) Excessively long block expiry times are rejected as invalid,
- keeps the log page from being distorted.
-* (bug 14708) Emulate INSERT...IGNORE with standard SQL for Postgres backend.
-* (bug 14646) Fix some double-escaping of HTML in feed output
-* (bug 14709) Fix login success message formatting when using cookie check
-* (bug 14710) Remove "donate" link from default sidebar
-* (bug 14745) Image moving works on sites that transform thumbnails via 404
-* (bug 2186) Document.write() in wikibits caused failures when using
- application/xhtml+xml. The calls to this have been removed.
-* (bug 14764) Fix regression in from Article::lastModified(), failed to work
- on non-mySQL schemas.
-* (bug 14763) Child classes of Database (DatabasePostgres and DatabaseOracle)
- had stict standards issues with setFakeSlaveLag() and setFakeMaster().
-* (bug 451) Improve the phrase mappings of the Chinese converter arrays.
-* (bug 12487) Rights log is not fully internationalized
-* (bug 10837) Language variants no longer override other languages than base
-* (bug 14778) 'limit' parameter now applies to history feeds as well as
- history pages
-* (bug 14845) Bug in prefs javascript: Calling an array item without checking
- its existance.
-* Accesskeys for minor edit/watch checkboxes on edit now work in Firefox 3
-* (bug 12384) Comments in maintenance/*php
-* (bug 12441) ./maintenance/generateSitemap.php fix -fspath requiring
- a trailing slash.
-* (bug 12568) configuration script now produce valid XHTML.
-* The accesskey to edit a page is now disabled when editing the page, to pre-
- vent conflicts with Safari shortcuts.
-
-=== API changes in 1.13 ===
-
-* Fixing main page display in meta=siteinfo
-* (bug 13128) Added patrolled flag to list=recentchanges
-* Implemented {bl,ei,iu}redirect (lists links through redirects as well)
-* (bug 13154) Introduced subpages flag to meta=siteinfo&siprop=namespaces
-* (bug 13157) Added ucuserprefix parameter to list=usercontibs
-* (bug 12394) Added rctitles parameter to list=recentchanges, making rcid
- retrieval easier
-* (bug 13218) Fix inclusion of " character in hyperlinks
-* Added watch and unwatch parameters to action=delete and action=move
-* Added action=edit
-* (bug 11401) Added xmldoublequote to xml formatter
-* Added rvsection parameter to prop=revisions to allow fetching the content of
- a certain section only
-* Introduced list=allimages
-* (bug 13371) Build page set from image hashes
-* Mark non-existent messages in meta=allmessages as missing
-* (bug 13390) One invalid title no longer kills an entire API query
-* (bug 13419) Fix gblredirect so it actually works
-* (bug 13418) Disable eiredirect because it's useless
-* (bug 13395) list=allcategories should use category table
-* (bug 13442) Missing pages in prop=langlinks and prop=extlinks are now
- handled properly.
-* (bug 13444) Add description to list=watchlist
-* (bug 13482) Disabled search types handled properly
-* Added inprop=talkid,subjectid to prop=info
-* Added help text message that specifies whether a module is POST-only
-* Added createonly parameter to action=edit
-* Replaced $wgAPIUCUserPrefixMinLength by the more generic $wgAPIMaxDBRows
-* (bug 11719) Remove trailing blanks in YAML output.
-* (bug 13541) Added siprop=specialpagealiases to meta=siteinfo
-* Added fallback8bitEncoding and readonly fields to
- meta=siteinfo&siprop=general output
-* (bug 13544) Added prop=revid to action=parse
-* (bug 13603) Added siprop=usergroups to meta=siteinfo
-* Cleaned up redirect resolution
-* Added possibility to obtain all external links through list=exturlusage
-* (bug 13606) Added archivename to iiprop
-* (bug 11633) Explicitly convert redirect titles to strings due to PHP's
- very weak typing on array keys.
-* (bug 12136) Extend allowed characters in JSON callback to ][.'"_A-Za-z0-9
-* (bug 11673) Return error 'unknown_action' in specified format
-* (bug 13618) Added rcprop=redirect and rcshow=redirect to list=recentchanges
-* (bug 13544) Added oldid parameter to action=parse to allow for parsing of old
- revisions
-* (bug 13718) Return the proper continue parameter for cmsort=timestamp
-* action=login now returns the correct waiting time in the details property
-* (bug 13792) Broken titles are now silently skipped in search results.
-* (bug 13819) exturlusage paging skipped an item
-* Fixed handling of usernames containing spaces in list=block
-* (bug 13836) Fixed fatal errors resulting from combining iiprop=metadata with
- format=xml
-* (bug 13735) Added prop=categoryinfo module
-* (bug 13945) Retrieve cascading protection sources via inprop=protection
-* (bug 13965) Hardcoded 51 limit on titles is too limiting
-* (bug 13993) apfrom doesn't work with apdir=descending
-* (bug 14018) Introduced alcontinue to list=alllinks to improve paging
-* (bug 14013) Added rcshow=patrolled to list=recentchanges
-* (bug 14028) Added language attribute to interwiki map in meta=siteinfo
-* (bug 14022) Added usprop=registration and auprop=blockinfo
-* (bug 14021) Removed titles= support from list=backlinks (has been obsolete
- for ages)
-* (bug 13829) Expose parse tree via action=expandtemplates
-* (bug 13606) Allow deletion of images
-* Added iiprop=mime and aiprop=metadata
-* Handled unrecognized values for parameters more gracefully
-* Handled requesting disallowed tokens more gracefully
-* (bug 14140) URL-encoded page titles are now decoded in edit summaries
-* (bug 14243) Only accept post requests in action=edit; patch by HardDisk
-* action=block now returns an ISO8601 timestamp, like all other modules do
-* Added md5 parameter to action=edit
-* (bug 14335) Logging in to unified account using API not possible
-* Added action=emailuser to send an email to a user
-* (bug 14471) Use HTMLTidy and generate limit report in action=parse
-* (bug 14459) Added prependtext and appendtext parameters to action=edit
-* (bug 14526) Unescaped SQL in list=backlinks
-* Added 'hidden' flag to list=allcategories and prop=categoryinfo output
-* Added nocreate parameter to action=edit
-* (bug 14402) Added maxage and smaxage parameters to api.php
-* Added bkip parameter to list=blocks
-* (bug 14651) apprefix and similar parameters are now canonicalized
-* Added clprop=timestamp to prop=categories
-* (bug 14678) API errors now respects $wgShowExceptionDetails and
- $wgShowSQLErrors
-* (bug 14723) Added time zone and writing direction to meta=siteinfo
-* Added APIQueryInfoTokens and APIQueryRevisionsTokens hooks so extensions
- can add their own tokens
-* Added block and unblock tokens to prop=info as well
-* Added paging (limit and continue parameters) to
- prop={links,templatelinks,langlinks,extlinks,categories,images}
-* Added flag "top" to list=usercontribs if the user is the last contributor to
- the page
-* list=exturlusage in "list all links" mode can now filter by protocol
-
-=== Languages updated in 1.13 ===
+* API search now falls back to fulltext search by default when using Lucene
+ or other engine which doesn't support a separate title search function.
+ This means you can use API search on Wikipedia without explicitly adding
+ &srwhat=text to the query.
+* Added iiprop=bitdepth to imageinfo and aiprop=bitdepth to allimages
+* (bug 14713) API-specific permissions (such as 'writeapi' and 'apihighlimits'
+ are now listed on action=help
+* (bug 15044) Added requestid parameter to api.php to facilitate distinguishing
+ between requests
+* (bug 15048) Added limit field for multivalue parameters to action=paraminfo
+ output.
+* When the limit on multivalue parameters is exceeded, a warning is issued
+* list=search doesn't list missing pages any more
+* (bug 15178) Added clshow to prop=categories to allow filtering for hidden/
+ non-hidden categories
+* (bug 15228) Combining revids= and redirects now throws a warning instead of
+ an error, and still resolves redirects generated by the generator.
+* list={backlinks,embeddedin,imageusage} now return arrays with keys 0, 1, 2,
+ etc. (AKA lists) instead of arrays with pageIDs as keys (AKA hash tables)
+ for consistency with other list modules.
+* Added action=watch
+* (bug 15275) apprefix and related parameters ignore spaces at the end
+* action=edit no longer throws unknown error 228 when trying to create an
+ empty section with section=new
+* Database replication lag doesn't cause all action=edit requests to return the
+ nochange flag any more
+* (bug 15392) ApiFormatBase::formatHTML now uses $wgUrlProtocols.
+* (bug 15444) action=edit returns "Unknown error: ``AS_END''" where it should
+ return just "Unknown error"
+* (bug 15448) YAML output returns empty values instead of 0
+* (bug 15445) Added action=patrol
+* (bug 15466) Added action=purge
+* (bug 15486) action=block ignores autoblock parameter
+* (bug 15492) added rcprop=loginfo to list=recentchanges
+* (bug 15527) action=rollback can now revert anonymous editors
+* (bug 15535) prop=info&inprop=protection doesn't list pre-1.10 protections
+ if the page is also protected otherwise (1.10+ style or cascading)
+* list=random now has rnredirect parameter, to get random redirects.
+* Added APIAfterExecute, APIQueryAfterExecute and APIQueryGeneratorAfterExecute
+ hooks which allow for extending core modules in a cleaner way
+* action=protect checks for invalid protection types and levels
+* (bug 15673) Added indentation to format=wddxfm output and improved built-in
+ WDDX formatter to resemble PHP's more
+* (bug 15706) Empty values for apprtype and apprlevel are now silently ignored
+ rather than causing an exception
+* Added uiprop=preferencestoken to meta=userinfo
+* (bug 15609) Add inprop=url and inprop=readable to prop=info
+* Add ApiDisabled and ApiQueryDisabled classes so individual modules can
+ be disabled in LocalSettings.php
+* (bug 15653) Add prop=duplicatefiles
+* (bug 15768) Add list=watchlistraw
+* (bug 15647) action=edit with basetimestamp fails if the page has been deleted
+ and undeleted since the last edit
+* (bug 15785) Allow for different expiry times for different protections in
+ action=protect
+* Added allowsduplicates attribute to action=paraminfo output
+* (bug 15767) apfilterlanglinks returns duplicate results
+* (bug 15845) Added pageid/fromid parameter to action=delete/move, making
+ manipulation of legacy pages with invalid titles possible
+* (bug 15881) Empty or invalid parameters cause database errors
+* The maxage and smaxage parameters are now properly validated
+* (bug 15945) list=recentchanges doesn't check $wgUseRCPatrol, $wgUseNPPatrol
+ and patrolmarks right
+* (bug 15985) acfrom and aifrom parameters didn't work when sorting in
+ descending order.
+* (bug 15995) Add cmstartsortkey and cmendsortkey parameters to
+ list=categorymembers
+* (bug 16017) list=categorymembers sets invalid continue parameters for
+ sortkeys containing pipes
+* (bug 16018) Added uccontinue parameter to list=usercontribs so paging
+ works properly when multiple users are queried or a userprefix is used
+* (bug 16047) Added activeusers attribute to meta=siteinfo&siprop=statistics
+ output
+* Added redirect resolution to action=parse
+* (bug 16074) rvprop=content combined with a generator with a high limit causes
+ an error
+* (bug 16105) Image metadata attributes containing spaces result in invalid XML
+* (bug 16126) Added siprop=magicwords to meta=siteinfo
+* (bug 16159) Added wlshow=patrolled|!patrolled to list=watchlist
+* (bug 16225) Titles like Talk:Talk:Foo broke apfrom and friends
+* meta=siteinfo&siprop=interwikimap no longer throws an exception for empty
+ sifilter parameter.
+* (bug 12760) meta=userinfo&uiprop=ratelimits doesn't list group-specific rate
+ limits
+* (bug 16398) meta=userinfo&uiprop=rights lists some rights twice in some cases
+* (bug 16408) Added rvgeneratexml to prop=revisions
+* (bug 16421) Made list=logevents's leuser accept user names with underscores
+ instead of spaces
+* (bug 16516) Made rvsection=T-2 work
+* (bug 16526) Added usprop=emailable to list=users
+* (bug 16548) list=search threw errors with an invalid error code
+* (bug 16515) Added pst and onlypst parameters to action=parse
+* (bug 16541) Added block expiry timestamp to list=logevents output
+* (bug 16613) action=protect doesn't tell when &cascade was set but cascading
+ protection wasn't allowed
+* (bug 16626) action=delete now correctly handles empty "reason" param
+* (bug 15579) clshow considers all categories !hidden
+* (bug 16647) list=allcategories, prop=categories don't return "hidden"
+ property for hidden categories
+* New siprop parameter of 'extensions' to list all installed extensions
+* (bug 16672) Include canonical namespace name in
+ meta=siteinfo&siprop=namespaces.
+* (bug 16726) siprop=namespacealiases should also list localized aliases
+* (bug 16730) Added apprfiltercascade parameter to list=allpages to filter
+ cascade-protected pages
+* (bug 16798) JSON encoding errors for some characters outside the BMP
+* (bug 16629) prop=info&inprop=protection lists empty legacy protections
+ incorrectly
+* (bug 15261, 16262) API no longer outputs invalid UTF-8
+* Fix broken list=alllinks paging and make alunique actually work
+
+=== Languages updated in 1.14 ===
MediaWiki supports over 300 languages. Many localisations are updated
regularly. Below only new and removed languages are listed.
-* Egyptian Spoken Arabic (arz) (new)
-* Southern Balochi (bcc) (new)
-* Middle Dutch (dum) (removed)
-* British English (en-gb) (new)
-* Fiji Hindi (Latin) (hif-latn) (new)
-* Old Norse (non) (removed)
-* Tarifit (rif) (new)
-* Serbian cyrillic iyekvian (sr-jc) (removed)
-* Serbian latin iyekavian (sr-jl) (removed)
-* Silesian (szl) (new)
-* Tajiki (Cyrllic script) (tg-cyrl) (new)
-* Tajiki (Latin script) (tg-latn) (new)
-* Chinese (Macau) (zh-mo) (new)
-* Chinese (Malaysia) (zh-my) (new)
+* Bakhtiari (bqi) (new)
+* Fiji Hindi (Devanagari script) (hif-deva) (new)
+* Krio (kri) (new)
+* Lezghian (lez) (new)
+* Laz (lzz) (new)
+* Eastern Mari (mhr) (new)
+* Niuean (niu) (new)
+* Oromo (om) (new)
+* Plautdietsch (pdt) (new)
+* Western Punjabi (pnb) (new)
+* Tarantino (roa-tara) (new)
+* Serbo-Croatian (sh) (new)
+* Tulu (tcy) (new)
== Compatibility ==
-MediaWiki 1.13 requires PHP 5 (5.1 recommended). PHP 4 is no longer supported.
+MediaWiki 1.14 requires PHP 5 (5.2 recommended). PHP 4 is no longer supported.
PHP 5.0.x fails on 64-bit systems due to serious bugs with array processing:
http://bugs.php.net/bug.php?id=34879
@@ -711,16 +641,16 @@ At this time we still recommend 4.0, but 4.1/5.0 will work fine in most cases.
== Upgrading ==
-1.13 has several database changes since 1.12, and will not work without schema
+1.14 has several database changes since 1.13, and will not work without schema
updates.
+If upgrading from before 1.11, and you are using a wiki as a commons reposito-
+ry, make sure that it is updated as well. Otherwise, errors may arise due to
+database schema changes.
+
If upgrading from before 1.7, you may want to run refreshLinks.php to ensure
new database fields are filled with data.
-If upgrading from before 1.11, and you are using a wiki as a commons repository,
-make sure that it is updated as well. Otherwise, errors may arise due to
-database schema changes.
-
If you are upgrading from MediaWiki 1.4.x or earlier, some major database
changes are made, and there is a slightly higher chance that things could
break. Don't forget to always back up your database before upgrading!
@@ -736,7 +666,7 @@ set $wgMimeType = "application/xhtml+xml"; to test for remaining problem
cases, but this is not recommended on live sites. (This must be set for
MathML to display properly in Mozilla.)
-For notes on 1.12.x and older releases, see HISTORY.
+For notes on 1.13.x and older releases, see HISTORY.
=== Online documentation ===
diff --git a/UPGRADE b/UPGRADE
index f817e738..9d0e0521 100644
--- a/UPGRADE
+++ b/UPGRADE
@@ -67,6 +67,11 @@ with $wgEnableUploads in later versions. When upgrading, consult the release
notes to check for configuration changes which would alter the expected
behaviour of MediaWiki.
+=== Check installed extensions ===
+In MediaWiki 1.14 some extensions are migrated into the core. Please see the
+RELEASE-NOTES section "Migrated extensions" and disable these extensions in your
+localSettings.php
+
=== Test ===
It makes sense to test your wiki immediately following any kind of maintenance
diff --git a/api.php b/api.php
index 77dc52a4..817f4bca 100644
--- a/api.php
+++ b/api.php
@@ -64,7 +64,7 @@ if( strcmp( "$wgScriptPath/api$wgScriptExtension", $url ) ) {
if (!$wgEnableAPI) {
echo 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php';
echo '<pre><b>$wgEnableAPI=true;</b></pre>';
- die(-1);
+ die(1);
}
/* Construct an ApiMain with the arguments passed via the URL. What we get back
diff --git a/config/index.php b/config/index.php
index cef32248..ced8bc92 100644
--- a/config/index.php
+++ b/config/index.php
@@ -67,11 +67,13 @@ $ourdb['postgres']['compile'] = 'pgsql';
$ourdb['postgres']['bgcolor'] = '#aaccff';
$ourdb['postgres']['rootuser'] = 'postgres';
-$ourdb['sqlite']['fullname'] = 'SQLite';
-$ourdb['sqlite']['havedriver'] = 0;
-$ourdb['sqlite']['compile'] = 'pdo_sqlite';
-$ourdb['sqlite']['bgcolor'] = '#b1ebb1';
-$ourdb['sqlite']['rootuser'] = '';
+/*** SQLITE DISABLED -- USE MEDIAWIKI 1.15 */
+#$ourdb['sqlite']['fullname'] = 'SQLite';
+#$ourdb['sqlite']['havedriver'] = 0;
+#$ourdb['sqlite']['compile'] = 'pdo_sqlite';
+#$ourdb['sqlite']['bgcolor'] = '#b1ebb1';
+#$ourdb['sqlite']['rootuser'] = '';
+/************************************/
$ourdb['mssql']['fullname'] = 'MSSQL';
$ourdb['mssql']['havedriver'] = 0;
@@ -688,13 +690,23 @@ if( $conf->SysopName ) {
}
$conf->License = importRequest( "License", "none" );
-if( $conf->License == "gfdl" ) {
- $conf->RightsUrl = "http://www.gnu.org/copyleft/fdl.html";
+if( $conf->License == "gfdl1_2" ) {
+ $conf->RightsUrl = "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt";
$conf->RightsText = "GNU Free Documentation License 1.2";
- $conf->RightsCode = "gfdl";
+ $conf->RightsCode = "gfdl1_2";
+ $conf->RightsIcon = '${wgScriptPath}/skins/common/images/gnu-fdl.png';
+} elseif( $conf->License == "gfdl1_3" ) {
+ $conf->RightsUrl = "http://www.gnu.org/copyleft/fdl.html";
+ $conf->RightsText = "GNU Free Documentation License 1.3";
+ $conf->RightsCode = "gfdl1_3";
$conf->RightsIcon = '${wgScriptPath}/skins/common/images/gnu-fdl.png';
} elseif( $conf->License == "none" ) {
$conf->RightsUrl = $conf->RightsText = $conf->RightsCode = $conf->RightsIcon = "";
+} elseif( $conf->License == "pd" ) {
+ $conf->RightsUrl = "http://creativecommons.org/licenses/publicdomain/";
+ $conf->RightsText = "Public Domain";
+ $conf->RightsCode = "pd";
+ $conf->RightsIcon = '${wgScriptPath}/skins/common/images/public-domain.png';
} else {
$conf->RightsUrl = importRequest( "RightsUrl", "" );
$conf->RightsText = importRequest( "RightsText", "" );
@@ -890,7 +902,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
continue;
}
- print "<li>Connected to " . htmlspecialchars( $myver );
+ print "<li>Connected to " . htmlspecialchars( "{$conf->DBtype} $myver" );
if ($conf->DBtype == 'mysql') {
if( version_compare( $myver, "4.0.14" ) < 0 ) {
print "</li>\n";
@@ -941,7 +953,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
$wgDatabase->selectDB( $wgDBname );
}
else if ($conf->DBtype == 'postgres') {
- if( version_compare( $myver, "PostgreSQL 8.0" ) < 0 ) {
+ if( version_compare( $myver, "8.0" ) < 0 ) {
dieout( "<b>Postgres 8.0 or later is required</b>. Aborting." );
}
}
@@ -1193,7 +1205,9 @@ if( count( $errs ) ) {
<ul class="plain">
<li><?php aField( $conf, "License", "No license metadata", "radio", "none" ); ?></li>
- <li><?php aField( $conf, "License", "GNU Free Documentation License 1.2 (Wikipedia-compatible)", "radio", "gfdl" ); ?></li>
+ <li><?php aField( $conf, "License", "Public Domain", "radio", "pd" ); ?></li>
+ <li><?php aField( $conf, "License", "GNU Free Documentation License 1.2 (Wikipedia-compatible)", "radio", "gfdl1_2" ); ?></li>
+ <li><?php aField( $conf, "License", "GNU Free Documentation License 1.3", "radio", "gfdl1_3" ); ?></li>
<li><?php
aField( $conf, "License", "A Creative Commons license - ", "radio", "cc" );
$partner = "MediaWiki";
@@ -1436,6 +1450,10 @@ if( count( $errs ) ) {
</div>
</fieldset>
+ <?php
+ # SQLITE DISABLED -- USE MEDIAWIKI 1.15
+ if (false):
+ ?>
<?php database_switcher('sqlite'); ?>
<div class="config-desc">
<b>NOTE:</b> SQLite only uses the <i>Database name</i> setting above, the user, password and root settings are ignored.
@@ -1452,6 +1470,11 @@ if( count( $errs ) ) {
</div>
</fieldset>
+ <?php
+ # SQLITE DISABLED -- USE MEDIAWIKI 1.15
+ endif
+ ?>
+
<?php database_switcher('mssql'); ?>
<div class="config-input"><?php
aField( $conf, "DBprefix2", "Database table prefix:" );
@@ -1472,7 +1495,7 @@ if( count( $errs ) ) {
</div>
</form>
<script type="text/javascript">
-window.onload = toggleDBarea('<?php echo Xml::encodeJsVar( $conf->DBtype ); ?>',
+window.onload = toggleDBarea(<?php echo Xml::encodeJsVar( $conf->DBtype ); ?>,
<?php
## If they passed in a root user name, don't populate it on page load
echo strlen(importPost('RootUser', '')) ? 0 : 1;
@@ -1605,7 +1628,7 @@ function writeLocalSettings( $conf ) {
# Add slashes to strings for double quoting
$slconf = array_map( "escapePhpString", get_object_vars( $conf ) );
- if( $conf->License == 'gfdl' ) {
+ if( $conf->License == 'gfdl1_2' || $conf->License == 'pd' || $conf->License == 'gfdl1_3' ) {
# Needs literal string interpolation for the current style path
$slconf['RightsIcon'] = $conf->RightsIcon;
}
@@ -1731,11 +1754,11 @@ if ( \$wgCommandLineMode ) {
## you can enable inline LaTeX equations:
\$wgUseTeX = false;
-\$wgLocalInterwiki = \$wgSitename;
+\$wgLocalInterwiki = strtolower( \$wgSitename );
\$wgLanguageCode = \"{$slconf['LanguageCode']}\";
-\$wgProxyKey = \"$secretKey\";
+\$wgSecretKey = \"$secretKey\";
## Default skin: you can change the default skin. Use the internal symbolic
## names, ie 'standard', 'nostalgia', 'cologneblue', 'monobook':
@@ -1964,7 +1987,7 @@ function printListItem( $item ) {
}
# Determine a suitable value for $wgShellLocale
-function getShellLocale( $wikiLanguage ) {
+function getShellLocale( $wikiLang ) {
# Give up now if we're in safe mode or open_basedir
# It's theoretically possible but tricky to work with
if ( wfIniGetBool( "safe_mode" ) || ini_get( 'open_basedir' ) ) {
diff --git a/docs/database.txt b/docs/database.txt
index 60e268c5..e80a4940 100644
--- a/docs/database.txt
+++ b/docs/database.txt
@@ -74,7 +74,7 @@ want to write code destined for Wikipedia.
It's often the case that the best algorithm to use for a given task
depends on whether or not replication is in use. Due to our unabashed
Wikipedia-centrism, we often just use the replication-friendly version,
-but if you like, you can use $wgLoadBalancer->getServerCount() > 1 to
+but if you like, you can use wfGetLB()->getServerCount() > 1 to
check to see if replication is in use.
=== Lag ===
@@ -110,7 +110,7 @@ in the session, and then at the start of each request, waiting for the
slave to catch up to that position before doing any reads from it. If
this wait times out, reads are allowed anyway, but the request is
considered to be in "lagged slave mode". Lagged slave mode can be
-checked by calling $wgLoadBalancer->getLaggedSlaveMode(). The only
+checked by calling wfGetLB()->getLaggedSlaveMode(). The only
practical consequence at present is a warning displayed in the page
footer.
diff --git a/docs/hooks.txt b/docs/hooks.txt
index 286ed7e2..04b1e2ac 100644
--- a/docs/hooks.txt
+++ b/docs/hooks.txt
@@ -198,6 +198,10 @@ system (LDAP, another PHP program, whatever), you could do:
Returning false makes less sense for events where the action is complete, and
will normally be ignored.
+Note that none of the examples made use of create_function() as a way to
+attach a function to a hook. This is known to cause problems (notably with
+Special:Version), and should be avoided when at all possible.
+
==Using hooks==
A calling function or method uses the wfRunHooks() function to run the hooks
@@ -234,6 +238,9 @@ to add events to the MediaWiki code.
$autoblockip: The IP going to be autoblocked.
$block: The block from which the autoblock is coming.
+'AbortDiffCache': Can be used to cancel the caching of a diff
+&$diffEngine: DifferenceEngine object
+
'AbortLogin': Return false to cancel account login.
$user: the User object being authenticated against
$password: the password being submitted, not yet checked for validity
@@ -265,6 +272,10 @@ before showing the edit form ( EditPage::edit() ). This is triggered
on &action=edit.
$EditPage : the EditPage object
+'APIAfterExecute': after calling the execute() method of an API module.
+Use this to extend core API modules.
+&$module: Module object
+
'APIEditBeforeSave': before saving a page with api.php?action=edit,
after processing request parameters. Return false to let the request
fail, returning an error message or an <edit result="Failure"> tag
@@ -273,6 +284,24 @@ $EditPage : the EditPage object
$text : the new text of the article (has yet to be saved)
$resultArr : data in this array will be added to the API result
+'APIGetAllowedParams': use this hook to modify a module's parameters.
+&$module: Module object
+&$params: Array of parameters
+
+'APIGetParamDescription': use this hook to modify a module's parameter
+descriptions.
+&$module: Module object
+&$desc: Array of parameter descriptions
+
+'APIQueryAfterExecute': after calling the execute() method of an
+action=query submodule. Use this to extend core API modules.
+&$module: Module object
+
+'APIQueryGeneratorAfterExecute': after calling the executeGenerator()
+method of an action=query submodule. Use this to extend core API modules.
+&$module: Module object
+&$resultPageSet: ApiPageSet object
+
'APIQueryInfoTokens': use this hook to add custom tokens to prop=info.
Every token has an action, which will be used in the intoken parameter
and in the output (actiontoken="..."), and a callback function which
@@ -295,6 +324,17 @@ associated Revision object. In the hook, just add your callback to the
$tokenFunctions array and return true (returning false makes no sense)
$tokenFunctions: array(action => callback)
+'APIQueryRecentChangesTokens': use this hook to add custom tokens to list=recentchanges.
+Every token has an action, which will be used in the rctoken parameter
+and in the output (actiontoken="..."), and a callback function which
+should return the token, or false if the user isn't allowed to obtain
+it. The prototype of the callback function is func($pageid, $title, $rc)
+where $pageid is the page ID of the page associated to the revision the
+token is requested for, $title the associated Title object and $rc the
+associated RecentChange object. In the hook, just add your callback to the
+$tokenFunctions array and return true (returning false makes no sense)
+$tokenFunctions: array(action => callback)
+
'ArticleAfterFetchContent': after fetching content of an article from the database
$article: the article (object) being loaded from the database
$content: the content (string) of the article
@@ -315,6 +355,11 @@ $id: id of the article that was deleted
'ArticleEditUpdateNewTalk': before updating user_newtalk when a user talk page was changed
$article: article (object) of the user talk page
+'ArticleEditUpdates': when edit updates (mainly link tracking) are made when an article has been changed
+$article: the article (object)
+$editInfo: data holder that includes the parser output ($editInfo->output) for that page after the change
+$changed: bool for if the page was changed
+
'ArticleEditUpdatesDeleteFromRecentchanges': before deleting old entries from recentchanges table, return false to not delete old entries
$article: article (object) being modified
@@ -375,6 +420,7 @@ $oldPageID: the page ID of the revision when archived (may be null)
$article: the article that was edited
$user: the user who did the rollback
$revision: the revision the page was reverted back to
+$current: the reverted revision
'ArticleSave': before an article is saved
$article: the article (object) being saved
@@ -396,17 +442,6 @@ $section: (No longer used)
$flags: Flags passed to Article::doEdit()
$revision: New Revision of the article
-'ArticleSaveComplete': after an article is saved
-$article: the article (object) saved
-$user: the user (object) who saved the article
-$text: the new article text
-$summary: the article summary (comment)
-$isminor: minor flag
-$iswatch: watch flag
-$section: section #
-
-wfRunHooks( 'ArticleSaveComplete', array( &$this, &$wgUser, $text, $summary, $flags & EDIT_MINOR, null, null, &$flags, $revision ) );
-
'ArticleUndelete': When one or more revisions of an article are restored
$title: Title corresponding to the article restored
$create: Whether or not the restoration caused the page to be created
@@ -471,13 +506,6 @@ rendered inline in wiki pages or galleries in category pages.
&$parser: Parser object
&$ig: ImageGallery object
-'BeforeWatchlist': Override watchlist display or add extra SQL clauses.
-$nondefaults: Assoc array with the following keys:
- days, hideOwn, hideBots, hideMinor, namespace
-$wgUser: wgUser.
-&$hookSql: a string which will be inserted without sanitation into the SQL query
- used to get the watchlist, at the end of the WHERE part.
-
'BlockIp': before an IP address or user is blocked
$block: the Block object about to be saved
$user: the user _doing_ the block (not the one being blocked)
@@ -490,18 +518,6 @@ $user: the user who did the block (not the one being blocked)
$isbn: ISBN to show information for
$output: OutputPage object in use
-'BrokenLink': Before the HTML is created for a broken (i.e. red) link
-&$linker: Linker instance
-$nt: the page title
-$query: the URL query string passed in
-&$u: the URL of this link
-&$style: the inline CSS style
-&$prefix: a prefix prepended to the linked text
-&$text: the text placed by the user in the wiki-link
-&$inside: any additional alphanumeric characters placed after the wiki-link,
-that are made part of the link text
-&$trail: text placed immediately after the HTML link
-
'CategoryPageView': before viewing a categorypage in CategoryPage::view
$catpage: CategoryPage instance
@@ -544,6 +560,17 @@ $newRev: Revision object of the "new" revision
$article: article (object) being viewed
$oldid: oldid (int) being viewed
+'DoEditSectionLink': Override the HTML generated for section edit links
+$skin: Skin object rendering the UI
+$title: Title object for the title being linked to (may not be the same as
+ $wgTitle, if the section is included from a template)
+$section: The designation of the section being pointed to, to be included in
+ the link, like "&section=$section"
+$tooltip: The default tooltip. Escape with htmlspecialchars() before using.
+ By default, this is wrapped in the 'editsectionhint' message.
+$result: The HTML to return, prefilled with the default plus whatever other
+ changes earlier hooks have made
+
'EditFilter': Perform checks on an edit
$editor: Edit form (see includes/EditPage.php)
$text: Contents of the edit box
@@ -589,19 +616,17 @@ sections.
'EditPageBeforeEditButtons': allows modifying the edit buttons below the textarea in the edit form
&$editpage: The current EditPage object
&$buttons: Array of edit buttons "Save", "Preview", "Live", and "Diff"
+&$tabindex: HTML tabindex of the last edit check/button
-'EditSectionLink': Override the return value of Linker::editSectionLink()
-$skin: Skin rendering the UI
-$title: Title being linked to
-$section: Section to link to
-$link: Default link
-$result: Result (alter this to override the generated links)
+'EditPageBeforeEditChecks': allows modifying the edit checks below the textarea in the edit form
+&$editpage: The current EditPage object
+&$checks: Array of edit checks like "watch this page"/"minor edit"
+&$tabindex: HTML tabindex of the last edit check/button
-'EditSectionLinkForOther': Override the return value of Linker::editSectionLinkForOther()
+'EditSectionLink': Do not use, use DoEditSectionLink instead.
$skin: Skin rendering the UI
$title: Title being linked to
$section: Section to link to
-$hint: Anchor title/tooltip attributes
$link: Default link
$result: Result (alter this to override the generated links)
@@ -692,6 +717,9 @@ $result: User permissions error to add. If none, return true.
'getUserPermissionsErrorsExpensive': Absolutely the same, but is called only
if expensive checks are enabled.
+'HTMLCacheUpdate::doUpdate': After cache invalidation updates are inserted into the job queue.
+$title: Title object, pages linked to this title are purged.
+
'ImageBeforeProduceHTML': Called before producing the HTML created by a wiki
image insertion. You can skip the default logic entirely by returning
false, or just modify a few things using call-by-reference.
@@ -726,6 +754,7 @@ $title: Title object ($wgTitle)
$request: WebRequest
$ignoreRedirect: boolean to skip redirect check
$target: Title/string of redirect target
+$article: Article object
'InitPreferencesForm': called at the end of PreferencesForm's constructor
$form: the PreferencesForm
@@ -762,6 +791,35 @@ $lang: laguage code (string)
$specialPageAliases: associative array of magic words synonyms
$lang: laguage code (string)
+'LinkBegin': Used when generating internal and interwiki links in
+Linker::link(), before processing starts. Return false to skip default proces-
+sing and return $ret. See documentation for Linker::link() for details on the
+expected meanings of parameters.
+$skin: the Skin object
+$target: the Title that the link is pointing to
+&$text: the contents that the <a> tag should have (raw HTML); null means "de-
+ fault"
+&$customAttribs: the HTML attributes that the <a> tag should have, in associa-
+ tive array form, with keys and values unescaped. Should be merged with de-
+ fault values, with a value of false meaning to suppress the attribute.
+&$query: the query string to add to the generated URL (the bit after the "?"),
+ in associative array form, with keys and values unescaped.
+&$options: array of options. Can include 'known', 'broken', 'noclasses'.
+&$ret: the value to return if your hook returns false.
+
+'LinkEnd': Used when generating internal and interwiki links in Linker::link(),
+just before the function returns a value. If you return true, an <a> element
+with HTML attributes $attribs and contents $text will be returned. If you re-
+turn false, $ret will be returned.
+$skin: the Skin object
+$target: the Title object that the link is pointing to
+$options: the options. Will always include either 'known' or 'broken', and may
+ include 'noclasses'.
+&$text: the final (raw HTML) contents of the <a> tag, after processing.
+&$attribs: the final HTML attributes of the <a> tag, after processing, in asso-
+ ciative array form.
+&$ret: the value to return if your hook returns false.
+
'LinkerMakeExternalImage': At the end of Linker::makeExternalImage() just before the return
&$url: the image url
&$alt: the image's alt text
@@ -829,6 +887,10 @@ $magicWords: array of strings
'MagicWordwgVariableIDs': When definig new magic words IDs. DEPRECATED: Use LanguageGetMagic hook instead
$variableIDs: array of strings
+'MakeGlobalVariablesScript': called right before Skin::makeVariablesScript is executed
+&$vars: variable (or multiple variables) to be added into the output
+ of Skin::makeVariablesScript
+
'MarkPatrolled': before an edit is marked patrolled
$rcid: ID of the revision to be marked patrolled
$user: the user (object) marking the revision as patrolled
@@ -870,6 +932,7 @@ $tools: array of tools
$article: the article edited
$rev: the new revision
$baseID: the revision ID this was based off, if any
+$user: the editing user
'NormalizeMessageKey': Called before the software gets the text of a message
(stuff in the MediaWiki: namespace), useful for changing WHAT message gets displayed
@@ -879,6 +942,11 @@ $baseID: the revision ID this was based off, if any
whether to use the content language (true) or site language (false) (bool)
&$transform: whether or not to expand variables and templates in the message (bool)
+'OldChangesListRecentChangesLine': Customize entire Recent Changes line.
+&$changeslist: The OldChangesList instance.
+&$s: HTML of the form "<li>...</li>" containing one RC entry.
+&$rc: The RecentChange object.
+
'OpenSearchUrls': Called when constructing the OpenSearch description XML.
Hooks can alter or append to the array of URLs for search & suggestion formats.
&$urls: array of associative arrays with Url element attributes
@@ -888,6 +956,9 @@ the resulting HTML is about to be displayed.
$parserOutput: the parserOutput (object) that corresponds to the page
$text: the text that will be displayed, in HTML (string)
+'OutputPageCheckLastModified': when checking if the page has been modified since the last visit
+&$modifiedTimes: array of timestamps, the following keys are set: page, user, epoch
+
'OutputPageParserOutput': after adding a parserOutput to $wgOut
$out: OutputPage instance (object)
$parserOutput: parserOutput instance being added in $out
@@ -1046,6 +1117,8 @@ $text : Current text being indexed
$term : Search term string
&$title : Outparam; set to $title object and return false for a match
+'SetupAfterCache': Called in Setup.php, after cache objects are set
+
'ShowRawCssJs': Customise the output of raw CSS and JavaScript in page views
$text: Text being shown
$title: Title of the custom script/stylesheet page
@@ -1065,6 +1138,17 @@ $skin: Skin object
&$text: bottomScripts Text
Append to $text to add additional text/scripts after the stock bottom scripts.
+'SkinAfterContent': Allows extensions to add text after the page content and
+article metadata.
+&$data: (string) Text to be printed out directly (without parsing)
+This hook should work in all skins. Just set the &$data variable to the text
+you're going to add.
+
+'SkinBuildSidebar': At the end of Skin::buildSidebar()
+$skin: Skin object
+&$bar: Sidebar contents
+Modify $bar to add or modify sidebar portlets.
+
'SkinSubPageSubtitle': At the beginning of Skin::subPageSubtitle()
$skin: Skin object
&$subpages: Subpage links HTML
@@ -1142,24 +1226,6 @@ $movePage: MovePageForm object
$oldTitle: old title (object)
$newTitle: new title (object)
-'SpecialPageExecuteAfterPage': called after executing a special page
-Warning: Not all the special pages call this hook
-$specialPage: SpecialPage object
-$par: paramter passed to the special page (string)
-$funct: function called to execute the special page
-
-'SpecialPageExecuteBeforeHeader': called before setting the header text of the special page
-Warning: Not all the special pages call this hook
-$specialPage: SpecialPage object
-$par: paramter passed to the special page (string)
-$funct: function called to execute the special page
-
-'SpecialPageExecuteBeforePage': called after setting the special page header text but before the main execution
-Warning: Not all the special pages call this hook
-$specialPage: SpecialPage object
-$par: paramter passed to the special page (string)
-$funct: function called to execute the special page
-
'SpecialPage_initList': called when setting up SpecialPage::$mList, use this hook to remove a core special page
$list: list (array) of core special pages
@@ -1168,7 +1234,7 @@ $list: list (array) of core special pages
$opts: FormOptions for this request
'SpecialRecentChangesQuery': called when building sql query for SpecialRecentChanges
-&$conds: array of where conditionals for query
+&$conds: array of WHERE conditionals for query
&$tables: array of tables to be queried
&$join_conds: join conditions for the tables
$opts: FormOptions for this request
@@ -1187,6 +1253,16 @@ $term: string of search term
'SpecialVersionExtensionTypes': called when generating the extensions credits, use this to change the tables headers
$extTypes: associative array of extensions types
+'SpecialWatchlistQuery': called when building sql query for SpecialWatchlist
+&$conds: array of WHERE conditionals for query
+&$tables: array of tables to be queried
+&$join_conds: join conditions for the tables
+&$fields: array of query fields
+
+'TitleArrayFromResult': called when creating an TitleArray object from a database result
+&$titleArray: set this to an object to override the default object returned
+$res: database result used to create the object
+
'TitleMoveComplete': after moving an article (title)
$old: old title
$nt: new title
@@ -1234,6 +1310,11 @@ string &$error: output: HTML error to show if upload canceled by returning false
'UploadComplete': Upon completion of a file upload
$uploadForm: Upload form object. File can be accessed by $uploadForm->mLocalFile.
+'User::mailPasswordInternal': before creation and mailing of a user's new temporary password
+$user: the user who sent the message out
+$ip: IP of the user who sent the message out
+$u: the account whose new password will be set
+
'UserArrayFromResult': called when creating an UserArray object from a database result
&$userArray: set this to an object to override the default object returned
$res: database result used to create the object
@@ -1254,9 +1335,21 @@ $user: User (object) whose permission is being checked
'UserClearNewTalkNotification': called when clearing the "You have new messages!" message, return false to not delete it
$user: User (object) that'll clear the message
+'UserComparePasswords': called when checking passwords, return false to override the default password checks
+&$hash: String of the password hash (from the database)
+&$password: String of the plaintext password the user entered
+&$userId: Integer of the user's ID or Boolean false if the user ID was not supplied
+&$result: If the hook returns false, this Boolean value will be checked to determine if the password was valid
+
'UserCreateForm': change to manipulate the login form
$template: SimpleTemplate instance for the form
+'UserCryptPassword': called when hashing a password, return false to implement your own hashing method
+&$password: String of the plaintext password to encrypt
+&$salt: String of the password salt or Boolean false if no salt is provided
+&$wgPasswordSalt: Boolean of whether the salt is used in the default hashing method
+&$hash: If the hook returns false, this String will be used as the hash
+
'UserEffectiveGroups': Called in User::getEffectiveGroups()
$user: User to get groups for
&$groups: Current effective groups
@@ -1275,6 +1368,9 @@ $user: User object
'UserGetImplicitGroups': Called in User::getImplicitGroups()
&$groups: List of implicit (automatically-assigned) groups
+'UserGetReservedNames': allows to modify $wgReservedUsernames at run time
+*&$reservedUsernames: $wgReservedUsernames
+
'UserGetRights': Called in User::getRights()
$user: User to get rights for
&$rights: Current rights
@@ -1283,10 +1379,13 @@ $user: User to get rights for
$user: user object
$name: user name
-'UserLoadFromSession': called to authenticate users on external/environmental means
+'UserLoadFromSession': called to authenticate users on external/environmental means; occurs before session is loaded
$user: user object being loaded
&$result: set this to a boolean value to abort the normal authentification process
+'UserLoadAfterLoadFromSession': called to authenticate users on external/environmental means; occurs after session is loaded
+$user: user object being loaded
+
'UserLoginComplete': after a user has logged in
$user: the user object that was created on login
$inject_html: Any HTML to inject after the "logged in" message.
@@ -1307,6 +1406,17 @@ $user : User object that was changed
$add : Array of strings corresponding to groups added
$remove: Array of strings corresponding to groups removed
+'UserrightsChangeableGroups': allows modification of the groups a user may add or remove via Special:UserRights
+$userrights : UserrightsPage object
+$user : User object of the current user
+$addergroups : Array of groups that the user is in
+&$groups : Array of groups that can be added or removed. In format of
+ array(
+ 'add' => array( addablegroups ),
+ 'remove' => array( removablegroups ),
+ 'add-self' => array( addablegroups to self ),
+ 'remove-self' => array( removable groups from self )
+ )
'UserRetrieveNewTalks': called when retrieving "You have new messages!" message(s)
$user: user retrieving new talks messages
$talks: array of new talks page(s)
diff --git a/docs/memcached.txt b/docs/memcached.txt
index b31554cc..2a904872 100644
--- a/docs/memcached.txt
+++ b/docs/memcached.txt
@@ -97,13 +97,6 @@ this is mentionned below.
(incomplete, out of date)
-Ajax Search:
- key: $wgDBname:ajaxsearch:md5( $search )
- ex: wikidb:ajaxsearch:9565814d5d564fa898dd6111b94fae0b
- stores: array with the result of research of a given text
- cleared by: nothing
- expiry: 30 minutes
-
Date Formatter:
key: $wgDBname:dateformatter
ex: wikidb:dateformatter
diff --git a/docs/php-memcached/Documentation b/docs/php-memcached/Documentation
index 4782807b..c9056053 100644
--- a/docs/php-memcached/Documentation
+++ b/docs/php-memcached/Documentation
@@ -165,7 +165,7 @@ EXAMPLE:
<?php
require("MemCachedClient.inc.php");
-// set the servers, with the last one having an interger weight value of 3
+// set the servers, with the last one having an integer weight value of 3
$options["servers"] = array("10.0.0.15:11000","10.0.0.16:11001",array("10.0.0.17:11002", 3));
$options["debug"] = false;
diff --git a/docs/upload.txt b/docs/upload.txt
new file mode 100644
index 00000000..e92ca786
--- /dev/null
+++ b/docs/upload.txt
@@ -0,0 +1,40 @@
+Special:Upload:
+
+wfSpecialUpload
+ new UploadForm
+ mUpload = new UploadFrom...
+ execute()
+ $wgEnableUploads
+ isAllowed(upload)
+ isBlocked()
+ wfReadOnly()
+ processUpload()
+ internalProcessUpload()
+ wfRunHooks(UploadForm:BeforeProcessing)
+ mUpload->getTitle()
+ wfStripIllegalFilenameChars
+ splitExtensions()
+ checkFileExtension()
+ Title::makeTitleSafe
+ getUserPermissionsErrors(edit; upload; create)
+ mUpload->verifyUpload()
+ empty(mFileSize)
+ getTitle()
+ checkOverwrite()
+ verifyFile()
+ checkMacBinary()
+ wfRunHooks(UploadVerification)
+ if(!ignoreWarning) mUpload->checkWarnings()
+ getInitialPageText()
+ mUpload->performUpload()
+ mLocalFile->upload()
+ if(isGood() && $watch) addWatch()
+ if(isGood()) wfRunHooks(UploadComplete)
+ wfRunHooks(SpecialUploadComplete)
+
+Changes:
+ * "Your file will be renamed to $1" check now done on the result of
+ Title::makeTitleSafe instead of filteredName
+ * getExistWarning only really does existence checks
+ * Other stuff forgotten to be documented
+ \ No newline at end of file
diff --git a/extensions/LLAuthPlugin.php b/extensions/LLAuthPlugin.php
index ec3ce565..a56df8d8 100644
--- a/extensions/LLAuthPlugin.php
+++ b/extensions/LLAuthPlugin.php
@@ -39,7 +39,7 @@ class LLAuthPlugin extends AuthPlugin {
}
}
- function getUserData($username) {
+ private function getUserData($username) {
if (is_null($this->data))
{
$this->connect();
@@ -53,7 +53,7 @@ class LLAuthPlugin extends AuthPlugin {
return $this->data;
}
- function userExists( $username ) {
+ public function userExists( $username ) {
$this->connect();
$result = mysqli_query($this->dbLink, 'SELECT id FROM users WHERE name = \''.mysqli_escape_string($this->dbLink, $username).'\'');
$exists = mysqli_num_rows($result) > 0;
@@ -62,7 +62,7 @@ class LLAuthPlugin extends AuthPlugin {
return $exists;
}
- function authenticate( $username, $password ) {
+ public function authenticate( $username, $password ) {
$this->connect();
$result = mysqli_query($this->dbLink, 'SELECT id FROM users WHERE name = \''.mysqli_escape_string($this->dbLink, $username).'\' AND password = \''.mysqli_escape_string($this->dbLink, sha1($password)).'\' ');
$authenticated = mysqli_num_rows($result) > 0;
@@ -71,57 +71,57 @@ class LLAuthPlugin extends AuthPlugin {
return $authenticated;
}
- function modifyUITemplate( &$template ) {
+ public function modifyUITemplate( &$template ) {
$template->set( 'usedomain', false );
$template->set('link', 'Um Dich hier anzumelden, nutze Deine Konto-Daten aus dem <a href="http://forum.archlinux.de/">archlinux.de-Forum</a>.');
}
- function setDomain( $domain ) {
+ public function setDomain( $domain ) {
$this->domain = $domain;
}
- function validDomain( $domain ) {
+ public function validDomain( $domain ) {
return true;
}
- function updateUser( &$user ) {
+ public function updateUser( &$user ) {
return $this->initUser($user);
}
- function autoCreate() {
+ public function autoCreate() {
return true;
}
- function allowPasswordChange() {
+ public function allowPasswordChange() {
return false;
}
- function setPassword( $user, $password ) {
+ public function setPassword( $user, $password ) {
return false;
}
- function updateExternalDB( $user ) {
+ public function updateExternalDB( $user ) {
// this way userdata is allways overwritten by external db
return $this->initUser($user);
}
- function canCreateAccounts() {
+ public function canCreateAccounts() {
return false;
}
- function addUser( $user, $password, $email = '', $realname = '' ) {
+ public function addUser( $user, $password, $email = '', $realname = '' ) {
return false;
}
- function strict() {
+ public function strict() {
return true;
}
- function strictUserAuth( $username ) {
+ public function strictUserAuth( $username ) {
return true;
}
- function initUser( &$user, $autocreate=false ) {
+ public function initUser( &$user, $autocreate=false ) {
$data = $this->getUserData($user->getName());
$user->setEmail($data['email']);
$user->confirmEmail();
@@ -129,7 +129,7 @@ class LLAuthPlugin extends AuthPlugin {
return true;
}
- function getCanonicalName( $username ) {
+ public function getCanonicalName( $username ) {
// fix bug #122
$data = $this->getUserData($username);
// needed for update.php
diff --git a/img_auth.php b/img_auth.php
index 4b625e39..91410181 100644
--- a/img_auth.php
+++ b/img_auth.php
@@ -48,7 +48,7 @@ if( preg_match( '!\d+px-(.*)!i', $name, $m ) )
$name = $m[1];
wfDebugLog( 'img_auth', "\$name is {$name}" );
-$title = Title::makeTitleSafe( NS_IMAGE, $name );
+$title = Title::makeTitleSafe( NS_FILE, $name );
if( !$title instanceof Title ) {
wfDebugLog( 'img_auth', "Unable to construct a valid Title from `{$name}`" );
wfForbidden();
diff --git a/includes/AjaxFunctions.php b/includes/AjaxFunctions.php
index 9daca9e5..1a9adbca 100644
--- a/includes/AjaxFunctions.php
+++ b/includes/AjaxFunctions.php
@@ -14,7 +14,8 @@ if( !defined( 'MEDIAWIKI' ) ) {
* Modified function from http://pure-essence.net/stuff/code/utf8RawUrlDecode.phps
*
* @param $source String escaped with Javascript's escape() function
- * @param $iconv_to String destination character set will be used as second paramether in the iconv function. Default is UTF-8.
+ * @param $iconv_to String destination character set will be used as second parameter
+ * in the iconv function. Default is UTF-8.
* @return string
*/
function js_unescape($source, $iconv_to = 'UTF-8') {
@@ -72,91 +73,6 @@ function code2utf($num){
return '';
}
-define( 'AJAX_SEARCH_VERSION', 2 ); //AJAX search cache version
-
-function wfSajaxSearch( $term ) {
- global $wgContLang, $wgUser, $wgCapitalLinks, $wgMemc;
- $limit = 16;
- $sk = $wgUser->getSkin();
- $output = '';
-
- $term = trim( $term );
- $term = $wgContLang->checkTitleEncoding( $wgContLang->recodeInput( js_unescape( $term ) ) );
- if ( $wgCapitalLinks )
- $term = $wgContLang->ucfirst( $term );
- $term_title = Title::newFromText( $term );
-
- $memckey = $term_title ? wfMemcKey( 'ajaxsearch', md5( $term_title->getFullText() ) ) : wfMemcKey( 'ajaxsearch', md5( $term ) );
- $cached = $wgMemc->get($memckey);
- if( is_array( $cached ) && $cached['version'] == AJAX_SEARCH_VERSION ) {
- $response = new AjaxResponse( $cached['html'] );
- $response->setCacheDuration( 30*60 );
- return $response;
- }
-
- $r = $more = '';
- $canSearch = true;
-
- $results = PrefixSearch::titleSearch( $term, $limit + 1 );
- foreach( array_slice( $results, 0, $limit ) as $titleText ) {
- $r .= '<li>' . $sk->makeKnownLink( $titleText ) . "</li>\n";
- }
-
- // Hack to check for specials
- if( $results ) {
- $t = Title::newFromText( $results[0] );
- if( $t && $t->getNamespace() == NS_SPECIAL ) {
- $canSearch = false;
- if( count( $results ) > $limit ) {
- $more = '<i>' .
- $sk->makeKnownLinkObj(
- SpecialPage::getTitleFor( 'Specialpages' ),
- wfMsgHtml( 'moredotdotdot' ) ) .
- '</i>';
- }
- } else {
- if( count( $results ) > $limit ) {
- $more = '<i>' .
- $sk->makeKnownLinkObj(
- SpecialPage::getTitleFor( "Allpages", $term ),
- wfMsgHtml( 'moredotdotdot' ) ) .
- '</i>';
- }
- }
- }
-
- $valid = (bool) $term_title;
- $term_url = urlencode( $term );
- $term_normalized = $valid ? $term_title->getFullText() : $term;
- $term_display = htmlspecialchars( $term );
- $subtitlemsg = ( $valid ? 'searchsubtitle' : 'searchsubtitleinvalid' );
- $subtitle = wfMsgExt( $subtitlemsg, array( 'parse' ), wfEscapeWikiText( $term_normalized ) );
- $html = '<div id="searchTargetHide"><a onclick="Searching_Hide_Results();">'
- . wfMsgHtml( 'hideresults' ) . '</a></div>'
- . '<h1 class="firstHeading">'.wfMsgHtml('search')
- . '</h1><div id="contentSub">'. $subtitle . '</div>';
- if( $canSearch ) {
- $html .= '<ul><li>'
- . $sk->makeKnownLink( $wgContLang->specialPage( 'Search' ),
- wfMsgHtml( 'searchcontaining', $term_display ),
- "search={$term_url}&fulltext=Search" )
- . '</li><li>' . $sk->makeKnownLink( $wgContLang->specialPage( 'Search' ),
- wfMsgHtml( 'searchnamed', $term_display ) ,
- "search={$term_url}&go=Go" )
- . "</li></ul>";
- }
- if( $r ) {
- $html .= "<h2>" . wfMsgHtml( 'articletitles', $term_display ) . "</h2>"
- . '<ul>' .$r .'</ul>' . $more;
- }
-
- $wgMemc->set( $memckey, array( 'version' => AJAX_SEARCH_VERSION, 'html' => $html ), 30 * 60 );
-
- $response = new AjaxResponse( $html );
- $response->setCacheDuration( 30*60 );
- return $response;
-}
-
/**
* Called for AJAX watch/unwatch requests.
* @param $pagename Prefixed title string for page to watch/unwatch
@@ -189,20 +105,54 @@ function wfAjaxWatch($pagename = "", $watch = "") {
if(!$watching) {
$dbw = wfGetDB(DB_MASTER);
$dbw->begin();
- $article->doWatch();
+ $ok = $article->doWatch();
$dbw->commit();
}
} else {
if($watching) {
$dbw = wfGetDB(DB_MASTER);
$dbw->begin();
- $article->doUnwatch();
+ $ok = $article->doUnwatch();
$dbw->commit();
}
}
+ // Something stopped the change
+ if( isset($ok) && !$ok ) {
+ return '<err#>';
+ }
if( $watch ) {
return '<w#>'.wfMsgExt( 'addedwatchtext', array( 'parse' ), $title->getPrefixedText() );
} else {
return '<u#>'.wfMsgExt( 'removedwatchtext', array( 'parse' ), $title->getPrefixedText() );
}
}
+
+/**
+ * Called in some places (currently just extensions)
+ * to get the thumbnail URL for a given file at a given resolution.
+ */
+function wfAjaxGetThumbnailUrl( $file, $width, $height ) {
+ $file = wfFindFile( $file );
+
+ if ( !$file || !$file->exists() )
+ return null;
+
+ $url = $file->getThumbnail( $width, $height )->url;
+
+ return $url;
+}
+
+/**
+ * Called in some places (currently just extensions)
+ * to get the URL for a given file.
+ */
+function wfAjaxGetFileUrl( $file ) {
+ $file = wfFindFile( $file );
+
+ if ( !$file || !$file->exists() )
+ return null;
+
+ $url = $file->getUrl();
+
+ return $url;
+} \ No newline at end of file
diff --git a/includes/AjaxResponse.php b/includes/AjaxResponse.php
index c79e928b..63468a14 100644
--- a/includes/AjaxResponse.php
+++ b/includes/AjaxResponse.php
@@ -9,7 +9,9 @@ if( !defined( 'MEDIAWIKI' ) ) {
}
/**
- * @todo document
+ * Handle responses for Ajax requests (send headers, print
+ * content, that sort of thing)
+ *
* @ingroup Ajax
*/
class AjaxResponse {
@@ -20,7 +22,7 @@ class AjaxResponse {
/** HTTP header Content-Type */
private $mContentType;
- /** @todo document */
+ /** Disables output. Can be set by calling $AjaxResponse->disable() */
private $mDisabled;
/** Date for the HTTP header Last-modified */
diff --git a/includes/Article.php b/includes/Article.php
index 4d8277bb..3d9c2147 100644
--- a/includes/Article.php
+++ b/includes/Article.php
@@ -16,27 +16,30 @@ class Article {
/**@{{
* @private
*/
- var $mComment; //!<
- var $mContent; //!<
- var $mContentLoaded; //!<
- var $mCounter; //!<
- var $mForUpdate; //!<
- var $mGoodAdjustment; //!<
- var $mLatest; //!<
- var $mMinorEdit; //!<
- var $mOldId; //!<
- var $mRedirectedFrom; //!<
- var $mRedirectUrl; //!<
- var $mRevIdFetched; //!<
- var $mRevision; //!<
- var $mTimestamp; //!<
- var $mTitle; //!<
- var $mTotalAdjustment; //!<
- var $mTouched; //!<
- var $mUser; //!<
- var $mUserText; //!<
- var $mRedirectTarget; //!<
- var $mIsRedirect;
+ var $mComment = ''; //!<
+ var $mContent; //!<
+ var $mContentLoaded = false; //!<
+ var $mCounter = -1; //!< Not loaded
+ var $mCurID = -1; //!< Not loaded
+ var $mDataLoaded = false; //!<
+ var $mForUpdate = false; //!<
+ var $mGoodAdjustment = 0; //!<
+ var $mIsRedirect = false; //!<
+ var $mLatest = false; //!<
+ var $mMinorEdit; //!<
+ var $mOldId; //!<
+ var $mPreparedEdit = false; //!< Title object if set
+ var $mRedirectedFrom = null; //!< Title object if set
+ var $mRedirectTarget = null; //!< Title object if set
+ var $mRedirectUrl = false; //!<
+ var $mRevIdFetched = 0; //!<
+ var $mRevision; //!<
+ var $mTimestamp = ''; //!<
+ var $mTitle; //!<
+ var $mTotalAdjustment = 0; //!<
+ var $mTouched = '19700101000000'; //!<
+ var $mUser = -1; //!< Not loaded
+ var $mUserText = ''; //!<
/**@}}*/
/**
@@ -44,10 +47,18 @@ class Article {
* @param $title Reference to a Title object.
* @param $oldId Integer revision ID, null to fetch from request, zero for current
*/
- function __construct( Title $title, $oldId = null ) {
+ public function __construct( Title $title, $oldId = null ) {
$this->mTitle =& $title;
$this->mOldId = $oldId;
- $this->clear();
+ }
+
+ /**
+ * Constructor from an article article
+ * @param $id The article ID to load
+ */
+ public static function newFromID( $id ) {
+ $t = Title::newFromID( $id );
+ return $t == null ? null : new Article( $t );
}
/**
@@ -55,7 +66,7 @@ class Article {
* from another page on the wiki.
* @param $from Title object.
*/
- function setRedirectedFrom( $from ) {
+ public function setRedirectedFrom( $from ) {
$this->mRedirectedFrom = $from;
}
@@ -67,22 +78,20 @@ class Article {
* @return mixed Title object, or null if this page is not a redirect
*/
public function getRedirectTarget() {
- if(!$this->mTitle || !$this->mTitle->isRedirect())
+ if( !$this->mTitle || !$this->mTitle->isRedirect() )
return null;
- if(!is_null($this->mRedirectTarget))
+ if( !is_null($this->mRedirectTarget) )
return $this->mRedirectTarget;
-
# Query the redirect table
- $dbr = wfGetDB(DB_SLAVE);
- $res = $dbr->select('redirect',
- array('rd_namespace', 'rd_title'),
- array('rd_from' => $this->getID()),
- __METHOD__
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'redirect',
+ array('rd_namespace', 'rd_title'),
+ array('rd_from' => $this->getID()),
+ __METHOD__
);
- $row = $dbr->fetchObject($res);
- if($row)
+ if( $row = $dbr->fetchObject($res) ) {
return $this->mRedirectTarget = Title::makeTitle($row->rd_namespace, $row->rd_title);
-
+ }
# This page doesn't have an entry in the redirect table
return $this->mRedirectTarget = $this->insertRedirect();
}
@@ -94,15 +103,19 @@ class Article {
* @return Title object
*/
public function insertRedirect() {
- $retval = Title::newFromRedirect($this->getContent());
- if(!$retval)
+ $retval = Title::newFromRedirect( $this->getContent() );
+ if( !$retval ) {
return null;
- $dbw = wfGetDB(DB_MASTER);
- $dbw->replace('redirect', array('rd_from'), array(
+ }
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->replace( 'redirect', array('rd_from'),
+ array(
'rd_from' => $this->getID(),
'rd_namespace' => $retval->getNamespace(),
'rd_title' => $retval->getDBKey()
- ), __METHOD__);
+ ),
+ __METHOD__
+ );
return $retval;
}
@@ -113,9 +126,9 @@ class Article {
*/
public function followRedirect() {
$text = $this->getContent();
- return self::followRedirectText( $text );
+ return $this->followRedirectText( $text );
}
-
+
/**
* Get the Title object this text redirects to
*
@@ -131,7 +144,6 @@ class Article {
//
// This can be hard to reverse and may produce loops,
// so they may be disabled in the site configuration.
-
$source = $this->mTitle->getFullURL( 'redirect=no' );
return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
}
@@ -142,7 +154,6 @@ class Article {
// the rest of the page we're on.
//
// This can be hard to reverse, so they may be disabled.
-
if( $rt->isSpecial( 'Userlogout' ) ) {
// rolleyes
} else {
@@ -159,15 +170,15 @@ class Article {
/**
* get the title object of the article
*/
- function getTitle() {
+ public function getTitle() {
return $this->mTitle;
}
/**
- * Clear the object
- * @private
- */
- function clear() {
+ * Clear the object
+ * @private
+ */
+ public function clear() {
$this->mDataLoaded = false;
$this->mContentLoaded = false;
@@ -190,30 +201,27 @@ class Article {
* Note that getContent/loadContent do not follow redirects anymore.
* If you need to fetch redirectable content easily, try
* the shortcut in Article::followContent()
- * FIXME
- * @todo There are still side-effects in this!
- * In general, you should use the Revision class, not Article,
- * to fetch text for purposes other than page views.
*
* @return Return the text of this revision
*/
- function getContent() {
- global $wgUser, $wgOut, $wgMessageCache;
-
+ public function getContent() {
+ global $wgUser, $wgContLang, $wgOut, $wgMessageCache;
wfProfileIn( __METHOD__ );
-
- if ( 0 == $this->getID() ) {
- wfProfileOut( __METHOD__ );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
-
- if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
- $wgMessageCache->loadAllMessages();
- $ret = wfMsgWeirdKey ( $this->mTitle->getText() ) ;
+ if( $this->getID() === 0 ) {
+ # If this is a MediaWiki:x message, then load the messages
+ # and return the message value for x.
+ if( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+ # If this is a system message, get the default text.
+ list( $message, $lang ) = $wgMessageCache->figureMessage( $wgContLang->lcfirst( $this->mTitle->getText() ) );
+ $wgMessageCache->loadAllMessages( $lang );
+ $text = wfMsgGetKey( $message, false, $lang, false );
+ if( wfEmptyMsg( $message, $text ) )
+ $text = '';
} else {
- $ret = wfMsg( $wgUser->isLoggedIn() ? 'noarticletext' : 'noarticletextanon' );
+ $text = wfMsg( $wgUser->isLoggedIn() ? 'noarticletext' : 'noarticletextanon' );
}
-
- return "<div class='noarticletext'>\n$ret\n</div>";
+ wfProfileOut( __METHOD__ );
+ return $text;
} else {
$this->loadContent();
wfProfileOut( __METHOD__ );
@@ -233,7 +241,7 @@ class Article {
* @return string text of the requested section
* @deprecated
*/
- function getSection($text,$section) {
+ public function getSection( $text, $section ) {
global $wgParser;
return $wgParser->getSection( $text, $section );
}
@@ -242,8 +250,8 @@ class Article {
* @return int The oldid of the article that is to be shown, 0 for the
* current revision
*/
- function getOldID() {
- if ( is_null( $this->mOldId ) ) {
+ public function getOldID() {
+ if( is_null( $this->mOldId ) ) {
$this->mOldId = $this->getOldIDFromRequest();
}
return $this->mOldId;
@@ -254,32 +262,27 @@ class Article {
*
* @return int The old id for the request
*/
- function getOldIDFromRequest() {
+ public function getOldIDFromRequest() {
global $wgRequest;
$this->mRedirectUrl = false;
$oldid = $wgRequest->getVal( 'oldid' );
- if ( isset( $oldid ) ) {
+ if( isset( $oldid ) ) {
$oldid = intval( $oldid );
- if ( $wgRequest->getVal( 'direction' ) == 'next' ) {
+ if( $wgRequest->getVal( 'direction' ) == 'next' ) {
$nextid = $this->mTitle->getNextRevisionID( $oldid );
- if ( $nextid ) {
+ if( $nextid ) {
$oldid = $nextid;
} else {
$this->mRedirectUrl = $this->mTitle->getFullURL( 'redirect=no' );
}
- } elseif ( $wgRequest->getVal( 'direction' ) == 'prev' ) {
+ } elseif( $wgRequest->getVal( 'direction' ) == 'prev' ) {
$previd = $this->mTitle->getPreviousRevisionID( $oldid );
- if ( $previd ) {
+ if( $previd ) {
$oldid = $previd;
- } else {
- # TODO
}
}
- # unused:
- # $lastid = $oldid;
}
-
- if ( !$oldid ) {
+ if( !$oldid ) {
$oldid = 0;
}
return $oldid;
@@ -289,25 +292,24 @@ class Article {
* Load the revision (including text) into this object
*/
function loadContent() {
- if ( $this->mContentLoaded ) return;
-
+ if( $this->mContentLoaded ) return;
+ wfProfileIn( __METHOD__ );
# Query variables :P
$oldid = $this->getOldID();
-
# Pre-fill content with error message so that if something
# fails we'll have something telling us what we intended.
$this->mOldId = $oldid;
$this->fetchContent( $oldid );
+ wfProfileOut( __METHOD__ );
}
/**
* Fetch a page record with the given conditions
- * @param Database $dbr
- * @param array $conditions
- * @private
+ * @param $dbr Database object
+ * @param $conditions Array
*/
- function pageData( $dbr, $conditions ) {
+ protected function pageData( $dbr, $conditions ) {
$fields = array(
'page_id',
'page_namespace',
@@ -333,20 +335,20 @@ class Article {
}
/**
- * @param Database $dbr
- * @param Title $title
+ * @param $dbr Database object
+ * @param $title Title object
*/
- function pageDataFromTitle( $dbr, $title ) {
+ public function pageDataFromTitle( $dbr, $title ) {
return $this->pageData( $dbr, array(
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey() ) );
}
/**
- * @param Database $dbr
- * @param int $id
+ * @param $dbr Database
+ * @param $id Integer
*/
- function pageDataFromId( $dbr, $id ) {
+ protected function pageDataFromId( $dbr, $id ) {
return $this->pageData( $dbr, array( 'page_id' => $id ) );
}
@@ -354,22 +356,21 @@ class Article {
* Set the general counter, title etc data loaded from
* some source.
*
- * @param object $data
- * @private
+ * @param $data Database row object or "fromdb"
*/
- function loadPageData( $data = 'fromdb' ) {
- if ( $data === 'fromdb' ) {
+ public function loadPageData( $data = 'fromdb' ) {
+ if( $data === 'fromdb' ) {
$dbr = wfGetDB( DB_MASTER );
$data = $this->pageDataFromId( $dbr, $this->getId() );
}
$lc = LinkCache::singleton();
- if ( $data ) {
+ if( $data ) {
$lc->addGoodLinkObj( $data->page_id, $this->mTitle, $data->page_len, $data->page_is_redirect );
$this->mTitle->mArticleID = $data->page_id;
- # Old-fashioned restrictions.
+ # Old-fashioned restrictions
$this->mTitle->loadRestrictions( $data->page_restrictions );
$this->mCounter = $data->page_counter;
@@ -377,7 +378,7 @@ class Article {
$this->mIsRedirect = $data->page_is_redirect;
$this->mLatest = $data->page_latest;
} else {
- if ( is_object( $this->mTitle ) ) {
+ if( is_object( $this->mTitle ) ) {
$lc->addBadLinkObj( $this->mTitle );
}
$this->mTitle->mArticleID = 0;
@@ -389,11 +390,11 @@ class Article {
/**
* Get text of an article from database
* Does *NOT* follow redirects.
- * @param int $oldid 0 for whatever the latest revision is
+ * @param $oldid Int: 0 for whatever the latest revision is
* @return string
*/
function fetchContent( $oldid = 0 ) {
- if ( $this->mContentLoaded ) {
+ if( $this->mContentLoaded ) {
return $this->mContent;
}
@@ -429,14 +430,14 @@ class Article {
}
$revision = Revision::newFromId( $this->mLatest );
if( is_null( $revision ) ) {
- wfDebug( __METHOD__." failed to retrieve current page, rev_id {$data->page_latest}\n" );
+ wfDebug( __METHOD__." failed to retrieve current page, rev_id {$this->mLatest}\n" );
return false;
}
}
// FIXME: Horrible, horrible! This content-loading interface just plain sucks.
// We should instead work with the Revision object when we need it...
- $this->mContent = $revision->revText(); // Loads if user is allowed
+ $this->mContent = $revision->getText( Revision::FOR_THIS_USER ); // Loads if user is allowed
$this->mUser = $revision->getUser();
$this->mUserText = $revision->getUserText();
@@ -457,7 +458,7 @@ class Article {
*
* @param $x Mixed: FIXME
*/
- function forUpdate( $x = NULL ) {
+ public function forUpdate( $x = NULL ) {
return wfSetVar( $this->mForUpdate, $x );
}
@@ -479,9 +480,9 @@ class Article {
* the default
* @return Array: options
*/
- function getSelectOptions( $options = '' ) {
- if ( $this->mForUpdate ) {
- if ( is_array( $options ) ) {
+ protected function getSelectOptions( $options = '' ) {
+ if( $this->mForUpdate ) {
+ if( is_array( $options ) ) {
$options[] = 'FOR UPDATE';
} else {
$options = 'FOR UPDATE';
@@ -493,7 +494,7 @@ class Article {
/**
* @return int Page ID
*/
- function getID() {
+ public function getID() {
if( $this->mTitle ) {
return $this->mTitle->getArticleID();
} else {
@@ -504,22 +505,38 @@ class Article {
/**
* @return bool Whether or not the page exists in the database
*/
- function exists() {
- return $this->getId() != 0;
+ public function exists() {
+ return $this->getId() > 0;
+ }
+
+ /**
+ * Check if this page is something we're going to be showing
+ * some sort of sensible content for. If we return false, page
+ * views (plain action=view) will return an HTTP 404 response,
+ * so spiders and robots can know they're following a bad link.
+ *
+ * @return bool
+ */
+ public function hasViewableContent() {
+ return $this->exists() || $this->mTitle->isAlwaysKnown();
}
/**
* @return int The view count for the page
*/
- function getCount() {
- if ( -1 == $this->mCounter ) {
+ public function getCount() {
+ if( -1 == $this->mCounter ) {
$id = $this->getID();
- if ( $id == 0 ) {
+ if( $id == 0 ) {
$this->mCounter = 0;
} else {
$dbr = wfGetDB( DB_SLAVE );
- $this->mCounter = $dbr->selectField( 'page', 'page_counter', array( 'page_id' => $id ),
- 'Article::getCount', $this->getSelectOptions() );
+ $this->mCounter = $dbr->selectField( 'page',
+ 'page_counter',
+ array( 'page_id' => $id ),
+ __METHOD__,
+ $this->getSelectOptions()
+ );
}
}
return $this->mCounter;
@@ -532,14 +549,11 @@ class Article {
* @param $text String: text to analyze
* @return bool
*/
- function isCountable( $text ) {
+ public function isCountable( $text ) {
global $wgUseCommaCount;
$token = $wgUseCommaCount ? ',' : '[[';
- return
- $this->mTitle->isContentPage()
- && !$this->isRedirect( $text )
- && in_string( $token, $text );
+ return $this->mTitle->isContentPage() && !$this->isRedirect($text) && in_string($token,$text);
}
/**
@@ -548,11 +562,11 @@ class Article {
* @param $text String: FIXME
* @return bool
*/
- function isRedirect( $text = false ) {
- if ( $text === false ) {
- if ( $this->mDataLoaded )
+ public function isRedirect( $text = false ) {
+ if( $text === false ) {
+ if( $this->mDataLoaded ) {
return $this->mIsRedirect;
-
+ }
// Apparently loadPageData was never called
$this->loadContent();
$titleObj = Title::newFromRedirect( $this->fetchContent() );
@@ -567,28 +581,25 @@ class Article {
* to this page (and it exists).
* @return bool
*/
- function isCurrent() {
+ public function isCurrent() {
# If no oldid, this is the current version.
- if ($this->getOldID() == 0)
+ if( $this->getOldID() == 0 ) {
return true;
-
- return $this->exists() &&
- isset( $this->mRevision ) &&
- $this->mRevision->isCurrent();
+ }
+ return $this->exists() && isset($this->mRevision) && $this->mRevision->isCurrent();
}
/**
* Loads everything except the text
* This isn't necessary for all uses, so it's only done if needed.
- * @private
*/
- function loadLastEdit() {
- if ( -1 != $this->mUser )
+ protected function loadLastEdit() {
+ if( -1 != $this->mUser )
return;
# New or non-existent articles have no user information
$id = $this->getID();
- if ( 0 == $id ) return;
+ if( 0 == $id ) return;
$this->mLastRevision = Revision::loadFromPageId( wfGetDB( DB_MASTER ), $id );
if( !is_null( $this->mLastRevision ) ) {
@@ -601,35 +612,36 @@ class Article {
}
}
- function getTimestamp() {
+ public function getTimestamp() {
// Check if the field has been filled by ParserCache::get()
- if ( !$this->mTimestamp ) {
+ if( !$this->mTimestamp ) {
$this->loadLastEdit();
}
return wfTimestamp(TS_MW, $this->mTimestamp);
}
- function getUser() {
+ public function getUser() {
$this->loadLastEdit();
return $this->mUser;
}
- function getUserText() {
+ public function getUserText() {
$this->loadLastEdit();
return $this->mUserText;
}
- function getComment() {
+ public function getComment() {
$this->loadLastEdit();
return $this->mComment;
}
- function getMinorEdit() {
+ public function getMinorEdit() {
$this->loadLastEdit();
return $this->mMinorEdit;
}
- function getRevIdFetched() {
+ /* Use this to fetch the rev ID used on page views */
+ public function getRevIdFetched() {
$this->loadLastEdit();
return $this->mRevIdFetched;
}
@@ -638,7 +650,7 @@ class Article {
* @param $limit Integer: default 0.
* @param $offset Integer: default 0.
*/
- function getContributors($limit = 0, $offset = 0) {
+ public function getContributors($limit = 0, $offset = 0) {
# XXX: this is expensive; cache this info somewhere.
$contribs = array();
@@ -648,49 +660,62 @@ class Article {
$user = $this->getUser();
$pageId = $this->getId();
- $sql = "SELECT rev_user, rev_user_text, user_real_name, MAX(rev_timestamp) as timestamp
+ $sql = "SELECT {$userTable}.*, MAX(rev_timestamp) as timestamp
FROM $revTable LEFT JOIN $userTable ON rev_user = user_id
WHERE rev_page = $pageId
AND rev_user != $user
GROUP BY rev_user, rev_user_text, user_real_name
ORDER BY timestamp DESC";
- if ($limit > 0) { $sql .= ' LIMIT '.$limit; }
- if ($offset > 0) { $sql .= ' OFFSET '.$offset; }
-
- $sql .= ' '. $this->getSelectOptions();
+ if($limit > 0) { $sql .= ' LIMIT '.$limit; }
+ if($offset > 0) { $sql .= ' OFFSET '.$offset; }
- $res = $dbr->query($sql, __METHOD__);
+ $sql .= ' '. $this->getSelectOptions();
- while ( $line = $dbr->fetchObject( $res ) ) {
- $contribs[] = array($line->rev_user, $line->rev_user_text, $line->user_real_name);
- }
+ $res = $dbr->query($sql, __METHOD__ );
- $dbr->freeResult($res);
- return $contribs;
+ return new UserArrayFromResult( $res );
}
/**
* This is the default action of the script: just view the page of
* the given title.
*/
- function view() {
+ public function view() {
global $wgUser, $wgOut, $wgRequest, $wgContLang;
global $wgEnableParserCache, $wgStylePath, $wgParser;
global $wgUseTrackbacks, $wgNamespaceRobotPolicies, $wgArticleRobotPolicies;
global $wgDefaultRobotPolicy;
- $sk = $wgUser->getSkin();
wfProfileIn( __METHOD__ );
- $parserCache = ParserCache::singleton();
- $ns = $this->mTitle->getNamespace(); # shortcut
-
# Get variables from query string
$oldid = $this->getOldID();
+ # Try file cache
+ if( $oldid === 0 && $this->checkTouched() ) {
+ global $wgUseETag;
+ if( $wgUseETag ) {
+ $parserCache = ParserCache::singleton();
+ $wgOut->setETag( $parserCache->getETag($this,$wgUser) );
+ }
+ if( $wgOut->checkLastModified( $this->getTouched() ) ) {
+ wfProfileOut( __METHOD__ );
+ return;
+ } else if( $this->tryFileCache() ) {
+ # tell wgOut that output is taken care of
+ $wgOut->disable();
+ $this->viewUpdates();
+ wfProfileOut( __METHOD__ );
+ return;
+ }
+ }
+
+ $ns = $this->mTitle->getNamespace(); # shortcut
+ $sk = $wgUser->getSkin();
+
# getOldID may want us to redirect somewhere else
- if ( $this->mRedirectUrl ) {
+ if( $this->mRedirectUrl ) {
$wgOut->redirect( $this->mRedirectUrl );
wfProfileOut( __METHOD__ );
return;
@@ -701,13 +726,14 @@ class Article {
$rdfrom = $wgRequest->getVal( 'rdfrom' );
$diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
$purge = $wgRequest->getVal( 'action' ) == 'purge';
+ $return404 = false;
$wgOut->setArticleFlag( true );
# Discourage indexing of printable versions, but encourage following
if( $wgOut->isPrintable() ) {
$policy = 'noindex,follow';
- } elseif ( isset( $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()] ) ) {
+ } elseif( isset( $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()] ) ) {
$policy = $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()];
} elseif( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
# Honour customised robot policies for this namespace
@@ -720,10 +746,12 @@ class Article {
# If we got diff and oldid in the query, we want to see a
# diff page instead of the article.
- if ( !is_null( $diff ) ) {
+ if( !is_null( $diff ) ) {
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
- $de = new DifferenceEngine( $this->mTitle, $oldid, $diff, $rcid, $purge );
+ $diff = $wgRequest->getVal( 'diff' );
+ $htmldiff = $wgRequest->getVal( 'htmldiff' , false);
+ $de = new DifferenceEngine( $this->mTitle, $oldid, $diff, $rcid, $purge, $htmldiff);
// DifferenceEngine directly fetched the revision:
$this->mRevIdFetched = $de->mNewid;
$de->showDiffPage( $diffOnly );
@@ -738,51 +766,36 @@ class Article {
return;
}
- if ( empty( $oldid ) && $this->checkTouched() ) {
- $wgOut->setETag($parserCache->getETag($this, $wgUser));
-
- if( $wgOut->checkLastModified( $this->mTouched ) ){
- wfProfileOut( __METHOD__ );
- return;
- } else if ( $this->tryFileCache() ) {
- # tell wgOut that output is taken care of
- $wgOut->disable();
- $this->viewUpdates();
- wfProfileOut( __METHOD__ );
- return;
- }
- }
-
# Should the parser cache be used?
$pcache = $this->useParserCache( $oldid );
wfDebug( 'Article::view using parser cache: ' . ($pcache ? 'yes' : 'no' ) . "\n" );
- if ( $wgUser->getOption( 'stubthreshold' ) ) {
+ if( $wgUser->getOption( 'stubthreshold' ) ) {
wfIncrStats( 'pcache_miss_stub' );
}
$wasRedirected = false;
- if ( isset( $this->mRedirectedFrom ) ) {
+ if( isset( $this->mRedirectedFrom ) ) {
// This is an internally redirected page view.
// We'll need a backlink to the source page for navigation.
- if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
+ if( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
$redir = $sk->makeKnownLinkObj( $this->mRedirectedFrom, '', 'redirect=no' );
- $s = wfMsg( 'redirectedfrom', $redir );
+ $s = wfMsgExt( 'redirectedfrom', array( 'parseinline', 'replaceafter' ), $redir );
$wgOut->setSubtitle( $s );
// Set the fragment if one was specified in the redirect
- if ( strval( $this->mTitle->getFragment() ) != '' ) {
+ if( strval( $this->mTitle->getFragment() ) != '' ) {
$fragment = Xml::escapeJsString( $this->mTitle->getFragmentForURL() );
$wgOut->addInlineScript( "redirectToFragment(\"$fragment\");" );
}
$wasRedirected = true;
}
- } elseif ( !empty( $rdfrom ) ) {
+ } elseif( !empty( $rdfrom ) ) {
// This is an externally redirected view, from some other wiki.
// If it was reported from a trusted site, supply a backlink.
global $wgRedirectSources;
if( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
$redir = $sk->makeExternalLink( $rdfrom, $rdfrom );
- $s = wfMsg( 'redirectedfrom', $redir );
+ $s = wfMsgExt( 'redirectedfrom', array( 'parseinline', 'replaceafter' ), $redir );
$wgOut->setSubtitle( $s );
$wasRedirected = true;
}
@@ -790,18 +803,20 @@ class Article {
$outputDone = false;
wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$pcache ) );
- if ( $pcache ) {
- if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
- // Ensure that UI elements requiring revision ID have
- // the correct version information.
- $wgOut->setRevisionId( $this->mLatest );
- $outputDone = true;
- }
+ if( $pcache && $wgOut->tryParserCache( $this, $wgUser ) ) {
+ // Ensure that UI elements requiring revision ID have
+ // the correct version information.
+ $wgOut->setRevisionId( $this->mLatest );
+ $outputDone = true;
}
# Fetch content and check for errors
- if ( !$outputDone ) {
+ if( !$outputDone ) {
+ # If the article does not exist and was deleted, show the log
+ if( $this->getID() == 0 ) {
+ $this->showDeletionLog();
+ }
$text = $this->getContent();
- if ( $text === false ) {
+ if( $text === false ) {
# Failed to load, replace text with error message
$t = $this->mTitle->getPrefixedText();
if( $oldid ) {
@@ -811,18 +826,38 @@ class Article {
$text = wfMsg( 'noarticletext' );
}
}
+
+ # Non-existent pages
+ if( $this->getID() === 0 ) {
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
+ $text = "<div class='noarticletext'>\n$text\n</div>";
+ if( !$this->hasViewableContent() ) {
+ // If there's no backing content, send a 404 Not Found
+ // for better machine handling of broken links.
+ $return404 = true;
+ }
+ }
+
+ if( $return404 ) {
+ $wgRequest->response()->header( "HTTP/1.x 404 Not Found" );
+ }
# Another whitelist check in case oldid is altering the title
- if ( !$this->mTitle->userCanRead() ) {
+ if( !$this->mTitle->userCanRead() ) {
$wgOut->loginToUse();
$wgOut->output();
+ $wgOut->disable();
wfProfileOut( __METHOD__ );
- exit;
+ return;
}
+
+ # For ?curid=x urls, disallow indexing
+ if( $wgRequest->getInt('curid') )
+ $wgOut->setRobotPolicy( 'noindex,follow' );
# We're looking at an old revision
- if ( !empty( $oldid ) ) {
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
+ if( !empty( $oldid ) ) {
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
if( is_null( $this->mRevision ) ) {
// FIXME: This would be a nice place to load the 'no such page' text.
} else {
@@ -840,27 +875,27 @@ class Article {
}
}
}
-
+
$wgOut->setRevisionId( $this->getRevIdFetched() );
// Pages containing custom CSS or JavaScript get special treatment
if( $this->mTitle->isCssOrJsPage() || $this->mTitle->isCssJsSubpage() ) {
- $wgOut->addHtml( wfMsgExt( 'clearyourcache', 'parse' ) );
+ $wgOut->addHTML( wfMsgExt( 'clearyourcache', 'parse' ) );
// Give hooks a chance to customise the output
if( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->mTitle, $wgOut ) ) ) {
// Wrap the whole lot in a <pre> and don't parse
$m = array();
preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m );
- $wgOut->addHtml( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
- $wgOut->addHtml( htmlspecialchars( $this->mContent ) );
- $wgOut->addHtml( "\n</pre>\n" );
+ $wgOut->addHTML( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
+ $wgOut->addHTML( htmlspecialchars( $this->mContent ) );
+ $wgOut->addHTML( "\n</pre>\n" );
}
- } else if ( $rt = Title::newFromRedirect( $text ) ) {
+ } else if( $rt = Title::newFromRedirect( $text ) ) {
# Don't append the subtitle if this was an old revision
- $this->viewRedirect( $rt, !$wasRedirected && $this->isCurrent() );
+ $wgOut->addHTML( $this->viewRedirect( $rt, !$wasRedirected && $this->isCurrent() ) );
$parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser));
$wgOut->addParserOutputNoText( $parseout );
- } else if ( $pcache ) {
+ } else if( $pcache ) {
# Display content and save to parser cache
$this->outputWikiText( $text );
} else {
@@ -876,7 +911,7 @@ class Article {
$time += wfTime();
# Timing hack
- if ( $time > 3 ) {
+ if( $time > 3 ) {
wfDebugLog( 'slow-parse', sprintf( "%-5.2f %s", $time,
$this->mTitle->getPrefixedDBkey()));
}
@@ -890,6 +925,14 @@ class Article {
$t = $wgOut->getPageTitle();
if( empty( $t ) ) {
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
+
+ # For the main page, overwrite the <title> element with the con-
+ # tents of 'pagetitle-view-mainpage' instead of the default (if
+ # that's not empty).
+ if( $this->mTitle->equals( Title::newMainPage() ) &&
+ wfMsgForContent( 'pagetitle-view-mainpage' ) !== '' ) {
+ $wgOut->setHTMLTitle( wfMsgForContent( 'pagetitle-view-mainpage' ) );
+ }
}
# check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
@@ -899,7 +942,7 @@ class Article {
# If we have been passed an &rcid= parameter, we want to give the user a
# chance to mark this new article as patrolled.
- if( !is_null( $rcid ) && $rcid != 0 && $wgUser->isAllowed( 'patrol' ) && $this->mTitle->exists() ) {
+ if( !empty($rcid) && $this->mTitle->exists() && $this->mTitle->userCan('patrol') ) {
$wgOut->addHTML(
"<div class='patrollink'>" .
wfMsgHtml( 'markaspatrolledlink',
@@ -911,19 +954,45 @@ class Article {
}
# Trackbacks
- if ($wgUseTrackbacks)
+ if( $wgUseTrackbacks ) {
$this->addTrackbacks();
+ }
$this->viewUpdates();
wfProfileOut( __METHOD__ );
}
- /*
+ protected function showDeletionLog() {
+ global $wgUser, $wgOut;
+ $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut );
+ $pager = new LogPager( $loglist, 'delete', false, $this->mTitle->getPrefixedText() );
+ if( $pager->getNumRows() > 0 ) {
+ $pager->mLimit = 10;
+ $wgOut->addHTML( '<div class="mw-warning-with-logexcerpt">' );
+ $wgOut->addWikiMsg( 'deleted-notice' );
+ $wgOut->addHTML(
+ $loglist->beginLogEventsList() .
+ $pager->getBody() .
+ $loglist->endLogEventsList()
+ );
+ if( $pager->getNumRows() > 10 ) {
+ $wgOut->addHTML( $wgUser->getSkin()->link(
+ SpecialPage::getTitleFor( 'Log' ),
+ wfMsgHtml( 'deletelog-fulllog' ),
+ array(),
+ array( 'type' => 'delete', 'page' => $this->mTitle->getPrefixedText() )
+ ) );
+ }
+ $wgOut->addHTML( '</div>' );
+ }
+ }
+
+ /*
* Should the parser cache be used?
*/
protected function useParserCache( $oldid ) {
global $wgUser, $wgEnableParserCache;
-
+
return $wgEnableParserCache
&& intval( $wgUser->getOption( 'stubthreshold' ) ) == 0
&& $this->exists()
@@ -931,47 +1000,48 @@ class Article {
&& !$this->mTitle->isCssOrJsPage()
&& !$this->mTitle->isCssJsSubpage();
}
-
- protected function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) {
+
+ /**
+ * View redirect
+ * @param $target Title object of destination to redirect
+ * @param $appendSubtitle Boolean [optional]
+ * @param $forceKnown Boolean: should the image be shown as a bluelink regardless of existence?
+ */
+ public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) {
global $wgParser, $wgOut, $wgContLang, $wgStylePath, $wgUser;
-
# Display redirect
$imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
$imageUrl = $wgStylePath.'/common/images/redirect' . $imageDir . '.png';
-
+
if( $appendSubtitle ) {
$wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) );
}
$sk = $wgUser->getSkin();
- if ( $forceKnown )
+ if( $forceKnown ) {
$link = $sk->makeKnownLinkObj( $target, htmlspecialchars( $target->getFullText() ) );
- else
+ } else {
$link = $sk->makeLinkObj( $target, htmlspecialchars( $target->getFullText() ) );
+ }
+ return '<img src="'.$imageUrl.'" alt="#REDIRECT " />' .
+ '<span class="redirectText">'.$link.'</span>';
- $wgOut->addHTML( '<img src="'.$imageUrl.'" alt="#REDIRECT " />' .
- '<span class="redirectText">'.$link.'</span>' );
-
}
- function addTrackbacks() {
+ public function addTrackbacks() {
global $wgOut, $wgUser;
-
- $dbr = wfGetDB(DB_SLAVE);
- $tbs = $dbr->select(
- /* FROM */ 'trackbacks',
- /* SELECT */ array('tb_id', 'tb_title', 'tb_url', 'tb_ex', 'tb_name'),
- /* WHERE */ array('tb_page' => $this->getID())
+ $dbr = wfGetDB( DB_SLAVE );
+ $tbs = $dbr->select( 'trackbacks',
+ array('tb_id', 'tb_title', 'tb_url', 'tb_ex', 'tb_name'),
+ array('tb_page' => $this->getID() )
);
-
- if (!$dbr->numrows($tbs))
- return;
+ if( !$dbr->numRows($tbs) ) return;
$tbtext = "";
- while ($o = $dbr->fetchObject($tbs)) {
+ while( $o = $dbr->fetchObject($tbs) ) {
$rmvtxt = "";
- if ($wgUser->isAllowed( 'trackback' )) {
- $delurl = $this->mTitle->getFullURL("action=deletetrackback&tbid="
- . $o->tb_id . "&token=" . urlencode( $wgUser->editToken() ) );
+ if( $wgUser->isAllowed( 'trackback' ) ) {
+ $delurl = $this->mTitle->getFullURL("action=deletetrackback&tbid=" .
+ $o->tb_id . "&token=" . urlencode( $wgUser->editToken() ) );
$rmvtxt = wfMsg( 'trackbackremove', htmlspecialchars( $delurl ) );
}
$tbtext .= "\n";
@@ -983,33 +1053,31 @@ class Article {
$rmvtxt);
}
$wgOut->addWikiMsg( 'trackbackbox', $tbtext );
+ $this->mTitle->invalidateCache();
}
- function deletetrackback() {
+ public function deletetrackback() {
global $wgUser, $wgRequest, $wgOut, $wgTitle;
-
- if (!$wgUser->matchEditToken($wgRequest->getVal('token'))) {
+ if( !$wgUser->matchEditToken($wgRequest->getVal('token')) ) {
$wgOut->addWikiMsg( 'sessionfailure' );
return;
}
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgUser );
-
- if (count($permission_errors)>0)
- {
+ if( count($permission_errors) ) {
$wgOut->showPermissionsErrorPage( $permission_errors );
return;
}
- $db = wfGetDB(DB_MASTER);
- $db->delete('trackbacks', array('tb_id' => $wgRequest->getInt('tbid')));
- $wgTitle->invalidateCache();
- $wgOut->addWikiMsg('trackbackdeleteok');
+ $db = wfGetDB( DB_MASTER );
+ $db->delete( 'trackbacks', array('tb_id' => $wgRequest->getInt('tbid')) );
+
+ $wgOut->addWikiMsg( 'trackbackdeleteok' );
+ $this->mTitle->invalidateCache();
}
- function render() {
+ public function render() {
global $wgOut;
-
$wgOut->setArticleBodyOnly(true);
$this->view();
}
@@ -1017,37 +1085,36 @@ class Article {
/**
* Handle action=purge
*/
- function purge() {
+ public function purge() {
global $wgUser, $wgRequest, $wgOut;
-
- if ( $wgUser->isAllowed( 'purge' ) || $wgRequest->wasPosted() ) {
+ if( $wgUser->isAllowed( 'purge' ) || $wgRequest->wasPosted() ) {
if( wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
$this->doPurge();
+ $this->view();
}
} else {
- $msg = $wgOut->parse( wfMsg( 'confirm_purge' ) );
- $action = htmlspecialchars( $_SERVER['REQUEST_URI'] );
- $button = htmlspecialchars( wfMsg( 'confirm_purge_button' ) );
- $msg = str_replace( '$1',
- "<form method=\"post\" action=\"$action\">\n" .
- "<input type=\"submit\" name=\"submit\" value=\"$button\" />\n" .
- "</form>\n", $msg );
-
+ $action = htmlspecialchars( $wgRequest->getRequestURL() );
+ $button = wfMsgExt( 'confirm_purge_button', array('escapenoentities') );
+ $form = "<form method=\"post\" action=\"$action\">\n" .
+ "<input type=\"submit\" name=\"submit\" value=\"$button\" />\n" .
+ "</form>\n";
+ $top = wfMsgExt( 'confirm-purge-top', array('parse') );
+ $bottom = wfMsgExt( 'confirm-purge-bottom', array('parse') );
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
- $wgOut->addHTML( $msg );
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
+ $wgOut->addHTML( $top . $form . $bottom );
}
}
/**
* Perform the actions of a page purging
*/
- function doPurge() {
+ public function doPurge() {
global $wgUseSquid;
// Invalidate the cache
$this->mTitle->invalidateCache();
- if ( $wgUseSquid ) {
+ if( $wgUseSquid ) {
// Commit the transaction before the purge is sent
$dbw = wfGetDB( DB_MASTER );
$dbw->immediateCommit();
@@ -1056,16 +1123,15 @@ class Article {
$update = SquidUpdate::newSimplePurge( $this->mTitle );
$update->doUpdate();
}
- if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+ if( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
global $wgMessageCache;
- if ( $this->getID() == 0 ) {
+ if( $this->getID() == 0 ) {
$text = false;
} else {
$text = $this->getContent();
}
$wgMessageCache->replace( $this->mTitle->getDBkey(), $text );
}
- $this->view();
}
/**
@@ -1075,11 +1141,11 @@ class Article {
* or else the record will be left in a funky state.
* Best if all done inside a transaction.
*
- * @param Database $dbw
- * @return int The newly created page_id key
+ * @param $dbw Database
+ * @return int The newly created page_id key, or false if the title already existed
* @private
*/
- function insertOn( $dbw ) {
+ public function insertOn( $dbw ) {
wfProfileIn( __METHOD__ );
$page_id = $dbw->nextSequenceValue( 'page_page_id_seq' );
@@ -1095,31 +1161,33 @@ class Article {
'page_touched' => $dbw->timestamp(),
'page_latest' => 0, # Fill this in shortly...
'page_len' => 0, # Fill this in shortly...
- ), __METHOD__ );
- $newid = $dbw->insertId();
-
- $this->mTitle->resetArticleId( $newid );
+ ), __METHOD__, 'IGNORE' );
+ $affected = $dbw->affectedRows();
+ if( $affected ) {
+ $newid = $dbw->insertId();
+ $this->mTitle->resetArticleId( $newid );
+ }
wfProfileOut( __METHOD__ );
- return $newid;
+ return $affected ? $newid : false;
}
/**
* Update the page record to point to a newly saved revision.
*
- * @param Database $dbw
- * @param Revision $revision For ID number, and text used to set
- length and redirect status fields
- * @param int $lastRevision If given, will not overwrite the page field
- * when different from the currently set value.
- * Giving 0 indicates the new page flag should
- * be set on.
- * @param bool $lastRevIsRedirect If given, will optimize adding and
- * removing rows in redirect table.
+ * @param $dbw Database object
+ * @param $revision Revision: For ID number, and text used to set
+ length and redirect status fields
+ * @param $lastRevision Integer: if given, will not overwrite the page field
+ * when different from the currently set value.
+ * Giving 0 indicates the new page flag should be set
+ * on.
+ * @param $lastRevIsRedirect Boolean: if given, will optimize adding and
+ * removing rows in redirect table.
* @return bool true on success, false on failure
* @private
*/
- function updateRevisionOn( &$dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null ) {
+ public function updateRevisionOn( &$dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null ) {
wfProfileIn( __METHOD__ );
$text = $revision->getText();
@@ -1143,8 +1211,7 @@ class Article {
__METHOD__ );
$result = $dbw->affectedRows() != 0;
-
- if ($result) {
+ if( $result ) {
$this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
}
@@ -1155,46 +1222,40 @@ class Article {
/**
* Add row to the redirect table if this is a redirect, remove otherwise.
*
- * @param Database $dbw
+ * @param $dbw Database
* @param $redirectTitle a title object pointing to the redirect target,
- * or NULL if this is not a redirect
- * @param bool $lastRevIsRedirect If given, will optimize adding and
- * removing rows in redirect table.
+ * or NULL if this is not a redirect
+ * @param $lastRevIsRedirect If given, will optimize adding and
+ * removing rows in redirect table.
* @return bool true on success, false on failure
* @private
*/
- function updateRedirectOn( &$dbw, $redirectTitle, $lastRevIsRedirect = null ) {
-
+ public function updateRedirectOn( &$dbw, $redirectTitle, $lastRevIsRedirect = null ) {
// Always update redirects (target link might have changed)
// Update/Insert if we don't know if the last revision was a redirect or not
// Delete if changing from redirect to non-redirect
$isRedirect = !is_null($redirectTitle);
- if ($isRedirect || is_null($lastRevIsRedirect) || $lastRevIsRedirect !== $isRedirect) {
-
+ if($isRedirect || is_null($lastRevIsRedirect) || $lastRevIsRedirect !== $isRedirect) {
wfProfileIn( __METHOD__ );
-
- if ($isRedirect) {
-
+ if( $isRedirect ) {
// This title is a redirect, Add/Update row in the redirect table
$set = array( /* SET */
'rd_namespace' => $redirectTitle->getNamespace(),
'rd_title' => $redirectTitle->getDBkey(),
'rd_from' => $this->getId(),
);
-
$dbw->replace( 'redirect', array( 'rd_from' ), $set, __METHOD__ );
} else {
// This is not a redirect, remove row from redirect table
$where = array( 'rd_from' => $this->getId() );
$dbw->delete( 'redirect', $where, __METHOD__);
}
-
- if( $this->getTitle()->getNamespace() == NS_IMAGE )
+ if( $this->getTitle()->getNamespace() == NS_FILE ) {
RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $this->getTitle() );
+ }
wfProfileOut( __METHOD__ );
return ( $dbw->affectedRows() != 0 );
}
-
return true;
}
@@ -1202,12 +1263,11 @@ class Article {
* If the given revision is newer than the currently set page_latest,
* update the page record. Otherwise, do nothing.
*
- * @param Database $dbw
- * @param Revision $revision
+ * @param $dbw Database object
+ * @param $revision Revision object
*/
- function updateIfNewerOn( &$dbw, $revision ) {
+ public function updateIfNewerOn( &$dbw, $revision ) {
wfProfileIn( __METHOD__ );
-
$row = $dbw->selectRow(
array( 'revision', 'page' ),
array( 'rev_id', 'rev_timestamp', 'page_is_redirect' ),
@@ -1227,28 +1287,27 @@ class Article {
$prev = 0;
$lastRevIsRedirect = null;
}
-
$ret = $this->updateRevisionOn( $dbw, $revision, $prev, $lastRevIsRedirect );
wfProfileOut( __METHOD__ );
return $ret;
}
/**
+ * @param $section empty/null/false or a section number (0, 1, 2, T1, T2...)
* @return string Complete article text, or null if error
*/
- function replaceSection($section, $text, $summary = '', $edittime = NULL) {
+ public function replaceSection( $section, $text, $summary = '', $edittime = NULL ) {
wfProfileIn( __METHOD__ );
-
- if( $section == '' ) {
- // Whole-page edit; let the text through unmolested.
+ if( strval( $section ) == '' ) {
+ // Whole-page edit; let the whole text through
} else {
- if( is_null( $edittime ) ) {
+ if( is_null($edittime) ) {
$rev = Revision::newFromTitle( $this->mTitle );
} else {
$dbw = wfGetDB( DB_MASTER );
$rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
}
- if( is_null( $rev ) ) {
+ if( !$rev ) {
wfDebug( "Article::replaceSection asked for bogus section (page: " .
$this->getId() . "; section: $section; edittime: $edittime)\n" );
return null;
@@ -1266,9 +1325,7 @@ class Article {
global $wgParser;
$text = $wgParser->replaceSection( $oldtext, $section, $text );
}
-
}
-
wfProfileOut( __METHOD__ );
return $text;
}
@@ -1277,27 +1334,28 @@ class Article {
* @deprecated use Article::doEdit()
*/
function insertNewArticle( $text, $summary, $isminor, $watchthis, $suppressRC=false, $comment=false, $bot=false ) {
+ wfDeprecated( __METHOD__ );
$flags = EDIT_NEW | EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY |
( $isminor ? EDIT_MINOR : 0 ) |
( $suppressRC ? EDIT_SUPPRESS_RC : 0 ) |
( $bot ? EDIT_FORCE_BOT : 0 );
# If this is a comment, add the summary as headline
- if ( $comment && $summary != "" ) {
+ if( $comment && $summary != "" ) {
$text = wfMsgForContent('newsectionheaderdefaultlevel',$summary) . "\n\n".$text;
}
$this->doEdit( $text, $summary, $flags );
$dbw = wfGetDB( DB_MASTER );
- if ($watchthis) {
- if (!$this->mTitle->userIsWatching()) {
+ if($watchthis) {
+ if(!$this->mTitle->userIsWatching()) {
$dbw->begin();
$this->doWatch();
$dbw->commit();
}
} else {
- if ( $this->mTitle->userIsWatching() ) {
+ if( $this->mTitle->userIsWatching() ) {
$dbw->begin();
$this->doUnwatch();
$dbw->commit();
@@ -1310,33 +1368,36 @@ class Article {
* @deprecated use Article::doEdit()
*/
function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false, $sectionanchor = '' ) {
+ wfDeprecated( __METHOD__ );
$flags = EDIT_UPDATE | EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY |
( $minor ? EDIT_MINOR : 0 ) |
( $forceBot ? EDIT_FORCE_BOT : 0 );
- $good = $this->doEdit( $text, $summary, $flags );
- if ( $good ) {
- $dbw = wfGetDB( DB_MASTER );
- if ($watchthis) {
- if (!$this->mTitle->userIsWatching()) {
- $dbw->begin();
- $this->doWatch();
- $dbw->commit();
- }
- } else {
- if ( $this->mTitle->userIsWatching() ) {
- $dbw->begin();
- $this->doUnwatch();
- $dbw->commit();
- }
+ $status = $this->doEdit( $text, $summary, $flags );
+ if( !$status->isOK() ) {
+ return false;
+ }
+
+ $dbw = wfGetDB( DB_MASTER );
+ if( $watchthis ) {
+ if(!$this->mTitle->userIsWatching()) {
+ $dbw->begin();
+ $this->doWatch();
+ $dbw->commit();
}
+ } else {
+ if( $this->mTitle->userIsWatching() ) {
+ $dbw->begin();
+ $this->doUnwatch();
+ $dbw->commit();
+ }
+ }
- $extraQuery = ''; // Give extensions a chance to modify URL query on update
- wfRunHooks( 'ArticleUpdateBeforeRedirect', array( $this, &$sectionanchor, &$extraQuery ) );
+ $extraQuery = ''; // Give extensions a chance to modify URL query on update
+ wfRunHooks( 'ArticleUpdateBeforeRedirect', array( $this, &$sectionanchor, &$extraQuery ) );
- $this->doRedirect( $this->isRedirect( $text ), $sectionanchor, $extraQuery );
- }
- return $good;
+ $this->doRedirect( $this->isRedirect( $text ), $sectionanchor, $extraQuery );
+ return true;
}
/**
@@ -1347,9 +1408,9 @@ class Article {
*
* $wgUser must be set before calling this function.
*
- * @param string $text New text
- * @param string $summary Edit summary
- * @param integer $flags bitfield:
+ * @param $text String: new text
+ * @param $summary String: edit summary
+ * @param $flags Integer bitfield:
* EDIT_NEW
* Article is known or assumed to be non-existent, create a new one
* EDIT_UPDATE
@@ -1366,40 +1427,67 @@ class Article {
* Fill in blank summaries with generated text where possible
*
* If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
- * If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If
- * EDIT_NEW is specified and the article does exist, a duplicate key error will cause an exception
- * to be thrown from the Database. These two conditions are also possible with auto-detection due
- * to MediaWiki's performance-optimised locking strategy.
- * @param $baseRevId, the revision ID this edit was based off, if any
+ * If EDIT_UPDATE is specified and the article doesn't exist, the function will an
+ * edit-gone-missing error. If EDIT_NEW is specified and the article does exist, an
+ * edit-already-exists error will be returned. These two conditions are also possible with
+ * auto-detection due to MediaWiki's performance-optimised locking strategy.
+ *
+ * @param $baseRevId the revision ID this edit was based off, if any
+ * @param $user Optional user object, $wgUser will be used if not passed
*
- * @return bool success
+ * @return Status object. Possible errors:
+ * edit-hook-aborted: The ArticleSave hook aborted the edit but didn't set the fatal flag of $status
+ * edit-gone-missing: In update mode, but the article didn't exist
+ * edit-conflict: In update mode, the article changed unexpectedly
+ * edit-no-change: Warning that the text was the same as before
+ * edit-already-exists: In creation mode, but the article already exists
+ *
+ * Extensions may define additional errors.
+ *
+ * $return->value will contain an associative array with members as follows:
+ * new: Boolean indicating if the function attempted to create a new article
+ * revision: The revision object for the inserted revision, or null
+ *
+ * Compatibility note: this function previously returned a boolean value indicating success/failure
*/
- function doEdit( $text, $summary, $flags = 0, $baseRevId = false ) {
+ public function doEdit( $text, $summary, $flags = 0, $baseRevId = false, $user = null ) {
global $wgUser, $wgDBtransactions, $wgUseAutomaticEditSummaries;
+ # Low-level sanity check
+ if( $this->mTitle->getText() == '' ) {
+ throw new MWException( 'Something is trying to edit an article with an empty title' );
+ }
+
wfProfileIn( __METHOD__ );
- $good = true;
- if ( !($flags & EDIT_NEW) && !($flags & EDIT_UPDATE) ) {
- $aid = $this->mTitle->getArticleID( GAID_FOR_UPDATE );
- if ( $aid ) {
+ $user = is_null($user) ? $wgUser : $user;
+ $status = Status::newGood( array() );
+
+ # Load $this->mTitle->getArticleID() and $this->mLatest if it's not already
+ $this->loadPageData();
+
+ if( !($flags & EDIT_NEW) && !($flags & EDIT_UPDATE) ) {
+ $aid = $this->mTitle->getArticleID();
+ if( $aid ) {
$flags |= EDIT_UPDATE;
} else {
$flags |= EDIT_NEW;
}
}
- if( !wfRunHooks( 'ArticleSave', array( &$this, &$wgUser, &$text,
- &$summary, $flags & EDIT_MINOR,
- null, null, &$flags ) ) )
+ if( !wfRunHooks( 'ArticleSave', array( &$this, &$user, &$text, &$summary,
+ $flags & EDIT_MINOR, null, null, &$flags, &$status ) ) )
{
wfDebug( __METHOD__ . ": ArticleSave hook aborted save!\n" );
wfProfileOut( __METHOD__ );
- return false;
+ if( $status->isOK() ) {
+ $status->fatal( 'edit-hook-aborted');
+ }
+ return $status;
}
# Silently ignore EDIT_MINOR if not allowed
- $isminor = ( $flags & EDIT_MINOR ) && $wgUser->isAllowed('minoredit');
+ $isminor = ( $flags & EDIT_MINOR ) && $user->isAllowed('minoredit');
$bot = $flags & EDIT_FORCE_BOT;
$oldtext = $this->getContent();
@@ -1417,32 +1505,29 @@ class Article {
$dbw = wfGetDB( DB_MASTER );
$now = wfTimestampNow();
- if ( $flags & EDIT_UPDATE ) {
+ if( $flags & EDIT_UPDATE ) {
# Update article, but only if changed.
-
+ $status->value['new'] = false;
# Make sure the revision is either completely inserted or not inserted at all
if( !$wgDBtransactions ) {
$userAbort = ignore_user_abort( true );
}
- $lastRevision = 0;
$revisionId = 0;
$changed = ( strcmp( $text, $oldtext ) != 0 );
- if ( $changed ) {
+ if( $changed ) {
$this->mGoodAdjustment = (int)$this->isCountable( $text )
- (int)$this->isCountable( $oldtext );
$this->mTotalAdjustment = 0;
- $lastRevision = $dbw->selectField(
- 'page', 'page_latest', array( 'page_id' => $this->getId() ) );
-
- if ( !$lastRevision ) {
+ if( !$this->mLatest ) {
# Article gone missing
wfDebug( __METHOD__.": EDIT_UPDATE specified but article doesn't exist\n" );
+ $status->fatal( 'edit-gone-missing' );
wfProfileOut( __METHOD__ );
- return false;
+ return $status;
}
$revision = new Revision( array(
@@ -1450,38 +1535,54 @@ class Article {
'comment' => $summary,
'minor_edit' => $isminor,
'text' => $text,
- 'parent_id' => $lastRevision
+ 'parent_id' => $this->mLatest,
+ 'user' => $user->getId(),
+ 'user_text' => $user->getName(),
) );
$dbw->begin();
$revisionId = $revision->insertOn( $dbw );
# Update page
- $ok = $this->updateRevisionOn( $dbw, $revision, $lastRevision );
+ #
+ # Note that we use $this->mLatest instead of fetching a value from the master DB
+ # during the course of this function. This makes sure that EditPage can detect
+ # edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
+ # before this function is called. A previous function used a separate query, this
+ # creates a window where concurrent edits can cause an ignored edit conflict.
+ $ok = $this->updateRevisionOn( $dbw, $revision, $this->mLatest );
if( !$ok ) {
/* Belated edit conflict! Run away!! */
- $good = false;
+ $status->fatal( 'edit-conflict' );
+ # Delete the invalid revision if the DB is not transactional
+ if( !$wgDBtransactions ) {
+ $dbw->delete( 'revision', array( 'rev_id' => $revisionId ), __METHOD__ );
+ }
+ $revisionId = 0;
$dbw->rollback();
} else {
- wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId ) );
-
+ global $wgUseRCPatrol;
+ wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, $baseRevId, $user) );
# Update recentchanges
if( !( $flags & EDIT_SUPPRESS_RC ) ) {
- $rcid = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $wgUser, $summary,
- $lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
- $revisionId );
-
# Mark as patrolled if the user can do so
- if( $GLOBALS['wgUseRCPatrol'] && $wgUser->isAllowed( 'autopatrol' ) ) {
- RecentChange::markPatrolled( $rcid );
- PatrolLog::record( $rcid, true );
+ $patrolled = $wgUseRCPatrol && $this->mTitle->userCan('autopatrol');
+ # Add RC row to the DB
+ $rc = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $user, $summary,
+ $this->mLatest, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
+ $revisionId, $patrolled
+ );
+ # Log auto-patrolled edits
+ if( $patrolled ) {
+ PatrolLog::record( $rc, true );
}
}
- $wgUser->incEditCount();
+ $user->incEditCount();
$dbw->commit();
}
} else {
+ $status->warning( 'edit-no-change' );
$revision = null;
// Keep the same revision ID, but do some updates on it
$revisionId = $this->getRevIdFetched();
@@ -1493,17 +1594,20 @@ class Article {
if( !$wgDBtransactions ) {
ignore_user_abort( $userAbort );
}
-
- if ( $good ) {
- # Invalidate cache of this article and all pages using this article
- # as a template. Partly deferred.
- Article::onArticleEdit( $this->mTitle );
-
- # Update links tables, site stats, etc.
- $this->editUpdates( $text, $summary, $isminor, $now, $revisionId, $changed );
+ // Now that ignore_user_abort is restored, we can respond to fatal errors
+ if( !$status->isOK() ) {
+ wfProfileOut( __METHOD__ );
+ return $status;
}
+
+ # Invalidate cache of this article and all pages using this article
+ # as a template. Partly deferred. Leave templatelinks for editUpdates().
+ Article::onArticleEdit( $this->mTitle, 'skiptransclusions' );
+ # Update links tables, site stats, etc.
+ $this->editUpdates( $text, $summary, $isminor, $now, $revisionId, $changed );
} else {
# Create new article
+ $status->value['new'] = true;
# Set statistics members
# We work out if it's countable after PST to avoid counter drift
@@ -1514,15 +1618,24 @@ class Article {
$dbw->begin();
# Add the page record; stake our claim on this title!
- # This will fail with a database query exception if the article already exists
+ # This will return false if the article already exists
$newid = $this->insertOn( $dbw );
+ if( $newid === false ) {
+ $dbw->rollback();
+ $status->fatal( 'edit-already-exists' );
+ wfProfileOut( __METHOD__ );
+ return $status;
+ }
+
# Save the revision text...
$revision = new Revision( array(
'page' => $newid,
'comment' => $summary,
'minor_edit' => $isminor,
- 'text' => $text
+ 'text' => $text,
+ 'user' => $user->getId(),
+ 'user_text' => $user->getName(),
) );
$revisionId = $revision->insertOn( $dbw );
@@ -1530,19 +1643,22 @@ class Article {
# Update the page record with revision data
$this->updateRevisionOn( $dbw, $revision, 0 );
-
- wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false) );
+ wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false, $user) );
+ # Update recentchanges
if( !( $flags & EDIT_SUPPRESS_RC ) ) {
- $rcid = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary, $bot,
- '', strlen( $text ), $revisionId );
- # Mark as patrolled if the user can
- if( ($GLOBALS['wgUseRCPatrol'] || $GLOBALS['wgUseNPPatrol']) && $wgUser->isAllowed( 'autopatrol' ) ) {
- RecentChange::markPatrolled( $rcid );
- PatrolLog::record( $rcid, true );
+ global $wgUseRCPatrol, $wgUseNPPatrol;
+ # Mark as patrolled if the user can do so
+ $patrolled = ($wgUseRCPatrol || $wgUseNPPatrol) && $this->mTitle->userCan('autopatrol');
+ # Add RC row to the DB
+ $rc = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot,
+ '', strlen($text), $revisionId, $patrolled );
+ # Log auto-patrolled edits
+ if( $patrolled ) {
+ PatrolLog::record( $rc, true );
}
}
- $wgUser->incEditCount();
+ $user->incEditCount();
$dbw->commit();
# Update links, etc.
@@ -1551,27 +1667,30 @@ class Article {
# Clear caches
Article::onArticleCreate( $this->mTitle );
- wfRunHooks( 'ArticleInsertComplete', array( &$this, &$wgUser, $text, $summary,
- $flags & EDIT_MINOR, null, null, &$flags, $revision ) );
+ wfRunHooks( 'ArticleInsertComplete', array( &$this, &$user, $text, $summary,
+ $flags & EDIT_MINOR, null, null, &$flags, $revision ) );
}
- if ( $good && !( $flags & EDIT_DEFER_UPDATES ) ) {
+ # Do updates right now unless deferral was requested
+ if( !( $flags & EDIT_DEFER_UPDATES ) ) {
wfDoUpdates();
}
- if ( $good ) {
- wfRunHooks( 'ArticleSaveComplete', array( &$this, &$wgUser, $text, $summary,
- $flags & EDIT_MINOR, null, null, &$flags, $revision ) );
- }
+ // Return the new revision (or null) to the caller
+ $status->value['revision'] = $revision;
+
+ wfRunHooks( 'ArticleSaveComplete', array( &$this, &$user, $text, $summary,
+ $flags & EDIT_MINOR, null, null, &$flags, $revision, &$status ) );
wfProfileOut( __METHOD__ );
- return $good;
+ return $status;
}
/**
* @deprecated wrapper for doRedirect
*/
- function showArticle( $text, $subtitle , $sectionanchor = '', $me2, $now, $summary, $oldid ) {
+ public function showArticle( $text, $subtitle , $sectionanchor = '', $me2, $now, $summary, $oldid ) {
+ wfDeprecated( __METHOD__ );
$this->doRedirect( $this->isRedirect( $text ), $sectionanchor );
}
@@ -1579,13 +1698,13 @@ class Article {
* Output a redirect back to the article.
* This is typically used after an edit.
*
- * @param boolean $noRedir Add redirect=no
- * @param string $sectionAnchor section to redirect to, including "#"
- * @param string $extraQuery, extra query params
+ * @param $noRedir Boolean: add redirect=no
+ * @param $sectionAnchor String: section to redirect to, including "#"
+ * @param $extraQuery String: extra query params
*/
- function doRedirect( $noRedir = false, $sectionAnchor = '', $extraQuery = '' ) {
+ public function doRedirect( $noRedir = false, $sectionAnchor = '', $extraQuery = '' ) {
global $wgOut;
- if ( $noRedir ) {
+ if( $noRedir ) {
$query = 'redirect=no';
if( $extraQuery )
$query .= "&$query";
@@ -1598,77 +1717,45 @@ class Article {
/**
* Mark this particular edit/page as patrolled
*/
- function markpatrolled() {
+ public function markpatrolled() {
global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUseNPPatrol, $wgUser;
$wgOut->setRobotPolicy( 'noindex,nofollow' );
- # Check patrol config options
-
- if ( !($wgUseNPPatrol || $wgUseRCPatrol)) {
- $wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
- return;
- }
-
# If we haven't been given an rc_id value, we can't do anything
$rcid = (int) $wgRequest->getVal('rcid');
- $rc = $rcid ? RecentChange::newFromId($rcid) : null;
- if ( is_null ( $rc ) )
- {
+ $rc = RecentChange::newFromId($rcid);
+ if( is_null($rc) ) {
$wgOut->showErrorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
return;
}
- if ( !$wgUseRCPatrol && $rc->getAttribute( 'rc_type' ) != RC_NEW) {
- // Only new pages can be patrolled if the general patrolling is off....???
- // @fixme -- is this necessary? Shouldn't we only bother controlling the
- // front end here?
- $wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
- return;
- }
+ #It would be nice to see where the user had actually come from, but for now just guess
+ $returnto = $rc->getAttribute( 'rc_type' ) == RC_NEW ? 'Newpages' : 'Recentchanges';
+ $return = Title::makeTitle( NS_SPECIAL, $returnto );
- # Check permissions
- $permission_errors = $this->mTitle->getUserPermissionsErrors( 'patrol', $wgUser );
+ $dbw = wfGetDB( DB_MASTER );
+ $errors = $rc->doMarkPatrolled();
- if (count($permission_errors)>0)
- {
- $wgOut->showPermissionsErrorPage( $permission_errors );
+ if( in_array(array('rcpatroldisabled'), $errors) ) {
+ $wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
return;
}
-
- # Handle the 'MarkPatrolled' hook
- if( !wfRunHooks( 'MarkPatrolled', array( $rcid, &$wgUser, false ) ) ) {
+
+ if( in_array(array('hookaborted'), $errors) ) {
+ // The hook itself has handled any output
return;
}
-
- #It would be nice to see where the user had actually come from, but for now just guess
- $returnto = $rc->getAttribute( 'rc_type' ) == RC_NEW ? 'Newpages' : 'Recentchanges';
- $return = Title::makeTitle( NS_SPECIAL, $returnto );
-
- # If it's left up to us, check that the user is allowed to patrol this edit
- # If the user has the "autopatrol" right, then we'll assume there are no
- # other conditions stopping them doing so
- if( !$wgUser->isAllowed( 'autopatrol' ) ) {
- $rc = RecentChange::newFromId( $rcid );
- # Graceful error handling, as we've done before here...
- # (If the recent change doesn't exist, then it doesn't matter whether
- # the user is allowed to patrol it or not; nothing is going to happen
- if( is_object( $rc ) && $wgUser->getName() == $rc->getAttribute( 'rc_user_text' ) ) {
- # The user made this edit, and can't patrol it
- # Tell them so, and then back off
- $wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) );
- $wgOut->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
- $wgOut->returnToMain( false, $return );
- return;
- }
+
+ if( in_array(array('markedaspatrollederror-noautopatrol'), $errors) ) {
+ $wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) );
+ $wgOut->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
+ $wgOut->returnToMain( false, $return );
+ return;
}
- # Check that the revision isn't patrolled already
- # Prevents duplicate log entries
- if( !$rc->getAttribute( 'rc_patrolled' ) ) {
- # Mark the edit as patrolled
- RecentChange::markPatrolled( $rcid );
- PatrolLog::record( $rcid );
- wfRunHooks( 'MarkPatrolledComplete', array( &$rcid, &$wgUser, false ) );
+ if( !empty($errors) ) {
+ $wgOut->showPermissionsErrorPage( $errors );
+ return;
}
# Inform the user
@@ -1681,26 +1768,21 @@ class Article {
* User-interface handler for the "watch" action
*/
- function watch() {
-
+ public function watch() {
global $wgUser, $wgOut;
-
- if ( $wgUser->isAnon() ) {
+ if( $wgUser->isAnon() ) {
$wgOut->showErrorPage( 'watchnologin', 'watchnologintext' );
return;
}
- if ( wfReadOnly() ) {
+ if( wfReadOnly() ) {
$wgOut->readOnlyPage();
return;
}
-
if( $this->doWatch() ) {
$wgOut->setPagetitle( wfMsg( 'addedwatch' ) );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
-
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->addWikiMsg( 'addedwatchtext', $this->mTitle->getPrefixedText() );
}
-
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
}
@@ -1708,44 +1790,36 @@ class Article {
* Add this page to $wgUser's watchlist
* @return bool true on successful watch operation
*/
- function doWatch() {
+ public function doWatch() {
global $wgUser;
if( $wgUser->isAnon() ) {
return false;
}
-
- if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) {
+ if( wfRunHooks('WatchArticle', array(&$wgUser, &$this)) ) {
$wgUser->addWatch( $this->mTitle );
-
return wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this));
}
-
return false;
}
/**
* User interface handler for the "unwatch" action.
*/
- function unwatch() {
-
+ public function unwatch() {
global $wgUser, $wgOut;
-
- if ( $wgUser->isAnon() ) {
+ if( $wgUser->isAnon() ) {
$wgOut->showErrorPage( 'watchnologin', 'watchnologintext' );
return;
}
- if ( wfReadOnly() ) {
+ if( wfReadOnly() ) {
$wgOut->readOnlyPage();
return;
}
-
if( $this->doUnwatch() ) {
$wgOut->setPagetitle( wfMsg( 'removedwatch' ) );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
-
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->addWikiMsg( 'removedwatchtext', $this->mTitle->getPrefixedText() );
}
-
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
}
@@ -1753,25 +1827,22 @@ class Article {
* Stop watching a page
* @return bool true on successful unwatch
*/
- function doUnwatch() {
+ public function doUnwatch() {
global $wgUser;
if( $wgUser->isAnon() ) {
return false;
}
-
- if (wfRunHooks('UnwatchArticle', array(&$wgUser, &$this))) {
+ if( wfRunHooks('UnwatchArticle', array(&$wgUser, &$this)) ) {
$wgUser->removeWatch( $this->mTitle );
-
return wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this));
}
-
return false;
}
/**
* action=protect handler
*/
- function protect() {
+ public function protect() {
$form = new ProtectionForm( $this );
$form->execute();
}
@@ -1779,26 +1850,28 @@ class Article {
/**
* action=unprotect handler (alias)
*/
- function unprotect() {
+ public function unprotect() {
$this->protect();
}
/**
* Update the article's restriction field, and leave a log entry.
*
- * @param array $limit set of restriction keys
- * @param string $reason
+ * @param $limit Array: set of restriction keys
+ * @param $reason String
+ * @param &$cascade Integer. Set to false if cascading protection isn't allowed.
+ * @param $expiry Array: per restriction type expiration
* @return bool true on success
*/
- function updateRestrictions( $limit = array(), $reason = '', $cascade = 0, $expiry = null ) {
+ public function updateRestrictions( $limit = array(), $reason = '', &$cascade = 0, $expiry = array() ) {
global $wgUser, $wgRestrictionTypes, $wgContLang;
$id = $this->mTitle->getArticleID();
- if( array() != $this->mTitle->getUserPermissionsErrors( 'protect', $wgUser ) || wfReadOnly() || $id == 0 ) {
+ if( $id <= 0 || wfReadOnly() || !$this->mTitle->userCan('protect') ) {
return false;
}
- if (!$cascade) {
+ if( !$cascade ) {
$cascade = false;
}
@@ -1808,34 +1881,39 @@ class Article {
# FIXME: Same limitations as described in ProtectionForm.php (line 37);
# we expect a single selection, but the schema allows otherwise.
$current = array();
- foreach( $wgRestrictionTypes as $action )
- $current[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
+ $updated = Article::flattenRestrictions( $limit );
+ $changed = false;
+ foreach( $wgRestrictionTypes as $action ) {
+ if( isset( $expiry[$action] ) ) {
+ # Get current restrictions on $action
+ $aLimits = $this->mTitle->getRestrictions( $action );
+ $current[$action] = implode( '', $aLimits );
+ # Are any actual restrictions being dealt with here?
+ $aRChanged = count($aLimits) || !empty($limit[$action]);
+ # If something changed, we need to log it. Checking $aRChanged
+ # assures that "unprotecting" a page that is not protected does
+ # not log just because the expiry was "changed".
+ if( $aRChanged && $this->mTitle->mRestrictionsExpiry[$action] != $expiry[$action] ) {
+ $changed = true;
+ }
+ }
+ }
$current = Article::flattenRestrictions( $current );
- $updated = Article::flattenRestrictions( $limit );
- $changed = ( $current != $updated );
+ $changed = ($changed || $current != $updated );
$changed = $changed || ($updated && $this->mTitle->areRestrictionsCascading() != $cascade);
- $changed = $changed || ($updated && $this->mTitle->mRestrictionsExpiry != $expiry);
$protect = ( $updated != '' );
# If nothing's changed, do nothing
if( $changed ) {
- global $wgGroupPermissions;
if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) {
$dbw = wfGetDB( DB_MASTER );
-
- $encodedExpiry = Block::encodeExpiry($expiry, $dbw );
-
- $expiry_description = '';
- if ( $encodedExpiry != 'infinity' ) {
- $expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry, false, false ) ).')';
- }
-
+
# Prepare a null revision to be added to the history
$modified = $current != '' && $protect;
- if ( $protect ) {
+ if( $protect ) {
$comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle';
} else {
$comment_type = 'unprotectedarticle';
@@ -1844,35 +1922,51 @@ class Article {
# Only restrictions with the 'protect' right can cascade...
# Otherwise, people who cannot normally protect can "protect" pages via transclusion
- foreach( $limit as $action => $restriction ) {
- # FIXME: can $restriction be an array or what? (same as fixme above)
- if( $restriction != 'protect' && $restriction != 'sysop' ) {
- $cascade = false;
- break;
- }
- }
-
- $cascade_description = '';
- if ($cascade) {
- $cascade_description = ' ['.wfMsg('protect-summary-cascade').']';
+ $editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' );
+ # The schema allows multiple restrictions
+ if(!in_array('protect', $editrestriction) && !in_array('sysop', $editrestriction))
+ $cascade = false;
+ $cascade_description = '';
+ if( $cascade ) {
+ $cascade_description = ' ['.wfMsgForContent('protect-summary-cascade').']';
}
if( $reason )
$comment .= ": $reason";
- if( $protect )
- $comment .= " [$updated]";
- if ( $expiry_description && $protect )
- $comment .= "$expiry_description";
- if ( $cascade )
- $comment .= "$cascade_description";
+ $editComment = $comment;
+ $encodedExpiry = array();
+ $protect_description = '';
+ foreach( $limit as $action => $restrictions ) {
+ $encodedExpiry[$action] = Block::encodeExpiry($expiry[$action], $dbw );
+ if( $restrictions != '' ) {
+ $protect_description .= "[$action=$restrictions] (";
+ if( $encodedExpiry[$action] != 'infinity' ) {
+ $protect_description .= wfMsgForContent( 'protect-expiring',
+ $wgContLang->timeanddate( $expiry[$action], false, false ) ,
+ $wgContLang->date( $expiry[$action], false, false ) ,
+ $wgContLang->time( $expiry[$action], false, false ) );
+ } else {
+ $protect_description .= wfMsgForContent( 'protect-expiry-indefinite' );
+ }
+ $protect_description .= ') ';
+ }
+ }
+ $protect_description = trim($protect_description);
+
+ if( $protect_description && $protect )
+ $editComment .= " ($protect_description)";
+ if( $cascade )
+ $editComment .= "$cascade_description";
# Update restrictions table
foreach( $limit as $action => $restrictions ) {
- if ($restrictions != '' ) {
+ if($restrictions != '' ) {
$dbw->replace( 'page_restrictions', array(array('pr_page', 'pr_type')),
- array( 'pr_page' => $id, 'pr_type' => $action
- , 'pr_level' => $restrictions, 'pr_cascade' => $cascade ? 1 : 0
- , 'pr_expiry' => $encodedExpiry ), __METHOD__ );
+ array( 'pr_page' => $id,
+ 'pr_type' => $action,
+ 'pr_level' => $restrictions,
+ 'pr_cascade' => ($cascade && $action == 'edit') ? 1 : 0,
+ 'pr_expiry' => $encodedExpiry[$action] ), __METHOD__ );
} else {
$dbw->delete( 'page_restrictions', array( 'pr_page' => $id,
'pr_type' => $action ), __METHOD__ );
@@ -1880,9 +1974,10 @@ class Article {
}
# Insert a null revision
- $nullRevision = Revision::newNullRevision( $dbw, $id, $comment, true );
+ $nullRevision = Revision::newNullRevision( $dbw, $id, $editComment, true );
$nullRevId = $nullRevision->insertOn( $dbw );
+ $latest = $this->getLatest();
# Update page record
$dbw->update( 'page',
array( /* SET */
@@ -1893,15 +1988,15 @@ class Article {
'page_id' => $id
), 'Article::protect'
);
-
- wfRunHooks( 'NewRevisionFromEditComplete', array($this, $nullRevision, false) );
+
+ wfRunHooks( 'NewRevisionFromEditComplete', array($this, $nullRevision, $latest, $wgUser) );
wfRunHooks( 'ArticleProtectComplete', array( &$this, &$wgUser, $limit, $reason ) );
# Update the protection log
$log = new LogPage( 'protect' );
if( $protect ) {
- $log->addEntry( $modified ? 'modify' : 'protect', $this->mTitle,
- trim( $reason . " [$updated]$cascade_description$expiry_description" ) );
+ $params = array($protect_description,$cascade ? 'cascade' : '');
+ $log->addEntry( $modified ? 'modify' : 'protect', $this->mTitle, trim( $reason), $params );
} else {
$log->addEntry( 'unprotect', $this->mTitle, $reason );
}
@@ -1915,11 +2010,10 @@ class Article {
/**
* Take an array of page restrictions and flatten it to a string
* suitable for insertion into the page_restrictions field.
- * @param array $limit
- * @return string
- * @private
+ * @param $limit Array
+ * @return String
*/
- function flattenRestrictions( $limit ) {
+ protected static function flattenRestrictions( $limit ) {
if( !is_array( $limit ) ) {
throw new MWException( 'Article::flattenRestrictions given non-array restriction set' );
}
@@ -1935,26 +2029,24 @@ class Article {
/**
* Auto-generates a deletion reason
- * @param bool &$hasHistory Whether the page has a history
+ * @param &$hasHistory Boolean: whether the page has a history
*/
- public function generateReason(&$hasHistory)
- {
+ public function generateReason( &$hasHistory ) {
global $wgContLang;
- $dbw = wfGetDB(DB_MASTER);
+ $dbw = wfGetDB( DB_MASTER );
// Get the last revision
- $rev = Revision::newFromTitle($this->mTitle);
- if(is_null($rev))
+ $rev = Revision::newFromTitle( $this->mTitle );
+ if( is_null( $rev ) )
return false;
+
// Get the article's contents
$contents = $rev->getText();
$blank = false;
// If the page is blank, use the text from the previous revision,
// which can only be blank if there's a move/import/protect dummy revision involved
- if($contents == '')
- {
+ if( $contents == '' ) {
$prev = $rev->getPrevious();
- if($prev)
- {
+ if( $prev ) {
$contents = $prev->getText();
$blank = true;
}
@@ -1963,44 +2055,51 @@ class Article {
// Find out if there was only one contributor
// Only scan the last 20 revisions
$limit = 20;
- $res = $dbw->select('revision', 'rev_user_text', array('rev_page' => $this->getID()), __METHOD__,
- array('LIMIT' => $limit));
- if($res === false)
+ $res = $dbw->select( 'revision', 'rev_user_text',
+ array( 'rev_page' => $this->getID() ), __METHOD__,
+ array( 'LIMIT' => $limit )
+ );
+ if( $res === false )
// This page has no revisions, which is very weird
return false;
- if($res->numRows() > 1)
+ if( $res->numRows() > 1 )
$hasHistory = true;
else
$hasHistory = false;
- $row = $dbw->fetchObject($res);
+ $row = $dbw->fetchObject( $res );
$onlyAuthor = $row->rev_user_text;
// Try to find a second contributor
- while( $row = $dbw->fetchObject($res) ) {
- if($row->rev_user_text != $onlyAuthor) {
+ foreach( $res as $row ) {
+ if( $row->rev_user_text != $onlyAuthor ) {
$onlyAuthor = false;
break;
}
}
- $dbw->freeResult($res);
+ $dbw->freeResult( $res );
// Generate the summary with a '$1' placeholder
- if($blank) {
+ if( $blank ) {
// The current revision is blank and the one before is also
// blank. It's just not our lucky day
- $reason = wfMsgForContent('exbeforeblank', '$1');
+ $reason = wfMsgForContent( 'exbeforeblank', '$1' );
} else {
- if($onlyAuthor)
- $reason = wfMsgForContent('excontentauthor', '$1', $onlyAuthor);
+ if( $onlyAuthor )
+ $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
else
- $reason = wfMsgForContent('excontent', '$1');
+ $reason = wfMsgForContent( 'excontent', '$1' );
+ }
+
+ if( $reason == '-' ) {
+ // Allow these UI messages to be blanked out cleanly
+ return '';
}
// Replace newlines with spaces to prevent uglyness
- $contents = preg_replace("/[\n\r]/", ' ', $contents);
+ $contents = preg_replace( "/[\n\r]/", ' ', $contents );
// Calculate the maximum amount of chars to get
// Max content length = max comment length - length of the comment (excl. $1) - '...'
- $maxLength = 255 - (strlen($reason) - 2) - 3;
- $contents = $wgContLang->truncate($contents, $maxLength, '...');
+ $maxLength = 255 - (strlen( $reason ) - 2) - 3;
+ $contents = $wgContLang->truncate( $contents, $maxLength, '...' );
// Remove possible unfinished links
$contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
// Now replace the '$1' placeholder
@@ -2012,7 +2111,7 @@ class Article {
/*
* UI entry point for page deletion
*/
- function delete() {
+ public function delete() {
global $wgUser, $wgOut, $wgRequest;
$confirm = $wgRequest->wasPosted() &&
@@ -2023,19 +2122,19 @@ class Article {
$reason = $this->DeleteReasonList;
- if ( $reason != 'other' && $this->DeleteReason != '') {
+ if( $reason != 'other' && $this->DeleteReason != '' ) {
// Entry from drop down menu + additional comment
$reason .= ': ' . $this->DeleteReason;
- } elseif ( $reason == 'other' ) {
+ } elseif( $reason == 'other' ) {
$reason = $this->DeleteReason;
}
# Flag to hide all contents of the archived revisions
- $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('suppressrevision');
+ $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed( 'suppressrevision' );
# This code desperately needs to be totally rewritten
# Read-only check...
- if ( wfReadOnly() ) {
+ if( wfReadOnly() ) {
$wgOut->readOnlyPage();
return;
}
@@ -2043,7 +2142,7 @@ class Article {
# Check permissions
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgUser );
- if (count($permission_errors)>0) {
+ if( count( $permission_errors ) > 0 ) {
$wgOut->showPermissionsErrorPage( $permission_errors );
return;
}
@@ -2054,8 +2153,10 @@ class Article {
$dbw = wfGetDB( DB_MASTER );
$conds = $this->mTitle->pageCond();
$latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
- if ( $latest === false ) {
- $wgOut->showFatalError( wfMsg( 'cannotdelete' ) );
+ if( $latest === false ) {
+ $wgOut->showFatalError( wfMsgExt( 'cannotdelete', array( 'parse' ) ) );
+ $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
+ LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() );
return;
}
@@ -2080,12 +2181,12 @@ class Article {
// Generate deletion reason
$hasHistory = false;
- if ( !$reason ) $reason = $this->generateReason($hasHistory);
+ if( !$reason ) $reason = $this->generateReason($hasHistory);
// If the page has a history, insert a warning
if( $hasHistory && !$confirm ) {
- $skin=$wgUser->getSkin();
- $wgOut->addHTML( '<strong>' . wfMsg( 'historywarning' ) . ' ' . $skin->historyLink() . '</strong>' );
+ $skin = $wgUser->getSkin();
+ $wgOut->addHTML( '<strong>' . wfMsgExt( 'historywarning', array( 'parseinline' ) ) . ' ' . $skin->historyLink() . '</strong>' );
if( $bigHistory ) {
global $wgLang, $wgDeleteRevisionsLimit;
$wgOut->wrapWikiMsg( "<div class='error'>\n$1</div>\n",
@@ -2099,7 +2200,7 @@ class Article {
/**
* @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions
*/
- function isBigDeletion() {
+ public function isBigDeletion() {
global $wgDeleteRevisionsLimit;
if( $wgDeleteRevisionsLimit ) {
$revCount = $this->estimateRevisionCount();
@@ -2111,8 +2212,8 @@ class Article {
/**
* @return int approximate revision count
*/
- function estimateRevisionCount() {
- $dbr = wfGetDB();
+ public function estimateRevisionCount() {
+ $dbr = wfGetDB( DB_SLAVE );
// For an exact count...
//return $dbr->selectField( 'revision', 'COUNT(*)',
// array( 'rev_page' => $this->getId() ), __METHOD__ );
@@ -2122,13 +2223,12 @@ class Article {
/**
* Get the last N authors
- * @param int $num Number of revisions to get
- * @param string $revLatest The latest rev_id, selected from the master (optional)
+ * @param $num Integer: number of revisions to get
+ * @param $revLatest String: the latest rev_id, selected from the master (optional)
* @return array Array of authors, duplicates not removed
*/
- function getLastNAuthors( $num, $revLatest = 0 ) {
+ public function getLastNAuthors( $num, $revLatest = 0 ) {
wfProfileIn( __METHOD__ );
-
// First try the slave
// If that doesn't have the latest revision, try the master
$continue = 2;
@@ -2145,12 +2245,12 @@ class Article {
'LIMIT' => $num
) )
);
- if ( !$res ) {
+ if( !$res ) {
wfProfileOut( __METHOD__ );
return array();
}
$row = $db->fetchObject( $res );
- if ( $continue == 2 && $revLatest && $row->rev_id != $revLatest ) {
+ if( $continue == 2 && $revLatest && $row->rev_id != $revLatest ) {
$db = wfGetDB( DB_MASTER );
$continue--;
} else {
@@ -2168,59 +2268,67 @@ class Article {
/**
* Output deletion confirmation dialog
- * @param $reason string Prefilled reason
+ * @param $reason String: prefilled reason
*/
- function confirmDelete( $reason ) {
- global $wgOut, $wgUser, $wgContLang;
- $align = $wgContLang->isRtl() ? 'left' : 'right';
+ public function confirmDelete( $reason ) {
+ global $wgOut, $wgUser;
wfDebug( "Article::confirmDelete\n" );
- $wgOut->setSubtitle( wfMsg( 'delete-backlink', $wgUser->getSkin()->makeKnownLinkObj( $this->mTitle ) ) );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
+ $wgOut->setSubtitle( wfMsgHtml( 'delete-backlink', $wgUser->getSkin()->makeKnownLinkObj( $this->mTitle ) ) );
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->addWikiMsg( 'confirmdeletetext' );
if( $wgUser->isAllowed( 'suppressrevision' ) ) {
- $suppress = "<tr id=\"wpDeleteSuppressRow\" name=\"wpDeleteSuppressRow\"><td></td><td>";
- $suppress .= Xml::checkLabel( wfMsg( 'revdelete-suppress' ), 'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '2' ) );
- $suppress .= "</td></tr>";
+ $suppress = "<tr id=\"wpDeleteSuppressRow\" name=\"wpDeleteSuppressRow\">
+ <td></td>
+ <td class='mw-input'>" .
+ Xml::checkLabel( wfMsg( 'revdelete-suppress' ),
+ 'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '4' ) ) .
+ "</td>
+ </tr>";
} else {
$suppress = '';
}
+ $checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching();
- $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->mTitle->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
+ $form = Xml::openElement( 'form', array( 'method' => 'post',
+ 'action' => $this->mTitle->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
Xml::tags( 'legend', null, wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) ) .
- Xml::openElement( 'table' ) .
+ Xml::openElement( 'table', array( 'id' => 'mw-deleteconfirm-table' ) ) .
"<tr id=\"wpDeleteReasonListRow\">
- <td align='$align'>" .
+ <td class='mw-label'>" .
Xml::label( wfMsg( 'deletecomment' ), 'wpDeleteReasonList' ) .
"</td>
- <td>" .
+ <td class='mw-input'>" .
Xml::listDropDown( 'wpDeleteReasonList',
wfMsgForContent( 'deletereason-dropdown' ),
wfMsgForContent( 'deletereasonotherlist' ), '', 'wpReasonDropDown', 1 ) .
"</td>
</tr>
<tr id=\"wpDeleteReasonRow\">
- <td align='$align'>" .
+ <td class='mw-label'>" .
Xml::label( wfMsg( 'deleteotherreason' ), 'wpReason' ) .
"</td>
- <td>" .
- Xml::input( 'wpReason', 60, $reason, array( 'type' => 'text', 'maxlength' => '255', 'tabindex' => '2', 'id' => 'wpReason' ) ) .
+ <td class='mw-input'>" .
+ Xml::input( 'wpReason', 60, $reason, array( 'type' => 'text', 'maxlength' => '255',
+ 'tabindex' => '2', 'id' => 'wpReason' ) ) .
"</td>
</tr>
<tr>
<td></td>
- <td>" .
- Xml::checkLabel( wfMsg( 'watchthis' ), 'wpWatch', 'wpWatch', $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching(), array( 'tabindex' => '3' ) ) .
+ <td class='mw-input'>" .
+ Xml::checkLabel( wfMsg( 'watchthis' ),
+ 'wpWatch', 'wpWatch', $checkWatch, array( 'tabindex' => '3' ) ) .
"</td>
</tr>
$suppress
<tr>
<td></td>
- <td>" .
- Xml::submitButton( wfMsg( 'deletepage' ), array( 'name' => 'wpConfirmB', 'id' => 'wpConfirmB', 'tabindex' => '4' ) ) .
+ <td class='mw-submit'>" .
+ Xml::submitButton( wfMsg( 'deletepage' ),
+ array( 'name' => 'wpConfirmB', 'id' => 'wpConfirmB', 'tabindex' => '5' ) ) .
"</td>
</tr>" .
Xml::closeElement( 'table' ) .
@@ -2228,43 +2336,30 @@ class Article {
Xml::hidden( 'wpEditToken', $wgUser->editToken() ) .
Xml::closeElement( 'form' );
- if ( $wgUser->isAllowed( 'editinterface' ) ) {
+ if( $wgUser->isAllowed( 'editinterface' ) ) {
$skin = $wgUser->getSkin();
$link = $skin->makeLink ( 'MediaWiki:Deletereason-dropdown', wfMsgHtml( 'delete-edit-reasonlist' ) );
$form .= '<p class="mw-delete-editreasons">' . $link . '</p>';
}
$wgOut->addHTML( $form );
- $this->showLogExtract( $wgOut );
- }
-
-
- /**
- * Show relevant lines from the deletion log
- */
- function showLogExtract( $out ) {
- $out->addHtml( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
- LogEventsList::showLogExtract( $out, 'delete', $this->mTitle->getPrefixedText() );
+ LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() );
}
-
/**
* Perform a deletion and output success or failure messages
*/
- function doDelete( $reason, $suppress = false ) {
+ public function doDelete( $reason, $suppress = false ) {
global $wgOut, $wgUser;
- wfDebug( __METHOD__."\n" );
-
- $id = $this->getId();
-
- $error = '';
+ $id = $this->mTitle->getArticleID( GAID_FOR_UPDATE );
- if (wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason, &$error))) {
- if ( $this->doDeleteArticle( $reason, $suppress ) ) {
+ $error = '';
+ if( wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason, &$error)) ) {
+ if( $this->doDeleteArticle( $reason, $suppress, $id ) ) {
$deleted = $this->mTitle->getPrefixedText();
$wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
$loglink = '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]';
@@ -2272,10 +2367,13 @@ class Article {
$wgOut->returnToMain( false );
wfRunHooks('ArticleDeleteComplete', array(&$this, &$wgUser, $reason, $id));
} else {
- if ($error = '')
- $wgOut->showFatalError( wfMsg( 'cannotdelete' ) );
- else
+ if( $error == '' ) {
+ $wgOut->showFatalError( wfMsgExt( 'cannotdelete', array( 'parse' ) ) );
+ $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
+ LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() );
+ } else {
$wgOut->showFatalError( $error );
+ }
}
}
}
@@ -2285,7 +2383,7 @@ class Article {
* Deletes the article with database consistency, writes logs, purges caches
* Returns success
*/
- function doDeleteArticle( $reason, $suppress = false ) {
+ public function doDeleteArticle( $reason, $suppress = false, $id = 0 ) {
global $wgUseSquid, $wgDeferredUpdateList;
global $wgUseTrackbacks;
@@ -2294,9 +2392,9 @@ class Article {
$dbw = wfGetDB( DB_MASTER );
$ns = $this->mTitle->getNamespace();
$t = $this->mTitle->getDBkey();
- $id = $this->mTitle->getArticleID();
+ $id = $id ? $id : $this->mTitle->getArticleID( GAID_FOR_UPDATE );
- if ( $t == '' || $id == 0 ) {
+ if( $t == '' || $id == 0 ) {
return false;
}
@@ -2304,7 +2402,7 @@ class Article {
array_push( $wgDeferredUpdateList, $u );
// Bitfields to further suppress the content
- if ( $suppress ) {
+ if( $suppress ) {
$bitfield = 0;
// This should be 15...
$bitfield |= Revision::DELETED_TEXT;
@@ -2351,15 +2449,6 @@ class Article {
# Delete restrictions for it
$dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
- # Fix category table counts
- $cats = array();
- $res = $dbw->select( 'categorylinks', 'cl_to',
- array( 'cl_from' => $id ), __METHOD__ );
- foreach( $res as $row ) {
- $cats []= $row->cl_to;
- }
- $this->updateCategoryCounts( array(), $cats );
-
# Now that it's safely backed up, delete it
$dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__);
$ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy
@@ -2367,12 +2456,20 @@ class Article {
$dbw->rollback();
return false;
}
+
+ # Fix category table counts
+ $cats = array();
+ $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
+ foreach( $res as $row ) {
+ $cats []= $row->cl_to;
+ }
+ $this->updateCategoryCounts( array(), $cats );
# If using cascading deletes, we can skip some explicit deletes
- if ( !$dbw->cascadingDeletes() ) {
+ if( !$dbw->cascadingDeletes() ) {
$dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
- if ($wgUseTrackbacks)
+ if($wgUseTrackbacks)
$dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ );
# Delete outgoing links
@@ -2386,14 +2483,17 @@ class Article {
}
# If using cleanup triggers, we can skip some manual deletes
- if ( !$dbw->cleanupTriggers() ) {
-
+ if( !$dbw->cleanupTriggers() ) {
# Clean up recentchanges entries...
$dbw->delete( 'recentchanges',
- array( 'rc_namespace' => $ns, 'rc_title' => $t, 'rc_type != '.RC_LOG ),
+ array( 'rc_type != '.RC_LOG,
+ 'rc_namespace' => $this->mTitle->getNamespace(),
+ 'rc_title' => $this->mTitle->getDBKey() ),
+ __METHOD__ );
+ $dbw->delete( 'recentchanges',
+ array( 'rc_type != '.RC_LOG, 'rc_cur_id' => $id ),
__METHOD__ );
}
- $dbw->commit();
# Clear caches
Article::onArticleDelete( $this->mTitle );
@@ -2409,6 +2509,8 @@ class Article {
# Make sure logging got through
$log->addEntry( 'delete', $this->mTitle, $reason, array() );
+ $dbw->commit();
+
return true;
}
@@ -2419,12 +2521,12 @@ class Article {
* performs permissions checks on $wgUser, then calls commitRollback()
* to do the dirty work
*
- * @param string $fromP - Name of the user whose edits to rollback.
- * @param string $summary - Custom summary. Set to default summary if empty.
- * @param string $token - Rollback token.
- * @param bool $bot - If true, mark all reverted edits as bot.
+ * @param $fromP String: Name of the user whose edits to rollback.
+ * @param $summary String: Custom summary. Set to default summary if empty.
+ * @param $token String: Rollback token.
+ * @param $bot Boolean: If true, mark all reverted edits as bot.
*
- * @param array $resultDetails contains result-specific array of additional values
+ * @param $resultDetails Array: contains result-specific array of additional values
* 'alreadyrolled' : 'current' (rev)
* success : 'summary' (str), 'current' (rev), 'target' (rev)
*
@@ -2438,16 +2540,18 @@ class Article {
$resultDetails = null;
# Check permissions
- $errors = array_merge( $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser ),
- $this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser ) );
+ $editErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser );
+ $rollbackErrors = $this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser );
+ $errors = array_merge( $editErrors, wfArrayDiff2( $rollbackErrors, $editErrors ) );
+
if( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) )
$errors[] = array( 'sessionfailure' );
- if ( $wgUser->pingLimiter('rollback') || $wgUser->pingLimiter() ) {
+ if( $wgUser->pingLimiter( 'rollback' ) || $wgUser->pingLimiter() ) {
$errors[] = array( 'actionthrottledtext' );
}
# If there were errors, bail out now
- if(!empty($errors))
+ if( !empty( $errors ) )
return $errors;
return $this->commitRollback($fromP, $summary, $bot, $resultDetails);
@@ -2493,7 +2597,7 @@ class Article {
$s = $dbw->selectRow( 'revision',
array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
array( 'rev_page' => $current->getPage(),
- "rev_user <> {$user} OR rev_user_text <> {$user_text}"
+ "rev_user != {$user} OR rev_user_text != {$user_text}"
), __METHOD__,
array( 'USE INDEX' => 'page_timestamp',
'ORDER BY' => 'rev_timestamp DESC' )
@@ -2507,16 +2611,16 @@ class Article {
}
$set = array();
- if ( $bot && $wgUser->isAllowed('markbotedits') ) {
+ if( $bot && $wgUser->isAllowed('markbotedits') ) {
# Mark all reverted edits as bot
$set['rc_bot'] = 1;
}
- if ( $wgUseRCPatrol ) {
+ if( $wgUseRCPatrol ) {
# Mark all reverted edits as patrolled
$set['rc_patrolled'] = 1;
}
- if ( $set ) {
+ if( $set ) {
$dbw->update( 'recentchanges', $set,
array( /* WHERE */
'rc_cur_id' => $current->getPage(),
@@ -2531,31 +2635,38 @@ class Article {
if( empty( $summary ) ){
$summary = wfMsgForContent( 'revertpage' );
}
-
+
# Allow the custom summary to use the same args as the default message
$args = array(
$target->getUserText(), $from, $s->rev_id,
$wgLang->timeanddate(wfTimestamp(TS_MW, $s->rev_timestamp), true),
$current->getId(), $wgLang->timeanddate($current->getTimestamp())
);
- $summary = wfMsgReplaceArgs( $summary, $args );
+ $summary = wfMsgReplaceArgs( $summary, $args );
# Save
$flags = EDIT_UPDATE;
- if ($wgUser->isAllowed('minoredit'))
+ if( $wgUser->isAllowed('minoredit') )
$flags |= EDIT_MINOR;
if( $bot && ($wgUser->isAllowed('markbotedits') || $wgUser->isAllowed('bot')) )
$flags |= EDIT_FORCE_BOT;
- $this->doEdit( $target->getText(), $summary, $flags, $target->getId() );
+ # Actually store the edit
+ $status = $this->doEdit( $target->getText(), $summary, $flags, $target->getId() );
+ if( !empty( $status->value['revision'] ) ) {
+ $revId = $status->value['revision']->getId();
+ } else {
+ $revId = false;
+ }
- wfRunHooks( 'ArticleRollbackComplete', array( $this, $wgUser, $target ) );
+ wfRunHooks( 'ArticleRollbackComplete', array( $this, $wgUser, $target, $current ) );
$resultDetails = array(
'summary' => $summary,
'current' => $current,
'target' => $target,
+ 'newid' => $revId
);
return array();
}
@@ -2563,7 +2674,7 @@ class Article {
/**
* User interface for rollback operations
*/
- function rollback() {
+ public function rollback() {
global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
$details = null;
@@ -2575,15 +2686,11 @@ class Article {
$details
);
- if( in_array( array( 'blocked' ), $result ) ) {
- $wgOut->blockedPage();
- return;
- }
if( in_array( array( 'actionthrottledtext' ), $result ) ) {
$wgOut->rateLimited();
return;
}
- if( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ){
+ if( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ) {
$wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
$errArray = $result[0];
$errMsg = array_shift( $errArray );
@@ -2591,7 +2698,8 @@ class Article {
if( isset( $details['current'] ) ){
$current = $details['current'];
if( $current->getComment() != '' ) {
- $wgOut->addWikiMsgArray( 'editcomment', array( $wgUser->getSkin()->formatComment( $current->getComment() ) ), array( 'replaceafter' ) );
+ $wgOut->addWikiMsgArray( 'editcomment', array(
+ $wgUser->getSkin()->formatComment( $current->getComment() ) ), array( 'replaceafter' ) );
}
}
return;
@@ -2599,7 +2707,7 @@ class Article {
# Display permissions errors before read-only message -- there's no
# point in misleading the user into thinking the inability to rollback
# is only temporary.
- if( !empty($result) && $result !== array( array('readonlytext') ) ) {
+ if( !empty( $result ) && $result !== array( array( 'readonlytext' ) ) ) {
# array_diff is completely broken for arrays of arrays, sigh. Re-
# move any 'readonlytext' error manually.
$out = array();
@@ -2611,24 +2719,25 @@ class Article {
$wgOut->showPermissionsErrorPage( $out );
return;
}
- if( $result == array( array('readonlytext') ) ) {
+ if( $result == array( array( 'readonlytext' ) ) ) {
$wgOut->readOnlyPage();
return;
}
$current = $details['current'];
$target = $details['target'];
+ $newId = $details['newid'];
$wgOut->setPageTitle( wfMsg( 'actioncomplete' ) );
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() )
. $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() );
$new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() )
. $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() );
- $wgOut->addHtml( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
+ $wgOut->addHTML( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
$wgOut->returnToMain( false, $this->mTitle );
-
- if( !$wgRequest->getBool( 'hidediff', false ) ) {
- $de = new DifferenceEngine( $this->mTitle, $current->getId(), 'next', false, true );
+
+ if( !$wgRequest->getBool( 'hidediff', false ) && !$wgUser->getBoolOption( 'norollbackdiff', false ) ) {
+ $de = new DifferenceEngine( $this->mTitle, $current->getId(), $newId, false, true );
$de->showDiff( '', '' );
}
}
@@ -2636,21 +2745,15 @@ class Article {
/**
* Do standard deferred updates after page view
- * @private
*/
- function viewUpdates() {
- global $wgDeferredUpdateList, $wgUser;
-
- if ( 0 != $this->getID() ) {
- # Don't update page view counters on views from bot users (bug 14044)
- global $wgDisableCounters;
- if( !$wgDisableCounters && !$wgUser->isAllowed( 'bot' ) ) {
- Article::incViewCount( $this->getID() );
- $u = new SiteStatsUpdate( 1, 0, 0 );
- array_push( $wgDeferredUpdateList, $u );
- }
+ public function viewUpdates() {
+ global $wgDeferredUpdateList, $wgDisableCounters, $wgUser;
+ # Don't update page view counters on views from bot users (bug 14044)
+ if( !$wgDisableCounters && !$wgUser->isAllowed('bot') && $this->getID() ) {
+ Article::incViewCount( $this->getID() );
+ $u = new SiteStatsUpdate( 1, 0, 0 );
+ array_push( $wgDeferredUpdateList, $u );
}
-
# Update newtalk / watchlist notification status
$wgUser->clearNotification( $this->mTitle );
}
@@ -2659,8 +2762,8 @@ class Article {
* Prepare text which is about to be saved.
* Returns a stdclass with source, pst and output members
*/
- function prepareTextForEdit( $text, $revid=null ) {
- if ( $this->mPreparedEdit && $this->mPreparedEdit->newText == $text && $this->mPreparedEdit->revid == $revid) {
+ public function prepareTextForEdit( $text, $revid=null ) {
+ if( $this->mPreparedEdit && $this->mPreparedEdit->newText == $text && $this->mPreparedEdit->revid == $revid) {
// Already prepared
return $this->mPreparedEdit;
}
@@ -2681,6 +2784,7 @@ class Article {
/**
* Do standard deferred updates after page edit.
* Update links tables, site stats, search index and message cache.
+ * Purges pages that include this page if the text was changed here.
* Every 100th edit, prune the recent changes table.
*
* @private
@@ -2691,14 +2795,14 @@ class Article {
* @param $newid rev_id value of the new revision
* @param $changed Whether or not the content actually changed
*/
- function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange, $newid, $changed = true ) {
+ public function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange, $newid, $changed = true ) {
global $wgDeferredUpdateList, $wgMessageCache, $wgUser, $wgParser, $wgEnableParserCache;
wfProfileIn( __METHOD__ );
# Parse the text
# Be careful not to double-PST: $text is usually already PST-ed once
- if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
+ if( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
$editInfo = $this->prepareTextForEdit( $text, $newid );
} else {
@@ -2707,17 +2811,20 @@ class Article {
}
# Save it to the parser cache
- if ( $wgEnableParserCache ) {
+ if( $wgEnableParserCache ) {
$parserCache = ParserCache::singleton();
$parserCache->save( $editInfo->output, $this, $wgUser );
}
# Update the links tables
- $u = new LinksUpdate( $this->mTitle, $editInfo->output );
+ $u = new LinksUpdate( $this->mTitle, $editInfo->output, false );
+ $u->setRecursiveTouch( $changed ); // refresh/invalidate including pages too
$u->doUpdate();
+
+ wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $changed ) );
if( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
- if ( 0 == mt_rand( 0, 99 ) ) {
+ if( 0 == mt_rand( 0, 99 ) ) {
// Flush old entries from the `recentchanges` table; we do this on
// random requests so as to avoid an increase in writes for no good reason
global $wgRCMaxAge;
@@ -2733,7 +2840,7 @@ class Article {
$title = $this->mTitle->getPrefixedDBkey();
$shortTitle = $this->mTitle->getDBkey();
- if ( 0 == $id ) {
+ if( 0 == $id ) {
wfProfileOut( __METHOD__ );
return;
}
@@ -2748,21 +2855,23 @@ class Article {
# load of user talk pages and piss people off, nor if it's a minor edit
# by a properly-flagged bot.
if( $this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getTitleKey() && $changed
- && !($minoredit && $wgUser->isAllowed('nominornewtalk') ) ) {
- if (wfRunHooks('ArticleEditUpdateNewTalk', array(&$this)) ) {
- $other = User::newFromName( $shortTitle );
- if( is_null( $other ) && User::isIP( $shortTitle ) ) {
+ && !( $minoredit && $wgUser->isAllowed( 'nominornewtalk' ) ) ) {
+ if( wfRunHooks('ArticleEditUpdateNewTalk', array( &$this ) ) ) {
+ $other = User::newFromName( $shortTitle, false );
+ if( !$other ) {
+ wfDebug( __METHOD__.": invalid username\n" );
+ } elseif( User::isIP( $shortTitle ) ) {
// An anonymous user
- $other = new User();
- $other->setName( $shortTitle );
- }
- if( $other ) {
$other->setNewtalk( true );
+ } elseif( $other->isLoggedIn() ) {
+ $other->setNewtalk( true );
+ } else {
+ wfDebug( __METHOD__. ": don't need to notify a nonexistent user\n" );
}
}
}
- if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+ if( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
$wgMessageCache->replace( $shortTitle, $text );
}
@@ -2772,13 +2881,13 @@ class Article {
/**
* Perform article updates on a special page creation.
*
- * @param Revision $rev
+ * @param $rev Revision object
*
* @todo This is a shitty interface function. Kill it and replace the
* other shitty functions like editUpdates and such so it's not needed
* anymore.
*/
- function createUpdates( $rev ) {
+ public function createUpdates( $rev ) {
$this->mGoodAdjustment = $this->isCountable( $rev->getText() );
$this->mTotalAdjustment = 1;
$this->editUpdates( $rev->getText(), $rev->getComment(),
@@ -2791,14 +2900,13 @@ class Article {
* Revision as of \<date\>; view current revision
* \<- Previous version | Next Version -\>
*
- * @private
- * @param string $oldid Revision ID of this article revision
+ * @param $oldid String: revision ID of this article revision
*/
- function setOldSubtitle( $oldid=0 ) {
+ public function setOldSubtitle( $oldid = 0 ) {
global $wgLang, $wgOut, $wgUser;
- if ( !wfRunHooks( 'DisplayOldSubtitle', array(&$this, &$oldid) ) ) {
- return;
+ if( !wfRunHooks( 'DisplayOldSubtitle', array( &$this, &$oldid ) ) ) {
+ return;
}
$revision = Revision::newFromId( $oldid );
@@ -2807,34 +2915,34 @@ class Article {
$td = $wgLang->timeanddate( $this->mTimestamp, true );
$sk = $wgUser->getSkin();
$lnk = $current
- ? wfMsg( 'currentrevisionlink' )
- : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'currentrevisionlink' ) );
+ ? wfMsgHtml( 'currentrevisionlink' )
+ : $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'currentrevisionlink' ) );
$curdiff = $current
- ? wfMsg( 'diff' )
- : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=cur&oldid='.$oldid );
+ ? wfMsgHtml( 'diff' )
+ : $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'diff' ), 'diff=cur&oldid='.$oldid );
$prev = $this->mTitle->getPreviousRevisionID( $oldid ) ;
$prevlink = $prev
- ? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'previousrevision' ), 'direction=prev&oldid='.$oldid )
- : wfMsg( 'previousrevision' );
+ ? $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'previousrevision' ), 'direction=prev&oldid='.$oldid )
+ : wfMsgHtml( 'previousrevision' );
$prevdiff = $prev
- ? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=prev&oldid='.$oldid )
- : wfMsg( 'diff' );
+ ? $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'diff' ), 'diff=prev&oldid='.$oldid )
+ : wfMsgHtml( 'diff' );
$nextlink = $current
- ? wfMsg( 'nextrevision' )
- : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'nextrevision' ), 'direction=next&oldid='.$oldid );
+ ? wfMsgHtml( 'nextrevision' )
+ : $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'nextrevision' ), 'direction=next&oldid='.$oldid );
$nextdiff = $current
- ? wfMsg( 'diff' )
- : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid );
+ ? wfMsgHtml( 'diff' )
+ : $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'diff' ), 'diff=next&oldid='.$oldid );
$cdel='';
if( $wgUser->isAllowed( 'deleterevision' ) ) {
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
if( $revision->isCurrent() ) {
// We don't handle top deleted edits too well
- $cdel = wfMsgHtml('rev-delundel');
+ $cdel = wfMsgHtml( 'rev-delundel' );
} else if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) {
// If revision was hidden from sysops
- $cdel = wfMsgHtml('rev-delundel');
+ $cdel = wfMsgHtml( 'rev-delundel' );
} else {
$cdel = $sk->makeKnownLinkObj( $revdel,
wfMsgHtml('rev-delundel'),
@@ -2855,9 +2963,10 @@ class Article {
? 'revision-info-current'
: 'revision-info';
- $r = "\n\t\t\t\t<div id=\"mw-{$infomsg}\">" . wfMsg( $infomsg, $td, $userlinks ) . "</div>\n" .
+ $r = "\n\t\t\t\t<div id=\"mw-{$infomsg}\">" . wfMsgExt( $infomsg, array( 'parseinline', 'replaceafter' ), $td, $userlinks, $revision->getID() ) . "</div>\n" .
- "\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
+ "\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsgExt( 'revision-nav', array( 'escapenoentities', 'parsemag', 'replaceafter' ),
+ $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
$wgOut->setSubtitle( $r );
}
@@ -2865,9 +2974,9 @@ class Article {
* This function is called right before saving the wikitext,
* so we can do things like signatures and links-in-context.
*
- * @param string $text
+ * @param $text String
*/
- function preSaveTransform( $text ) {
+ public function preSaveTransform( $text ) {
global $wgParser, $wgUser;
return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser, ParserOptions::newFromUser( $wgUser ) );
}
@@ -2879,17 +2988,16 @@ class Article {
* output to the client that is necessary for this request.
* (that is, it has sent a cached version of the page)
*/
- function tryFileCache() {
+ protected function tryFileCache() {
static $called = false;
if( $called ) {
wfDebug( "Article::tryFileCache(): called twice!?\n" );
- return;
+ return false;
}
$called = true;
- if($this->isFileCacheable()) {
- $touched = $this->mTouched;
+ if( $this->isFileCacheable() ) {
$cache = new HTMLFileCache( $this->mTitle );
- if($cache->isFileCacheGood( $touched )) {
+ if( $cache->isFileCacheGood( $this->mTouched ) ) {
wfDebug( "Article::tryFileCache(): about to load file\n" );
$cache->loadFromFileCache();
return true;
@@ -2900,46 +3008,22 @@ class Article {
} else {
wfDebug( "Article::tryFileCache(): not cacheable\n" );
}
+ return false;
}
/**
* Check if the page can be cached
* @return bool
*/
- function isFileCacheable() {
- global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest, $wgLang, $wgContLang;
- $action = $wgRequest->getVal( 'action' );
- $oldid = $wgRequest->getVal( 'oldid' );
- $diff = $wgRequest->getVal( 'diff' );
- $redirect = $wgRequest->getVal( 'redirect' );
- $printable = $wgRequest->getVal( 'printable' );
- $page = $wgRequest->getVal( 'page' );
-
- //check for non-standard user language; this covers uselang,
- //and extensions for auto-detecting user language.
- $ulang = $wgLang->getCode();
- $clang = $wgContLang->getCode();
-
- $cacheable = $wgUseFileCache
- && (!$wgShowIPinHeader)
- && ($this->getID() != 0)
- && ($wgUser->isAnon())
- && (!$wgUser->getNewtalk())
- && ($this->mTitle->getNamespace() != NS_SPECIAL )
- && (empty( $action ) || $action == 'view')
- && (!isset($oldid))
- && (!isset($diff))
- && (!isset($redirect))
- && (!isset($printable))
- && !isset($page)
- && (!$this->mRedirectedFrom)
- && ($ulang === $clang);
-
- if ( $cacheable ) {
- //extension may have reason to disable file caching on some pages.
- $cacheable = wfRunHooks( 'IsFileCacheable', array( $this ) );
+ public function isFileCacheable() {
+ $cacheable = false;
+ if( HTMLFileCache::useFileCache() ) {
+ $cacheable = $this->getID() && !$this->mRedirectedFrom;
+ // Extension may have reason to disable file caching on some pages.
+ if( $cacheable ) {
+ $cacheable = wfRunHooks( 'IsFileCacheable', array( &$this ) );
+ }
}
-
return $cacheable;
}
@@ -2947,7 +3031,7 @@ class Article {
* Loads page_touched and returns a value indicating if it should be used
*
*/
- function checkTouched() {
+ public function checkTouched() {
if( !$this->mDataLoaded ) {
$this->loadPageData();
}
@@ -2957,7 +3041,7 @@ class Article {
/**
* Get the page_touched field
*/
- function getTouched() {
+ public function getTouched() {
# Ensure that page data has been loaded
if( !$this->mDataLoaded ) {
$this->loadPageData();
@@ -2968,8 +3052,8 @@ class Article {
/**
* Get the page_latest field
*/
- function getLatest() {
- if ( !$this->mDataLoaded ) {
+ public function getLatest() {
+ if( !$this->mDataLoaded ) {
$this->loadPageData();
}
return $this->mLatest;
@@ -2980,15 +3064,14 @@ class Article {
* The article must already exist; link tables etc
* are not updated, caches are not flushed.
*
- * @param string $text text submitted
- * @param string $comment comment submitted
- * @param bool $minor whereas it's a minor modification
+ * @param $text String: text submitted
+ * @param $comment String: comment submitted
+ * @param $minor Boolean: whereas it's a minor modification
*/
- function quickEdit( $text, $comment = '', $minor = 0 ) {
+ public function quickEdit( $text, $comment = '', $minor = 0 ) {
wfProfileIn( __METHOD__ );
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin();
$revision = new Revision( array(
'page' => $this->getId(),
'text' => $text,
@@ -2997,9 +3080,8 @@ class Article {
) );
$revision->insertOn( $dbw );
$this->updateRevisionOn( $dbw, $revision );
- $dbw->commit();
-
- wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false) );
+
+ wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false, $wgUser) );
wfProfileOut( __METHOD__ );
}
@@ -3007,10 +3089,9 @@ class Article {
/**
* Used to increment the view counter
*
- * @static
- * @param integer $id article id
+ * @param $id Integer: article id
*/
- function incViewCount( $id ) {
+ public static function incViewCount( $id ) {
$id = intval( $id );
global $wgHitcounterUpdateFreq, $wgDBtype;
@@ -3043,14 +3124,14 @@ class Article {
wfProfileIn( 'Article::incViewCount-collect' );
$old_user_abort = ignore_user_abort( true );
- if ($wgDBtype == 'mysql')
+ if($wgDBtype == 'mysql')
$dbw->query("LOCK TABLES $hitcounterTable WRITE");
$tabletype = $wgDBtype == 'mysql' ? "ENGINE=HEAP " : '';
$dbw->query("CREATE TEMPORARY TABLE $acchitsTable $tabletype AS ".
"SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable ".
'GROUP BY hc_id');
$dbw->query("DELETE FROM $hitcounterTable");
- if ($wgDBtype == 'mysql') {
+ if($wgDBtype == 'mysql') {
$dbw->query('UNLOCK TABLES');
$dbw->query("UPDATE $pageTable,$acchitsTable SET page_counter=page_counter + hc_n ".
'WHERE page_id = hc_id');
@@ -3075,13 +3156,13 @@ class Article {
* This is a good place to put code to clear caches, for instance.
*
* This is called on page move and undelete, as well as edit
- * @static
- * @param $title_obj a title object
+ *
+ * @param $title a title object
*/
- static function onArticleCreate($title) {
- # The talk page isn't in the regular link tables, so we need to update manually:
- if ( $title->isTalkPage() ) {
+ public static function onArticleCreate( $title ) {
+ # Update existence markers on article/talk tabs...
+ if( $title->isTalkPage() ) {
$other = $title->getSubjectPage();
} else {
$other = $title->getTalkPage();
@@ -3094,10 +3175,9 @@ class Article {
$title->deleteTitleProtection();
}
- static function onArticleDelete( $title ) {
- global $wgUseFileCache, $wgMessageCache;
-
- // Update existence markers on article/talk tabs...
+ public static function onArticleDelete( $title ) {
+ global $wgMessageCache;
+ # Update existence markers on article/talk tabs...
if( $title->isTalkPage() ) {
$other = $title->getSubjectPage();
} else {
@@ -3110,17 +3190,14 @@ class Article {
$title->purgeSquid();
# File cache
- if ( $wgUseFileCache ) {
- $cm = new HTMLFileCache( $title );
- @unlink( $cm->fileCacheName() );
- }
+ HTMLFileCache::clearFileCache( $title );
# Messages
if( $title->getNamespace() == NS_MEDIAWIKI ) {
$wgMessageCache->replace( $title->getDBkey(), false );
}
# Images
- if( $title->getNamespace() == NS_IMAGE ) {
+ if( $title->getNamespace() == NS_FILE ) {
$update = new HTMLCacheUpdate( $title, 'imagelinks' );
$update->doUpdate();
}
@@ -3134,11 +3211,12 @@ class Article {
/**
* Purge caches on page update etc
*/
- static function onArticleEdit( $title ) {
- global $wgDeferredUpdateList, $wgUseFileCache;
+ public static function onArticleEdit( $title, $transclusions = 'transclusions' ) {
+ global $wgDeferredUpdateList;
// Invalidate caches of articles which include this page
- $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'templatelinks' );
+ if( $transclusions !== 'skiptransclusions' )
+ $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'templatelinks' );
// Invalidate the caches of all pages which redirect here
$wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'redirect' );
@@ -3146,11 +3224,8 @@ class Article {
# Purge squid for this page only
$title->purgeSquid();
- # Clear file cache
- if ( $wgUseFileCache ) {
- $cm = new HTMLFileCache( $title );
- @unlink( $cm->fileCacheName() );
- }
+ # Clear file cache for this page only
+ HTMLFileCache::clearFileCache( $title );
}
/**#@-*/
@@ -3159,7 +3234,7 @@ class Article {
* Overriden by ImagePage class, only present here to avoid a fatal error
* Called for ?action=revert
*/
- public function revert(){
+ public function revert() {
global $wgOut;
$wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
}
@@ -3167,13 +3242,11 @@ class Article {
/**
* Info about this page
* Called for ?action=info when $wgAllowPageInfo is on.
- *
- * @public
*/
- function info() {
+ public function info() {
global $wgLang, $wgOut, $wgAllowPageInfo, $wgUser;
- if ( !$wgAllowPageInfo ) {
+ if( !$wgAllowPageInfo ) {
$wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
return;
}
@@ -3182,21 +3255,21 @@ class Article {
$wgOut->setPagetitle( $page->getPrefixedText() );
$wgOut->setPageTitleActionText( wfMsg( 'info_short' ) );
- $wgOut->setSubtitle( wfMsg( 'infosubtitle' ) );
+ $wgOut->setSubtitle( wfMsgHtml( 'infosubtitle' ) );
if( !$this->mTitle->exists() ) {
- $wgOut->addHtml( '<div class="noarticletext">' );
+ $wgOut->addHTML( '<div class="noarticletext">' );
if( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
// This doesn't quite make sense; the user is asking for
// information about the _page_, not the message... -- RC
- $wgOut->addHtml( htmlspecialchars( wfMsgWeirdKey( $this->mTitle->getText() ) ) );
+ $wgOut->addHTML( htmlspecialchars( wfMsgWeirdKey( $this->mTitle->getText() ) ) );
} else {
$msg = $wgUser->isLoggedIn()
? 'noarticletext'
: 'noarticletextanon';
- $wgOut->addHtml( wfMsgExt( $msg, 'parse' ) );
+ $wgOut->addHTML( wfMsgExt( $msg, 'parse' ) );
}
- $wgOut->addHtml( '</div>' );
+ $wgOut->addHTML( '</div>' );
} else {
$dbr = wfGetDB( DB_SLAVE );
$wl_clause = array(
@@ -3222,7 +3295,6 @@ class Article {
$wgOut->addHTML( '<li>' . wfMsg('numtalkauthors', $wgLang->formatNum( $talkInfo['authors'] ) ) . '</li>' );
}
$wgOut->addHTML( '</ul>' );
-
}
}
@@ -3230,34 +3302,30 @@ class Article {
* Return the total number of edits and number of unique editors
* on a given page. If page does not exist, returns false.
*
- * @param Title $title
+ * @param $title Title object
* @return array
- * @private
*/
- function pageCountInfo( $title ) {
+ protected function pageCountInfo( $title ) {
$id = $title->getArticleId();
if( $id == 0 ) {
return false;
}
-
$dbr = wfGetDB( DB_SLAVE );
-
$rev_clause = array( 'rev_page' => $id );
-
$edits = $dbr->selectField(
'revision',
'COUNT(rev_page)',
$rev_clause,
__METHOD__,
- $this->getSelectOptions() );
-
+ $this->getSelectOptions()
+ );
$authors = $dbr->selectField(
'revision',
'COUNT(DISTINCT rev_user_text)',
$rev_clause,
__METHOD__,
- $this->getSelectOptions() );
-
+ $this->getSelectOptions()
+ );
return array( 'edits' => $edits, 'authors' => $authors );
}
@@ -3265,25 +3333,22 @@ class Article {
* Return a list of templates used by this article.
* Uses the templatelinks table
*
- * @return array Array of Title objects
+ * @return Array of Title objects
*/
- function getUsedTemplates() {
+ public function getUsedTemplates() {
$result = array();
$id = $this->mTitle->getArticleID();
if( $id == 0 ) {
return array();
}
-
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( array( 'templatelinks' ),
array( 'tl_namespace', 'tl_title' ),
array( 'tl_from' => $id ),
- 'Article:getUsedTemplates' );
- if ( false !== $res ) {
- if ( $dbr->numRows( $res ) ) {
- while ( $row = $dbr->fetchObject( $res ) ) {
- $result[] = Title::makeTitle( $row->tl_namespace, $row->tl_title );
- }
+ __METHOD__ );
+ if( $res !== false ) {
+ foreach( $res as $row ) {
+ $result[] = Title::makeTitle( $row->tl_namespace, $row->tl_title );
}
}
$dbr->freeResult( $res );
@@ -3294,26 +3359,23 @@ class Article {
* Returns a list of hidden categories this page is a member of.
* Uses the page_props and categorylinks tables.
*
- * @return array Array of Title objects
+ * @return Array of Title objects
*/
- function getHiddenCategories() {
+ public function getHiddenCategories() {
$result = array();
$id = $this->mTitle->getArticleID();
if( $id == 0 ) {
return array();
}
-
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( array( 'categorylinks', 'page_props', 'page' ),
array( 'cl_to' ),
array( 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat',
'page_namespace' => NS_CATEGORY, 'page_title=cl_to'),
- 'Article:getHiddenCategories' );
- if ( false !== $res ) {
- if ( $dbr->numRows( $res ) ) {
- while ( $row = $dbr->fetchObject( $res ) ) {
- $result[] = Title::makeTitle( NS_CATEGORY, $row->cl_to );
- }
+ __METHOD__ );
+ if( $res !== false ) {
+ foreach( $res as $row ) {
+ $result[] = Title::makeTitle( NS_CATEGORY, $row->cl_to );
}
}
$dbr->freeResult( $res );
@@ -3322,17 +3384,18 @@ class Article {
/**
* Return an applicable autosummary if one exists for the given edit.
- * @param string $oldtext The previous text of the page.
- * @param string $newtext The submitted text of the page.
- * @param bitmask $flags A bitmask of flags submitted for the edit.
+ * @param $oldtext String: the previous text of the page.
+ * @param $newtext String: The submitted text of the page.
+ * @param $flags Bitmask: a bitmask of flags submitted for the edit.
* @return string An appropriate autosummary, or an empty string.
*/
public static function getAutosummary( $oldtext, $newtext, $flags ) {
# Decide what kind of autosummary is needed.
# Redirect autosummaries
+ $ot = Title::newFromRedirect( $oldtext );
$rt = Title::newFromRedirect( $newtext );
- if( is_object( $rt ) ) {
+ if( is_object( $rt ) && ( !is_object( $ot ) || !$rt->equals( $ot ) || $ot->getFragment() != $rt->getFragment() ) ) {
return wfMsgForContent( 'autoredircomment', $rt->getFullText() );
}
@@ -3342,14 +3405,14 @@ class Article {
global $wgContLang;
$truncatedtext = $wgContLang->truncate(
str_replace("\n", ' ', $newtext),
- max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new') ) ),
+ max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new' ) ) ),
'...' );
return wfMsgForContent( 'autosumm-new', $truncatedtext );
}
# Blanking autosummaries
if( $oldtext != '' && $newtext == '' ) {
- return wfMsgForContent('autosumm-blank');
+ return wfMsgForContent( 'autosumm-blank' );
} elseif( strlen( $oldtext ) > 10 * strlen( $newtext ) && strlen( $newtext ) < 500) {
# Removing more than 90% of the article
global $wgContLang;
@@ -3371,11 +3434,11 @@ class Article {
* Saves the text into the parser cache if possible.
* Updates templatelinks if it is out of date.
*
- * @param string $text
- * @param bool $cache
+ * @param $text String
+ * @param $cache Boolean
*/
public function outputWikiText( $text, $cache = true ) {
- global $wgParser, $wgUser, $wgOut, $wgEnableParserCache;
+ global $wgParser, $wgUser, $wgOut, $wgEnableParserCache, $wgUseFileCache;
$popts = $wgOut->parserOptions();
$popts->setTidy(true);
@@ -3384,12 +3447,18 @@ class Article {
$popts, true, true, $this->getRevIdFetched() );
$popts->setTidy(false);
$popts->enableLimitReport( false );
- if ( $wgEnableParserCache && $cache && $this && $parserOutput->getCacheTime() != -1 ) {
+ if( $wgEnableParserCache && $cache && $this && $parserOutput->getCacheTime() != -1 ) {
$parserCache = ParserCache::singleton();
$parserCache->save( $parserOutput, $this, $wgUser );
}
+ // Make sure file cache is not used on uncacheable content.
+ // Output that has magic words in it can still use the parser cache
+ // (if enabled), though it will generally expire sooner.
+ if( $parserOutput->getCacheTime() == -1 || $parserOutput->containsOldMagic() ) {
+ $wgUseFileCache = false;
+ }
- if ( !wfReadOnly() && $this->mTitle->areRestrictionsCascading() ) {
+ if( $this->isCurrent() && !wfReadOnly() && $this->mTitle->areRestrictionsCascading() ) {
// templatelinks table may have become out of sync,
// especially if using variable-based transclusions.
// For paranoia, check if things have changed and if
@@ -3406,15 +3475,13 @@ class Article {
$res = $dbr->select( array( 'templatelinks' ),
array( 'tl_namespace', 'tl_title' ),
array( 'tl_from' => $id ),
- 'Article:getUsedTemplates' );
+ __METHOD__ );
global $wgContLang;
- if ( false !== $res ) {
- if ( $dbr->numRows( $res ) ) {
- while ( $row = $dbr->fetchObject( $res ) ) {
- $tlTemplates[] = $wgContLang->getNsText( $row->tl_namespace ) . ':' . $row->tl_title ;
- }
+ if( $res !== false ) {
+ foreach( $res as $row ) {
+ $tlTemplates[] = $wgContLang->getNsText( $row->tl_namespace ) . ':' . $row->tl_title ;
}
}
@@ -3429,16 +3496,10 @@ class Article {
# Get the diff
$templates_diff = array_diff( $poTemplates, $tlTemplates );
- if ( count( $templates_diff ) > 0 ) {
+ if( count( $templates_diff ) > 0 ) {
# Whee, link updates time.
$u = new LinksUpdate( $this->mTitle, $parserOutput );
-
- $dbw = wfGetDb( DB_MASTER );
- $dbw->begin();
-
$u->doUpdate();
-
- $dbw->commit();
}
}
@@ -3479,12 +3540,12 @@ class Article {
if( $ns == NS_CATEGORY ) {
$addFields[] = 'cat_subcats = cat_subcats + 1';
$removeFields[] = 'cat_subcats = cat_subcats - 1';
- } elseif( $ns == NS_IMAGE ) {
+ } elseif( $ns == NS_FILE ) {
$addFields[] = 'cat_files = cat_files + 1';
$removeFields[] = 'cat_files = cat_files - 1';
}
- if ( $added ) {
+ if( $added ) {
$dbw->update(
'category',
$addFields,
@@ -3492,7 +3553,7 @@ class Article {
__METHOD__
);
}
- if ( $deleted ) {
+ if( $deleted ) {
$dbw->update(
'category',
$removeFields,
diff --git a/includes/AuthPlugin.php b/includes/AuthPlugin.php
index 7717e001..b29e13f2 100644
--- a/includes/AuthPlugin.php
+++ b/includes/AuthPlugin.php
@@ -38,9 +38,8 @@ class AuthPlugin {
*
* @param $username String: username.
* @return bool
- * @public
*/
- function userExists( $username ) {
+ public function userExists( $username ) {
# Override this!
return false;
}
@@ -54,9 +53,8 @@ class AuthPlugin {
* @param $username String: username.
* @param $password String: user password.
* @return bool
- * @public
*/
- function authenticate( $username, $password ) {
+ public function authenticate( $username, $password ) {
# Override this!
return false;
}
@@ -65,9 +63,8 @@ class AuthPlugin {
* Modify options in the login template.
*
* @param $template UserLoginTemplate object.
- * @public
*/
- function modifyUITemplate( &$template ) {
+ public function modifyUITemplate( &$template ) {
# Override this!
$template->set( 'usedomain', false );
}
@@ -76,9 +73,8 @@ class AuthPlugin {
* Set the domain this plugin is supposed to use when authenticating.
*
* @param $domain String: authentication domain.
- * @public
*/
- function setDomain( $domain ) {
+ public function setDomain( $domain ) {
$this->domain = $domain;
}
@@ -87,9 +83,8 @@ class AuthPlugin {
*
* @param $domain String: authentication domain.
* @return bool
- * @public
*/
- function validDomain( $domain ) {
+ public function validDomain( $domain ) {
# Override this!
return true;
}
@@ -103,9 +98,8 @@ class AuthPlugin {
* forget the & on your function declaration.
*
* @param User $user
- * @public
*/
- function updateUser( &$user ) {
+ public function updateUser( &$user ) {
# Override this and do something
return true;
}
@@ -123,9 +117,8 @@ class AuthPlugin {
* This is just a question, and shouldn't perform any actions.
*
* @return bool
- * @public
*/
- function autoCreate() {
+ public function autoCreate() {
return false;
}
@@ -134,7 +127,7 @@ class AuthPlugin {
*
* @return bool
*/
- function allowPasswordChange() {
+ public function allowPasswordChange() {
return true;
}
@@ -149,9 +142,8 @@ class AuthPlugin {
* @param $user User object.
* @param $password String: password.
* @return bool
- * @public
*/
- function setPassword( $user, $password ) {
+ public function setPassword( $user, $password ) {
return true;
}
@@ -161,9 +153,8 @@ class AuthPlugin {
*
* @param $user User object.
* @return bool
- * @public
*/
- function updateExternalDB( $user ) {
+ public function updateExternalDB( $user ) {
return true;
}
@@ -171,9 +162,8 @@ class AuthPlugin {
* Check to see if external accounts can be created.
* Return true if external accounts can be created.
* @return bool
- * @public
*/
- function canCreateAccounts() {
+ public function canCreateAccounts() {
return false;
}
@@ -186,9 +176,8 @@ class AuthPlugin {
* @param string $email
* @param string $realname
* @return bool
- * @public
*/
- function addUser( $user, $password, $email='', $realname='' ) {
+ public function addUser( $user, $password, $email='', $realname='' ) {
return true;
}
@@ -200,9 +189,8 @@ class AuthPlugin {
* This is just a question, and shouldn't perform any actions.
*
* @return bool
- * @public
*/
- function strict() {
+ public function strict() {
return false;
}
@@ -212,9 +200,8 @@ class AuthPlugin {
*
* @param $username String: username.
* @return bool
- * @public
*/
- function strictUserAuth( $username ) {
+ public function strictUserAuth( $username ) {
return false;
}
@@ -228,9 +215,8 @@ class AuthPlugin {
*
* @param $user User object.
* @param $autocreate bool True if user is being autocreated on login
- * @public
*/
- function initUser( &$user, $autocreate=false ) {
+ public function initUser( &$user, $autocreate=false ) {
# Override this to do something.
}
@@ -238,7 +224,43 @@ class AuthPlugin {
* If you want to munge the case of an account name before the final
* check, now is your chance.
*/
- function getCanonicalName( $username ) {
+ public function getCanonicalName( $username ) {
return $username;
}
+
+ /**
+ * Get an instance of a User object
+ *
+ * @param $user User
+ * @public
+ */
+ public function getUserInstance( User &$user ) {
+ return new AuthPluginUser( $user );
+ }
+}
+
+class AuthPluginUser {
+ function __construct( $user ) {
+ # Override this!
+ }
+
+ public function getId() {
+ # Override this!
+ return -1;
+ }
+
+ public function isLocked() {
+ # Override this!
+ return false;
+ }
+
+ public function isHidden() {
+ # Override this!
+ return false;
+ }
+
+ public function resetAuthToken() {
+ # Override this!
+ return true;
+ }
}
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index de75b41d..ce1912ea 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -4,483 +4,544 @@
ini_set('unserialize_callback_func', '__autoload' );
-class AutoLoader {
- # Locations of core classes
- # Extension classes are specified with $wgAutoloadClasses
- static $localClasses = array(
- # Includes
- 'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
- 'AjaxResponse' => 'includes/AjaxResponse.php',
- 'AlphabeticPager' => 'includes/Pager.php',
- 'APCBagOStuff' => 'includes/BagOStuff.php',
- 'ArrayDiffFormatter' => 'includes/DifferenceEngine.php',
- 'Article' => 'includes/Article.php',
- 'AtomFeed' => 'includes/Feed.php',
- 'AuthPlugin' => 'includes/AuthPlugin.php',
- 'Autopromote' => 'includes/Autopromote.php',
- 'BagOStuff' => 'includes/BagOStuff.php',
- 'Block' => 'includes/Block.php',
- 'CacheDependency' => 'includes/CacheDependency.php',
- 'Category' => 'includes/Category.php',
- 'Categoryfinder' => 'includes/Categoryfinder.php',
- 'CategoryPage' => 'includes/CategoryPage.php',
- 'CategoryViewer' => 'includes/CategoryPage.php',
- 'ChangesList' => 'includes/ChangesList.php',
- 'ChangesFeed' => 'includes/ChangesFeed.php',
- 'ChannelFeed' => 'includes/Feed.php',
- 'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php',
- 'ConstantDependency' => 'includes/CacheDependency.php',
- 'DBABagOStuff' => 'includes/BagOStuff.php',
- 'DependencyWrapper' => 'includes/CacheDependency.php',
- '_DiffEngine' => 'includes/DifferenceEngine.php',
- 'DifferenceEngine' => 'includes/DifferenceEngine.php',
- 'DiffFormatter' => 'includes/DifferenceEngine.php',
- 'Diff' => 'includes/DifferenceEngine.php',
- '_DiffOp_Add' => 'includes/DifferenceEngine.php',
- '_DiffOp_Change' => 'includes/DifferenceEngine.php',
- '_DiffOp_Copy' => 'includes/DifferenceEngine.php',
- '_DiffOp_Delete' => 'includes/DifferenceEngine.php',
- '_DiffOp' => 'includes/DifferenceEngine.php',
- 'DjVuImage' => 'includes/DjVuImage.php',
- 'DoubleReplacer' => 'includes/StringUtils.php',
- 'DoubleRedirectJob' => 'includes/DoubleRedirectJob.php',
- 'Dump7ZipOutput' => 'includes/Export.php',
- 'DumpBZip2Output' => 'includes/Export.php',
- 'DumpFileOutput' => 'includes/Export.php',
- 'DumpFilter' => 'includes/Export.php',
- 'DumpGZipOutput' => 'includes/Export.php',
- 'DumpLatestFilter' => 'includes/Export.php',
- 'DumpMultiWriter' => 'includes/Export.php',
- 'DumpNamespaceFilter' => 'includes/Export.php',
- 'DumpNotalkFilter' => 'includes/Export.php',
- 'DumpOutput' => 'includes/Export.php',
- 'DumpPipeOutput' => 'includes/Export.php',
- 'eAccelBagOStuff' => 'includes/BagOStuff.php',
- 'EditPage' => 'includes/EditPage.php',
- 'EmaillingJob' => 'includes/EmaillingJob.php',
- 'EmailNotification' => 'includes/UserMailer.php',
- 'EnhancedChangesList' => 'includes/ChangesList.php',
- 'EnotifNotifyJob' => 'includes/EnotifNotifyJob.php',
- 'ErrorPageError' => 'includes/Exception.php',
- 'Exif' => 'includes/Exif.php',
- 'ExternalEdit' => 'includes/ExternalEdit.php',
- 'ExternalStoreDB' => 'includes/ExternalStoreDB.php',
- 'ExternalStoreHttp' => 'includes/ExternalStoreHttp.php',
- 'ExternalStore' => 'includes/ExternalStore.php',
- 'FatalError' => 'includes/Exception.php',
- 'FakeTitle' => 'includes/FakeTitle.php',
- 'FauxRequest' => 'includes/WebRequest.php',
- 'FeedItem' => 'includes/Feed.php',
- 'FeedUtils' => 'includes/FeedUtils.php',
- 'FileDeleteForm' => 'includes/FileDeleteForm.php',
- 'FileDependency' => 'includes/CacheDependency.php',
- 'FileRevertForm' => 'includes/FileRevertForm.php',
- 'FileStore' => 'includes/FileStore.php',
- 'FormatExif' => 'includes/Exif.php',
- 'FormOptions' => 'includes/FormOptions.php',
- 'FSException' => 'includes/FileStore.php',
- 'FSTransaction' => 'includes/FileStore.php',
- 'GlobalDependency' => 'includes/CacheDependency.php',
- 'HashBagOStuff' => 'includes/BagOStuff.php',
- 'HashtableReplacer' => 'includes/StringUtils.php',
- 'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
- 'HistoryBlob' => 'includes/HistoryBlob.php',
- 'HistoryBlobStub' => 'includes/HistoryBlob.php',
- 'HTMLCacheUpdate' => 'includes/HTMLCacheUpdate.php',
- 'HTMLCacheUpdateJob' => 'includes/HTMLCacheUpdate.php',
- 'HTMLFileCache' => 'includes/HTMLFileCache.php',
- 'Http' => 'includes/HttpFunctions.php',
- '_HWLDF_WordAccumulator' => 'includes/DifferenceEngine.php',
- 'IEContentAnalyzer' => 'includes/IEContentAnalyzer.php',
- 'ImageGallery' => 'includes/ImageGallery.php',
- 'ImageHistoryList' => 'includes/ImagePage.php',
- 'ImagePage' => 'includes/ImagePage.php',
- 'ImageQueryPage' => 'includes/ImageQueryPage.php',
- 'IncludableSpecialPage' => 'includes/SpecialPage.php',
- 'IndexPager' => 'includes/Pager.php',
- 'IP' => 'includes/IP.php',
- 'Job' => 'includes/JobQueue.php',
- 'License' => 'includes/Licenses.php',
- 'Licenses' => 'includes/Licenses.php',
- 'LinkBatch' => 'includes/LinkBatch.php',
- 'LinkCache' => 'includes/LinkCache.php',
- 'Linker' => 'includes/Linker.php',
- 'LinkFilter' => 'includes/LinkFilter.php',
- 'LinksUpdate' => 'includes/LinksUpdate.php',
- 'LogPage' => 'includes/LogPage.php',
- 'LogPager' => 'includes/LogEventsList.php',
- 'LogEventsList' => 'includes/LogEventsList.php',
- 'LogReader' => 'includes/LogEventsList.php',
- 'LogViewer' => 'includes/LogEventsList.php',
- 'MacBinary' => 'includes/MacBinary.php',
- 'MagicWordArray' => 'includes/MagicWord.php',
- 'MagicWord' => 'includes/MagicWord.php',
- 'MailAddress' => 'includes/UserMailer.php',
- 'MappedDiff' => 'includes/DifferenceEngine.php',
- 'MathRenderer' => 'includes/Math.php',
- 'MediaTransformError' => 'includes/MediaTransformOutput.php',
- 'MediaTransformOutput' => 'includes/MediaTransformOutput.php',
- 'MediaWikiBagOStuff' => 'includes/BagOStuff.php',
- 'MediaWiki_I18N' => 'includes/SkinTemplate.php',
- 'MediaWiki' => 'includes/Wiki.php',
- 'memcached' => 'includes/memcached-client.php',
- 'MessageCache' => 'includes/MessageCache.php',
- 'MimeMagic' => 'includes/MimeMagic.php',
- 'MWException' => 'includes/Exception.php',
- 'MWNamespace' => 'includes/Namespace.php',
- 'MySQLSearchResultSet' => 'includes/SearchMySQL.php',
- 'Namespace' => 'includes/NamespaceCompat.php', // Compat
- 'OldChangesList' => 'includes/ChangesList.php',
- 'OracleSearchResultSet' => 'includes/SearchOracle.php',
- 'OutputPage' => 'includes/OutputPage.php',
- 'PageHistory' => 'includes/PageHistory.php',
- 'PageHistoryPager' => 'includes/PageHistory.php',
- 'PageQueryPage' => 'includes/PageQueryPage.php',
- 'Pager' => 'includes/Pager.php',
- 'PasswordError' => 'includes/User.php',
- 'PatrolLog' => 'includes/PatrolLog.php',
- 'PostgresSearchResult' => 'includes/SearchPostgres.php',
- 'PostgresSearchResultSet' => 'includes/SearchPostgres.php',
- 'PrefixSearch' => 'includes/PrefixSearch.php',
- 'Profiler' => 'includes/Profiler.php',
- 'ProfilerSimple' => 'includes/ProfilerSimple.php',
- 'ProfilerSimpleText' => 'includes/ProfilerSimpleText.php',
- 'ProfilerSimpleUDP' => 'includes/ProfilerSimpleUDP.php',
- 'ProtectionForm' => 'includes/ProtectionForm.php',
- 'QueryPage' => 'includes/QueryPage.php',
- 'QuickTemplate' => 'includes/SkinTemplate.php',
- 'RawPage' => 'includes/RawPage.php',
- 'RCCacheEntry' => 'includes/ChangesList.php',
- 'RecentChange' => 'includes/RecentChange.php',
- 'RefreshLinksJob' => 'includes/RefreshLinksJob.php',
- 'RegexlikeReplacer' => 'includes/StringUtils.php',
- 'ReplacementArray' => 'includes/StringUtils.php',
- 'Replacer' => 'includes/StringUtils.php',
- 'ReverseChronologicalPager' => 'includes/Pager.php',
- 'Revision' => 'includes/Revision.php',
- 'RSSFeed' => 'includes/Feed.php',
- 'Sanitizer' => 'includes/Sanitizer.php',
- 'SearchEngineDummy' => 'includes/SearchEngine.php',
- 'SearchEngine' => 'includes/SearchEngine.php',
- 'SearchHighlighter' => 'includes/SearchEngine.php',
- 'SearchMySQL4' => 'includes/SearchMySQL4.php',
- 'SearchMySQL' => 'includes/SearchMySQL.php',
- 'SearchOracle' => 'includes/SearchOracle.php',
- 'SearchPostgres' => 'includes/SearchPostgres.php',
- 'SearchResult' => 'includes/SearchEngine.php',
- 'SearchResultSet' => 'includes/SearchEngine.php',
- 'SearchResultTooMany' => 'includes/SearchEngine.php',
- 'SearchUpdate' => 'includes/SearchUpdate.php',
- 'SearchUpdateMyISAM' => 'includes/SearchUpdate.php',
- 'SiteConfiguration' => 'includes/SiteConfiguration.php',
- 'SiteStats' => 'includes/SiteStats.php',
- 'SiteStatsUpdate' => 'includes/SiteStats.php',
- 'Skin' => 'includes/Skin.php',
- 'SkinTemplate' => 'includes/SkinTemplate.php',
- 'SpecialMycontributions' => 'includes/SpecialPage.php',
- 'SpecialMypage' => 'includes/SpecialPage.php',
- 'SpecialMytalk' => 'includes/SpecialPage.php',
- 'SpecialPage' => 'includes/SpecialPage.php',
- 'SpecialRedirectToSpecial' => 'includes/SpecialPage.php',
- 'SqlBagOStuff' => 'includes/BagOStuff.php',
- 'SquidUpdate' => 'includes/SquidUpdate.php',
- 'Status' => 'includes/Status.php',
- 'StringUtils' => 'includes/StringUtils.php',
- 'TableDiffFormatter' => 'includes/DifferenceEngine.php',
- 'TablePager' => 'includes/Pager.php',
- 'ThumbnailImage' => 'includes/MediaTransformOutput.php',
- 'TitleDependency' => 'includes/CacheDependency.php',
- 'Title' => 'includes/Title.php',
- 'TitleListDependency' => 'includes/CacheDependency.php',
- 'TransformParameterError' => 'includes/MediaTransformOutput.php',
- 'TurckBagOStuff' => 'includes/BagOStuff.php',
- 'UnifiedDiffFormatter' => 'includes/DifferenceEngine.php',
- 'UnlistedSpecialPage' => 'includes/SpecialPage.php',
- 'User' => 'includes/User.php',
- 'UserArray' => 'includes/UserArray.php',
- 'UserArrayFromResult' => 'includes/UserArray.php',
- 'UserMailer' => 'includes/UserMailer.php',
- 'UserRightsProxy' => 'includes/UserRightsProxy.php',
- 'WatchedItem' => 'includes/WatchedItem.php',
- 'WatchlistEditor' => 'includes/WatchlistEditor.php',
- 'WebRequest' => 'includes/WebRequest.php',
- 'WebResponse' => 'includes/WebResponse.php',
- 'WikiError' => 'includes/WikiError.php',
- 'WikiErrorMsg' => 'includes/WikiError.php',
- 'WikiExporter' => 'includes/Export.php',
- 'WikiXmlError' => 'includes/WikiError.php',
- 'WordLevelDiff' => 'includes/DifferenceEngine.php',
- 'XCacheBagOStuff' => 'includes/BagOStuff.php',
- 'XmlDumpWriter' => 'includes/Export.php',
- 'Xml' => 'includes/Xml.php',
- 'XmlSelect' => 'includes/Xml.php',
- 'XmlTypeCheck' => 'includes/XmlTypeCheck.php',
- 'ZhClient' => 'includes/ZhClient.php',
+# Locations of core classes
+# Extension classes are specified with $wgAutoloadClasses
+# This array is a global instead of a static member of AutoLoader to work around a bug in APC
+global $wgAutoloadLocalClasses;
+$wgAutoloadLocalClasses = array(
+ # Includes
+ 'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
+ 'AjaxResponse' => 'includes/AjaxResponse.php',
+ 'AlphabeticPager' => 'includes/Pager.php',
+ 'APCBagOStuff' => 'includes/BagOStuff.php',
+ 'Article' => 'includes/Article.php',
+ 'AtomFeed' => 'includes/Feed.php',
+ 'AuthPlugin' => 'includes/AuthPlugin.php',
+ 'AuthPluginUser' => 'includes/AuthPlugin.php',
+ 'Autopromote' => 'includes/Autopromote.php',
+ 'BagOStuff' => 'includes/BagOStuff.php',
+ 'Block' => 'includes/Block.php',
+ 'CacheDependency' => 'includes/CacheDependency.php',
+ 'Category' => 'includes/Category.php',
+ 'Categoryfinder' => 'includes/Categoryfinder.php',
+ 'CategoryPage' => 'includes/CategoryPage.php',
+ 'CategoryViewer' => 'includes/CategoryPage.php',
+ 'ChangesList' => 'includes/ChangesList.php',
+ 'ChangesFeed' => 'includes/ChangesFeed.php',
+ 'ChannelFeed' => 'includes/Feed.php',
+ 'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php',
+ 'ConstantDependency' => 'includes/CacheDependency.php',
+ 'CreativeCommonsRdf' => 'includes/Metadata.php',
+ 'Credits' => 'includes/Credits.php',
+ 'DBABagOStuff' => 'includes/BagOStuff.php',
+ 'DependencyWrapper' => 'includes/CacheDependency.php',
+ 'DiffHistoryBlob' => 'includes/HistoryBlob.php',
+ 'DjVuImage' => 'includes/DjVuImage.php',
+ 'DoubleReplacer' => 'includes/StringUtils.php',
+ 'DoubleRedirectJob' => 'includes/DoubleRedirectJob.php',
+ 'DublinCoreRdf' => 'includes/Metadata.php',
+ 'Dump7ZipOutput' => 'includes/Export.php',
+ 'DumpBZip2Output' => 'includes/Export.php',
+ 'DumpFileOutput' => 'includes/Export.php',
+ 'DumpFilter' => 'includes/Export.php',
+ 'DumpGZipOutput' => 'includes/Export.php',
+ 'DumpLatestFilter' => 'includes/Export.php',
+ 'DumpMultiWriter' => 'includes/Export.php',
+ 'DumpNamespaceFilter' => 'includes/Export.php',
+ 'DumpNotalkFilter' => 'includes/Export.php',
+ 'DumpOutput' => 'includes/Export.php',
+ 'DumpPipeOutput' => 'includes/Export.php',
+ 'eAccelBagOStuff' => 'includes/BagOStuff.php',
+ 'EditPage' => 'includes/EditPage.php',
+ 'EmaillingJob' => 'includes/EmaillingJob.php',
+ 'EmailNotification' => 'includes/UserMailer.php',
+ 'EnhancedChangesList' => 'includes/ChangesList.php',
+ 'EnotifNotifyJob' => 'includes/EnotifNotifyJob.php',
+ 'ErrorPageError' => 'includes/Exception.php',
+ 'Exif' => 'includes/Exif.php',
+ 'ExplodeIterator' => 'includes/StringUtils.php',
+ 'ExternalEdit' => 'includes/ExternalEdit.php',
+ 'ExternalStoreDB' => 'includes/ExternalStoreDB.php',
+ 'ExternalStoreHttp' => 'includes/ExternalStoreHttp.php',
+ 'ExternalStore' => 'includes/ExternalStore.php',
+ 'FatalError' => 'includes/Exception.php',
+ 'FakeTitle' => 'includes/FakeTitle.php',
+ 'FauxRequest' => 'includes/WebRequest.php',
+ 'FeedItem' => 'includes/Feed.php',
+ 'FeedUtils' => 'includes/FeedUtils.php',
+ 'FileDeleteForm' => 'includes/FileDeleteForm.php',
+ 'FileDependency' => 'includes/CacheDependency.php',
+ 'FileRevertForm' => 'includes/FileRevertForm.php',
+ 'FileStore' => 'includes/FileStore.php',
+ 'FormatExif' => 'includes/Exif.php',
+ 'FormOptions' => 'includes/FormOptions.php',
+ 'FSException' => 'includes/FileStore.php',
+ 'FSTransaction' => 'includes/FileStore.php',
+ 'GlobalDependency' => 'includes/CacheDependency.php',
+ 'HashBagOStuff' => 'includes/BagOStuff.php',
+ 'HashtableReplacer' => 'includes/StringUtils.php',
+ 'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
+ 'HistoryBlob' => 'includes/HistoryBlob.php',
+ 'HistoryBlobStub' => 'includes/HistoryBlob.php',
+ 'HTMLCacheUpdate' => 'includes/HTMLCacheUpdate.php',
+ 'HTMLCacheUpdateJob' => 'includes/HTMLCacheUpdate.php',
+ 'HTMLFileCache' => 'includes/HTMLFileCache.php',
+ 'Http' => 'includes/HttpFunctions.php',
+ 'IEContentAnalyzer' => 'includes/IEContentAnalyzer.php',
+ 'ImageGallery' => 'includes/ImageGallery.php',
+ 'ImageHistoryList' => 'includes/ImagePage.php',
+ 'ImagePage' => 'includes/ImagePage.php',
+ 'ImageQueryPage' => 'includes/ImageQueryPage.php',
+ 'IncludableSpecialPage' => 'includes/SpecialPage.php',
+ 'IndexPager' => 'includes/Pager.php',
+ 'Interwiki' => 'includes/Interwiki.php',
+ 'IP' => 'includes/IP.php',
+ 'Job' => 'includes/JobQueue.php',
+ 'License' => 'includes/Licenses.php',
+ 'Licenses' => 'includes/Licenses.php',
+ 'LinkBatch' => 'includes/LinkBatch.php',
+ 'LinkCache' => 'includes/LinkCache.php',
+ 'Linker' => 'includes/Linker.php',
+ 'LinkFilter' => 'includes/LinkFilter.php',
+ 'LinksUpdate' => 'includes/LinksUpdate.php',
+ 'LogPage' => 'includes/LogPage.php',
+ 'LogPager' => 'includes/LogEventsList.php',
+ 'LogEventsList' => 'includes/LogEventsList.php',
+ 'LogReader' => 'includes/LogEventsList.php',
+ 'LogViewer' => 'includes/LogEventsList.php',
+ 'MacBinary' => 'includes/MacBinary.php',
+ 'MagicWordArray' => 'includes/MagicWord.php',
+ 'MagicWord' => 'includes/MagicWord.php',
+ 'MailAddress' => 'includes/UserMailer.php',
+ 'MathRenderer' => 'includes/Math.php',
+ 'MediaTransformError' => 'includes/MediaTransformOutput.php',
+ 'MediaTransformOutput' => 'includes/MediaTransformOutput.php',
+ 'MediaWikiBagOStuff' => 'includes/BagOStuff.php',
+ 'MediaWiki_I18N' => 'includes/SkinTemplate.php',
+ 'MediaWiki' => 'includes/Wiki.php',
+ 'memcached' => 'includes/memcached-client.php',
+ 'MessageCache' => 'includes/MessageCache.php',
+ 'MimeMagic' => 'includes/MimeMagic.php',
+ 'MWException' => 'includes/Exception.php',
+ 'MWNamespace' => 'includes/Namespace.php',
+ 'MySQLSearchResultSet' => 'includes/SearchMySQL.php',
+ 'Namespace' => 'includes/NamespaceCompat.php', // Compat
+ 'OldChangesList' => 'includes/ChangesList.php',
+ 'OracleSearchResultSet' => 'includes/SearchOracle.php',
+ 'OutputPage' => 'includes/OutputPage.php',
+ 'PageHistory' => 'includes/PageHistory.php',
+ 'PageHistoryPager' => 'includes/PageHistory.php',
+ 'PageQueryPage' => 'includes/PageQueryPage.php',
+ 'Pager' => 'includes/Pager.php',
+ 'PasswordError' => 'includes/User.php',
+ 'PatrolLog' => 'includes/PatrolLog.php',
+ 'PostgresSearchResult' => 'includes/SearchPostgres.php',
+ 'PostgresSearchResultSet' => 'includes/SearchPostgres.php',
+ 'PrefixSearch' => 'includes/PrefixSearch.php',
+ 'Profiler' => 'includes/Profiler.php',
+ 'ProfilerSimple' => 'includes/ProfilerSimple.php',
+ 'ProfilerSimpleText' => 'includes/ProfilerSimpleText.php',
+ 'ProfilerSimpleUDP' => 'includes/ProfilerSimpleUDP.php',
+ 'ProtectionForm' => 'includes/ProtectionForm.php',
+ 'QueryPage' => 'includes/QueryPage.php',
+ 'QuickTemplate' => 'includes/SkinTemplate.php',
+ 'RawPage' => 'includes/RawPage.php',
+ 'RCCacheEntry' => 'includes/ChangesList.php',
+ 'RdfMetaData' => 'includes/Metadata.php',
+ 'RecentChange' => 'includes/RecentChange.php',
+ 'RefreshLinksJob' => 'includes/RefreshLinksJob.php',
+ 'RefreshLinksJob2' => 'includes/RefreshLinksJob.php',
+ 'RegexlikeReplacer' => 'includes/StringUtils.php',
+ 'ReplacementArray' => 'includes/StringUtils.php',
+ 'Replacer' => 'includes/StringUtils.php',
+ 'ReverseChronologicalPager' => 'includes/Pager.php',
+ 'Revision' => 'includes/Revision.php',
+ 'RSSFeed' => 'includes/Feed.php',
+ 'Sanitizer' => 'includes/Sanitizer.php',
+ 'SearchEngineDummy' => 'includes/SearchEngine.php',
+ 'SearchEngine' => 'includes/SearchEngine.php',
+ 'SearchHighlighter' => 'includes/SearchEngine.php',
+ 'SearchMySQL4' => 'includes/SearchMySQL4.php',
+ 'SearchMySQL' => 'includes/SearchMySQL.php',
+ 'SearchOracle' => 'includes/SearchOracle.php',
+ 'SearchPostgres' => 'includes/SearchPostgres.php',
+ 'SearchResult' => 'includes/SearchEngine.php',
+ 'SearchResultSet' => 'includes/SearchEngine.php',
+ 'SearchResultTooMany' => 'includes/SearchEngine.php',
+ 'SearchUpdate' => 'includes/SearchUpdate.php',
+ 'SearchUpdateMyISAM' => 'includes/SearchUpdate.php',
+ 'SiteConfiguration' => 'includes/SiteConfiguration.php',
+ 'SiteStats' => 'includes/SiteStats.php',
+ 'SiteStatsUpdate' => 'includes/SiteStats.php',
+ 'Skin' => 'includes/Skin.php',
+ 'SkinTemplate' => 'includes/SkinTemplate.php',
+ 'SpecialMycontributions' => 'includes/SpecialPage.php',
+ 'SpecialMypage' => 'includes/SpecialPage.php',
+ 'SpecialMytalk' => 'includes/SpecialPage.php',
+ 'SpecialPage' => 'includes/SpecialPage.php',
+ 'SpecialRedirectToSpecial' => 'includes/SpecialPage.php',
+ 'SqlBagOStuff' => 'includes/BagOStuff.php',
+ 'SquidUpdate' => 'includes/SquidUpdate.php',
+ 'Status' => 'includes/Status.php',
+ 'StringUtils' => 'includes/StringUtils.php',
+ 'TablePager' => 'includes/Pager.php',
+ 'ThumbnailImage' => 'includes/MediaTransformOutput.php',
+ 'TitleDependency' => 'includes/CacheDependency.php',
+ 'Title' => 'includes/Title.php',
+ 'TitleArray' => 'includes/TitleArray.php',
+ 'TitleListDependency' => 'includes/CacheDependency.php',
+ 'TransformParameterError' => 'includes/MediaTransformOutput.php',
+ 'TurckBagOStuff' => 'includes/BagOStuff.php',
+ 'UnlistedSpecialPage' => 'includes/SpecialPage.php',
+ 'UploadBase' => 'includes/UploadBase.php',
+ 'UploadFromStash' => 'includes/UploadFromStash.php',
+ 'UploadFromUpload' => 'includes/UploadFromUpload.php',
+ 'UploadFromUrl' => 'includes/UploadFromUrl.php',
+ 'User' => 'includes/User.php',
+ 'UserArray' => 'includes/UserArray.php',
+ 'UserArrayFromResult' => 'includes/UserArray.php',
+ 'UserMailer' => 'includes/UserMailer.php',
+ 'UserRightsProxy' => 'includes/UserRightsProxy.php',
+ 'WatchedItem' => 'includes/WatchedItem.php',
+ 'WatchlistEditor' => 'includes/WatchlistEditor.php',
+ 'WebRequest' => 'includes/WebRequest.php',
+ 'WebResponse' => 'includes/WebResponse.php',
+ 'WikiError' => 'includes/WikiError.php',
+ 'WikiErrorMsg' => 'includes/WikiError.php',
+ 'WikiExporter' => 'includes/Export.php',
+ 'WikiXmlError' => 'includes/WikiError.php',
+ 'XCacheBagOStuff' => 'includes/BagOStuff.php',
+ 'XmlDumpWriter' => 'includes/Export.php',
+ 'Xml' => 'includes/Xml.php',
+ 'XmlSelect' => 'includes/Xml.php',
+ 'XmlTypeCheck' => 'includes/XmlTypeCheck.php',
+ 'ZhClient' => 'includes/ZhClient.php',
+
+ # includes/api
+ 'ApiBase' => 'includes/api/ApiBase.php',
+ 'ApiBlock' => 'includes/api/ApiBlock.php',
+ 'ApiDelete' => 'includes/api/ApiDelete.php',
+ 'ApiDisabled' => 'includes/api/ApiDisabled.php',
+ 'ApiEditPage' => 'includes/api/ApiEditPage.php',
+ 'ApiEmailUser' => 'includes/api/ApiEmailUser.php',
+ 'ApiExpandTemplates' => 'includes/api/ApiExpandTemplates.php',
+ 'ApiFeedWatchlist' => 'includes/api/ApiFeedWatchlist.php',
+ 'ApiFormatBase' => 'includes/api/ApiFormatBase.php',
+ 'ApiFormatDbg' => 'includes/api/ApiFormatDbg.php',
+ 'ApiFormatFeedWrapper' => 'includes/api/ApiFormatBase.php',
+ 'ApiFormatJson' => 'includes/api/ApiFormatJson.php',
+ 'ApiFormatPhp' => 'includes/api/ApiFormatPhp.php',
+ 'ApiFormatTxt' => 'includes/api/ApiFormatTxt.php',
+ 'ApiFormatWddx' => 'includes/api/ApiFormatWddx.php',
+ 'ApiFormatXml' => 'includes/api/ApiFormatXml.php',
+ 'ApiFormatYaml' => 'includes/api/ApiFormatYaml.php',
+ 'ApiHelp' => 'includes/api/ApiHelp.php',
+ 'ApiLogin' => 'includes/api/ApiLogin.php',
+ 'ApiLogout' => 'includes/api/ApiLogout.php',
+ 'ApiMain' => 'includes/api/ApiMain.php',
+ 'ApiMove' => 'includes/api/ApiMove.php',
+ 'ApiOpenSearch' => 'includes/api/ApiOpenSearch.php',
+ 'ApiPageSet' => 'includes/api/ApiPageSet.php',
+ 'ApiParamInfo' => 'includes/api/ApiParamInfo.php',
+ 'ApiParse' => 'includes/api/ApiParse.php',
+ 'ApiPatrol' => 'includes/api/ApiPatrol.php',
+ 'ApiProtect' => 'includes/api/ApiProtect.php',
+ 'ApiPurge' => 'includes/api/ApiPurge.php',
+ 'ApiQuery' => 'includes/api/ApiQuery.php',
+ 'ApiQueryAllCategories' => 'includes/api/ApiQueryAllCategories.php',
+ 'ApiQueryAllimages' => 'includes/api/ApiQueryAllimages.php',
+ 'ApiQueryAllLinks' => 'includes/api/ApiQueryAllLinks.php',
+ 'ApiQueryAllUsers' => 'includes/api/ApiQueryAllUsers.php',
+ 'ApiQueryAllmessages' => 'includes/api/ApiQueryAllmessages.php',
+ 'ApiQueryAllpages' => 'includes/api/ApiQueryAllpages.php',
+ 'ApiQueryBacklinks' => 'includes/api/ApiQueryBacklinks.php',
+ 'ApiQueryBase' => 'includes/api/ApiQueryBase.php',
+ 'ApiQueryBlocks' => 'includes/api/ApiQueryBlocks.php',
+ 'ApiQueryCategories' => 'includes/api/ApiQueryCategories.php',
+ 'ApiQueryCategoryInfo' => 'includes/api/ApiQueryCategoryInfo.php',
+ 'ApiQueryCategoryMembers' => 'includes/api/ApiQueryCategoryMembers.php',
+ 'ApiQueryContributions' => 'includes/api/ApiQueryUserContributions.php',
+ 'ApiQueryDeletedrevs' => 'includes/api/ApiQueryDeletedrevs.php',
+ 'ApiQueryDisabled' => 'includes/api/ApiQueryDisabled.php',
+ 'ApiQueryDuplicateFiles' => 'includes/api/ApiQueryDuplicateFiles.php',
+ 'ApiQueryExtLinksUsage' => 'includes/api/ApiQueryExtLinksUsage.php',
+ 'ApiQueryExternalLinks' => 'includes/api/ApiQueryExternalLinks.php',
+ 'ApiQueryGeneratorBase' => 'includes/api/ApiQueryBase.php',
+ 'ApiQueryImageInfo' => 'includes/api/ApiQueryImageInfo.php',
+ 'ApiQueryImages' => 'includes/api/ApiQueryImages.php',
+ 'ApiQueryInfo' => 'includes/api/ApiQueryInfo.php',
+ 'ApiQueryLangLinks' => 'includes/api/ApiQueryLangLinks.php',
+ 'ApiQueryLinks' => 'includes/api/ApiQueryLinks.php',
+ 'ApiQueryLogEvents' => 'includes/api/ApiQueryLogEvents.php',
+ 'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
+ 'ApiQueryRecentChanges'=> 'includes/api/ApiQueryRecentChanges.php',
+ 'ApiQueryRevisions' => 'includes/api/ApiQueryRevisions.php',
+ 'ApiQuerySearch' => 'includes/api/ApiQuerySearch.php',
+ 'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php',
+ 'ApiQueryUserInfo' => 'includes/api/ApiQueryUserInfo.php',
+ 'ApiQueryUsers' => 'includes/api/ApiQueryUsers.php',
+ 'ApiQueryWatchlist' => 'includes/api/ApiQueryWatchlist.php',
+ 'ApiQueryWatchlistRaw' => 'includes/api/ApiQueryWatchlistRaw.php',
+ 'ApiResult' => 'includes/api/ApiResult.php',
+ 'ApiRollback' => 'includes/api/ApiRollback.php',
+ 'ApiUnblock' => 'includes/api/ApiUnblock.php',
+ 'ApiUndelete' => 'includes/api/ApiUndelete.php',
+ 'ApiWatch' => 'includes/api/ApiWatch.php',
+ 'Services_JSON' => 'includes/api/ApiFormatJson_json.php',
+ 'Services_JSON_Error' => 'includes/api/ApiFormatJson_json.php',
+ 'Spyc' => 'includes/api/ApiFormatYaml_spyc.php',
+ 'UsageException' => 'includes/api/ApiMain.php',
- # includes/api
- 'ApiBase' => 'includes/api/ApiBase.php',
- 'ApiBlock' => 'includes/api/ApiBlock.php',
- 'ApiDelete' => 'includes/api/ApiDelete.php',
- 'ApiEditPage' => 'includes/api/ApiEditPage.php',
- 'ApiEmailUser' => 'includes/api/ApiEmailUser.php',
- 'ApiExpandTemplates' => 'includes/api/ApiExpandTemplates.php',
- 'ApiFeedWatchlist' => 'includes/api/ApiFeedWatchlist.php',
- 'ApiFormatBase' => 'includes/api/ApiFormatBase.php',
- 'ApiFormatDbg' => 'includes/api/ApiFormatDbg.php',
- 'ApiFormatFeedWrapper' => 'includes/api/ApiFormatBase.php',
- 'ApiFormatJson' => 'includes/api/ApiFormatJson.php',
- 'ApiFormatPhp' => 'includes/api/ApiFormatPhp.php',
- 'ApiFormatTxt' => 'includes/api/ApiFormatTxt.php',
- 'ApiFormatWddx' => 'includes/api/ApiFormatWddx.php',
- 'ApiFormatXml' => 'includes/api/ApiFormatXml.php',
- 'ApiFormatYaml' => 'includes/api/ApiFormatYaml.php',
- 'ApiHelp' => 'includes/api/ApiHelp.php',
- 'ApiLogin' => 'includes/api/ApiLogin.php',
- 'ApiLogout' => 'includes/api/ApiLogout.php',
- 'ApiMain' => 'includes/api/ApiMain.php',
- 'ApiMove' => 'includes/api/ApiMove.php',
- 'ApiOpenSearch' => 'includes/api/ApiOpenSearch.php',
- 'ApiPageSet' => 'includes/api/ApiPageSet.php',
- 'ApiParamInfo' => 'includes/api/ApiParamInfo.php',
- 'ApiParse' => 'includes/api/ApiParse.php',
- 'ApiProtect' => 'includes/api/ApiProtect.php',
- 'ApiQuery' => 'includes/api/ApiQuery.php',
- 'ApiQueryAllCategories' => 'includes/api/ApiQueryAllCategories.php',
- 'ApiQueryAllimages' => 'includes/api/ApiQueryAllimages.php',
- 'ApiQueryAllLinks' => 'includes/api/ApiQueryAllLinks.php',
- 'ApiQueryAllUsers' => 'includes/api/ApiQueryAllUsers.php',
- 'ApiQueryAllmessages' => 'includes/api/ApiQueryAllmessages.php',
- 'ApiQueryAllpages' => 'includes/api/ApiQueryAllpages.php',
- 'ApiQueryBacklinks' => 'includes/api/ApiQueryBacklinks.php',
- 'ApiQueryBase' => 'includes/api/ApiQueryBase.php',
- 'ApiQueryBlocks' => 'includes/api/ApiQueryBlocks.php',
- 'ApiQueryCategories' => 'includes/api/ApiQueryCategories.php',
- 'ApiQueryCategoryInfo' => 'includes/api/ApiQueryCategoryInfo.php',
- 'ApiQueryCategoryMembers' => 'includes/api/ApiQueryCategoryMembers.php',
- 'ApiQueryContributions' => 'includes/api/ApiQueryUserContributions.php',
- 'ApiQueryDeletedrevs' => 'includes/api/ApiQueryDeletedrevs.php',
- 'ApiQueryExtLinksUsage' => 'includes/api/ApiQueryExtLinksUsage.php',
- 'ApiQueryExternalLinks' => 'includes/api/ApiQueryExternalLinks.php',
- 'ApiQueryGeneratorBase' => 'includes/api/ApiQueryBase.php',
- 'ApiQueryImageInfo' => 'includes/api/ApiQueryImageInfo.php',
- 'ApiQueryImages' => 'includes/api/ApiQueryImages.php',
- 'ApiQueryInfo' => 'includes/api/ApiQueryInfo.php',
- 'ApiQueryLangLinks' => 'includes/api/ApiQueryLangLinks.php',
- 'ApiQueryLinks' => 'includes/api/ApiQueryLinks.php',
- 'ApiQueryLogEvents' => 'includes/api/ApiQueryLogEvents.php',
- 'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
- 'ApiQueryRecentChanges'=> 'includes/api/ApiQueryRecentChanges.php',
- 'ApiQueryRevisions' => 'includes/api/ApiQueryRevisions.php',
- 'ApiQuerySearch' => 'includes/api/ApiQuerySearch.php',
- 'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php',
- 'ApiQueryUserInfo' => 'includes/api/ApiQueryUserInfo.php',
- 'ApiQueryUsers' => 'includes/api/ApiQueryUsers.php',
- 'ApiQueryWatchlist' => 'includes/api/ApiQueryWatchlist.php',
- 'ApiResult' => 'includes/api/ApiResult.php',
- 'ApiRollback' => 'includes/api/ApiRollback.php',
- 'ApiUnblock' => 'includes/api/ApiUnblock.php',
- 'ApiUndelete' => 'includes/api/ApiUndelete.php',
- 'Services_JSON' => 'includes/api/ApiFormatJson_json.php',
- 'Services_JSON_Error' => 'includes/api/ApiFormatJson_json.php',
- 'Spyc' => 'includes/api/ApiFormatYaml_spyc.php',
- 'UsageException' => 'includes/api/ApiMain.php',
- 'YAMLNode' => 'includes/api/ApiFormatYaml_spyc.php',
+ # includes/db
+ 'Blob' => 'includes/db/Database.php',
+ 'ChronologyProtector' => 'includes/db/LBFactory.php',
+ 'Database' => 'includes/db/Database.php',
+ 'DatabaseMssql' => 'includes/db/DatabaseMssql.php',
+ 'DatabaseMysql' => 'includes/db/Database.php',
+ 'DatabaseOracle' => 'includes/db/DatabaseOracle.php',
+ 'DatabasePostgres' => 'includes/db/DatabasePostgres.php',
+ 'DatabaseSqlite' => 'includes/db/DatabaseSqlite.php',
+ 'DBConnectionError' => 'includes/db/Database.php',
+ 'DBError' => 'includes/db/Database.php',
+ 'DBObject' => 'includes/db/Database.php',
+ 'DBQueryError' => 'includes/db/Database.php',
+ 'DBUnexpectedError' => 'includes/db/Database.php',
+ 'LBFactory' => 'includes/db/LBFactory.php',
+ 'LBFactory_Multi' => 'includes/db/LBFactory_Multi.php',
+ 'LBFactory_Simple' => 'includes/db/LBFactory.php',
+ 'LoadBalancer' => 'includes/db/LoadBalancer.php',
+ 'LoadMonitor' => 'includes/db/LoadMonitor.php',
+ 'LoadMonitor_MySQL' => 'includes/db/LoadMonitor.php',
+ 'MSSQLField' => 'includes/db/DatabaseMssql.php',
+ 'MySQLField' => 'includes/db/Database.php',
+ 'MySQLMasterPos' => 'includes/db/Database.php',
+ 'ORABlob' => 'includes/db/DatabaseOracle.php',
+ 'ORAResult' => 'includes/db/DatabaseOracle.php',
+ 'PostgresField' => 'includes/db/DatabasePostgres.php',
+ 'ResultWrapper' => 'includes/db/Database.php',
+ 'SQLiteField' => 'includes/db/DatabaseSqlite.php',
- # includes/db
- 'Blob' => 'includes/db/Database.php',
- 'ChronologyProtector' => 'includes/db/LBFactory.php',
- 'Database' => 'includes/db/Database.php',
- 'DatabaseMssql' => 'includes/db/DatabaseMssql.php',
- 'DatabaseMysql' => 'includes/db/Database.php',
- 'DatabaseOracle' => 'includes/db/DatabaseOracle.php',
- 'DatabasePostgres' => 'includes/db/DatabasePostgres.php',
- 'DatabaseSqlite' => 'includes/db/DatabaseSqlite.php',
- 'DBConnectionError' => 'includes/db/Database.php',
- 'DBError' => 'includes/db/Database.php',
- 'DBObject' => 'includes/db/Database.php',
- 'DBQueryError' => 'includes/db/Database.php',
- 'DBUnexpectedError' => 'includes/db/Database.php',
- 'LBFactory' => 'includes/db/LBFactory.php',
- 'LBFactory_Multi' => 'includes/db/LBFactory_Multi.php',
- 'LBFactory_Simple' => 'includes/db/LBFactory.php',
- 'LoadBalancer' => 'includes/db/LoadBalancer.php',
- 'LoadMonitor' => 'includes/db/LoadMonitor.php',
- 'LoadMonitor_MySQL' => 'includes/db/LoadMonitor.php',
- 'MSSQLField' => 'includes/db/DatabaseMssql.php',
- 'MySQLField' => 'includes/db/Database.php',
- 'MySQLMasterPos' => 'includes/db/Database.php',
- 'ORABlob' => 'includes/db/DatabaseOracle.php',
- 'ORAResult' => 'includes/db/DatabaseOracle.php',
- 'PostgresField' => 'includes/db/DatabasePostgres.php',
- 'ResultWrapper' => 'includes/db/Database.php',
- 'SQLiteField' => 'includes/db/DatabaseSqlite.php',
+ # includes/diff
+ 'AncestorComparator' => 'includes/diff/HTMLDiff.php',
+ 'AnchorToString' => 'includes/diff/HTMLDiff.php',
+ 'ArrayDiffFormatter' => 'includes/diff/DifferenceEngine.php',
+ 'BodyNode' => 'includes/diff/Nodes.php',
+ 'ChangeText' => 'includes/diff/HTMLDiff.php',
+ 'ChangeTextGenerator' => 'includes/diff/HTMLDiff.php',
+ 'DelegatingContentHandler' => 'includes/diff/HTMLDiff.php',
+ '_DiffEngine' => 'includes/diff/DifferenceEngine.php',
+ 'DifferenceEngine' => 'includes/diff/DifferenceEngine.php',
+ 'DiffFormatter' => 'includes/diff/DifferenceEngine.php',
+ 'Diff' => 'includes/diff/DifferenceEngine.php',
+ '_DiffOp_Add' => 'includes/diff/DifferenceEngine.php',
+ '_DiffOp_Change' => 'includes/diff/DifferenceEngine.php',
+ '_DiffOp_Copy' => 'includes/diff/DifferenceEngine.php',
+ '_DiffOp_Delete' => 'includes/diff/DifferenceEngine.php',
+ '_DiffOp' => 'includes/diff/DifferenceEngine.php',
+ 'DomTreeBuilder' => 'includes/diff/HTMLDiff.php',
+ 'DummyNode' => 'includes/diff/Nodes.php',
+ 'HTMLDiffer' => 'includes/diff/HTMLDiff.php',
+ 'HTMLOutput' => 'includes/diff/HTMLDiff.php',
+ '_HWLDF_WordAccumulator' => 'includes/diff/DifferenceEngine.php',
+ 'ImageNode' => 'includes/diff/Nodes.php',
+ 'LastCommonParentResult' => 'includes/diff/HTMLDiff.php',
+ 'MappedDiff' => 'includes/diff/DifferenceEngine.php',
+ 'Modification' => 'includes/diff/HTMLDiff.php',
+ 'NoContentTagToString' => 'includes/diff/HTMLDiff.php',
+ 'Node' => 'includes/diff/Nodes.php',
+ 'RangeDifference' => 'includes/diff/Diff.php',
+ 'TableDiffFormatter' => 'includes/diff/DifferenceEngine.php',
+ 'TagNode' => 'includes/diff/Nodes.php',
+ 'TagToString' => 'includes/diff/HTMLDiff.php',
+ 'TagToStringFactory' => 'includes/diff/HTMLDiff.php',
+ 'TextNode' => 'includes/diff/Nodes.php',
+ 'TextNodeDiffer' => 'includes/diff/HTMLDiff.php',
+ 'TextOnlyComparator' => 'includes/diff/HTMLDiff.php',
+ 'UnifiedDiffFormatter' => 'includes/diff/DifferenceEngine.php',
+ 'WhiteSpaceNode' => 'includes/diff/Nodes.php',
+ 'WikiDiff3' => 'includes/diff/Diff.php',
+ 'WordLevelDiff' => 'includes/diff/DifferenceEngine.php',
- # includes/filerepo
- 'ArchivedFile' => 'includes/filerepo/ArchivedFile.php',
- 'File' => 'includes/filerepo/File.php',
- 'FileRepo' => 'includes/filerepo/FileRepo.php',
- 'FileRepoStatus' => 'includes/filerepo/FileRepoStatus.php',
- 'ForeignAPIFile' => 'includes/filerepo/ForeignAPIFile.php',
- 'ForeignAPIRepo' => 'includes/filerepo/ForeignAPIRepo.php',
- 'ForeignDBFile' => 'includes/filerepo/ForeignDBFile.php',
- 'ForeignDBRepo' => 'includes/filerepo/ForeignDBRepo.php',
- 'ForeignDBViaLBRepo' => 'includes/filerepo/ForeignDBViaLBRepo.php',
- 'FSRepo' => 'includes/filerepo/FSRepo.php',
- 'Image' => 'includes/filerepo/Image.php',
- 'LocalFile' => 'includes/filerepo/LocalFile.php',
- 'LocalFileDeleteBatch' => 'includes/filerepo/LocalFile.php',
- 'LocalFileMoveBatch' => 'includes/filerepo/LocalFile.php',
- 'LocalFileRestoreBatch' => 'includes/filerepo/LocalFile.php',
- 'LocalRepo' => 'includes/filerepo/LocalRepo.php',
- 'OldLocalFile' => 'includes/filerepo/OldLocalFile.php',
- 'RepoGroup' => 'includes/filerepo/RepoGroup.php',
- 'UnregisteredLocalFile' => 'includes/filerepo/UnregisteredLocalFile.php',
+ # includes/filerepo
+ 'ArchivedFile' => 'includes/filerepo/ArchivedFile.php',
+ 'File' => 'includes/filerepo/File.php',
+ 'FileCache' => 'includes/filerepo/FileCache.php',
+ 'FileRepo' => 'includes/filerepo/FileRepo.php',
+ 'FileRepoStatus' => 'includes/filerepo/FileRepoStatus.php',
+ 'ForeignAPIFile' => 'includes/filerepo/ForeignAPIFile.php',
+ 'ForeignAPIRepo' => 'includes/filerepo/ForeignAPIRepo.php',
+ 'ForeignDBFile' => 'includes/filerepo/ForeignDBFile.php',
+ 'ForeignDBRepo' => 'includes/filerepo/ForeignDBRepo.php',
+ 'ForeignDBViaLBRepo' => 'includes/filerepo/ForeignDBViaLBRepo.php',
+ 'FSRepo' => 'includes/filerepo/FSRepo.php',
+ 'Image' => 'includes/filerepo/Image.php',
+ 'LocalFile' => 'includes/filerepo/LocalFile.php',
+ 'LocalFileDeleteBatch' => 'includes/filerepo/LocalFile.php',
+ 'LocalFileMoveBatch' => 'includes/filerepo/LocalFile.php',
+ 'LocalFileRestoreBatch' => 'includes/filerepo/LocalFile.php',
+ 'LocalRepo' => 'includes/filerepo/LocalRepo.php',
+ 'OldLocalFile' => 'includes/filerepo/OldLocalFile.php',
+ 'RepoGroup' => 'includes/filerepo/RepoGroup.php',
+ 'UnregisteredLocalFile' => 'includes/filerepo/UnregisteredLocalFile.php',
- # includes/media
- 'BitmapHandler' => 'includes/media/Bitmap.php',
- 'BmpHandler' => 'includes/media/BMP.php',
- 'DjVuHandler' => 'includes/media/DjVu.php',
- 'ImageHandler' => 'includes/media/Generic.php',
- 'MediaHandler' => 'includes/media/Generic.php',
- 'SvgHandler' => 'includes/media/SVG.php',
+ # includes/media
+ 'BitmapHandler' => 'includes/media/Bitmap.php',
+ 'BitmapHandler_ClientOnly' => 'includes/media/Bitmap_ClientOnly.php',
+ 'BmpHandler' => 'includes/media/BMP.php',
+ 'DjVuHandler' => 'includes/media/DjVu.php',
+ 'ImageHandler' => 'includes/media/Generic.php',
+ 'MediaHandler' => 'includes/media/Generic.php',
+ 'SvgHandler' => 'includes/media/SVG.php',
- # includes/normal
- 'UtfNormal' => 'includes/normal/UtfNormal.php',
+ # includes/normal
+ 'UtfNormal' => 'includes/normal/UtfNormal.php',
- # includes/parser
- 'CoreParserFunctions' => 'includes/parser/CoreParserFunctions.php',
- 'DateFormatter' => 'includes/parser/DateFormatter.php',
- 'OnlyIncludeReplacer' => 'includes/parser/Parser.php',
- 'PPDAccum_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDPart' => 'includes/parser/Preprocessor_DOM.php',
- 'PPDPart_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDStack' => 'includes/parser/Preprocessor_DOM.php',
- 'PPDStackElement' => 'includes/parser/Preprocessor_DOM.php',
- 'PPDStackElement_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPDStack_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPFrame' => 'includes/parser/Preprocessor.php',
- 'PPFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
- 'PPFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'PPNode' => 'includes/parser/Preprocessor.php',
- 'PPNode_DOM' => 'includes/parser/Preprocessor_DOM.php',
- 'PPNode_Hash_Array' => 'includes/parser/Preprocessor_Hash.php',
- 'PPNode_Hash_Attr' => 'includes/parser/Preprocessor_Hash.php',
- 'PPNode_Hash_Text' => 'includes/parser/Preprocessor_Hash.php',
- 'PPNode_Hash_Tree' => 'includes/parser/Preprocessor_Hash.php',
- 'PPTemplateFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
- 'PPTemplateFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'Parser' => 'includes/parser/Parser.php',
- 'ParserCache' => 'includes/parser/ParserCache.php',
- 'ParserOptions' => 'includes/parser/ParserOptions.php',
- 'ParserOutput' => 'includes/parser/ParserOutput.php',
- 'Parser_DiffTest' => 'includes/parser/Parser_DiffTest.php',
- 'Parser_OldPP' => 'includes/parser/Parser_OldPP.php',
- 'Preprocessor' => 'includes/parser/Preprocessor.php',
- 'Preprocessor_DOM' => 'includes/parser/Preprocessor_DOM.php',
- 'Preprocessor_Hash' => 'includes/parser/Preprocessor_Hash.php',
- 'StripState' => 'includes/parser/Parser.php',
+ # includes/parser
+ 'CoreLinkFunctions' => 'includes/parser/CoreLinkFunctions.php',
+ 'CoreParserFunctions' => 'includes/parser/CoreParserFunctions.php',
+ 'DateFormatter' => 'includes/parser/DateFormatter.php',
+ 'LinkHolderArray' => 'includes/parser/LinkHolderArray.php',
+ 'LinkMarkerReplacer' => 'includes/parser/LinkMarkerReplacer.php',
+ 'OnlyIncludeReplacer' => 'includes/parser/Parser.php',
+ 'PPDAccum_Hash' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPDPart' => 'includes/parser/Preprocessor_DOM.php',
+ 'PPDPart_Hash' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPDStack' => 'includes/parser/Preprocessor_DOM.php',
+ 'PPDStackElement' => 'includes/parser/Preprocessor_DOM.php',
+ 'PPDStackElement_Hash' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPDStack_Hash' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPFrame' => 'includes/parser/Preprocessor.php',
+ 'PPFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
+ 'PPFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPNode' => 'includes/parser/Preprocessor.php',
+ 'PPNode_DOM' => 'includes/parser/Preprocessor_DOM.php',
+ 'PPNode_Hash_Array' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPNode_Hash_Attr' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPNode_Hash_Text' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPNode_Hash_Tree' => 'includes/parser/Preprocessor_Hash.php',
+ 'PPTemplateFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
+ 'PPTemplateFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
+ 'Parser' => 'includes/parser/Parser.php',
+ 'ParserCache' => 'includes/parser/ParserCache.php',
+ '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',
+ 'StripState' => 'includes/parser/Parser.php',
- # includes/specials
- 'AncientPagesPage' => 'includes/specials/SpecialAncientpages.php',
- 'BrokenRedirectsPage' => 'includes/specials/SpecialBrokenRedirects.php',
- 'ContribsPager' => 'includes/specials/SpecialContributions.php',
- 'DBLockForm' => 'includes/specials/SpecialLockdb.php',
- 'DBUnlockForm' => 'includes/specials/SpecialUnlockdb.php',
- 'DeadendPagesPage' => 'includes/specials/SpecialDeadendpages.php',
- 'DisambiguationsPage' => 'includes/specials/SpecialDisambiguations.php',
- 'DoubleRedirectsPage' => 'includes/specials/SpecialDoubleRedirects.php',
- 'EmailConfirmation' => 'includes/specials/SpecialConfirmemail.php',
- 'EmailInvalidation' => 'includes/specials/SpecialConfirmemail.php',
- 'EmailUserForm' => 'includes/specials/SpecialEmailuser.php',
- 'FewestrevisionsPage' => 'includes/specials/SpecialFewestrevisions.php',
- 'FileDuplicateSearchPage' => 'includes/specials/SpecialFileDuplicateSearch.php',
- 'IPBlockForm' => 'includes/specials/SpecialBlockip.php',
- 'IPBlocklistPager' => 'includes/specials/SpecialIpblocklist.php',
- 'IPUnblockForm' => 'includes/specials/SpecialIpblocklist.php',
- 'ImportReporter' => 'includes/specials/SpecialImport.php',
- 'ImportStreamSource' => 'includes/specials/SpecialImport.php',
- 'ImportStringSource' => 'includes/specials/SpecialImport.php',
- 'ListredirectsPage' => 'includes/specials/SpecialListredirects.php',
- 'LoginForm' => 'includes/specials/SpecialUserlogin.php',
- 'LonelyPagesPage' => 'includes/specials/SpecialLonelypages.php',
- 'LongPagesPage' => 'includes/specials/SpecialLongpages.php',
- 'MIMEsearchPage' => 'includes/specials/SpecialMIMEsearch.php',
- 'MostcategoriesPage' => 'includes/specials/SpecialMostcategories.php',
- 'MostimagesPage' => 'includes/specials/SpecialMostimages.php',
- 'MostlinkedCategoriesPage' => 'includes/specials/SpecialMostlinkedcategories.php',
- 'MostlinkedPage' => 'includes/specials/SpecialMostlinked.php',
- 'MostrevisionsPage' => 'includes/specials/SpecialMostrevisions.php',
- 'MovePageForm' => 'includes/specials/SpecialMovepage.php',
- 'SpecialNewpages' => 'includes/specials/SpecialNewpages.php',
- 'NewPagesPager' => 'includes/specials/SpecialNewpages.php',
- 'PageArchive' => 'includes/specials/SpecialUndelete.php',
- 'PasswordResetForm' => 'includes/specials/SpecialResetpass.php',
- 'PopularPagesPage' => 'includes/specials/SpecialPopularpages.php',
- 'PreferencesForm' => 'includes/specials/SpecialPreferences.php',
- 'RandomPage' => 'includes/specials/SpecialRandompage.php',
- 'RevisionDeleteForm' => 'includes/specials/SpecialRevisiondelete.php',
- 'RevisionDeleter' => 'includes/specials/SpecialRevisiondelete.php',
- 'ShortPagesPage' => 'includes/specials/SpecialShortpages.php',
- 'SpecialAllpages' => 'includes/specials/SpecialAllpages.php',
- 'SpecialBookSources' => 'includes/specials/SpecialBooksources.php',
- 'SpecialListGroupRights' => 'includes/specials/SpecialListgrouprights.php',
- 'SpecialMostlinkedtemplates' => 'includes/specials/SpecialMostlinkedtemplates.php',
- 'SpecialPrefixindex' => 'includes/specials/SpecialPrefixindex.php',
- 'SpecialRandomredirect' => 'includes/specials/SpecialRandomredirect.php',
- 'SpecialRecentchanges' => 'includes/specials/SpecialRecentchanges.php',
- 'SpecialRecentchangeslinked' => 'includes/specials/SpecialRecentchangeslinked.php',
- 'SpecialSearch' => 'includes/specials/SpecialSearch.php',
- 'SpecialVersion' => 'includes/specials/SpecialVersion.php',
- 'UncategorizedCategoriesPage' => 'includes/specials/SpecialUncategorizedcategories.php',
- 'UncategorizedPagesPage' => 'includes/specials/SpecialUncategorizedpages.php',
- 'UncategorizedTemplatesPage' => 'includes/specials/SpecialUncategorizedtemplates.php',
- 'UndeleteForm' => 'includes/specials/SpecialUndelete.php',
- 'UnusedCategoriesPage' => 'includes/specials/SpecialUnusedcategories.php',
- 'UnusedimagesPage' => 'includes/specials/SpecialUnusedimages.php',
- 'UnusedtemplatesPage' => 'includes/specials/SpecialUnusedtemplates.php',
- 'UnwatchedpagesPage' => 'includes/specials/SpecialUnwatchedpages.php',
- 'UploadForm' => 'includes/specials/SpecialUpload.php',
- 'UploadFormMogile' => 'includes/specials/SpecialUploadMogile.php',
- 'UserrightsPage' => 'includes/specials/SpecialUserrights.php',
- 'UsersPager' => 'includes/specials/SpecialListusers.php',
- 'WantedCategoriesPage' => 'includes/specials/SpecialWantedcategories.php',
- 'WantedPagesPage' => 'includes/specials/SpecialWantedpages.php',
- 'WhatLinksHerePage' => 'includes/specials/SpecialWhatlinkshere.php',
- 'WikiImporter' => 'includes/specials/SpecialImport.php',
- 'WikiRevision' => 'includes/specials/SpecialImport.php',
- 'WithoutInterwikiPage' => 'includes/specials/SpecialWithoutinterwiki.php',
+ # includes/specials
+ 'AncientPagesPage' => 'includes/specials/SpecialAncientpages.php',
+ 'BrokenRedirectsPage' => 'includes/specials/SpecialBrokenRedirects.php',
+ 'ContribsPager' => 'includes/specials/SpecialContributions.php',
+ 'DBLockForm' => 'includes/specials/SpecialLockdb.php',
+ 'DBUnlockForm' => 'includes/specials/SpecialUnlockdb.php',
+ 'DeadendPagesPage' => 'includes/specials/SpecialDeadendpages.php',
+ 'DeletedContributionsPage' => 'includes/specials/SpecialDeletedContributions.php',
+ 'DeletedContribsPager' => 'includes/specials/SpecialDeletedContributions.php',
+ 'DisambiguationsPage' => 'includes/specials/SpecialDisambiguations.php',
+ 'DoubleRedirectsPage' => 'includes/specials/SpecialDoubleRedirects.php',
+ 'EmailConfirmation' => 'includes/specials/SpecialConfirmemail.php',
+ 'EmailInvalidation' => 'includes/specials/SpecialConfirmemail.php',
+ 'EmailUserForm' => 'includes/specials/SpecialEmailuser.php',
+ 'FewestrevisionsPage' => 'includes/specials/SpecialFewestrevisions.php',
+ 'FileDuplicateSearchPage' => 'includes/specials/SpecialFileDuplicateSearch.php',
+ 'IPBlockForm' => 'includes/specials/SpecialBlockip.php',
+ 'IPBlocklistPager' => 'includes/specials/SpecialIpblocklist.php',
+ 'IPUnblockForm' => 'includes/specials/SpecialIpblocklist.php',
+ 'ImportReporter' => 'includes/specials/SpecialImport.php',
+ 'ImportStreamSource' => 'includes/Import.php',
+ 'ImportStringSource' => 'includes/Import.php',
+ 'LinkSearchPage' => 'includes/specials/SpecialLinkSearch.php',
+ 'ListredirectsPage' => 'includes/specials/SpecialListredirects.php',
+ 'LoginForm' => 'includes/specials/SpecialUserlogin.php',
+ 'LonelyPagesPage' => 'includes/specials/SpecialLonelypages.php',
+ 'LongPagesPage' => 'includes/specials/SpecialLongpages.php',
+ 'MIMEsearchPage' => 'includes/specials/SpecialMIMEsearch.php',
+ 'MostcategoriesPage' => 'includes/specials/SpecialMostcategories.php',
+ 'MostimagesPage' => 'includes/specials/SpecialMostimages.php',
+ 'MostlinkedCategoriesPage' => 'includes/specials/SpecialMostlinkedcategories.php',
+ 'MostlinkedPage' => 'includes/specials/SpecialMostlinked.php',
+ 'MostrevisionsPage' => 'includes/specials/SpecialMostrevisions.php',
+ 'MovePageForm' => 'includes/specials/SpecialMovepage.php',
+ 'SpecialNewpages' => 'includes/specials/SpecialNewpages.php',
+ 'SpecialContributions' => 'includes/specials/SpecialContributions.php',
+ 'NewPagesPager' => 'includes/specials/SpecialNewpages.php',
+ 'PageArchive' => 'includes/specials/SpecialUndelete.php',
+ 'SpecialResetpass' => 'includes/specials/SpecialResetpass.php',
+ 'PopularPagesPage' => 'includes/specials/SpecialPopularpages.php',
+ 'PreferencesForm' => 'includes/specials/SpecialPreferences.php',
+ 'RandomPage' => 'includes/specials/SpecialRandompage.php',
+ 'RevisionDeleteForm' => 'includes/specials/SpecialRevisiondelete.php',
+ 'RevisionDeleter' => 'includes/specials/SpecialRevisiondelete.php',
+ 'ShortPagesPage' => 'includes/specials/SpecialShortpages.php',
+ 'SpecialAllpages' => 'includes/specials/SpecialAllpages.php',
+ 'SpecialBookSources' => 'includes/specials/SpecialBooksources.php',
+ 'SpecialImport' => 'includes/specials/SpecialImport.php',
+ 'SpecialListGroupRights' => 'includes/specials/SpecialListgrouprights.php',
+ 'SpecialMostlinkedtemplates' => 'includes/specials/SpecialMostlinkedtemplates.php',
+ 'SpecialPrefixindex' => 'includes/specials/SpecialPrefixindex.php',
+ 'SpecialRandomredirect' => 'includes/specials/SpecialRandomredirect.php',
+ 'SpecialRecentchanges' => 'includes/specials/SpecialRecentchanges.php',
+ 'SpecialRecentchangeslinked' => 'includes/specials/SpecialRecentchangeslinked.php',
+ 'SpecialSearch' => 'includes/specials/SpecialSearch.php',
+ 'SpecialSearchOld' => 'includes/specials/SpecialSearch.php',
+ 'SpecialStatistics' => 'includes/specials/SpecialStatistics.php',
+ 'SpecialVersion' => 'includes/specials/SpecialVersion.php',
+ 'UncategorizedCategoriesPage' => 'includes/specials/SpecialUncategorizedcategories.php',
+ 'UncategorizedPagesPage' => 'includes/specials/SpecialUncategorizedpages.php',
+ 'UncategorizedTemplatesPage' => 'includes/specials/SpecialUncategorizedtemplates.php',
+ 'UndeleteForm' => 'includes/specials/SpecialUndelete.php',
+ 'UnusedCategoriesPage' => 'includes/specials/SpecialUnusedcategories.php',
+ 'UnusedimagesPage' => 'includes/specials/SpecialUnusedimages.php',
+ 'UnusedtemplatesPage' => 'includes/specials/SpecialUnusedtemplates.php',
+ 'UnwatchedpagesPage' => 'includes/specials/SpecialUnwatchedpages.php',
+ 'UploadForm' => 'includes/specials/SpecialUpload.php',
+ 'UploadFormMogile' => 'includes/specials/SpecialUploadMogile.php',
+ 'UserrightsPage' => 'includes/specials/SpecialUserrights.php',
+ 'UsersPager' => 'includes/specials/SpecialListusers.php',
+ 'WantedCategoriesPage' => 'includes/specials/SpecialWantedcategories.php',
+ 'WantedFilesPage' => 'includes/specials/SpecialWantedfiles.php',
+ 'WantedPagesPage' => 'includes/specials/SpecialWantedpages.php',
+ 'WantedTemplatesPage' => 'includes/specials/SpecialWantedtemplates.php',
+ 'WhatLinksHerePage' => 'includes/specials/SpecialWhatlinkshere.php',
+ 'WikiImporter' => 'includes/Import.php',
+ 'WikiRevision' => 'includes/Import.php',
+ 'WithoutInterwikiPage' => 'includes/specials/SpecialWithoutinterwiki.php',
- # includes/templates
- 'UsercreateTemplate' => 'includes/templates/Userlogin.php',
- 'UserloginTemplate' => 'includes/templates/Userlogin.php',
+ # includes/templates
+ 'UsercreateTemplate' => 'includes/templates/Userlogin.php',
+ 'UserloginTemplate' => 'includes/templates/Userlogin.php',
- # languages
- 'Language' => 'languages/Language.php',
- 'FakeConverter' => 'languages/Language.php',
+ # languages
+ 'Language' => 'languages/Language.php',
+ 'FakeConverter' => 'languages/Language.php',
- # maintenance/language
- 'statsOutput' => 'maintenance/language/StatOutputs.php',
- 'wikiStatsOutput' => 'maintenance/language/StatOutputs.php',
- 'metawikiStatsOutput' => 'maintenance/language/StatOutputs.php',
- 'textStatsOutput' => 'maintenance/language/StatOutputs.php',
- 'csvStatsOutput' => 'maintenance/language/StatOutputs.php',
+ # maintenance/language
+ 'statsOutput' => 'maintenance/language/StatOutputs.php',
+ 'wikiStatsOutput' => 'maintenance/language/StatOutputs.php',
+ 'metawikiStatsOutput' => 'maintenance/language/StatOutputs.php',
+ 'textStatsOutput' => 'maintenance/language/StatOutputs.php',
+ 'csvStatsOutput' => 'maintenance/language/StatOutputs.php',
- );
+);
+class AutoLoader {
/**
* autoload - take a class name and attempt to load it
- *
+ *
* @param string $className Name of class we're looking for.
* @return bool Returning false is important on failure as
* it allows Zend to try and look in other registered autoloaders
- * as well.
+ * as well.
*/
static function autoload( $className ) {
- global $wgAutoloadClasses;
+ global $wgAutoloadClasses, $wgAutoloadLocalClasses;
- wfProfileIn( __METHOD__ );
- if ( isset( self::$localClasses[$className] ) ) {
- $filename = self::$localClasses[$className];
+ if ( isset( $wgAutoloadLocalClasses[$className] ) ) {
+ $filename = $wgAutoloadLocalClasses[$className];
} elseif ( isset( $wgAutoloadClasses[$className] ) ) {
$filename = $wgAutoloadClasses[$className];
} else {
@@ -488,14 +549,15 @@ class AutoLoader {
# The case can sometimes be wrong when unserializing PHP 4 objects
$filename = false;
$lowerClass = strtolower( $className );
- foreach ( self::$localClasses as $class2 => $file2 ) {
+ foreach ( $wgAutoloadLocalClasses as $class2 => $file2 ) {
if ( strtolower( $class2 ) == $lowerClass ) {
$filename = $file2;
}
}
if ( !$filename ) {
+ if( function_exists( 'wfDebug' ) )
+ wfDebug( "Class {$className} not found; skipped loading" );
# Give up
- wfProfileOut( __METHOD__ );
return false;
}
}
@@ -506,7 +568,6 @@ class AutoLoader {
$filename = "$IP/$filename";
}
require( $filename );
- wfProfileOut( __METHOD__ );
return true;
}
@@ -532,4 +593,3 @@ if ( function_exists( 'spl_autoload_register' ) ) {
AutoLoader::autoload( $class );
}
}
-
diff --git a/includes/Autopromote.php b/includes/Autopromote.php
index 68fe6636..c8a4c03b 100644
--- a/includes/Autopromote.php
+++ b/includes/Autopromote.php
@@ -19,7 +19,7 @@ class Autopromote {
$promote[] = $group;
}
- wfRunHooks( 'GetAutoPromoteGroups', array($user, &$promote) );
+ wfRunHooks( 'GetAutoPromoteGroups', array( $user, &$promote ) );
return $promote;
}
@@ -106,9 +106,16 @@ class Autopromote {
case APCOND_AGE:
$age = time() - wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
return $age >= $cond[1];
+ case APCOND_AGE_FROM_EDIT:
+ $age = time() - wfTimestampOrNull( TS_UNIX, $user->getFirstEditTimestamp() );
+ return $age >= $cond[1];
case APCOND_INGROUPS:
$groups = array_slice( $cond, 1 );
return count( array_intersect( $groups, $user->getGroups() ) ) == count( $groups );
+ case APCOND_ISIP:
+ return $cond[1] == wfGetIP();
+ case APCOND_IPINRANGE:
+ return IP::isInRange( wfGetIP(), $cond[1] );
default:
$result = null;
wfRunHooks( 'AutopromoteCondition', array( $cond[0], array_slice( $cond, 1 ), $user, &$result ) );
diff --git a/includes/BagOStuff.php b/includes/BagOStuff.php
index 92311329..572dca6c 100644
--- a/includes/BagOStuff.php
+++ b/includes/BagOStuff.php
@@ -475,8 +475,19 @@ class MediaWikiBagOStuff extends SqlBagOStuff {
function _fromunixtime($ts) {
return $this->_getDB()->timestamp($ts);
}
+ /***
+ * Note -- this should *not* check wfReadOnly().
+ * Read-only mode has been repurposed from the original
+ * "nothing must write to the database" to "users should not
+ * be able to edit or alter anything user-visible".
+ *
+ * Backend bits like the object cache should continue
+ * to work in this mode, otherwise things will blow up
+ * like the message cache failing to save its state,
+ * causing long delays (bug 11533).
+ */
function _readonly(){
- return wfReadOnly();
+ return false;
}
function _strencode($s) {
return $this->_getDB()->strencode($s);
diff --git a/includes/Block.php b/includes/Block.php
index b208fa8a..2c2227e2 100644
--- a/includes/Block.php
+++ b/includes/Block.php
@@ -13,11 +13,10 @@
*
* @todo This could be used everywhere, but it isn't.
*/
-class Block
-{
+class Block {
/* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry,
$mRangeStart, $mRangeEnd, $mAnonOnly, $mEnableAutoblock, $mHideName,
- $mBlockEmail, $mByName, $mAngryAutoblock;
+ $mBlockEmail, $mByName, $mAngryAutoblock, $mAllowUsertalk;
/* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate, $mFromMaster;
const EB_KEEP_EXPIRED = 1;
@@ -26,7 +25,7 @@ class Block
function __construct( $address = '', $user = 0, $by = 0, $reason = '',
$timestamp = '' , $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
- $hideName = 0, $blockEmail = 0 )
+ $hideName = 0, $blockEmail = 0, $allowUsertalk = 0 )
{
$this->mId = 0;
# Expand valid IPv6 addresses
@@ -43,6 +42,7 @@ class Block
$this->mEnableAutoblock = $enableAutoblock;
$this->mHideName = $hideName;
$this->mBlockEmail = $blockEmail;
+ $this->mAllowUsertalk = $allowUsertalk;
$this->mForUpdate = false;
$this->mFromMaster = false;
$this->mByName = false;
@@ -50,9 +50,18 @@ class Block
$this->initialiseRange();
}
- static function newFromDB( $address, $user = 0, $killExpired = true )
- {
- $block = new Block();
+ /**
+ * Load a block from the database, using either the IP address or
+ * user ID. Tries the user ID first, and if that doesn't work, tries
+ * the address.
+ *
+ * @param $address String: IP address of user/anon
+ * @param $user Integer: user id of user
+ * @param $killExpired Boolean: delete expired blocks on load
+ * @return Block Object
+ */
+ public static function newFromDB( $address, $user = 0, $killExpired = true ) {
+ $block = new Block;
$block->load( $address, $user, $killExpired );
if ( $block->isValid() ) {
return $block;
@@ -61,8 +70,13 @@ class Block
}
}
- static function newFromID( $id )
- {
+ /**
+ * Load a blocked user from their block id.
+ *
+ * @param $id Integer: Block id to search for
+ * @return Block object
+ */
+ public static function newFromID( $id ) {
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->resultObject( $dbr->select( 'ipblocks', '*',
array( 'ipb_id' => $id ), __METHOD__ ) );
@@ -73,21 +87,47 @@ class Block
return null;
}
}
+
+ /**
+ * Check if two blocks are effectively equal
+ *
+ * @return Boolean
+ */
+ public function equals( Block $block ) {
+ return (
+ $this->mAddress == $block->mAddress
+ && $this->mUser == $block->mUser
+ && $this->mAuto == $block->mAuto
+ && $this->mAnonOnly == $block->mAnonOnly
+ && $this->mCreateAccount == $block->mCreateAccount
+ && $this->mExpiry == $block->mExpiry
+ && $this->mEnableAutoblock == $block->mEnableAutoblock
+ && $this->mHideName == $block->mHideName
+ && $this->mBlockEmail == $block->mBlockEmail
+ && $this->mAllowUsertalk == $block->mAllowUsertalk
+ );
+ }
- function clear()
- {
+ /**
+ * Clear all member variables in the current object. Does not clear
+ * the block from the DB.
+ */
+ public function clear() {
$this->mAddress = $this->mReason = $this->mTimestamp = '';
$this->mId = $this->mAnonOnly = $this->mCreateAccount =
$this->mEnableAutoblock = $this->mAuto = $this->mUser =
- $this->mBy = $this->mHideName = $this->mBlockEmail = 0;
+ $this->mBy = $this->mHideName = $this->mBlockEmail = $this->mAllowUsertalk = 0;
$this->mByName = false;
}
/**
- * Get the DB object and set the reference parameter to the query options
+ * Get the DB object and set the reference parameter to the select options.
+ * The options array will contain FOR UPDATE if appropriate.
+ *
+ * @param $options Array
+ * @return Database
*/
- function &getDBOptions( &$options )
- {
+ protected function &getDBOptions( &$options ) {
global $wgAntiLockFlags;
if ( $this->mForUpdate || $this->mFromMaster ) {
$db = wfGetDB( DB_MASTER );
@@ -104,15 +144,15 @@ class Block
}
/**
- * Get a ban from the DB, with either the given address or the given username
+ * Get a block from the DB, with either the given address or the given username
*
- * @param string $address The IP address of the user, or blank to skip IP blocks
- * @param integer $user The user ID, or zero for anonymous users
- * @param bool $killExpired Whether to delete expired rows while loading
+ * @param $address string The IP address of the user, or blank to skip IP blocks
+ * @param $user int The user ID, or zero for anonymous users
+ * @param $killExpired bool Whether to delete expired rows while loading
+ * @return Boolean: the user is blocked from editing
*
*/
- function load( $address = '', $user = 0, $killExpired = true )
- {
+ public function load( $address = '', $user = 0, $killExpired = true ) {
wfDebug( "Block::load: '$address', '$user', $killExpired\n" );
$options = array();
@@ -143,7 +183,10 @@ class Block
if ( $user && $this->mAnonOnly ) {
# Block is marked anon-only
# Whitelist this IP address against autoblocks and range blocks
- $this->clear();
+ # (but not account creation blocks -- bug 13611)
+ if( !$this->mCreateAccount ) {
+ $this->clear();
+ }
return false;
} else {
return true;
@@ -154,7 +197,10 @@ class Block
# Try range block
if ( $this->loadRange( $address, $killExpired, $user ) ) {
if ( $user && $this->mAnonOnly ) {
- $this->clear();
+ # Respect account creation blocks on logged-in users -- bug 13611
+ if( !$this->mCreateAccount ) {
+ $this->clear();
+ }
return false;
} else {
return true;
@@ -180,9 +226,12 @@ class Block
/**
* Fill in member variables from a result wrapper
+ *
+ * @param $res ResultWrapper: row from the ipblocks table
+ * @param $killExpired Boolean: whether to delete expired rows while loading
+ * @return Boolean
*/
- function loadFromResult( ResultWrapper $res, $killExpired = true )
- {
+ protected function loadFromResult( ResultWrapper $res, $killExpired = true ) {
$ret = false;
if ( 0 != $res->numRows() ) {
# Get first block
@@ -216,9 +265,13 @@ class Block
/**
* Search the database for any range blocks matching the given address, and
* load the row if one is found.
+ *
+ * @param $address String: IP address range
+ * @param $killExpired Boolean: whether to delete expired rows while loading
+ * @param $userid Integer: if not 0, then sets ipb_anon_only
+ * @return Boolean
*/
- function loadRange( $address, $killExpired = true, $user = 0 )
- {
+ public function loadRange( $address, $killExpired = true, $user = 0 ) {
$iaddr = IP::toHex( $address );
if ( $iaddr === false ) {
# Invalid address
@@ -247,15 +300,12 @@ class Block
}
/**
- * Determine if a given integer IPv4 address is in a given CIDR network
- * @deprecated Use IP::isInRange
+ * Given a database row from the ipblocks table, initialize
+ * member variables
+ *
+ * @param $row ResultWrapper: a row from the ipblocks table
*/
- function isAddressInRange( $addr, $range ) {
- return IP::isInRange( $addr, $range );
- }
-
- function initFromRow( $row )
- {
+ public function initFromRow( $row ) {
$this->mAddress = $row->ipb_address;
$this->mReason = $row->ipb_reason;
$this->mTimestamp = wfTimestamp(TS_MW,$row->ipb_timestamp);
@@ -266,6 +316,7 @@ class Block
$this->mCreateAccount = $row->ipb_create_account;
$this->mEnableAutoblock = $row->ipb_enable_autoblock;
$this->mBlockEmail = $row->ipb_block_email;
+ $this->mAllowUsertalk = $row->ipb_allow_usertalk;
$this->mHideName = $row->ipb_deleted;
$this->mId = $row->ipb_id;
$this->mExpiry = self::decodeExpiry( $row->ipb_expiry );
@@ -278,8 +329,11 @@ class Block
$this->mRangeEnd = $row->ipb_range_end;
}
- function initialiseRange()
- {
+ /**
+ * Once $mAddress has been set, get the range they came from.
+ * Wrapper for IP::parseRange
+ */
+ protected function initialiseRange() {
$this->mRangeStart = '';
$this->mRangeEnd = '';
@@ -289,64 +343,12 @@ class Block
}
/**
- * Callback with a Block object for every block
- * @return integer number of blocks;
+ * Delete the row from the IP blocks table.
+ *
+ * @return Boolean
*/
- /*static*/ function enumBlocks( $callback, $tag, $flags = 0 )
- {
- global $wgAntiLockFlags;
-
- $block = new Block();
- if ( $flags & Block::EB_FOR_UPDATE ) {
- $db = wfGetDB( DB_MASTER );
- if ( $wgAntiLockFlags & ALF_NO_BLOCK_LOCK ) {
- $options = '';
- } else {
- $options = 'FOR UPDATE';
- }
- $block->forUpdate( true );
- } else {
- $db = wfGetDB( DB_SLAVE );
- $options = '';
- }
- if ( $flags & Block::EB_RANGE_ONLY ) {
- $cond = " AND ipb_range_start <> ''";
- } else {
- $cond = '';
- }
-
- $now = wfTimestampNow();
-
- list( $ipblocks, $user ) = $db->tableNamesN( 'ipblocks', 'user' );
-
- $sql = "SELECT $ipblocks.*,user_name FROM $ipblocks,$user " .
- "WHERE user_id=ipb_by $cond ORDER BY ipb_timestamp DESC $options";
- $res = $db->query( $sql, 'Block::enumBlocks' );
- $num_rows = $db->numRows( $res );
-
- while ( $row = $db->fetchObject( $res ) ) {
- $block->initFromRow( $row );
- if ( ( $flags & Block::EB_RANGE_ONLY ) && $block->mRangeStart == '' ) {
- continue;
- }
-
- if ( !( $flags & Block::EB_KEEP_EXPIRED ) ) {
- if ( $block->mExpiry && $now > $block->mExpiry ) {
- $block->delete();
- } else {
- call_user_func( $callback, $block, $tag );
- }
- } else {
- call_user_func( $callback, $block, $tag );
- }
- }
- $db->freeResult( $res );
- return $num_rows;
- }
-
- function delete()
- {
- if (wfReadOnly()) {
+ public function delete() {
+ if ( wfReadOnly() ) {
return false;
}
if ( !$this->mId ) {
@@ -359,33 +361,17 @@ class Block
}
/**
- * Insert a block into the block table.
- * @return Whether or not the insertion was successful.
- */
- function insert()
- {
+ * Insert a block into the block table. Will fail if there is a conflicting
+ * block (same name and options) already in the database.
+ *
+ * @return Boolean: whether or not the insertion was successful.
+ */
+ public function insert() {
wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
$dbw = wfGetDB( DB_MASTER );
- # Unset ipb_anon_only for user blocks, makes no sense
- if ( $this->mUser ) {
- $this->mAnonOnly = 0;
- }
-
- # Unset ipb_enable_autoblock for IP blocks, makes no sense
- if ( !$this->mUser ) {
- $this->mEnableAutoblock = 0;
- $this->mBlockEmail = 0; //Same goes for email...
- }
-
- if( !$this->mByName ) {
- if( $this->mBy ) {
- $this->mByName = User::whoIs( $this->mBy );
- } else {
- global $wgUser;
- $this->mByName = $wgUser->getName();
- }
- }
+ $this->validateBlockParams();
+ $this->initialiseRange();
# Don't collide with expired blocks
Block::purgeExpired();
@@ -408,7 +394,8 @@ class Block
'ipb_range_start' => $this->mRangeStart,
'ipb_range_end' => $this->mRangeEnd,
'ipb_deleted' => $this->mHideName,
- 'ipb_block_email' => $this->mBlockEmail
+ 'ipb_block_email' => $this->mBlockEmail,
+ 'ipb_allow_usertalk' => $this->mAllowUsertalk
), 'Block::insert', array( 'IGNORE' )
);
$affected = $dbw->affectedRows();
@@ -416,15 +403,76 @@ class Block
if ($affected)
$this->doRetroactiveAutoblock();
- return $affected;
+ return (bool)$affected;
+ }
+
+ /**
+ * Update a block in the DB with new parameters.
+ * The ID field needs to be loaded first.
+ */
+ public function update() {
+ wfDebug( "Block::update; timestamp {$this->mTimestamp}\n" );
+ $dbw = wfGetDB( DB_MASTER );
+
+ $this->validateBlockParams();
+
+ $dbw->update( 'ipblocks',
+ array(
+ 'ipb_user' => $this->mUser,
+ 'ipb_by' => $this->mBy,
+ 'ipb_by_text' => $this->mByName,
+ 'ipb_reason' => $this->mReason,
+ 'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),
+ 'ipb_auto' => $this->mAuto,
+ 'ipb_anon_only' => $this->mAnonOnly,
+ 'ipb_create_account' => $this->mCreateAccount,
+ 'ipb_enable_autoblock' => $this->mEnableAutoblock,
+ 'ipb_expiry' => self::encodeExpiry( $this->mExpiry, $dbw ),
+ 'ipb_range_start' => $this->mRangeStart,
+ 'ipb_range_end' => $this->mRangeEnd,
+ 'ipb_deleted' => $this->mHideName,
+ 'ipb_block_email' => $this->mBlockEmail,
+ 'ipb_allow_usertalk' => $this->mAllowUsertalk ),
+ array( 'ipb_id' => $this->mId ),
+ 'Block::update' );
+
+ return $dbw->affectedRows();
}
+
+ /**
+ * Make sure all the proper members are set to sane values
+ * before adding/updating a block
+ */
+ protected function validateBlockParams() {
+ # Unset ipb_anon_only for user blocks, makes no sense
+ if ( $this->mUser ) {
+ $this->mAnonOnly = 0;
+ }
+
+ # Unset ipb_enable_autoblock for IP blocks, makes no sense
+ if ( !$this->mUser ) {
+ $this->mEnableAutoblock = 0;
+ $this->mBlockEmail = 0; //Same goes for email...
+ }
+ if( !$this->mByName ) {
+ if( $this->mBy ) {
+ $this->mByName = User::whoIs( $this->mBy );
+ } else {
+ global $wgUser;
+ $this->mByName = $wgUser->getName();
+ }
+ }
+ }
+
+
/**
* Retroactively autoblocks the last IP used by the user (if it is a user)
* blocked by this Block.
- *@return Whether or not a retroactive autoblock was made.
+ *
+ * @return Boolean: whether or not a retroactive autoblock was made.
*/
- function doRetroactiveAutoblock() {
+ public function doRetroactiveAutoblock() {
$dbr = wfGetDB( DB_SLAVE );
#If autoblock is enabled, autoblock the LAST IP used
# - stolen shamelessly from CheckUser_body.php
@@ -458,25 +506,25 @@ class Block
}
}
}
-
+
/**
- * Autoblocks the given IP, referring to this Block.
- * @param string $autoblockip The IP to autoblock.
- * @param bool $justInserted The main block was just inserted
- * @return bool Whether or not an autoblock was inserted.
- */
- function doAutoblock( $autoblockip, $justInserted = false ) {
- # If autoblocks are disabled, go away.
- if ( !$this->mEnableAutoblock ) {
- return;
+ * Checks whether a given IP is on the autoblock whitelist.
+ *
+ * @param $ip String: The IP to check
+ * @return Boolean
+ */
+ public static function isWhitelistedFromAutoblocks( $ip ) {
+ global $wgMemc;
+
+ // Try to get the autoblock_whitelist from the cache, as it's faster
+ // than getting the msg raw and explode()'ing it.
+ $key = wfMemcKey( 'ipb', 'autoblock', 'whitelist' );
+ $lines = $wgMemc->get( $key );
+ if ( !$lines ) {
+ $lines = explode( "\n", wfMsgForContentNoTrans( 'autoblock_whitelist' ) );
+ $wgMemc->set( $key, $lines, 3600 * 24 );
}
- # Check for presence on the autoblock whitelist
- # TODO cache this?
- $lines = explode( "\n", wfMsgForContentNoTrans( 'autoblock_whitelist' ) );
-
- $ip = $autoblockip;
-
wfDebug("Checking the autoblock whitelist..\n");
foreach( $lines as $line ) {
@@ -493,23 +541,42 @@ class Block
# Is the IP in this range?
if (IP::isInRange( $ip, $wlEntry )) {
wfDebug(" IP $ip matches $wlEntry, not autoblocking\n");
- #$autoblockip = null; # Don't autoblock a whitelisted IP.
- return; #This /SHOULD/ introduce a dummy block - but
- # I don't know a safe way to do so. -werdna
+ return true;
} else {
wfDebug( " No match\n" );
}
}
+ return false;
+ }
+
+ /**
+ * Autoblocks the given IP, referring to this Block.
+ *
+ * @param $autoblockIP String: the IP to autoblock.
+ * @param $justInserted Boolean: the main block was just inserted
+ * @return Boolean: whether or not an autoblock was inserted.
+ */
+ public function doAutoblock( $autoblockIP, $justInserted = false ) {
+ # If autoblocks are disabled, go away.
+ if ( !$this->mEnableAutoblock ) {
+ return;
+ }
+
+ # Check for presence on the autoblock whitelist
+ if (Block::isWhitelistedFromAutoblocks($autoblockIP)) {
+ return;
+ }
+
## Allow hooks to cancel the autoblock.
- if (!wfRunHooks( 'AbortAutoblock', array( $autoblockip, &$this ) )) {
+ if (!wfRunHooks( 'AbortAutoblock', array( $autoblockIP, &$this ) )) {
wfDebug( "Autoblock aborted by hook." );
return false;
}
# It's okay to autoblock. Go ahead and create/insert the block.
- $ipblock = Block::newFromDB( $autoblockip );
+ $ipblock = Block::newFromDB( $autoblockIP );
if ( $ipblock ) {
# If the user is already blocked. Then check if the autoblock would
# exceed the user block. If it would exceed, then do nothing, else
@@ -528,8 +595,8 @@ class Block
}
# Make a new block object with the desired properties
- wfDebug( "Autoblocking {$this->mAddress}@" . $autoblockip . "\n" );
- $ipblock->mAddress = $autoblockip;
+ wfDebug( "Autoblocking {$this->mAddress}@" . $autoblockIP . "\n" );
+ $ipblock->mAddress = $autoblockIP;
$ipblock->mUser = 0;
$ipblock->mBy = $this->mBy;
$ipblock->mByName = $this->mByName;
@@ -539,7 +606,7 @@ class Block
$ipblock->mCreateAccount = $this->mCreateAccount;
# Continue suppressing the name if needed
$ipblock->mHideName = $this->mHideName;
-
+ $ipblock->mAllowUsertalk = $this->mAllowUsertalk;
# If the user is already blocked with an expiry date, we don't
# want to pile on top of that!
if($this->mExpiry) {
@@ -551,8 +618,11 @@ class Block
return $ipblock->insert();
}
- function deleteIfExpired()
- {
+ /**
+ * Check if a block has expired. Delete it if it is.
+ * @return Boolean
+ */
+ public function deleteIfExpired() {
$fname = 'Block::deleteIfExpired';
wfProfileIn( $fname );
if ( $this->isExpired() ) {
@@ -567,8 +637,11 @@ class Block
return $retVal;
}
- function isExpired()
- {
+ /**
+ * Has the block expired?
+ * @return Boolean
+ */
+ public function isExpired() {
wfDebug( "Block::isExpired() checking current " . wfTimestampNow() . " vs $this->mExpiry\n" );
if ( !$this->mExpiry ) {
return false;
@@ -577,13 +650,18 @@ class Block
}
}
- function isValid()
- {
+ /**
+ * Is the block address valid (i.e. not a null string?)
+ * @return Boolean
+ */
+ public function isValid() {
return $this->mAddress != '';
}
- function updateTimestamp()
- {
+ /**
+ * Update the timestamp on autoblocks.
+ */
+ public function updateTimestamp() {
if ( $this->mAuto ) {
$this->mTimestamp = wfTimestamp();
$this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
@@ -600,41 +678,43 @@ class Block
}
}
- /*
- function getIntegerAddr()
- {
- return $this->mIntegerAddr;
- }
-
- function getNetworkBits()
- {
- return $this->mNetworkBits;
- }*/
-
/**
- * @return The blocker user ID.
+ * Get the user id of the blocking sysop
+ *
+ * @return Integer
*/
public function getBy() {
return $this->mBy;
}
/**
- * @return The blocker user name.
+ * Get the username of the blocking sysop
+ *
+ * @return String
*/
- function getByName()
- {
+ public function getByName() {
return $this->mByName;
}
- function forUpdate( $x = NULL ) {
+ /**
+ * Get/set the SELECT ... FOR UPDATE flag
+ */
+ public function forUpdate( $x = NULL ) {
return wfSetVar( $this->mForUpdate, $x );
}
- function fromMaster( $x = NULL ) {
+ /**
+ * Get/set a flag determining whether the master is used for reads
+ */
+ public function fromMaster( $x = NULL ) {
return wfSetVar( $this->mFromMaster, $x );
}
- function getRedactedName() {
+ /**
+ * Get the block name, but with autoblocked IPs hidden as per standard privacy policy
+ * @return String
+ */
+ public function getRedactedName() {
if ( $this->mAuto ) {
return '#' . $this->mId;
} else {
@@ -644,8 +724,12 @@ class Block
/**
* Encode expiry for DB
+ *
+ * @param $expiry String: timestamp for expiry, or
+ * @param $db Database object
+ * @return String
*/
- static function encodeExpiry( $expiry, $db ) {
+ public static function encodeExpiry( $expiry, $db ) {
if ( $expiry == '' || $expiry == Block::infinity() ) {
return Block::infinity();
} else {
@@ -655,8 +739,12 @@ class Block
/**
* Decode expiry which has come from the DB
+ *
+ * @param $expiry String: Database expiry format
+ * @param $timestampType Requested timestamp format
+ * @return String
*/
- static function decodeExpiry( $expiry, $timestampType = TS_MW ) {
+ public static function decodeExpiry( $expiry, $timestampType = TS_MW ) {
if ( $expiry == '' || $expiry == Block::infinity() ) {
return Block::infinity();
} else {
@@ -664,8 +752,12 @@ class Block
}
}
- static function getAutoblockExpiry( $timestamp )
- {
+ /**
+ * Get a timestamp of the expiry for autoblocks
+ *
+ * @return String
+ */
+ public static function getAutoblockExpiry( $timestamp ) {
global $wgAutoblockExpiry;
return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
}
@@ -673,8 +765,10 @@ class Block
/**
* Gets rid of uneeded numbers in quad-dotted/octet IP strings
* For example, 127.111.113.151/24 -> 127.111.113.0/24
+ * @param $range String: IP address to normalize
+ * @return string
*/
- static function normaliseRange( $range ) {
+ public static function normaliseRange( $range ) {
$parts = explode( '/', $range );
if ( count( $parts ) == 2 ) {
// IPv6
@@ -706,31 +800,31 @@ class Block
/**
* Purge expired blocks from the ipblocks table
*/
- static function purgeExpired() {
+ public static function purgeExpired() {
$dbw = wfGetDB( DB_MASTER );
$dbw->delete( 'ipblocks', array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ );
}
- static function infinity() {
+ /**
+ * Get a value to insert into expiry field of the database when infinite expiry
+ * is desired. In principle this could be DBMS-dependant, but currently all
+ * supported DBMS's support the string "infinity", so we just use that.
+ *
+ * @return String
+ */
+ public static function infinity() {
# This is a special keyword for timestamps in PostgreSQL, and
# works with CHAR(14) as well because "i" sorts after all numbers.
return 'infinity';
-
- /*
- static $infinity;
- if ( !isset( $infinity ) ) {
- $dbr = wfGetDB( DB_SLAVE );
- $infinity = $dbr->bigTimestamp();
- }
- return $infinity;
- */
}
/**
* Convert a DB-encoded expiry into a real string that humans can read.
+ *
+ * @param $encoded_expiry String: Database encoded expiry time
+ * @return String
*/
- static function formatExpiry( $encoded_expiry ) {
-
+ public static function formatExpiry( $encoded_expiry ) {
static $msg = null;
if( is_null( $msg ) ) {
@@ -749,14 +843,15 @@ class Block
$expiretimestr = $wgLang->timeanddate( $expiry, true );
$expirystr = wfMsgReplaceArgs( $msg['expiringblock'], array($expiretimestr) );
}
-
return $expirystr;
}
/**
* Convert a typed-in expiry time into something we can put into the database.
+ * @param $expiry_input String: whatever was typed into the form
+ * @return String: more database friendly
*/
- static function parseExpiryInput( $expiry_input ) {
+ public static function parseExpiryInput( $expiry_input ) {
if ( $expiry_input == 'infinite' || $expiry_input == 'indefinite' ) {
$expiry = 'infinity';
} else {
@@ -765,7 +860,6 @@ class Block
return false;
}
}
-
return $expiry;
}
diff --git a/includes/Category.php b/includes/Category.php
index acafc47a..78567add 100644
--- a/includes/Category.php
+++ b/includes/Category.php
@@ -1,6 +1,8 @@
<?php
/**
- * Category objects are immutable, strictly speaking. If you call methods that change the database, like to refresh link counts, the objects will be appropriately reinitialized. Member variables are lazy-initialized.
+ * Category objects are immutable, strictly speaking. If you call methods that change the database,
+ * like to refresh link counts, the objects will be appropriately reinitialized.
+ * Member variables are lazy-initialized.
*
* TODO: Move some stuff from CategoryPage.php to here, and use that.
*
@@ -79,7 +81,7 @@ class Category {
/**
* Factory function.
*
- * @param array $name A category name (no "Category:" prefix). It need
+ * @param $name Array: A category name (no "Category:" prefix). It need
* not be normalized, with spaces replaced by underscores.
* @return mixed Category, or false on a totally invalid name
*/
@@ -99,8 +101,8 @@ class Category {
/**
* Factory function.
*
- * @param array $title Title for the category page
- * @return mixed Category, or false on a totally invalid name
+ * @param $title Title for the category page
+ * @return Mixed: category, or false on a totally invalid name
*/
public static function newFromTitle( $title ) {
$cat = new self();
@@ -114,7 +116,7 @@ class Category {
/**
* Factory function.
*
- * @param array $id A category id
+ * @param $id Integer: a category id
* @return Category
*/
public static function newFromID( $id ) {
@@ -192,6 +194,33 @@ class Category {
return $this->mTitle;
}
+ /**
+ * Fetch a TitleArray of up to $limit category members, beginning after the
+ * category sort key $offset.
+ * @param $limit integer
+ * @param $offset string
+ * @return TitleArray object for category members.
+ */
+ public function getMembers( $limit = false, $offset = '' ) {
+ $dbr = wfGetDB( DB_SLAVE );
+
+ $conds = array( 'cl_to' => $this->getName(), 'cl_from = page_id' );
+ $options = array( 'ORDER BY' => 'cl_sortkey' );
+ if( $limit ) $options[ 'LIMIT' ] = $limit;
+ if( $offset !== '' ) $conds[] = 'cl_sortkey > ' . $dbr->addQuotes( $offset );
+
+ return TitleArray::newFromResult(
+ $dbr->select(
+ array( 'page', 'categorylinks' ),
+ array( 'page_id', 'page_namespace','page_title', 'page_len',
+ 'page_is_redirect', 'page_latest' ),
+ $conds,
+ __METHOD__,
+ $options
+ )
+ );
+ }
+
/** Generic accessor */
private function getX( $key ) {
if( !$this->initialize() ) {
@@ -228,7 +257,7 @@ class Category {
}
$cond1 = $dbw->conditional( 'page_namespace='.NS_CATEGORY, 1, 'NULL' );
- $cond2 = $dbw->conditional( 'page_namespace='.NS_IMAGE, 1, 'NULL' );
+ $cond2 = $dbw->conditional( 'page_namespace='.NS_FILE, 1, 'NULL' );
$result = $dbw->selectRow(
array( 'categorylinks', 'page' ),
array( 'COUNT(*) AS pages',
diff --git a/includes/CategoryPage.php b/includes/CategoryPage.php
index 92e4e279..4ac24b5f 100644
--- a/includes/CategoryPage.php
+++ b/includes/CategoryPage.php
@@ -36,18 +36,18 @@ class CategoryPage extends Article {
$this->closeShowCategory();
}
}
-
+
/**
- * This page should not be cached if 'from' or 'until' has been used
- * @return bool
+ * Don't return a 404 for categories in use.
*/
- function isFileCacheable() {
- global $wgRequest;
-
- return ( ! Article::isFileCacheable()
- || $wgRequest->getVal( 'from' )
- || $wgRequest->getVal( 'until' )
- ) ? false : true;
+ function hasViewableContent() {
+ if( parent::hasViewableContent() ) {
+ return true;
+ } else {
+ $cat = Category::newFromTitle( $this->mTitle );
+ return $cat->getId() != 0;
+ }
+
}
function openShowCategory() {
@@ -85,8 +85,6 @@ class CategoryViewer {
/**
* Format the category data list.
*
- * @param string $from -- return only sort keys from this item on
- * @param string $until -- don't return keys after this point.
* @return string HTML output
* @private
*/
@@ -144,7 +142,7 @@ class CategoryViewer {
/**
* Add a subcategory to the internal lists, using a title object
- * @deprectated kept for compatibility, please use addSubcategoryObject instead
+ * @deprecated kept for compatibility, please use addSubcategoryObject instead
*/
function addSubcategory( $title, $sortkey, $pageLength ) {
global $wgContLang;
@@ -225,14 +223,14 @@ class CategoryViewer {
array( 'page', 'categorylinks', 'category' ),
array( 'page_title', 'page_namespace', 'page_len', 'page_is_redirect', 'cl_sortkey',
'cat_id', 'cat_title', 'cat_subcats', 'cat_pages', 'cat_files' ),
- array( $pageCondition,
- 'cl_to' => $this->title->getDBkey() ),
+ array( $pageCondition, 'cl_to' => $this->title->getDBkey() ),
__METHOD__,
array( 'ORDER BY' => $this->flip ? 'cl_sortkey DESC' : 'cl_sortkey',
- 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ),
- 'LIMIT' => $this->limit + 1 ),
+ 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ),
+ 'LIMIT' => $this->limit + 1 ),
array( 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
- 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY ) ) );
+ 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY ) )
+ );
$count = 0;
$this->nextPage = null;
@@ -249,7 +247,7 @@ class CategoryViewer {
if( $title->getNamespace() == NS_CATEGORY ) {
$cat = Category::newFromRow( $x, $title );
$this->addSubcategoryObject( $cat, $x->cl_sortkey, $x->page_len );
- } elseif( $this->showGallery && $title->getNamespace() == NS_IMAGE ) {
+ } elseif( $this->showGallery && $title->getNamespace() == NS_FILE ) {
$this->addImage( $title, $x->cl_sortkey, $x->page_len, $x->page_is_redirect );
} else {
$this->addPage( $title, $x->cl_sortkey, $x->page_len, $x->page_is_redirect );
@@ -339,10 +337,10 @@ class CategoryViewer {
* Format a list of articles chunked by letter, either as a
* bullet list or a columnar format, depending on the length.
*
- * @param array $articles
- * @param array $articles_start_char
- * @param int $cutoff
- * @return string
+ * @param $articles Array
+ * @param $articles_start_char Array
+ * @param $cutoff Int
+ * @return String
* @private
*/
function formatList( $articles, $articles_start_char, $cutoff = 6 ) {
@@ -359,9 +357,9 @@ class CategoryViewer {
* Format a list of articles chunked by letter in a three-column
* list, ordered vertically.
*
- * @param array $articles
- * @param array $articles_start_char
- * @return string
+ * @param $articles Array
+ * @param $articles_start_char Array
+ * @return String
* @private
*/
function columnList( $articles, $articles_start_char ) {
@@ -418,9 +416,9 @@ class CategoryViewer {
/**
* Format a list of articles chunked by letter in a bullet list.
- * @param array $articles
- * @param array $articles_start_char
- * @return string
+ * @param $articles Array
+ * @param $articles_start_char Array
+ * @return String
* @private
*/
function shortList( $articles, $articles_start_char ) {
@@ -440,12 +438,12 @@ class CategoryViewer {
}
/**
- * @param Title $title
- * @param string $first
- * @param string $last
- * @param int $limit
- * @param array $query - additional query options to pass
- * @return string
+ * @param $title Title object
+ * @param $first String
+ * @param $last String
+ * @param $limit Int
+ * @param $query Array: additional query options to pass
+ * @return String
* @private
*/
function pagingLinks( $title, $first, $last, $limit, $query = array() ) {
@@ -477,10 +475,10 @@ class CategoryViewer {
* 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.
+ * @param $rescnt Int: The number of items returned by our database query.
+ * @param $dbcnt Int: The number of items according to the category table.
+ * @param $type String: 'subcat', 'article', or 'file'
+ * @return String: A message giving the number of items, to output to HTML.
*/
private function getCountMessage( $rescnt, $dbcnt, $type ) {
global $wgLang;
@@ -500,8 +498,12 @@ class CategoryViewer {
# Case 1: seems sane.
$totalcnt = $dbcnt;
} elseif($totalrescnt < $this->limit && !$this->from && !$this->until){
- # Case 2: not sane, but salvageable.
+ # 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.
return wfMsgExt("category-$type-count-limited", 'parse',
diff --git a/includes/Categoryfinder.php b/includes/Categoryfinder.php
index d28f2eeb..4413bd1a 100644
--- a/includes/Categoryfinder.php
+++ b/includes/Categoryfinder.php
@@ -86,9 +86,15 @@ class Categoryfinder {
* This functions recurses through the parent representation, trying to match the conditions
* @param $id The article/category to check
* @param $conds The array of categories to match
+ * @param $path used to check for recursion loops
* @return bool Does this match the conditions?
*/
- function check ( $id , &$conds ) {
+ function check ( $id , &$conds, $path=array() ) {
+ // Check for loops and stop!
+ if( in_array( $id, $path ) )
+ return false;
+ $path[] = $id;
+
# Shortcut (runtime paranoia): No contitions=all matched
if ( count ( $conds ) == 0 ) return true ;
@@ -120,7 +126,7 @@ class Categoryfinder {
# No sub-parent
continue ;
}
- $done = $this->check ( $this->name2id[$pname] , $conds ) ;
+ $done = $this->check ( $this->name2id[$pname] , $conds, $path );
if ( $done OR count ( $conds ) == 0 ) {
# Subparents have done it!
return true ;
diff --git a/includes/ChangesFeed.php b/includes/ChangesFeed.php
index 9bee1790..f3c3e429 100644
--- a/includes/ChangesFeed.php
+++ b/includes/ChangesFeed.php
@@ -12,14 +12,15 @@ class ChangesFeed {
public function getFeedObject( $title, $description ) {
global $wgSitename, $wgContLanguageCode, $wgFeedClasses, $wgTitle;
$feedTitle = "$wgSitename - {$title} [$wgContLanguageCode]";
-
+ if( !isset($wgFeedClasses[$this->format] ) )
+ return false;
return new $wgFeedClasses[$this->format](
$feedTitle, htmlspecialchars( $description ), $wgTitle->getFullUrl() );
}
public function execute( $feed, $rows, $limit = 0 , $hideminor = false, $lastmod = false ) {
global $messageMemc, $wgFeedCacheTimeout;
- global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode;
+ global $wgFeedClasses, $wgSitename, $wgContLanguageCode;
if ( !FeedUtils::checkFeedOutput( $this->format ) ) {
return;
@@ -85,7 +86,7 @@ class ChangesFeed {
}
/**
- * @todo document
+ * Generate the feed items given a row from the database.
* @param $rows Database resource with recentchanges rows
* @param $feed Feed object
*/
diff --git a/includes/ChangesList.php b/includes/ChangesList.php
index 436f006e..a8f5fff0 100644
--- a/includes/ChangesList.php
+++ b/includes/ChangesList.php
@@ -3,10 +3,9 @@
/**
* @todo document
*/
-class RCCacheEntry extends RecentChange
-{
+class RCCacheEntry extends RecentChange {
var $secureName, $link;
- var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
+ var $curlink , $difflink, $lastlink, $usertalklink, $versionlink;
var $userlink, $timestamp, $watched;
static function newFromParent( $rc ) {
@@ -15,7 +14,7 @@ class RCCacheEntry extends RecentChange
$rc2->mExtra = $rc->mExtra;
return $rc2;
}
-} ;
+}
/**
* Class to show various lists of changes:
@@ -25,13 +24,13 @@ class RCCacheEntry extends RecentChange
*/
class ChangesList {
# Called by history lists and recent changes
- #
+ public $skin;
/**
* Changeslist contructor
* @param Skin $skin
*/
- function __construct( &$skin ) {
+ public function __construct( &$skin ) {
$this->skin =& $skin;
$this->preCacheMessages();
}
@@ -47,7 +46,8 @@ class ChangesList {
$sk = $user->getSkin();
$list = NULL;
if( wfRunHooks( 'FetchChangesList', array( &$user, &$sk, &$list ) ) ) {
- return $user->getOption( 'usenewrc' ) ? new EnhancedChangesList( $sk ) : new OldChangesList( $sk );
+ return $user->getOption( 'usenewrc' ) ?
+ new EnhancedChangesList( $sk ) : new OldChangesList( $sk );
} else {
return $list;
}
@@ -58,7 +58,6 @@ class ChangesList {
* they are called often, we call them once and save them in $this->message
*/
private function preCacheMessages() {
- // Precache various messages
if( !isset( $this->message ) ) {
foreach( explode(' ', 'cur diff hist minoreditletter newpageletter last '.
'blocklink history boteditletter semicolon-separator' ) as $msg ) {
@@ -78,10 +77,10 @@ class ChangesList {
* @return string
*/
protected function recentChangesFlags( $new, $minor, $patrolled, $nothing = '&nbsp;', $bot = false ) {
- $f = $new ? '<span class="newpage">' . $this->message['newpageletter'] . '</span>'
- : $nothing;
- $f .= $minor ? '<span class="minor">' . $this->message['minoreditletter'] . '</span>'
- : $nothing;
+ $f = $new ?
+ '<span class="newpage">' . $this->message['newpageletter'] . '</span>' : $nothing;
+ $f .= $minor ?
+ '<span class="minor">' . $this->message['minoreditletter'] . '</span>' : $nothing;
$f .= $bot ? '<span class="bot">' . $this->message['boteditletter'] . '</span>' : $nothing;
$f .= $patrolled ? '<span class="unpatrolled">!</span>' : $nothing;
return $f;
@@ -99,6 +98,30 @@ class ChangesList {
$this->rclistOpen = false;
return '';
}
+
+ /**
+ * Show formatted char difference
+ * @param int $old bytes
+ * @param int $new bytes
+ * @returns string
+ */
+ public static function showCharacterDifference( $old, $new ) {
+ global $wgRCChangedSizeThreshold, $wgLang;
+ $szdiff = $new - $old;
+ $formatedSize = wfMsgExt( 'rc-change-size', array( 'parsemag', 'escape'), $wgLang->formatNum($szdiff) );
+ if( abs( $szdiff ) > abs( $wgRCChangedSizeThreshold ) ) {
+ $tag = 'strong';
+ } else {
+ $tag = 'span';
+ }
+ if( $szdiff === 0 ) {
+ return "<$tag class='mw-plusminus-null'>($formatedSize)</$tag>";
+ } elseif( $szdiff > 0 ) {
+ return "<$tag class='mw-plusminus-pos'>(+$formatedSize)</$tag>";
+ } else {
+ return "<$tag class='mw-plusminus-neg'>($formatedSize)</$tag>";
+ }
+ }
/**
* Returns text for the end of RC
@@ -116,21 +139,18 @@ class ChangesList {
# Diff
$s .= '(' . $this->message['diff'] . ') (';
# Hist
- $s .= $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), $this->message['hist'], 'action=history' ) .
- ') . . ';
-
+ $s .= $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), $this->message['hist'],
+ 'action=history' ) . ') . . ';
# "[[x]] moved to [[y]]"
$msg = ( $rc->mAttribs['rc_type'] == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
$s .= wfMsg( $msg, $this->skin->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
$this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
}
- protected function insertDateHeader(&$s, $rc_timestamp) {
+ protected function insertDateHeader( &$s, $rc_timestamp ) {
global $wgLang;
-
# Make date header if necessary
$date = $wgLang->date( $rc_timestamp, true, true );
- $s = '';
if( $date != $this->lastdate ) {
if( '' != $this->lastdate ) {
$s .= "</ul>\n";
@@ -141,21 +161,19 @@ class ChangesList {
}
}
- protected function insertLog(&$s, $title, $logtype) {
+ protected function insertLog( &$s, $title, $logtype ) {
$logname = LogPage::logName( $logtype );
$s .= '(' . $this->skin->makeKnownLinkObj($title, $logname ) . ')';
}
- protected function insertDiffHist(&$s, &$rc, $unpatrolled) {
+ protected function insertDiffHist( &$s, &$rc, $unpatrolled ) {
# Diff link
- if( !$this->userCan($rc,Revision::DELETED_TEXT) ) {
+ if( $rc->mAttribs['rc_type'] == RC_NEW || $rc->mAttribs['rc_type'] == RC_LOG ) {
$diffLink = $this->message['diff'];
- } else if( $rc->mAttribs['rc_type'] == RC_NEW || $rc->mAttribs['rc_type'] == RC_LOG ) {
+ } else if( !$this->userCan($rc,Revision::DELETED_TEXT) ) {
$diffLink = $this->message['diff'];
} else {
- $rcidparam = $unpatrolled
- ? array( 'rcid' => $rc->mAttribs['rc_id'] )
- : array();
+ $rcidparam = $unpatrolled ? array( 'rcid' => $rc->mAttribs['rc_id'] ) : array();
$diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['diff'],
wfArrayToCGI( array(
'curid' => $rc->mAttribs['rc_cur_id'],
@@ -165,7 +183,6 @@ class ChangesList {
'', '', ' tabindex="'.$rc->counter.'"');
}
$s .= '('.$diffLink.') (';
-
# History link
$s .= $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['hist'],
wfArrayToCGI( array(
@@ -174,39 +191,40 @@ class ChangesList {
$s .= ') . . ';
}
- protected function insertArticleLink(&$s, &$rc, $unpatrolled, $watched) {
- # Article link
+ protected function insertArticleLink( &$s, &$rc, $unpatrolled, $watched ) {
+ global $wgContLang;
# If it's a new article, there is no diff link, but if it hasn't been
# patrolled yet, we need to give users a way to do so
- $params = ( $unpatrolled && $rc->mAttribs['rc_type'] == RC_NEW )
- ? 'rcid='.$rc->mAttribs['rc_id']
- : '';
+ $params = ( $unpatrolled && $rc->mAttribs['rc_type'] == RC_NEW ) ?
+ 'rcid='.$rc->mAttribs['rc_id'] : '';
if( $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
$articlelink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params );
$articlelink = '<span class="history-deleted">'.$articlelink.'</span>';
} else {
$articlelink = ' '. $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params );
}
- if( $watched )
+ # Bolden pages watched by this user
+ if( $watched ) {
$articlelink = "<strong class=\"mw-watched\">{$articlelink}</strong>";
- global $wgContLang;
+ }
+ # RTL/LTR marker
$articlelink .= $wgContLang->getDirMark();
- wfRunHooks('ChangesListInsertArticleLink',
- array(&$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched));
+ wfRunHooks( 'ChangesListInsertArticleLink',
+ array(&$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched) );
- $s .= ' '.$articlelink;
+ $s .= " $articlelink";
}
- protected function insertTimestamp(&$s, $rc) {
+ protected function insertTimestamp( &$s, $rc ) {
global $wgLang;
- # Timestamp
- $s .= $this->message['semicolon-separator'] . ' ' . $wgLang->time( $rc->mAttribs['rc_timestamp'], true, true ) . ' . . ';
+ $s .= $this->message['semicolon-separator'] .
+ $wgLang->time( $rc->mAttribs['rc_timestamp'], true, true ) . ' . . ';
}
/** Insert links to user page, user talk page and eventually a blocking link */
- protected function insertUserRelatedLinks(&$s, &$rc) {
- if ( $this->isDeleted($rc,Revision::DELETED_USER) ) {
+ public function insertUserRelatedLinks(&$s, &$rc) {
+ if( $this->isDeleted($rc,Revision::DELETED_USER) ) {
$s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-user') . '</span>';
} else {
$s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
@@ -216,13 +234,11 @@ class ChangesList {
/** insert a formatted action */
protected function insertAction(&$s, &$rc) {
- # Add action
if( $rc->mAttribs['rc_type'] == RC_LOG ) {
- // log action
- if ( $this->isDeleted($rc,LogPage::DELETED_ACTION) ) {
+ if( $this->isDeleted($rc,LogPage::DELETED_ACTION) ) {
$s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
} else {
- $s .= ' ' . LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'],
+ $s .= ' '.LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'],
$rc->getTitle(), $this->skin, LogPage::extractParams($rc->mAttribs['rc_params']), true, true );
}
}
@@ -230,10 +246,8 @@ class ChangesList {
/** insert a formatted comment */
protected function insertComment(&$s, &$rc) {
- # Add comment
if( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) {
- // log comment
- if ( $this->isDeleted($rc,Revision::DELETED_COMMENT) ) {
+ if( $this->isDeleted($rc,Revision::DELETED_COMMENT) ) {
$s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-comment') . '</span>';
} else {
$s .= $this->skin->commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
@@ -256,8 +270,8 @@ class ChangesList {
protected function numberofWatchingusers( $count ) {
global $wgLang;
static $cache = array();
- if ( $count > 0 ) {
- if ( !isset( $cache[$count] ) ) {
+ if( $count > 0 ) {
+ if( !isset( $cache[$count] ) ) {
$cache[$count] = wfMsgExt('number_of_watching_users_RCview',
array('parsemag', 'escape'), $wgLang->formatNum($count));
}
@@ -290,12 +304,20 @@ class ChangesList {
$permission = ( $rc->mAttribs['rc_deleted'] & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED
? 'suppressrevision'
: 'deleterevision';
- wfDebug( "Checking for $permission due to $field match on $rc->mAttribs['rc_deleted']\n" );
+ wfDebug( "Checking for $permission due to $field match on {$rc->mAttribs['rc_deleted']}\n" );
return $wgUser->isAllowed( $permission );
} else {
return true;
}
}
+
+ protected function maybeWatchedLink( $link, $watched=false ) {
+ if( $watched ) {
+ return '<strong class="mw-watched">' . $link . '</strong>';
+ } else {
+ return '<span class="mw-rc-unwatched">' . $link . '</span>';
+ }
+ }
}
@@ -308,55 +330,43 @@ class OldChangesList extends ChangesList {
*/
public function recentChangesLine( &$rc, $watched = false ) {
global $wgContLang, $wgRCShowChangedSize, $wgUser;
-
- $fname = 'ChangesList::recentChangesLineOld';
- wfProfileIn( $fname );
-
- # Extract DB fields into local scope
- // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
- extract( $rc->mAttribs );
-
+ wfProfileIn( __METHOD__ );
# Should patrol-related stuff be shown?
- $unpatrolled = $wgUser->useRCPatrol() && $rc_patrolled == 0;
+ $unpatrolled = $wgUser->useRCPatrol() && !$rc->mAttribs['rc_patrolled'];
- $this->insertDateHeader($s,$rc_timestamp);
-
- $s .= '<li>';
+ $dateheader = ''; // $s now contains only <li>...</li>, for hooks' convenience.
+ $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
+ $s = '';
// Moved pages
- if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+ if( $rc->mAttribs['rc_type'] == RC_MOVE || $rc->mAttribs['rc_type'] == RC_MOVE_OVER_REDIRECT ) {
$this->insertMove( $s, $rc );
// Log entries
- } elseif( $rc_log_type ) {
- $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
- $this->insertLog( $s, $logtitle, $rc_log_type );
+ } elseif( $rc->mAttribs['rc_log_type'] ) {
+ $logtitle = Title::newFromText( 'Log/'.$rc->mAttribs['rc_log_type'], NS_SPECIAL );
+ $this->insertLog( $s, $logtitle, $rc->mAttribs['rc_log_type'] );
// Log entries (old format) or log targets, and special pages
- } elseif( $rc_namespace == NS_SPECIAL ) {
- list( $specialName, $specialSubpage ) = SpecialPage::resolveAliasWithSubpage( $rc_title );
- if ( $specialName == 'Log' ) {
- $this->insertLog( $s, $rc->getTitle(), $specialSubpage );
- } else {
- wfDebug( "Unexpected special page in recentchanges\n" );
+ } elseif( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
+ list( $name, $subpage ) = SpecialPage::resolveAliasWithSubpage( $rc->mAttribs['rc_title'] );
+ if( $name == 'Log' ) {
+ $this->insertLog( $s, $rc->getTitle(), $subpage );
}
// Regular entries
} else {
- wfProfileIn($fname.'-page');
-
- $this->insertDiffHist($s, $rc, $unpatrolled);
-
+ $this->insertDiffHist( $s, $rc, $unpatrolled );
# M, N, b and ! (minor, new, bot and unpatrolled)
- $s .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $unpatrolled, '', $rc_bot );
- $this->insertArticleLink($s, $rc, $unpatrolled, $watched);
-
- wfProfileOut($fname.'-page');
+ $s .= $this->recentChangesFlags( $rc->mAttribs['rc_new'], $rc->mAttribs['rc_minor'],
+ $unpatrolled, '', $rc->mAttribs['rc_bot'] );
+ $this->insertArticleLink( $s, $rc, $unpatrolled, $watched );
}
-
- wfProfileIn( $fname.'-rest' );
-
- $this->insertTimestamp($s,$rc);
-
+ # Edit/log timestamp
+ $this->insertTimestamp( $s, $rc );
+ # Bytes added or removed
if( $wgRCShowChangedSize ) {
- $s .= ( $rc->getCharacterDifference() == '' ? '' : $rc->getCharacterDifference() . ' . . ' );
+ $cd = $rc->getCharacterDifference();
+ if( $cd != '' ) {
+ $s .= "$cd . . ";
+ }
}
# User tool links
$this->insertUserRelatedLinks($s,$rc);
@@ -364,29 +374,45 @@ class OldChangesList extends ChangesList {
$this->insertAction($s, $rc);
# Edit or log comment
$this->insertComment($s, $rc);
-
# Mark revision as deleted if so
- if ( !$rc_log_type && $this->isDeleted($rc,Revision::DELETED_TEXT) )
+ if( !$rc->mAttribs['rc_log_type'] && $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
$s .= ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
- if($rc->numberofWatchingusers > 0) {
- $s .= ' ' . wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rc->numberofWatchingusers));
+ }
+ # How many users watch this page
+ if( $rc->numberofWatchingusers > 0 ) {
+ $s .= ' ' . wfMsg( 'number_of_watching_users_RCview',
+ $wgContLang->formatNum($rc->numberofWatchingusers) );
}
- $s .= "</li>\n";
-
- wfProfileOut( $fname.'-rest' );
+ wfRunHooks( 'OldChangesListRecentChangesLine', array(&$this, &$s, $rc) );
- wfProfileOut( $fname );
- return $s;
+ wfProfileOut( __METHOD__ );
+ return "$dateheader<li>$s</li>\n";
}
}
/**
- * Generate a list of changes using an Enhanced system (use javascript).
+ * Generate a list of changes using an Enhanced system (uses javascript).
*/
class EnhancedChangesList extends ChangesList {
/**
+ * Add the JavaScript file for enhanced changeslist
+ * @ return string
+ */
+ public function beginRecentChangesList() {
+ global $wgStylePath, $wgJsMimeType, $wgStyleVersion;
+ $this->rc_cache = array();
+ $this->rcMoveIndex = 0;
+ $this->rcCacheIndex = 0;
+ $this->lastdate = '';
+ $this->rclistOpen = false;
+ $script = Xml::tags( 'script', array(
+ 'type' => $wgJsMimeType,
+ 'src' => $wgStylePath . "/common/enhancedchanges.js?$wgStyleVersion" ), '' );
+ return $script;
+ }
+ /**
* Format a line for enhanced recentchange (aka with javascript and block of lines).
*/
public function recentChangesLine( &$baseRC, $watched = false ) {
@@ -396,12 +422,13 @@ class EnhancedChangesList extends ChangesList {
$rc = RCCacheEntry::newFromParent( $baseRC );
# Extract fields from DB into the function scope (rc_xxxx variables)
- // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
+ // FIXME: Would be good to replace this extract() call with something
+ // that explicitly initializes variables.
extract( $rc->mAttribs );
$curIdEq = 'curid=' . $rc_cur_id;
# If it's a new day, add the headline and flush the cache
- $date = $wgLang->date( $rc_timestamp, true);
+ $date = $wgLang->date( $rc_timestamp, true );
$ret = '';
if( $date != $this->lastdate ) {
# Process current cache
@@ -425,17 +452,6 @@ class EnhancedChangesList extends ChangesList {
$msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
$clink = wfMsg( $msg, $this->skin->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
$this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
- // Log entries (old format) and special pages
- } elseif( $rc_namespace == NS_SPECIAL ) {
- list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( $rc_title );
- if ( $specialName == 'Log' ) {
- # Log updates, etc
- $logname = LogPage::logName( $logtype );
- $clink = '(' . $this->skin->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
- } else {
- wfDebug( "Unexpected special page in recentchanges\n" );
- $clink = '';
- }
// New unpatrolled pages
} else if( $rc->unpatrolled && $rc_type == RC_NEW ) {
$clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
@@ -443,11 +459,23 @@ class EnhancedChangesList extends ChangesList {
} else if( $rc_type == RC_LOG ) {
if( $rc_log_type ) {
$logtitle = SpecialPage::getTitleFor( 'Log', $rc_log_type );
- $clink = '(' . $this->skin->makeKnownLinkObj( $logtitle, LogPage::logName($rc_log_type) ) . ')';
+ $clink = '(' . $this->skin->makeKnownLinkObj( $logtitle,
+ LogPage::logName($rc_log_type) ) . ')';
} else {
$clink = $this->skin->makeLinkObj( $rc->getTitle(), '' );
}
$watched = false;
+ // Log entries (old format) and special pages
+ } elseif( $rc_namespace == NS_SPECIAL ) {
+ list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( $rc_title );
+ if ( $specialName == 'Log' ) {
+ # Log updates, etc
+ $logname = LogPage::logName( $logtype );
+ $clink = '(' . $this->skin->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
+ } else {
+ wfDebug( "Unexpected special page in recentchanges\n" );
+ $clink = '';
+ }
// Edits
} else {
$clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '' );
@@ -473,7 +501,8 @@ class EnhancedChangesList extends ChangesList {
$querycur = $curIdEq."&diff=0&oldid=$rc_this_oldid";
$querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid$rcIdQuery";
$aprops = ' tabindex="'.$baseRC->counter.'"';
- $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['cur'], $querycur, '' ,'', $aprops );
+ $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(),
+ $this->message['cur'], $querycur, '' ,'', $aprops );
# Make "diff" an "cur" links
if( !$showdifflinks ) {
@@ -485,7 +514,8 @@ class EnhancedChangesList extends ChangesList {
}
$diffLink = $this->message['diff'];
} else {
- $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['diff'], $querydiff, '' ,'', $aprops );
+ $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['diff'],
+ $querydiff, '' ,'', $aprops );
}
# Make "last" link
@@ -545,7 +575,7 @@ class EnhancedChangesList extends ChangesList {
$curId = $currentRevision = 0;
# Some catalyst variables...
$namehidden = true;
- $alllogs = true;
+ $allLogs = true;
foreach( $block as $rcObj ) {
$oldid = $rcObj->mAttribs['rc_last_oldid'];
if( $rcObj->mAttribs['rc_new'] ) {
@@ -564,7 +594,7 @@ class EnhancedChangesList extends ChangesList {
$unpatrolled = true;
}
if( $rcObj->mAttribs['rc_type'] != RC_LOG ) {
- $alllogs = false;
+ $allLogs = false;
}
# Get the latest entry with a page_id and oldid
# since logs may not have these.
@@ -587,20 +617,24 @@ class EnhancedChangesList extends ChangesList {
$text = $userlink;
$text .= $wgContLang->getDirMark();
if( $count > 1 ) {
- $text .= ' ('.$count.'&times;)';
+ $text .= ' (' . $wgLang->formatNum( $count ) . '×)';
}
array_push( $users, $text );
}
- $users = ' <span class="changedby">[' . implode( $this->message['semicolon-separator'] . ' ', $users ) . ']</span>';
+ $users = ' <span class="changedby">[' .
+ implode( $this->message['semicolon-separator'], $users ) . ']</span>';
- # Arrow
- $rci = 'RCI'.$this->rcCacheIndex;
- $rcl = 'RCL'.$this->rcCacheIndex;
- $rcm = 'RCM'.$this->rcCacheIndex;
- $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')";
- $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'">' . $this->sideArrow() . '</a></span>';
- $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'">' . $this->downArrow() . '</a></span>';
+ # ID for JS visibility toggle
+ $jsid = $this->rcCacheIndex;
+ # onclick handler to toggle hidden/expanded
+ $toggleLink = "onclick='toggleVisibility($jsid); return false'";
+ # Title for <a> tags
+ $expandTitle = htmlspecialchars( wfMsg('rc-enhanced-expand') );
+ $closeTitle = htmlspecialchars( wfMsg('rc-enhanced-hide') );
+
+ $tl = "<span id='mw-rc-openarrow-$jsid' class='mw-changeslist-expanded' style='visibility:hidden'><a href='#' $toggleLink title='$expandTitle'>" . $this->sideArrow() . "</a></span>";
+ $tl .= "<span id='mw-rc-closearrow-$jsid' class='mw-changeslist-hidden' style='display:none'><a href='#' $toggleLink title='$closeTitle'>" . $this->downArrow() . "</a></span>";
$r .= '<td valign="top" style="white-space: nowrap"><tt>'.$tl.'&nbsp;';
# Main line
@@ -612,8 +646,10 @@ class EnhancedChangesList extends ChangesList {
# Article link
if( $namehidden ) {
$r .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
- } else {
+ } else if( $allLogs ) {
$r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
+ } else {
+ $this->insertArticleLink( $r, $block[0], $block[0]->unpatrolled, $block[0]->watched );
}
$r .= $wgContLang->getDirMark();
@@ -627,7 +663,7 @@ class EnhancedChangesList extends ChangesList {
}
# Total change link
$r .= ' ';
- if( !$alllogs ) {
+ if( !$allLogs ) {
$r .= '(';
if( !ChangesList::userCan($rcObj,Revision::DELETED_TEXT) ) {
$r .= $nchanges[$n];
@@ -637,11 +673,21 @@ class EnhancedChangesList extends ChangesList {
$r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
$nchanges[$n], $curIdEq."&diff=$currentRevision&oldid=$oldid" );
}
- $r .= ') . . ';
}
+ # History
+ if( $allLogs ) {
+ // don't show history link for logs
+ } else if( $namehidden || !$block[0]->getTitle()->exists() ) {
+ $r .= $this->message['semicolon-separator'] . $this->message['hist'] . ')';
+ } else {
+ $r .= $this->message['semicolon-separator'] . $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
+ $this->message['hist'], $curIdEq . '&action=history' ) . ')';
+ }
+ $r .= ' . . ';
+
# Character difference (does not apply if only log items)
- if( $wgRCShowChangedSize && !$alllogs ) {
+ if( $wgRCShowChangedSize && !$allLogs ) {
$last = 0;
$first = count($block) - 1;
# Some events (like logs) have an "empty" size, so we need to skip those...
@@ -662,26 +708,18 @@ class EnhancedChangesList extends ChangesList {
}
}
- # History
- if( $alllogs ) {
- // don't show history link for logs
- } else if( $namehidden || !$block[0]->getTitle()->exists() ) {
- $r .= '(' . $this->message['history'] . ')';
- } else {
- $r .= '(' . $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
- $this->message['history'], $curIdEq.'&action=history' ) . ')';
- }
-
$r .= $users;
$r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers);
$r .= "</td></tr></table>\n";
# Sub-entries
- $r .= '<div id="'.$rci.'" style="display:none;"><table cellpadding="0" cellspacing="0" border="0" style="background: none">';
+ $r .= '<div id="mw-rc-subentries-'.$jsid.'" class="mw-changeslist-hidden">';
+ $r .= '<table cellpadding="0" cellspacing="0" border="0" style="background: none">';
foreach( $block as $rcObj ) {
- # Get rc_xxxx variables
- // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
+ # Extract fields from DB into the function scope (rc_xxxx variables)
+ // FIXME: Would be good to replace this extract() call with something
+ // that explicitly initializes variables.
extract( $rcObj->mAttribs );
#$r .= '<tr><td valign="top">'.$this->spacerArrow();
@@ -701,9 +739,10 @@ class EnhancedChangesList extends ChangesList {
} else if( !ChangesList::userCan($rcObj,Revision::DELETED_TEXT) ) {
$link = '<span class="history-deleted"><tt>'.$rcObj->timestamp.'</tt></span> ';
} else {
- $rcIdEq = ($rcObj->unpatrolled && $rc_type == RC_NEW) ? '&rcid='.$rcObj->mAttribs['rc_id'] : '';
-
- $link = '<tt>'.$this->skin->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp, $curIdEq.'&'.$o.$rcIdEq ).'</tt>';
+ $rcIdEq = ($rcObj->unpatrolled && $rc_type == RC_NEW) ?
+ '&rcid='.$rcObj->mAttribs['rc_id'] : '';
+ $link = '<tt>'.$this->skin->makeKnownLinkObj( $rcObj->getTitle(),
+ $rcObj->timestamp, $curIdEq.'&'.$o.$rcIdEq ).'</tt>';
if( $this->isDeleted($rcObj,Revision::DELETED_TEXT) )
$link = '<span class="history-deleted">'.$link.'</span> ';
}
@@ -712,7 +751,7 @@ class EnhancedChangesList extends ChangesList {
if ( !$rc_type == RC_LOG || $rc_type == RC_NEW ) {
$r .= ' (';
$r .= $rcObj->curlink;
- $r .= $this->message['semicolon-separator'] . ' ';
+ $r .= $this->message['semicolon-separator'];
$r .= $rcObj->lastlink;
$r .= ')';
}
@@ -742,26 +781,19 @@ class EnhancedChangesList extends ChangesList {
return $r;
}
- protected function maybeWatchedLink( $link, $watched=false ) {
- if( $watched ) {
- // FIXME: css style might be more appropriate
- return '<strong class="mw-watched">' . $link . '</strong>';
- } else {
- return $link;
- }
- }
-
/**
* Generate HTML for an arrow or placeholder graphic
* @param string $dir one of '', 'd', 'l', 'r'
* @param string $alt text
+ * @param string $title text
* @return string HTML <img> tag
*/
- protected function arrow( $dir, $alt='' ) {
+ protected function arrow( $dir, $alt='', $title='' ) {
global $wgStylePath;
$encUrl = htmlspecialchars( $wgStylePath . '/common/images/Arr_' . $dir . '.png' );
$encAlt = htmlspecialchars( $alt );
- return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" />";
+ $encTitle = htmlspecialchars( $title );
+ return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" title=\"$encTitle\" />";
}
/**
@@ -772,7 +804,7 @@ class EnhancedChangesList extends ChangesList {
protected function sideArrow() {
global $wgContLang;
$dir = $wgContLang->isRTL() ? 'l' : 'r';
- return $this->arrow( $dir, '+' );
+ return $this->arrow( $dir, '+', wfMsg('rc-enhanced-expand') );
}
/**
@@ -781,7 +813,7 @@ class EnhancedChangesList extends ChangesList {
* @return string HTML <img> tag
*/
protected function downArrow() {
- return $this->arrow( 'd', '-' );
+ return $this->arrow( 'd', '-', wfMsg('rc-enhanced-hide') );
}
/**
@@ -789,7 +821,7 @@ class EnhancedChangesList extends ChangesList {
* @return string HTML <img> tag
*/
protected function spacerArrow() {
- return $this->arrow( '', ' ' );
+ return $this->arrow( '', codepointToUtf8( 0xa0 ) ); // non-breaking space
}
/**
@@ -806,16 +838,14 @@ class EnhancedChangesList extends ChangesList {
*/
protected function recentChangesBlockLine( $rcObj ) {
global $wgContLang, $wgRCShowChangedSize;
-
- # Get rc_xxxx variables
- // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
+ # Extract fields from DB into the function scope (rc_xxxx variables)
+ // FIXME: Would be good to replace this extract() call with something
+ // that explicitly initializes variables.
extract( $rcObj->mAttribs );
- $curIdEq = 'curid='.$rc_cur_id;
+ $curIdEq = "curid={$rc_cur_id}";
$r = '<table cellspacing="0" cellpadding="0" border="0" style="background: none"><tr>';
-
$r .= '<td valign="top" style="white-space: nowrap"><tt>' . $this->spacerArrow() . '&nbsp;';
-
# Flag and Timestamp
if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
$r .= '&nbsp;&nbsp;&nbsp;&nbsp;'; // 4 flags -> 4 spaces
@@ -823,33 +853,27 @@ class EnhancedChangesList extends ChangesList {
$r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, '&nbsp;', $rc_bot );
}
$r .= '&nbsp;'.$rcObj->timestamp.'&nbsp;</tt></td><td>';
-
# Article or log link
if( $rc_log_type ) {
$logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
$logname = LogPage::logName( $rc_log_type );
$r .= '(' . $this->skin->makeKnownLinkObj($logtitle, $logname ) . ')';
- } else if( !$this->userCan($rcObj,Revision::DELETED_TEXT) ) {
- $r .= '<span class="history-deleted">' . $rcObj->link . '</span>';
} else {
- $r .= $this->maybeWatchedLink( $rcObj->link, $rcObj->watched );
+ $this->insertArticleLink( $r, $rcObj, $rcObj->unpatrolled, $rcObj->watched );
}
-
# Diff and hist links
if ( $rc_type != RC_LOG ) {
- $r .= ' ('. $rcObj->difflink . $this->message['semicolon-separator'] . ' ';
- $r .= $this->skin->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' ) . ')';
+ $r .= ' ('. $rcObj->difflink . $this->message['semicolon-separator'];
+ $r .= $this->skin->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ),
+ $curIdEq.'&action=history' ) . ')';
}
$r .= ' . . ';
-
# Character diff
- if( $wgRCShowChangedSize ) {
- $r .= ( $rcObj->getCharacterDifference() == '' ? '' : '&nbsp;' . $rcObj->getCharacterDifference() . ' . . ' ) ;
+ if( $wgRCShowChangedSize && ($cd = $rcObj->getCharacterDifference()) ) {
+ $r .= "$cd . . ";
}
-
# User/talk
$r .= ' '.$rcObj->userlink . $rcObj->usertalklink;
-
# Log action (if any)
if( $rc_log_type ) {
if( $this->isDeleted($rcObj,LogPage::DELETED_ACTION) ) {
@@ -859,7 +883,6 @@ class EnhancedChangesList extends ChangesList {
$this->skin, LogPage::extractParams($rc_params), true, true );
}
}
-
# Edit or log comment
if( $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
// log comment
@@ -869,7 +892,6 @@ class EnhancedChangesList extends ChangesList {
$r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
}
}
-
# Show how many people are watching this if enabled
$r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers);
@@ -893,7 +915,6 @@ class EnhancedChangesList extends ChangesList {
$blockOut .= $this->recentChangesBlockGroup( $block );
}
}
-
return '<div>'.$blockOut.'</div>';
}
diff --git a/includes/Credits.php b/includes/Credits.php
index 6326e3a2..ae9377f2 100644
--- a/includes/Credits.php
+++ b/includes/Credits.php
@@ -20,167 +20,187 @@
* @author <evan@wikitravel.org>
*/
-/**
- * This is largely cadged from PageHistory::history
- */
-function showCreditsPage($article) {
- global $wgOut;
-
- $fname = 'showCreditsPage';
-
- wfProfileIn( $fname );
-
- $wgOut->setPageTitle( $article->mTitle->getPrefixedText() );
- $wgOut->setSubtitle( wfMsg( 'creditspage' ) );
- $wgOut->setArticleFlag( false );
- $wgOut->setArticleRelated( true );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
-
- if( $article->mTitle->getArticleID() == 0 ) {
- $s = wfMsg( 'nocredits' );
- } else {
- $s = getCredits($article, -1);
- }
-
- $wgOut->addHTML( $s );
-
- wfProfileOut( $fname );
-}
-
-function getCredits($article, $cnt, $showIfMax=true) {
- $fname = 'getCredits';
- wfProfileIn( $fname );
- $s = '';
-
- if (isset($cnt) && $cnt != 0) {
- $s = getAuthorCredits($article);
- if ($cnt > 1 || $cnt < 0) {
- $s .= ' ' . getContributorCredits($article, $cnt - 1, $showIfMax);
+class Credits {
+
+ /**
+ * This is largely cadged from PageHistory::history
+ * @param $article Article object
+ */
+ public static function showPage( Article $article ) {
+ global $wgOut;
+
+ wfProfileIn( __METHOD__ );
+
+ $wgOut->setPageTitle( $article->mTitle->getPrefixedText() );
+ $wgOut->setSubtitle( wfMsg( 'creditspage' ) );
+ $wgOut->setArticleFlag( false );
+ $wgOut->setArticleRelated( true );
+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
+
+ if( $article->mTitle->getArticleID() == 0 ) {
+ $s = wfMsg( 'nocredits' );
+ } else {
+ $s = self::getCredits($article, -1 );
}
+
+ $wgOut->addHTML( $s );
+
+ wfProfileOut( __METHOD__ );
}
- wfProfileOut( $fname );
- return $s;
-}
-
-/**
- *
- */
-function getAuthorCredits($article) {
- global $wgLang, $wgAllowRealName;
-
- $last_author = $article->getUser();
-
- if ($last_author == 0) {
- $author_credit = wfMsg('anonymous');
- } else {
- if($wgAllowRealName) { $real_name = User::whoIsReal($last_author); }
- $user_name = User::whoIs($last_author);
-
- if (!empty($real_name)) {
- $author_credit = creditLink($user_name, $real_name);
- } else {
- $author_credit = wfMsg('siteuser', creditLink($user_name));
+ /**
+ * Get a list of contributors of $article
+ * @param $article Article object
+ * @param $cnt Int: maximum list of contributors to show
+ * @param $showIfMax Bool: whether to contributors if there more than $cnt
+ * @return String: html
+ */
+ public static function getCredits($article, $cnt, $showIfMax=true) {
+ wfProfileIn( __METHOD__ );
+ $s = '';
+
+ if( isset( $cnt ) && $cnt != 0 ){
+ $s = self::getAuthor( $article );
+ if ($cnt > 1 || $cnt < 0) {
+ $s .= ' ' . self::getContributors( $article, $cnt - 1, $showIfMax );
+ }
}
- }
- $timestamp = $article->getTimestamp();
- if ($timestamp) {
- $d = $wgLang->date($article->getTimestamp(), true);
- $t = $wgLang->time($article->getTimestamp(), true);
- } else {
- $d = '';
- $t = '';
+ wfProfileOut( __METHOD__ );
+ return $s;
}
- return wfMsg('lastmodifiedatby', $d, $t, $author_credit);
-}
-
-/**
- *
- */
-function getContributorCredits($article, $cnt, $showIfMax) {
-
- global $wgLang, $wgAllowRealName;
- $contributors = $article->getContributors();
+ /**
+ * Get the last author with the last modification time
+ * @param $article Article object
+ */
+ protected static function getAuthor( Article $article ){
+ global $wgLang, $wgAllowRealName;
- $others_link = '';
+ $user = User::newFromId( $article->getUser() );
- # Hmm... too many to fit!
-
- if ($cnt > 0 && count($contributors) > $cnt) {
- $others_link = creditOthersLink($article);
- if (!$showIfMax) {
- return wfMsg('othercontribs', $others_link);
+ $timestamp = $article->getTimestamp();
+ if( $timestamp ){
+ $d = $wgLang->date( $article->getTimestamp(), true );
+ $t = $wgLang->time( $article->getTimestamp(), true );
} else {
- $contributors = array_slice($contributors, 0, $cnt);
+ $d = '';
+ $t = '';
}
+ return wfMsg( 'lastmodifiedatby', $d, $t, self::userLink( $user ) );
}
- $real_names = array();
- $user_names = array();
-
- $anon = '';
-
- # Sift for real versus user names
-
- foreach ($contributors as $user_parts) {
- if ($user_parts[0] != 0) {
- if ($wgAllowRealName && !empty($user_parts[2])) {
- $real_names[] = creditLink($user_parts[1], $user_parts[2]);
+ /**
+ * Get a list of contributors of $article
+ * @param $article Article object
+ * @param $cnt Int: maximum list of contributors to show
+ * @param $showIfMax Bool: whether to contributors if there more than $cnt
+ * @return String: html
+ */
+ protected static function getContributors( Article $article, $cnt, $showIfMax ) {
+ global $wgLang, $wgAllowRealName;
+
+ $contributors = $article->getContributors();
+
+ $others_link = '';
+
+ # Hmm... too many to fit!
+ if( $cnt > 0 && $contributors->count() > $cnt ){
+ $others_link = self::othersLink( $article );
+ if( !$showIfMax )
+ return wfMsg( 'othercontribs', $others_link );
+ }
+
+ $real_names = array();
+ $user_names = array();
+ $anon = 0;
+
+ # Sift for real versus user names
+ foreach( $contributors as $user ) {
+ $cnt--;
+ if( $user->isLoggedIn() ){
+ $link = self::link( $user );
+ if( $wgAllowRealName && $user->getRealName() )
+ $real_names[] = $link;
+ else
+ $user_names[] = $link;
} else {
- $user_names[] = creditLink($user_parts[1]);
+ $anon++;
+ }
+ if( $cnt == 0 ) break;
+ }
+
+ # Two strings: real names, and user names
+ $real = $wgLang->listToText( $real_names );
+ $user = $wgLang->listToText( $user_names );
+ if( $anon )
+ $anon = wfMsgExt( 'anonymous', array( 'parseinline' ), $anon );
+
+ # "ThisSite user(s) A, B and C"
+ if( !empty( $user ) ){
+ $user = wfMsgExt( 'siteusers', array( 'parsemag' ), $user, count( $user_names ) );
+ }
+
+ # This is the big list, all mooshed together. We sift for blank strings
+ $fulllist = array();
+ foreach( array( $real, $user, $anon, $others_link ) as $s ){
+ if( !empty( $s ) ){
+ array_push( $fulllist, $s );
}
- } else {
- $anon = wfMsg('anonymous');
}
- }
-
- # Two strings: real names, and user names
-
- $real = $wgLang->listToText($real_names);
- $user = $wgLang->listToText($user_names);
- # "ThisSite user(s) A, B and C"
+ # Make the list into text...
+ $creds = $wgLang->listToText( $fulllist );
- if (!empty($user)) {
- $user = wfMsg('siteusers', $user);
+ # "Based on work by ..."
+ return empty( $creds ) ? '' : wfMsg( 'othercontribs', $creds );
}
- # This is the big list, all mooshed together. We sift for blank strings
-
- $fulllist = array();
+ /**
+ * Get a link to $user_name page
+ * @param $user User object
+ * @return String: html
+ */
+ protected static function link( User $user ) {
+ global $wgUser, $wgAllowRealName;
+ if( $wgAllowRealName )
+ $real = $user->getRealName();
+ else
+ $real = false;
+
+ $skin = $wgUser->getSkin();
+ $page = $user->getUserPage();
+
+ return $skin->link( $page, htmlspecialchars( $real ? $real : $user->getName() ) );
+ }
- foreach (array($real, $user, $anon, $others_link) as $s) {
- if (!empty($s)) {
- array_push($fulllist, $s);
+ /**
+ * Get a link to $user_name page
+ * @param $user_name String: user name
+ * @param $linkText String: optional display
+ * @return String: html
+ */
+ protected static function userLink( User $user ) {
+ global $wgUser, $wgAllowRealName;
+ if( $user->isAnon() ){
+ return wfMsgExt( 'anonymous', array( 'parseinline' ), 1 );
+ } else {
+ $link = self::link( $user );
+ if( $wgAllowRealName && $user->getRealName() )
+ return $link;
+ else
+ return wfMsgExt( 'siteuser', array( 'parseinline', 'replaceafter' ), $link );
}
}
- # Make the list into text...
-
- $creds = $wgLang->listToText($fulllist);
-
- # "Based on work by ..."
-
- return (empty($creds)) ? '' : wfMsg('othercontribs', $creds);
-}
-
-/**
- *
- */
-function creditLink($user_name, $link_text = '') {
- global $wgUser, $wgContLang;
- $skin = $wgUser->getSkin();
- return $skin->makeLink($wgContLang->getNsText(NS_USER) . ':' . $user_name,
- htmlspecialchars( (empty($link_text)) ? $user_name : $link_text ));
-}
-
-/**
- *
- */
-function creditOthersLink($article) {
- global $wgUser;
- $skin = $wgUser->getSkin();
- return $skin->makeKnownLink($article->mTitle->getPrefixedText(), wfMsg('others'), 'action=credits');
-}
+ /**
+ * Get a link to action=credits of $article page
+ * @param $article Article object
+ * @return String: html
+ */
+ protected static function othersLink( Article $article ) {
+ global $wgUser;
+ $skin = $wgUser->getSkin();
+ return $skin->link( $article->getTitle(), wfMsgHtml( 'others' ), array(), array( 'action' => 'credits' ), array( 'known' ) );
+ }
+} \ No newline at end of file
diff --git a/includes/DatabaseFunctions.php b/includes/DatabaseFunctions.php
index ad6e7f6c..52e9a8c8 100644
--- a/includes/DatabaseFunctions.php
+++ b/includes/DatabaseFunctions.php
@@ -154,6 +154,7 @@ function wfFieldName( $res, $n, $dbi = DB_LAST )
/**
* @todo document function
+ * @see Database::insertId()
*/
function wfInsertId( $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -166,6 +167,7 @@ function wfInsertId( $dbi = DB_LAST ) {
/**
* @todo document function
+ * @see Database::dataSeek()
*/
function wfDataSeek( $res, $row, $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -177,7 +179,8 @@ function wfDataSeek( $res, $row, $dbi = DB_LAST ) {
}
/**
- * @todo document function
+ * Get the last error number
+ * @see Database::lastErrno()
*/
function wfLastErrno( $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -189,7 +192,8 @@ function wfLastErrno( $dbi = DB_LAST ) {
}
/**
- * @todo document function
+ * Get the last error
+ * @see Database::lastError()
*/
function wfLastError( $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -201,7 +205,8 @@ function wfLastError( $dbi = DB_LAST ) {
}
/**
- * @todo document function
+ * Get the number of affected rows
+ * @see Database::affectedRows()
*/
function wfAffectedRows( $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -213,7 +218,8 @@ function wfAffectedRows( $dbi = DB_LAST ) {
}
/**
- * @todo document function
+ * Get the last query ran
+ * @see Database::lastQuery
*/
function wfLastDBquery( $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -245,8 +251,8 @@ function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_MASTER )
/**
+ * Simple select wrapper, return one field
* @see Database::selectField()
- * @todo document function
* @param $table
* @param $var
* @param $cond Default ''
@@ -263,8 +269,8 @@ function wfGetSQL( $table, $var, $cond='', $dbi = DB_LAST )
}
/**
+ * Does a given field exist on the specified table?
* @see Database::fieldExists()
- * @todo document function
* @param $table
* @param $field
* @param $dbi Default DB_LAST
@@ -280,8 +286,8 @@ function wfFieldExists( $table, $field, $dbi = DB_LAST ) {
}
/**
+ * Does the requested index exist on the specified table?
* @see Database::indexExists()
- * @todo document function
* @param $table String
* @param $index
* @param $dbi Default DB_LAST
@@ -354,7 +360,8 @@ function wfUpdateArray( $table, $values, $conds, $fname = 'wfUpdateArray', $dbi
}
/**
- * @todo document function
+ * Get fully usable table name
+ * @see Database::tableName()
*/
function wfTableName( $name, $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -367,6 +374,7 @@ function wfTableName( $name, $dbi = DB_LAST ) {
/**
* @todo document function
+ * @see Database::strencode()
*/
function wfStrencode( $s, $dbi = DB_LAST ) {
$db = wfGetDB( $dbi );
@@ -379,6 +387,7 @@ function wfStrencode( $s, $dbi = DB_LAST ) {
/**
* @todo document function
+ * @see Database::nextSequenceValue()
*/
function wfNextSequenceValue( $seqName, $dbi = DB_MASTER ) {
$db = wfGetDB( $dbi );
@@ -391,6 +400,7 @@ function wfNextSequenceValue( $seqName, $dbi = DB_MASTER ) {
/**
* @todo document function
+ * @see Database::useIndexClause()
*/
function wfUseIndexClause( $index, $dbi = DB_SLAVE ) {
$db = wfGetDB( $dbi );
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index aaf934f5..ed68fe7a 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -27,11 +27,13 @@ if( !defined( 'MEDIAWIKI' ) ) {
* Create a site configuration object
* Not used for much in a default install
*/
-require_once( "$IP/includes/SiteConfiguration.php" );
-$wgConf = new SiteConfiguration;
+if ( !defined( 'MW_PHP4' ) ) {
+ require_once( "$IP/includes/SiteConfiguration.php" );
+ $wgConf = new SiteConfiguration;
+}
/** MediaWiki version number */
-$wgVersion = '1.13.4';
+$wgVersion = '1.14.0';
/** Name of the site. It must be changed in LocalSettings.php */
$wgSitename = 'MediaWiki';
@@ -539,10 +541,10 @@ $wgSMTP = false;
*/
/** database host name or ip address */
$wgDBserver = 'localhost';
-/** database port number */
-$wgDBport = '';
+/** database port number (for PostgreSQL) */
+$wgDBport = 5432;
/** name of the database */
-$wgDBname = 'wikidb';
+$wgDBname = 'my_wiki';
/** */
$wgDBconnection = '';
/** Database username */
@@ -572,6 +574,12 @@ $wgDBts2schema = 'public';
/** To override default SQLite data directory ($docroot/../data) */
$wgSQLiteDataDir = '';
+/** Default directory mode for SQLite data directory on creation.
+ * Note that this is different from the default directory mode used
+ * elsewhere.
+ */
+$wgSQLiteDataDirMode = 0700;
+
/**
* Make all database connections secretly go to localhost. Fool the load balancer
* thinking there is an arbitrarily large cluster of servers to connect to.
@@ -672,14 +680,6 @@ $wgDBClusterTimeout = 10;
*/
$wgDBAvgStatusPoll = 2000;
-/**
- * wgDBminWordLen :
- * MySQL 3.x : used to discard words that MySQL will not return any results for
- * shorter values configure mysql directly.
- * MySQL 4.x : ignore it and configure mySQL
- * See: http://dev.mysql.com/doc/mysql/en/Fulltext_Fine-tuning.html
- */
-$wgDBminWordLen = 4;
/** Set to true if using InnoDB tables */
$wgDBtransactions = false;
/** Set to true for compatibility with extensions that might be checking.
@@ -745,12 +745,6 @@ $wgLocalMessageCache = false;
*/
$wgLocalMessageCacheSerialized = true;
-/**
- * Directory for compiled constant message array databases
- * WARNING: turning anything on will just break things, aaaaaah!!!!
- */
-$wgCachedMessageArrays = false;
-
# Language settings
#
/** Site language code, should be one of ./languages/Language(.*).php */
@@ -844,7 +838,6 @@ $wgTranslateNumerals = true;
/**
* Translation using MediaWiki: namespace.
- * This will increase load times by 25-60% unless memcached is installed.
* Interface messages will be loaded from the database.
*/
$wgUseDatabaseMessages = true;
@@ -860,6 +853,14 @@ $wgMsgCacheExpiry = 86400;
$wgMaxMsgCacheEntrySize = 10000;
/**
+ * If true, serialized versions of the messages arrays will be
+ * read from the 'serialized' subdirectory if they are present.
+ * Set to false to always use the Messages files, regardless of
+ * whether they are up to date or not.
+ */
+$wgEnableSerializedMessages = true;
+
+/**
* Set to false if you are thorough system admin who always remembers to keep
* serialized files up to date to save few mtime calls.
*/
@@ -868,6 +869,9 @@ $wgCheckSerialized = true;
/** Whether to enable language variant conversion. */
$wgDisableLangConversion = false;
+/** Whether to enable language variant conversion for links. */
+$wgDisableTitleConversion = false;
+
/** Default variant code, if false, the default will be the language code */
$wgDefaultLanguageVariant = false;
@@ -947,26 +951,68 @@ $wgMaxPPNodeCount = 1000000; # A complexity limit on template expansion
$wgMaxTemplateDepth = 40;
$wgMaxPPExpandDepth = 40;
+/**
+ * If true, removes (substitutes) templates in "~~~~" signatures.
+ */
+$wgCleanSignatures = true;
+
$wgExtraSubtitle = '';
$wgSiteSupportPage = ''; # A page where you users can receive donations
+/**
+ * Set this to a string to put the wiki into read-only mode. The text will be
+ * used as an explanation to users.
+ *
+ * This prevents most write operations via the web interface. Cache updates may
+ * still be possible. To prevent database writes completely, use the read_only
+ * option in MySQL.
+ */
+$wgReadOnly = null;
+
/***
- * If this lock file exists, the wiki will be forced into read-only mode.
+ * If this lock file exists (size > 0), the wiki will be forced into read-only mode.
* Its contents will be shown to users as part of the read-only warning
* message.
*/
$wgReadOnlyFile = false; ///< defaults to "{$wgUploadDirectory}/lock_yBgMBwiR";
/**
+ * Filename for debug logging.
* The debug log file should be not be publicly accessible if it is used, as it
- * may contain private data. */
+ * may contain private data.
+ */
$wgDebugLogFile = '';
+/**
+ * Prefix for debug log lines
+ */
+$wgDebugLogPrefix = '';
+
+/**
+ * If true, instead of redirecting, show a page with a link to the redirect
+ * destination. This allows for the inspection of PHP error messages, and easy
+ * resubmission of form data. For developer use only.
+ */
$wgDebugRedirects = false;
-$wgDebugRawPage = false; # Avoid overlapping debug entries by leaving out CSS
+/**
+ * If true, log debugging data from action=raw.
+ * This is normally false to avoid overlapping debug entries due to gen=css and
+ * gen=js requests.
+ */
+$wgDebugRawPage = false;
+
+/**
+ * Send debug data to an HTML comment in the output.
+ *
+ * This may occasionally be useful when supporting a non-technical end-user. It's
+ * more secure than exposing the debug log file to the web, since the output only
+ * contains private data for the current user. But it's not ideal for development
+ * use since data is lost on fatal errors and redirects.
+ */
$wgDebugComments = false;
-$wgReadOnly = null;
+
+/** Does nothing. Obsolete? */
$wgLogQueries = false;
/**
@@ -1025,11 +1071,18 @@ $wgUseCategoryBrowser = false;
* same options.
*
* This can provide a significant speedup for medium to large pages,
- * so you probably want to keep it on.
+ * so you probably want to keep it on. Extensions that conflict with the
+ * parser cache should disable the cache on a per-page basis instead.
*/
$wgEnableParserCache = true;
/**
+ * Append a configured value to the parser cache and the sitenotice key so
+ * that they can be kept separate for some class of activity.
+ */
+$wgRenderHashAppend = '';
+
+/**
* If on, the sidebar navigation links are cached for users with the
* current language set. This can save a touch of load on a busy site
* by shaving off extra message lookups.
@@ -1070,7 +1123,7 @@ $wgHitcounterUpdateFreq = 1;
$wgSysopUserBans = true; # Allow sysops to ban logged-in users
$wgSysopRangeBans = true; # Allow sysops to ban IP ranges
$wgAutoblockExpiry = 86400; # Number of seconds before autoblock entries expire
-$wgBlockAllowsUTEdit = false; # Blocks allow users to edit their own user talk page
+$wgBlockAllowsUTEdit = false; # Default setting for option on block form to allow self talkpage editing whilst blocked
$wgSysopEmailBans = true; # Allow sysops to ban users from accessing Emailuser
# Pages anonymous user may see as an array, e.g.:
@@ -1110,40 +1163,42 @@ $wgEmailConfirmToEdit=false;
$wgGroupPermissions = array();
// Implicit group for all visitors
-$wgGroupPermissions['*' ]['createaccount'] = true;
-$wgGroupPermissions['*' ]['read'] = true;
-$wgGroupPermissions['*' ]['edit'] = true;
-$wgGroupPermissions['*' ]['createpage'] = true;
-$wgGroupPermissions['*' ]['createtalk'] = true;
-$wgGroupPermissions['*' ]['writeapi'] = true;
+$wgGroupPermissions['*']['createaccount'] = true;
+$wgGroupPermissions['*']['read'] = true;
+$wgGroupPermissions['*']['edit'] = true;
+$wgGroupPermissions['*']['createpage'] = true;
+$wgGroupPermissions['*']['createtalk'] = true;
+$wgGroupPermissions['*']['writeapi'] = true;
// Implicit group for all logged-in accounts
-$wgGroupPermissions['user' ]['move'] = true;
-$wgGroupPermissions['user' ]['move-subpages'] = true;
-$wgGroupPermissions['user' ]['read'] = true;
-$wgGroupPermissions['user' ]['edit'] = true;
-$wgGroupPermissions['user' ]['createpage'] = true;
-$wgGroupPermissions['user' ]['createtalk'] = true;
-$wgGroupPermissions['user' ]['writeapi'] = true;
-$wgGroupPermissions['user' ]['upload'] = true;
-$wgGroupPermissions['user' ]['reupload'] = true;
-$wgGroupPermissions['user' ]['reupload-shared'] = true;
-$wgGroupPermissions['user' ]['minoredit'] = true;
-$wgGroupPermissions['user' ]['purge'] = true; // can use ?action=purge without clicking "ok"
+$wgGroupPermissions['user']['move'] = true;
+$wgGroupPermissions['user']['move-subpages'] = true;
+$wgGroupPermissions['user']['move-rootuserpages'] = true; // can move root userpages
+//$wgGroupPermissions['user']['movefile'] = true; // Disabled for now due to possible bugs and security concerns
+$wgGroupPermissions['user']['read'] = true;
+$wgGroupPermissions['user']['edit'] = true;
+$wgGroupPermissions['user']['createpage'] = true;
+$wgGroupPermissions['user']['createtalk'] = true;
+$wgGroupPermissions['user']['writeapi'] = true;
+$wgGroupPermissions['user']['upload'] = true;
+$wgGroupPermissions['user']['reupload'] = true;
+$wgGroupPermissions['user']['reupload-shared'] = true;
+$wgGroupPermissions['user']['minoredit'] = true;
+$wgGroupPermissions['user']['purge'] = true; // can use ?action=purge without clicking "ok"
// Implicit group for accounts that pass $wgAutoConfirmAge
$wgGroupPermissions['autoconfirmed']['autoconfirmed'] = true;
// Users with bot privilege can have their edits hidden
// from various log pages by default
-$wgGroupPermissions['bot' ]['bot'] = true;
-$wgGroupPermissions['bot' ]['autoconfirmed'] = true;
-$wgGroupPermissions['bot' ]['nominornewtalk'] = true;
-$wgGroupPermissions['bot' ]['autopatrol'] = true;
-$wgGroupPermissions['bot' ]['suppressredirect'] = true;
-$wgGroupPermissions['bot' ]['apihighlimits'] = true;
-$wgGroupPermissions['bot' ]['writeapi'] = true;
-#$wgGroupPermissions['bot' ]['editprotected'] = true; // can edit all protected pages without cascade protection enabled
+$wgGroupPermissions['bot']['bot'] = true;
+$wgGroupPermissions['bot']['autoconfirmed'] = true;
+$wgGroupPermissions['bot']['nominornewtalk'] = true;
+$wgGroupPermissions['bot']['autopatrol'] = true;
+$wgGroupPermissions['bot']['suppressredirect'] = true;
+$wgGroupPermissions['bot']['apihighlimits'] = true;
+$wgGroupPermissions['bot']['writeapi'] = true;
+#$wgGroupPermissions['bot']['editprotected'] = true; // can edit all protected pages without cascade protection enabled
// Most extra permission abilities go to this group
$wgGroupPermissions['sysop']['block'] = true;
@@ -1158,6 +1213,7 @@ $wgGroupPermissions['sysop']['import'] = true;
$wgGroupPermissions['sysop']['importupload'] = true;
$wgGroupPermissions['sysop']['move'] = true;
$wgGroupPermissions['sysop']['move-subpages'] = true;
+$wgGroupPermissions['sysop']['move-rootuserpages'] = true;
$wgGroupPermissions['sysop']['patrol'] = true;
$wgGroupPermissions['sysop']['autopatrol'] = true;
$wgGroupPermissions['sysop']['protect'] = true;
@@ -1173,10 +1229,10 @@ $wgGroupPermissions['sysop']['upload_by_url'] = true;
$wgGroupPermissions['sysop']['ipblock-exempt'] = true;
$wgGroupPermissions['sysop']['blockemail'] = true;
$wgGroupPermissions['sysop']['markbotedits'] = true;
-$wgGroupPermissions['sysop']['suppressredirect'] = true;
$wgGroupPermissions['sysop']['apihighlimits'] = true;
$wgGroupPermissions['sysop']['browsearchive'] = true;
$wgGroupPermissions['sysop']['noratelimit'] = true;
+$wgGroupPermissions['sysop']['movefile'] = true;
#$wgGroupPermissions['sysop']['mergehistory'] = true;
// Permission to change users' group assignments
@@ -1208,8 +1264,22 @@ $wgGroupPermissions['bureaucrat']['noratelimit'] = true;
$wgImplicitGroups = array( '*', 'user', 'autoconfirmed' );
/**
- * These are the groups that users are allowed to add to or remove from
- * their own account via Special:Userrights.
+ * A map of group names that the user is in, to group names that those users
+ * are allowed to add or revoke.
+ *
+ * Setting the list of groups to add or revoke to true is equivalent to "any group".
+ *
+ * For example, to allow sysops to add themselves to the "bot" group:
+ *
+ * $wgGroupsAddToSelf = array( 'sysop' => array( 'bot' ) );
+ *
+ * Implicit groups may be used for the source group, for instance:
+ *
+ * $wgGroupsRemoveFromSelf = array( '*' => true );
+ *
+ * This allows users in the '*' group (i.e. any user) to remove themselves from
+ * any group that they happen to be in.
+ *
*/
$wgGroupsAddToSelf = array();
$wgGroupsRemoveFromSelf = array();
@@ -1237,9 +1307,10 @@ $wgRestrictionLevels = array( '', 'autoconfirmed', 'sysop' );
* Set the minimum permissions required to edit pages in each
* namespace. If you list more than one permission, a user must
* have all of them to edit pages in that namespace.
+ *
+ * Note: NS_MEDIAWIKI is implicitly restricted to editinterface.
*/
$wgNamespaceProtection = array();
-$wgNamespaceProtection[ NS_MEDIAWIKI ] = array( 'editinterface' );
/**
* Pages in namespaces in this array can not be used as templates.
@@ -1303,8 +1374,8 @@ $wgAutopromote = array(
* // Sysops can disable other sysops in an emergency, and disable bots
* $wgRemoveGroups['sysop'] = array( 'sysop', 'bot' );
*/
-$wgAddGroups = $wgRemoveGroups = array();
-
+$wgAddGroups = array();
+$wgRemoveGroups = array();
/**
* A list of available rights, in addition to the ones defined by the core.
@@ -1375,7 +1446,7 @@ $wgCacheEpoch = '20030516000000';
* to ensure that client-side caches don't keep obsolete copies of global
* styles.
*/
-$wgStyleVersion = '164';
+$wgStyleVersion = '195';
# Server-side caching:
@@ -1439,6 +1510,9 @@ $wgEnotifMaxRecips = 500;
# Send mails via the job queue.
$wgEnotifUseJobQ = false;
+# Use real name instead of username in e-mail "from" field
+$wgEnotifUseRealName = false;
+
/**
* Array of usernames who will be sent a notification email for every change which occurs on a wiki
*/
@@ -1456,14 +1530,17 @@ $wgRCShowChangedSize = true;
* before and after the edit is below that value, the value will be
* highlighted on the RC page.
*/
-$wgRCChangedSizeThreshold = -500;
+$wgRCChangedSizeThreshold = 500;
/**
* Show "Updated (since my last visit)" marker in RC view, watchlist and history
* view for watched pages with new changes */
$wgShowUpdatedMarker = true;
-$wgCookieExpiration = 2592000;
+/**
+ * Default cookie expiration time. Setting to 0 makes all cookies session-only.
+ */
+$wgCookieExpiration = 30*86400;
/** Clock skew or the one-second resolution of time() can occasionally cause cache
* problems when the user requests two pages within a short period of time. This
@@ -1523,6 +1600,9 @@ $wgHTCPMulticastTTL = 1;
# $wgHTCPMulticastAddress = "224.0.0.85";
$wgHTCPMulticastAddress = false;
+/** Should forwarded Private IPs be accepted? */
+$wgUsePrivateIPs = false;
+
# Cookie settings:
#
/**
@@ -1572,14 +1652,26 @@ $wgAllowExternalImages = false;
/** If the above is false, you can specify an exception here. Image URLs
* that start with this string are then rendered, while all others are not.
* You can use this to set up a trusted, simple repository of images.
+ * You may also specify an array of strings to allow multiple sites
*
- * Example:
+ * Examples:
* $wgAllowExternalImagesFrom = 'http://127.0.0.1/';
+ * $wgAllowExternalImagesFrom = array( 'http://127.0.0.1/', 'http://example.com' );
*/
$wgAllowExternalImagesFrom = '';
-/** Allows to move images and other media files. Experemintal, not sure if it always works */
-$wgAllowImageMoving = false;
+/** If $wgAllowExternalImages is false, you can allow an on-wiki
+ * whitelist of regular expression fragments to match the image URL
+ * against. If the image matches one of the regular expression fragments,
+ * The image will be displayed.
+ *
+ * Set this to true to enable the on-wiki whitelist (MediaWiki:External image whitelist)
+ * Or false to disable it
+ */
+$wgEnableImageWhitelist = true;
+
+/** Allows to move images and other media files */
+$wgAllowImageMoving = true;
/** Disable database-intensive features */
$wgMiserMode = false;
@@ -1598,6 +1690,7 @@ $wgAllowSlowParserFunctions = false;
*/
$wgJobClasses = array(
'refreshLinks' => 'RefreshLinksJob',
+ 'refreshLinks2' => 'RefreshLinksJob2',
'htmlCacheUpdate' => 'HTMLCacheUpdateJob',
'html_cache_update' => 'HTMLCacheUpdateJob', // backwards-compatible
'sendMail' => 'EmaillingJob',
@@ -1606,6 +1699,14 @@ $wgJobClasses = array(
);
/**
+ * Additional functions to be performed with updateSpecialPages.
+ * Expensive Querypages are already updated.
+ */
+$wgSpecialPageCacheUpdates = array(
+ 'Statistics' => array('SiteStatsUpdate','cacheUpdate')
+);
+
+/**
* To use inline TeX, you need to compile 'texvc' (in the 'math' subdirectory of
* the MediaWiki package and have latex, dvips, gs (ghostscript), andconvert
* (ImageMagick) installed and available in the PATH.
@@ -1797,7 +1898,10 @@ $wgMimeTypeBlacklist= array(
# Client-side hazards on Internet Explorer
'text/scriptlet', 'application/x-msdownload',
# Windows metafile, client-side vulnerability on some systems
- 'application/x-msmetafile'
+ 'application/x-msmetafile',
+ # A ZIP file may be a valid Java archive containing an applet which exploits the
+ # same-origin policy to steal cookies
+ 'application/zip',
);
/** This is a flag to determine whether or not to check file extensions on upload. */
@@ -1823,7 +1927,7 @@ $wgNamespacesWithSubpages = array(
NS_USER => true,
NS_USER_TALK => true,
NS_PROJECT_TALK => true,
- NS_IMAGE_TALK => true,
+ NS_FILE_TALK => true,
NS_MEDIAWIKI_TALK => true,
NS_TEMPLATE_TALK => true,
NS_HELP_TALK => true,
@@ -1835,6 +1939,21 @@ $wgNamespacesToBeSearchedDefault = array(
);
/**
+ * Additional namespaces to those in $wgNamespacesToBeSearchedDefault that
+ * will be added to default search for "project" page inclusive searches
+ *
+ * Same format as $wgNamespacesToBeSearchedDefault
+ */
+$wgNamespacesToBeSearchedProject = array(
+ NS_USER => true,
+ NS_PROJECT => true,
+ NS_HELP => true,
+ NS_CATEGORY => true,
+);
+
+$wgUseOldSearchUI = true; // temp testing variable
+
+/**
* Site notice shown at the top of each page
*
* This message can contain wiki text, and can also be set through the