From cecb985bee3bdd252e1b8dc0bd500b37cd52be01 Mon Sep 17 00:00:00 2001
From: Pierre Schmitz
Date: Wed, 16 May 2007 20:58:53 +0000
Subject: Aktualisierung auf MediaWiki 1.10.0 Plugins angepasst und verbessert
kleine Korrekturen am Design
---
HISTORY | 691 ++++
Makefile | 7 +
RELEASE-NOTES | 1266 +++---
Test.php | 307 ++
bin/svnstat | 2 +
bin/ulimit4.sh | 4 +
config/index.php | 169 +-
docs/database.txt | 10 +-
docs/deferred.txt | 8 +
docs/design.txt | 19 +-
docs/hooks.txt | 61 +
docs/memcached.txt | 10 +-
docs/title.txt | 15 +-
extensions/FunnyDot.php | 16 +-
extensions/LLAuthPlugin.php | 202 +-
extensions/README | 17 +-
img_auth.php | 1 +
includes/AjaxDispatcher.php | 23 +-
includes/AjaxFunctions.php | 95 +-
includes/AjaxResponse.php | 70 +-
includes/Article.php | 463 ++-
includes/AuthPlugin.php | 8 +-
includes/AutoLoader.php | 49 +-
includes/BagOStuff.php | 41 +-
includes/Block.php | 100 +-
includes/CacheDependency.php | 21 +-
includes/CategoryPage.php | 35 +-
includes/Categoryfinder.php | 73 +-
includes/ChangesList.php | 78 +-
includes/CoreParserFunctions.php | 23 +-
includes/Credits.php | 1 -
includes/Database.php | 295 +-
includes/DatabaseFunctions.php | 53 +-
includes/DatabaseOracle.php | 788 ++--
includes/DatabasePostgres.php | 332 +-
includes/DateFormatter.php | 10 +-
includes/DefaultSettings.php | 198 +-
includes/Defines.php | 1 -
includes/DifferenceEngine.php | 127 +-
includes/DjVuImage.php | 134 +-
includes/EditPage.php | 615 +--
includes/Exception.php | 30 +-
includes/Exif.php | 30 +-
includes/Export.php | 38 +-
includes/ExternalEdit.php | 4 +-
includes/ExternalStore.php | 1 -
includes/ExternalStoreDB.php | 2 -
includes/ExternalStoreHttp.php | 1 -
includes/FakeTitle.php | 3 +-
includes/Feed.php | 18 +-
includes/FileStore.php | 16 +-
includes/GlobalFunctions.php | 197 +-
includes/HTMLCacheUpdate.php | 9 +-
includes/HTMLFileCache.php | 4 +-
includes/HTMLForm.php | 4 +-
includes/HistoryBlob.php | 98 +-
includes/Hooks.php | 3 +-
includes/IP.php | 279 +-
includes/Image.php | 1279 +++----
includes/ImageFunctions.php | 2 +-
includes/ImageGallery.php | 137 +-
includes/ImagePage.php | 256 +-
includes/ImageQueryPage.php | 68 +
includes/JobQueue.php | 125 +-
includes/Licenses.php | 12 +-
includes/LinkBatch.php | 7 +-
includes/LinkCache.php | 15 +-
includes/LinkFilter.php | 46 +-
includes/Linker.php | 322 +-
includes/LinksUpdate.php | 16 +-
includes/LoadBalancer.php | 13 +-
includes/LogPage.php | 56 +-
includes/MacBinary.php | 7 +-
includes/MagicWord.php | 7 +-
includes/Math.php | 8 +-
includes/MediaTransformOutput.php | 166 +
includes/MemcachedSessions.php | 1 -
includes/MessageCache.php | 10 +-
includes/Metadata.php | 5 +-
includes/MimeMagic.php | 39 +-
includes/Namespace.php | 16 +-
includes/ObjectCache.php | 6 +-
includes/OutputHandler.php | 64 +
includes/OutputPage.php | 122 +-
includes/PageHistory.php | 59 +-
includes/PageQueryPage.php | 26 +
includes/Pager.php | 57 +-
includes/Parser.php | 522 +--
includes/ParserCache.php | 28 +-
includes/ParserOptions.php | 119 +
includes/ParserOutput.php | 133 +
includes/PatrolLog.php | 83 +
includes/Profiler.php | 11 +-
includes/ProfilerSimple.php | 19 +-
includes/ProfilerSimpleUDP.php | 11 +-
includes/ProtectionForm.php | 183 +-
includes/ProxyTools.php | 50 +-
includes/QueryPage.php | 223 +-
includes/RawPage.php | 35 +-
includes/RecentChange.php | 12 +-
includes/Revision.php | 85 +-
includes/Sanitizer.php | 184 +-
includes/SearchEngine.php | 48 +-
includes/SearchMySQL.php | 13 +-
includes/SearchMySQL4.php | 12 +-
includes/SearchOracle.php | 235 ++
includes/SearchPostgres.php | 176 +-
includes/SearchTsearch2.php | 20 +-
includes/SearchUpdate.php | 16 +-
includes/Setup.php | 4 +-
includes/SiteConfiguration.php | 10 +-
includes/SiteStats.php | 53 +-
includes/Skin.php | 111 +-
includes/SkinTemplate.php | 114 +-
includes/SpecialAllmessages.php | 9 +-
includes/SpecialAllpages.php | 61 +-
includes/SpecialAncientpages.php | 10 +-
includes/SpecialBlockip.php | 293 +-
includes/SpecialBlockme.php | 3 +-
includes/SpecialBooksources.php | 9 +-
includes/SpecialBrokenRedirects.php | 43 +-
includes/SpecialCategories.php | 103 +-
includes/SpecialConfirmemail.php | 16 +-
includes/SpecialContributions.php | 568 ++-
includes/SpecialDeadendpages.php | 18 +-
includes/SpecialDisambiguations.php | 129 +-
includes/SpecialDoubleRedirects.php | 30 +-
includes/SpecialEmailuser.php | 23 +-
includes/SpecialExport.php | 71 +-
includes/SpecialFewestrevisions.php | 65 +
includes/SpecialImagelist.php | 22 +-
includes/SpecialImport.php | 123 +-
includes/SpecialIpblocklist.php | 61 +-
includes/SpecialListredirects.php | 10 +-
includes/SpecialListusers.php | 301 +-
includes/SpecialLockdb.php | 10 +-
includes/SpecialLog.php | 173 +-
includes/SpecialLonelypages.php | 11 +-
includes/SpecialLongpages.php | 15 +-
includes/SpecialMIMEsearch.php | 14 +-
includes/SpecialMostcategories.php | 9 +-
includes/SpecialMostimages.php | 29 +-
includes/SpecialMostlinked.php | 13 +-
includes/SpecialMostlinkedcategories.php | 10 +-
includes/SpecialMostrevisions.php | 8 +-
includes/SpecialMovepage.php | 35 +-
includes/SpecialNewimages.php | 33 +-
includes/SpecialNewpages.php | 31 +-
includes/SpecialPage.php | 41 +-
includes/SpecialPopularpages.php | 34 +-
includes/SpecialPreferences.php | 49 +-
includes/SpecialPrefixindex.php | 13 +-
includes/SpecialProtectedpages.php | 260 ++
includes/SpecialRandompage.php | 142 +-
includes/SpecialRandomredirect.php | 47 +-
includes/SpecialRecentchanges.php | 17 +-
includes/SpecialRecentchangeslinked.php | 54 +-
includes/SpecialResetpass.php | 9 +-
includes/SpecialRevisiondelete.php | 9 +-
includes/SpecialSearch.php | 22 +-
includes/SpecialShortpages.php | 8 +-
includes/SpecialSpecialpages.php | 5 +-
includes/SpecialStatistics.php | 17 +-
includes/SpecialUncategorizedcategories.php | 8 +-
includes/SpecialUncategorizedimages.php | 26 +-
includes/SpecialUncategorizedpages.php | 10 +-
includes/SpecialUndelete.php | 204 +-
includes/SpecialUnlockdb.php | 6 +-
includes/SpecialUnusedcategories.php | 8 +-
includes/SpecialUnusedimages.php | 39 +-
includes/SpecialUnusedtemplates.php | 13 +-
includes/SpecialUnwatchedpages.php | 14 +-
includes/SpecialUpload.php | 151 +-
includes/SpecialUploadMogile.php | 10 +-
includes/SpecialUserlogin.php | 88 +-
includes/SpecialUserlogout.php | 3 +-
includes/SpecialUserrights.php | 89 +-
includes/SpecialVersion.php | 28 +-
includes/SpecialWantedcategories.php | 12 +-
includes/SpecialWantedpages.php | 10 +-
includes/SpecialWatchlist.php | 46 +-
includes/SpecialWhatlinkshere.php | 170 +-
includes/SpecialWithoutinterwiki.php | 56 +
includes/SquidUpdate.php | 6 +-
includes/StringUtils.php | 4 +-
includes/StubObject.php | 7 +-
includes/Title.php | 829 ++--
includes/User.php | 249 +-
includes/UserMailer.php | 42 +-
includes/Utf8Case.php | 3 +-
includes/WatchedItem.php | 29 +-
includes/WebRequest.php | 46 +-
includes/WebResponse.php | 14 +-
includes/WebStart.php | 12 +
includes/Wiki.php | 107 +-
includes/WikiError.php | 9 +-
includes/Xml.php | 12 +-
includes/XmlFunctions.php | 2 +-
includes/ZhClient.php | 2 -
includes/ZhConversion.php | 1 -
includes/api/ApiBase.php | 9 +-
includes/api/ApiFeedWatchlist.php | 6 +-
includes/api/ApiFormatBase.php | 9 +-
includes/api/ApiFormatJson.php | 8 +-
includes/api/ApiFormatJson_json.php | 51 +-
includes/api/ApiFormatPhp.php | 8 +-
includes/api/ApiFormatWddx.php | 8 +-
includes/api/ApiFormatXml.php | 8 +-
includes/api/ApiFormatYaml.php | 8 +-
includes/api/ApiFormatYaml_spyc.php | 13 +-
includes/api/ApiHelp.php | 8 +-
includes/api/ApiLogin.php | 6 +-
includes/api/ApiMain.php | 9 +-
includes/api/ApiOpenSearch.php | 8 +-
includes/api/ApiPageSet.php | 16 +-
includes/api/ApiQuery.php | 10 +-
includes/api/ApiQueryAllpages.php | 8 +-
includes/api/ApiQueryBacklinks.php | 10 +-
includes/api/ApiQueryBase.php | 9 +-
includes/api/ApiQueryInfo.php | 6 +-
includes/api/ApiQueryLogEvents.php | 8 +-
includes/api/ApiQueryRecentChanges.php | 10 +-
includes/api/ApiQueryRevisions.php | 8 +-
includes/api/ApiQuerySiteinfo.php | 8 +-
includes/api/ApiQueryUserContributions.php | 8 +-
includes/api/ApiQueryWatchlist.php | 6 +-
includes/api/ApiResult.php | 8 +-
includes/media/BMP.php | 31 +
includes/media/Bitmap.php | 236 ++
includes/media/DjVu.php | 206 +
includes/media/Generic.php | 298 ++
includes/media/SVG.php | 97 +
includes/memcached-client.php | 2 +-
includes/mime.info | 5 +-
includes/mime.types | 1 +
includes/normal/CleanUpTest.php | 36 +-
includes/normal/Makefile | 36 +-
includes/normal/README | 4 +
includes/normal/RandomTest.php | 4 +-
includes/normal/Utf8Test.php | 2 +-
includes/normal/UtfNormal.php | 39 +-
includes/normal/UtfNormalBench.php | 10 +-
includes/normal/UtfNormalData.inc | 9 +-
includes/normal/UtfNormalDataK.inc | 3 +-
includes/normal/UtfNormalGenerate.php | 4 +-
includes/normal/UtfNormalTest.php | 2 +-
includes/normal/UtfNormalUtil.php | 2 +-
includes/proxy_check.php | 1 -
includes/templates/Userlogin.php | 9 +-
includes/tidy.conf | 18 +
index.php | 41 +
install-utils.inc | 50 +-
languages/Language.php | 83 +-
languages/LanguageConverter.php | 12 +-
languages/Names.php | 60 +-
languages/classes/LanguageAr.php | 28 +
languages/classes/LanguageAz.php | 3 +-
languages/classes/LanguageBe.php | 8 +-
languages/classes/LanguageBe_x_old.php | 88 +
languages/classes/LanguageBg.php | 6 +-
languages/classes/LanguageBs.php | 3 +-
languages/classes/LanguageCs.php | 3 +-
languages/classes/LanguageCu.php | 3 +-
languages/classes/LanguageEo.php | 3 +-
languages/classes/LanguageEt.php | 3 +-
languages/classes/LanguageFi.php | 10 +-
languages/classes/LanguageFr.php | 3 +-
languages/classes/LanguageGa.php | 3 +-
languages/classes/LanguageGsw.php | 3 +-
languages/classes/LanguageHe.php | 3 +-
languages/classes/LanguageHr.php | 3 +-
languages/classes/LanguageHsb.php | 3 +-
languages/classes/LanguageHu.php | 3 +-
languages/classes/LanguageHy.php | 73 +
languages/classes/LanguageJa.php | 3 +-
languages/classes/LanguageKk.php | 48 +-
languages/classes/LanguageKk_kz.php | 3 +-
languages/classes/LanguageKo.php | 4 +-
languages/classes/LanguageKsh.php | 3 +-
languages/classes/LanguageLa.php | 57 +-
languages/classes/LanguageLt.php | 3 +-
languages/classes/LanguageLv.php | 3 +-
languages/classes/LanguagePt_br.php | 3 +-
languages/classes/LanguageRu.php | 3 +-
languages/classes/LanguageSk.php | 3 +-
languages/classes/LanguageSl.php | 111 +-
languages/classes/LanguageSr.php | 5 +-
languages/classes/LanguageSr_ec.php | 3 +-
languages/classes/LanguageSr_el.php | 3 +-
languages/classes/LanguageTr.php | 3 +-
languages/classes/LanguageTyv.php | 3 +-
languages/classes/LanguageUk.php | 88 +
languages/classes/LanguageWa.php | 3 +-
languages/classes/LanguageZh.php | 3 +-
languages/classes/LanguageZh_cn.php | 3 +-
languages/classes/LanguageZh_yue.php | 3 +-
languages/messages/MessagesAf.php | 39 +-
languages/messages/MessagesAr.php | 2481 +++++++++---
languages/messages/MessagesArc.php | 3 +-
languages/messages/MessagesAs.php | 3 +-
languages/messages/MessagesAst.php | 3 +-
languages/messages/MessagesAv.php | 3 +-
languages/messages/MessagesAy.php | 7 +-
languages/messages/MessagesAz.php | 953 +++--
languages/messages/MessagesBa.php | 362 +-
languages/messages/MessagesBar.php | 3 +-
languages/messages/MessagesBat_smg.php | 3 +-
languages/messages/MessagesBe.php | 1786 +++++----
languages/messages/MessagesBe_x_old.php | 1028 +++++
languages/messages/MessagesBg.php | 3208 ++++++++++------
languages/messages/MessagesBh.php | 20 +
languages/messages/MessagesBm.php | 3 +-
languages/messages/MessagesBn.php | 3 +-
languages/messages/MessagesBo.php | 3 +-
languages/messages/MessagesBpy.php | 572 +--
languages/messages/MessagesBr.php | 2778 +++++++++-----
languages/messages/MessagesBs.php | 219 +-
languages/messages/MessagesCa.php | 3015 +++++++++------
languages/messages/MessagesCe.php | 3 +-
languages/messages/MessagesCs.php | 3007 ++++++++-------
languages/messages/MessagesCsb.php | 17 +-
languages/messages/MessagesCu.php | 2 +-
languages/messages/MessagesCv.php | 414 +-
languages/messages/MessagesCy.php | 68 +-
languages/messages/MessagesDa.php | 257 +-
languages/messages/MessagesDe.php | 1031 ++---
languages/messages/MessagesDv.php | 3 +-
languages/messages/MessagesDz.php | 3 +-
languages/messages/MessagesEl.php | 296 +-
languages/messages/MessagesEn.php | 651 ++--
languages/messages/MessagesEo.php | 2096 +++++-----
languages/messages/MessagesEs.php | 235 +-
languages/messages/MessagesEt.php | 49 +-
languages/messages/MessagesEu.php | 229 +-
languages/messages/MessagesFa.php | 26 +-
languages/messages/MessagesFi.php | 3174 +++++++--------
languages/messages/MessagesFiu_vro.php | 2023 ++++++++++
languages/messages/MessagesFo.php | 13 +-
languages/messages/MessagesFr.php | 3061 +++++++++------
languages/messages/MessagesFur.php | 45 +-
languages/messages/MessagesFy.php | 39 +-
languages/messages/MessagesGa.php | 272 +-
languages/messages/MessagesGn.php | 3 +-
languages/messages/MessagesGsw.php | 168 +-
languages/messages/MessagesGu.php | 3 +-
languages/messages/MessagesHe.php | 851 ++--
languages/messages/MessagesHi.php | 158 +-
languages/messages/MessagesHr.php | 225 +-
languages/messages/MessagesHsb.php | 3465 +++++++++--------
languages/messages/MessagesHu.php | 2197 ++++++-----
languages/messages/MessagesHy.php | 1008 +++++
languages/messages/MessagesIa.php | 25 +-
languages/messages/MessagesId.php | 3428 +++++++++--------
languages/messages/MessagesIi.php | 3 +-
languages/messages/MessagesIs.php | 172 +-
languages/messages/MessagesIt.php | 3542 ++++++++---------
languages/messages/MessagesJa.php | 3303 ++++++++--------
languages/messages/MessagesJbo.php | 3 +-
languages/messages/MessagesJv.php | 454 ++-
languages/messages/MessagesKa.php | 542 ++-
languages/messages/MessagesKaa.php | 3 +-
languages/messages/MessagesKab.php | 1639 ++++++++
languages/messages/MessagesKg.php | 3 +-
languages/messages/MessagesKk.php | 3 +-
languages/messages/MessagesKk_cn.php | 3186 ++++++++-------
languages/messages/MessagesKk_kz.php | 1347 ++++---
languages/messages/MessagesKk_tr.php | 1314 ++++---
languages/messages/MessagesKm.php | 3 +-
languages/messages/MessagesKn.php | 5 +-
languages/messages/MessagesKo.php | 2388 +++++++-----
languages/messages/MessagesKs.php | 16 +-
languages/messages/MessagesKsh.php | 4047 +++++++++-----------
languages/messages/MessagesKu.php | 245 +-
languages/messages/MessagesKv.php | 3 +-
languages/messages/MessagesLa.php | 1858 +++++----
languages/messages/MessagesLg.php | 287 ++
languages/messages/MessagesLi.php | 1735 +++++----
languages/messages/MessagesLn.php | 5 +-
languages/messages/MessagesLo.php | 3 +-
languages/messages/MessagesLt.php | 995 ++---
languages/messages/MessagesLv.php | 1744 +++++----
languages/messages/MessagesMi.php | 4 +-
languages/messages/MessagesMk.php | 190 +-
languages/messages/MessagesMl.php | 3 +-
languages/messages/MessagesMr.php | 272 ++
languages/messages/MessagesMs.php | 21 +-
languages/messages/MessagesMt.php | 4 +-
languages/messages/MessagesMzn.php | 3 +-
languages/messages/MessagesNah.php | 3 +-
languages/messages/MessagesNap.php | 3 +-
languages/messages/MessagesNds.php | 2172 ++++++-----
languages/messages/MessagesNds_nl.php | 8 +-
languages/messages/MessagesNe.php | 20 +
languages/messages/MessagesNew.php | 39 +
languages/messages/MessagesNl.php | 3296 ++++++++--------
languages/messages/MessagesNn.php | 199 +-
languages/messages/MessagesNo.php | 201 +-
languages/messages/MessagesNon.php | 3 +-
languages/messages/MessagesNv.php | 3 +-
languages/messages/MessagesOc.php | 2606 +++++++++----
languages/messages/MessagesOr.php | 3 +-
languages/messages/MessagesOs.php | 12 +-
languages/messages/MessagesPa.php | 22 +-
languages/messages/MessagesPi.php | 20 +
languages/messages/MessagesPl.php | 580 ++-
languages/messages/MessagesPms.php | 3151 +++++++--------
languages/messages/MessagesPs.php | 3 +-
languages/messages/MessagesPt.php | 198 +-
languages/messages/MessagesPt_br.php | 15 +-
languages/messages/MessagesQu.php | 3 +-
languages/messages/MessagesRmy.php | 644 ++--
languages/messages/MessagesRo.php | 3097 ++++++++-------
languages/messages/MessagesRu.php | 3065 +++++++--------
languages/messages/MessagesSa.php | 84 +
languages/messages/MessagesSc.php | 23 +-
languages/messages/MessagesScn.php | 85 +
languages/messages/MessagesSd.php | 3 +-
languages/messages/MessagesSk.php | 3487 +++++++++--------
languages/messages/MessagesSl.php | 2937 +++++++-------
languages/messages/MessagesSq.php | 204 +-
languages/messages/MessagesSr.php | 3 +-
languages/messages/MessagesSr_ec.php | 196 +-
languages/messages/MessagesSr_el.php | 197 +-
languages/messages/MessagesSr_jc.php | 3 +-
languages/messages/MessagesSr_jl.php | 3 +-
languages/messages/MessagesSu.php | 2289 ++++++-----
languages/messages/MessagesSv.php | 3273 +++++++++-------
languages/messages/MessagesTa.php | 27 +-
languages/messages/MessagesTe.php | 12 +-
languages/messages/MessagesTg.php | 3 +-
languages/messages/MessagesTh.php | 13 +-
languages/messages/MessagesTlh.php | 3 +-
languages/messages/MessagesTr.php | 171 +-
languages/messages/MessagesTt.php | 177 +-
languages/messages/MessagesTy.php | 8 +
languages/messages/MessagesTyv.php | 6 +-
languages/messages/MessagesUdm.php | 3 +-
languages/messages/MessagesUg.php | 3 +-
languages/messages/MessagesUk.php | 2823 ++++++++++----
languages/messages/MessagesUr.php | 615 +++
languages/messages/MessagesUz.php | 424 +-
languages/messages/MessagesVec.php | 189 +-
languages/messages/MessagesVi.php | 266 +-
languages/messages/MessagesVls.php | 3 +-
languages/messages/MessagesWa.php | 226 +-
languages/messages/MessagesXal.php | 3 +-
languages/messages/MessagesYi.php | 203 +-
languages/messages/MessagesZa.php | 3 +-
languages/messages/MessagesZea.php | 34 +
languages/messages/MessagesZh_classical.php | 1223 ++++++
languages/messages/MessagesZh_cn.php | 2831 ++++++++++----
languages/messages/MessagesZh_hk.php | 3 +-
languages/messages/MessagesZh_sg.php | 3 +-
languages/messages/MessagesZh_tw.php | 2824 ++++++++++----
languages/messages/MessagesZh_yue.php | 719 ++--
maintenance/Doxyfile | 4 +-
maintenance/FiveUpgrade.inc | 48 +-
maintenance/Makefile | 17 +-
maintenance/addwiki.php | 4 +-
maintenance/archives/patch-ar_deleted.sql | 3 +
maintenance/archives/patch-ar_len.sql | 3 +
maintenance/archives/patch-categorylinks.sql | 2 +-
maintenance/archives/patch-externallinks.sql | 2 +-
maintenance/archives/patch-fa_deleted.sql | 3 +
maintenance/archives/patch-filearchive.sql | 2 +-
maintenance/archives/patch-indexes.sql | 2 +-
maintenance/archives/patch-interwiki.sql | 2 +-
maintenance/archives/patch-ipb_anon_only.sql | 2 +-
maintenance/archives/patch-ipb_deleted.sql | 3 +
maintenance/archives/patch-job.sql | 2 +-
maintenance/archives/patch-langlinks.sql | 2 +-
maintenance/archives/patch-linkscc.sql | 2 +-
maintenance/archives/patch-linktables.sql | 8 +-
maintenance/archives/patch-log_deleted.sql | 3 +
maintenance/archives/patch-log_id.sql | 8 +
maintenance/archives/patch-logging.sql | 2 +-
maintenance/archives/patch-math.sql | 2 +-
maintenance/archives/patch-objectcache.sql | 2 +-
maintenance/archives/patch-page_restrictions.sql | 22 +
.../archives/patch-page_restrictions_sortkey.sql | 8 +
maintenance/archives/patch-pagelinks.sql | 2 +-
maintenance/archives/patch-parsercache.sql | 2 +-
maintenance/archives/patch-querycache.sql | 2 +-
maintenance/archives/patch-querycacheinfo.sql | 2 +-
maintenance/archives/patch-querycachetwo.sql | 2 +-
maintenance/archives/patch-rc_deleted.sql | 8 +
maintenance/archives/patch-redirect.sql | 2 +-
maintenance/archives/patch-rev_len.sql | 3 +
maintenance/archives/patch-rev_parent_id.sql | 9 +
maintenance/archives/patch-templatelinks.sql | 2 +-
maintenance/archives/patch-transcache.sql | 2 +-
maintenance/archives/patch-user_groups.sql | 2 +-
maintenance/archives/patch-user_rights.sql | 2 +-
maintenance/archives/patch-userlevels.sql | 4 +-
maintenance/archives/patch-validate.sql | 2 +-
maintenance/archives/rebuildRecentchanges.inc | 3 +-
maintenance/archives/upgradeWatchlist.php | 3 +-
maintenance/attachLatest.php | 5 +-
maintenance/attribute.php | 5 +-
maintenance/backup.inc | 26 +-
maintenance/benchmarkPurge.php | 3 +-
maintenance/changePassword.php | 5 +-
maintenance/checkUsernames.php | 2 +-
maintenance/cleanupCaps.php | 6 +-
maintenance/cleanupDupes.inc | 7 +-
maintenance/cleanupDupes.php | 3 +-
maintenance/cleanupImages.php | 3 +-
maintenance/cleanupSpam.php | 9 +-
maintenance/cleanupTable.inc | 2 +-
maintenance/cleanupTitles.php | 9 +-
maintenance/cleanupWatchlist.php | 9 +-
maintenance/clear_interwiki_cache.php | 5 +-
maintenance/commandLine.inc | 5 +-
maintenance/convertLinks.inc | 9 +-
maintenance/convertLinks.php | 3 +-
maintenance/createAndPromote.php | 3 +-
maintenance/deleteBatch.php | 2 +-
maintenance/deleteDefaultMessages.php | 4 +-
maintenance/deleteImageMemcached.php | 4 +-
maintenance/deleteOldRevisions.inc | 5 +-
maintenance/deleteOldRevisions.php | 3 +-
maintenance/deleteOrphanedRevisions.inc.php | 3 +-
maintenance/deleteOrphanedRevisions.php | 5 +-
maintenance/deleteRevision.php | 2 +-
maintenance/dumpBackup.php | 3 +-
maintenance/dumpHTML.inc | 26 +-
maintenance/dumpHTML.php | 7 +-
maintenance/dumpInterwiki.inc | 27 +-
maintenance/dumpInterwiki.php | 3 +-
maintenance/dumpLinks.php | 7 +-
maintenance/dumpReplayLog.php | 9 +-
maintenance/dumpSisterSites.php | 3 +-
maintenance/dumpTextPass.php | 5 +-
maintenance/eval.php | 3 +-
maintenance/findhooks.php | 5 +-
maintenance/fixSlaveDesync.php | 19 +-
maintenance/fixTimestamps.php | 2 +-
maintenance/fixUserRegistration.php | 4 +-
maintenance/fuzz-tester.php | 397 +-
maintenance/generateSitemap.php | 40 +-
maintenance/getLagTimes.php | 3 +-
maintenance/getSlaveServer.php | 12 +-
maintenance/importDump.php | 13 +-
maintenance/importImages.inc.php | 5 +-
maintenance/importImages.php | 19 +-
maintenance/importLogs.inc | 11 +-
maintenance/importLogs.php | 3 +-
maintenance/importPhase2.php | 18 +-
maintenance/importTextFile.php | 34 +-
maintenance/importUseModWiki.php | 12 +-
maintenance/initStats.inc | 55 +
maintenance/initStats.php | 56 +-
maintenance/installExtension.php | 51 +-
maintenance/interwiki.sql | 2 +
maintenance/language/alltrans.php | 3 +-
maintenance/language/checkExtensioni18n.php | 279 ++
maintenance/language/checkLanguage.inc | 92 +
maintenance/language/checkLanguage.php | 88 +-
maintenance/language/date-formats.php | 1 +
maintenance/language/diffLanguage.php | 8 +-
maintenance/language/dumpMessages.php | 3 +-
maintenance/language/lang2po.php | 21 +-
maintenance/language/languages.inc | 36 +-
maintenance/language/messageTypes.inc | 68 +-
maintenance/language/messages.inc | 400 +-
maintenance/language/rebuildLanguage.php | 38 +-
maintenance/language/transstat.php | 5 +-
maintenance/language/writeMessagesArray.inc | 71 +-
maintenance/mcc.php | 9 +-
maintenance/mctest.php | 4 +-
maintenance/moveBatch.php | 5 +-
maintenance/mwdocgen.php | 3 +-
maintenance/mwdoxygen.cfg | 946 +----
maintenance/namespaceDupes.php | 2 +-
maintenance/nextJobDB.php | 48 +
maintenance/nukeNS.php | 108 +
maintenance/nukePage.inc | 15 +-
maintenance/nukePage.php | 3 +-
maintenance/ora/tables.sql | 437 +++
maintenance/orphans.php | 9 +-
maintenance/ourusers.php | 3 +-
maintenance/parserTests.inc | 359 +-
maintenance/parserTests.php | 12 +-
maintenance/parserTests.txt | 291 +-
maintenance/parserTestsParserHook.php | 3 +-
maintenance/parserTestsParserTime.php | 3 +-
maintenance/parserTestsStaticParserHook.php | 3 +-
.../postgres/archives/patch-archive-ar_deleted.sql | 1 +
maintenance/postgres/archives/patch-archive2.sql | 15 +
.../postgres/archives/patch-archive_delete.sql | 5 +
.../postgres/archives/patch-archive_insert.sql | 6 +
.../postgres/archives/patch-mediawiki_version.sql | 18 +
maintenance/postgres/archives/patch-mwuser.sql | 1 +
.../postgres/archives/patch-page_deleted.sql | 11 +
.../postgres/archives/patch-page_restrictions.sql | 10 +
.../postgres/archives/patch-pagecontent.sql | 1 +
maintenance/postgres/archives/patch-profiling.sql | 7 +
.../postgres/archives/patch-querycachetwo.sql | 12 +
.../postgres/archives/patch-rc_cur_id-not-null.sql | 1 +
maintenance/postgres/archives/patch-redirect.sql | 7 +
.../postgres/archives/patch-remove-archive2.sql | 3 +
.../postgres/archives/patch-rev_text_id_idx.sql | 1 +
.../archives/patch-revision_rev_user_fkey.sql | 4 +
maintenance/postgres/compare_schemas.pl | 30 +-
maintenance/postgres/mediawiki_mysql2postgres.pl | 444 +++
maintenance/postgres/tables.sql | 78 +-
maintenance/purgeList.php | 3 +
maintenance/purgeOldText.inc | 8 +-
maintenance/purgeOldText.php | 3 +-
maintenance/reassignEdits.inc.php | 7 +-
maintenance/reassignEdits.php | 3 +-
maintenance/rebuildImages.php | 7 +-
maintenance/rebuildInterwiki.inc | 10 +-
maintenance/rebuildInterwiki.php | 3 +-
maintenance/rebuildall.php | 3 +-
maintenance/rebuildrecentchanges.inc | 14 +-
maintenance/rebuildrecentchanges.php | 3 +-
maintenance/rebuildtextindex.inc | 5 +-
maintenance/rebuildtextindex.php | 3 +-
maintenance/refreshImageCount.php | 2 +-
maintenance/refreshLinks.inc | 9 +-
maintenance/refreshLinks.php | 3 +-
maintenance/removeUnusedAccounts.inc | 5 +-
maintenance/removeUnusedAccounts.php | 7 +-
maintenance/renamewiki.php | 60 +
maintenance/renderDump.php | 3 +-
maintenance/runJobs.php | 9 +-
maintenance/showJobs.php | 2 +-
maintenance/showStats.php | 2 +-
maintenance/sql.php | 67 +
maintenance/storage/blobs.sql | 6 +-
maintenance/storage/checkStorage.php | 12 +-
maintenance/storage/compressOld.inc | 38 +-
maintenance/storage/compressOld.php | 7 +-
maintenance/storage/dumpRev.php | 9 +-
maintenance/storage/moveToExternal.php | 128 +-
maintenance/storage/resolveStubs.php | 17 +-
maintenance/tables.sql | 131 +-
maintenance/update.php | 3 +-
maintenance/updateArticleCount.inc.php | 7 +-
maintenance/updateArticleCount.php | 5 +-
maintenance/updateRestrictions.php | 67 +
maintenance/updateSearchIndex.inc | 11 +-
maintenance/updateSearchIndex.php | 3 +-
maintenance/updateSpecialPages.php | 8 +-
maintenance/updaters.inc | 574 ++-
maintenance/userDupes.inc | 6 +-
maintenance/userDupes.php | 2 +-
maintenance/userOptions.inc | 237 ++
maintenance/userOptions.php | 21 +
maintenance/waitForSlave.php | 16 +
maintenance/wikipedia-interwiki.sql | 53 +-
serialized/README | 4 +-
skins/Chick.deps.php | 2 +-
skins/Chick.php | 8 +-
skins/CologneBlue.php | 6 +-
skins/MonoBook.php | 48 +-
skins/MySkin.deps.php | 2 +-
skins/MySkin.php | 8 +-
skins/Nostalgia.php | 6 +-
skins/Simple.deps.php | 2 +-
skins/Simple.php | 8 +-
skins/Standard.php | 8 +-
skins/archlinux/handheld.css | 32 +-
skins/archlinux/main.css | 38 +-
skins/archlinux/rtl.css | 5 +
skins/chick/main.css | 22 +-
skins/common/IEFixes.js | 8 +-
skins/common/ajax.js | 32 +-
skins/common/ajaxsearch.js | 6 +-
skins/common/block.js | 47 +
skins/common/common.css | 55 +-
skins/common/commonPrint.css | 8 +-
skins/common/common_rtl.css | 6 +-
skins/common/images/Checker-16x16.png | Bin 0 -> 81 bytes
skins/common/metadata.js | 18 +-
skins/common/preview.js | 91 +-
skins/common/protect.js | 41 +-
skins/common/sticky.js | 10 +-
skins/common/wikibits.js | 538 ++-
skins/disabled/HTMLDump.php | 8 +-
skins/disabled/MonoBookCBT.php | 6 +-
skins/monobook/handheld.css | 32 +-
skins/monobook/main.css | 58 +-
skins/monobook/rtl.css | 5 +
skins/simple/main.css | 18 +-
t/00-test.t | 8 +
t/README | 54 +
t/inc/IP.t | 60 +
t/inc/Licenses.t | 29 +
t/inc/Sanitizer.t | 62 +
t/inc/Title.t | 33 +
t/inc/Xml.t | 56 +
t/maint/eol-style.t | 35 +
t/maint/php-lint.t | 33 +
t/maint/php-tag.t | 29 +
t/maint/unix-newlines.t | 28 +
thumb.php | 103 +-
trackback.php | 8 +-
699 files changed, 92173 insertions(+), 56022 deletions(-)
create mode 100644 Test.php
create mode 100755 bin/svnstat
create mode 100755 bin/ulimit4.sh
create mode 100644 includes/ImageQueryPage.php
create mode 100644 includes/MediaTransformOutput.php
create mode 100644 includes/OutputHandler.php
create mode 100644 includes/PageQueryPage.php
create mode 100644 includes/ParserOptions.php
create mode 100644 includes/ParserOutput.php
create mode 100644 includes/PatrolLog.php
create mode 100644 includes/SearchOracle.php
create mode 100644 includes/SpecialFewestrevisions.php
create mode 100644 includes/SpecialProtectedpages.php
create mode 100644 includes/SpecialWithoutinterwiki.php
create mode 100644 includes/media/BMP.php
create mode 100644 includes/media/Bitmap.php
create mode 100644 includes/media/DjVu.php
create mode 100644 includes/media/Generic.php
create mode 100644 includes/media/SVG.php
create mode 100644 includes/tidy.conf
create mode 100644 languages/classes/LanguageAr.php
create mode 100644 languages/classes/LanguageBe_x_old.php
create mode 100644 languages/classes/LanguageHy.php
create mode 100644 languages/classes/LanguageUk.php
create mode 100644 languages/messages/MessagesBe_x_old.php
create mode 100644 languages/messages/MessagesBh.php
create mode 100644 languages/messages/MessagesFiu_vro.php
create mode 100644 languages/messages/MessagesHy.php
create mode 100644 languages/messages/MessagesKab.php
create mode 100644 languages/messages/MessagesLg.php
create mode 100644 languages/messages/MessagesMr.php
create mode 100644 languages/messages/MessagesNe.php
create mode 100644 languages/messages/MessagesNew.php
create mode 100644 languages/messages/MessagesPi.php
create mode 100644 languages/messages/MessagesSa.php
create mode 100644 languages/messages/MessagesScn.php
create mode 100644 languages/messages/MessagesTy.php
create mode 100644 languages/messages/MessagesZea.php
create mode 100644 languages/messages/MessagesZh_classical.php
create mode 100644 maintenance/archives/patch-ar_deleted.sql
create mode 100644 maintenance/archives/patch-ar_len.sql
create mode 100644 maintenance/archives/patch-fa_deleted.sql
create mode 100644 maintenance/archives/patch-ipb_deleted.sql
create mode 100644 maintenance/archives/patch-log_deleted.sql
create mode 100644 maintenance/archives/patch-log_id.sql
create mode 100644 maintenance/archives/patch-page_restrictions.sql
create mode 100644 maintenance/archives/patch-page_restrictions_sortkey.sql
create mode 100644 maintenance/archives/patch-rc_deleted.sql
create mode 100644 maintenance/archives/patch-rev_len.sql
create mode 100644 maintenance/archives/patch-rev_parent_id.sql
create mode 100644 maintenance/initStats.inc
create mode 100644 maintenance/language/checkExtensioni18n.php
create mode 100644 maintenance/language/checkLanguage.inc
create mode 100644 maintenance/nextJobDB.php
create mode 100644 maintenance/nukeNS.php
create mode 100644 maintenance/ora/tables.sql
create mode 100644 maintenance/postgres/archives/patch-archive-ar_deleted.sql
create mode 100644 maintenance/postgres/archives/patch-archive2.sql
create mode 100644 maintenance/postgres/archives/patch-archive_delete.sql
create mode 100644 maintenance/postgres/archives/patch-archive_insert.sql
create mode 100644 maintenance/postgres/archives/patch-mediawiki_version.sql
create mode 100644 maintenance/postgres/archives/patch-mwuser.sql
create mode 100644 maintenance/postgres/archives/patch-page_deleted.sql
create mode 100644 maintenance/postgres/archives/patch-page_restrictions.sql
create mode 100644 maintenance/postgres/archives/patch-pagecontent.sql
create mode 100644 maintenance/postgres/archives/patch-profiling.sql
create mode 100644 maintenance/postgres/archives/patch-querycachetwo.sql
create mode 100644 maintenance/postgres/archives/patch-rc_cur_id-not-null.sql
create mode 100644 maintenance/postgres/archives/patch-redirect.sql
create mode 100644 maintenance/postgres/archives/patch-remove-archive2.sql
create mode 100644 maintenance/postgres/archives/patch-rev_text_id_idx.sql
create mode 100644 maintenance/postgres/archives/patch-revision_rev_user_fkey.sql
create mode 100644 maintenance/postgres/mediawiki_mysql2postgres.pl
create mode 100644 maintenance/renamewiki.php
create mode 100644 maintenance/sql.php
create mode 100644 maintenance/updateRestrictions.php
create mode 100644 maintenance/userOptions.inc
create mode 100644 maintenance/userOptions.php
create mode 100644 maintenance/waitForSlave.php
create mode 100644 skins/common/block.js
create mode 100644 skins/common/images/Checker-16x16.png
create mode 100644 t/00-test.t
create mode 100644 t/README
create mode 100644 t/inc/IP.t
create mode 100644 t/inc/Licenses.t
create mode 100644 t/inc/Sanitizer.t
create mode 100644 t/inc/Title.t
create mode 100644 t/inc/Xml.t
create mode 100644 t/maint/eol-style.t
create mode 100644 t/maint/php-lint.t
create mode 100644 t/maint/php-tag.t
create mode 100644 t/maint/unix-newlines.t
diff --git a/HISTORY b/HISTORY
index 302f9b0f..6e710a09 100644
--- a/HISTORY
+++ b/HISTORY
@@ -5,6 +5,697 @@
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.
+
+== Changes since 1.8 ==
+
+* (bug 8200) Make category lists sorted by name when using Postgres.
+* (bug 7841) Support 'IGNORE' inserts for Postgres, fixes watchlist
+ adding problem.
+* (bug 6835) Removing the includes/Parser.php::getTemplateArgs() function,
+ because it seems to be unused.
+* (bug 7139) Increasing the visual width of the edit summary field on larger
+ screen sizes, for the default monobook skin.
+* Fix PHP notice and estimates for dumpBackup.php and friends
+* Improved register_globals paranoia checks
+* (bug 7545) Fix PHP version check on install
+* Disable PHP exception backtrace printing unless $wgShowExceptionDetails
+ is set. Backtraces may contain sensitive information in function call
+ parameters.
+* (bug 6164) Avoid smashing Cite state if message transformation triggers
+ during bad image list check, by skipping message transformation.
+ This isn't a good permanent fix.
+* (bug 6918) Stopped borders and backgrounds from showing through floated
+ tables in Monobook
+* (bug 6868) Un-hardcode section edit link style
+* (bug 3205) Stop right floats from stacking horizontally in non-Monobook skins
+* Added global $wgStyleVersion to centralize bumping CSS and JS file versions
+ for cache-friendly style and script updating
+* (bug 7562) Fix non-ASCII namespaces on Windows/XAMPP servers
+* Friendlier check for PHP 5 in command-line scripts; it's common for parallel
+ PHP 4 and 5 installations to interfere on the command-line.
+* Fix regression in autoconfirm permission check
+* (bug 3015) Add CSS ids to subcategory and page sections on category pages
+* (bug 7587) Fix erroneous id for specialpage tab, enabling informative popup
+* (bug 7599) Fix thumbnail purging, PHP notices on HTCP image page purge
+* (bug 7581) Update language name for cbk-zam
+* (bug 7444) Update namespace translations for Telugu (te), kept old values as
+ alias for compatibility
+* (bug 4525) Move section links down visually to same level as headings
+ (editsection links are now inside the heading elements)
+* Workaround for http://bugs.php.net/bug.php?id=31892 , PATH_INFO and hence
+ URLs of the style /index.php/Main_Page were broken on some CGI installations.
+* (bug 7623) Validate custom HTML id's correctly in Monobook interface
+* (bug 2241) Fix collision of 'w' and 'd' accesskeys
+* (bug 5795) CSS class added to body based on page name for page-specific
+ styling
+* (bug 6276) Stopped search field from getting too large in Cologne Blue
+* (bug 7644) User creations that are aborted by hooks shouldn't be counted
+ against account creations per day limit
+* (bug 7636) Show Firefox 2 users correct accesskey prefix
+* (bug 6427) Block blocked IPs from using the mail password function
+ to allow blocking of flooders
+* Include common.css from classic-style skins in main HTML with the bump URL
+* (bug 7607) Add Karakalpak (kaa) to Names.php and stub message file for linktrail
+* (bug 7582) Add 'tog-nolangconversion' to MessagesEn.php.
+ This key is need for languages with variants (zh, sr, kk)
+* (bug 7606) MediaWiki messages for "rss" and "atom" missing
+* (bug 7609) Add some more '*-summary' messages to MessagesEn.php with empty
+ strings to allow better localisation via Special:Allmessages. Mark this new
+ messages as optional for localisation.
+* Fix user_newpass upgrade for prefixed tables (reported by Fyren)
+* (bug 7663) Include language variant switcher links on Nostalgia skin
+* (bug 6531) Fix PHP fatal error on installation page with bad username input.
+* (bug 6977) Remove 404 link for autogenerated database documentation.
+* (bug 7369) Allow "Show Changes" without requiring edit token.
+* (bug 7687) Fix movetalk box checks itself when confirming a delete and move.
+* (bug 7684) Obey watchcreated preference for Special:Upload watch checkbox
+* (bug 7686) Include id attribute on delete form confirmation button
+* Allow compound interwiki prefixes in $wgImportSources
+* (bug 7304) Added redirect table to store redirect targets.
+* Added querycachetwo table (similar to querycache but has two titles)
+* PageArchive can now return a Revision object for more convenient processing
+ of deleted revision data
+* Added 'UndeleteShowRevision' hook in Special:Undelete
+* Error message on attempt to view invalid or missing deleted revisions
+* Remove unsightly "_" from namespace in Special:Allpages, Special:Prefixindex
+* (bug 3224) Allow minor edits by bots to skip new message notification on
+ user talk pages. This can be disabled by adjusting the 'nominornewtalk'
+ permission. Patch by Werdna.
+* (bug 7741) MATH: fixed broken syntax of underbrace etc. Fixed arrays
+* Fix purging for updated SVG files
+* (bug 7745) Add id attribute to search button in Monobook
+* (bug 7749) MATH: added some more LaTeX symbols, e.g. parallel, diamond, ast, ...
+* (bug 7304) Added code in Article.php to keep redirect table up to date.
+* Made special page names case-insensitive and localisable. Care has been taken
+ to maintain backwards compatibility.
+* Used special page subpages in a few more places, instead of query parameters.
+* (bug 7758) Added wrapper span to "templates used" explanation to allow CSS
+ styling (class="mw-templatesUsedExplanation").
+* Added {{#special:}} parser function, to give the local default title for
+ special pages
+* (bug 7766) Remove redundant / from AJAX requests, can break some servers
+* Add tab links from extensions to classic-based skins (SkinTemplateTab hook)
+ Provides better cross-skin compatibility for extensions using the modern
+ skin hooks, such as Oversight
+* Moved variant language links on Cologne Blue and Nostalgia to before the
+ login/logout link
+* Fix for parser tests with MySQL 5 in strict mode
+* Added block option "enable autoblocks"
+* Amend Special:Ipblocklist to note when a block has autoblock DISABLED.
+* (bug 7780) Fix regression in editing redirects
+* Add whitespace above "templates included on this page" using CSS, not
+ hardcoded line break.
+* Remove entries from redirect table on article deletion
+* (bug 7788) Force section headers in new section links for users who have
+ 'prompt for blank edit summaries' on.
+* (bug 1133) Special:Emailuser: add an option to send yourself a copy of your mail.
+* (bug 461) Allow "Categories:" link at bottom of pages to be customized via
+ pagecategorieslink message.
+* Sort the list of skins in "My Preferences" -> Skins by alphabetical order.
+* (bug 7785) Postgres compatibility for timestamps in RC feeds
+* (bug 7550) Normalize user parameter normally on Special:Log
+* (bug 7294) Fix PATH search for diff3 on install
+* Various fixes related to the blocking change re: autoblocks. On inserting
+ an IP block, the ipb_enable_autoblock field is now automagically blanked,
+ because it doesn't make any sense for an IP. Additionally, IP blocks
+ without the ipb_enable_autoblock option no longer show up as "autoblock
+ disabled" on Special:Ipblocklist.
+* (bug 7774) MATH: aded more amstex functions
+* (bug 1182) MATH: fixed inconsistent rendering of upper case Greek letters in TeX
+* Fix regression in streaming page dump generation
+* (bug 7801) Add support for parser function hooks in parser tests
+* checkUsernames.php now uses wfDebugLog instead of hardcoded path to log
+* (bug 7810) Update talk namespaces for Occitan
+* Allow case-sensitive URLs to be used for uploading from URLs.
+* (bug 1109) Correct fix for compressed 304 responses when additional output
+ buffers have been installed within the compression handler
+* (bug 7819) Move automatic redirect edit summary after pre-save transform
+ to work properly with subst: fun
+* (bug 7826) Fix typos in two English messages.
+* (bug 5365) Stop users being prompted to enter an edit summary for null edits,
+ if they have selected that option in preferences.
+* (bug 5936) Show an 'm' to the left of the edit summary on diff pages for minor edits.
+* (bug 7820) Improve error reporting for uploads via URL.
+* (bug 5149) When autoblocks are enabled, retroactively apply an autoblock to the most
+ recently used IP of a user when they are blocked.
+* Add an index on (rc_user_text,rc_timestamp) on the recentchanges table. This will
+ make CheckUser.php and the new retroactive autoblock functionality faster.
+* Fix regression in Special:Undelete for revisions deleted under MediaWiki 1.4
+ with compression or legacy encoding
+* (bug 6737) Fixes for MySQL 5 schema in strict mode
+* Approximate height for client-side scaling fallback instead of passing -1
+ into the HTML output.
+* Make the DNSBL to check for proxy blocking configurable via $wgSorbsUrl
+* Add experimental recording/reporting mode to parser tests runner, to
+ compare changes against the previous run.
+ Additional tables 'testrun' and 'testitem' are in maintenance/testRunner.sql,
+ source this and pass --record option to parserTests.php
+* Make the set of default parser test input files extensible via
+ $wgParserTestFiles. This can now be appended to by extensions or local
+ configuration files so that extension or custom tests can be automatically
+ run along with the main batch.
+* Run PHP install version checks on update.php so command-line updaters see
+ new version requirements
+* Do a check for the PHP 5.0.x 64-bit bug, since this is much more disruptive
+ as of MW 1.8 than it used to be. Install or upgrade now aborts with a
+ warning and a request to upgrade.
+* (bug 6440) Updated indexes to improve backlinking queries (links, templates, images)
+* Switched 'anon-only' block mode to default for IP blocks
+* (bug 3687, 7892) Add distinct heading for media files in category display,
+ with count.
+* (bug 1578) Add different icons for external links to audio, video, or PDF in
+ Monobook.
+* Made autoblocks block account creation if the user block has that option enabled.
+* Add auto-summaries to blankings and large removals without summaries.
+* (bug 7811) Allow preview of edit summaries.
+* (bug 6839) Wikibits.js minor changes to make JS-lint happier.
+* (bug 7932) Make sure that edit toolbar clears floats so it appears correctly.
+* (bug 6873) When viewing old revisions, add link to diff to current version.
+* (bug 3315) Provide rollback link directly on history page.
+* Replace 'old-revision-navigation' message with 'revision-info' and
+ 'revision-nav' messages, wrapped in divs with appropriate id's.
+* (bug 4178) MediaWiki:Common.js will now be included for all users if
+ $wgUseSiteJs is enabled, in addition to (if applicable) MediaWiki:Monobook.js
+ and user JS subpages.
+* (bug 7918) "Templates used on this page" changes during preview to reflect
+ any added or removed templates, and works as expected for section edits.
+* (bug 7919) "Templates used on this page" is now shown for read-only pages.
+* (bug 7688) When viewing diff, section anchors in autosummary jump to section
+ on current page instead of loading the latest version.
+* (bug 7970) Use current connection explicitly on Database::getServerVersion
+* (bug 2001) Tables with class="sortable" can now be dynamically sorted via
+ JavaScript.
+* Added autosummary for new pages with 500 or less characters, and refactor
+ the autosummary code so it's all done in one function. doEdit is getting too
+ big!
+* (bug 7554) The correct MIME type for SVG images is now displayed on the
+ image page (image/svg+xml, not image/svg).
+* (bug 7883) Added autoblock whitelisting feature, using which specific ranges
+ can be protected from autoblocking. These ranges are specified, in list format,
+ in the autoblock_whitelist system message.
+* Added placeholders for text injection by hooks to EditPage.php
+* (bug 8009) Automatic edit summary for redirects is not filled for edits in existing pages
+* Installer support for experimental MySQL 4.1/5.0 binary-safe schema
+* Use INSERT IGNORE for db-based BagOStuff add/insert, for more memcache-like
+ behavior when keys already exist on add (instead of dying with an error...)
+* Add a hook 'UploadForm:initial' before the upload form is generated, and two
+ member variable for text injection into the form, which can be filled by the hooks.
+* (bug 6295) Add a "revision patching" functionality, where an edit can be undone
+ (with a functionality similar to diff rev1 rev2 | patch -R rev3 -o rev3).
+ This is triggered by including &undo=revid in an edit URL. A link to a URL
+ that will undo a given edit is shown on NEW revision headers on diff pages.
+ The link leads to a "Show Changes" page showing what will be done to undo the
+ edit.
+* Fix display of link in "already rolled back" message for image/category pages
+* (bug 6016) Left-aligned images should stack vertically, like right-aligned
+ images, not horizontally.
+* Patch from LeonWP: added UploadForm:BeforeProcessing hook in SpecialUpload.php
+* Add AuthPluginSetup hook to override $wgAuth after configuration
+* Fix regression in authentication hook auto-creation on login
+* (bug 8110) Allow spaces in ISBNs
+* (bug 8024) Introduce "send me copies of emails I send to others" preference
+* Added 'EditPage::attemptSave' hook before an article is saved.
+* (bug 8083) Applied patch for sk localisation
+* Add a backslash character to the edit token, to prevent edits via certain
+ broken proxies that mangle such characters in form submissions
+* (bug 7461) Allow overwriting pages using importTextFile.php
+* (bug 7946) importTextFile.php doesn't perform pre-save transform
+* (bug 8117) {{REVISIONTIMESTAMP}} showed weird default if $wgLocalTZoffset set;
+ now uses current time for previews and if timestamp can't be loaded from DB
+* {{REVISIONTIMESTAMP}} now uses site local timezone instead of user timezone
+ to ensure consistent behavior
+* {{REVISIONTIMESTAMP}} and friends should now work on non-MySQL backends
+* (bug 7671) Observe canonical media namespace prefix in Linker::formatComment
+* Added js variable wgCurRevisionId to the output
+* (bug 8141) Cleanup of Parser::doTableStuff, patch by AzaTht
+* (bug 8042) Make miser mode caching limits settable via $wgQueryCacheLimit
+ instead of hardcoding to 1000
+* Enable QueryPage classes to override list formatting
+* (bug 5485) Show number of intervening revisions in diff view
+* (bug 8100) Fix XHTML validity in Taiwanese localization
+* Added redirect to section feature. Use it wisely.
+* Added a configuration variable allowing the "break out of framesets" feature
+ to be switched on and off ($wgBreakFrames). Off by default.
+* Allow Xml::check() $attribs parameter to override 'value' attribute
+* DB schema change: added two columns (rc_old_len and rc_new_len) to the recentchanges table to store
+ the text lengths before and after the edit
+* (bug 1085) Made Special:Recentchanges show the character difference between the changed revisions
+* Removed a redundant tag from diff pages that was causing display issues for some users
+* (bug 8203) The keyboard shortcut for "log out" was removed, because users were pressing it
+ when they intended to press the shortcut for "preview".
+* (bug 8148) Handle non-removable output buffers gracefully when cleaning
+ buffers for HTTP 304 responses, StreamFile, and Special:Export.
+ Duplicated code merged into wfResetOutputBuffers() and wfClearOutputBuffers()
+* Special:AllPages : 'next page' link now point to the first title of the next
+ chunk instead of pointing to the last title of current chunk.
+* (bug 4673) Special:AllPages : add a 'previous' link (new message 'prevpage')
+* (bug 8121) wfRandom() was not between 0 and 1
+* Add static method Parser::createAssocArgs($args), so parser functions can
+ use the same code to parse arguments as the templates do.
+* Change behavior of logins using the temporary e-mailed password (as stored
+ in user_newpassword hash field). Instead of just logging in silently and
+ leaving the previous user_password field in place indefinitely, the user
+ is now prompted to set a new password.
+
+ The password-changing form is at Special:Resetpass; currently it's only
+ usable for changing from the temporary password during login, but it
+ could perhaps be generalized, replacing the subform in preferences.
+
+ Once the new password is set successfully, the temporary password is wiped
+ so it cannot be used to login a second time, and the login process
+ is completed.
+* Suppress 'mail new password' button on login form if $wgAuth forbids
+ changing user passwords; it wouldn't work very well...
+* Consolidate password length checks and $wgAuth manipulation into
+ User::setPassword() to avoid duplicate code in different places
+ that set passwords.
+* User::setPassword() now throws PasswordError exceptions if the password
+ is illegal or cannot be set via $wgAuth. These can be caught and a human-
+ readable error message displayed by UI code.
+* Added Title::isSubpage()
+* (bug 8241) Don't consider user pages of User:Foo.css to be CSS subpages
+* Set an explicit class on framed thumbnail inner divs and images, changed some
+ CSS to use these instead of using descendent selectors.
+* Accept null parameter to User::setPassword() as indicating the password
+ field should be cleared to an unusable state. Login will only be possible
+ after the password is reset, for instance by e-mail.
+* (bug 6394) Invalidate the password set for "by e-mail" account creations
+ to avoid accidental empty password creations.
+* Made the show change size function work on page moves, page creations, and
+ log entries. Also fixed it in the javascript recentchanges.
+* (bug 8239) correctly get 50 new contributions when clicking '(50 next)'
+* (bug 2259) Fix old regression where e-mail addresses were no longer
+ confirmed on login with mailed password.
+* Add a notification about the confirmation mail sent during account
+ creation, so people don't immediately go off to request a second one.
+* Add a warning on Special:Confirmemail if a code was already sent and has
+ not yet expired.
+* Add user_editcount field to provide data for heuristics on account use.
+ Incremented on edit, with lazy initialization from past revision data.
+ Can batch-initialize with maintenance/initEditCount.php (not yet friendly
+ to replication environments, this will do all accounts in one query).
+* Allow raw SQL subsections in Database::update() SET portion as well as
+ for WHERE portion. Handy for increments and such.
+* User::getOption now accept a default value to override default user values
+ this makes it consistent with WebRequest::get* methods. Corrected code in
+ various places accordingly.
+* (bug 8264) Fix JavaScript global vars for XHTML mode
+* Make $wgSiteNotice value wikitext again, for consistency with editable
+ MediaWiki:Sitenotice and MediaWiki:Anonnotice.
+* (bug 8044) When redirecting from the canonical name of the special page
+ to the localised one, parameters/subpages are omitted
+* (bug 8164) Special:Booksources should use GET for form submission
+* Rewrite Special:Booksources to clean up interface and remove redundant code
+* (bug 7925) Change Special:Allmessages message name filter javascript to be
+ a bit more responsive and easier on the CPU
+* (bug 4488) Support watching pages on deletion; introduces new user preference
+* Minor restructuring of Special:Preferences; "watch pages I edit" and "watch
+ pages I create" options now accessible under "Watchlist" options
+* (bug 8153) doesn't work in site notice
+* (bug 6690) wfMsgNoTrans() transforms messages
+* (bug 8274) Wrap edit tools in a
with a specified class
+* Detect PHP 5.0.x 64-bit bug and abort in WebStart.php; too many things break
+ mysteriously otherwise (detection code copied from install-utils.inc)
+* (bug 8295) Change handling of
tags in doBlockLevels() to match that
+ of
+* (bug 8110) Make magic ISBN linking stricter: only match ten-digit sequences
+ (plus optional ISBN-13 prefix) with no immediately following alphanumeric
+ character, disallow multiple consecutive internal redirects
+* (bug 2785) Accept optional colon prefix in links when formatting comments
+* Don't show "you can view and copy the source of this page" message for
+ pages which don't exist
+* (bug 8310) Blank line added to top of 'post' when page is blank
+* (bug 8109) Template parameters ignored in "recentchangestext"
+* Gracefully skip redirect-to-fragment on WebKit versions less than 420;
+ it messes up on current versions of Safari but is ok in the latest
+ nightlies. Checking the version number will allow it to automatically
+ work when new releases of Safari appear.
+* Fix regression in thumb styles; size and padding didn't match with
+ new arrangement.
+* (bug 8333) Fix quick user data update on login password change on
+ replication database setups. User data is now pulled from master
+ instead of slave in User::loadFromDatabase, ensuring that it is
+ fresh and accurate when read and then saved back into cache.
+ This was breaking with the Special:Rename operation which
+ automatically logs the user in with the new password after changing
+ it; pulling from slave meant the record was often not the updated
+ one.
+* (bug 8335) Set image width to the first valid parameter found.
+* (bug 8350) Fix watchlist viewing bug when using Postgres.
+* (bug 6603) When warning about invalid file extensions, output the bit
+ of the extension we actually checked
+* (bug 7669) Drop defaults on BLOB/TEXT columns for better compatibility
+ with MySQL's strict mode, often enabled by the Windows installer.
+ The defaults are ignored anyway when strict mode is off...
+* (bug 7685) Use explicit values for ar_text and ar_flags when deleting,
+ for better compatibility with MySQL's strict mode
+* Update default interwiki values to reflect changed location of ursine:
+* (bug 5411) Remove autopatrol preference
+* Users who have the "autopatrol" permission will have their edits marked as
+ patrolled automatically
+* Users who do not have the "autopatrol" permission will no longer be able
+ to mark their own edits as patrolled
+* Introduce 'PingLimiter' hook; see docs/hooks.txt for more information
+* (bug 532) Tweaked alt text for some interface messages
+* (bug 8231) Gave useful alt text to the main on image pages
+* (bug 371) Remove alt text for "Enlarge" icon on thumbnails
+* Initialize user_editcount to 0 instead of NULL for newly created accounts
+* (bug 3696) Strip LRM and RLM characters from titles to work around the
+ problem some people have where titles cut-and-pasted from lists include
+ the bidi override characters appended to the lists.
+ A more thorough blacklist for forbidden and translatable characters would
+ be wise, though, as might a cleaner method for the lists in the first place.
+* Fix regression in email password resets on read-restricted sites
+* Set tabindex on fields in deletion form so you don't have to tab through
+ the links in the sitenotice
+* (bug 8271) Show full time and date on viewer for individual deleted
+ revisions
+* (bug 8214) Output file size limit and actual file size in appropriate units
+ on Special:Upload
+* (bug 8016) Purge objectcache table during upgrade processes - use the --nopurge
+ option to prevent this when running maintenance/update.php
+* (bug 7612) Remove superfluous link to Special:Categories from result items
+ on Special:Mostcategories
+* {{PLURAL:}} now handles formatted numbers correctly
+* (bug 8331) Added the change size value to watchlists; therefore made
+ watchlists use RecentChange::newFromRow() instead of newFromCurRow()
+* (bug 8351) Fix undo for simple reverts
+* (bug 6856) User::clearNotification() does not respect read-only mode
+* (bug 6853) Use a checkbox on the installer form to indicate that a superuser
+ account should be used; this is clearer than the old check which relied on
+ the password never being an obscure value
+* Remove old unused watchlist cache, which was a leftover from the old schema
+ where watchlists were more expensive to generate
+* Minor cosmetic changes to Special:Userrights
+* Added wgCanonicalSpecialPageName to JavaScript variables
+* Fix image deleting when using Postgres.
+* Output both source and destination titles in maintenance/moveBatch.php
+* Added basic parser tests for language variants
+* Enable selflinks and categories to be written in some of the language variants
+* Prevent conversion of JavaScript code in language variants
+* Output software version number in maintenance/parserTests.php
+* (bug 7169) Use Ajax to watch/unwatch articles if enabled
+* Make variant table caching a little more robust, using main language code
+ in cache key. Probably this is still a bit wonky, though. Was breaking
+ parser tests when Chinese tables were getting loaded into Serbian code.
+* (bug 8380) Be nicer about blank lines in deleteBatch.php
+* (bug 8401) Fix regression in SORBS lookup for some DNS setups
+* Use raw file descriptor in posix_isatty() check to avoid warning on
+ Linux systems with at least some versions of PHP
+* (bug 5908) Allow overriding the default category sort key for all items on
+ a page using {{DEFAULTSORT}}
+* (bug 6449) Throw a more definitive error message when installation fails
+ due to an invalid database name
+* (bug 5827) Use full text for option link labels on Special:Watchlist
+* (bug 8018) Allow hiding minor edits from the watchlist
+* (bug 8427) MonoBook RTL IE 7.0 tweaks failed when sidebar's navigation
+ section is renamed; no longer relies on first section name
+* Stabilize client-side table sorting even if the underlying Javascript sort()
+ implementation is unstable
+* Add hook for extensions to add user information to the panel in preferences,
+ next to the user name and ID.
+* (bug 8392) Display protection status of transcluded pages in the edit page
+ template list. Patch by Fyren, with i18n naming tweak.
+* Fix for interwiki transclusion where target wiki uses query string for title
+* Resolve namespaces on interwiki Title objects using canonical namespace names
+ if possible (should not happen, though, outside interwiki transclusion... and
+ maybe not even then, but it does)
+* (bug 8447) Fix SQL typo breaking non-default $wgHitcounterUpdateFreq
+* Do not allow previews of deleted images to be cached
+* Add global variable $wgDefaultLanguageVariant used to set the default language
+ variant of a wiki to something different than the main language code
+* Add 'variant' option to parserTests - runs test with the given variant as
+ preferred, utilize it for more parser tests of language variants code
+* (bug 6503) Fix bug that stopped certain irrelevant links from being hidden
+ for printing
+* Avoid PHP warning in Creative Commons metadata when a creative commons
+ license is not actually set up
+* (bug 8463) Don't print external link icons for Monobook
+* (bug 8461) Support watching pages on move
+* (bug 8041) Work around bug with debug_backtrace when Zend Optimizer is
+ loaded by skipping the function. Use wfDebugBacktrace() wrapper function.
+* Reduce config file clutter by setting various script and upload paths
+ based on $IP or $wgScriptPath in Setup.php. They can still be explicitly
+ overridden in LocalSettings.php if desired...
+* Attempt to detect redirect loops for the canonical title redirect, and
+ give some hints to the poor confused administrator.
+* Introduce new flag 'R' - raw output for language variant escape tags
+* Advise users when updates for a query page have been disabled using
+ $wgDisableQueryPageUpdate
+* (bug 8413) Improve comments for $wgNamespaceRobotPolicies
+* (bug 8330) Show "bytes" suffix on recent changes diff counter
+ optionally... if set in rc-changes-size message (default empty for now)
+* (bug 8489) Support basic links in caption attribute
+* (bug 8485) Correct Lingala number formatting
+* The MediaWiki namespace is no longer pre-filled with default messages on
+ install. All default messages will be removed from the MediaWiki namespace
+ on upgrade.
+* Recentchanges RSS/Atom feeds now use a separate message for the description
+ to avoid cluttering it with useless wiki formatting
+* (bug 8417) Handle EXIF unknown dates
+* (bug 8372) Return nothing on empty
@@ -1079,7 +1132,7 @@ if( count( $errs ) ) {
- Use this to disable all e-mail functions (password reminders, user-to-user e-mail and e-mail notifications)
+ Use this to disable all e-mail functions (password reminders, user-to-user e-mail, and e-mail notifications)
if sending mail doesn't work on your server.
@@ -1157,7 +1210,7 @@ if( count( $errs ) ) {
enter those here. If you have database root access (see below)
you can specify new accounts/databases to be created. This account
will not be created if it pre-exists. If this is the case, ensure that it
- has SELECT, INSERT, UPDATE and DELETE permissions on the MediaWiki database.
+ has SELECT, INSERT, UPDATE, and DELETE permissions on the MediaWiki database.
If the database user specified above does not exist, or does not have access to create
the database (if needed) or tables within it, please check the box and provide details
@@ -1188,7 +1241,7 @@ if( count( $errs ) ) {
?>
If you need to share one database between multiple wikis, or
- MediaWiki and another web application, you may choose to
+ between MediaWiki and another web application, you may choose to
add a prefix to all the table names to avoid conflicts.
Avoid exotic characters; something like mw_ is good.
The username specified above will have it's search path set to the above schemas,
- so it is recommended that you create a new user.
+
The username specified above (at "DB username") will have its search path set to the above schemas,
+ so it is recommended that you create a new user. The above schemas are generally correct:
+ only change them if you are sure you need to.
@@ -1283,9 +1337,7 @@ function escapePhpString( $string ) {
}
function writeLocalSettings( $conf ) {
- $conf->UseImageResize = $conf->UseImageResize ? 'true' : 'false';
$conf->PasswordSender = $conf->EmergencyContact;
- $zlib = ($conf->zlib ? "" : "# ");
$magic = ($conf->ImageMagick ? "" : "# ");
$convert = ($conf->ImageMagick ? $conf->ImageMagick : "/usr/bin/convert" );
$rights = ($conf->RightsUrl) ? "" : "# ";
@@ -1380,10 +1432,9 @@ if ( \$wgCommandLineMode ) {
if ( isset( \$_SERVER ) && array_key_exists( 'REQUEST_METHOD', \$_SERVER ) ) {
die( \"This script must be run from the command line\\n\" );
}
-} elseif ( empty( \$wgNoOutputBuffer ) ) {
- ## Compress output if the browser supports it
- {$zlib}if( !ini_get( 'zlib.output_compression' ) ) @ob_start( 'ob_gzhandler' );
}
+## Uncomment this to disable output compression
+# \$wgDisableOutputCompression = true;
\$wgSitename = \"{$slconf['Sitename']}\";
@@ -1417,6 +1468,9 @@ if ( \$wgCommandLineMode ) {
\$wgDBport = \"{$slconf['DBport']}\";
\$wgDBprefix = \"{$slconf['DBprefix']}\";
+# MySQL table options to use during installation or update
+\$wgDBTableOptions = \"{$slconf['DBTableOptions']}\";
+
# Schemas for Postgres
\$wgDBmwschema = \"{$slconf['DBmwschema']}\";
\$wgDBts2schema = \"{$slconf['DBts2schema']}\";
@@ -1431,7 +1485,6 @@ if ( \$wgCommandLineMode ) {
## To enable image uploads, make sure the 'images' directory
## is writable, then set this to true:
\$wgEnableUploads = false;
-\$wgUseImageResize = {$conf->UseImageResize};
{$magic}\$wgUseImageMagick = true;
{$magic}\$wgImageMagickConvertCommand = \"{$convert}\";
diff --git a/docs/database.txt b/docs/database.txt
index 25dce8b7..80044734 100644
--- a/docs/database.txt
+++ b/docs/database.txt
@@ -7,7 +7,7 @@ By Tim Starling, January 2006.
For information about the MediaWiki database layout, such as a
description of the tables and their contents, please see:
- http://meta.wikimedia.org/wiki/Help:Database_layout
+ http://www.mediawiki.org/wiki/Manual:Database_layout
http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/maintenance/tables.sql?view=markup
@@ -17,7 +17,7 @@ description of the tables and their contents, please see:
To make a read query, something like this usually suffices:
-$dbr =& wfGetDB( DB_SLAVE );
+$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( /* ...see docs... */ );
while ( $row = $dbr->fetchObject( $res ) ) {
...
@@ -28,7 +28,7 @@ Note the assignment operator in the while condition.
For a write query, use something like:
-$dbw =& wfGetDB( DB_MASTER );
+$dbw = wfGetDB( DB_MASTER );
$dbw->insert( /* ...see docs... */ );
We use the convention $dbr for read and $dbw for write to help you keep
@@ -103,7 +103,7 @@ regularly lag by several minutes, making review of recent edits
difficult.
In addition to this, MediaWiki attempts to ensure that the user sees
-events occuring on the wiki in chronological order. A few seconds of lag
+events occurring on the wiki in chronological order. A few seconds of lag
can be tolerated, as long as the user sees a consistent picture from
subsequent requests. This is done by saving the master binlog position
in the session, and then at the start of each request, waiting for the
@@ -157,7 +157,7 @@ Often this approach is not good enough, and it becomes necessary to
enclose small groups of queries in their own transaction. Use the
following syntax:
-$dbw =& wfGetDB( DB_MASTER );
+$dbw = wfGetDB( DB_MASTER );
$dbw->immediateBegin();
/* Do queries */
$dbw->immediateCommit();
diff --git a/docs/deferred.txt b/docs/deferred.txt
index 445eb0e4..06155c56 100644
--- a/docs/deferred.txt
+++ b/docs/deferred.txt
@@ -17,3 +17,11 @@ smart like collating updates to the same table or such because
the list is almost always going to have just one item on it, if
that, so it's not worth the trouble.
+
+Since 1.6 there is a 'job queue' in the jobs table, which is used
+to update link tables of transcluding pages after edits; this
+may be extended in the future to more general background tasks.
+
+Job queue items are fetched out of the queue and run either
+at a random rate during regular page views (by default) or by
+a batch process which can be run via maintenance/runJobs.php.
diff --git a/docs/design.txt b/docs/design.txt
index 5fff9fd0..8f24d0d8 100644
--- a/docs/design.txt
+++ b/docs/design.txt
@@ -1,5 +1,8 @@
This is a brief overview of the new design.
+More thorough and up-to-date information is available on the documentation
+wiki at http://www.mediawiki.org/
+
Primary source files/objects:
index.php
@@ -42,10 +45,15 @@ Primary source files/objects:
don't involve their text, such as access rights.
Article
- Encapsulates access to the "cur" table of the database. The
+ Encapsulates access to the "page" table of the database. The
object represents a an article, and maintains state such as
text (in Wikitext format), flags, etc.
+ Revision
+ Encapsulates individual page revision data and access to the
+ revision/text/blobs storage system. Higher-level code should
+ never touch text storage directly; this class mediates it.
+
Skin
Encapsulates a "look and feel" for the wiki. All of the
functions that render HTML, and make choices about how to
@@ -117,12 +125,3 @@ Naming/coding conventions:
of session variables are wsName, cookies wcName, and form field
values wpName ("p" for "POST").
- - Be kind to your release manager and don't use CVS keywords (Id,
- Revision, etc.) to mark file versions. They make merging code
- between different branches a pain for CVS, and are kind of sketchy
- for versions after that. (Yes, you can use the '-kk' flag so that
- merges ignore keywords, but that messes up binary files. See
- https://www.cvshome.org/docs/manual/cvs-1.11.18/cvs_5.html#SEC64).
-
-
-
diff --git a/docs/hooks.txt b/docs/hooks.txt
index d5a17660..9f5d289f 100644
--- a/docs/hooks.txt
+++ b/docs/hooks.txt
@@ -286,6 +286,11 @@ $isminor: minor flag
$iswatch: watch flag
$section: section #
+'ArticleUndeleted': 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
+(i.e. it didn't exist before)
+
'AuthPluginSetup': update or replace authentication plugin object ($wgAuth)
Gives a chance for an extension to set it programattically to a variable class.
&$auth: the $wgAuth object, probably a stub
@@ -308,6 +313,18 @@ $user: the user _doing_ the block (not the one being blocked)
$block: the Block object that was saved
$user: the user who did the block (not the one being blocked)
+'BookInformation': Before information output on Special:Booksources
+$isbn: ISBN to show information for
+$output: OutputPage object in use
+
+'CustomEditor': When invoking the page editor
+$article: Article being edited
+$user: User performing the edit
+
+Return true to allow the normal editor to be used, or false
+if implementing a custom editor, e.g. for a special namespace,
+etc.
+
'DiffViewHeader': called before diff display
$diff: DifferenceEngine object that's calling
$oldRev: Revision object of the "old" revision (may be null/invalid)
@@ -321,6 +338,11 @@ saved, that is before insertNewArticle() is called
&$text: Text to preload with
&$title: Title object representing the page being created
+'EditPage::showEditForm:fields': allows injection of form field into edit form
+&$editor: the EditPage instance for reference
+&$out: an OutputPage instance to write to
+return value is ignored (should always return true)
+
'EditFilter': Perform checks on an edit
$editor: Edit form (see includes/EditPage.php)
$text: Contents of the edit box
@@ -356,6 +378,9 @@ $text: text of the mail
&$list: List object (defaults to NULL, change it to an object instance and return
false override the list derivative used)
+'FileUpload': When a file upload occurs
+$file : Image object representing the file that was uploaded
+
'GetInternalURL': modify fully-qualified URLs used for squid cache purging
$title: Title object of page
$url: string value as output (out parameter, can modify)
@@ -371,6 +396,12 @@ $title: Title object of page
$url: string value as output (out parameter, can modify)
$query: query options passed to Title::getFullURL()
+'InternalParseBeforeLinks': during Parser's internalParse method before links but
+after noinclude/includeonly/onlyinclude and other processing.
+&$this: Parser object
+&$text: string containing partially parsed text
+&$this->mStripState: Parser's internal StripState object
+
'LogPageValidTypes': action being logged. DEPRECATED: Use $wgLogTypes
&$type: array of strings
@@ -405,11 +436,23 @@ 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)
+'PageHistoryBeforeList': When a history page list is about to be constructed.
+$article: the article that the history is loading for
+
+'PageHistoryLineEnding' : right before the end
is added to a history line
+$row: the revision row for this line
+$s: the string representing this parsed line
+
'PageRenderingHash': alter the parser cache option hash key
A parser extension which depends on user options should install
this hook and append its values to the key.
$hash: reference to a hash key string which can be modified
+'ParserTestTables': alter the list of tables to duplicate when parser tests
+are run. Use when page save hooks require the presence of custom tables
+to ensure that tests continue to run properly.
+&$tables: array of table names
+
'PersonalUrls': Alter the user-specific navigation links (e.g. "my page,
my talk page, my contributions" etc).
@@ -427,6 +470,16 @@ the built-in rate limiting checks are used, if enabled.
$form : PreferencesForm object
&$html : HTML to append to
+'RawPageViewBeforeOutput': Right before the text is blown out in action=raw
+&$obj: RawPage object
+&$text: The text that's going to be the output
+
+'SearchUpdate': Prior to search update completion
+$id : Page id
+$namespace : Page namespace
+$title : Page title
+$text : Current text being indexed
+
'SiteNoticeBefore': Before the sitenotice/anonnotice is composed
&$siteNotice: HTML returned as the sitenotice
Return true to allow the normal method of notice selection/rendering to work,
@@ -436,6 +489,10 @@ or change the value of $siteNotice and return false to alter it.
&$siteNotice: HTML sitenotice
Alter the contents of $siteNotice to add to/alter the sitenotice/anonnotice.
+'SkinTemplateOutputPageBeforeExec': Before SkinTemplate::outputPage() starts page output
+&$sktemplate: SkinTemplate object
+&$tpl: Template engine object
+
'TitleMoveComplete': after moving an article (title)
$old: old title
$nt: new title
@@ -529,5 +586,9 @@ $content_actions: The array of content actions
Can be used to set custom CSS/JS
$out: OutputPage object
+'AjaxAddScript': Called in output page just before the initialisation
+of the javascript ajax engine. The hook is only called when ajax
+is enabled ( $wgUseAjax = true; ).
+
More hooks might be available but undocumented, you can execute
./maintenance/findhooks.php to find hidden one.
diff --git a/docs/memcached.txt b/docs/memcached.txt
index 6752e9c8..d4e2915f 100644
--- a/docs/memcached.txt
+++ b/docs/memcached.txt
@@ -29,7 +29,6 @@ can run multiple servers on one machine or on multiple machines on
a network; storage can be distributed across multiple servers, and
multiple web servers can use the same cache cluster.
-
********************* W A R N I N G ! ! ! ! ! ***********************
Memcached has no security or authentication. Please ensure that your
server is appropriately firewalled, and that the port(s) used for
@@ -54,8 +53,8 @@ on port 11000, using up to 64MB of memory)
In your LocalSettings.php file, set:
- $wgUseMemCached = true;
- $wgMemCachedServers = array( "127.0.0.1:11000" );
+ $wgMainCacheType = CACHE_MEMCACHED;;
+ $wgMemCachedServers = array( "127.0.0.1:11000" );
The wiki should then use memcached to cache various data. To use
multiple servers (physically separate boxes or multiple caches
@@ -66,10 +65,9 @@ usage evenly), make its entry a subarray:
$wgMemCachedServers = array(
"127.0.0.1:11000", # one gig on this box
- array("192.168.0.1:11000", 2) # two gigs on the other box
+ array("192.168.0.1:11000", 2 ) # two gigs on the other box
);
-
== PHP client for memcached ==
As of this writing, MediaWiki includes version 1.0.10 of the PHP
@@ -129,4 +127,4 @@ IP blocks:
stores: array of arrays, for the BlockCache class
cleared by: BlockCache:clear()
-... more to come ...
+... more to come ...
\ No newline at end of file
diff --git a/docs/title.txt b/docs/title.txt
index b404bd3c..5d9bd417 100644
--- a/docs/title.txt
+++ b/docs/title.txt
@@ -35,9 +35,14 @@ and the colon is just removed. Note that because of these
rules, it is possible to have articles with colons in their
names. "E. Coli 0157:H7" is a valid title, as is "2001: A Space
Odyssey", because "E. Coli 0157" and "2001" are not valid
-interwikis or namespaces. Likewise, ":de:name" is a link to
-the article "de:name"--even though "de" is a valid interwiki,
-the initial colon stops all prefix matching.
+interwikis or namespaces.
+
+It is not possible to have an article whose bare name includes
+a namespace or interwiki prefix.
+
+An initial colon in a title listed in wiki text may however
+suppress special handling for interlanguage links, image links,
+and category links.
Character mapping rules: Once prefixes have been stripped, the
rest of the title processed this way: spaces and underscores are
@@ -64,9 +69,9 @@ lowercase. The namespace will use underscores when returned
alone; it will use spaces only when attached to the text title.
getArticleID() needs some explanation: for "internal" articles,
-it should return the "cur_id" field if the article exists, else
+it should return the "page_id" field if the article exists, else
it returns 0. For all external articles it returns 0. All of
the IDs for all instances of Title created during a request are
-cached, so they can be looked up wuickly while rendering wiki
+cached, so they can be looked up quickly while rendering wiki
text with lots of internal links.
diff --git a/extensions/FunnyDot.php b/extensions/FunnyDot.php
index 418575e2..d9d932ae 100644
--- a/extensions/FunnyDot.php
+++ b/extensions/FunnyDot.php
@@ -1,9 +1,6 @@
'FunnyDot',
@@ -12,13 +9,15 @@ $wgExtensionCredits['other'][] = array(
'url' => 'http://www.laber-land.de',
);
-function hexVal($in)
+class FunnyDot {
+
+private static function hexVal($in)
{
$result = preg_replace('/[^0-9a-fA-F]/', '', $in);
return (empty($result) ? 0 : $result);
}
-function checkAntiSpamHash()
+public static function checkAntiSpamHash()
{
global $wgAntiSpamHash, $wgAntiSpamTimeout, $wgAntiSpamWait;
@@ -27,7 +26,7 @@ function checkAntiSpamHash()
if (!empty($_COOKIE['AntiSpamTime']) && !empty($_COOKIE['AntiSpamHash']))
{
$time = intval($_COOKIE['AntiSpamTime']);
- $hash = hexVal($_COOKIE['AntiSpamHash']);
+ $hash = self::hexVal($_COOKIE['AntiSpamHash']);
if ($hash != sha1($time.$wgAntiSpamHash))
{
@@ -51,5 +50,6 @@ function checkAntiSpamHash()
return true;
}
-} # End invocation guard
+}
+
?>
\ No newline at end of file
diff --git a/extensions/LLAuthPlugin.php b/extensions/LLAuthPlugin.php
index 2d903b28..f5bb718f 100644
--- a/extensions/LLAuthPlugin.php
+++ b/extensions/LLAuthPlugin.php
@@ -1,40 +1,6 @@
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
-/**
- * Authentication plugin interface. Instantiate a subclass of AuthPlugin
- * and set $wgAuth to it to authenticate against some external tool.
- *
- * The default behavior is not to do anything, and use the local user
- * database for all authentication. A subclass can require that all
- * accounts authenticate externally, or use it only as a fallback; also
- * you can transparently create internal wiki accounts the first time
- * someone logs in who can be authenticated externally.
- *
- * This interface is new, and might change a bit before 1.4.0 final is
- * done...
- *
- * @package MediaWiki
- */
+$wgHooks['isValidPassword'][] = 'LLAuthPlugin::isValidPassword';
$wgExtensionCredits['other'][] = array(
'name' => 'LLAuthPlugin',
@@ -47,218 +13,92 @@ require_once('includes/AuthPlugin.php');
class LLAuthPlugin extends AuthPlugin {
+ public static function isValidPassword($password) {
+ $length = strlen($password);
+ return ($length >= 6 && $length <= 25);
+ }
+
private $dbLink = null;
- function __construct()
- {
+ function __construct() {
global $wgDBuser, $wgDBpassword;
$this->dbLink = mysqli_connect('localhost', $wgDBuser, $wgDBpassword, 'current');
- }
+ }
- function __destruct()
- {
+ function __destruct() {
mysqli_close($this->dbLink);
- }
+ }
- function getUserData($username)
- {
+ function getUserData($username) {
$result = mysqli_query($this->dbLink, 'SELECT id, email, realname FROM users WHERE name = \''.mysqli_escape_string($this->dbLink, $username).'\'');
$data = mysqli_fetch_assoc($result);
mysqli_free_result($result);
return $data;
- }
- /**
- * Check whether there exists a user account with the given name.
- * The name will be normalized to MediaWiki's requirements, so
- * you might need to munge it (for instance, for lowercase initial
- * letters).
- *
- * @param $username String: username.
- * @return bool
- * @public
- */
+ }
+
function userExists( $username ) {
$result = mysqli_query($this->dbLink, 'SELECT id FROM users WHERE name = \''.mysqli_escape_string($this->dbLink, $username).'\'');
$exists = mysqli_num_rows($result) > 0;
mysqli_free_result($result);
- return $exists;
+ return $exists;
}
- /**
- * Check if a username+password pair is a valid login.
- * The name will be normalized to MediaWiki's requirements, so
- * you might need to munge it (for instance, for lowercase initial
- * letters).
- *
- * @param $username String: username.
- * @param $password String: user password.
- * @return bool
- * @public
- */
function authenticate( $username, $password ) {
$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;
mysqli_free_result($result);
- return $authenticated;
+ return $authenticated;
}
- /**
- * Modify options in the login template.
- *
- * @param $template UserLoginTemplate object.
- * @public
- */
function modifyUITemplate( &$template ) {
- # Override this!
$template->set( 'usedomain', false );
$template->set('link', 'Um Dich hier anzumelden, nutze Deine Konto-Daten aus dem archlinux.de-Forum.');
}
- /**
- * Set the domain this plugin is supposed to use when authenticating.
- *
- * @param $domain String: authentication domain.
- * @public
- */
function setDomain( $domain ) {
$this->domain = $domain;
}
- /**
- * Check to see if the specific domain is a valid domain.
- *
- * @param $domain String: authentication domain.
- * @return bool
- * @public
- */
function validDomain( $domain ) {
- # Override this!
return true;
}
- /**
- * When a user logs in, optionally fill in preferences and such.
- * For instance, you might pull the email address or real name from the
- * external user database.
- *
- * The User object is passed by reference so it can be modified; don't
- * forget the & on your function declaration.
- *
- * @param User $user
- * @public
- */
function updateUser( &$user ) {
return $this->initUser($user);
}
-
- /**
- * Return true if the wiki should create a new local account automatically
- * when asked to login a user who doesn't exist locally but does in the
- * external auth database.
- *
- * If you don't automatically create accounts, you must still create
- * accounts in some way. It's not possible to authenticate without
- * a local account.
- *
- * This is just a question, and shouldn't perform any actions.
- *
- * @return bool
- * @public
- */
function autoCreate() {
return true;
}
- /**
- * Can users change their passwords?
- *
- * @return bool
- */
function allowPasswordChange() {
- return true;
+ return false;
}
- /**
- * Set the given password in the authentication database.
- * As a special case, the password may be set to null to request
- * locking the password to an unusable value, with the expectation
- * that it will be set later through a mail reset or other method.
- *
- * Return true if successful.
- *
- * @param $user User object.
- * @param $password String: password.
- * @return bool
- * @public
- */
function setPassword( $user, $password ) {
- return true;
+ return false;
}
- /**
- * Update user information in the external authentication database.
- * Return true if successful.
- *
- * @param $user User object.
- * @return bool
- * @public
- */
function updateExternalDB( $user ) {
+ // this way userdata is allways overwritten by external db
return $this->initUser($user);
}
- /**
- * Check to see if external accounts can be created.
- * Return true if external accounts can be created.
- * @return bool
- * @public
- */
function canCreateAccounts() {
return false;
}
- /**
- * Add a user to the external authentication database.
- * Return true if successful.
- *
- * @param User $user
- * @param string $password
- * @return bool
- * @public
- */
- function addUser( $user, $password ) {
+ function addUser( $user, $password, $email = '', $realname = '' ) {
return false;
}
-
- /**
- * Return true to prevent logins that don't authenticate here from being
- * checked against the local database's password fields.
- *
- * This is just a question, and shouldn't perform any actions.
- *
- * @return bool
- * @public
- */
function strict() {
return true;
}
- /**
- * When creating a user account, optionally fill in preferences and such.
- * For instance, you might pull the email address or real name from the
- * external user database.
- *
- * The User object is passed by reference so it can be modified; don't
- * forget the & on your function declaration.
- *
- * @param $user User object.
- * @public
- */
function initUser( &$user ) {
$data = $this->getUserData($user->getName());
$user->setEmail($data['email']);
@@ -267,10 +107,6 @@ class LLAuthPlugin extends AuthPlugin {
return true;
}
- /**
- * If you want to munge the case of an account name before the final
- * check, now is your chance.
- */
function getCanonicalName( $username ) {
return $username;
}
diff --git a/extensions/README b/extensions/README
index cc931160..85f4943b 100644
--- a/extensions/README
+++ b/extensions/README
@@ -1,3 +1,14 @@
-Some extensions (such as the hieroglyphic module WikiHiero) are
-distributed separately. Drop them into this extensions directory
-and enable as per the extension's directions.
+Extensions (such as the hieroglyphic module WikiHiero) are distributed
+separately. Drop them into this extensions directory and enable as
+per the extension's directions.
+
+If you are a developer, you want to fetch the extension tree in another
+directory and make a symbolic link:
+
+ mediawiki/extensions$ ln -s ../../extensions-trunk/FooBarExt
+
+The extensions are available through svn at:
+ http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/
+
+You can find documentation and additional extensions on MediaWiki website:
+ http://www.mediawiki.org/wiki/Category:Extensions
diff --git a/img_auth.php b/img_auth.php
index e0a6459f..11684b37 100644
--- a/img_auth.php
+++ b/img_auth.php
@@ -7,6 +7,7 @@
* to an array of pages you want everyone to be able to access. Your server must
* support PATH_INFO, CGI-based configurations generally don't.
*/
+define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
require_once( './includes/WebStart.php' );
wfProfileIn( 'img_auth.php' );
require_once( './includes/StreamFile.php' );
diff --git a/includes/AjaxDispatcher.php b/includes/AjaxDispatcher.php
index 39ec19f8..ca129029 100644
--- a/includes/AjaxDispatcher.php
+++ b/includes/AjaxDispatcher.php
@@ -1,7 +1,8 @@
mode = "";
@@ -28,14 +33,14 @@ class AjaxDispatcher {
}
if ($this->mode == "get") {
- $this->func_name = $_GET["rs"];
+ $this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : '';
if (! empty($_GET["rsargs"])) {
$this->args = $_GET["rsargs"];
} else {
$this->args = array();
}
} else {
- $this->func_name = $_POST["rs"];
+ $this->func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : '';
if (! empty($_POST["rsargs"])) {
$this->args = $_POST["rsargs"];
} else {
@@ -47,7 +52,7 @@ class AjaxDispatcher {
function performAction() {
global $wgAjaxExportList, $wgOut;
-
+
if ( empty( $this->mode ) ) {
return;
}
@@ -59,7 +64,7 @@ class AjaxDispatcher {
} else {
try {
$result = call_user_func_array($this->func_name, $this->args);
-
+
if ( $result === false || $result === NULL ) {
wfHttpError( 500, 'Internal Error',
"{$this->func_name} returned no data" );
@@ -68,7 +73,7 @@ class AjaxDispatcher {
if ( is_string( $result ) ) {
$result= new AjaxResponse( $result );
}
-
+
$result->sendHeaders();
$result->printText();
}
@@ -82,7 +87,7 @@ class AjaxDispatcher {
}
}
}
-
+
wfProfileOut( __METHOD__ );
$wgOut = null;
}
diff --git a/includes/AjaxFunctions.php b/includes/AjaxFunctions.php
index eee2a1a4..86f853db 100644
--- a/includes/AjaxFunctions.php
+++ b/includes/AjaxFunctions.php
@@ -1,7 +1,13 @@
ucfirst(
@@ -81,7 +86,7 @@ function wfSajaxSearch( $term ) {
if ( strlen( str_replace( '_', '', $term ) )<3 )
return;
- $db =& wfGetDB( DB_SLAVE );
+ $db = wfGetDB( DB_SLAVE );
$res = $db->select( 'page', 'page_title',
array( 'page_namespace' => 0,
"page_title LIKE '". $db->strencode( $term) ."%'" ),
@@ -108,8 +113,8 @@ function wfSajaxSearch( $term ) {
$subtitlemsg = ( Title::newFromText($term) ? 'searchsubtitle' : 'searchsubtitleinvalid' );
$subtitle = $wgOut->parse( wfMsg( $subtitlemsg, wfEscapeWikiText($term) ) ); #FIXME: parser is missing mTitle !
- $term = htmlspecialchars( $term );
- $html = '
";
+ }
return $r;
}
@@ -391,7 +404,7 @@ class CategoryViewer {
*/
function pagingLinks( $title, $first, $last, $limit, $query = array() ) {
global $wgUser, $wgLang;
- $sk =& $this->getSkin();
+ $sk = $this->getSkin();
$limitText = $wgLang->formatNum( $limit );
$prevLink = htmlspecialchars( wfMsg( 'prevn', $limitText ) );
diff --git a/includes/Categoryfinder.php b/includes/Categoryfinder.php
index a8cdf3ce..7faae935 100644
--- a/includes/Categoryfinder.php
+++ b/includes/Categoryfinder.php
@@ -1,26 +1,27 @@
seed (
- array ( 12345 ) ,
- array ( "Category 1","Category 2" ) ,
- "AND"
- ) ;
- $a = $cf->run() ;
- print implode ( "," , $a ) ;
-
-*/
-
+/**
+ * The "Categoryfinder" class takes a list of articles, creates an internal
+ * representation of all their parent categories (as well as parents of
+ * parents etc.). From this representation, it determines which of these
+ * articles are in one or all of a given subset of categories.
+ *
+ * Example use :
+ *
+ * # Determines whether the article with the page_id 12345 is in both
+ * # "Category 1" and "Category 2" or their subcategories, respectively
+ *
+ * $cf = new Categoryfinder ;
+ * $cf->seed (
+ * array ( 12345 ) ,
+ * array ( "Category 1","Category 2" ) ,
+ * "AND"
+ * ) ;
+ * $a = $cf->run() ;
+ * print implode ( "," , $a ) ;
+ *
+ *
+ */
class Categoryfinder {
var $articles = array () ; # The original article IDs passed to the seed function
@@ -34,8 +35,8 @@ class Categoryfinder {
/**
* Constructor (currently empty).
- */
- function Categoryfinder () {
+ */
+ function __construct() {
}
/**
@@ -61,10 +62,10 @@ class Categoryfinder {
/**
* Iterates through the parent tree starting with the seed values,
* then checks the articles if they match the conditions
- @return array of page_ids (those given to seed() that match the conditions)
- */
+ * @return array of page_ids (those given to seed() that match the conditions)
+ */
function run () {
- $this->dbr =& wfGetDB( DB_SLAVE );
+ $this->dbr = wfGetDB( DB_SLAVE );
while ( count ( $this->next ) > 0 ) {
$this->scan_next_layer () ;
}
@@ -83,20 +84,20 @@ 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
- @return bool Does this match the conditions?
- */
+ * @param $id The article/category to check
+ * @param $conds The array of categories to match
+ * @return bool Does this match the conditions?
+ */
function check ( $id , &$conds ) {
# Shortcut (runtime paranoia): No contitions=all matched
if ( count ( $conds ) == 0 ) return true ;
-
+
if ( !isset ( $this->parents[$id] ) ) return false ;
# iterate through the parents
foreach ( $this->parents[$id] AS $p ) {
$pname = $p->cl_to ;
-
+
# Is this a condition?
if ( isset ( $conds[$pname] ) ) {
# This key is in the category list!
@@ -113,7 +114,7 @@ class Categoryfinder {
}
}
}
-
+
# Not done yet, try sub-parents
if ( !isset ( $this->name2id[$pname] ) ) {
# No sub-parent
@@ -130,10 +131,10 @@ class Categoryfinder {
/**
* Scans a "parent layer" of the articles/categories in $this->next
- */
+ */
function scan_next_layer () {
$fname = "Categoryfinder::scan_next_layer" ;
-
+
# Find all parents of the article currently in $this->next
$layer = array () ;
$res = $this->dbr->select(
@@ -161,7 +162,7 @@ class Categoryfinder {
$this->dbr->freeResult( $res ) ;
$this->next = array() ;
-
+
# Find the IDs of all category pages in $layer, if they exist
if ( count ( $layer ) > 0 ) {
$res = $this->dbr->select(
diff --git a/includes/ChangesList.php b/includes/ChangesList.php
index a2c1a265..bc141579 100644
--- a/includes/ChangesList.php
+++ b/includes/ChangesList.php
@@ -1,15 +1,7 @@
mAttribs = $rc->mAttribs;
$rc2->mExtra = $rc->mExtra;
@@ -27,14 +18,17 @@ class RCCacheEntry extends RecentChange
} ;
/**
- * @package MediaWiki
+ * Class to show various lists of changes:
+ * - what links here
+ * - related changes
+ * - recent changes
*/
class ChangesList {
# Called by history lists and recent changes
#
/** @todo document */
- function ChangesList( &$skin ) {
+ function __construct( &$skin ) {
$this->skin =& $skin;
$this->preCacheMessages();
}
@@ -47,7 +41,7 @@ class ChangesList {
* @return ChangesList derivative
*/
public static function newFromUser( &$user ) {
- $sk =& $user->getSkin();
+ $sk = $user->getSkin();
$list = NULL;
if( wfRunHooks( 'FetchChangesList', array( &$user, &$sk, &$list ) ) ) {
return $user->getOption( 'usenewrc' ) ? new EnhancedChangesList( $sk ) : new OldChangesList( $sk );
@@ -64,7 +58,7 @@ class ChangesList {
// Precache various messages
if( !isset( $this->message ) ) {
foreach( explode(' ', 'cur diff hist minoreditletter newpageletter last '.
- 'blocklink changes history boteditletter' ) as $msg ) {
+ 'blocklink history boteditletter' ) as $msg ) {
$this->message[$msg] = wfMsgExt( $msg, array( 'escape') );
}
}
@@ -212,6 +206,23 @@ class ChangesList {
global $wgUseRCPatrol, $wgUser;
return( $wgUseRCPatrol && $wgUser->isAllowed( 'patrol' ) );
}
+
+ /**
+ * Returns the string which indicates the number of watching users
+ */
+ function numberofWatchingusers( $count ) {
+ global $wgLang;
+ static $cache = array();
+ if ( $count > 0 ) {
+ if ( !isset( $cache[$count] ) ) {
+ $cache[$count] = wfMsgExt('number_of_watching_users_RCview',
+ array('parsemag', 'escape'), $wgLang->formatNum($count));
+ }
+ return $cache[$count];
+ } else {
+ return '';
+ }
+ }
}
@@ -229,6 +240,7 @@ class OldChangesList extends ChangesList {
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 );
# Should patrol-related stuff be shown?
@@ -273,9 +285,7 @@ class OldChangesList extends ChangesList {
$this->insertUserRelatedLinks($s,$rc);
$this->insertComment($s, $rc);
- if($rc->numberofWatchingusers > 0) {
- $s .= ' ' . wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rc->numberofWatchingusers));
- }
+ $s .= rtrim(' ' . $this->numberofWatchingusers($rc->numberofWatchingusers));
$s .= "\n";
@@ -301,6 +311,7 @@ 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.
extract( $rc->mAttribs );
$curIdEq = 'curid=' . $rc_cur_id;
@@ -405,7 +416,7 @@ class EnhancedChangesList extends ChangesList {
* Enhanced RC group
*/
function recentChangesBlockGroup( $block ) {
- global $wgContLang, $wgRCShowChangedSize;
+ global $wgLang, $wgContLang, $wgRCShowChangedSize;
$r = '';
# Collate list of users
@@ -467,22 +478,32 @@ class EnhancedChangesList extends ChangesList {
$currentRevision = $block[0]->mAttribs['rc_this_oldid'];
if( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
# Changes
- $r .= ' ('.count($block).' ';
+
+ $n = count($block);
+ static $nchanges = array();
+ if ( !isset( $nchanges[$n] ) ) {
+ $nchanges[$n] = wfMsgExt( 'nchanges', array( 'parsemag', 'escape'),
+ $wgLang->formatNum( $n ) );
+ }
+
+ $r .= ' (';
if( $isnew ) {
- $r .= $this->message['changes'];
+ $r .= $nchanges[$n];
} else {
$r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
- $this->message['changes'], $curIdEq."&diff=$currentRevision&oldid=$oldid" );
+ $nchanges[$n], $curIdEq."&diff=$currentRevision&oldid=$oldid" );
}
+ $r .= ') . . ';
+
# Character difference
$chardiff = $rcObj->getCharacterDifference( $block[ count( $block ) - 1 ]->mAttribs['rc_old_len'],
$block[0]->mAttribs['rc_new_len'] );
if( $chardiff == '' ) {
- $r .= '; ';
+ $r .= ' (';
} else {
- $r .= '; ' . $chardiff . ' ';
+ $r .= ' ' . $chardiff. ' . . (';
}
@@ -494,16 +515,14 @@ class EnhancedChangesList extends ChangesList {
$r .= $users;
- if($block[0]->numberofWatchingusers > 0) {
- global $wgContLang;
- $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($block[0]->numberofWatchingusers));
- }
+ $r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers);
$r .= " \n";
# Sub-entries
$r .= '
';
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( $rcObj->mAttribs );
$r .= $this->spacerArrow();
@@ -607,6 +626,7 @@ class EnhancedChangesList extends ChangesList {
global $wgContLang, $wgRCShowChangedSize;
# Get rc_xxxx variables
+ // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
extract( $rcObj->mAttribs );
$curIdEq = 'curid='.$rc_cur_id;
@@ -647,9 +667,7 @@ class EnhancedChangesList extends ChangesList {
$r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
}
- if( $rcObj->numberofWatchingusers > 0 ) {
- $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rcObj->numberofWatchingusers));
- }
+ $r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers);
$r .= " \n";
return $r;
diff --git a/includes/CoreParserFunctions.php b/includes/CoreParserFunctions.php
index 402a3ba9..72ceb45f 100644
--- a/includes/CoreParserFunctions.php
+++ b/includes/CoreParserFunctions.php
@@ -2,8 +2,8 @@
/**
* Various core parser functions, registered in Parser::firstCallInit()
+ * @addtogroup Parser
*/
-
class CoreParserFunctions {
static function intFunction( $parser, $part1 = '' /*, ... */ ) {
if ( strval( $part1 ) !== '' ) {
@@ -87,7 +87,7 @@ class CoreParserFunctions {
static function formatNum( $parser, $num = '' ) {
return $parser->getFunctionLang()->formatNum( $num );
}
-
+
static function grammar( $parser, $case = '', $word = '' ) {
return $parser->getFunctionLang()->convertGrammar( $word, $case );
}
@@ -135,6 +135,7 @@ class CoreParserFunctions {
static function numberofarticles( $parser, $raw = null ) { return self::statisticsFunction( 'articles', $raw ); }
static function numberoffiles( $parser, $raw = null ) { return self::statisticsFunction( 'images', $raw ); }
static function numberofadmins( $parser, $raw = null ) { return self::statisticsFunction( 'admins', $raw ); }
+ static function numberofedits( $parser, $raw = null ) { return self::statisticsFunction( 'edits', $raw ); }
static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
$count = SiteStats::pagesInNs( intval( $namespace ) );
@@ -151,7 +152,7 @@ class CoreParserFunctions {
$lang = $wgContLang->getLanguageName( strtolower( $arg ) );
return $lang != '' ? $lang : $arg;
}
-
+
static function pad( $string = '', $length = 0, $char = 0, $direction = STR_PAD_RIGHT ) {
$length = min( max( $length, 0 ), 500 );
$char = substr( $char, 0, 1 );
@@ -159,17 +160,21 @@ class CoreParserFunctions {
? str_pad( $string, $length, (string)$char, $direction )
: $string;
}
-
+
static function padleft( $parser, $string = '', $length = 0, $char = 0 ) {
return self::pad( $string, $length, $char, STR_PAD_LEFT );
}
-
+
static function padright( $parser, $string = '', $length = 0, $char = 0 ) {
return self::pad( $string, $length, $char );
}
-
+
static function anchorencode( $parser, $text ) {
- return strtr( urlencode( $text ) , array( '%' => '.' , '+' => '_' ) );
+ $a = urlencode( $text );
+ $a = strtr( $a, array( '%' => '.', '+' => '_' ) );
+ # leave colons alone, however
+ $a = str_replace( '.3A', ':', $a );
+ return $a;
}
static function special( $parser, $text ) {
@@ -180,14 +185,12 @@ class CoreParserFunctions {
return wfMsgForContent( 'nosuchspecialpage' );
}
}
-
+
public static function defaultsort( $parser, $text ) {
$text = trim( $text );
if( strlen( $text ) > 0 )
$parser->setDefaultSort( $text );
return '';
}
-
}
-
?>
diff --git a/includes/Credits.php b/includes/Credits.php
index 62f0b256..87382a86 100644
--- a/includes/Credits.php
+++ b/includes/Credits.php
@@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* @author
- * @package MediaWiki
*/
/**
diff --git a/includes/Database.php b/includes/Database.php
index eb1ee135..3fd6ad16 100644
--- a/includes/Database.php
+++ b/includes/Database.php
@@ -2,7 +2,6 @@
/**
* This file deals with MySQL interface functions
* and query specifics/optimisations
- * @package MediaWiki
*/
/** Number of times to re-try an operation in case of deadlock */
@@ -16,6 +15,10 @@ define( 'DEADLOCK_DELAY_MAX', 1500000 );
* Utility classes
*****************************************************************************/
+/**
+ * Utility class.
+ * @addtogroup Database
+ */
class DBObject {
public $mData;
@@ -32,12 +35,66 @@ class DBObject {
}
};
+/**
+ * Utility class.
+ * @addtogroup Database
+ */
+class MySQLField {
+ private $name, $tablename, $default, $max_length, $nullable,
+ $is_pk, $is_unique, $is_key, $type;
+ function __construct ($info) {
+ $this->name = $info->name;
+ $this->tablename = $info->table;
+ $this->default = $info->def;
+ $this->max_length = $info->max_length;
+ $this->nullable = !$info->not_null;
+ $this->is_pk = $info->primary_key;
+ $this->is_unique = $info->unique_key;
+ $this->is_multiple = $info->multiple_key;
+ $this->is_key = ($this->is_pk || $this->is_unique || $this->is_multiple);
+ $this->type = $info->type;
+ }
+
+ function name() {
+ return $this->name;
+ }
+
+ function tableName() {
+ return $this->tableName;
+ }
+
+ function defaultValue() {
+ return $this->default;
+ }
+
+ function maxLength() {
+ return $this->max_length;
+ }
+
+ function nullable() {
+ return $this->nullable;
+ }
+
+ function isKey() {
+ return $this->is_key;
+ }
+
+ function isMultipleKey() {
+ return $this->is_multiple;
+ }
+
+ function type() {
+ return $this->type;
+ }
+}
+
/******************************************************************************
* Error classes
*****************************************************************************/
/**
* Database error base class
+ * @addtogroup Database
*/
class DBError extends MWException {
public $db;
@@ -53,6 +110,9 @@ class DBError extends MWException {
}
}
+/**
+ * @addtogroup Database
+ */
class DBConnectionError extends DBError {
public $error;
@@ -154,6 +214,7 @@ border=\"0\" ALT=\"Google\">
$cache = new HTMLFileCache( $t );
if( $cache->isFileCached() ) {
+ // FIXME: $msg is not defined on the next line.
$msg = '
'.$msg." \n" .
$cachederror . "
\n";
@@ -169,6 +230,9 @@ border=\"0\" ALT=\"Google\">
}
}
+/**
+ * @addtogroup Database
+ */
class DBQueryError extends DBError {
public $error, $errno, $sql, $fname;
@@ -222,13 +286,16 @@ class DBQueryError extends DBError {
}
}
+/**
+ * @addtogroup Database
+ */
class DBUnexpectedError extends DBError {}
/******************************************************************************/
/**
* Database abstraction object
- * @package MediaWiki
+ * @addtogroup Database
*/
class Database {
@@ -247,9 +314,6 @@ class Database {
protected $mTrxLevel = 0;
protected $mErrorCount = 0;
protected $mLBInfo = array();
- protected $mCascadingDeletes = false;
- protected $mCleanupTriggers = false;
- protected $mStrictIPs = false;
#------------------------------------------------------------------------------
# Accessors
@@ -344,14 +408,14 @@ class Database {
* Returns true if this database supports (and uses) cascading deletes
*/
function cascadingDeletes() {
- return $this->mCascadingDeletes;
+ return false;
}
/**
* Returns true if this database supports (and uses) triggers (e.g. on the page table)
*/
function cleanupTriggers() {
- return $this->mCleanupTriggers;
+ return false;
}
/**
@@ -359,7 +423,7 @@ class Database {
* Specifically, it uses a NULL value instead of an empty string.
*/
function strictIPs() {
- return $this->mStrictIPs;
+ return false;
}
/**
@@ -376,6 +440,14 @@ class Database {
return true;
}
+ /**
+ * Returns true if this database can do a native search on IP columns
+ * e.g. this works as expected: .. WHERE rc_ip = '127.42.12.102/32';
+ */
+ function searchableIPs() {
+ return false;
+ }
+
/**#@+
* Get function
*/
@@ -407,13 +479,11 @@ class Database {
#------------------------------------------------------------------------------
/**@{{
+ * Constructor.
* @param string $server database server host
* @param string $user database user name
* @param string $password database user password
* @param string $dbname database name
- */
-
- /**
* @param failFunction
* @param $flags
* @param $tablePrefix String: database table prefixes. By default use the prefix gave in LocalSettings.php
@@ -463,8 +533,7 @@ class Database {
* @param failFunction
* @param $flags
*/
- static function newFromParams( $server, $user, $password, $dbName,
- $failFunction = false, $flags = 0 )
+ static function newFromParams( $server, $user, $password, $dbName, $failFunction = false, $flags = 0 )
{
return new Database( $server, $user, $password, $dbName, $failFunction, $flags );
}
@@ -514,7 +583,7 @@ class Database {
}
if ($this->mConn === false) {
$iplus = $i + 1;
- wfLogDBError("Connect loop error $iplus of $max ($server): " . mysql_errno() . " - " . mysql_error()."\n");
+ #wfLogDBError("Connect loop error $iplus of $max ($server): " . mysql_errno() . " - " . mysql_error()."\n");
}
}
@@ -541,12 +610,19 @@ class Database {
}
if ( $success ) {
- global $wgDBmysql5;
- if( $wgDBmysql5 ) {
+ $version = $this->getServerVersion();
+ if ( version_compare( $version, '4.1' ) >= 0 ) {
// Tell the server we're communicating with it in UTF-8.
// This may engage various charset conversions.
- $this->query( 'SET NAMES utf8' );
+ global $wgDBmysql5;
+ if( $wgDBmysql5 ) {
+ $this->query( 'SET NAMES utf8', __METHOD__ );
+ }
+ // Turn off strict mode
+ $this->query( "SET sql_mode = ''", __METHOD__ );
}
+
+ // Turn off strict mode if it is on
} else {
$this->reportConnectionError();
}
@@ -599,10 +675,15 @@ class Database {
}
/**
- * Usually aborts on failure
- * If errors are explicitly ignored, returns success
+ * Usually aborts on failure. If errors are explicitly ignored, returns success.
+ *
+ * @param $sql String: SQL query
+ * @param $fname String: Name of the calling function, for profiling/SHOW PROCESSLIST comment (you can use __METHOD__ or add some extra info)
+ * @param $tempIgnore Bool: Whether to avoid throwing an exception on errors... maybe best to catch the exception instead?
+ * @return Result object to feed to fetchObject, fetchRow, ...; or false on failure if $tempIgnore set
+ * @throws DBQueryError Thrown when the database returns an error of any kind
*/
- function query( $sql, $fname = '', $tempIgnore = false ) {
+ public function query( $sql, $fname = '', $tempIgnore = false ) {
global $wgProfiling;
if ( $wgProfiling ) {
@@ -626,11 +707,21 @@ class Database {
$this->mLastQuery = $sql;
# Add a comment for easy SHOW PROCESSLIST interpretation
- if ( $fname ) {
- $commentedSql = preg_replace('/\s/', " /* $fname */ ", $sql, 1);
- } else {
- $commentedSql = $sql;
- }
+ #if ( $fname ) {
+ global $wgUser;
+ if ( is_object( $wgUser ) && !($wgUser instanceof StubObject) ) {
+ $userName = $wgUser->getName();
+ if ( strlen( $userName ) > 15 ) {
+ $userName = substr( $userName, 0, 15 ) . '...';
+ }
+ $userName = str_replace( '/', '', $userName );
+ } else {
+ $userName = '';
+ }
+ $commentedSql = preg_replace('/\s/', " /* $fname $userName */ ", $sql, 1);
+ #} else {
+ # $commentedSql = $sql;
+ #}
# If DBO_TRX is set, start a transaction
if ( ( $this->mFlags & DBO_TRX ) && !$this->trxLevel() &&
@@ -655,6 +746,11 @@ class Database {
wfDebug( "Connection lost, reconnecting...\n" );
if ( $this->ping() ) {
wfDebug( "Reconnected\n" );
+ $sqlx = substr( $commentedSql, 0, 500 );
+ $sqlx = strtr( $sqlx, "\t\n", ' ' );
+ global $wgRequestTime;
+ $elapsed = round( microtime(true) - $wgRequestTime, 3 );
+ wfLogDBError( "Connection lost and reconnected after {$elapsed}s, query: $sqlx\n" );
$ret = $this->doQuery( $commentedSql );
} else {
wfDebug( "Failed\n" );
@@ -674,9 +770,11 @@ class Database {
/**
* The DBMS-dependent part of query()
- * @param string $sql SQL query.
+ * @param $sql String: SQL query.
+ * @return Result object to feed to fetchObject, fetchRow, ...; or false on failure
+ * @access private
*/
- function doQuery( $sql ) {
+ /*private*/ function doQuery( $sql ) {
if( $this->bufferResults() ) {
$ret = mysql_query( $sql, $this->mConn );
} else {
@@ -817,7 +915,13 @@ class Database {
}
/**
- * Fetch the next row from the given result object, in object form
+ * Fetch the next row from the given result object, in object form.
+ * Fields can be retrieved with $row->fieldname, with fields acting like
+ * member variables.
+ *
+ * @param $res SQL result object as returned from Database::query(), etc.
+ * @return MySQL row object
+ * @throws DBUnexpectedError Thrown if the database returns an error
*/
function fetchObject( $res ) {
@/**/$row = mysql_fetch_object( $res );
@@ -828,8 +932,12 @@ class Database {
}
/**
- * Fetch the next row from the given result object
- * Returns an array
+ * Fetch the next row from the given result object, in associative array
+ * form. Fields are retrieved with $row['fieldname'].
+ *
+ * @param $res SQL result object as returned from Database::query(), etc.
+ * @return MySQL row object
+ * @throws DBUnexpectedError Thrown if the database returns an error
*/
function fetchRow( $res ) {
@/**/$row = mysql_fetch_array( $res );
@@ -972,7 +1080,7 @@ class Database {
* @return array
*/
function makeSelectOptions( $options ) {
- $tailOpts = '';
+ $preLimitTail = $postLimitTail = '';
$startOpts = '';
$noKeyOptions = array();
@@ -982,16 +1090,17 @@ class Database {
}
}
- if ( isset( $options['GROUP BY'] ) ) $tailOpts .= " GROUP BY {$options['GROUP BY']}";
- if ( isset( $options['ORDER BY'] ) ) $tailOpts .= " ORDER BY {$options['ORDER BY']}";
+ if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY {$options['GROUP BY']}";
+ if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY {$options['ORDER BY']}";
- if (isset($options['LIMIT'])) {
- $tailOpts .= $this->limitResult('', $options['LIMIT'],
- isset($options['OFFSET']) ? $options['OFFSET'] : false);
- }
-
- if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $tailOpts .= ' FOR UPDATE';
- if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $tailOpts .= ' LOCK IN SHARE MODE';
+ //if (isset($options['LIMIT'])) {
+ // $tailOpts .= $this->limitResult('', $options['LIMIT'],
+ // isset($options['OFFSET']) ? $options['OFFSET']
+ // : false);
+ //}
+
+ if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $postLimitTail .= ' FOR UPDATE';
+ if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $postLimitTail .= ' LOCK IN SHARE MODE';
if ( isset( $noKeyOptions['DISTINCT'] ) && isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT';
# Various MySQL extensions
@@ -1010,7 +1119,7 @@ class Database {
$useIndex = '';
}
- return array( $startOpts, $useIndex, $tailOpts );
+ return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
}
/**
@@ -1038,20 +1147,33 @@ class Database {
else
$from = ' FROM ' . implode( ',', array_map( array( &$this, 'tableName' ), $table ) );
} elseif ($table!='') {
- $from = ' FROM ' . $this->tableName( $table );
+ if ($table{0}==' ') {
+ $from = ' FROM ' . $table;
+ } else {
+ $from = ' FROM ' . $this->tableName( $table );
+ }
} else {
$from = '';
}
- list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $options );
+ list( $startOpts, $useIndex, $preLimitTail, $postLimitTail ) = $this->makeSelectOptions( $options );
if( !empty( $conds ) ) {
if ( is_array( $conds ) ) {
$conds = $this->makeList( $conds, LIST_AND );
}
- $sql = "SELECT $startOpts $vars $from $useIndex WHERE $conds $tailOpts";
+ $sql = "SELECT $startOpts $vars $from $useIndex WHERE $conds $preLimitTail";
} else {
- $sql = "SELECT $startOpts $vars $from $useIndex $tailOpts";
+ $sql = "SELECT $startOpts $vars $from $useIndex $preLimitTail";
+ }
+
+ if (isset($options['LIMIT']))
+ $sql = $this->limitResult($sql, $options['LIMIT'],
+ isset($options['OFFSET']) ? $options['OFFSET'] : false);
+ $sql = "$sql $postLimitTail";
+
+ if (isset($options['EXPLAIN'])) {
+ $sql = 'EXPLAIN ' . $sql;
}
return $this->query( $sql, $fname );
@@ -1085,6 +1207,33 @@ class Database {
return $obj;
}
+
+ /**
+ * Estimate rows in dataset
+ * Returns estimated count, based on EXPLAIN output
+ * Takes same arguments as Database::select()
+ */
+
+ function estimateRowCount( $table, $vars='*', $conds='', $fname = 'Database::estimateRowCount', $options = array() ) {
+ $options['EXPLAIN']=true;
+ $res = $this->select ($table, $vars, $conds, $fname, $options );
+ if ( $res === false )
+ return false;
+ if (!$this->numRows($res)) {
+ $this->freeResult($res);
+ return 0;
+ }
+
+ $rows=1;
+
+ while( $plan = $this->fetchObject( $res ) ) {
+ $rows *= ($plan->rows > 0)?$plan->rows:1; // avoid resetting to zero
+ }
+
+ $this->freeResult($res);
+ return $rows;
+ }
+
/**
* Removes most variables from an SQL query and replaces them with X or N for numbers.
@@ -1207,7 +1356,7 @@ class Database {
for( $i = 0; $i < $n; $i++ ) {
$meta = mysql_fetch_field( $res, $i );
if( $field == $meta->name ) {
- return $meta;
+ return new MySQLField($meta);
}
}
return false;
@@ -1417,7 +1566,7 @@ class Database {
}
/**
- * @desc: Fetch a number of table names into an zero-indexed numerical array
+ * Fetch a number of table names into an zero-indexed numerical array
* This is handy when you need to construct SQL for joins
*
* Example:
@@ -1951,21 +2100,51 @@ class Database {
return $b;
}
+ /**
+ * Override database's default connection timeout.
+ * May be useful for very long batch queries such as
+ * full-wiki dumps, where a single query reads out
+ * over hours or days.
+ * @param int $timeout in seconds
+ */
+ public function setTimeout( $timeout ) {
+ $this->query( "SET net_read_timeout=$timeout" );
+ $this->query( "SET net_write_timeout=$timeout" );
+ }
+
/**
* Read and execute SQL commands from a file.
* Returns true on success, error string on failure
+ * @param string $filename File name to open
+ * @param callback $lineCallback Optional function called before reading each line
+ * @param callback $resultCallback Optional function called for each MySQL result
*/
- function sourceFile( $filename ) {
+ function sourceFile( $filename, $lineCallback = false, $resultCallback = false ) {
$fp = fopen( $filename, 'r' );
if ( false === $fp ) {
return "Could not open \"{$filename}\".\n";
}
+ $error = $this->sourceStream( $fp, $lineCallback, $resultCallback );
+ fclose( $fp );
+ return $error;
+ }
+ /**
+ * Read and execute commands from an open file handle
+ * Returns true on success, error string on failure
+ * @param string $fp File handle
+ * @param callback $lineCallback Optional function called before reading each line
+ * @param callback $resultCallback Optional function called for each MySQL result
+ */
+ function sourceStream( $fp, $lineCallback = false, $resultCallback = false ) {
$cmd = "";
$done = false;
$dollarquote = false;
while ( ! feof( $fp ) ) {
+ if ( $lineCallback ) {
+ call_user_func( $lineCallback );
+ }
$line = trim( fgets( $fp, 1024 ) );
$sl = strlen( $line ) - 1;
@@ -1995,7 +2174,10 @@ class Database {
if ( $done ) {
$cmd = str_replace(';;', ";", $cmd);
$cmd = $this->replaceVars( $cmd );
- $res = $this->query( $cmd, 'dbsource', true );
+ $res = $this->query( $cmd, __METHOD__, true );
+ if ( $resultCallback ) {
+ call_user_func( $resultCallback, $this->resultObject( $res ) );
+ }
if ( false === $res ) {
$err = $this->lastError();
@@ -2006,10 +2188,10 @@ class Database {
$done = false;
}
}
- fclose( $fp );
return true;
}
+
/**
* Replace variables in sourced SQL
*/
@@ -2017,7 +2199,7 @@ class Database {
$varnames = array(
'wgDBserver', 'wgDBname', 'wgDBintlname', 'wgDBuser',
'wgDBpassword', 'wgDBsqluser', 'wgDBsqlpassword',
- 'wgDBadminuser', 'wgDBadminpassword',
+ 'wgDBadminuser', 'wgDBadminpassword', 'wgDBTableOptions',
);
// Ordinary variables
@@ -2050,7 +2232,7 @@ class Database {
* Database abstraction object for mySQL
* Inherit all methods and properties of Database::Database()
*
- * @package MediaWiki
+ * @addtogroup Database
* @see Database
*/
class DatabaseMysql extends Database {
@@ -2060,8 +2242,7 @@ class DatabaseMysql extends Database {
/**
* Result wrapper for grabbing data queried by someone else
- *
- * @package MediaWiki
+ * @addtogroup Database
*/
class ResultWrapper {
var $db, $result;
@@ -2107,6 +2288,12 @@ class ResultWrapper {
function seek( $row ) {
$this->db->dataSeek( $this->result, $row );
}
+
+ function rewind() {
+ if ($this->numRows()) {
+ $this->db->dataSeek($this->result, 0);
+ }
+ }
}
diff --git a/includes/DatabaseFunctions.php b/includes/DatabaseFunctions.php
index ca83b9e5..4b31b4f0 100644
--- a/includes/DatabaseFunctions.php
+++ b/includes/DatabaseFunctions.php
@@ -3,7 +3,6 @@
* Legacy database functions, for compatibility with pre-1.3 code
* NOTE: this file is no longer loaded by default.
*
- * @package MediaWiki
*/
/**
@@ -18,7 +17,7 @@ function wfQuery( $sql, $db, $fname = '' ) {
# Someone has tried to call this the old way
throw new FatalError( wfMsgNoDB( 'wrong_wfQuery_params', $db, $sql ) );
}
- $c =& wfGetDB( $db );
+ $c = wfGetDB( $db );
if ( $c !== false ) {
return $c->query( $sql, $fname );
} else {
@@ -34,7 +33,7 @@ function wfQuery( $sql, $db, $fname = '' ) {
* @return Array: first row from the database
*/
function wfSingleQuery( $sql, $dbi, $fname = '' ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
$res = $db->query($sql, $fname );
$row = $db->fetchRow( $res );
$ret = $row[0];
@@ -54,7 +53,7 @@ function wfSingleQuery( $sql, $dbi, $fname = '' ) {
* @return Returns the previous state.
*/
function wfIgnoreSQLErrors( $newstate, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->ignoreErrors( $newstate );
} else {
@@ -73,7 +72,7 @@ function wfIgnoreSQLErrors( $newstate, $dbi = DB_LAST ) {
*/
function wfFreeResult( $res, $dbi = DB_LAST )
{
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
$db->freeResult( $res );
return true;
@@ -87,7 +86,7 @@ function wfFreeResult( $res, $dbi = DB_LAST )
* @return object|false object we requested
*/
function wfFetchObject( $res, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->fetchObject( $res, $dbi = DB_LAST );
} else {
@@ -100,7 +99,7 @@ function wfFetchObject( $res, $dbi = DB_LAST ) {
* @return object|false row we requested
*/
function wfFetchRow( $res, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->fetchRow ( $res, $dbi = DB_LAST );
} else {
@@ -113,7 +112,7 @@ function wfFetchRow( $res, $dbi = DB_LAST ) {
* @return integer|false number of rows
*/
function wfNumRows( $res, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->numRows( $res, $dbi = DB_LAST );
} else {
@@ -126,7 +125,7 @@ function wfNumRows( $res, $dbi = DB_LAST ) {
* @return integer|false number of fields
*/
function wfNumFields( $res, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->numFields( $res );
} else {
@@ -143,7 +142,7 @@ function wfNumFields( $res, $dbi = DB_LAST ) {
*/
function wfFieldName( $res, $n, $dbi = DB_LAST )
{
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->fieldName( $res, $n, $dbi = DB_LAST );
} else {
@@ -156,7 +155,7 @@ function wfFieldName( $res, $n, $dbi = DB_LAST )
* @todo document function
*/
function wfInsertId( $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->insertId();
} else {
@@ -168,7 +167,7 @@ function wfInsertId( $dbi = DB_LAST ) {
* @todo document function
*/
function wfDataSeek( $res, $row, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->dataSeek( $res, $row );
} else {
@@ -180,7 +179,7 @@ function wfDataSeek( $res, $row, $dbi = DB_LAST ) {
* @todo document function
*/
function wfLastErrno( $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->lastErrno();
} else {
@@ -192,7 +191,7 @@ function wfLastErrno( $dbi = DB_LAST ) {
* @todo document function
*/
function wfLastError( $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->lastError();
} else {
@@ -204,7 +203,7 @@ function wfLastError( $dbi = DB_LAST ) {
* @todo document function
*/
function wfAffectedRows( $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->affectedRows();
} else {
@@ -216,7 +215,7 @@ function wfAffectedRows( $dbi = DB_LAST ) {
* @todo document function
*/
function wfLastDBquery( $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->lastQuery();
} else {
@@ -235,7 +234,7 @@ function wfLastDBquery( $dbi = DB_LAST ) {
*/
function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_MASTER )
{
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->set( $table, $var, $value, $cond );
} else {
@@ -254,7 +253,7 @@ function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_MASTER )
*/
function wfGetSQL( $table, $var, $cond='', $dbi = DB_LAST )
{
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->selectField( $table, $var, $cond );
} else {
@@ -271,7 +270,7 @@ function wfGetSQL( $table, $var, $cond='', $dbi = DB_LAST )
* @return Result of Database::fieldExists() or false.
*/
function wfFieldExists( $table, $field, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->fieldExists( $table, $field );
} else {
@@ -288,7 +287,7 @@ function wfFieldExists( $table, $field, $dbi = DB_LAST ) {
* @return Result of Database::indexExists() or false.
*/
function wfIndexExists( $table, $index, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->indexExists( $table, $index );
} else {
@@ -306,7 +305,7 @@ function wfIndexExists( $table, $index, $dbi = DB_LAST ) {
* @return result of Database::insert() or false.
*/
function wfInsertArray( $table, $array, $fname = 'wfInsertArray', $dbi = DB_MASTER ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->insert( $table, $array, $fname );
} else {
@@ -325,7 +324,7 @@ function wfInsertArray( $table, $array, $fname = 'wfInsertArray', $dbi = DB_MAST
* @return result of Database::getArray() or false.
*/
function wfGetArray( $table, $vars, $conds, $fname = 'wfGetArray', $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->getArray( $table, $vars, $conds, $fname );
} else {
@@ -344,7 +343,7 @@ function wfGetArray( $table, $vars, $conds, $fname = 'wfGetArray', $dbi = DB_LAS
* @todo document function
*/
function wfUpdateArray( $table, $values, $conds, $fname = 'wfUpdateArray', $dbi = DB_MASTER ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
$db->update( $table, $values, $conds, $fname );
return true;
@@ -357,7 +356,7 @@ function wfUpdateArray( $table, $values, $conds, $fname = 'wfUpdateArray', $dbi
* @todo document function
*/
function wfTableName( $name, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->tableName( $name );
} else {
@@ -369,7 +368,7 @@ function wfTableName( $name, $dbi = DB_LAST ) {
* @todo document function
*/
function wfStrencode( $s, $dbi = DB_LAST ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->strencode( $s );
} else {
@@ -381,7 +380,7 @@ function wfStrencode( $s, $dbi = DB_LAST ) {
* @todo document function
*/
function wfNextSequenceValue( $seqName, $dbi = DB_MASTER ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->nextSequenceValue( $seqName );
} else {
@@ -393,7 +392,7 @@ function wfNextSequenceValue( $seqName, $dbi = DB_MASTER ) {
* @todo document function
*/
function wfUseIndexClause( $index, $dbi = DB_SLAVE ) {
- $db =& wfGetDB( $dbi );
+ $db = wfGetDB( $dbi );
if ( $db !== false ) {
return $db->useIndexClause( $index );
} else {
diff --git a/includes/DatabaseOracle.php b/includes/DatabaseOracle.php
index 1a6f62f2..2b720df7 100644
--- a/includes/DatabaseOracle.php
+++ b/includes/DatabaseOracle.php
@@ -1,44 +1,141 @@
mData = $data;
}
- function data() {
+
+ function getData() {
return $this->mData;
}
-};
+}
+
+/**
+ * The oci8 extension is fairly weak and doesn't support oci_num_rows, among
+ * other things. We use a wrapper class to handle that and other
+ * Oracle-specific bits, like converting column names back to lowercase.
+ * @addtogroup Database
+ */
+class ORAResult {
+ private $rows;
+ private $cursor;
+ private $stmt;
+ private $nrows;
+ private $db;
+
+ function __construct(&$db, $stmt) {
+ $this->db =& $db;
+ if (($this->nrows = oci_fetch_all($stmt, $this->rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM)) === false) {
+ $e = oci_error($stmt);
+ $db->reportQueryError($e['message'], $e['code'], '', __FUNCTION__);
+ return;
+ }
+
+ $this->cursor = 0;
+ $this->stmt = $stmt;
+ }
+
+ function free() {
+ oci_free_statement($this->stmt);
+ }
+
+ function seek($row) {
+ $this->cursor = min($row, $this->nrows);
+ }
+
+ function numRows() {
+ return $this->nrows;
+ }
+
+ function numFields() {
+ return oci_num_fields($this->stmt);
+ }
+
+ function fetchObject() {
+ if ($this->cursor >= $this->nrows)
+ return false;
+
+ $row = $this->rows[$this->cursor++];
+ $ret = new stdClass();
+ foreach ($row as $k => $v) {
+ $lc = strtolower(oci_field_name($this->stmt, $k + 1));
+ $ret->$lc = $v;
+ }
+
+ return $ret;
+ }
+
+ function fetchAssoc() {
+ if ($this->cursor >= $this->nrows)
+ return false;
+
+ $row = $this->rows[$this->cursor++];
+ $ret = array();
+ foreach ($row as $k => $v) {
+ $lc = strtolower(oci_field_name($this->stmt, $k + 1));
+ $ret[$lc] = $v;
+ $ret[$k] = $v;
+ }
+ return $ret;
+ }
+}
/**
- *
- * @package MediaWiki
+ * @addtogroup Database
*/
class DatabaseOracle extends Database {
var $mInsertId = NULL;
var $mLastResult = NULL;
- var $mFetchCache = array();
- var $mFetchID = array();
- var $mNcols = array();
- var $mFieldNames = array(), $mFieldTypes = array();
- var $mAffectedRows = array();
- var $mErr;
+ var $numeric_version = NULL;
+ var $lastResult = null;
+ var $cursor = 0;
+ var $mAffectedRows;
function DatabaseOracle($server = false, $user = false, $password = false, $dbName = false,
- $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
+ $failFunction = false, $flags = 0 )
{
- Database::Database( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
+
+ global $wgOut;
+ # Can't get a reference if it hasn't been set yet
+ if ( !isset( $wgOut ) ) {
+ $wgOut = NULL;
+ }
+ $this->mOut =& $wgOut;
+ $this->mFailFunction = $failFunction;
+ $this->mFlags = $flags;
+ $this->open( $server, $user, $password, $dbName);
+
+ }
+
+ function cascadingDeletes() {
+ return true;
+ }
+ function cleanupTriggers() {
+ return true;
+ }
+ function strictIPs() {
+ return true;
+ }
+ function realTimestamps() {
+ return true;
+ }
+ function implicitGroupby() {
+ return false;
+ }
+ function searchableIPs() {
+ return true;
}
- /* static */ function newFromParams( $server = false, $user = false, $password = false, $dbName = false,
- $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
+ static function newFromParams( $server = false, $user = false, $password = false, $dbName = false,
+ $failFunction = false, $flags = 0)
{
- return new DatabaseOracle( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
+ return new DatabaseOracle( $server, $user, $password, $dbName, $failFunction, $flags );
}
/**
@@ -47,23 +144,33 @@ class DatabaseOracle extends Database {
*/
function open( $server, $user, $password, $dbName ) {
if ( !function_exists( 'oci_connect' ) ) {
- throw new DBConnectionError( $this, "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n" );
+ throw new DBConnectionError( $this, "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" );
}
+
+ # Needed for proper UTF-8 functionality
+ putenv("NLS_LANG=AMERICAN_AMERICA.AL32UTF8");
+
$this->close();
$this->mServer = $server;
$this->mUser = $user;
$this->mPassword = $password;
$this->mDBname = $dbName;
- $this->mConn = oci_new_connect($user, $password, $dbName, "AL32UTF8");
- if ( $this->mConn === false ) {
- wfDebug( "DB connection error\n" );
- wfDebug( "Server: $server, Database: $dbName, User: $user, Password: "
- . substr( $password, 0, 3 ) . "...\n" );
- wfDebug( $this->lastError()."\n" );
- } else {
- $this->mOpened = true;
+ if (!strlen($user)) { ## e.g. the class is being loaded
+ return;
+ }
+
+ error_reporting( E_ALL );
+ $this->mConn = oci_connect($user, $password, $dbName);
+
+ if ($this->mConn == false) {
+ wfDebug("DB connection error\n");
+ wfDebug("Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n");
+ wfDebug($this->lastError()."\n");
+ return false;
}
+
+ $this->mOpened = true;
return $this->mConn;
}
@@ -73,116 +180,67 @@ class DatabaseOracle extends Database {
*/
function close() {
$this->mOpened = false;
- if ($this->mConn) {
- return oci_close($this->mConn);
+ if ( $this->mConn ) {
+ return oci_close( $this->mConn );
} else {
return true;
}
}
- function parseStatement($sql) {
- $this->mErr = $this->mLastResult = false;
- if (($stmt = oci_parse($this->mConn, $sql)) === false) {
- $this->lastError();
- return $this->mLastResult = false;
- }
- $this->mAffectedRows[$stmt] = 0;
- return $this->mLastResult = $stmt;
+ function execFlags() {
+ return $this->mTrxLevel ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS;
}
function doQuery($sql) {
- if (($stmt = $this->parseStatement($sql)) === false)
- return false;
- return $this->executeStatement($stmt);
- }
+ wfDebug("SQL: [$sql]\n");
+ if (!mb_check_encoding($sql)) {
+ throw new MWException("SQL encoding is invalid");
+ }
- function executeStatement($stmt) {
- if (!oci_execute($stmt, OCI_DEFAULT)) {
- $this->lastError();
- oci_free_statement($stmt);
- return false;
+ if (($this->mLastResult = $stmt = oci_parse($this->mConn, $sql)) === false) {
+ $e = oci_error($this->mConn);
+ $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__);
}
- $this->mAffectedRows[$stmt] = oci_num_rows($stmt);
- $this->mFetchCache[$stmt] = array();
- $this->mFetchID[$stmt] = 0;
- $this->mNcols[$stmt] = oci_num_fields($stmt);
- if ($this->mNcols[$stmt] == 0)
- return $this->mLastResult;
- for ($i = 1; $i <= $this->mNcols[$stmt]; $i++) {
- $this->mFieldNames[$stmt][$i] = oci_field_name($stmt, $i);
- $this->mFieldTypes[$stmt][$i] = oci_field_type($stmt, $i);
+
+ if (oci_execute($stmt, $this->execFlags()) == false) {
+ $e = oci_error($stmt);
+ $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__);
}
- while (($o = oci_fetch_array($stmt)) !== false) {
- foreach ($o as $key => $value) {
- if (is_object($value)) {
- $o[$key] = $value->load();
- }
- }
- $this->mFetchCache[$stmt][] = $o;
+ if (oci_statement_type($stmt) == "SELECT")
+ return new ORAResult($this, $stmt);
+ else {
+ $this->mAffectedRows = oci_num_rows($stmt);
+ return true;
}
- return $this->mLastResult;
}
- function queryIgnore( $sql, $fname = '' ) {
- return $this->query( $sql, $fname, true );
+ function queryIgnore($sql, $fname = '') {
+ return $this->query($sql, $fname, true);
}
- function freeResult( $res ) {
- if (!oci_free_statement($res)) {
- throw new DBUnexpectedError( $this, "Unable to free Oracle result\n" );
- }
- unset($this->mFetchID[$res]);
- unset($this->mFetchCache[$res]);
- unset($this->mNcols[$res]);
- unset($this->mFieldNames[$res]);
- unset($this->mFieldTypes[$res]);
+ function freeResult($res) {
+ $res->free();
}
- function fetchAssoc($res) {
- if ($this->mFetchID[$res] >= count($this->mFetchCache[$res]))
- return false;
-
- for ($i = 1; $i <= $this->mNcols[$res]; $i++) {
- $name = $this->mFieldNames[$res][$i];
- if (isset($this->mFetchCache[$res][$this->mFetchID[$res]][$name]))
- $value = $this->mFetchCache[$res][$this->mFetchID[$res]][$name];
- else $value = NULL;
- $key = strtolower($name);
- wfdebug("'$key' => '$value'\n");
- $ret[$key] = $value;
- }
- $this->mFetchID[$res]++;
- return $ret;
+ function fetchObject($res) {
+ return $res->fetchObject();
}
function fetchRow($res) {
- $r = $this->fetchAssoc($res);
- if (!$r)
- return false;
- $i = 0;
- $ret = array();
- foreach ($r as $value) {
- wfdebug("ret[$i]=[$value]\n");
- $ret[$i++] = $value;
- }
- return $ret;
+ return $res->fetchAssoc();
}
- function fetchObject($res) {
- $row = $this->fetchAssoc($res);
- if (!$row)
- return false;
- $ret = new stdClass;
- foreach ($row as $key => $value)
- $ret->$key = $value;
- return $ret;
+ function numRows($res) {
+ return $res->numRows();
}
- function numRows($res) {
- return count($this->mFetchCache[$res]);
+ function numFields($res) {
+ return $res->numFields();
+ }
+
+ function fieldName($stmt, $n) {
+ return pg_field_name($stmt, $n);
}
- function numFields( $res ) { return pg_num_fields( $res ); }
- function fieldName( $res, $n ) { return pg_field_name( $res, $n ); }
/**
* This must be called after nextSequenceVal
@@ -192,139 +250,153 @@ class DatabaseOracle extends Database {
}
function dataSeek($res, $row) {
- $this->mFetchID[$res] = $row;
+ $res->seek($row);
}
function lastError() {
- if ($this->mErr === false) {
- if ($this->mLastResult !== false) {
- $what = $this->mLastResult;
- } else if ($this->mConn !== false) {
- $what = $this->mConn;
- } else {
- $what = false;
- }
- $err = ($what !== false) ? oci_error($what) : oci_error();
- if ($err === false) {
- $this->mErr = 'no error';
- } else {
- $this->mErr = $err['message'];
- }
- }
- return str_replace("\n", ' ', $this->mErr);
+ if ($this->mConn === false)
+ $e = oci_error();
+ else
+ $e = oci_error($this->mConn);
+ return $e['message'];
}
+
function lastErrno() {
- return 0;
+ if ($this->mConn === false)
+ $e = oci_error();
+ else
+ $e = oci_error($this->mConn);
+ return $e['code'];
}
function affectedRows() {
- return $this->mAffectedRows[$this->mLastResult];
+ return $this->mAffectedRows;
}
/**
* Returns information about an index
* If errors are explicitly ignored, returns NULL on failure
*/
- function indexInfo ($table, $index, $fname = 'Database::indexInfo' ) {
- $table = $this->tableName($table, true);
- if ($index == 'PRIMARY')
- $index = "${table}_pk";
- $sql = "SELECT uniqueness FROM all_indexes WHERE table_name='" .
- $table . "' AND index_name='" .
- $this->strencode(strtoupper($index)) . "'";
- $res = $this->query($sql, $fname);
- if (!$res)
- return NULL;
- if (($row = $this->fetchObject($res)) == NULL)
- return false;
- $this->freeResult($res);
- $row->Non_unique = !$row->uniqueness;
- return $row;
-
- // BUG: !!!! This code needs to be synced up with database.php
-
+ function indexInfo( $table, $index, $fname = 'Database::indexExists' ) {
+ return false;
}
- function indexUnique ($table, $index, $fname = 'indexUnique') {
- if (!($i = $this->indexInfo($table, $index, $fname)))
- return $i;
- return $i->uniqueness == 'UNIQUE';
+ function indexUnique ($table, $index, $fname = 'Database::indexUnique' ) {
+ return false;
}
- function fieldInfo( $table, $field ) {
- $o = new stdClass;
- $o->multiple_key = true; /* XXX */
- return $o;
- }
+ function insert( $table, $a, $fname = 'Database::insert', $options = array() ) {
+ if (!is_array($options))
+ $options = array($options);
- function getColumnInformation($table, $field) {
- $table = $this->tableName($table, true);
- $field = strtoupper($field);
+ #if (in_array('IGNORE', $options))
+ # $oldIgnore = $this->ignoreErrors(true);
- $res = $this->doQuery("SELECT * FROM all_tab_columns " .
- "WHERE table_name='".$table."' " .
- "AND column_name='".$field."'");
- if (!$res)
- return false;
- $o = $this->fetchObject($res);
- $this->freeResult($res);
- return $o;
- }
+ # IGNORE is performed using single-row inserts, ignoring errors in each
+ # FIXME: need some way to distiguish between key collision and other types of error
+ //$oldIgnore = $this->ignoreErrors(true);
+ if (!is_array(reset($a))) {
+ $a = array($a);
+ }
+ foreach ($a as $row) {
+ $this->insertOneRow($table, $row, $fname);
+ }
+ //$this->ignoreErrors($oldIgnore);
+ $retVal = true;
- function fieldExists( $table, $field, $fname = 'Database::fieldExists' ) {
- $column = $this->getColumnInformation($table, $field);
- if (!$column)
- return false;
- return true;
+ //if (in_array('IGNORE', $options))
+ // $this->ignoreErrors($oldIgnore);
+
+ return $retVal;
}
- function tableName($name, $forddl = false) {
- # First run any transformations from the parent object
- $name = parent::tableName( $name );
+ function insertOneRow($table, $row, $fname) {
+ // "INSERT INTO tables (a, b, c)"
+ $sql = "INSERT INTO " . $this->tableName($table) . " (" . join(',', array_keys($row)) . ')';
+ $sql .= " VALUES (";
+
+ // for each value, append ":key"
+ $first = true;
+ $returning = '';
+ foreach ($row as $col => $val) {
+ if (is_object($val)) {
+ $what = "EMPTY_BLOB()";
+ assert($returning === '');
+ $returning = " RETURNING $col INTO :bval";
+ $blobcol = $col;
+ } else
+ $what = ":$col";
+
+ if ($first)
+ $sql .= "$what";
+ else
+ $sql.= ", $what";
+ $first = false;
+ }
+ $sql .= ") $returning";
+
+ $stmt = oci_parse($this->mConn, $sql);
+ foreach ($row as $col => $val) {
+ if (!is_object($val)) {
+ if (oci_bind_by_name($stmt, ":$col", $row[$col]) === false)
+ $this->reportQueryError($this->lastErrno(), $this->lastError(), $sql, __METHOD__);
+ }
+ }
+
+ if (($bval = oci_new_descriptor($this->mConn, OCI_D_LOB)) === false) {
+ $e = oci_error($stmt);
+ throw new DBUnexpectedError($this, "Cannot create LOB descriptor: " . $e['message']);
+ }
+
+ if (strlen($returning))
+ oci_bind_by_name($stmt, ":bval", $bval, -1, SQLT_BLOB);
- # Replace backticks into empty
- # Note: "foo" and foo are not the same in Oracle!
- $name = str_replace('`', '', $name);
+ if (oci_execute($stmt, OCI_DEFAULT) === false) {
+ $e = oci_error($stmt);
+ $this->reportQueryError($e['message'], $e['code'], $sql, __METHOD__);
+ }
+ if (strlen($returning)) {
+ $bval->save($row[$blobcol]->getData());
+ $bval->free();
+ }
+ if (!$this->mTrxLevel)
+ oci_commit($this->mConn);
- # Now quote Oracle reserved keywords
+ oci_free_statement($stmt);
+ }
+
+ function tableName( $name ) {
+ # Replace reserved words with better ones
switch( $name ) {
case 'user':
- case 'group':
- case 'validate':
- if ($forddl)
- return $name;
- else
- return '"' . $name . '"';
-
+ return 'mwuser';
+ case 'text':
+ return 'pagecontent';
default:
- return strtoupper($name);
+ return $name;
}
}
- function strencode( $s ) {
- return str_replace("'", "''", $s);
- }
-
/**
* Return the next in a sequence, save the value for retrieval via insertId()
*/
- function nextSequenceValue( $seqName ) {
- $r = $this->doQuery("SELECT $seqName.nextval AS val FROM dual");
- $o = $this->fetchObject($r);
- $this->freeResult($r);
- return $this->mInsertId = (int)$o->val;
+ function nextSequenceValue($seqName) {
+ $res = $this->query("SELECT $seqName.nextval FROM dual");
+ $row = $this->fetchRow($res);
+ $this->mInsertId = $row[0];
+ $this->freeResult($res);
+ return $this->mInsertId;
}
/**
- * USE INDEX clause
- * PostgreSQL doesn't have them and returns ""
+ * Oracle does not have a "USE INDEX" clause, so return an empty string
*/
- function useIndexClause( $index ) {
+ function useIndexClause($index) {
return '';
}
# REPLACE query wrapper
- # PostgreSQL simulates this with a DELETE followed by INSERT
+ # Oracle simulates this with a DELETE followed by INSERT
# $row is the row to insert, an associative array
# $uniqueIndexes is an array of indexes. Each element may be either a
# field name or an array of field names
@@ -333,15 +405,15 @@ class DatabaseOracle extends Database {
# However if you do this, you run the risk of encountering errors which wouldn't have
# occurred in MySQL
function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) {
- $table = $this->tableName( $table );
+ $table = $this->tableName($table);
if (count($rows)==0) {
return;
}
# Single row case
- if ( !is_array( reset( $rows ) ) ) {
- $rows = array( $rows );
+ if (!is_array(reset($rows))) {
+ $rows = array($rows);
}
foreach( $rows as $row ) {
@@ -377,14 +449,14 @@ class DatabaseOracle extends Database {
# Now insert the row
$sql = "INSERT INTO $table (" . $this->makeList( array_keys( $row ), LIST_NAMES ) .') VALUES (' .
$this->makeList( $row, LIST_COMMA ) . ')';
- $this->query( $sql, $fname );
+ $this->query($sql, $fname);
}
}
# DELETE where the condition is a join
function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) {
if ( !$conds ) {
- throw new DBUnexpectedError( $this, 'Database::deleteJoin() called with empty $conds' );
+ throw new DBUnexpectedError($this, 'Database::deleteJoin() called with empty $conds' );
}
$delTable = $this->tableName( $delTable );
@@ -421,17 +493,14 @@ class DatabaseOracle extends Database {
}
function limitResult($sql, $limit, $offset) {
- $ret = "SELECT * FROM ($sql) WHERE ROWNUM < " . ((int)$limit + (int)($offset+1));
- if (is_numeric($offset))
- $ret .= " AND ROWNUM >= " . (int)$offset;
- return $ret;
- }
- function limitResultForUpdate($sql, $limit) {
- return $sql;
+ if ($offset === false)
+ $offset = 0;
+ return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < 1 + $limit + $offset";
}
+
/**
* Returns an SQL expression for a simple conditional.
- * Uses CASE on PostgreSQL.
+ * Uses CASE on Oracle
*
* @param string $cond SQL expression which will result in a boolean value
* @param string $trueVal SQL expression to return if true
@@ -442,15 +511,12 @@ class DatabaseOracle extends Database {
return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
}
- # FIXME: actually detecting deadlocks might be nice
function wasDeadlock() {
- return false;
+ return $this->lastErrno() == 'OCI-00060';
}
- # Return DB-style timestamp used for MySQL schema
function timestamp($ts = 0) {
- return $this->strencode(wfTimestamp(TS_ORACLE, $ts));
-# return "TO_TIMESTAMP('" . $this->strencode(wfTimestamp(TS_DB, $ts)) . "', 'RRRR-MM-DD HH24:MI:SS')";
+ return wfTimestamp(TS_ORACLE, $ts);
}
/**
@@ -460,13 +526,25 @@ class DatabaseOracle extends Database {
return $valuedata;
}
+ function reportQueryError($error, $errno, $sql, $fname, $tempIgnore = false) {
+ # Ignore errors during error handling to avoid infinite
+ # recursion
+ $ignore = $this->ignoreErrors(true);
+ ++$this->mErrorCount;
- function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
- $message = "A database error has occurred\n" .
- "Query: $sql\n" .
- "Function: $fname\n" .
- "Error: $errno $error\n";
- throw new DBUnexpectedError($this, $message);
+ if ($ignore || $tempIgnore) {
+echo "error ignored! query = [$sql]\n";
+ wfDebug("SQL ERROR (ignored): $error\n");
+ $this->ignoreErrors( $ignore );
+ }
+ else {
+echo "error!\n";
+ $message = "A database error has occurred\n" .
+ "Query: $sql\n" .
+ "Function: $fname\n" .
+ "Error: $errno $error\n";
+ throw new DBUnexpectedError($this, $message);
+ }
}
/**
@@ -483,209 +561,125 @@ class DatabaseOracle extends Database {
return oci_server_version($this->mConn);
}
- function setSchema($schema=false) {
- $schemas=$this->mSchemas;
- if ($schema) { array_unshift($schemas,$schema); }
- $searchpath=$this->makeList($schemas,LIST_NAMES);
- $this->query("SET search_path = $searchpath");
+ /**
+ * Query whether a given table exists (in the given schema, or the default mw one if not given)
+ */
+ function tableExists($table) {
+ $etable= $this->addQuotes($table);
+ $SQL = "SELECT 1 FROM user_tables WHERE table_name='$etable'";
+ $res = $this->query($SQL);
+ $count = $res ? oci_num_rows($res) : 0;
+ if ($res)
+ $this->freeResult($res);
+ return $count;
}
- function begin() {
+ /**
+ * Query whether a given column exists in the mediawiki schema
+ */
+ function fieldExists( $table, $field ) {
+ return true; // XXX
}
- function immediateCommit( $fname = 'Database::immediateCommit' ) {
- oci_commit($this->mConn);
- $this->mTrxLevel = 0;
+ function fieldInfo( $table, $field ) {
+ return false; // XXX
}
- function rollback( $fname = 'Database::rollback' ) {
- oci_rollback($this->mConn);
- $this->mTrxLevel = 0;
+
+ function begin( $fname = '' ) {
+ $this->mTrxLevel = 1;
}
- function getLag() {
- return false;
+ function immediateCommit( $fname = '' ) {
+ return true;
}
- function getStatus($which=null) {
- $result = array('Threads_running' => 0, 'Threads_connected' => 0);
- return $result;
+ function commit( $fname = '' ) {
+ oci_commit($this->mConn);
+ $this->mTrxLevel = 0;
}
- /**
- * Returns an optional USE INDEX clause to go after the table, and a
- * string to go at the end of the query
- *
- * @access private
- *
- * @param array $options an associative array of options to be turned into
- * an SQL query, valid keys are listed in the function.
- * @return array
- */
- function makeSelectOptions($options) {
- $tailOpts = '';
-
- if (isset( $options['ORDER BY'])) {
- $tailOpts .= " ORDER BY {$options['ORDER BY']}";
- }
+ /* Not even sure why this is used in the main codebase... */
+ function limitResultForUpdate($sql, $num) {
+ return $sql;
+ }
- return array('', $tailOpts);
+ function strencode($s) {
+ return str_replace("'", "''", $s);
}
- function maxListLen() {
- return 1000;
+ function encodeBlob($b) {
+ return new ORABlob($b);
+ }
+ function decodeBlob($b) {
+ return $b; //return $b->load();
}
- /**
- * Query whether a given table exists
- */
- function tableExists( $table ) {
- $table = $this->tableName($table, true);
- $res = $this->query( "SELECT COUNT(*) as NUM FROM user_tables WHERE table_name='"
- . $table . "'" );
- if (!$res)
- return false;
- $row = $this->fetchObject($res);
- $this->freeResult($res);
- return $row->num >= 1;
+ function addQuotes( $s ) {
+ global $wgLang;
+ $s = $wgLang->checkTitleEncoding($s);
+ return "'" . $this->strencode($s) . "'";
}
- /**
- * UPDATE wrapper, takes a condition array and a SET array
- */
- function update( $table, $values, $conds, $fname = 'Database::update' ) {
- $table = $this->tableName( $table );
+ function quote_ident( $s ) {
+ return $s;
+ }
- $sql = "UPDATE $table SET ";
- $first = true;
- foreach ($values as $field => $v) {
- if ($first)
- $first = false;
- else
- $sql .= ", ";
- $sql .= "$field = :n$field ";
- }
- if ( $conds != '*' ) {
- $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
- }
- $stmt = $this->parseStatement($sql);
- if ($stmt === false) {
- $this->reportQueryError( $this->lastError(), $this->lastErrno(), $stmt );
- return false;
- }
- if ($this->debug())
- wfDebug("SQL: $sql\n");
- $s = '';
- foreach ($values as $field => $v) {
- oci_bind_by_name($stmt, ":n$field", $values[$field]);
- if ($this->debug())
- $s .= " [$field] = [$v]\n";
- }
- if ($this->debug())
- wfdebug(" PH: $s\n");
- $ret = $this->executeStatement($stmt);
- return $ret;
+ /* For now, does nothing */
+ function selectDB( $db ) {
+ return true;
}
/**
- * INSERT wrapper, inserts an array into a table
+ * Returns an optional USE INDEX clause to go after the table, and a
+ * string to go at the end of the query
*
- * $a may be a single associative array, or an array of these with numeric keys, for
- * multi-row insert.
+ * @private
*
- * Usually aborts on failure
- * If errors are explicitly ignored, returns success
+ * @param array $options an associative array of options to be turned into
+ * an SQL query, valid keys are listed in the function.
+ * @return array
*/
- function insert( $table, $a, $fname = 'Database::insert', $options = array() ) {
- # No rows to insert, easy just return now
- if ( !count( $a ) ) {
- return true;
- }
-
- $table = $this->tableName( $table );
- if (!is_array($options))
- $options = array($options);
-
- $oldIgnore = false;
- if (in_array('IGNORE', $options))
- $oldIgnore = $this->ignoreErrors( true );
-
- if ( isset( $a[0] ) && is_array( $a[0] ) ) {
- $multi = true;
- $keys = array_keys( $a[0] );
- } else {
- $multi = false;
- $keys = array_keys( $a );
+ function makeSelectOptions( $options ) {
+ $preLimitTail = $postLimitTail = '';
+ $startOpts = '';
+
+ $noKeyOptions = array();
+ foreach ( $options as $key => $option ) {
+ if ( is_numeric( $key ) ) {
+ $noKeyOptions[$option] = true;
+ }
}
- $sql = "INSERT INTO $table (" . implode( ',', $keys ) . ') VALUES (';
- $return = '';
- $first = true;
- foreach ($a as $key => $value) {
- if ($first)
- $first = false;
- else
- $sql .= ", ";
- if (is_object($value) && $value->isLOB()) {
- $sql .= "EMPTY_BLOB()";
- $return = "RETURNING $key INTO :bobj";
- } else
- $sql .= ":$key";
+ if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY {$options['GROUP BY']}";
+ if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY {$options['ORDER BY']}";
+
+ if (isset($options['LIMIT'])) {
+ // $tailOpts .= $this->limitResult('', $options['LIMIT'],
+ // isset($options['OFFSET']) ? $options['OFFSET']
+ // : false);
}
- $sql .= ") $return";
- if ($this->debug()) {
- wfDebug("SQL: $sql\n");
- }
+ #if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $tailOpts .= ' FOR UPDATE';
+ #if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $tailOpts .= ' LOCK IN SHARE MODE';
+ if ( isset( $noKeyOptions['DISTINCT'] ) && isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT';
- if (($stmt = $this->parseStatement($sql)) === false) {
- $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname);
- $this->ignoreErrors($oldIgnore);
- return false;
+ if ( isset( $options['USE INDEX'] ) && ! is_array( $options['USE INDEX'] ) ) {
+ $useIndex = $this->useIndexClause( $options['USE INDEX'] );
+ } else {
+ $useIndex = '';
}
+
+ return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
+ }
- /*
- * If we're inserting multiple rows, parse the statement once and
- * execute it for each set of values. Otherwise, convert it into an
- * array and pretend.
- */
- if (!$multi)
- $a = array($a);
-
- foreach ($a as $key => $row) {
- $blob = false;
- $bdata = false;
- $s = '';
- foreach ($row as $k => $value) {
- if (is_object($value) && $value->isLOB()) {
- $blob = oci_new_descriptor($this->mConn, OCI_D_LOB);
- $bdata = $value->data();
- oci_bind_by_name($stmt, ":bobj", $blob, -1, OCI_B_BLOB);
- } else
- oci_bind_by_name($stmt, ":$k", $a[$key][$k], -1);
- if ($this->debug())
- $s .= " [$k] = {$row[$k]}";
- }
- if ($this->debug())
- wfDebug(" PH: $s\n");
- if (($s = $this->executeStatement($stmt)) === false) {
- $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname);
- $this->ignoreErrors($oldIgnore);
- return false;
- }
-
- if ($blob) {
- $blob->save($bdata);
- }
- }
- $this->ignoreErrors($oldIgnore);
- return $this->mLastResult = $s;
+ public function setTimeout( $timeout ) {
+ // @todo fixme no-op
}
function ping() {
+ wfDebug( "Function ping() not written for DatabasePostgres.php yet");
return true;
}
- function encodeBlob($b) {
- return new OracleBlob($b);
- }
-}
+
+} // end DatabaseOracle class
?>
diff --git a/includes/DatabasePostgres.php b/includes/DatabasePostgres.php
index 803c0e26..7158e2d1 100644
--- a/includes/DatabasePostgres.php
+++ b/includes/DatabasePostgres.php
@@ -7,12 +7,69 @@
* than MySQL ones, some of them should be moved to parent
* Database class.
*
- * @package MediaWiki
+ * @addtogroup Database
*/
+class PostgresField {
+ private $name, $tablename, $type, $nullable, $max_length;
+
+ static function fromText($db, $table, $field) {
+ global $wgDBmwschema;
+
+ $q = <<query(sprintf($q,
+ $db->addQuotes($wgDBmwschema),
+ $db->addQuotes($table),
+ $db->addQuotes($field)));
+ $row = $db->fetchObject($res);
+ if (!$row)
+ return null;
+ $n = new PostgresField;
+ $n->type = $row->typname;
+ $n->nullable = ($row->attnotnull == 'f');
+ $n->name = $field;
+ $n->tablename = $table;
+ $n->max_length = $row->attlen;
+ return $n;
+ }
+
+ function name() {
+ return $this->name;
+ }
+
+ function tableName() {
+ return $this->tablename;
+ }
+
+ function type() {
+ return $this->type;
+ }
+
+ function nullable() {
+ return $this->nullable;
+ }
+ function maxLength() {
+ return $this->max_length;
+ }
+}
+
+/**
+ * @addtogroup Database
+ */
class DatabasePostgres extends Database {
var $mInsertId = NULL;
var $mLastResult = NULL;
+ var $numeric_version = NULL;
function DatabasePostgres($server = false, $user = false, $password = false, $dbName = false,
$failFunction = false, $flags = 0 )
@@ -25,24 +82,31 @@ class DatabasePostgres extends Database {
}
$this->mOut =& $wgOut;
$this->mFailFunction = $failFunction;
- $this->mCascadingDeletes = true;
- $this->mCleanupTriggers = true;
- $this->mStrictIPs = true;
$this->mFlags = $flags;
$this->open( $server, $user, $password, $dbName);
}
+ function cascadingDeletes() {
+ return true;
+ }
+ function cleanupTriggers() {
+ return true;
+ }
+ function strictIPs() {
+ return true;
+ }
function realTimestamps() {
return true;
}
-
function implicitGroupby() {
return false;
}
+ function searchableIPs() {
+ return true;
+ }
- static function newFromParams( $server = false, $user = false, $password = false, $dbName = false,
- $failFunction = false, $flags = 0)
+ static function newFromParams( $server, $user, $password, $dbName, $failFunction = false, $flags = 0)
{
return new DatabasePostgres( $server, $user, $password, $dbName, $failFunction, $flags );
}
@@ -57,9 +121,12 @@ class DatabasePostgres extends Database {
throw new DBConnectionError( $this, "Postgres functions missing, have you compiled PHP with the --with-pgsql option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" );
}
-
global $wgDBport;
+ if (!strlen($user)) { ## e.g. the class is being loaded
+ return;
+ }
+
$this->close();
$this->mServer = $server;
$port = $wgDBport;
@@ -75,9 +142,6 @@ class DatabasePostgres extends Database {
$hstring .= "port=$port ";
}
- if (!strlen($user)) { ## e.g. the class is being loaded
- return;
- }
error_reporting( E_ALL );
@$this->mConn = pg_connect("$hstring dbname=$dbName user=$user password=$password");
@@ -94,21 +158,15 @@ class DatabasePostgres extends Database {
if (defined('MEDIAWIKI_INSTALL')) {
global $wgDBname, $wgDBuser, $wgDBpassword, $wgDBsuperuser, $wgDBmwschema,
$wgDBts2schema;
- print "OK\n";
print "
Checking the version of Postgres...";
- $version = pg_fetch_result($this->doQuery("SELECT version()"),0,0);
- $thisver = array();
- if (!preg_match('/PostgreSQL (\d+\.\d+)(\S+)/', $version, $thisver)) {
- print "FAILED (could not determine the version)
\n";
- dieout("");
- }
+ $version = $this->getServerVersion();
$PGMINVER = "8.1";
- if ($thisver[1] < $PGMINVER) {
- print "FAILED. Required version is $PGMINVER. You have $thisver[1]$thisver[2]\n";
+ if ($this->numeric_version < $PGMINVER) {
+ print "FAILED. Required version is $PGMINVER. You have $this->numeric_version ($version)\n";
dieout("");
}
- print "version $thisver[1]$thisver[2] is OK.\n";
+ print "version $this->numeric_version is OK.\n";
$safeuser = $this->quote_ident($wgDBuser);
## Are we connecting as a superuser for the first time?
@@ -232,7 +290,8 @@ class DatabasePostgres extends Database {
$wgDBsuperuser = '';
return true; ## Reconnect as regular user
- }
+
+ } ## end superuser
if (!defined('POSTGRES_SEARCHPATH')) {
@@ -249,13 +308,24 @@ class DatabasePostgres extends Database {
## Does this user have the rights to the tsearch2 tables?
$ctype = pg_fetch_result($this->doQuery("SHOW lc_ctype"),0,0);
print "
Checking tsearch2 permissions...";
+ ## Let's check all four, just to be safe
+ error_reporting( 0 );
+ $ts2tables = array('cfg','cfgmap','dict','parser');
+ foreach ( $ts2tables AS $tname ) {
+ $SQL = "SELECT count(*) FROM $wgDBts2schema.pg_ts_$tname";
+ $res = $this->doQuery($SQL);
+ if (!$res) {
+ print "FAILED to access pg_ts_$tname. Make sure that the user ".
+ "\"$wgDBuser\" has SELECT access to all four tsearch2 tables
\n";
+ dieout("");
+ }
+ }
$SQL = "SELECT ts_name FROM $wgDBts2schema.pg_ts_cfg WHERE locale = '$ctype'";
$SQL .= " ORDER BY CASE WHEN ts_name <> 'default' THEN 1 ELSE 0 END";
- error_reporting( 0 );
$res = $this->doQuery($SQL);
error_reporting( E_ALL );
if (!$res) {
- print "FAILED. Make sure that the user \"$wgDBuser\" has SELECT access to the tsearch2 tables\n";
+ print "FAILED. Could not determine the tsearch2 locale information\n";
dieout("");
}
print "OK";
@@ -282,7 +352,7 @@ class DatabasePostgres extends Database {
$res = $this->doQuery($SQL);
if (!$res) {
print "FAILED. ";
- print "Please make sure that the locale in pg_ts_cfg for \"default\" is set to \"ctype\"\n";
+ print "Please make sure that the locale in pg_ts_cfg for \"default\" is set to \"$ctype\"\n";
dieout("");
}
print "OK";
@@ -325,9 +395,13 @@ class DatabasePostgres extends Database {
$result = $this->schemaExists($wgDBmwschema);
if (!$result) {
print "
\n";
+ print "FAILED. The user \"$wgDBuser\" must be able to access the schema. ".
+ "You can try making them the owner of the database, or try creating the schema with a ".
+ "different user, and then grant access to the \"$wgDBuser\" user.\n";
dieout("");
}
print "OK\n";
@@ -339,6 +413,39 @@ class DatabasePostgres extends Database {
print "
Schema \"$wgDBmwschema\" exists and is owned by \"$user\". Excellent.
\n";
}
+ ## Always return GMT time to accomodate the existing integer-based timestamp assumption
+ print "
Setting the timezone to GMT for user \"$user\" ...";
+ $SQL = "ALTER USER $safeuser SET timezone = 'GMT'";
+ $result = pg_query($this->mConn, $SQL);
+ if (!$result) {
+ print "FAILED.
\n";
+ dieout("");
+ }
+ print "OK\n";
+ ## Set for the rest of this session
+ $SQL = "SET timezone = 'GMT'";
+ $result = pg_query($this->mConn, $SQL);
+ if (!$result) {
+ print "
Failed to set timezone
\n";
+ dieout("");
+ }
+
+ print "
Setting the datestyle to ISO, YMD for user \"$user\" ...";
+ $SQL = "ALTER USER $safeuser SET datestyle = 'ISO, YMD'";
+ $result = pg_query($this->mConn, $SQL);
+ if (!$result) {
+ print "FAILED.
\n";
+ dieout("");
+ }
+ print "OK\n";
+ ## Set for the rest of this session
+ $SQL = "SET datestyle = 'ISO, YMD'";
+ $result = pg_query($this->mConn, $SQL);
+ if (!$result) {
+ print "
Failed to set datestyle
\n";
+ dieout("");
+ }
+
## Fix up the search paths if needed
print "
Setting the search path for user \"$user\" ...";
$path = $this->quote_ident($wgDBmwschema);
@@ -454,6 +561,30 @@ class DatabasePostgres extends Database {
return pg_affected_rows( $this->mLastResult );
}
+ /**
+ * Estimate rows in dataset
+ * Returns estimated count, based on EXPLAIN output
+ * This is not necessarily an accurate estimate, so use sparingly
+ * Returns -1 if count cannot be found
+ * Takes same arguments as Database::select()
+ */
+
+ function estimateRowCount( $table, $vars='*', $conds='', $fname = 'Database::estimateRowCount', $options = array() ) {
+ $options['EXPLAIN'] = true;
+ $res = $this->select( $table, $vars, $conds, $fname, $options );
+ $rows = -1;
+ if ( $res ) {
+ $row = $this->fetchRow( $res );
+ $count = array();
+ if( preg_match( '/rows=(\d+)/', $row[0], $count ) ) {
+ $rows = $count[1];
+ }
+ $this->freeResult($res);
+ }
+ return $rows;
+ }
+
+
/**
* Returns information about an index
* If errors are explicitly ignored, returns NULL on failure
@@ -645,7 +776,7 @@ class DatabasePostgres extends Database {
return '';
}
- function limitResult($sql, $limit,$offset) {
+ function limitResult($sql, $limit,$offset=false) {
return "$sql LIMIT $limit ".(is_numeric($offset)?" OFFSET {$offset} ":"");
}
@@ -707,26 +838,31 @@ class DatabasePostgres extends Database {
* @return string Version information from the database
*/
function getServerVersion() {
- $res = $this->query( "SELECT version()" );
- $row = $this->fetchRow( $res );
- $version = $row[0];
- $this->freeResult( $res );
+ $version = pg_fetch_result($this->doQuery("SELECT version()"),0,0);
+ $thisver = array();
+ if (!preg_match('/PostgreSQL (\d+\.\d+)(\S+)/', $version, $thisver)) {
+ die("Could not determine the numeric version from $version!");
+ }
+ $this->numeric_version = $thisver[1];
return $version;
}
/**
- * Query whether a given table exists (in the given schema, or the default mw one if not given)
+ * Query whether a given relation exists (in the given schema, or the
+ * default mw one if not given)
*/
- function tableExists( $table, $schema = false ) {
+ function relationExists( $table, $types, $schema = false ) {
global $wgDBmwschema;
+ if (!is_array($types))
+ $types = array($types);
if (! $schema )
$schema = $wgDBmwschema;
- $etable = preg_replace("/'/", "''", $table);
- $eschema = preg_replace("/'/", "''", $schema);
+ $etable = $this->addQuotes($table);
+ $eschema = $this->addQuotes($schema);
$SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
- . "WHERE c.relnamespace = n.oid AND c.relname = '$etable' AND n.nspname = '$eschema' "
- . "AND c.relkind IN ('r','v')";
+ . "WHERE c.relnamespace = n.oid AND c.relname = $etable AND n.nspname = $eschema "
+ . "AND c.relkind IN ('" . implode("','", $types) . "')";
$res = $this->query( $SQL );
$count = $res ? pg_num_rows($res) : 0;
if ($res)
@@ -734,6 +870,61 @@ class DatabasePostgres extends Database {
return $count;
}
+ /*
+ * For backward compatibility, this function checks both tables and
+ * views.
+ */
+ function tableExists ($table, $schema = false) {
+ return $this->relationExists($table, array('r', 'v'), $schema);
+ }
+
+ function sequenceExists ($sequence, $schema = false) {
+ return $this->relationExists($sequence, 'S', $schema);
+ }
+
+ function triggerExists($table, $trigger) {
+ global $wgDBmwschema;
+
+ $q = <<query(sprintf($q,
+ $this->addQuotes($wgDBmwschema),
+ $this->addQuotes($table),
+ $this->addQuotes($trigger)));
+ if (!$res)
+ return NULL;
+ $rows = pg_num_rows($res);
+ $this->freeResult($res);
+ return $rows;
+ }
+
+ function ruleExists($table, $rule) {
+ global $wgDBmwschema;
+ $exists = $this->selectField("pg_rules", "rulename",
+ array( "rulename" => $rule,
+ "tablename" => $table,
+ "schemaname" => $wgDBmwschema));
+ return $exists === $rule;
+ }
+
+ function constraintExists($table, $constraint) {
+ global $wgDBmwschema;
+ $SQL = sprintf("SELECT 1 FROM information_schema.table_constraints ".
+ "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
+ $this->addQuotes($wgDBmwschema),
+ $this->addQuotes($table),
+ $this->addQuotes($constraint));
+ $res = $this->query($SQL);
+ if (!$res)
+ return NULL;
+ $rows = pg_num_rows($res);
+ $this->freeResult($res);
+ return $rows;
+ }
/**
* Query whether a given schema exists. Returns the name of the owner
@@ -752,7 +943,7 @@ class DatabasePostgres extends Database {
/**
* Query whether a given column exists in the mediawiki schema
*/
- function fieldExists( $table, $field ) {
+ function fieldExists( $table, $field, $fname = 'DatabasePostgres::fieldExists' ) {
global $wgDBmwschema;
$etable = preg_replace("/'/", "''", $table);
$eschema = preg_replace("/'/", "''", $wgDBmwschema);
@@ -760,7 +951,7 @@ class DatabasePostgres extends Database {
$SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n, pg_catalog.pg_attribute a "
. "WHERE c.relnamespace = n.oid AND c.relname = '$etable' AND n.nspname = '$eschema' "
. "AND a.attrelid = c.oid AND a.attname = '$ecol'";
- $res = $this->query( $SQL );
+ $res = $this->query( $SQL, $fname );
$count = $res ? pg_num_rows($res) : 0;
if ($res)
$this->freeResult( $res );
@@ -768,12 +959,10 @@ class DatabasePostgres extends Database {
}
function fieldInfo( $table, $field ) {
- $res = $this->query( "SELECT $field FROM $table LIMIT 1" );
- $type = pg_field_type( $res, 0 );
- return $type;
+ return PostgresField::fromText($this, $table, $field);
}
- function begin( $fname = 'DatabasePostgrs::begin' ) {
+ function begin( $fname = 'DatabasePostgres::begin' ) {
$this->query( 'BEGIN', $fname );
$this->mTrxLevel = 1;
}
@@ -791,10 +980,36 @@ class DatabasePostgres extends Database {
}
function setup_database() {
- global $wgVersion, $wgDBmwschema, $wgDBts2schema, $wgDBport;
+ global $wgVersion, $wgDBmwschema, $wgDBts2schema, $wgDBport, $wgDBuser;
+
+ ## Make sure that we can write to the correct schema
+ ## If not, Postgres will happily and silently go to the next search_path item
+ $ctest = "mw_test_table";
+ if ($this->tableExists($ctest, $wgDBmwschema)) {
+ $this->doQuery("DROP TABLE $wgDBmwschema.$ctest");
+ }
+ $SQL = "CREATE TABLE $wgDBmwschema.$ctest(a int)";
+ error_reporting( 0 );
+ $res = $this->doQuery($SQL);
+ error_reporting( E_ALL );
+ if (!$res) {
+ print "FAILED. Make sure that the user \"$wgDBuser\" can write to the schema \"$wgDBmwschema\"
\n";
+ dieout("");
+ }
+ $this->doQuery("DROP TABLE $wgDBmwschema.mw_test_table");
dbsource( "../maintenance/postgres/tables.sql", $this);
+ ## Version-specific stuff
+ if ($this->numeric_version == 8.1) {
+ $this->doQuery("CREATE INDEX ts2_page_text ON pagecontent USING gist(textvector)");
+ $this->doQuery("CREATE INDEX ts2_page_title ON page USING gist(titlevector)");
+ }
+ else {
+ $this->doQuery("CREATE INDEX ts2_page_text ON pagecontent USING gin(textvector)");
+ $this->doQuery("CREATE INDEX ts2_page_title ON page USING gin(titlevector)");
+ }
+
## Update version information
$mwv = $this->addQuotes($wgVersion);
$pgv = $this->addQuotes($this->getServerVersion());
@@ -827,6 +1042,8 @@ class DatabasePostgres extends Database {
$this->query("$SQL $matches[1],$matches[2])");
}
print " (table interwiki successfully populated)...\n";
+
+ $this->doQuery("COMMIT");
}
function encodeBlob($b) {
@@ -870,7 +1087,7 @@ class DatabasePostgres extends Database {
* @return array
*/
function makeSelectOptions( $options ) {
- $tailOpts = '';
+ $preLimitTail = $postLimitTail = '';
$startOpts = '';
$noKeyOptions = array();
@@ -880,16 +1097,17 @@ class DatabasePostgres extends Database {
}
}
- if ( isset( $options['GROUP BY'] ) ) $tailOpts .= " GROUP BY {$options['GROUP BY']}";
- if ( isset( $options['ORDER BY'] ) ) $tailOpts .= " ORDER BY {$options['ORDER BY']}";
+ if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY " . $options['GROUP BY'];
+ if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY " . $options['ORDER BY'];
- if (isset($options['LIMIT'])) {
- $tailOpts .= $this->limitResult('', $options['LIMIT'],
- isset($options['OFFSET']) ? $options['OFFSET'] : false);
- }
-
- if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $tailOpts .= ' FOR UPDATE';
- if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $tailOpts .= ' LOCK IN SHARE MODE';
+ //if (isset($options['LIMIT'])) {
+ // $tailOpts .= $this->limitResult('', $options['LIMIT'],
+ // isset($options['OFFSET']) ? $options['OFFSET']
+ // : false);
+ //}
+
+ if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $postLimitTail .= ' FOR UPDATE';
+ if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $postLimitTail .= ' LOCK IN SHARE MODE';
if ( isset( $noKeyOptions['DISTINCT'] ) && isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT';
if ( isset( $options['USE INDEX'] ) && ! is_array( $options['USE INDEX'] ) ) {
@@ -898,7 +1116,11 @@ class DatabasePostgres extends Database {
$useIndex = '';
}
- return array( $startOpts, $useIndex, $tailOpts );
+ return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
+ }
+
+ public function setTimeout( $timeout ) {
+ // @todo fixme no-op
}
function ping() {
diff --git a/includes/DateFormatter.php b/includes/DateFormatter.php
index c795618a..88a64453 100644
--- a/includes/DateFormatter.php
+++ b/includes/DateFormatter.php
@@ -1,15 +1,9 @@
Causes problems with HTML escaping, don't use
* % Enabled by default, minor problems with path to query rewrite rules, see below
* + Enabled by default, but doesn't work with path to query rewrite rules, corrupted by apache
* ? Enabled by default, but doesn't work with path to PATH_INFO rewrites
@@ -307,8 +306,8 @@ $wgVerifyMimeType= true;
/** Sets the mime type definition file to use by MimeMagic.php.
* @global string $wgMimeTypeFile
*/
-#$wgMimeTypeFile= "/etc/mime.types";
$wgMimeTypeFile= "includes/mime.types";
+#$wgMimeTypeFile= "/etc/mime.types";
#$wgMimeTypeFile= NULL; #use built-in defaults only.
/** Sets the mime type info file to use by MimeMagic.php.
@@ -372,7 +371,11 @@ $wgSharedUploadDBprefix = '';
$wgCacheSharedUploads = true;
/** Allow for upload to be copied from an URL. Requires Special:Upload?source=web */
$wgAllowCopyUploads = false;
-/** Max size for uploads, in bytes */
+/**
+ * Max size for uploads, in bytes. Currently only works for uploads from URL
+ * via CURL (see $wgAllowCopyUploads). The only way to impose limits on
+ * normal uploads is currently to edit php.ini.
+ */
$wgMaxUploadSize = 1024*1024*100; # 100MB
/**
@@ -502,8 +505,12 @@ $wgDBtype = "mysql";
$wgSearchType = null;
/** Table name prefix */
$wgDBprefix = '';
+/** MySQL table options to use during installation or update */
+$wgDBTableOptions = 'TYPE=InnoDB';
+
/**#@-*/
+
/** Live high performance sites should disable this - some checks acquire giant mysql locks */
$wgCheckDBSchema = true;
@@ -964,6 +971,7 @@ $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;
@@ -977,6 +985,7 @@ $wgGroupPermissions['emailconfirmed']['emailconfirmed'] = true;
$wgGroupPermissions['bot' ]['bot'] = true;
$wgGroupPermissions['bot' ]['autoconfirmed'] = true;
$wgGroupPermissions['bot' ]['nominornewtalk'] = true;
+$wgGroupPermissions['bot' ]['autopatrol'] = true;
// Most extra permission abilities go to this group
$wgGroupPermissions['sysop']['block'] = true;
@@ -988,7 +997,7 @@ $wgGroupPermissions['sysop']['import'] = true;
$wgGroupPermissions['sysop']['importupload'] = true;
$wgGroupPermissions['sysop']['move'] = true;
$wgGroupPermissions['sysop']['patrol'] = true;
-$wgGroupPermissions['sysop']['autopatrol'] = true;
+$wgGroupPermissions['sysop']['autopatrol'] = true;
$wgGroupPermissions['sysop']['protect'] = true;
$wgGroupPermissions['sysop']['proxyunbannable'] = true;
$wgGroupPermissions['sysop']['rollback'] = true;
@@ -1029,6 +1038,21 @@ $wgRestrictionTypes = array( 'edit', 'move' );
*/
$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.
+ */
+$wgNamespaceProtection = array();
+$wgNamespaceProtection[ NS_MEDIAWIKI ] = array( 'editinterface' );
+
+/**
+* Pages in namespaces in this array can not be used as templates.
+* Elements must be numeric namespace ids.
+* Among other things, this may be useful to enforce read-restrictions
+* which may otherwise be bypassed by using the template machanism.
+*/
+$wgNonincludableNamespaces = array();
/**
* Number of seconds an account is required to age before
@@ -1045,6 +1069,11 @@ $wgAutoConfirmAge = 0;
//$wgAutoConfirmAge = 600; // ten minutes
//$wgAutoConfirmAge = 3600*24; // one day
+# Number of edits an account requires before it is autoconfirmed
+# Passing both this AND the time requirement is needed
+$wgAutoConfirmCount = 0;
+//$wgAutoConfirmCount = 50;
+
# Proxy scanner settings
@@ -1096,7 +1125,7 @@ $wgCacheEpoch = '20030516000000';
* to ensure that client-side caches don't keep obsolete copies of global
* styles.
*/
-$wgStyleVersion = '42b';
+$wgStyleVersion = '63';
# Server-side caching:
@@ -1145,6 +1174,11 @@ $wgEnotifRevealEditorAddress = false; # UPO; reply-to address may be filled with
$wgEnotifMinorEdits = true; # UPO; false: "minor edits" on pages do not trigger notification mails.
# # Attention: _every_ change on a user_talk page trigger a notification mail (if the user is not yet notified)
+/**
+ * Array of usernames who will be sent a notification email for every change which occurs on a wiki
+ */
+$wgUsersNotifedOnAllChanges = array();
+
/** Show watching users in recent changes, watchlist and page history views */
$wgRCShowWatchingUsers = false; # UPO
/** Show watching users in Page views */
@@ -1419,8 +1453,19 @@ $wgSiteNotice = '';
# Images settings
#
-/** dynamic server side image resizing ("Thumbnails") */
-$wgUseImageResize = false;
+/**
+ * Plugins for media file type handling.
+ * Each entry in the array maps a MIME type to a class name
+ */
+$wgMediaHandlers = array(
+ 'image/jpeg' => 'BitmapHandler',
+ 'image/png' => 'BitmapHandler',
+ 'image/gif' => 'BitmapHandler',
+ 'image/x-ms-bmp' => 'BmpHandler',
+ 'image/svg+xml' => 'SvgHandler',
+ 'image/vnd.djvu' => 'DjVuHandler',
+);
+
/**
* Resizing can be done using PHP's internal image libraries or using
@@ -1434,6 +1479,12 @@ $wgUseImageMagick = false;
/** The convert command shipped with ImageMagick */
$wgImageMagickConvertCommand = '/usr/bin/convert';
+/** Sharpening parameter to ImageMagick */
+$wgSharpenParameter = '0x0.4';
+
+/** Reduction in linear dimensions below which sharpening will be enabled */
+$wgSharpenReductionThreshold = 0.85;
+
/**
* Use another resizing converter, e.g. GraphicMagick
* %s will be replaced with the source path, %d with the destination
@@ -1451,7 +1502,7 @@ $wgCustomConvertCommand = false;
#
# An external program is required to perform this conversion:
$wgSVGConverters = array(
- 'ImageMagick' => '$path/convert -background white -geometry $width $input $output',
+ 'ImageMagick' => '$path/convert -background white -geometry $width $input PNG:$output',
'sodipodi' => '$path/sodipodi -z -w $width -f $input -e $output',
'inkscape' => '$path/inkscape -z -w $width -f $input -e $output',
'batik' => 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input',
@@ -1499,11 +1550,17 @@ $wgIgnoreImageErrors = false;
*/
$wgGenerateThumbnailOnParse = true;
+/** Obsolete, always true, kept for compatibility with extensions */
+$wgUseImageResize = true;
+
+
/** Set $wgCommandLineMode if it's not set already, to avoid notices */
if( !isset( $wgCommandLineMode ) ) {
$wgCommandLineMode = false;
}
+/** For colorized maintenance script output, is your terminal background dark ? */
+$wgCommandLineDarkBg = false;
#
# Recent changes settings
@@ -1613,18 +1670,22 @@ $wgExportAllowListContributors = false ;
/** Text matching this regular expression will be recognised as spam
* See http://en.wikipedia.org/wiki/Regular_expression */
$wgSpamRegex = false;
-/** Similarly if this function returns true */
+/** Similarly you can get a function to do the job. The function will be given
+ * the following args:
+ * - a Title object for the article the edit is made on
+ * - the text submitted in the textarea (wpTextbox1)
+ * - the section number.
+ * The return should be boolean indicating whether the edit matched some evilness:
+ * - true : block it
+ * - false : let it through
+ *
+ * For a complete example, have a look at the SpamBlacklist extension.
+ */
$wgFilterCallback = false;
/** Go button goes straight to the edit screen if the article doesn't exist. */
$wgGoToEdit = false;
-/** Allow limited user-specified HTML in wiki pages?
- * It will be run through a whitelist for security. Set this to false if you
- * want wiki pages to consist only of wiki markup. Note that replacements do not
- * yet exist for all HTML constructs.*/
-$wgUserHtml = true;
-
/** Allow raw, unchecked HTML in ... sections.
* THIS IS VERY DANGEROUS on a publically editable site, so USE wgGroupPermissions
* TO RESTRICT EDITING to only those that you trust
@@ -1633,8 +1694,7 @@ $wgRawHtml = false;
/**
* $wgUseTidy: use tidy to make sure HTML output is sane.
- * This should only be enabled if $wgUserHtml is true.
- * tidy is a free tool that fixes broken HTML.
+ * Tidy is a free tool that fixes broken HTML.
* See http://www.w3.org/People/Raggett/tidy/
* $wgTidyBin should be set to the path of the binary and
* $wgTidyConf to the path of the configuration file.
@@ -1649,7 +1709,7 @@ $wgRawHtml = false;
$wgUseTidy = false;
$wgAlwaysUseTidy = false;
$wgTidyBin = 'tidy';
-$wgTidyConf = $IP.'/extensions/tidy/tidy.conf';
+$wgTidyConf = $IP.'/includes/tidy.conf';
$wgTidyOpts = '';
$wgTidyInternal = function_exists( 'tidy_load_config' );
@@ -1660,7 +1720,7 @@ $wgDefaultSkin = 'monobook';
* Settings added to this array will override the default globals for the user
* preferences used by anonymous visitors and newly created accounts.
* For instance, to disable section editing links:
- * $wgDefaultUserOptions ['editsection'] = 0;
+ * $wgDefaultUserOptions ['editsection'] = 0;
*
*/
$wgDefaultUserOptions = array(
@@ -1830,10 +1890,29 @@ $wgFeedDiffCutoff = 32768;
# );
$wgExtraNamespaces = NULL;
+/**
+ * Namespace aliases
+ * These are alternate names for the primary localised namespace names, which
+ * are defined by $wgExtraNamespaces and the language file. If a page is
+ * requested with such a prefix, the request will be redirected to the primary
+ * name.
+ *
+ * Set this to a map from namespace names to IDs.
+ * Example:
+ * $wgNamespaceAliases = array(
+ * 'Wikipedian' => NS_USER,
+ * 'Help' => 100,
+ * );
+ */
+$wgNamespaceAliases = array();
+
/**
* Limit images on image description pages to a user-selectable limit. In order
- * to reduce disk usage, limits can only be selected from a list. This is the
- * list of settings the user can choose from:
+ * to reduce disk usage, limits can only be selected from a list.
+ * The user preference is saved as an array offset in the database, by default
+ * the offset is set with $wgDefaultUserOptions['imagesize']. Make sure you
+ * change it if you alter the array (see bug 8858).
+ * This is the list of settings the user can choose from:
*/
$wgImageLimits = array (
array(320,240),
@@ -1883,9 +1962,9 @@ $wgBrowserBlackList = array(
*
* Reference: http://www.psychedelix.com/agents/index.shtml
*/
- '/^Mozilla\/2\.[^ ]+ .*?\((?!compatible).*; [UIN]/',
- '/^Mozilla\/3\.[^ ]+ .*?\((?!compatible).*; [UIN]/',
- '/^Mozilla\/4\.[^ ]+ .*?\((?!compatible).*; [UIN]/',
+ '/^Mozilla\/2\.[^ ]+ [^(]*?\((?!compatible).*; [UIN]/',
+ '/^Mozilla\/3\.[^ ]+ [^(]*?\((?!compatible).*; [UIN]/',
+ '/^Mozilla\/4\.[^ ]+ [^(]*?\((?!compatible).*; [UIN]/',
/**
* MSIE on Mac OS 9 is teh sux0r, converts þ to , ð to , Þ to and Ð to
@@ -1985,7 +2064,9 @@ $wgLogTypes = array( '',
'delete',
'upload',
'move',
- 'import' );
+ 'import',
+ 'patrol',
+);
/**
* Lists the message key string for each log type. The localized messages
@@ -2001,7 +2082,9 @@ $wgLogNames = array(
'delete' => 'dellogpage',
'upload' => 'uploadlogpage',
'move' => 'movelogpage',
- 'import' => 'importlogpage' );
+ 'import' => 'importlogpage',
+ 'patrol' => 'patrol-log-page',
+);
/**
* Lists the message key string for descriptive text to be shown at the
@@ -2017,7 +2100,9 @@ $wgLogHeaders = array(
'delete' => 'dellogpagetext',
'upload' => 'uploadlogpagetext',
'move' => 'movelogpagetext',
- 'import' => 'importlogpagetext', );
+ 'import' => 'importlogpagetext',
+ 'patrol' => 'patrol-log-header',
+);
/**
* Lists the message key string for formatting individual events of each
@@ -2039,7 +2124,8 @@ $wgLogActions = array(
'move/move' => '1movedto2',
'move/move_redir' => '1movedto2_redir',
'import/upload' => 'import-logentry-upload',
- 'import/interwiki' => 'import-logentry-interwiki' );
+ 'import/interwiki' => 'import-logentry-interwiki',
+);
/**
* Experimental preview feature to fetch rendered text
@@ -2166,6 +2252,9 @@ $wgRateLimits = array(
'mailpassword' => array(
'anon' => NULL,
),
+ 'emailuser' => array(
+ 'user' => null,
+ ),
);
/**
@@ -2235,7 +2324,7 @@ $wgTrustedMediaFormats= array(
MEDIATYPE_BITMAP, //all bitmap formats
MEDIATYPE_AUDIO, //all audio formats
MEDIATYPE_VIDEO, //all plain video formats
- "image/svg", //svg (only needed if inline rendering of svg is not supported)
+ "image/svg+xml", //svg (only needed if inline rendering of svg is not supported)
"application/pdf", //PDF files
#"application/x-shockwave-flash", //flash/shockwave movie
);
@@ -2330,7 +2419,7 @@ $wgAllowDisplayTitle = false ;
$wgReservedUsernames = array(
'MediaWiki default', // Default 'Main Page' and MediaWiki: message pages
'Conversion script', // Used for the old Wikipedia software upgrade
- 'Maintenance script', // ... maintenance/edit.php uses this?
+ 'Maintenance script', // Maintenance scripts which perform editing, image import script
'Template namespace initialisation script', // Used in 1.2->1.3 upgrade
);
@@ -2338,7 +2427,7 @@ $wgReservedUsernames = array(
* MediaWiki will reject HTMLesque tags in uploaded files due to idiotic browsers which can't
* perform basic stuff like MIME detection and which are vulnerable to further idiots uploading
* crap files as images. When this directive is on, will be allowed in files with
- * an "image/svg" MIME type. You should leave this disabled if your web server is misconfigured
+ * an "image/svg+xml" MIME type. You should leave this disabled if your web server is misconfigured
* and doesn't send appropriate MIME types for SVG images.
*/
$wgAllowTitlesInSVG = false;
@@ -2364,25 +2453,42 @@ $wgMaxShellFileSize = 102400;
/**
* DJVU settings
- * Path of the djvutoxml executable
+ * Path of the djvudump executable
* Enable this and $wgDjvuRenderer to enable djvu rendering
*/
-# $wgDjvuToXML = 'djvutoxml';
-$wgDjvuToXML = null;
+# $wgDjvuDump = 'djvudump';
+$wgDjvuDump = null;
/**
* Path of the ddjvu DJVU renderer
- * Enable this and $wgDjvuToXML to enable djvu rendering
+ * Enable this and $wgDjvuDump to enable djvu rendering
*/
# $wgDjvuRenderer = 'ddjvu';
$wgDjvuRenderer = null;
/**
- * Path of the DJVU post processor
- * May include command line options
- * Default: ppmtojpeg, since ddjvu generates ppm output
+ * Path of the djvutoxml executable
+ * This works like djvudump except much, much slower as of version 3.5.
+ *
+ * For now I recommend you use djvudump instead. The djvuxml output is
+ * probably more stable, so we'll switch back to it as soon as they fix
+ * the efficiency problem.
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1704049&group_id=32953&atid=406583
+ */
+# $wgDjvuToXML = 'djvutoxml';
+$wgDjvuToXML = null;
+
+
+/**
+ * Shell command for the DJVU post processor
+ * Default: pnmtopng, since ddjvu generates ppm output
+ * Set this to false to output the ppm file directly.
+ */
+$wgDjvuPostProcessor = 'pnmtojpeg';
+/**
+ * File extension for the DJVU post processor output
*/
-$wgDjvuPostProcessor = 'ppmtojpeg';
+$wgDjvuOutputExtension = 'jpg';
/**
* Enable direct access to the data API
@@ -2416,4 +2522,14 @@ $wgBreakFrames = false;
*/
$wgDisableQueryPageUpdate = false;
+/**
+ * Set this to false to disable cascading protection
+ */
+$wgEnableCascadingProtection = true;
+
+/**
+ * Disable output compression (enabled by default if zlib is available)
+ */
+$wgDisableOutputCompression = false;
+
?>
diff --git a/includes/Defines.php b/includes/Defines.php
index 84bc4495..98e76277 100644
--- a/includes/Defines.php
+++ b/includes/Defines.php
@@ -1,7 +1,6 @@
mRcidMarkPatrolled = intval($rcid); # force it to be an integer
}
- function showDiffPage() {
- global $wgUser, $wgOut, $wgContLang, $wgUseExternalEditor, $wgUseRCPatrol;
+ function showDiffPage( $diffOnly = false ) {
+ global $wgUser, $wgOut, $wgUseExternalEditor, $wgUseRCPatrol;
$fname = 'DifferenceEngine::showDiffPage';
wfProfileIn( $fname );
@@ -118,6 +117,7 @@ CONTROL;
# is the first version of that article. In that case, V' does not exist.
if ( $this->mOldid === false ) {
$this->showFirstRevision();
+ $this->renderNewRevision(); // should we respect $diffOnly here or not?
wfProfileOut( $fname );
return;
}
@@ -178,15 +178,34 @@ CONTROL;
$oldHeader = "{$this->mOldtitle} " .
$sk->revUserTools( $this->mOldRev ) . " " .
- $oldminor . $sk->revComment( $this->mOldRev, true ) . " " .
+ $oldminor . $sk->revComment( $this->mOldRev, !$diffOnly ) . " " .
$prevlink;
$newHeader = "{$this->mNewtitle} " .
$sk->revUserTools( $this->mNewRev ) . " $rollback " .
- $newminor . $sk->revComment( $this->mNewRev, true ) . " " .
+ $newminor . $sk->revComment( $this->mNewRev, !$diffOnly ) . " " .
$nextlink . $patrol;
$this->showDiff( $oldHeader, $newHeader );
+
+ if ( !$diffOnly )
+ $this->renderNewRevision();
+
+ wfProfileOut( $fname );
+ }
+
+ /**
+ * Show the new revision of the page.
+ */
+ function renderNewRevision() {
+ global $wgOut;
+ $fname = 'DifferenceEngine::renderNewRevision';
+ wfProfileIn( $fname );
+
$wgOut->addHTML( "
';
+ } elseif( $this->mParsing && wfIsBadImage( $nt->getDBkey(), $this->getContextTitle() ) ) {
# The image is blacklisted, just show it as a text link.
- $thumbhtml = '
';
}
@@ -200,27 +241,55 @@ class ImageGallery
# in version 4.8.6 generated crackpot html in its absence, see:
# http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar
- $s .= ($i%4==0) ? '
" );
}
} else {
#if direct link is allowed but it's not a renderable image, show an icon.
@@ -296,25 +314,26 @@ class ImagePage extends Article {
if ($showLink) {
- $filename = wfEscapeWikiText( $this->img->getName() );
- // Hacky workaround: for some reason we use the incorrect MIME type
- // image/svg for SVG. This should be fixed internally, but at least
- // make the displayed type right.
- $mime = $this->img->getMimeType();
+ // Workaround for incorrect MIME type on SVGs uploaded in previous versions
if ($mime == 'image/svg') $mime = 'image/svg+xml';
- $info = wfMsg( 'fileinfo',
- ceil($this->img->getSize()/1024.0),
- $mime );
+ $filename = wfEscapeWikiText( $this->img->getName() );
+ $info = wfMsg( 'file-info', $sk->formatSize( $this->img->getSize() ), $mime );
+ $infores = '';
+
+ // Check for MIME type. Other types may have more information in the future.
+ if (substr($mime,0,9) == 'image/svg' ) {
+ $infores = wfMsg('file-svg', $width_orig, $height_orig ) . ' ';
+ }
global $wgContLang;
$dirmark = $wgContLang->getDirMark();
if (!$this->img->isSafeFile()) {
$warning = wfMsg( 'mediawarning' );
$wgOut->addWikiText( <<
+
";
+ if ( !$thumb ) {
+ $s .= htmlspecialchars( wfMsg( 'thumbnail_error', '' ) );
$zoomicon = '';
} elseif( !$img->exists() ) {
$s .= $this->makeBrokenImageLinkObj( $img->getTitle() );
$zoomicon = '';
} else {
- $s .= ''.
- '';
+ $imgAttribs = array(
+ 'alt' => $alt,
+ 'longdesc' => $u,
+ 'class' => 'thumbimage'
+ );
+ $linkAttribs = array(
+ 'href' => $u,
+ 'class' => 'internal',
+ 'title' => $alt
+ );
+
+ $s .= $thumb->toHtml( $imgAttribs, $linkAttribs );
if ( $framed ) {
$zoomicon="";
} else {
@@ -680,8 +622,6 @@ class Linker {
*
* @param $title Title object.
* @param $text String: pre-sanitized HTML
- * @param $nourl Boolean: Mask absolute URLs, so the parser doesn't
- * linkify them (it is currently not context-aware)
* @return string HTML
*
* @public
@@ -756,10 +696,10 @@ class Linker {
/**
* @param $userId Integer: user id in database.
* @param $userText String: user name in database.
+ * @param $redContribsWhenNoEdits Bool: return a red contribs link when the user had no edits and this is true.
* @return string HTML fragment with talk and/or block links
- * @private
*/
- function userToolLinks( $userId, $userText ) {
+ public function userToolLinks( $userId, $userText, $redContribsWhenNoEdits = false ) {
global $wgUser, $wgDisableAnonTalk, $wgSysopUserBans;
$talkable = !( $wgDisableAnonTalk && 0 == $userId );
$blockable = ( $wgSysopUserBans || 0 == $userId );
@@ -769,9 +709,15 @@ class Linker {
$items[] = $this->userTalkLink( $userId, $userText );
}
if( $userId ) {
+ // check if the user has an edit
+ if( $redContribsWhenNoEdits && User::edits( $userId ) == 0 ) {
+ $style = "class='new'";
+ } else {
+ $style = '';
+ }
$contribsPage = SpecialPage::getTitleFor( 'Contributions', $userText );
- $items[] = $this->makeKnownLinkObj( $contribsPage ,
- wfMsgHtml( 'contribslink' ) );
+
+ $items[] = $this->makeKnownLinkObj( $contribsPage, wfMsgHtml( 'contribslink' ), '', '', '', '', $style );
}
if( $blockable && $wgUser->isAllowed( 'block' ) ) {
$items[] = $this->blockLink( $userId, $userText );
@@ -784,6 +730,14 @@ class Linker {
}
}
+ /**
+ * Alias for userToolLinks( $userId, $userText, true );
+ */
+ public function userToolLinksRedContribs( $userId, $userText ) {
+ return $this->userToolLinks( $userId, $userText, true );
+ }
+
+
/**
* @param $userId Integer: user id in database.
* @param $userText String: user name in database.
@@ -791,11 +745,8 @@ class Linker {
* @private
*/
function userTalkLink( $userId, $userText ) {
- global $wgLang;
- $talkname = $wgLang->getNsText( NS_TALK ); # use the shorter name
-
$userTalkPage = Title::makeTitle( NS_USER_TALK, $userText );
- $userTalkLink = $this->makeLinkObj( $userTalkPage, $talkname );
+ $userTalkLink = $this->makeLinkObj( $userTalkPage, wfMsgHtml( 'talkpagelinktext' ) );
return $userTalkLink;
}
@@ -860,7 +811,7 @@ class Linker {
* Since you can't set a default parameter for a reference, I've turned it
* temporarily to a value pass. Should be adjusted further. --brion
*
- * $param string $comment
+ * @param string $comment
* @param mixed $title Title object (to generate link to the section in autocomment) or null
* @param bool $local Whether section links should refer to local page
*/
@@ -1013,7 +964,7 @@ class Linker {
/** @todo document */
function tocList($toc) {
global $wgJsMimeType;
- $title = wfMsgForContent('toc') ;
+ $title = wfMsgHtml('toc') ;
return
'
'
. '
' . $title . "
\n"
@@ -1023,8 +974,8 @@ class Linker {
. "\n
"
. '\n";
@@ -1134,7 +1085,7 @@ class Linker {
global $wgUser;
wfProfileIn( __METHOD__ );
- $sk =& $wgUser->getSkin();
+ $sk = $wgUser->getSkin();
$outText = '';
if ( count( $templates ) > 0 ) {
@@ -1182,10 +1133,14 @@ class Linker {
*/
public function formatSize( $size ) {
global $wgLang;
+ // For small sizes no decimal places necessary
+ $round = 0;
if( $size > 1024 ) {
$size = $size / 1024;
if( $size > 1024 ) {
$size = $size / 1024;
+ // For MB and bigger two decimal places are smarter
+ $round = 2;
if( $size > 1024 ) {
$size = $size / 1024;
$msg = 'size-gigabytes';
@@ -1198,10 +1153,59 @@ class Linker {
} else {
$msg = 'size-bytes';
}
- $size = round( $size, 0 );
+ $size = round( $size, $round );
return wfMsgHtml( $msg, $wgLang->formatNum( $size ) );
}
-
+
+ /**
+ * Given the id of an interface element, constructs the appropriate title
+ * and accesskey attributes from the system messages. (Note, this is usu-
+ * ally the id but isn't always, because sometimes the accesskey needs to
+ * go on a different element than the id, for reverse-compatibility, etc.)
+ *
+ * @param string $name Id of the element, minus prefixes.
+ * @return string title and accesskey attributes, ready to drop in an
+ * element (e.g., ' title="This does something [x]" accesskey="x"').
+ */
+ public function tooltipAndAccesskey($name) {
+ $out = '';
+
+ $tooltip = wfMsg('tooltip-'.$name);
+ if (!wfEmptyMsg('tooltip-'.$name, $tooltip) && $tooltip != '-') {
+ // Compatibility: formerly some tooltips had [alt-.] hardcoded
+ $tooltip = preg_replace( "/ ?\[alt-.\]$/", '', $tooltip );
+ $out .= ' title="'.htmlspecialchars($tooltip);
+ }
+ $accesskey = wfMsg('accesskey-'.$name);
+ if ($accesskey && $accesskey != '-' && !wfEmptyMsg('accesskey-'.$name, $accesskey)) {
+ if ($out) $out .= " [$accesskey]\" accesskey=\"$accesskey\"";
+ else $out .= " title=\"[$accesskey]\" accesskey=\"$accesskey\"";
+ } elseif ($out) {
+ $out .= '"';
+ }
+ return $out;
+ }
+
+ /**
+ * Given the id of an interface element, constructs the appropriate title
+ * attribute from the system messages. (Note, this is usually the id but
+ * isn't always, because sometimes the accesskey needs to go on a different
+ * element than the id, for reverse-compatibility, etc.)
+ *
+ * @param string $name Id of the element, minus prefixes.
+ * @return string title attribute, ready to drop in an element
+ * (e.g., ' title="This does something"').
+ */
+ public function tooltip($name) {
+ $out = '';
+
+ $tooltip = wfMsg('tooltip-'.$name);
+ if (!wfEmptyMsg('tooltip-'.$name, $tooltip) && $tooltip != '-') {
+ $out = ' title="'.htmlspecialchars($tooltip).'"';
+ }
+
+ return $out;
+ }
}
?>
diff --git a/includes/LinksUpdate.php b/includes/LinksUpdate.php
index 9e25bf07..856c665d 100644
--- a/includes/LinksUpdate.php
+++ b/includes/LinksUpdate.php
@@ -1,19 +1,15 @@
mOptions = array( 'FOR UPDATE' );
}
- $this->mDb =& wfGetDB( DB_MASTER );
+ $this->mDb = wfGetDB( DB_MASTER );
if ( !is_object( $title ) ) {
throw new MWException( "The calling convention to LinksUpdate::LinksUpdate() has changed. " .
@@ -172,7 +168,7 @@ class LinksUpdate {
wfProfileIn( __METHOD__ );
$batchSize = 100;
- $dbr =& wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( array( 'templatelinks', 'page' ),
array( 'page_namespace', 'page_title' ),
array(
diff --git a/includes/LoadBalancer.php b/includes/LoadBalancer.php
index 396ef865..4ebe26c7 100644
--- a/includes/LoadBalancer.php
+++ b/includes/LoadBalancer.php
@@ -1,7 +1,6 @@
mServers = $servers;
$this->mFailFunction = $failFunction;
@@ -32,7 +30,7 @@ class LoadBalancer {
$this->mWriteIndex = -1;
$this->mForce = -1;
$this->mConnections = array();
- $this->mLastIndex = 1;
+ $this->mLastIndex = -1;
$this->mLoads = array();
$this->mWaitForFile = false;
$this->mWaitForPos = false;
@@ -97,7 +95,9 @@ class LoadBalancer {
# Unset excessively lagged servers
$lags = $this->getLagTimes();
foreach ( $lags as $i => $lag ) {
- if ( isset( $this->mServers[$i]['max lag'] ) && $lag > $this->mServers[$i]['max lag'] ) {
+ if ( $i != 0 && isset( $this->mServers[$i]['max lag'] ) &&
+ ( $lag === false || $lag > $this->mServers[$i]['max lag'] ) )
+ {
unset( $loads[$i] );
}
}
@@ -504,8 +504,7 @@ class LoadBalancer {
* Save master pos to the session and to memcached, if the session exists
*/
function saveMasterPos() {
- global $wgSessionStarted;
- if ( $wgSessionStarted && count( $this->mServers ) > 1 ) {
+ if ( session_id() != '' && count( $this->mServers ) > 1 ) {
# If this entire request was served from a slave without opening a connection to the
# master (however unlikely that may be), then we can fetch the position from the slave.
if ( empty( $this->mConnections[0] ) ) {
diff --git a/includes/LogPage.php b/includes/LogPage.php
index dd395126..af03bbba 100644
--- a/includes/LogPage.php
+++ b/includes/LogPage.php
@@ -21,7 +21,6 @@
/**
* Contain log classes
*
- * @package MediaWiki
*/
/**
@@ -29,7 +28,6 @@
* The logs are now kept in a table which is easier to manage and trim
* than ever-growing wiki pages.
*
- * @package MediaWiki
*/
class LogPage {
/* @access private */
@@ -44,7 +42,7 @@ class LogPage {
* 'upload', 'move'
* @param bool $rc Whether to update recent changes as well as the logging table
*/
- function LogPage( $type, $rc = true ) {
+ function __construct( $type, $rc = true ) {
$this->type = $type;
$this->updateRecentChanges = $rc;
}
@@ -55,7 +53,7 @@ class LogPage {
global $wgUser;
$fname = 'LogPage::saveContent';
- $dbw =& wfGetDB( DB_MASTER );
+ $dbw = wfGetDB( DB_MASTER );
$uid = $wgUser->getID();
$this->timestamp = $now = wfTimestampNow();
@@ -119,7 +117,7 @@ class LogPage {
}
/**
- * @fixme: handle missing log types
+ * @todo handle missing log types
* @static
*/
function logHeader( $type ) {
@@ -134,6 +132,10 @@ class LogPage {
global $wgLang, $wgContLang, $wgLogActions;
$key = "$type/$action";
+
+ if( $key == 'patrol/patrol' )
+ return PatrolLog::makeActionText( $title, $params, $skin );
+
if( isset( $wgLogActions[$key] ) ) {
if( is_null( $title ) ) {
$rv=wfMsg( $wgLogActions[$key] );
@@ -183,8 +185,13 @@ class LogPage {
}
} else {
array_unshift( $params, $titleLink );
- if ( $translate && $key == 'block/block' ) {
- $params[1] = $wgLang->translateBlockExpiry($params[1]);
+ if ( $key == 'block/block' ) {
+ if ( $translate ) {
+ $params[1] = $wgLang->translateBlockExpiry( $params[1] );
+ }
+ $params[2] = isset( $params[2] )
+ ? self::formatBlockFlags( $params[2] )
+ : '';
}
$rv = wfMsgReal( $wgLogActions[$key], $params, true, !$skin );
}
@@ -241,6 +248,41 @@ class LogPage {
return explode( "\n", $blob );
}
}
+
+ /**
+ * Convert a comma-delimited list of block log flags
+ * into a more readable (and translated) form
+ *
+ * @param $flags Flags to format
+ * @return string
+ */
+ public static function formatBlockFlags( $flags ) {
+ $flags = explode( ',', trim( $flags ) );
+ if( count( $flags ) > 0 ) {
+ for( $i = 0; $i < count( $flags ); $i++ )
+ $flags[$i] = self::formatBlockFlag( $flags[$i] );
+ return '(' . implode( ', ', $flags ) . ')';
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Translate a block log flag if possible
+ *
+ * @param $flag Flag to translate
+ * @return string
+ */
+ public static function formatBlockFlag( $flag ) {
+ static $messages = array();
+ if( !isset( $messages[$flag] ) ) {
+ $k = 'block-log-flags-' . $flag;
+ $msg = wfMsg( $k );
+ $messages[$flag] = htmlspecialchars( wfEmptyMsg( $k, $msg ) ? $flag : $msg );
+ }
+ return $messages[$flag];
+ }
+
}
?>
diff --git a/includes/MacBinary.php b/includes/MacBinary.php
index 05c3ce5c..2f6ad4f4 100644
--- a/includes/MacBinary.php
+++ b/includes/MacBinary.php
@@ -22,12 +22,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
- * @package MediaWiki
- * @subpackage SpecialPage
+ * @addtogroup SpecialPage
*/
class MacBinary {
- function MacBinary( $filename ) {
+ function __construct( $filename ) {
$this->open( $filename );
$this->loadHeader();
}
@@ -269,4 +268,4 @@ class MacBinary {
}
}
-?>
\ No newline at end of file
+?>
diff --git a/includes/MagicWord.php b/includes/MagicWord.php
index 60bfd0f4..bf72a0c8 100644
--- a/includes/MagicWord.php
+++ b/includes/MagicWord.php
@@ -1,8 +1,7 @@
mId = $id;
$this->mSynonyms = (array)$syn;
$this->mCaseSensitive = $cs;
diff --git a/includes/Math.php b/includes/Math.php
index 9fa631f7..88934e5f 100644
--- a/includes/Math.php
+++ b/includes/Math.php
@@ -1,7 +1,6 @@
parsing
- * @package MediaWiki
*/
/**
@@ -11,7 +10,6 @@
*
* by Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004)
*
- * @package MediaWiki
*/
class MathRenderer {
var $mode = MW_MATH_MODERN;
@@ -22,7 +20,7 @@ class MathRenderer {
var $mathml = '';
var $conservativeness = 0;
- function MathRenderer( $tex ) {
+ function __construct( $tex ) {
$this->tex = $tex;
}
@@ -156,7 +154,7 @@ class MathRenderer {
$md5_sql = pack('H32', $this->md5); # Binary packed, not hex
- $dbw =& wfGetDB( DB_MASTER );
+ $dbw = wfGetDB( DB_MASTER );
$dbw->replace( 'math', array( 'math_inputhash' ),
array(
'math_inputhash' => $md5_sql,
@@ -185,7 +183,7 @@ class MathRenderer {
$fname = 'MathRenderer::_recall';
$this->md5 = md5( $this->tex );
- $dbr =& wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_SLAVE );
$rpage = $dbr->selectRow( 'math',
array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ),
array( 'math_inputhash' => pack("H32", $this->md5)), # Binary packed, not hex
diff --git a/includes/MediaTransformOutput.php b/includes/MediaTransformOutput.php
new file mode 100644
index 00000000..60057e3a
--- /dev/null
+++ b/includes/MediaTransformOutput.php
@@ -0,0 +1,166 @@
+width;
+ }
+
+ /**
+ * Get the height of the output box
+ */
+ function getHeight() {
+ return $this->height;
+ }
+
+ /**
+ * @return string The thumbnail URL
+ */
+ function getUrl() {
+ return $this->url;
+ }
+
+ /**
+ * @return string Destination file path (local filesystem)
+ */
+ function getPath() {
+ return $this->path;
+ }
+
+ /**
+ * Fetch HTML for this transform output
+ * @param array $attribs Advisory associative array of HTML attributes supplied
+ * by the linker. These can be incorporated into the output in any way.
+ * @param array $linkAttribs Attributes of a suggested enclosing tag.
+ * May be ignored.
+ */
+ abstract function toHtml( $attribs = array() , $linkAttribs = false );
+
+ /**
+ * This will be overridden to return true in error classes
+ */
+ function isError() {
+ return false;
+ }
+
+ /**
+ * Wrap some XHTML text in an anchor tag with the given attributes
+ */
+ protected function linkWrap( $linkAttribs, $contents ) {
+ if ( $linkAttribs ) {
+ return Xml::tags( 'a', $linkAttribs, $contents );
+ } else {
+ return $contents;
+ }
+ }
+}
+
+
+/**
+ * Media transform output for images
+ *
+ * @addtogroup Media
+ */
+class ThumbnailImage extends MediaTransformOutput {
+ /**
+ * @param string $path Filesystem path to the thumb
+ * @param string $url URL path to the thumb
+ * @private
+ */
+ function ThumbnailImage( $url, $width, $height, $path = false ) {
+ $this->url = $url;
+ # These should be integers when they get here.
+ # If not, there's a bug somewhere. But let's at
+ # least produce valid HTML code regardless.
+ $this->width = round( $width );
+ $this->height = round( $height );
+ $this->path = $path;
+ }
+
+ /**
+ * Return HTML tag for the thumbnail, will include
+ * width and height attributes and a blank alt text (as required).
+ *
+ * You can set or override additional attributes by passing an
+ * associative array of name => data pairs. The data will be escaped
+ * for HTML output, so should be in plaintext.
+ *
+ * If $linkAttribs is given, the image will be enclosed in an tag.
+ *
+ * @param array $attribs
+ * @param array $linkAttribs
+ * @return string
+ * @public
+ */
+ function toHtml( $attribs = array(), $linkAttribs = false ) {
+ $attribs['src'] = $this->url;
+ $attribs['width'] = $this->width;
+ $attribs['height'] = $this->height;
+ if( !isset( $attribs['alt'] ) ) $attribs['alt'] = '';
+ return $this->linkWrap( $linkAttribs, Xml::element( 'img', $attribs ) );
+ }
+
+}
+
+/**
+ * Basic media transform error class
+ *
+ * @addtogroup Media
+ */
+class MediaTransformError extends MediaTransformOutput {
+ var $htmlMsg, $textMsg, $width, $height, $url, $path;
+
+ function __construct( $msg, $width, $height /*, ... */ ) {
+ $args = array_slice( func_get_args(), 3 );
+ $htmlArgs = array_map( 'htmlspecialchars', $args );
+ $htmlArgs = array_map( 'nl2br', $htmlArgs );
+
+ $this->htmlMsg = wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $msg, true ) ), $htmlArgs );
+ $this->textMsg = wfMsgReal( $msg, $args );
+ $this->width = intval( $width );
+ $this->height = intval( $height );
+ $this->url = false;
+ $this->path = false;
+ }
+
+ function toHtml( $attribs = array(), $linkAttribs = false ) {
+ return "
width}px; height: {$this->height}px;\">
" .
+ $this->htmlMsg .
+ "
";
+ }
+
+ function toText() {
+ return $this->textMsg;
+ }
+
+ function getHtmlMsg() {
+ return $this->htmlMsg;
+ }
+
+ function isError() {
+ return true;
+ }
+}
+
+/**
+ * Shortcut class for parameter validation errors
+ *
+ * @addtogroup Media
+ */
+class TransformParameterError extends MediaTransformError {
+ function __construct( $params ) {
+ parent::__construct( 'thumbnail_error',
+ max( @$params['width'], 180 ), max( @$params['height'], 180 ),
+ wfMsg( 'thumbnail_invalid_params' ) );
+ }
+}
+
+?>
diff --git a/includes/MemcachedSessions.php b/includes/MemcachedSessions.php
index e2dc52ca..3bcf5535 100644
--- a/includes/MemcachedSessions.php
+++ b/includes/MemcachedSessions.php
@@ -6,7 +6,6 @@
* be necessary to change the cookie settings to work across hostnames.
* See: http://www.php.net/manual/en/function.session-set-save-handler.php
*
- * @package MediaWiki
*/
/**
diff --git a/includes/MessageCache.php b/includes/MessageCache.php
index a269c620..e2cbf5f6 100644
--- a/includes/MessageCache.php
+++ b/includes/MessageCache.php
@@ -1,8 +1,7 @@
mCache = array();
# Load titles for all oversized pages in the MediaWiki namespace
@@ -547,7 +545,7 @@ class MessageCache {
if ( $type == ' ' ) {
$message = substr( $entry, 1 );
- $this->mCache[$title] = $message;
+ $this->mCache[$title] = $entry;
return $message;
} elseif ( $entry == '!NONEXISTENT' ) {
return false;
diff --git a/includes/Metadata.php b/includes/Metadata.php
index 4e0d91b7..b995b223 100644
--- a/includes/Metadata.php
+++ b/includes/Metadata.php
@@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* @author Evan Prodromou
- * @package MediaWiki
*/
/**
@@ -74,7 +73,9 @@ function wfCreativeCommonsRdf($article) {
function rdfSetup() {
global $wgOut, $_SERVER;
- $rdftype = wfNegotiateType(wfAcceptToPrefs($_SERVER['HTTP_ACCEPT']), wfAcceptToPrefs(RDF_TYPE_PREFS));
+ $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null;
+
+ $rdftype = wfNegotiateType(wfAcceptToPrefs($httpaccept), wfAcceptToPrefs(RDF_TYPE_PREFS));
if (!$rdftype) {
wfHttpError(406, "Not Acceptable", wfMsg("notacceptable"));
diff --git a/includes/MimeMagic.php b/includes/MimeMagic.php
index ca05dbb3..db35535d 100644
--- a/includes/MimeMagic.php
+++ b/includes/MimeMagic.php
@@ -1,7 +1,6 @@
mMimeToExt[$mime]) $this->mMimeToExt[$mime] .= ' '.$ext;
+ if ( !empty($this->mMimeToExt[$mime])) $this->mMimeToExt[$mime] .= ' '.$ext;
else $this->mMimeToExt[$mime]= $ext;
$extensions= explode(' ',$ext);
@@ -158,7 +159,7 @@ class MimeMagic {
$e= trim($e);
if (empty($e)) continue;
- if (@$this->mExtToMime[$e]) $this->mExtToMime[$e] .= ' '.$mime;
+ if ( !empty($this->mExtToMime[$e])) $this->mExtToMime[$e] .= ' '.$mime;
else $this->mExtToMime[$e]= $mime;
}
}
@@ -262,7 +263,7 @@ class MimeMagic {
function getTypesForExtension($ext) {
$ext= strtolower($ext);
- $r= @$this->mExtToMime[$ext];
+ $r= isset( $this->mExtToMime[$ext] ) ? $this->mExtToMime[$ext] : null;
return $r;
}
@@ -341,7 +342,7 @@ class MimeMagic {
}
- /** mime type detection. This uses detectMimeType to detect the mim type of the file,
+ /** mime type detection. This uses detectMimeType to detect the mime type of the file,
* but applies additional checks to determine some well known file formats that may be missed
* or misinterpreter by the default mime detection (namely xml based formats like XHTML or SVG).
*
@@ -399,8 +400,8 @@ class MimeMagic {
#print " ANALYSING $file ($mime): doctype= $doctype; tag= $tag ";
- if (strpos($doctype,"-//W3C//DTD SVG")===0) $mime= "image/svg";
- elseif ($tag==="svg") $mime= "image/svg";
+ if (strpos($doctype,"-//W3C//DTD SVG")===0) $mime= "image/svg+xml";
+ elseif ($tag==="svg") $mime= "image/svg+xml";
elseif (strpos($doctype,"-//W3C//DTD XHTML")===0) $mime= "text/html";
elseif ($tag==="html") $mime= "text/html";
}
@@ -424,7 +425,9 @@ class MimeMagic {
$match= array();
$prog= "";
- if (preg_match('%/?([^\s]+/)(w+)%sim',$head,$match)) $script= $match[2];
+ if (preg_match('%/?([^\s]+/)(w+)%sim',$head,$match)) {
+ $script= $match[2]; // FIXME: $script variable not used; should this be "$prog = $match[2];" instead?
+ }
$mime= "application/x-$prog";
}
diff --git a/includes/Namespace.php b/includes/Namespace.php
index 78493902..dd67b55a 100644
--- a/includes/Namespace.php
+++ b/includes/Namespace.php
@@ -1,7 +1,6 @@
= NS_MAIN );
}
+
+ /**
+ * Does this namespace contain content, for the purposes
+ * of calculating statistics, etc?
+ *
+ * @param $index Index to check
+ * @return bool
+ */
+ public static function isContent( $index ) {
+ global $wgContentNamespaces;
+ return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
+ }
+
}
+
?>
diff --git a/includes/ObjectCache.php b/includes/ObjectCache.php
index 2b26cf4e..a493a75c 100644
--- a/includes/ObjectCache.php
+++ b/includes/ObjectCache.php
@@ -1,7 +1,6 @@
/i', '', $s );
+}
+
+/**
+ * Add a Content-Length header if possible. This makes it cooperate with squid better.
+ */
+function wfDoContentLength( $length ) {
+ if ( !headers_sent() && $_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0' ) {
+ header( "Content-Length: $length" );
+ }
+}
+
+?>
diff --git a/includes/OutputPage.php b/includes/OutputPage.php
index 6d3cc0ac..03e832a4 100644
--- a/includes/OutputPage.php
+++ b/includes/OutputPage.php
@@ -2,12 +2,10 @@
if ( ! defined( 'MEDIAWIKI' ) )
die( 1 );
/**
- * @package MediaWiki
*/
/**
* @todo document
- * @package MediaWiki
*/
class OutputPage {
var $mMetatags, $mKeywords;
@@ -34,7 +32,7 @@ class OutputPage {
* Constructor
* Initialise private variables
*/
- function OutputPage() {
+ function __construct() {
$this->mMetatags = $this->mKeywords = $this->mLinktags = array();
$this->mHTMLtitle = $this->mPagetitle = $this->mBodytext =
$this->mRedirect = $this->mLastModified =
@@ -49,6 +47,7 @@ class OutputPage {
$this->mParserOptions = null;
$this->mSquidMaxage = 0;
$this->mScripts = '';
+ $this->mHeadItems = array();
$this->mETag = false;
$this->mRevisionId = null;
$this->mNewSectionLink = false;
@@ -71,7 +70,7 @@ class OutputPage {
# To add an http-equiv meta tag, precede the name with "http:"
function addMeta( $name, $val ) { array_push( $this->mMetatags, array( $name, $val ) ); }
function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
- function addScript( $script ) { $this->mScripts .= $script; }
+ function addScript( $script ) { $this->mScripts .= "\t\t".$script; }
/**
* Add a self-contained script tag with the given contents
@@ -79,10 +78,24 @@ class OutputPage {
*/
function addInlineScript( $script ) {
global $wgJsMimeType;
- $this->mScripts .= "";
+ $this->mScripts .= "";
}
- function getScript() { return $this->mScripts; }
+ function getScript() {
+ return $this->mScripts . $this->getHeadItems();
+ }
+
+ function getHeadItems() {
+ $s = '';
+ foreach ( $this->mHeadItems as $item ) {
+ $s .= $item;
+ }
+ return $s;
+ }
+
+ function addHeadItem( $name, $value ) {
+ $this->mHeadItems[$name] = $value;
+ }
function setETag($tag) { $this->mETag = $tag; }
function setArticleBodyOnly($only) { $this->mArticleBodyOnly = $only; }
@@ -254,7 +267,7 @@ class OutputPage {
$lb->setArray( $arr );
$lb->execute();
- $sk =& $wgUser->getSkin();
+ $sk = $wgUser->getSkin();
foreach ( $categories as $category => $unused ) {
$title = Title::makeTitleSafe( NS_CATEGORY, $category );
$text = $wgContLang->convertHtml( $title->getText() );
@@ -315,14 +328,26 @@ class OutputPage {
$this->addWikiTextTitle($text, $title, $linestart);
}
- private function addWikiTextTitle($text, &$title, $linestart) {
+ function addWikiTextTitleTidy($text, &$title, $linestart = true) {
+ $this->addWikiTextTitle( $text, $title, $linestart, true );
+ }
+
+ public function addWikiTextTitle($text, &$title, $linestart, $tidy = false) {
global $wgParser;
+
$fname = 'OutputPage:addWikiTextTitle';
wfProfileIn($fname);
+
wfIncrStats('pcache_not_possible');
- $parserOutput = $wgParser->parse( $text, $title, $this->parserOptions(),
+
+ $popts = $this->parserOptions();
+ $popts->setTidy($tidy);
+
+ $parserOutput = $wgParser->parse( $text, $title, $popts,
$linestart, true, $this->mRevisionId );
+
$this->addParserOutput( $parserOutput );
+
wfProfileOut($fname);
}
@@ -345,6 +370,7 @@ class OutputPage {
$this->mSubtitle .= $parserOutput->mSubtitle ;
}
$this->mNoGallery = $parserOutput->getNoGallery();
+ $this->mHeadItems = array_merge( $this->mHeadItems, (array)$parserOutput->mHeadItems );
wfRunHooks( 'OutputPageParserOutput', array( &$this, $parserOutput ) );
}
@@ -366,6 +392,7 @@ class OutputPage {
* @param string $text
* @param Article $article
* @param bool $cache
+ * @deprecated Use Article::outputWikitext
*/
public function addPrimaryWikiText( $text, $article, $cache = true ) {
global $wgParser, $wgUser;
@@ -384,17 +411,19 @@ class OutputPage {
}
/**
- * For anything that isn't primary text or interface message
- *
- * @param string $text
- * @param bool $linestart Is this the start of a line?
+ * @deprecated use addWikiTextTidy()
*/
public function addSecondaryWikiText( $text, $linestart = true ) {
global $wgTitle;
- $popts = $this->parserOptions();
- $popts->setTidy(true);
- $this->addWikiTextTitle($text, $wgTitle, $linestart);
- $popts->setTidy(false);
+ $this->addWikiTextTitleTidy($text, $wgTitle, $linestart);
+ }
+
+ /**
+ * Add wikitext with tidy enabled
+ */
+ public function addWikiTextTidy( $text, $linestart = true ) {
+ global $wgTitle;
+ $this->addWikiTextTitleTidy($text, $wgTitle, $linestart);
}
@@ -476,7 +505,7 @@ class OutputPage {
# maintain different caches for logged-in users and non-logged in ones
$wgRequest->response()->header( 'Vary: Accept-Encoding, Cookie' );
if( !$this->uncacheableBecauseRequestvars() && $this->mEnableClientCache ) {
- if( $wgUseSquid && ! isset( $_COOKIE[ini_get( 'session.name') ] ) &&
+ if( $wgUseSquid && session_id() == '' &&
! $this->isPrintable() && $this->mSquidMaxage != 0 )
{
if ( $wgUseESI ) {
@@ -536,13 +565,16 @@ class OutputPage {
if ( $wgUseAjax ) {
$this->addScript( "\n" );
+
+ wfRunHooks( 'AjaxAddScript', array( &$this ) );
+
if( $wgAjaxSearch ) {
- $this->addScript( "\n" );
+ $this->addScript( "\n" );
$this->addScript( "\n" );
}
if( $wgAjaxWatch && $wgUser->isLoggedIn() ) {
- $this->addScript( "\n" );
+ $this->addScript( "\n" );
}
}
@@ -750,7 +782,7 @@ class OutputPage {
$this->returnToMain( false );
}
- /** @obsolete */
+ /** @deprecated */
public function errorpage( $title, $msg ) {
throw new ErrorPageError( $title, $msg );
}
@@ -792,10 +824,10 @@ class OutputPage {
$groupName = User::getGroupName( $key );
$groupPage = User::getGroupPage( $key );
if( $groupPage ) {
- $skin =& $wgUser->getSkin();
- $groups[] = '"'.$skin->makeLinkObj( $groupPage, $groupName ).'"';
+ $skin = $wgUser->getSkin();
+ $groups[] = $skin->makeLinkObj( $groupPage, $groupName );
} else {
- $groups[] = '"'.$groupName.'"';
+ $groups[] = $groupName;
}
}
}
@@ -860,7 +892,7 @@ class OutputPage {
$this->returnToMain( true, $mainPage );
}
- /** @obsolete */
+ /** @deprecated */
public function databaseError( $fname, $sql, $error, $errno ) {
throw new MWException( "OutputPage::databaseError is obsolete\n" );
}
@@ -881,10 +913,22 @@ class OutputPage {
$this->setPageTitle( wfMsg( 'viewsource' ) );
$this->setSubtitle( wfMsg( 'viewsourcefor', $skin->makeKnownLinkObj( $wgTitle ) ) );
+ list( $cascadeSources, $restrictions ) = $wgTitle->getCascadeProtectionSources();
+
# Determine if protection is due to the page being a system message
# and show an appropriate explanation
- if( $wgTitle->getNamespace() == NS_MEDIAWIKI && !$wgUser->isAllowed( 'editinterface' ) ) {
+ if( $wgTitle->getNamespace() == NS_MEDIAWIKI ) {
$this->addWikiText( wfMsg( 'protectedinterface' ) );
+ } if ( $cascadeSources && count($cascadeSources) > 0 ) {
+ $titles = '';
+
+ foreach ( $cascadeSources as $title ) {
+ $titles .= '* [[:' . $title->getPrefixedText() . "]]\n";
+ }
+
+ $notice = wfMsgExt( 'cascadeprotected', array('parsemag'), count($cascadeSources) ) . "\n$titles";
+
+ $this->addWikiText( $notice );
} else {
$this->addWikiText( wfMsg( 'protectedpagetext' ) );
}
@@ -900,17 +944,8 @@ class OutputPage {
if( is_string( $source ) ) {
$this->addWikiText( wfMsg( 'viewsourcetext' ) );
- if( $source === '' ) {
- global $wgTitle;
- if ( $wgTitle->getNamespace() == NS_MEDIAWIKI ) {
- $source = wfMsgWeirdKey ( $wgTitle->getText() );
- } else {
- $source = '';
- }
- }
$rows = $wgUser->getIntOption( 'rows' );
$cols = $wgUser->getIntOption( 'cols' );
-
$text = "\n";
$this->addHTML( $text );
@@ -921,32 +956,32 @@ class OutputPage {
$this->returnToMain( false );
}
- /** @obsolete */
+ /** @deprecated */
public function fatalError( $message ) {
throw new FatalError( $message );
}
- /** @obsolete */
+ /** @deprecated */
public function unexpectedValueError( $name, $val ) {
throw new FatalError( wfMsg( 'unexpected', $name, $val ) );
}
- /** @obsolete */
+ /** @deprecated */
public function fileCopyError( $old, $new ) {
throw new FatalError( wfMsg( 'filecopyerror', $old, $new ) );
}
- /** @obsolete */
+ /** @deprecated */
public function fileRenameError( $old, $new ) {
throw new FatalError( wfMsg( 'filerenameerror', $old, $new ) );
}
- /** @obsolete */
+ /** @deprecated */
public function fileDeleteError( $name ) {
throw new FatalError( wfMsg( 'filedeleteerror', $name ) );
}
- /** @obsolete */
+ /** @deprecated */
public function fileNotFoundError( $name ) {
throw new FatalError( wfMsg( 'filenotfound', $name ) );
}
@@ -1082,6 +1117,7 @@ class OutputPage {
$ret .= $sk->getHeadScripts();
$ret .= $this->mScripts;
$ret .= $sk->getUserStyles();
+ $ret .= $this->getHeadItems();
if ($wgUseTrackbacks && $this->isArticleRelated())
$ret .= $wgTitle->trackbackRDF();
@@ -1118,11 +1154,11 @@ class OutputPage {
"/<.*?>/" => '',
"/_/" => ' '
);
- $ret .= "mKeywords ))) . "\" />\n";
}
foreach ( $this->mLinktags as $tag ) {
- $ret .= ' $val ) {
$ret .= " $attr=\"" . htmlspecialchars( $val ) . "\"";
}
diff --git a/includes/PageHistory.php b/includes/PageHistory.php
index aea0f0ed..b1cf41f0 100644
--- a/includes/PageHistory.php
+++ b/includes/PageHistory.php
@@ -3,7 +3,6 @@
* Page history
*
* Split off from Article.php and Skin.php, 2003-12-22
- * @package MediaWiki
*/
/**
@@ -14,9 +13,7 @@
* Construct it by passing in an Article, and call $h->history() to print the
* history.
*
- * @package MediaWiki
*/
-
class PageHistory {
const DIR_PREV = 0;
const DIR_NEXT = 1;
@@ -33,7 +30,7 @@ class PageHistory {
* @param Article $article
* @returns nothing
*/
- function PageHistory($article) {
+ function __construct($article) {
global $wgUser;
$this->mArticle =& $article;
@@ -101,6 +98,8 @@ class PageHistory {
$wgOut->redirect( $wgTitle->getLocalURL( "action=history&limit={$limit}&dir=prev" ) );
return;
}
+
+ wfRunHooks( 'PageHistoryBeforeList', array( &$this->mArticle ) );
/**
* Do the list
@@ -159,7 +158,7 @@ class PageHistory {
'class' => 'historysubmit',
'type' => 'submit',
'accesskey' => wfMsg( 'accesskey-compareselectedversions' ),
- 'title' => wfMsg( 'tooltip-compareselectedversions' ),
+ 'title' => wfMsg( 'tooltip-compareselectedversions' ).' ['.wfMsg( 'accesskey-compareselectedversions' ).']',
'value' => wfMsg( 'compareselectedversions' ),
) ) )
: '';
@@ -179,7 +178,7 @@ class PageHistory {
* @return string HTML output for the row
*/
function historyLine( $row, $next, $counter = '', $notificationtimestamp = false, $latest = false, $firstInList = false ) {
- global $wgUser;
+ global $wgUser, $wgLang;
$rev = new Revision( $row );
$rev->setTitle( $this->mTitle );
@@ -199,31 +198,58 @@ class PageHistory {
if( $firstInList ) {
// We don't currently handle well changing the top revision's settings
$del = wfMsgHtml( 'rev-delundel' );
+ } else if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
+ // If revision was hidden from sysops
+ $del = wfMsgHtml( 'rev-delundel' );
} else {
$del = $this->mSkin->makeKnownLinkObj( $revdel,
wfMsg( 'rev-delundel' ),
'target=' . urlencode( $this->mTitle->getPrefixedDbkey() ) .
'&oldid=' . urlencode( $rev->getId() ) );
}
- $s .= "($del) ";
+ $s .= " ($del) ";
}
- $s .= " $link $user";
+ $s .= " $link";
+ #getUser is safe, but this avoids making the invalid untargeted contribs links
+ if( $row->rev_deleted & Revision::DELETED_USER ) {
+ $user = '' . wfMsg('rev-deleted-user') . '';
+ }
+ $s .= " $user";
if( $row->rev_minor_edit ) {
$s .= ' ' . wfElement( 'span', array( 'class' => 'minor' ), wfMsg( 'minoreditletter') );
}
- $s .= $this->mSkin->revComment( $rev );
+ if (!is_null($size = $rev->getSize())) {
+ if ($size == 0)
+ $stxt = wfMsgHtml('historyempty');
+ else
+ $stxt = wfMsgHtml('historysize', $wgLang->formatNum( $size ) );
+ $s .= " $stxt";
+ }
+
+ #getComment is safe, but this is better formatted
+ if( $rev->isDeleted( Revision::DELETED_COMMENT ) ) {
+ $s .= " " .
+ wfMsgHtml( 'rev-deleted-comment' ) . "";
+ } else {
+ $s .= $this->mSkin->revComment( $rev );
+ }
+
if ($notificationtimestamp && ($row->rev_timestamp >= $notificationtimestamp)) {
$s .= ' ' . wfMsgHtml( 'updatedmarker' ) . '';
}
+ #add blurb about text having been deleted
if( $row->rev_deleted & Revision::DELETED_TEXT ) {
$s .= ' ' . wfMsgHtml( 'deletedrev' );
}
if( $wgUser->isAllowed( 'rollback' ) && $latest ) {
$s .= ' '.$this->mSkin->generateRollback( $rev );
}
+
+ wfRunHooks( 'PageHistoryLineEnding', array( &$row , &$s ) );
+
$s .= "\n";
return $s;
@@ -332,7 +358,7 @@ class PageHistory {
function getLatestId() {
if( is_null( $this->mLatestId ) ) {
$id = $this->mTitle->getArticleID();
- $db =& wfGetDB(DB_SLAVE);
+ $db = wfGetDB(DB_SLAVE);
$this->mLatestId = $db->selectField( 'page',
"page_latest",
array( 'page_id' => $id ),
@@ -349,7 +375,7 @@ class PageHistory {
function fetchRevisions($limit, $offset, $direction) {
$fname = 'PageHistory::fetchRevisions';
- $dbr =& wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_SLAVE );
if ($direction == PageHistory::DIR_PREV)
list($dirs, $oper) = array("ASC", ">=");
@@ -365,8 +391,7 @@ class PageHistory {
$res = $dbr->select(
'revision',
- array('rev_id', 'rev_page', 'rev_text_id', 'rev_user', 'rev_comment', 'rev_user_text',
- 'rev_timestamp', 'rev_minor_edit', 'rev_deleted'),
+ Revision::selectFields(),
array_merge(array("rev_page=$page_id"), $offsets),
$fname,
array('ORDER BY' => "rev_timestamp $dirs",
@@ -391,7 +416,7 @@ class PageHistory {
if ($wgUser->isAnon() || !$wgShowUpdatedMarker)
return $this->mNotificationTimestamp = false;
- $dbr =& wfGetDB(DB_SLAVE);
+ $dbr = wfGetDB(DB_SLAVE);
$this->mNotificationTimestamp = $dbr->selectField(
'watchlist',
@@ -497,6 +522,9 @@ class PageHistory {
}
+/**
+ * @addtogroup Pager
+ */
class PageHistoryPager extends ReverseChronologicalPager {
public $mLastRow = false, $mPageHistory;
@@ -508,8 +536,7 @@ class PageHistoryPager extends ReverseChronologicalPager {
function getQueryInfo() {
return array(
'tables' => 'revision',
- 'fields' => array('rev_id', 'rev_page', 'rev_text_id', 'rev_user', 'rev_comment', 'rev_user_text',
- 'rev_timestamp', 'rev_minor_edit', 'rev_deleted'),
+ 'fields' => Revision::selectFields(),
'conds' => array('rev_page' => $this->mPageHistory->mTitle->getArticleID() ),
'options' => array( 'USE INDEX' => 'page_timestamp' )
);
diff --git a/includes/PageQueryPage.php b/includes/PageQueryPage.php
new file mode 100644
index 00000000..5b82ebf6
--- /dev/null
+++ b/includes/PageQueryPage.php
@@ -0,0 +1,26 @@
+namespace, $row->title );
+ return $skin->makeKnownLinkObj( $title,
+ htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) );
+ }
+}
+
+?>
diff --git a/includes/Pager.php b/includes/Pager.php
index 0987cc06..a475dc16 100644
--- a/includes/Pager.php
+++ b/includes/Pager.php
@@ -2,6 +2,7 @@
/**
* Basic pager interface.
+ * @addtogroup Pager
*/
interface Pager {
function getNavigationBar();
@@ -46,6 +47,8 @@ interface Pager {
* please see the examples in PageHistory.php and SpecialIpblocklist.php. You just need
* to override formatRow(), getQueryInfo() and getIndexField(). Don't forget to call the
* parent constructor if you override it.
+ *
+ * @addtogroup Pager
*/
abstract class IndexPager implements Pager {
public $mRequest;
@@ -69,17 +72,18 @@ abstract class IndexPager implements Pager {
public $mResult;
function __construct() {
- global $wgRequest;
+ global $wgRequest, $wgUser;
$this->mRequest = $wgRequest;
-
+
# NB: the offset is quoted, not validated. It is treated as an arbitrary string
# to support the widest variety of index types. Be careful outputting it into
# HTML!
$this->mOffset = $this->mRequest->getText( 'offset' );
- $this->mLimit = $this->mRequest->getInt( 'limit', $this->mDefaultLimit );
- if ( $this->mLimit <= 0 || $this->mLimit > 50000 ) {
- $this->mLimit = $this->mDefaultLimit;
- }
+
+ # Use consistent behavior for the limit options
+ $this->mDefaultLimit = intval( $wgUser->getOption( 'rclimit' ) );
+ list( $this->mLimit, /* $offset */ ) = $this->mRequest->getLimitOffset();
+
$this->mIsBackwards = ( $this->mRequest->getVal( 'dir' ) == 'prev' );
$this->mIndexField = $this->getIndexField();
$this->mDb = wfGetDB( DB_SLAVE );
@@ -386,8 +390,45 @@ abstract class IndexPager implements Pager {
abstract function getIndexField();
}
+
+/**
+ * IndexPager with an alphabetic list and a formatted navigation bar
+ * @addtogroup Pager
+ */
+abstract class AlphabeticPager extends IndexPager {
+ public $mDefaultDirection = false;
+
+ function __construct() {
+ parent::__construct();
+ }
+
+ /**
+ * Shamelessly stolen bits from ReverseChronologicalPager, d
+ * didn't want to do class magic as may be still revamped
+ */
+ function getNavigationBar() {
+ global $wgLang;
+
+ $linkTexts = array(
+ 'prev' => wfMsgHtml( "prevn", $this->mLimit ),
+ 'next' => wfMsgHtml( 'nextn', $this->mLimit ),
+ 'first' => wfMsgHtml('page_first'), /* Introduced the message */
+ 'last' => wfMsgHtml( 'page_last' ) /* Introduced the message */
+ );
+
+ $pagingLinks = $this->getPagingLinks( $linkTexts );
+ $limitLinks = $this->getLimitLinks();
+ $limits = implode( ' | ', $limitLinks );
+
+ $this->mNavigationBar = "({$pagingLinks['first']} | {$pagingLinks['last']}) " . wfMsgHtml("viewprevnext", $pagingLinks['prev'], $pagingLinks['next'], $limits);
+ return $this->mNavigationBar;
+
+ }
+}
+
/**
* IndexPager with a formatted navigation bar
+ * @addtogroup Pager
*/
abstract class ReverseChronologicalPager extends IndexPager {
public $mDefaultDirection = true;
@@ -413,13 +454,15 @@ abstract class ReverseChronologicalPager extends IndexPager {
$limitLinks = $this->getLimitLinks();
$limits = implode( ' | ', $limitLinks );
- $this->mNavigationBar = "({$pagingLinks['first']} | {$pagingLinks['last']}) " . wfMsgHtml("viewprevnext", $pagingLinks['prev'], $pagingLinks['next'], $limits);
+ $this->mNavigationBar = "({$pagingLinks['first']} | {$pagingLinks['last']}) " .
+ wfMsgHtml("viewprevnext", $pagingLinks['prev'], $pagingLinks['next'], $limits);
return $this->mNavigationBar;
}
}
/**
* Table-based display with a user-selectable sort order
+ * @addtogroup Pager
*/
abstract class TablePager extends IndexPager {
var $mSort;
diff --git a/includes/Parser.php b/includes/Parser.php
index 8d67279d..8e36e170 100644
--- a/includes/Parser.php
+++ b/includes/Parser.php
@@ -2,8 +2,7 @@
/**
* File for Parser and related classes
*
- * @package MediaWiki
- * @subpackage Parser
+ * @addtogroup Parser
*/
/**
@@ -57,9 +56,10 @@ define( 'MW_COLON_STATE_COMMENTDASH', 6 );
define( 'MW_COLON_STATE_COMMENTDASHDASH', 7 );
/**
- * PHP Parser
- *
- * Processes wiki markup
+ * PHP Parser - Processes wiki markup (which uses a more user-friendly
+ * syntax, such as "[[link]]" for making links), and provides a one-way
+ * transformation of that wiki markup it into XHTML output / markup
+ * (which in turn the browser understands, and can display).
*
*
* There are four main entry points into the Parser class:
@@ -86,10 +86,11 @@ define( 'MW_COLON_STATE_COMMENTDASHDASH', 7 );
* * only within ParserOptions
*
*
- * @package MediaWiki
+ * @addtogroup Parser
*/
class Parser
{
+ const VERSION = MW_PARSER_VERSION;
/**#@+
* @private
*/
@@ -114,7 +115,7 @@ class Parser
$ot, // Shortcut alias, see setOutputType()
$mRevisionId, // ID to display in {{REVISIONID}} tags
$mRevisionTimestamp, // The timestamp of the specified revision ID
- $mRevIdForTs; // The revision ID which was used to fetch the timestamp
+ $mRevIdForTs; // The revision ID which was used to fetch the timestamp
/**#@-*/
@@ -162,6 +163,7 @@ class Parser
$this->setFunctionHook( 'numberofarticles', array( 'CoreParserFunctions', 'numberofarticles' ), SFH_NO_HASH );
$this->setFunctionHook( 'numberoffiles', array( 'CoreParserFunctions', 'numberoffiles' ), SFH_NO_HASH );
$this->setFunctionHook( 'numberofadmins', array( 'CoreParserFunctions', 'numberofadmins' ), SFH_NO_HASH );
+ $this->setFunctionHook( 'numberofedits', array( 'CoreParserFunctions', 'numberofedits' ), SFH_NO_HASH );
$this->setFunctionHook( 'language', array( 'CoreParserFunctions', 'language' ), SFH_NO_HASH );
$this->setFunctionHook( 'padleft', array( 'CoreParserFunctions', 'padleft' ), SFH_NO_HASH );
$this->setFunctionHook( 'padright', array( 'CoreParserFunctions', 'padright' ), SFH_NO_HASH );
@@ -211,7 +213,7 @@ class Parser
'titles' => array()
);
$this->mRevisionTimestamp = $this->mRevisionId = null;
-
+
/**
* Prefix for temporary replacement strings for the multipass parser.
* \x07 should never appear in input as it's disallowed in XML.
@@ -262,7 +264,6 @@ class Parser
* Convert wikitext to HTML
* Do not call this function recursively.
*
- * @private
* @param string $text Text we want to parse
* @param Title &$title A title object
* @param array $options
@@ -271,7 +272,7 @@ class Parser
* @param int $revid number to pass in {{REVISIONID}}
* @return ParserOutput a ParserOutput
*/
- function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null ) {
+ public function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null ) {
/**
* First pass--just handle sections, pass the rest off
* to internalParse() which does all the real work.
@@ -724,7 +725,7 @@ class Parser
$descriptorspec = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
- 2 => array('file', '/dev/null', 'a')
+ 2 => array('file', '/dev/null', 'a') // FIXME: this line in UNIX-specific, it generates a warning on Windows, because /dev/null is not a valid Windows file.
);
$pipes = array();
$process = proc_open("$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes);
@@ -872,7 +873,7 @@ class Parser
array_push ( $td_history , false );
array_push ( $last_tag_history , '' );
}
- else if ( $first_character == '|' || $first_character == '!' || substr ( $line , 0 , 2 ) == '|+' ) {
+ else if ( $first_character == '|' || $first_character == '!' || substr ( $line , 0 , 2 ) == '|+' ) {
// This might be cell elements, td, th or captions
if ( substr ( $line , 0 , 2 ) == '|+' ) {
$first_character = '+';
@@ -1002,6 +1003,7 @@ class Parser
$text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) );
$text = $this->replaceVariables( $text, $args );
+ wfRunHooks( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
// Tables need to come after variable replacement for things to work
// properly; putting them before other transformations should keep
@@ -1086,7 +1088,7 @@ class Parser
}
$url = wfMsg( $urlmsg, $id);
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
$la = $sk->getExternalLinkAttributes( $url, $keyword.$id );
$text = "{$keyword} {$id}";
}
@@ -1287,7 +1289,8 @@ class Parser
$output .= '';
if ($state == 'bi')
$output .= '';
- if ($state == 'both')
+ # There might be lonely ''''', so make sure we have a buffer
+ if ($state == 'both' && $buffer)
$output .= ''.$buffer.'';
return $output;
}
@@ -1306,7 +1309,7 @@ class Parser
$fname = 'Parser::replaceExternalLinks';
wfProfileIn( $fname );
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
$bits = preg_split( EXT_LINK_BRACKETED, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
@@ -1395,7 +1398,7 @@ class Parser
$s = array_shift( $bits );
$i = 0;
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
while ( $i < count( $bits ) ){
$protocol = $bits[$i++];
@@ -1468,7 +1471,7 @@ class Parser
* @param string
* @return string
* @static
- * @fixme This can merge genuinely required bits in the path or query string,
+ * @todo This can merge genuinely required bits in the path or query string,
* breaking legit URLs. A proper fix would treat the various parts of
* the URL differently; as a workaround, just use the output for
* statistical records, not for actual linking/output.
@@ -1503,7 +1506,7 @@ class Parser
* @private
*/
function maybeMakeExternalImage( $url ) {
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
$imagesfrom = $this->mOptions->getAllowExternalImagesFrom();
$imagesexception = !empty($imagesfrom);
$text = false;
@@ -1533,7 +1536,7 @@ class Parser
# the % is needed to support urlencoded titles as well
if ( !$tc ) { $tc = Title::legalChars() . '#%'; }
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
#split the entire text string on occurences of [[
$a = explode( '[[', ' ' . $s );
@@ -1552,7 +1555,6 @@ class Parser
$e2 = wfMsgForContent( 'linkprefix' );
$useLinkPrefixExtension = $wgContLang->linkPrefixExtension();
-
if( is_null( $this->mTitle ) ) {
throw new MWException( __METHOD__.": \$this->mTitle is null\n" );
}
@@ -1569,10 +1571,11 @@ class Parser
$prefix = '';
}
- if($wgContLang->hasVariants())
+ if($wgContLang->hasVariants()) {
$selflink = $wgContLang->convertLinkToAllVariants($this->mTitle->getPrefixedText());
- else
+ } else {
$selflink = array($this->mTitle->getPrefixedText());
+ }
$useSubpages = $this->areSubpagesAllowed();
wfProfileOut( $fname.'-setup' );
@@ -1626,7 +1629,7 @@ class Parser
$might_be_img = true;
$text = $m[2];
if ( strpos( $m[1], '%' ) !== false ) {
- $m[1] = urldecode($m[1]);
+ $m[1] = urldecode($m[1]);
}
$trail = "";
} else { # Invalid form; output directly
@@ -1640,7 +1643,7 @@ class Parser
# Don't allow internal links to pages containing
# PROTO: where PROTO is a valid URL protocol; these
# should be external links.
- if (preg_match('/^(\b(?:' . wfUrlProtocols() . '))/', $m[1])) {
+ if (preg_match('/^\b(?:' . wfUrlProtocols() . ')/', $m[1])) {
$s .= $prefix . '[[' . $line ;
continue;
}
@@ -1723,8 +1726,8 @@ class Parser
wfProfileIn( "$fname-interwiki" );
if( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
$this->mOutput->addLanguageLink( $nt->getFullText() );
- $s = rtrim($s . "\n");
- $s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
+ $s = rtrim($s . $prefix);
+ $s .= trim($trail, "\n") == '' ? '': $prefix . $trail;
wfProfileOut( "$fname-interwiki" );
continue;
}
@@ -1778,11 +1781,12 @@ class Parser
}
}
- if( ( in_array( $nt->getPrefixedText(), $selflink ) ) &&
- ( $nt->getFragment() === '' ) ) {
- # Self-links are handled specially; generally de-link and change to bold.
- $s .= $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail );
- continue;
+ # Self-link checking
+ if( $nt->getFragment() === '' ) {
+ if( in_array( $nt->getPrefixedText(), $selflink, true ) ) {
+ $s .= $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail );
+ continue;
+ }
}
# Special and Media are pseudo-namespaces; no pages actually exist in them
@@ -1862,7 +1866,7 @@ class Parser
*/
function makeKnownLinkHolder( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
list( $inside, $trail ) = Linker::splitTrail( $trail );
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
$link = $sk->makeKnownLinkObj( $nt, $text, $query, $inside, $prefix );
return $this->armorLinks( $link ) . $trail;
}
@@ -1923,9 +1927,9 @@ class Parser
# Look at the first character
if( $target != '' && $target{0} == '/' ) {
# / at end means we don't want the slash to be shown
- if( substr( $target, -1, 1 ) == '/' ) {
- $target = substr( $target, 1, -1 );
- $noslash = $target;
+ $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m );
+ if( $trailingSlashes ) {
+ $noslash = $target = substr( $target, 1, -strlen($m[0][0]) );
} else {
$noslash = substr( $target, 1 );
}
@@ -2134,9 +2138,9 @@ class Parser
wfProfileIn( "$fname-paragraph" );
# No prefix (not in list)--go to paragraph mode
// XXX: use a stack for nestable elements like span, table and div
- $openmatch = preg_match('/(
mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );
if ( $openmatch or $closematch ) {
$paragraphStack = false;
@@ -2538,6 +2542,8 @@ class Parser
return $varCache[$index] = $wgContLang->formatNum( SiteStats::pages() );
case 'numberofadmins':
return $varCache[$index] = $wgContLang->formatNum( SiteStats::admins() );
+ case 'numberofedits':
+ return $varCache[$index] = $wgContLang->formatNum( SiteStats::edits() );
case 'currenttimestamp':
return $varCache[$index] = wfTimestampNow();
case 'localtimestamp':
@@ -2852,7 +2858,7 @@ class Parser
return $text;
}
-
+
/// Clean up argument array - refactored in 1.9 so parserfunctions can use it, too.
static function createAssocArgs( $args ) {
$assocArgs = array();
@@ -2872,10 +2878,10 @@ class Parser
}
}
}
-
+
return $assocArgs;
}
-
+
/**
* Return the text of a template, after recursively
* replacing any variables or templates within the template.
@@ -2888,7 +2894,7 @@ class Parser
* @private
*/
function braceSubstitution( $piece ) {
- global $wgContLang, $wgLang, $wgAllowDisplayTitle;
+ global $wgContLang, $wgLang, $wgAllowDisplayTitle, $wgNonincludableNamespaces;
$fname = __METHOD__ /*. '-L' . count( $this->mArgStack )*/;
wfProfileIn( $fname );
wfProfileIn( __METHOD__.'-setup' );
@@ -3031,6 +3037,19 @@ class Parser
} else {
# set $text to cached message.
$text = $linestart . $this->mTemplates[$piece['title']];
+ #treat title for cached page the same as others
+ $ns = NS_TEMPLATE;
+ $subpage = '';
+ $part1 = $this->maybeDoSubpageLink( $part1, $subpage );
+ if ($subpage !== '') {
+ $ns = $this->mTitle->getNamespace();
+ }
+ $title = Title::newFromText( $part1, $ns );
+ //used by include size checking
+ $titleText = $title->getPrefixedText();
+ //used by edit section links
+ $replaceHeadings = true;
+
}
}
@@ -3066,6 +3085,9 @@ class Parser
$isHTML = true;
$this->disableCache();
}
+ } else if ( $wgNonincludableNamespaces && in_array( $title->getNamespace(), $wgNonincludableNamespaces ) ) {
+ $found = false; //access denied
+ wfDebug( "$fname: template inclusion denied for " . $title->getPrefixedDBkey() );
} else {
$articleContent = $this->fetchTemplate( $title );
if ( $articleContent !== false ) {
@@ -3155,7 +3177,7 @@ class Parser
# If the template begins with a table or block-level
# element, it should be treated as beginning a new line.
- if (!$piece['lineStart'] && preg_match('/^({\\||:|;|#|\*)/', $text)) /*}*/{
+ if (!$piece['lineStart'] && preg_match('/^(?:{\\||:|;|#|\*)/', $text)) /*}*/{
$text = "\n" . $text;
}
} elseif ( !$noargs ) {
@@ -3271,7 +3293,7 @@ class Parser
return wfMsg('scarytranscludedisabled');
$url = $title->getFullUrl( "action=$action" );
-
+
if (strlen($url) > 255)
return wfMsg('scarytranscludetoolong');
return $this->fetchScaryTemplateMaybeFromCache($url);
@@ -3279,7 +3301,7 @@ class Parser
function fetchScaryTemplateMaybeFromCache($url) {
global $wgTranscludeCacheExpiry;
- $dbr =& wfGetDB(DB_SLAVE);
+ $dbr = wfGetDB(DB_SLAVE);
$obj = $dbr->selectRow('transcache', array('tc_time', 'tc_contents'),
array('tc_url' => $url));
if ($obj) {
@@ -3294,7 +3316,7 @@ class Parser
if (!$text)
return wfMsg('scarytranscludefailed', $url);
- $dbw =& wfGetDB(DB_MASTER);
+ $dbw = wfGetDB(DB_MASTER);
$dbw->replace('transcache', array('tc_url'), array(
'tc_url' => $url,
'tc_time' => time(),
@@ -3395,7 +3417,7 @@ class Parser
global $wgMaxTocLevel, $wgContLang;
$doNumberHeadings = $this->mOptions->getNumberHeadings();
- if( !$this->mTitle->userCanEdit() ) {
+ if( !$this->mTitle->quickUserCan( 'edit' ) ) {
$showEditLink = 0;
} else {
$showEditLink = $this->mOptions->getEditSection();
@@ -3437,7 +3459,7 @@ class Parser
}
# We need this to perform operations on the HTML
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
# headline counter
$headlineCount = 0;
@@ -3723,11 +3745,7 @@ class Parser
}
# Trim trailing whitespace
- # __END__ tag allows for trailing
- # whitespace to be deliberately included
$text = rtrim( $text );
- $mw =& MagicWord::get( 'end' );
- $mw->matchAndRemove( $text );
return $text;
}
@@ -3847,7 +3865,7 @@ class Parser
wfProfileIn($fname);
- if ( $wgTitle ) {
+ if ( $wgTitle && !( $wgTitle instanceof FakeTitle ) ) {
$this->mTitle = $wgTitle;
} else {
$this->mTitle = Title::newFromText('msg');
@@ -3966,12 +3984,12 @@ class Parser
$pdbks = array();
$colours = array();
- $sk =& $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin();
$linkCache =& LinkCache::singleton();
if ( !empty( $this->mLinkHolders['namespaces'] ) ) {
wfProfileIn( $fname.'-check' );
- $dbr =& wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_SLAVE );
$page = $dbr->tableName( 'page' );
$threshold = $wgUser->getOption('stubthreshold');
@@ -4161,8 +4179,8 @@ class Parser
if(isset($categoryMap[$vardbk])){
$oldkey = $categoryMap[$vardbk];
if($oldkey != $vardbk)
- $varCategories[$oldkey]=$vardbk;
- }
+ $varCategories[$oldkey]=$vardbk;
+ }
}
// rebuild the categories in original order (if there are replacements)
@@ -4303,6 +4321,7 @@ class Parser
*/
function renderImageGallery( $text, $params ) {
$ig = new ImageGallery();
+ $ig->setContextTitle( $this->mTitle );
$ig->setShowBytes( false );
$ig->setShowFilename( false );
$ig->setParsing();
@@ -4314,6 +4333,15 @@ class Parser
$caption = $this->replaceInternalLinks( $caption );
$ig->setCaptionHtml( $caption );
}
+ if( isset( $params['perrow'] ) ) {
+ $ig->setPerRow( $params['perrow'] );
+ }
+ if( isset( $params['widths'] ) ) {
+ $ig->setWidths( $params['widths'] );
+ }
+ if( isset( $params['heights'] ) ) {
+ $ig->setHeights( $params['heights'] );
+ }
$lines = explode( "\n", $text );
foreach ( $lines as $line ) {
@@ -4359,10 +4387,8 @@ class Parser
* Parse image options text and use it to make an image
*/
function makeImage( $nt, $options ) {
- global $wgUseImageResize, $wgDjvuRenderer;
-
- $align = '';
-
+ # @TODO: let the MediaHandler specify its transform parameters
+ #
# Check if the options text is of the form "options|alt text"
# Options are:
# * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
@@ -4372,61 +4398,74 @@ class Parser
# * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
# * center center the image
# * framed Keep original image size, no magnify-button.
-
- $part = explode( '|', $options);
-
+ # vertical-align values (no % or length right now):
+ # * baseline
+ # * sub
+ # * super
+ # * top
+ # * text-top
+ # * middle
+ # * bottom
+ # * text-bottom
+
+
+ $part = array_map( 'trim', explode( '|', $options) );
+
+ $mwAlign = array();
+ $alignments = array( 'left', 'right', 'center', 'none', 'baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom' );
+ foreach ( $alignments as $alignment ) {
+ $mwAlign[$alignment] =& MagicWord::get( 'img_'.$alignment );
+ }
$mwThumb =& MagicWord::get( 'img_thumbnail' );
$mwManualThumb =& MagicWord::get( 'img_manualthumb' );
- $mwLeft =& MagicWord::get( 'img_left' );
- $mwRight =& MagicWord::get( 'img_right' );
- $mwNone =& MagicWord::get( 'img_none' );
$mwWidth =& MagicWord::get( 'img_width' );
- $mwCenter =& MagicWord::get( 'img_center' );
$mwFramed =& MagicWord::get( 'img_framed' );
$mwPage =& MagicWord::get( 'img_page' );
$caption = '';
- $width = $height = $framed = $thumb = false;
- $page = null;
+ $params = array();
+ $framed = $thumb = false;
$manual_thumb = '' ;
+ $align = $valign = '';
+ $sk = $this->mOptions->getSkin();
foreach( $part as $val ) {
- if ( $wgUseImageResize && ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
+ if ( !is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
$thumb=true;
} elseif ( ! is_null( $match = $mwManualThumb->matchVariableStartToEnd($val) ) ) {
# use manually specified thumbnail
$thumb=true;
$manual_thumb = $match;
- } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
- # remember to set an alignment, don't render immediately
- $align = 'right';
- } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
- # remember to set an alignment, don't render immediately
- $align = 'left';
- } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
- # remember to set an alignment, don't render immediately
- $align = 'center';
- } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
- # remember to set an alignment, don't render immediately
- $align = 'none';
- } elseif ( isset( $wgDjvuRenderer ) && $wgDjvuRenderer
- && ! is_null( $match = $mwPage->matchVariableStartToEnd($val) ) ) {
- # Select a page in a multipage document
- $page = $match;
- } elseif ( $wgUseImageResize && !$width && ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
- wfDebug( "img_width match: $match\n" );
- # $match is the image width in pixels
- $m = array();
- if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
- $width = intval( $m[1] );
- $height = intval( $m[2] );
+ } else {
+ foreach( $alignments as $alignment ) {
+ if ( ! is_null( $mwAlign[$alignment]->matchVariableStartToEnd($val) ) ) {
+ switch ( $alignment ) {
+ case 'left': case 'right': case 'center': case 'none':
+ $align = $alignment; break;
+ default:
+ $valign = $alignment;
+ }
+ continue 2;
+ }
+ }
+ if ( ! is_null( $match = $mwPage->matchVariableStartToEnd($val) ) ) {
+ # Select a page in a multipage document
+ $params['page'] = $match;
+ } elseif ( !isset( $params['width'] ) && ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
+ wfDebug( "img_width match: $match\n" );
+ # $match is the image width in pixels
+ $m = array();
+ if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
+ $params['width'] = intval( $m[1] );
+ $params['height'] = intval( $m[2] );
+ } else {
+ $params['width'] = intval($match);
+ }
+ } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
+ $framed=true;
} else {
- $width = intval($match);
+ $caption = $val;
}
- } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
- $framed=true;
- } else {
- $caption = $val;
}
}
# Strip bad stuff out of the alt text
@@ -4439,8 +4478,7 @@ class Parser
$alt = Sanitizer::stripAllTags( $alt );
# Linker does the rest
- $sk =& $this->mOptions->getSkin();
- return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $width, $height, $framed, $thumb, $manual_thumb, $page );
+ return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $params, $framed, $thumb, $manual_thumb, $valign );
}
/**
@@ -4518,24 +4556,6 @@ class Parser
$uniq = preg_quote( $this->uniqPrefix(), '/' );
$comment = "(?:$uniq-!--.*?QINU)";
$secs = preg_split(
- /*
- "/
- ^(
- (?:$comment|<\/?noinclude>)* # Initial comments will be stripped
- (?:
- (=+) # Should this be limited to 6?
- .+? # Section title...
- \\2 # Ending = count must match start
- |
- ^
-
- .*?
- <\/h\\3\s*>
- )
- (?:$comment|<\/?noinclude>|\s+)* # Trailing whitespace ok
- )$
- /mix",
- */
"/
(
^
@@ -4559,7 +4579,8 @@ class Parser
// "Section 0" returns the content before any other section.
$rv = $secs[0];
} else {
- $rv = "";
+ //track missing section, will replace if found.
+ $rv = $newtext;
}
} elseif( $mode == "replace" ) {
if( $section == 0 ) {
@@ -4614,8 +4635,10 @@ class Parser
}
}
}
- # reinsert stripped tags
- $rv = trim( $stripState->unstripBoth( $rv ) );
+ if (is_string($rv))
+ # reinsert stripped tags
+ $rv = trim( $stripState->unstripBoth( $rv ) );
+
return $rv;
}
@@ -4628,34 +4651,35 @@ class Parser
*
* @param $text String: text to look in
* @param $section Integer: section number
+ * @param $deftext: default to return if section is not found
* @return string text of the requested section
*/
- function getSection( $text, $section ) {
- return $this->extractSections( $text, $section, "get" );
+ public function getSection( $text, $section, $deftext='' ) {
+ return $this->extractSections( $text, $section, "get", $deftext );
}
- function replaceSection( $oldtext, $section, $text ) {
+ public function replaceSection( $oldtext, $section, $text ) {
return $this->extractSections( $oldtext, $section, "replace", $text );
}
/**
- * Get the timestamp associated with the current revision, adjusted for
+ * Get the timestamp associated with the current revision, adjusted for
* the default server-local timestamp
*/
function getRevisionTimestamp() {
if ( is_null( $this->mRevisionTimestamp ) ) {
wfProfileIn( __METHOD__ );
global $wgContLang;
- $dbr =& wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_SLAVE );
$timestamp = $dbr->selectField( 'revision', 'rev_timestamp',
array( 'rev_id' => $this->mRevisionId ), __METHOD__ );
-
+
// Normalize timestamp to internal MW format for timezone processing.
// This has the added side-effect of replacing a null value with
// the current time, which gives us more sensible behavior for
// previews.
$timestamp = wfTimestamp( TS_MW, $timestamp );
-
+
// The cryptic '' timezone parameter tells to use the site-default
// timezone offset instead of the user settings.
//
@@ -4663,12 +4687,12 @@ class Parser
// to other users, and potentially even used inside links and such,
// it needs to be consistent for all visitors.
$this->mRevisionTimestamp = $wgContLang->userAdjust( $timestamp, '' );
-
+
wfProfileOut( __METHOD__ );
}
return $this->mRevisionTimestamp;
}
-
+
/**
* Mutator for $mDefaultSort
*
@@ -4677,7 +4701,7 @@ class Parser
public function setDefaultSort( $sort ) {
$this->mDefaultSort = $sort;
}
-
+
/**
* Accessor for $mDefaultSort
* Will use the title/prefixed title if none is set
@@ -4693,241 +4717,13 @@ class Parser
: $this->mTitle->getPrefixedText();
}
}
-
-}
-
-/**
- * @todo document
- * @package MediaWiki
- */
-class ParserOutput
-{
- var $mText, # The output text
- $mLanguageLinks, # List of the full text of language links, in the order they appear
- $mCategories, # Map of category names to sort keys
- $mContainsOldMagic, # Boolean variable indicating if the input contained variables like {{CURRENTDAY}}
- $mCacheTime, # Time when this object was generated, or -1 for uncacheable. Used in ParserCache.
- $mVersion, # Compatibility check
- $mTitleText, # title text of the chosen language variant
- $mLinks, # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken.
- $mTemplates, # 2-D map of NS/DBK to ID for the template references. ID=zero for broken.
- $mImages, # DB keys of the images used, in the array key only
- $mExternalLinks, # External link URLs, in the key only
- $mHTMLtitle, # Display HTML title
- $mSubtitle, # Additional subtitle
- $mNewSection, # Show a new section link?
- $mNoGallery; # No gallery on category page? (__NOGALLERY__)
-
- function ParserOutput( $text = '', $languageLinks = array(), $categoryLinks = array(),
- $containsOldMagic = false, $titletext = '' )
- {
- $this->mText = $text;
- $this->mLanguageLinks = $languageLinks;
- $this->mCategories = $categoryLinks;
- $this->mContainsOldMagic = $containsOldMagic;
- $this->mCacheTime = '';
- $this->mVersion = MW_PARSER_VERSION;
- $this->mTitleText = $titletext;
- $this->mLinks = array();
- $this->mTemplates = array();
- $this->mImages = array();
- $this->mExternalLinks = array();
- $this->mHTMLtitle = "" ;
- $this->mSubtitle = "" ;
- $this->mNewSection = false;
- $this->mNoGallery = false;
- }
- function getText() { return $this->mText; }
- function &getLanguageLinks() { return $this->mLanguageLinks; }
- function getCategoryLinks() { return array_keys( $this->mCategories ); }
- function &getCategories() { return $this->mCategories; }
- function getCacheTime() { return $this->mCacheTime; }
- function getTitleText() { return $this->mTitleText; }
- function &getLinks() { return $this->mLinks; }
- function &getTemplates() { return $this->mTemplates; }
- function &getImages() { return $this->mImages; }
- function &getExternalLinks() { return $this->mExternalLinks; }
- function getNoGallery() { return $this->mNoGallery; }
- function getSubtitle() { return $this->mSubtitle; }
-
- function containsOldMagic() { return $this->mContainsOldMagic; }
- function setText( $text ) { return wfSetVar( $this->mText, $text ); }
- function setLanguageLinks( $ll ) { return wfSetVar( $this->mLanguageLinks, $ll ); }
- function setCategoryLinks( $cl ) { return wfSetVar( $this->mCategories, $cl ); }
- function setContainsOldMagic( $com ) { return wfSetVar( $this->mContainsOldMagic, $com ); }
- function setCacheTime( $t ) { return wfSetVar( $this->mCacheTime, $t ); }
- function setTitleText( $t ) { return wfSetVar($this->mTitleText, $t); }
- function setSubtitle( $st ) { return wfSetVar( $this->mSubtitle, $st ); }
-
- function addCategory( $c, $sort ) { $this->mCategories[$c] = $sort; }
- function addImage( $name ) { $this->mImages[$name] = 1; }
- function addLanguageLink( $t ) { $this->mLanguageLinks[] = $t; }
- function addExternalLink( $url ) { $this->mExternalLinks[$url] = 1; }
-
- function setNewSection( $value ) {
- $this->mNewSection = (bool)$value;
- }
- function getNewSection() {
- return (bool)$this->mNewSection;
- }
-
- function addLink( $title, $id = null ) {
- $ns = $title->getNamespace();
- $dbk = $title->getDBkey();
- if ( !isset( $this->mLinks[$ns] ) ) {
- $this->mLinks[$ns] = array();
- }
- if ( is_null( $id ) ) {
- $id = $title->getArticleID();
- }
- $this->mLinks[$ns][$dbk] = $id;
- }
-
- function addTemplate( $title, $id ) {
- $ns = $title->getNamespace();
- $dbk = $title->getDBkey();
- if ( !isset( $this->mTemplates[$ns] ) ) {
- $this->mTemplates[$ns] = array();
- }
- $this->mTemplates[$ns][$dbk] = $id;
- }
-
- /**
- * Return true if this cached output object predates the global or
- * per-article cache invalidation timestamps, or if it comes from
- * an incompatible older version.
- *
- * @param string $touched the affected article's last touched timestamp
- * @return bool
- * @public
- */
- function expired( $touched ) {
- global $wgCacheEpoch;
- return $this->getCacheTime() == -1 || // parser says it's uncacheable
- $this->getCacheTime() < $touched ||
- $this->getCacheTime() <= $wgCacheEpoch ||
- !isset( $this->mVersion ) ||
- version_compare( $this->mVersion, MW_PARSER_VERSION, "lt" );
- }
}
/**
- * Set options of the Parser
- * @todo document
- * @package MediaWiki
+ * @todo document, briefly.
+ * @addtogroup Parser
*/
-class ParserOptions
-{
- # All variables are supposed to be private in theory, although in practise this is not the case.
- var $mUseTeX; # Use texvc to expand tags
- var $mUseDynamicDates; # Use DateFormatter to format dates
- var $mInterwikiMagic; # Interlanguage links are removed and returned in an array
- var $mAllowExternalImages; # Allow external images inline
- var $mAllowExternalImagesFrom; # If not, any exception?
- var $mSkin; # Reference to the preferred skin
- var $mDateFormat; # Date format index
- var $mEditSection; # Create "edit section" links
- var $mNumberHeadings; # Automatically number headings
- var $mAllowSpecialInclusion; # Allow inclusion of special pages
- var $mTidy; # Ask for tidy cleanup
- var $mInterfaceMessage; # Which lang to call for PLURAL and GRAMMAR
- var $mMaxIncludeSize; # Maximum size of template expansions, in bytes
- var $mRemoveComments; # Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
-
- var $mUser; # Stored user object, just used to initialise the skin
-
- function getUseTeX() { return $this->mUseTeX; }
- function getUseDynamicDates() { return $this->mUseDynamicDates; }
- function getInterwikiMagic() { return $this->mInterwikiMagic; }
- function getAllowExternalImages() { return $this->mAllowExternalImages; }
- function getAllowExternalImagesFrom() { return $this->mAllowExternalImagesFrom; }
- function getEditSection() { return $this->mEditSection; }
- function getNumberHeadings() { return $this->mNumberHeadings; }
- function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; }
- function getTidy() { return $this->mTidy; }
- function getInterfaceMessage() { return $this->mInterfaceMessage; }
- function getMaxIncludeSize() { return $this->mMaxIncludeSize; }
- function getRemoveComments() { return $this->mRemoveComments; }
-
- function &getSkin() {
- if ( !isset( $this->mSkin ) ) {
- $this->mSkin = $this->mUser->getSkin();
- }
- return $this->mSkin;
- }
-
- function getDateFormat() {
- if ( !isset( $this->mDateFormat ) ) {
- $this->mDateFormat = $this->mUser->getDatePreference();
- }
- return $this->mDateFormat;
- }
-
- function setUseTeX( $x ) { return wfSetVar( $this->mUseTeX, $x ); }
- function setUseDynamicDates( $x ) { return wfSetVar( $this->mUseDynamicDates, $x ); }
- function setInterwikiMagic( $x ) { return wfSetVar( $this->mInterwikiMagic, $x ); }
- function setAllowExternalImages( $x ) { return wfSetVar( $this->mAllowExternalImages, $x ); }
- function setAllowExternalImagesFrom( $x ) { return wfSetVar( $this->mAllowExternalImagesFrom, $x ); }
- function setDateFormat( $x ) { return wfSetVar( $this->mDateFormat, $x ); }
- function setEditSection( $x ) { return wfSetVar( $this->mEditSection, $x ); }
- function setNumberHeadings( $x ) { return wfSetVar( $this->mNumberHeadings, $x ); }
- function setAllowSpecialInclusion( $x ) { return wfSetVar( $this->mAllowSpecialInclusion, $x ); }
- function setTidy( $x ) { return wfSetVar( $this->mTidy, $x); }
- function setSkin( $x ) { $this->mSkin = $x; }
- function setInterfaceMessage( $x ) { return wfSetVar( $this->mInterfaceMessage, $x); }
- function setMaxIncludeSize( $x ) { return wfSetVar( $this->mMaxIncludeSize, $x ); }
- function setRemoveComments( $x ) { return wfSetVar( $this->mRemoveComments, $x ); }
-
- function ParserOptions( $user = null ) {
- $this->initialiseFromUser( $user );
- }
-
- /**
- * Get parser options
- * @static
- */
- static function newFromUser( $user ) {
- return new ParserOptions( $user );
- }
-
- /** Get user options */
- function initialiseFromUser( $userInput ) {
- global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages;
- global $wgAllowExternalImagesFrom, $wgAllowSpecialInclusion, $wgMaxArticleSize;
- $fname = 'ParserOptions::initialiseFromUser';
- wfProfileIn( $fname );
- if ( !$userInput ) {
- global $wgUser;
- if ( isset( $wgUser ) ) {
- $user = $wgUser;
- } else {
- $user = new User;
- }
- } else {
- $user =& $userInput;
- }
-
- $this->mUser = $user;
-
- $this->mUseTeX = $wgUseTeX;
- $this->mUseDynamicDates = $wgUseDynamicDates;
- $this->mInterwikiMagic = $wgInterwikiMagic;
- $this->mAllowExternalImages = $wgAllowExternalImages;
- $this->mAllowExternalImagesFrom = $wgAllowExternalImagesFrom;
- $this->mSkin = null; # Deferred
- $this->mDateFormat = null; # Deferred
- $this->mEditSection = true;
- $this->mNumberHeadings = $user->getOption( 'numberheadings' );
- $this->mAllowSpecialInclusion = $wgAllowSpecialInclusion;
- $this->mTidy = false;
- $this->mInterfaceMessage = false;
- $this->mMaxIncludeSize = $wgMaxArticleSize * 1024;
- $this->mRemoveComments = true;
- wfProfileOut( $fname );
- }
-}
-
class OnlyIncludeReplacer {
var $output = '';
@@ -4940,6 +4736,10 @@ class OnlyIncludeReplacer {
}
}
+/**
+ * @todo document, briefly.
+ * @addtogroup Parser
+ */
class StripState {
var $general, $nowiki;
diff --git a/includes/ParserCache.php b/includes/ParserCache.php
index 37a42b7f..1489fcf9 100644
--- a/includes/ParserCache.php
+++ b/includes/ParserCache.php
@@ -1,13 +1,8 @@
mMemc =& $memCached;
}
function getKey( &$article, &$user ) {
global $action;
$hash = $user->getPageRenderingHash();
- if( !$article->mTitle->userCanEdit() ) {
+ if( !$article->mTitle->quickUserCan( 'edit' ) ) {
// section edit links are suppressed even if the user has them on
$edit = '!edit=0';
} else {
@@ -95,31 +90,30 @@ class ParserCache {
function save( $parserOutput, &$article, &$user ){
global $wgParserCacheExpireTime;
$key = $this->getKey( $article, $user );
-
+
if( $parserOutput->getCacheTime() != -1 ) {
-
+
$now = wfTimestampNow();
$parserOutput->setCacheTime( $now );
-
+
// Save the timestamp so that we don't have to load the revision row on view
$parserOutput->mTimestamp = $article->getTimestamp();
-
+
$parserOutput->mText .= "\n\n";
wfDebug( "Saved in parser cache with key $key and timestamp $now\n" );
-
+
if( $parserOutput->containsOldMagic() ){
$expire = 3600; # 1 hour
} else {
$expire = $wgParserCacheExpireTime;
}
$this->mMemc->set( $key, $parserOutput, $expire );
-
+
} else {
wfDebug( "Parser output was marked as uncacheable and has not been saved.\n" );
}
-
}
-
+
}
?>
diff --git a/includes/ParserOptions.php b/includes/ParserOptions.php
new file mode 100644
index 00000000..e335720f
--- /dev/null
+++ b/includes/ParserOptions.php
@@ -0,0 +1,119 @@
+ tags
+ var $mUseDynamicDates; # Use DateFormatter to format dates
+ var $mInterwikiMagic; # Interlanguage links are removed and returned in an array
+ var $mAllowExternalImages; # Allow external images inline
+ var $mAllowExternalImagesFrom; # If not, any exception?
+ var $mSkin; # Reference to the preferred skin
+ var $mDateFormat; # Date format index
+ var $mEditSection; # Create "edit section" links
+ var $mNumberHeadings; # Automatically number headings
+ var $mAllowSpecialInclusion; # Allow inclusion of special pages
+ var $mTidy; # Ask for tidy cleanup
+ var $mInterfaceMessage; # Which lang to call for PLURAL and GRAMMAR
+ var $mMaxIncludeSize; # Maximum size of template expansions, in bytes
+ var $mRemoveComments; # Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
+
+ var $mUser; # Stored user object, just used to initialise the skin
+
+ function getUseTeX() { return $this->mUseTeX; }
+ function getUseDynamicDates() { return $this->mUseDynamicDates; }
+ function getInterwikiMagic() { return $this->mInterwikiMagic; }
+ function getAllowExternalImages() { return $this->mAllowExternalImages; }
+ function getAllowExternalImagesFrom() { return $this->mAllowExternalImagesFrom; }
+ function getEditSection() { return $this->mEditSection; }
+ function getNumberHeadings() { return $this->mNumberHeadings; }
+ function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; }
+ function getTidy() { return $this->mTidy; }
+ function getInterfaceMessage() { return $this->mInterfaceMessage; }
+ function getMaxIncludeSize() { return $this->mMaxIncludeSize; }
+ function getRemoveComments() { return $this->mRemoveComments; }
+
+ function getSkin() {
+ if ( !isset( $this->mSkin ) ) {
+ $this->mSkin = $this->mUser->getSkin();
+ }
+ return $this->mSkin;
+ }
+
+ function getDateFormat() {
+ if ( !isset( $this->mDateFormat ) ) {
+ $this->mDateFormat = $this->mUser->getDatePreference();
+ }
+ return $this->mDateFormat;
+ }
+
+ function setUseTeX( $x ) { return wfSetVar( $this->mUseTeX, $x ); }
+ function setUseDynamicDates( $x ) { return wfSetVar( $this->mUseDynamicDates, $x ); }
+ function setInterwikiMagic( $x ) { return wfSetVar( $this->mInterwikiMagic, $x ); }
+ function setAllowExternalImages( $x ) { return wfSetVar( $this->mAllowExternalImages, $x ); }
+ function setAllowExternalImagesFrom( $x ) { return wfSetVar( $this->mAllowExternalImagesFrom, $x ); }
+ function setDateFormat( $x ) { return wfSetVar( $this->mDateFormat, $x ); }
+ function setEditSection( $x ) { return wfSetVar( $this->mEditSection, $x ); }
+ function setNumberHeadings( $x ) { return wfSetVar( $this->mNumberHeadings, $x ); }
+ function setAllowSpecialInclusion( $x ) { return wfSetVar( $this->mAllowSpecialInclusion, $x ); }
+ function setTidy( $x ) { return wfSetVar( $this->mTidy, $x); }
+ function setSkin( $x ) { $this->mSkin = $x; }
+ function setInterfaceMessage( $x ) { return wfSetVar( $this->mInterfaceMessage, $x); }
+ function setMaxIncludeSize( $x ) { return wfSetVar( $this->mMaxIncludeSize, $x ); }
+ function setRemoveComments( $x ) { return wfSetVar( $this->mRemoveComments, $x ); }
+
+ function __construct( $user = null ) {
+ $this->initialiseFromUser( $user );
+ }
+
+ /**
+ * Get parser options
+ * @static
+ */
+ static function newFromUser( $user ) {
+ return new ParserOptions( $user );
+ }
+
+ /** Get user options */
+ function initialiseFromUser( $userInput ) {
+ global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages;
+ global $wgAllowExternalImagesFrom, $wgAllowSpecialInclusion, $wgMaxArticleSize;
+ $fname = 'ParserOptions::initialiseFromUser';
+ wfProfileIn( $fname );
+ if ( !$userInput ) {
+ global $wgUser;
+ if ( isset( $wgUser ) ) {
+ $user = $wgUser;
+ } else {
+ $user = new User;
+ }
+ } else {
+ $user =& $userInput;
+ }
+
+ $this->mUser = $user;
+
+ $this->mUseTeX = $wgUseTeX;
+ $this->mUseDynamicDates = $wgUseDynamicDates;
+ $this->mInterwikiMagic = $wgInterwikiMagic;
+ $this->mAllowExternalImages = $wgAllowExternalImages;
+ $this->mAllowExternalImagesFrom = $wgAllowExternalImagesFrom;
+ $this->mSkin = null; # Deferred
+ $this->mDateFormat = null; # Deferred
+ $this->mEditSection = true;
+ $this->mNumberHeadings = $user->getOption( 'numberheadings' );
+ $this->mAllowSpecialInclusion = $wgAllowSpecialInclusion;
+ $this->mTidy = false;
+ $this->mInterfaceMessage = false;
+ $this->mMaxIncludeSize = $wgMaxArticleSize * 1024;
+ $this->mRemoveComments = true;
+ wfProfileOut( $fname );
+ }
+}
+
+?>
diff --git a/includes/ParserOutput.php b/includes/ParserOutput.php
new file mode 100644
index 00000000..03f1819c
--- /dev/null
+++ b/includes/ParserOutput.php
@@ -0,0 +1,133 @@
+ section
+
+ function ParserOutput( $text = '', $languageLinks = array(), $categoryLinks = array(),
+ $containsOldMagic = false, $titletext = '' )
+ {
+ $this->mText = $text;
+ $this->mLanguageLinks = $languageLinks;
+ $this->mCategories = $categoryLinks;
+ $this->mContainsOldMagic = $containsOldMagic;
+ $this->mCacheTime = '';
+ $this->mVersion = Parser::VERSION;
+ $this->mTitleText = $titletext;
+ $this->mLinks = array();
+ $this->mTemplates = array();
+ $this->mImages = array();
+ $this->mExternalLinks = array();
+ $this->mHTMLtitle = "" ;
+ $this->mSubtitle = "" ;
+ $this->mNewSection = false;
+ $this->mNoGallery = false;
+ $this->mHeadItems = array();
+ }
+
+ function getText() { return $this->mText; }
+ function &getLanguageLinks() { return $this->mLanguageLinks; }
+ function getCategoryLinks() { return array_keys( $this->mCategories ); }
+ function &getCategories() { return $this->mCategories; }
+ function getCacheTime() { return $this->mCacheTime; }
+ function getTitleText() { return $this->mTitleText; }
+ function &getLinks() { return $this->mLinks; }
+ function &getTemplates() { return $this->mTemplates; }
+ function &getImages() { return $this->mImages; }
+ function &getExternalLinks() { return $this->mExternalLinks; }
+ function getNoGallery() { return $this->mNoGallery; }
+ function getSubtitle() { return $this->mSubtitle; }
+
+ function containsOldMagic() { return $this->mContainsOldMagic; }
+ function setText( $text ) { return wfSetVar( $this->mText, $text ); }
+ function setLanguageLinks( $ll ) { return wfSetVar( $this->mLanguageLinks, $ll ); }
+ function setCategoryLinks( $cl ) { return wfSetVar( $this->mCategories, $cl ); }
+ function setContainsOldMagic( $com ) { return wfSetVar( $this->mContainsOldMagic, $com ); }
+ function setCacheTime( $t ) { return wfSetVar( $this->mCacheTime, $t ); }
+ function setTitleText( $t ) { return wfSetVar($this->mTitleText, $t); }
+ function setSubtitle( $st ) { return wfSetVar( $this->mSubtitle, $st ); }
+
+ function addCategory( $c, $sort ) { $this->mCategories[$c] = $sort; }
+ function addImage( $name ) { $this->mImages[$name] = 1; }
+ function addLanguageLink( $t ) { $this->mLanguageLinks[] = $t; }
+ function addExternalLink( $url ) { $this->mExternalLinks[$url] = 1; }
+
+ function setNewSection( $value ) {
+ $this->mNewSection = (bool)$value;
+ }
+ function getNewSection() {
+ return (bool)$this->mNewSection;
+ }
+
+ function addLink( $title, $id = null ) {
+ $ns = $title->getNamespace();
+ $dbk = $title->getDBkey();
+ if ( !isset( $this->mLinks[$ns] ) ) {
+ $this->mLinks[$ns] = array();
+ }
+ if ( is_null( $id ) ) {
+ $id = $title->getArticleID();
+ }
+ $this->mLinks[$ns][$dbk] = $id;
+ }
+
+ function addTemplate( $title, $id ) {
+ $ns = $title->getNamespace();
+ $dbk = $title->getDBkey();
+ if ( !isset( $this->mTemplates[$ns] ) ) {
+ $this->mTemplates[$ns] = array();
+ }
+ $this->mTemplates[$ns][$dbk] = $id;
+ }
+
+ /**
+ * Return true if this cached output object predates the global or
+ * per-article cache invalidation timestamps, or if it comes from
+ * an incompatible older version.
+ *
+ * @param string $touched the affected article's last touched timestamp
+ * @return bool
+ * @public
+ */
+ function expired( $touched ) {
+ global $wgCacheEpoch;
+ return $this->getCacheTime() == -1 || // parser says it's uncacheable
+ $this->getCacheTime() < $touched ||
+ $this->getCacheTime() <= $wgCacheEpoch ||
+ !isset( $this->mVersion ) ||
+ version_compare( $this->mVersion, Parser::VERSION, "lt" );
+ }
+
+ /**
+ * Add some text to the .
+ * If $tag is set, the section with that tag will only be included once
+ * in a given page.
+ */
+ function addHeadItem( $section, $tag = false ) {
+ if ( $tag !== false ) {
+ $this->mHeadItems[$tag] = $section;
+ } else {
+ $this->mHeadItems[] = $section;
+ }
+ }
+}
+
+?>
diff --git a/includes/PatrolLog.php b/includes/PatrolLog.php
new file mode 100644
index 00000000..a22839ff
--- /dev/null
+++ b/includes/PatrolLog.php
@@ -0,0 +1,83 @@
+
+ */
+class PatrolLog {
+
+ /**
+ * Record a log event for a change being patrolled
+ *
+ * @param mixed $change Change identifier or RecentChange object
+ * @param bool $auto Was this patrol event automatic?
+ */
+ public static function record( $change, $auto = false ) {
+ if( !( is_object( $change ) && $change instanceof RecentChange ) ) {
+ $change = RecentChange::newFromId( $change );
+ if( !is_object( $change ) )
+ return false;
+ }
+ $title = Title::makeTitleSafe( $change->getAttribute( 'rc_namespace' ),
+ $change->getAttribute( 'rc_title' ) );
+ if( is_object( $title ) ) {
+ $params = self::buildParams( $change, $auto );
+ $log = new LogPage( 'patrol', false ); # False suppresses RC entries
+ $log->addEntry( 'patrol', $title, '', $params );
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Generate the log action text corresponding to a patrol log item
+ *
+ * @param Title $title Title of the page that was patrolled
+ * @param array $params Log parameters (from logging.log_params)
+ * @param Skin $skin Skin to use for building links, etc.
+ * @return string
+ */
+ public static function makeActionText( $title, $params, $skin ) {
+ # This is a bit of a hack, but...if $skin is not a Skin, then *do nothing*
+ # -- this is fine, because the action text we would be queried for under
+ # these conditions would have gone into recentchanges, which we aren't
+ # supposed to be updating
+ if( is_object( $skin ) ) {
+ list( $cur, $prev, $auto ) = $params;
+ # Standard link to the page in question
+ $link = $skin->makeLinkObj( $title );
+ # Generate a diff link
+ $bits[] = 'oldid=' . urlencode( $cur );
+ $bits[] = 'diff=prev';
+ $bits = implode( '&', $bits );
+ $diff = $skin->makeLinkObj( $title, htmlspecialchars( wfMsg( 'patrol-log-diff', $cur ) ), $bits );
+ # Indicate whether or not the patrolling was automatic
+ $auto = $auto ? wfMsgHtml( 'patrol-log-auto' ) : '';
+ # Put it all together
+ return wfMsgHtml( 'patrol-log-line', $diff, $link, $auto );
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Prepare log parameters for a patrolled change
+ *
+ * @param RecentChange $change RecentChange to represent
+ * @param bool $auto Whether the patrol event was automatic
+ * @return array
+ */
+ private static function buildParams( $change, $auto ) {
+ return array(
+ $change->getAttribute( 'rc_this_oldid' ),
+ $change->getAttribute( 'rc_last_oldid' ),
+ (int)$auto
+ );
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/includes/Profiler.php b/includes/Profiler.php
index 30cda63f..da3a82ed 100644
--- a/includes/Profiler.php
+++ b/includes/Profiler.php
@@ -1,7 +1,6 @@
profileIn( '-total' );
}
-
}
function profileIn($functionname) {
@@ -291,7 +288,7 @@ class Profiler {
* @return Integer
* @private
*/
- function calltreeCount(& $stack, $start) {
+ function calltreeCount($stack, $start) {
$level = $stack[$start][1];
$count = 0;
for ($i = $start -1; $i >= 0 && $stack[$i][1] > $level; $i --) {
@@ -308,7 +305,7 @@ class Profiler {
global $wguname, $wgProfilePerHost;
$fname = 'Profiler::logToDB';
- $dbw = & wfGetDB(DB_MASTER);
+ $dbw = wfGetDB(DB_MASTER);
if (!is_object($dbw))
return false;
$errorState = $dbw->ignoreErrors( true );
diff --git a/includes/ProfilerSimple.php b/includes/ProfilerSimple.php
index e69bfc47..f43c7dfc 100644
--- a/includes/ProfilerSimple.php
+++ b/includes/ProfilerSimple.php
@@ -1,20 +1,17 @@
mWorkStack[] = array( '-total', 0, $wgRequestTime,$this->getCpuTime($wgRUstart));
@@ -26,7 +23,6 @@ class ProfilerSimple extends Profiler {
if (!is_array($entry)) {
$entry = array('cpu'=> 0.0, 'cpu_sq' => 0.0, 'real' => 0.0, 'real_sq' => 0.0, 'count' => 0);
$this->mCollated["-setup"] =& $entry;
-
}
$entry['cpu'] += $elapsedcpu;
$entry['cpu_sq'] += $elapsedcpu*$elapsedcpu;
@@ -57,7 +53,7 @@ class ProfilerSimple extends Profiler {
if ($wgDebugFunctionEntry) {
$this->debug(str_repeat(' ', count($this->mWorkStack)).'Entering '.$functionname."\n");
}
- $this->mWorkStack[] = array($functionname, count( $this->mWorkStack ), microtime(true), $this->getCpuTime());
+ $this->mWorkStack[] = array($functionname, count( $this->mWorkStack ), microtime(true), $this->getCpuTime());
}
function profileOut($functionname) {
@@ -87,7 +83,6 @@ class ProfilerSimple extends Profiler {
if (!is_array($entry)) {
$entry = array('cpu'=> 0.0, 'cpu_sq' => 0.0, 'real' => 0.0, 'real_sq' => 0.0, 'count' => 0);
$this->mCollated[$functionname] =& $entry;
-
}
$entry['cpu'] += $elapsedcpu;
$entry['cpu_sq'] += $elapsedcpu*$elapsedcpu;
diff --git a/includes/ProfilerSimpleUDP.php b/includes/ProfilerSimpleUDP.php
index a8527c38..500f1cbd 100644
--- a/includes/ProfilerSimpleUDP.php
+++ b/includes/ProfilerSimpleUDP.php
@@ -1,11 +1,13 @@
mArticle =& $article;
$this->mTitle =& $article->mTitle;
if( $this->mTitle ) {
+ $this->mTitle->loadRestrictions();
+
foreach( $wgRestrictionTypes as $action ) {
// Fixme: this form currently requires individual selections,
// but the db allows multiples separated by commas.
$this->mRestrictions[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
}
+
+ $this->mCascade = $this->mTitle->areRestrictionsCascading();
+
+ if ( $this->mTitle->mRestrictionsExpiry == 'infinity' ) {
+ $this->mExpiry = 'infinite';
+ } else if ( strlen($this->mTitle->mRestrictionsExpiry) == 0 ) {
+ $this->mExpiry = '';
+ } else {
+ $this->mExpiry = wfTimestamp( TS_RFC2822, $this->mTitle->mRestrictionsExpiry );
+ }
}
// The form will be available in read-only to show levels.
@@ -48,6 +63,9 @@ class ProtectionForm {
if( $wgRequest->wasPosted() ) {
$this->mReason = $wgRequest->getText( 'mwProtect-reason' );
+ $this->mCascade = $wgRequest->getBool( 'mwProtect-cascade' );
+ $this->mExpiry = $wgRequest->getText( 'mwProtect-expiry' );
+
foreach( $wgRestrictionTypes as $action ) {
$val = $wgRequest->getVal( "mwProtect-level-$action" );
if( isset( $val ) && in_array( $val, $wgRestrictionLevels ) ) {
@@ -56,9 +74,21 @@ class ProtectionForm {
}
}
}
+
+ function execute() {
+ global $wgRequest;
+ if( $wgRequest->wasPosted() ) {
+ if( $this->save() ) {
+ global $wgOut;
+ $wgOut->redirect( $this->mTitle->getFullUrl() );
+ }
+ } else {
+ $this->show();
+ }
+ }
- function show() {
- global $wgOut;
+ function show( $err = null ) {
+ global $wgOut, $wgUser;
$wgOut->setRobotpolicy( 'noindex,nofollow' );
@@ -69,17 +99,47 @@ class ProtectionForm {
return;
}
- if( $this->save() ) {
- $wgOut->redirect( $this->mTitle->getFullUrl() );
- return;
+ list( $cascadeSources, $restrictions ) = $this->mTitle->getCascadeProtectionSources();
+
+ if ( "" != $err ) {
+ $wgOut->setSubtitle( wfMsgHtml( 'formerror' ) );
+ $wgOut->addHTML( "
' );
+ # Disable the "next" link when we reach the end
+ $paging = wfViewPrevNext( $offset, $limit, $wgContLang->specialPage( $sname ),
+ wfArrayToCGI( $this->linkParameters() ), ( $num < $limit ) );
+ $wgOut->addHtml( '
' . $paging . '
' );
+ } else {
+ # No results to show, so don't bother with "showing X of Y" etc.
+ # -- just let the user know and give up now
+ $wgOut->addHtml( '
' . wfMsgHtml( 'specialpage-empty' ) . '
' );
+ return;
+ }
+ }
+
+ # The actual results; specialist subclasses will want to handle this
+ # with more than a straight list, so we hand them the info, plus
+ # an OutputPage, and let them get on with it
+ $this->outputResults( $wgOut,
+ $wgUser->getSkin(),
+ $dbr, # Should use a ResultWrapper for this
+ $res,
+ $dbr->numRows( $res ),
+ $offset );
+
+ # Repeat the paging links at the bottom
+ if( $shownavigation ) {
+ $wgOut->addHtml( '