Merge "Title: Refactor JS/CSS page handling to be more sane"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 22 Feb 2018 19:19:29 +0000 (19:19 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 22 Feb 2018 19:19:29 +0000 (19:19 +0000)
466 files changed:
.gitignore
.phpcs.xml
.travis.yml
Gruntfile.js
RELEASE-NOTES-1.31
autoload.php
composer.json
docs/hooks.txt
includes/CategoryFinder.php
includes/DefaultSettings.php
includes/DevelopmentSettings.php [new file with mode: 0644]
includes/MediaWikiServices.php
includes/Message.php
includes/ServiceWiring.php
includes/SiteStats.php
includes/SiteStatsInit.php
includes/Storage/RevisionStore.php
includes/Storage/SqlBlobStore.php
includes/api/ApiBase.php
includes/api/ApiFeedRecentChanges.php
includes/api/ApiMain.php
includes/api/i18n/ar.json
includes/api/i18n/ba.json
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/es.json
includes/api/i18n/fr.json
includes/api/i18n/gl.json
includes/api/i18n/he.json
includes/api/i18n/hu.json
includes/api/i18n/it.json
includes/api/i18n/ksh.json
includes/api/i18n/lb.json
includes/api/i18n/lt.json
includes/api/i18n/mk.json
includes/api/i18n/nb.json
includes/api/i18n/pl.json
includes/api/i18n/pt-br.json
includes/api/i18n/pt.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/sv.json
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/auth/AuthPluginPrimaryAuthenticationProvider.php
includes/cache/MessageCache.php
includes/changetags/ChangeTags.php
includes/db/DatabaseOracle.php
includes/deferred/SiteStatsUpdate.php
includes/exception/MWException.php
includes/import/ImportableOldRevision.php [new file with mode: 0644]
includes/import/ImportableOldRevisionImporter.php [new file with mode: 0644]
includes/import/ImportableUploadRevision.php [new file with mode: 0644]
includes/import/ImportableUploadRevisionImporter.php [new file with mode: 0644]
includes/import/OldRevisionImporter.php [new file with mode: 0644]
includes/import/UploadRevisionImporter.php [new file with mode: 0644]
includes/import/WikiRevision.php
includes/installer/i18n/ast.json
includes/installer/i18n/fi.json
includes/installer/i18n/nan.json
includes/installer/i18n/sv.json
includes/jobqueue/jobs/RecentChangesUpdateJob.php
includes/jobqueue/jobs/UserGroupExpiryJob.php [new file with mode: 0644]
includes/libs/DeferredStringifier.php
includes/libs/objectcache/IExpiringStore.php
includes/libs/objectcache/WANObjectCache.php
includes/libs/rdbms/ChronologyProtector.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseMssql.php
includes/libs/rdbms/database/DatabaseMysqlBase.php
includes/libs/rdbms/database/DatabaseMysqli.php
includes/libs/rdbms/database/DatabasePostgres.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/database/IDatabase.php
includes/libs/rdbms/database/position/MySQLMasterPos.php
includes/libs/rdbms/database/resultwrapper/MssqlResultWrapper.php
includes/libs/rdbms/encasing/Blob.php
includes/libs/rdbms/encasing/MssqlBlob.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/rdbms/loadmonitor/LoadMonitor.php
includes/media/Bitmap.php
includes/media/JpegMetadataExtractor.php
includes/page/WikiPage.php
includes/parser/DateFormatter.php
includes/parser/ParserOptions.php
includes/profiler/Profiler.php
includes/skins/QuickTemplate.php
includes/skins/Skin.php
includes/specialpage/ChangesListSpecialPage.php
includes/specials/SpecialContributions.php
includes/specials/SpecialRecentchanges.php
includes/user/ExternalUserNames.php
includes/user/UserGroupMembership.php
languages/Language.php
languages/data/Names.php
languages/i18n/ace.json
languages/i18n/ady-cyrl.json
languages/i18n/af.json
languages/i18n/ais.json
languages/i18n/am.json
languages/i18n/an.json
languages/i18n/ang.json
languages/i18n/ar.json
languages/i18n/arc.json
languages/i18n/ary.json
languages/i18n/arz.json
languages/i18n/as.json
languages/i18n/ast.json
languages/i18n/avk.json
languages/i18n/awa.json
languages/i18n/az.json
languages/i18n/azb.json
languages/i18n/ba.json
languages/i18n/bar.json
languages/i18n/bcc.json
languages/i18n/bcl.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bgn.json
languages/i18n/bho.json
languages/i18n/bjn.json
languages/i18n/bn.json
languages/i18n/bo.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/bto.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/ch.json
languages/i18n/ckb.json
languages/i18n/crh-cyrl.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/csb.json
languages/i18n/cu.json
languages/i18n/cv.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de-ch.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dsb.json
languages/i18n/dty.json
languages/i18n/egl.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es-formal.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/ext.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fo.json
languages/i18n/fr.json
languages/i18n/frp.json
languages/i18n/frr.json
languages/i18n/fur.json
languages/i18n/fy.json
languages/i18n/ga.json
languages/i18n/gan-hans.json
languages/i18n/gan-hant.json
languages/i18n/gd.json
languages/i18n/gl.json
languages/i18n/gom-deva.json
languages/i18n/gom-latn.json
languages/i18n/grc.json
languages/i18n/gsw.json
languages/i18n/gu.json
languages/i18n/gv.json
languages/i18n/hak.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hif-latn.json
languages/i18n/hil.json
languages/i18n/hr.json
languages/i18n/hrx.json
languages/i18n/hsb.json
languages/i18n/hu.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/ie.json
languages/i18n/ig.json
languages/i18n/ilo.json
languages/i18n/inh.json
languages/i18n/io.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/kaa.json
languages/i18n/kab.json
languages/i18n/kiu.json
languages/i18n/kk-arab.json
languages/i18n/kk-cyrl.json
languages/i18n/kk-latn.json
languages/i18n/km.json
languages/i18n/kn.json
languages/i18n/ko.json
languages/i18n/krc.json
languages/i18n/ksh.json
languages/i18n/ku-latn.json
languages/i18n/kum.json
languages/i18n/ky.json
languages/i18n/la.json
languages/i18n/lad.json
languages/i18n/lb.json
languages/i18n/lez.json
languages/i18n/lfn.json
languages/i18n/li.json
languages/i18n/lij.json
languages/i18n/lki.json
languages/i18n/lmo.json
languages/i18n/lrc.json
languages/i18n/lt.json
languages/i18n/lus.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/lzz.json
languages/i18n/mai.json
languages/i18n/map-bms.json
languages/i18n/mdf.json
languages/i18n/mg.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/mn.json
languages/i18n/mr.json
languages/i18n/ms.json
languages/i18n/mt.json
languages/i18n/mwl.json
languages/i18n/my.json
languages/i18n/myv.json
languages/i18n/nah.json
languages/i18n/nan.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nds.json
languages/i18n/ne.json
languages/i18n/nl-informal.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/oc.json
languages/i18n/or.json
languages/i18n/os.json
languages/i18n/pa.json
languages/i18n/pam.json
languages/i18n/pdc.json
languages/i18n/pfl.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pnb.json
languages/i18n/pnt.json
languages/i18n/prg.json
languages/i18n/ps.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/qu.json
languages/i18n/rm.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/rue.json
languages/i18n/sa.json
languages/i18n/sah.json
languages/i18n/sat.json
languages/i18n/sc.json
languages/i18n/scn.json
languages/i18n/sco.json
languages/i18n/sd.json
languages/i18n/sdc.json
languages/i18n/se.json
languages/i18n/sei.json
languages/i18n/ses.json
languages/i18n/sgs.json
languages/i18n/sh.json
languages/i18n/shi.json
languages/i18n/shn.json
languages/i18n/si.json
languages/i18n/sk.json
languages/i18n/skr-arab.json
languages/i18n/sl.json
languages/i18n/sli.json
languages/i18n/so.json
languages/i18n/sq.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/stq.json
languages/i18n/su.json
languages/i18n/sv.json
languages/i18n/sw.json
languages/i18n/szl.json
languages/i18n/ta.json
languages/i18n/tay.json
languages/i18n/tcy.json
languages/i18n/te.json
languages/i18n/tg-cyrl.json
languages/i18n/tg-latn.json
languages/i18n/th.json
languages/i18n/tk.json
languages/i18n/tl.json
languages/i18n/tly.json
languages/i18n/to.json
languages/i18n/tpi.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/tt-latn.json
languages/i18n/tzm.json
languages/i18n/ug-arab.json
languages/i18n/uk.json
languages/i18n/ur.json
languages/i18n/vec.json
languages/i18n/vep.json
languages/i18n/vi.json
languages/i18n/vo.json
languages/i18n/vro.json
languages/i18n/wa.json
languages/i18n/war.json
languages/i18n/wo.json
languages/i18n/xmf.json
languages/i18n/yi.json
languages/i18n/yo.json
languages/i18n/yue.json
languages/i18n/zea.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesCs.php
languages/messages/MessagesEs_formal.php [new file with mode: 0644]
maintenance/Maintenance.php
maintenance/checkLess.php
maintenance/cleanupUsersWithNoId.php
maintenance/jsduck/categories.json
maintenance/migrateComments.php
maintenance/sql.php
resources/Resources.php
resources/src/jquery/jquery.byteLength.js
resources/src/jquery/jquery.byteLimit.js
resources/src/mediawiki.language/mediawiki.cldr.js
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.special/mediawiki.special.upload.js
resources/src/mediawiki.widgets.visibleByteLimit/mediawiki.widgets.visibleByteLimit.js
resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js
resources/src/mediawiki/mediawiki.String.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.Title.js
resources/src/mediawiki/mediawiki.inspect.js
resources/src/mediawiki/mediawiki.js
resources/src/startup.js
tests/integration/includes/http/MWHttpRequestTestCase.php
tests/integration/includes/shell/FirejailCommandTest.php
tests/parser/ParserTestRunner.php
tests/parser/PhpunitTestRecorder.php
tests/phpunit/MediaWikiPHPUnitTestListener.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/data/media/jpeg-xmp-loop.jpg [new file with mode: 0644]
tests/phpunit/includes/FauxRequestTest.php
tests/phpunit/includes/GlobalFunctions/wfArrayFilterTest.php
tests/phpunit/includes/MediaWikiVersionFetcherTest.php
tests/phpunit/includes/SanitizerValidateEmailTest.php
tests/phpunit/includes/SiteStatsTest.php
tests/phpunit/includes/TitleArrayFromResultTest.php
tests/phpunit/includes/WikiReferenceTest.php
tests/phpunit/includes/XmlJsTest.php
tests/phpunit/includes/api/ApiPageSetTest.php
tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
tests/phpunit/includes/auth/EmailNotificationSecondaryAuthenticationProviderTest.php
tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php
tests/phpunit/includes/config/EtcdConfigTest.php
tests/phpunit/includes/db/DatabaseSqliteTest.php
tests/phpunit/includes/db/DatabaseTestHelper.php
tests/phpunit/includes/debug/logger/monolog/LogstashFormatterTest.php
tests/phpunit/includes/deferred/MWCallableUpdateTest.php
tests/phpunit/includes/deferred/TransactionRoundDefiningUpdateTest.php
tests/phpunit/includes/exception/BadTitleErrorTest.php
tests/phpunit/includes/exception/ThrottledErrorTest.php
tests/phpunit/includes/externalstore/ExternalStoreFactoryTest.php
tests/phpunit/includes/htmlform/HTMLRestrictionsFieldTest.php
tests/phpunit/includes/jobqueue/JobQueueMemoryTest.php
tests/phpunit/includes/libs/ArrayUtilsTest.php
tests/phpunit/includes/libs/DeferredStringifierTest.php
tests/phpunit/includes/libs/DnsSrvDiscovererTest.php
tests/phpunit/includes/libs/GenericArrayObjectTest.php
tests/phpunit/includes/libs/HashRingTest.php
tests/phpunit/includes/libs/HtmlArmorTest.php
tests/phpunit/includes/libs/IEUrlExtensionTest.php
tests/phpunit/includes/libs/IPTest.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php
tests/phpunit/includes/libs/MWMessagePackTest.php
tests/phpunit/includes/libs/MapCacheLRUTest.php
tests/phpunit/includes/libs/MemoizedCallableTest.php
tests/phpunit/includes/libs/ProcessCacheLRUTest.php
tests/phpunit/includes/libs/SamplingStatsdClientTest.php
tests/phpunit/includes/libs/StringUtilsTest.php
tests/phpunit/includes/libs/TimingTest.php
tests/phpunit/includes/libs/XhprofDataTest.php
tests/phpunit/includes/libs/XhprofTest.php
tests/phpunit/includes/libs/XmlTypeCheckTest.php
tests/phpunit/includes/libs/http/HttpAcceptNegotiatorTest.php
tests/phpunit/includes/libs/http/HttpAcceptParserTest.php
tests/phpunit/includes/libs/mime/MimeAnalyzerTest.php
tests/phpunit/includes/libs/objectcache/CachedBagOStuffTest.php
tests/phpunit/includes/libs/objectcache/HashBagOStuffTest.php
tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php
tests/phpunit/includes/libs/rdbms/TransactionProfilerTest.php
tests/phpunit/includes/libs/rdbms/connectionmanager/ConnectionManagerTest.php
tests/phpunit/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManagerTest.php
tests/phpunit/includes/libs/rdbms/database/DBConnRefTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseDomainTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseMysqlBaseTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php
tests/phpunit/includes/libs/xmp/XMPTest.php
tests/phpunit/includes/libs/xmp/XMPValidateTest.php
tests/phpunit/includes/media/JpegMetadataExtractorTest.php
tests/phpunit/includes/objectcache/RedisBagOStuffTest.php
tests/phpunit/includes/parser/ParserIntegrationTest.php
tests/phpunit/includes/registration/VersionCheckerTest.php
tests/phpunit/includes/resourceloader/DerivativeResourceLoaderContextTest.php
tests/phpunit/includes/resourceloader/MessageBlobStoreTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderClientHtmlTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderContextTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderSkinModuleTest.php
tests/phpunit/includes/search/SearchSuggestionSetTest.php
tests/phpunit/includes/services/ServiceContainerTest.php
tests/phpunit/includes/shell/CommandFactoryTest.php
tests/phpunit/includes/shell/CommandTest.php
tests/phpunit/includes/shell/FirejailCommandTest.php
tests/phpunit/includes/shell/ShellTest.php
tests/phpunit/includes/site/FileBasedSiteLookupTest.php
tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php
tests/phpunit/includes/site/SiteExporterTest.php
tests/phpunit/includes/site/SiteImporterTest.php
tests/phpunit/includes/site/SitesCacheFileBuilderTest.php
tests/phpunit/includes/sparql/SparqlClientTest.php
tests/phpunit/includes/utils/AvroValidatorTest.php
tests/phpunit/includes/utils/ClassCollectorTest.php
tests/phpunit/includes/utils/FileContentsHasherTest.php
tests/phpunit/includes/utils/MWCryptHashTest.php
tests/phpunit/includes/utils/MWRestrictionsTest.php
tests/phpunit/includes/utils/UIDGeneratorTest.php
tests/phpunit/includes/utils/ZipDirectoryReaderTest.php
tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php
tests/phpunit/includes/watcheditem/WatchedItemStoreUnitTest.php
tests/phpunit/languages/LanguageCodeTest.php
tests/phpunit/languages/LanguageTest.php
tests/phpunit/maintenance/BenchmarkerTest.php
tests/phpunit/maintenance/fetchTextTest.php
tests/phpunit/phpunit.php
tests/phpunit/structure/ApiStructureTest.php
tests/phpunit/structure/AvailableRightsTest.php
tests/phpunit/structure/ExtensionJsonValidationTest.php
tests/phpunit/structure/StructureTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/jquery/jquery.byteLength.test.js [deleted file]
tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.String.byteLength.test.js [new file with mode: 0644]
tests/qunit/suites/resources/mediawiki/mediawiki.String.trimByteLength.test.js [new file with mode: 0644]
tests/qunit/suites/resources/startup.test.js
tests/selenium/README.md

index bb3a946..0112cf3 100644 (file)
@@ -35,6 +35,8 @@ sftp-config.json
 /images/timeline
 ## Extension:Score
 /images/lilypond
+## Extension:TimedMediaHandler
+/images/transcoded
 /images/tmp
 /maintenance/.mweval_history
 /maintenance/.mwsql_history
index 7f90f27..cd55428 100644 (file)
@@ -7,7 +7,6 @@
                <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPublic" />
                <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamTag" />
                <exclude name="MediaWiki.Commenting.FunctionComment.MissingReturn" />
-               <exclude name="MediaWiki.Commenting.FunctionComment.ParamNameNoMatch" />
                <exclude name="MediaWiki.Commenting.FunctionComment.ExtraParamComment" />
                <exclude name="MediaWiki.Commenting.FunctionComment.WrongStyle" />
                <exclude name="MediaWiki.Commenting.IllegalSingleLineComment.IllegalSingleLineCommentStart" />
@@ -29,6 +28,8 @@
                <exclude name="MediaWiki.Commenting.FunctionComment.SpacingDocTag" />
                <exclude name="Squiz.Scope.MethodScope.Missing" />
                <exclude name="Squiz.Scope.MemberVarScope.Missing" />
+               <exclude name="MediaWiki.Commenting.MissingCovers.MissingCovers" />
+               <exclude name="MediaWiki.Usage.AssignmentInReturn.AssignmentInReturn" />
        </rule>
        <rule ref="MediaWiki.NamingConventions.PrefixedGlobalFunctions">
                <properties>
index b06d9f4..a28dac0 100644 (file)
@@ -69,6 +69,8 @@ before_script:
       --dbuser "$dbuser"
       --dbpass ""
       --scriptpath "/w"
+  - echo -en "\n\nrequire_once __DIR__ . '/includes/DevelopmentSettings.php';\n" >> ./LocalSettings.php
+  - php -l ./LocalSettings.php
 
 script:
   - php tests/phpunit/phpunit.php
index d1ef72f..cb9a20d 100644 (file)
@@ -98,8 +98,8 @@ module.exports = function ( grunt ) {
                        chromium: {
                                browsers: [ 'Chromium' ]
                        },
-                       more: {
-                               browsers: [ 'Chrome', 'Firefox' ]
+                       firefox: {
+                               browsers: [ 'Firefox' ]
                        }
                },
                copy: {
index c1bc8f7..131a3b9 100644 (file)
@@ -26,6 +26,8 @@ production.
   default mode.
 * CACHE_ACCEL now only supports APC(u) or WinCache. XCache support was removed
   as upstream is inactive and has no plans to move to PHP 7.
+* The old CategorizedRecentChanges feature, including its related configuration
+  option $wgAllowCategorizedRecentChanges, has been removed.
 
 === New features in 1.31 ===
 * Wikimedia\Rdbms\IDatabase->select() and similar methods now support
@@ -63,6 +65,7 @@ production.
 * Updated wikimedia/running-stat from 1.1.0 to 1.2.0.
 * Updated wikimedia/wrappedstring from 2.2.0 to 2.3.0.
 * Updated mediawiki/at-ease from 1.1.0 to 1.2.0.
+* Updated wikimedia/php-session-serializer from 1.0.4 to 1.0.5.
 * …
 
 ==== New external libraries ====
@@ -100,8 +103,10 @@ changes to languages because of Phabricator reports.
 * (T186359) New language support: Siberian Tatar [cебертатар] (sty).
 * (T186635) New language support: Guianan Creole (gcr).
 * (T186647) New language support: Kumyk [къумукъ] (kum).
+* (T187750) New language support: Spanish formal address (es-formal).
 
 === Other changes in 1.31 ===
+* Browser support for Internet Explorer 10 was lowered from Grade A to Grade C.
 * Introducing multi-content-revision capability into the storage layer. For details,
   see <https://www.mediawiki.org/wiki/Requests_for_comment/Multi-Content_Revisions>.
 * The Revision class was deprecated in favor of RevisionStore, BlobStore, and
@@ -240,6 +245,9 @@ changes to languages because of Phabricator reports.
   * Title::isCssSubpage – use ::isUserCssConfigPage
   * Title::isJsSubpage – use ::isUserJsConfigPage
 * The method ResourceLoaderModule::getPosition(), deprecated in 1.29, has been removed.
+* The DeferredStringifier class is deprecated, use Message::listParam() instead.
+* The type string for the parameter $lang of DateFormatter::getInstance is
+  deprecated.
 
 == Compatibility ==
 MediaWiki 1.31 requires PHP 5.5.9 or later. Although HHVM 3.18.5 or later is supported,
index fc77fcb..7f90d47 100644 (file)
@@ -647,6 +647,10 @@ $wgAutoloadLocalClasses = [
        'ImportStringSource' => __DIR__ . '/includes/import/ImportStringSource.php',
        'ImportTextFiles' => __DIR__ . '/maintenance/importTextFiles.php',
        'ImportTitleFactory' => __DIR__ . '/includes/title/ImportTitleFactory.php',
+       'ImportableOldRevision' => __DIR__ . '/includes/import/ImportableOldRevision.php',
+       'ImportableOldRevisionImporter' => __DIR__ . '/includes/import/ImportableOldRevisionImporter.php',
+       'ImportableUploadRevision' => __DIR__ . '/includes/import/ImportableUploadRevision.php',
+       'ImportableUploadRevisionImporter' => __DIR__ . '/includes/import/ImportableUploadRevisionImporter.php',
        'IncludableSpecialPage' => __DIR__ . '/includes/specialpage/IncludableSpecialPage.php',
        'IndexPager' => __DIR__ . '/includes/pager/IndexPager.php',
        'InfoAction' => __DIR__ . '/includes/actions/InfoAction.php',
@@ -1075,6 +1079,7 @@ $wgAutoloadLocalClasses = [
        'ObjectFactory' => __DIR__ . '/includes/compat/ObjectFactory.php',
        'OldChangesList' => __DIR__ . '/includes/changes/OldChangesList.php',
        'OldLocalFile' => __DIR__ . '/includes/filerepo/file/OldLocalFile.php',
+       'OldRevisionImporter' => __DIR__ . '/includes/import/OldRevisionImporter.php',
        'OracleInstaller' => __DIR__ . '/includes/installer/OracleInstaller.php',
        'OracleUpdater' => __DIR__ . '/includes/installer/OracleUpdater.php',
        'OrderedStreamingForkController' => __DIR__ . '/includes/OrderedStreamingForkController.php',
@@ -1570,6 +1575,7 @@ $wgAutoloadLocalClasses = [
        'UploadFromStash' => __DIR__ . '/includes/upload/UploadFromStash.php',
        'UploadFromUrl' => __DIR__ . '/includes/upload/UploadFromUrl.php',
        'UploadLogFormatter' => __DIR__ . '/includes/logging/UploadLogFormatter.php',
+       'UploadRevisionImporter' => __DIR__ . '/includes/import/UploadRevisionImporter.php',
        'UploadSourceAdapter' => __DIR__ . '/includes/import/UploadSourceAdapter.php',
        'UploadSourceField' => __DIR__ . '/includes/specials/formfields/UploadSourceField.php',
        'UploadStash' => __DIR__ . '/includes/upload/UploadStash.php',
@@ -1591,6 +1597,7 @@ $wgAutoloadLocalClasses = [
        'UserBlockedError' => __DIR__ . '/includes/exception/UserBlockedError.php',
        'UserCache' => __DIR__ . '/includes/cache/UserCache.php',
        'UserDupes' => __DIR__ . '/maintenance/userDupes.inc',
+       'UserGroupExpiryJob' => __DIR__ . '/includes/jobqueue/jobs/UserGroupExpiryJob.php',
        'UserGroupMembership' => __DIR__ . '/includes/user/UserGroupMembership.php',
        'UserMailer' => __DIR__ . '/includes/mail/UserMailer.php',
        'UserNamePrefixSearch' => __DIR__ . '/includes/user/UserNamePrefixSearch.php',
index c3ff8d6..c96374f 100644 (file)
@@ -37,7 +37,7 @@
                "wikimedia/html-formatter": "1.0.1",
                "wikimedia/ip-set": "1.2.0",
                "wikimedia/object-factory": "1.0.0",
-               "wikimedia/php-session-serializer": "1.0.4",
+               "wikimedia/php-session-serializer": "1.0.5",
                "wikimedia/purtle": "1.0.6",
                "wikimedia/relpath": "2.1.1",
                "wikimedia/remex-html": "1.0.2",
@@ -55,7 +55,7 @@
                "jakub-onderka/php-parallel-lint": "0.9.2",
                "jetbrains/phpstorm-stubs": "dev-master#1b9906084d6635456fcf3f3a01f0d7d5b99a578a",
                "justinrainbow/json-schema": "~5.2",
-               "mediawiki/mediawiki-codesniffer": "15.0.0",
+               "mediawiki/mediawiki-codesniffer": "16.0.0",
                "monolog/monolog": "~1.22.1",
                "nikic/php-parser": "3.1.3",
                "nmred/kafka-php": "0.1.5",
index 7084b51..4e8474b 100644 (file)
@@ -2333,6 +2333,7 @@ $wikiPage: the WikiPage edited
 $rev: the new revision
 $baseID: the revision ID this was based off, if any
 $user: the editing user
+&$tags: tags to apply to the edit and recent change
 
 'OldChangesListRecentChangesLine': Customize entire recent changes line, or
 return false to omit the line from RecentChanges and Watchlist special pages.
index 3561f7f..7446b59 100644 (file)
@@ -42,6 +42,8 @@ use Wikimedia\Rdbms\IDatabase;
  *     $a = $cf->run();
  *     print implode( ',' , $a );
  * @endcode
+ *
+ * @deprecated since 1.31
  */
 class CategoryFinder {
        /** @var int[] The original article IDs passed to the seed function */
index f31238a..35b821c 100644 (file)
@@ -6954,11 +6954,6 @@ $wgShowUpdatedMarker = true;
  */
 $wgDisableAnonTalk = false;
 
-/**
- * Enable filtering of categories in Recentchanges
- */
-$wgAllowCategorizedRecentChanges = false;
-
 /**
  * Allow filtering by change tag in recentchanges, history, etc
  * Has no effect if no tags are defined in valid_tag.
@@ -7460,6 +7455,7 @@ $wgJobClasses = [
        'clearUserWatchlist' => ClearUserWatchlistJob::class,
        'cdnPurge' => CdnPurgeJob::class,
        'enqueue' => EnqueueJob::class, // local queue for multi-DC setups
+       'userGroupExpiry' => UserGroupExpiryJob::class,
        'null' => NullJob::class,
 ];
 
diff --git a/includes/DevelopmentSettings.php b/includes/DevelopmentSettings.php
new file mode 100644 (file)
index 0000000..96ed56b
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Extra settings useful for MediaWiki development.
+ *
+ * To enable built-in debug and development settings, add the
+ * following to your LocalSettings.php file.
+ *
+ *     require "$IP/includes/DevelopmentSettings.php";
+ *
+ * Alternatively, if running phpunit.php (or another Maintenance script),
+ * you can use the --mwdebug option to automatically load these settings.
+ *
+ * @file
+ */
+
+/**
+ * Debugging: PHP
+ */
+
+// Enable showing of errors
+error_reporting( -1 );
+ini_set( 'display_errors', 1 );
+
+/**
+ * Debugging: MediaWiki
+ */
+global $wgDevelopmentWarnings, $wgShowDBErrorBacktrace, $wgShowExceptionDetails,
+       $wgShowSQLErrors, $wgDebugRawPage,
+       $wgDebugComments, $wgDebugDumpSql, $wgDebugTimestamps,
+       $wgCommandLineMode, $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
+
+// Use of wfWarn() should cause tests to fail
+$wgDevelopmentWarnings = true;
+
+// Enable showing of errors
+$wgShowDBErrorBacktrace = true;
+$wgShowExceptionDetails = true;
+$wgShowSQLErrors = true;
+$wgDebugRawPage = true; // T49960
+
+// Enable log files
+$logDir = getenv( 'MW_LOG_DIR' );
+if ( $logDir ) {
+       if ( $wgCommandLineMode ) {
+               $wgDebugLogFile = "$logDir/mw-debug-cli.log";
+       } else {
+               $wgDebugLogFile = "$logDir/mw-debug-www.log";
+       }
+       $wgDBerrorLog = "$logDir/mw-dberror.log";
+       $wgDebugLogGroups['ratelimit'] = "$logDir/mw-ratelimit.log";
+       $wgDebugLogGroups['exception'] = "$logDir/mw-exception.log";
+       $wgDebugLogGroups['error'] = "$logDir/mw-error.log";
+}
+unset( $logDir );
index 9077666..59f194d 100644 (file)
@@ -690,6 +690,30 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'ReadOnlyMode' );
        }
 
+       /**
+        * @since 1.31
+        * @return \UploadRevisionImporter
+        */
+       public function getWikiRevisionUploadImporter() {
+               return $this->getService( 'UploadRevisionImporter' );
+       }
+
+       /**
+        * @since 1.31
+        * @return \OldRevisionImporter
+        */
+       public function getWikiRevisionOldRevisionImporter() {
+               return $this->getService( 'OldRevisionImporter' );
+       }
+
+       /**
+        * @since 1.31
+        * @return \OldRevisionImporter
+        */
+       public function getWikiRevisionOldRevisionImporterNoUpdates() {
+               return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
+       }
+
        /**
         * @since 1.30
         * @return CommandFactory
index fac9a59..7d05f41 100644 (file)
@@ -1105,7 +1105,7 @@ class Message implements MessageSpecifier, Serializable {
        public static function listParam( array $list, $type = 'text' ) {
                if ( !isset( self::$listTypeMap[$type] ) ) {
                        throw new InvalidArgumentException(
-                               "Invalid type '$type'. Known types are: " . join( ', ', array_keys( self::$listTypeMap ) )
+                               "Invalid type '$type'. Known types are: " . implode( ', ', array_keys( self::$listTypeMap ) )
                        );
                }
                return [ 'list' => $list, 'type' => $type ];
index 8b0452d..dab9fb9 100644 (file)
@@ -442,6 +442,29 @@ return [
                );
        },
 
+       'UploadRevisionImporter' => function ( MediaWikiServices $services ) {
+               return new ImportableUploadRevisionImporter(
+                       $services->getMainConfig()->get( 'EnableUploads' ),
+                       LoggerFactory::getInstance( 'UploadRevisionImporter' )
+               );
+       },
+
+       'OldRevisionImporter' => function ( MediaWikiServices $services ) {
+               return new ImportableOldRevisionImporter(
+                       true,
+                       LoggerFactory::getInstance( 'OldRevisionImporter' ),
+                       $services->getDBLoadBalancer()
+               );
+       },
+
+       'WikiRevisionOldRevisionImporterNoUpdates' => function ( MediaWikiServices $services ) {
+               return new ImportableOldRevisionImporter(
+                       false,
+                       LoggerFactory::getInstance( 'OldRevisionImporter' ),
+                       $services->getDBLoadBalancer()
+               );
+       },
+
        'ShellCommandFactory' => function ( MediaWikiServices $services ) {
                $config = $services->getMainConfig();
 
index 7b2b8d3..745c891 100644 (file)
@@ -56,13 +56,13 @@ class SiteStats {
                wfDebug( __METHOD__ . ": reading site_stats from replica DB\n" );
                $row = self::doLoadFromDB( $dbr );
 
-               if ( !self::isSane( $row ) && $lb->hasOrMadeRecentMasterChanges() ) {
+               if ( !self::isRowSane( $row ) && $lb->hasOrMadeRecentMasterChanges() ) {
                        // Might have just been initialized during this request? Underflow?
                        wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" );
                        $row = self::doLoadFromDB( $lb->getConnection( DB_MASTER ) );
                }
 
-               if ( !self::isSane( $row ) ) {
+               if ( !self::isRowSane( $row ) ) {
                        if ( $config->get( 'MiserMode' ) ) {
                                // Start off with all zeroes, assuming that this is a new wiki or any
                                // repopulations where done manually via script.
@@ -79,35 +79,22 @@ class SiteStats {
                        $row = self::doLoadFromDB( $lb->getConnection( DB_MASTER ) );
                }
 
-               if ( !self::isSane( $row ) ) {
+               if ( !self::isRowSane( $row ) ) {
                        wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
                        // Always return a row-like object
-                       $row = (object)array_fill_keys( self::selectFields(), 0 );
+                       $row = self::salvageInsaneRow( $row );
                }
 
                return $row;
        }
 
-       /**
-        * @param IDatabase $db
-        * @return stdClass|bool
-        */
-       private static function doLoadFromDB( IDatabase $db ) {
-               return $db->selectRow(
-                       'site_stats',
-                       self::selectFields(),
-                       [ 'ss_row_id' => 1 ],
-                       __METHOD__
-               );
-       }
-
        /**
         * @return int
         */
        public static function edits() {
                self::load();
 
-               return self::$row->ss_total_edits;
+               return (int)self::$row->ss_total_edits;
        }
 
        /**
@@ -116,7 +103,7 @@ class SiteStats {
        public static function articles() {
                self::load();
 
-               return self::$row->ss_good_articles;
+               return (int)self::$row->ss_good_articles;
        }
 
        /**
@@ -125,7 +112,7 @@ class SiteStats {
        public static function pages() {
                self::load();
 
-               return self::$row->ss_total_pages;
+               return (int)self::$row->ss_total_pages;
        }
 
        /**
@@ -134,7 +121,7 @@ class SiteStats {
        public static function users() {
                self::load();
 
-               return self::$row->ss_users;
+               return (int)self::$row->ss_users;
        }
 
        /**
@@ -143,7 +130,7 @@ class SiteStats {
        public static function activeUsers() {
                self::load();
 
-               return self::$row->ss_active_users;
+               return (int)self::$row->ss_active_users;
        }
 
        /**
@@ -152,7 +139,7 @@ class SiteStats {
        public static function images() {
                self::load();
 
-               return self::$row->ss_images;
+               return (int)self::$row->ss_images;
        }
 
        /**
@@ -245,6 +232,19 @@ class SiteStats {
                ];
        }
 
+       /**
+        * @param IDatabase $db
+        * @return stdClass|bool
+        */
+       private static function doLoadFromDB( IDatabase $db ) {
+               return $db->selectRow(
+                       'site_stats',
+                       self::selectFields(),
+                       [ 'ss_row_id' => 1 ],
+                       __METHOD__
+               );
+       }
+
        /**
         * Is the provided row of site stats sane, or should it be regenerated?
         *
@@ -253,7 +253,7 @@ class SiteStats {
         * @param bool|object $row
         * @return bool
         */
-       private static function isSane( $row ) {
+       private static function isRowSane( $row ) {
                if ( $row === false
                        || $row->ss_total_pages < $row->ss_good_articles
                        || $row->ss_total_edits < $row->ss_total_pages
@@ -268,7 +268,7 @@ class SiteStats {
                        'ss_users',
                        'ss_images',
                ] as $member ) {
-                       if ( $row->$member > 2000000000 || $row->$member < 0 ) {
+                       if ( $row->$member < 0 ) {
                                return false;
                        }
                }
@@ -276,6 +276,22 @@ class SiteStats {
                return true;
        }
 
+       /**
+        * @param stdClass|bool $row
+        * @return stdClass
+        */
+       private static function salvageInsaneRow( $row ) {
+               $map = $row ? (array)$row : [];
+               // Fill in any missing values with zero
+               $map += array_fill_keys( self::selectFields(), 0 );
+               // Convert negative values to zero
+               foreach ( $map as $field => $value ) {
+                       $map[$field] = max( 0, $value );
+               }
+
+               return (object)$row;
+       }
+
        /**
         * @return LoadBalancer
         */
index f888690..f527cb2 100644 (file)
@@ -198,9 +198,12 @@ class SiteStatsInit {
 
        /**
         * @param int $index
+        * @param string[] $groups
         * @return IDatabase
         */
-       private static function getDB( $index ) {
-               return MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( $index );
+       private static function getDB( $index, $groups = [] ) {
+               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
+
+               return $lb->getConnection( $index, $groups );
        }
 }
index e7c9060..2992211 100644 (file)
@@ -740,8 +740,6 @@ class RevisionStore
 
                        if ( isset( $row->rev_text_id ) && $row->rev_text_id > 0 ) {
                                $mainSlotRow->cont_address = 'tt:' . $row->rev_text_id;
-                       } elseif ( isset( $row->ar_id ) ) {
-                               $mainSlotRow->cont_address = 'ar:' . $row->ar_id;
                        }
 
                        if ( isset( $row->old_text ) ) {
index 031cb58..b890e5a 100644 (file)
@@ -299,7 +299,6 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
                list( $schema, $id, ) = self::splitBlobAddress( $blobAddress );
 
                //TODO: MCR: also support 'ex' schema with ExternalStore URLs, plus flags encoded in the URL!
-               //TODO: MCR: also support 'ar' schema for content blobs in old style archive rows!
                if ( $schema === 'tt' ) {
                        $textId = intval( $id );
                } else {
index 62d73f4..228d319 100644 (file)
@@ -897,7 +897,7 @@ abstract class ApiBase extends ContextSource {
 
                if ( $badParams ) {
                        $this->dieWithError(
-                               [ 'apierror-mustpostparams', join( ', ', $badParams ), count( $badParams ) ]
+                               [ 'apierror-mustpostparams', implode( ', ', $badParams ), count( $badParams ) ]
                        );
                }
        }
@@ -1152,7 +1152,7 @@ abstract class ApiBase extends ContextSource {
                                if ( $multi ) {
                                        // This loses the potential $wgContLang->checkTitleEncoding() transformation
                                        // done by WebRequest for $_GET. Let's call that a feature.
-                                       $value = join( "\x1f", $request->normalizeUnicode( explode( "\x1f", $rawValue ) ) );
+                                       $value = implode( "\x1f", $request->normalizeUnicode( explode( "\x1f", $rawValue ) ) );
                                } else {
                                        $this->dieWithError( 'apierror-badvalue-notmultivalue', 'badvalue_notmultivalue' );
                                }
@@ -1829,7 +1829,7 @@ abstract class ApiBase extends ContextSource {
                $msgs = [ $this->msg( 'api-usage-mailinglist-ref' ) ];
                Hooks::run( 'ApiDeprecationHelp', [ &$msgs ] );
                if ( count( $msgs ) > 1 ) {
-                       $key = '$' . join( ' $', range( 1, count( $msgs ) ) );
+                       $key = '$' . implode( ' $', range( 1, count( $msgs ) ) );
                        $msg = ( new RawMessage( $key ) )->params( $msgs );
                } else {
                        $msg = reset( $msgs );
index 2a80dd5..e5dba8f 100644 (file)
@@ -169,16 +169,6 @@ class ApiFeedRecentChanges extends ApiBase {
                        'showlinkedto' => false,
                ];
 
-               if ( $config->get( 'AllowCategorizedRecentChanges' ) ) {
-                       $ret += [
-                               'categories' => [
-                                       ApiBase::PARAM_TYPE => 'string',
-                                       ApiBase::PARAM_ISMULTI => true,
-                               ],
-                               'categories_any' => false,
-                       ];
-               }
-
                return $ret;
        }
 
index 008015b..a7e3c1b 100644 (file)
@@ -593,7 +593,7 @@ class ApiMain extends ApiBase {
                $this->setCacheMode( 'private' );
 
                $response = $this->getRequest()->response();
-               $headerStr = 'MediaWiki-API-Error: ' . join( ', ', $errCodes );
+               $headerStr = 'MediaWiki-API-Error: ' . implode( ', ', $errCodes );
                $response->header( $headerStr );
 
                // Reset and print just the error message
index 57d4b05..f07c6e2 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "فلتر بالوسم.",
        "apihelp-feedrecentchanges-param-target": "أحدث التغييرات في الصفحات الموصولة من هذه الصفحة فقط",
        "apihelp-feedrecentchanges-param-showlinkedto": "أظهر التغييرات للصفحات الموصولة للصفحة المعطاة عوضا عن ذلك",
-       "apihelp-feedrecentchanges-param-categories": "أظهر التغييرات في الصفحات في كل تصنيف من هذه التصنيفات فقط.",
-       "apihelp-feedrecentchanges-param-categories_any": "أظهر التغييرات في الصفحات في أي تصنيف بدلا من ذلك.",
        "apihelp-feedrecentchanges-example-simple": " اظهر التغييرات الحديثة",
        "apihelp-feedrecentchanges-example-30days": "أظهر التغييرات الأخيرة في 30 يوم.",
        "apihelp-feedwatchlist-summary": "إرجاع تغذية قائمة المراقبة.",
index da8535d..99421fe 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Тэг буйынса һөҙгөс",
        "apihelp-feedrecentchanges-param-target": "Был биттән һылтанған биттәрҙә һуңғы үҙгәртеүҙәрҙе күрһәтергә",
        "apihelp-feedrecentchanges-param-showlinkedto": "Киреһенсә, был биткә һылтанма яһаған биттәрҙәге үҙгәртеүҙәрҙе күрһәтергә",
-       "apihelp-feedrecentchanges-param-categories": "Бар категория биттәрендәге үҙгәрештәрҙе генә күрһәтергә",
-       "apihelp-feedrecentchanges-param-categories_any": "Был категориянан башҡа теләһә ҡайһы категориялар биттәрендәге үҙгәрештәрҙе генә күрһәтергә",
        "apihelp-feedrecentchanges-example-simple": "Һуңғы үҙгәртеүҙәрҙе күрһәтергә.",
        "apihelp-feedrecentchanges-example-30days": "30 көн арауығындағы һуңғы үҙгәртеүҙәрҙе күрһәтергә.",
        "apihelp-feedwatchlist-summary": "Күҙәтеү каналын ҡайтара",
index 37a259d..bbee4fa 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Nach Markierung filtern.",
        "apihelp-feedrecentchanges-param-target": "Nur Änderungen an Seiten anzeigen, die von dieser Seite verlinkt sind.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Zeige Änderungen an Seiten die von der ausgewählten Seite verlinkt sind.",
-       "apihelp-feedrecentchanges-param-categories": "Zeigt nur Änderungen von Seiten in all diesen Kategorien.",
-       "apihelp-feedrecentchanges-param-categories_any": "Zeigt stattdessen nur Änderungen auf Seiten in einer dieser Kategorien.",
        "apihelp-feedrecentchanges-example-simple": "Letzte Änderungen anzeigen",
        "apihelp-feedrecentchanges-example-30days": "Letzte Änderungen für 30 Tage anzeigen",
        "apihelp-feedwatchlist-summary": "Gibt einen Beobachtungslisten-Feed zurück.",
index 1689019..8d7a61c 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filter by tag.",
        "apihelp-feedrecentchanges-param-target": "Show only changes on pages linked from this page.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Show changes on pages linked to the selected page instead.",
-       "apihelp-feedrecentchanges-param-categories": "Show only changes on pages in all of these categories.",
-       "apihelp-feedrecentchanges-param-categories_any": "Show only changes on pages in any of the categories instead.",
        "apihelp-feedrecentchanges-example-simple": "Show recent changes.",
        "apihelp-feedrecentchanges-example-30days": "Show recent changes for 30 days.",
 
index d2aaa77..7cbf1e1 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrar por etiquetas.",
        "apihelp-feedrecentchanges-param-target": "Mostrar solo los cambios en las páginas enlazadas en esta.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Mostrar los cambios en páginas enlazadas con la página seleccionada.",
-       "apihelp-feedrecentchanges-param-categories": "Mostrar sólo cambios en las páginas en todas estas categorías.",
-       "apihelp-feedrecentchanges-param-categories_any": "Mostrar sólo cambios en las páginas en cualquiera de las categorías en lugar.",
        "apihelp-feedrecentchanges-example-simple": "Mostrar los cambios recientes.",
        "apihelp-feedrecentchanges-example-30days": "Mostrar los cambios recientes limitados a 30 días.",
        "apihelp-feedwatchlist-summary": "Devuelve el suministro de una lista de seguimiento.",
index 3e5fb41..4c3b74d 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrer par balise.",
        "apihelp-feedrecentchanges-param-target": "Afficher uniquement les modifications sur les pages liées depuis cette page.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Afficher les modifications plutôt sur les pages liées vers la page sélectionnée.",
-       "apihelp-feedrecentchanges-param-categories": "Afficher uniquement les modifications sur les pages dans toutes ces catégories",
-       "apihelp-feedrecentchanges-param-categories_any": "Afficher plutôt uniquement les modifications sur les pages dans n’importe laquelle de ces catégories.",
        "apihelp-feedrecentchanges-example-simple": "Afficher les modifications récentes",
        "apihelp-feedrecentchanges-example-30days": "Afficher les modifications récentes sur 30 jours",
        "apihelp-feedwatchlist-summary": "Renvoie un flux de liste de suivi.",
index 6b01875..4c66794 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrar por etiqueta.",
        "apihelp-feedrecentchanges-param-target": "Mostrar só os cambios nas páxinas ligadas a esta.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Mostrar os cambios nas páxinas ligadas coa páxina seleccionada.",
-       "apihelp-feedrecentchanges-param-categories": "Só mostrar cambios en páxinas pertencentes a todas estas categorías.",
-       "apihelp-feedrecentchanges-param-categories_any": "Só mostrar cambios en páxinas pertencentes a calquera das categorías.",
        "apihelp-feedrecentchanges-example-simple": "Mostrar os cambios recentes",
        "apihelp-feedrecentchanges-example-30days": "Mostrar os cambios recentes limitados a 30 días",
        "apihelp-feedwatchlist-summary": "Devolve o fluxo dunha lista de vixiancia.",
index 2e68946..2064b7b 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "סינון לפי תגית.",
        "apihelp-feedrecentchanges-param-target": "הצגת שינויים שנעשו בדפים המקושרים לדף זה בלבד.",
        "apihelp-feedrecentchanges-param-showlinkedto": "להציג את השינויים בדפים שמקושרים לדף שנבחר במקום זה.",
-       "apihelp-feedrecentchanges-param-categories": "להציג רק שינויים בדפים בכל הקטגוריות האלו.",
-       "apihelp-feedrecentchanges-param-categories_any": "להציג רק שינויים בדפים בכל הקטגוריות במקום.",
        "apihelp-feedrecentchanges-example-simple": "הצגת שינויים אחרונים.",
        "apihelp-feedrecentchanges-example-30days": "הצגת שינויים אחרונים עבור 30 ימים.",
        "apihelp-feedwatchlist-summary": "החזרת הזנת רשימת מעקב.",
index 7c03097..f6f813d 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Szűrés címke szerint.",
        "apihelp-feedrecentchanges-param-target": "Csak a megadott lapról hivatkozott lapok szerkesztéseinek megjelenítése.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Inkább a megadott lap''ra'' hivatkozó lapok szerkesztéseinek megjelenítése.",
-       "apihelp-feedrecentchanges-param-categories": "Csak a megadott kategóriák mindegyikében szereplő lapok szerkesztéseinek megjelenítése.",
-       "apihelp-feedrecentchanges-param-categories_any": "Inkább a megadott kategóriák bármelyikében szereplő lapok szerkesztéseinek megjelenítése.",
        "apihelp-feedrecentchanges-example-simple": "Friss változtatások megjelenítése.",
        "apihelp-feedrecentchanges-example-30days": "Az elmúlt 30 nap friss változtatásainak megjelenítése.",
        "apihelp-feedwatchlist-summary": "A figyelőlista lekérése hírcsatornaként.",
index 25da0e6..66b0942 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtra per etichetta.",
        "apihelp-feedrecentchanges-param-target": "Mostra solo le modifiche alle pagine collegate da questa pagina.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Mostra solo le modifiche alle pagine collegate a quella specificata.",
-       "apihelp-feedrecentchanges-param-categories": "Mostra solo le variazioni sulle pagine di tutte queste categorie.",
-       "apihelp-feedrecentchanges-param-categories_any": "Mostra invece solo le variazioni sulle pagine in una qualunque categoria.",
        "apihelp-feedrecentchanges-example-simple": "Mostra le ultime modifiche.",
        "apihelp-feedrecentchanges-example-30days": "Mostra le modifiche degli ultimi 30 giorni.",
        "apihelp-feedwatchlist-param-feedformat": "Il formato del feed.",
index 1ed917a..b0231df 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Noh Makkehronge beschängke.",
        "apihelp-feedrecentchanges-param-target": "Zeijsch Änderonge aan Sigge, op di vun heh dä Sigg ene Lengk jeihd.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Zeijsch Änderonge aan Sigge, op di vun dä ußjesöhk Sigg ene Lengk jeihd.",
-       "apihelp-feedrecentchanges-param-categories": "Donn blohß de Änderonge aan de Zohjehüreshkeit för all heh di Saachjroppe zeije.",
-       "apihelp-feedrecentchanges-param-categories_any": "Donn deföhr blohß de Änderonge aan de Zohjehüreshkeit för öhndseijn fun heh dä Saachjroppe zeije.",
        "apihelp-feedrecentchanges-example-simple": "Zeijsch de {{LCFIRST:{{int:recentchanges}}}}",
        "apihelp-feedrecentchanges-example-30days": "Zeijsch de {{LCFIRST:{{int:recentchanges}}}} vun de läzde 30 Dähsch.",
        "apihelp-feedwatchlist-summary": "Donn ene Kannahl met dä Oppaßleß zerökjävve.",
index fc2c789..d2c7593 100644 (file)
@@ -52,8 +52,6 @@
        "apihelp-feedrecentchanges-param-hideliu": "Ännerunge vu registréierte Benotzer verstoppen.",
        "apihelp-feedrecentchanges-param-hidemyself": "Ännerunge vum aktuelle Benotzer verstoppen.",
        "apihelp-feedrecentchanges-param-hidecategorization": "Ännerunge vun der Memberschaft a Kategorie verstoppen.",
-       "apihelp-feedrecentchanges-param-categories": "Nëmmen Ännerunge vu Säiten aus all dëse Kategorië weisen.",
-       "apihelp-feedrecentchanges-param-categories_any": "Nëmmen Ännerunge vu Säiten aus enger vun dëse Kategorië weisen.",
        "apihelp-feedrecentchanges-example-simple": "Rezent Ännerunge weisen",
        "apihelp-filerevert-param-comment": "Bemierkung eroplueden.",
        "apihelp-help-example-main": "Hëllef fir den Haaptmodul.",
index 6f4c6a3..9d39405 100644 (file)
@@ -72,8 +72,6 @@
        "apihelp-feedrecentchanges-param-tagfilter": "Filtruoti pagal žymę.",
        "apihelp-feedrecentchanges-param-target": "Rodyti tik keitimus puslapiuose, pasiekiamuose iš šio puslapio.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Vietoj to, rodyti pakeitimus puslapyje, susietame su pasirinktu puslapiu.",
-       "apihelp-feedrecentchanges-param-categories": "Rodyti pakeitimus tik puslapiuose, esančiuose visuose šiuose kategorijose.",
-       "apihelp-feedrecentchanges-param-categories_any": "Vietoj to, rodyti tik pakeitimus puslapiuse, esančiuose bet kurioje iš kategorijų.",
        "apihelp-feedrecentchanges-example-simple": "Parodyti naujausius keitimus.",
        "apihelp-feedrecentchanges-example-30days": "Rodyti naujausius pakeitimus per 30 dienų.",
        "apihelp-feedwatchlist-summary": "Gražina stebimųjų sąrašo srautą.",
index a012900..3cec5d4 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Филтрирање по ознака.",
        "apihelp-feedrecentchanges-param-target": "Прикажи само промени на страници што водат од оваа.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Наместо тоа, прикажи ги промените на страниците поврзани со избраната страница.",
-       "apihelp-feedrecentchanges-param-categories": "Прикажи само промени на страниците во сите овие категории.",
-       "apihelp-feedrecentchanges-param-categories_any": "Прикажи само промени на страниците во било која од категориите.",
        "apihelp-feedrecentchanges-example-simple": "Прикажи скорешни промени",
        "apihelp-feedrecentchanges-example-30days": "Прикажувај скорешни промени 30 дена",
        "apihelp-feedwatchlist-summary": "Дава тековник со набљудуваните.",
index dc9fb11..c2fea1c 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrer etter tagger.",
        "apihelp-feedrecentchanges-param-target": "Vis bare endringer på sider som lenkes fra denne siden.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Vis endringer på sider som lenker til den valgte siden i stedet.",
-       "apihelp-feedrecentchanges-param-categories": "Vis bare endringer på sider i alle disse kategoriene.",
-       "apihelp-feedrecentchanges-param-categories_any": "Vis bare endringer på sider som er i noen av kategoriene i stedet.",
        "apihelp-feedrecentchanges-example-simple": "Vis siste endringer.",
        "apihelp-feedrecentchanges-example-30days": "Vis siste endringer for 30 døgn.",
        "apihelp-feedwatchlist-summary": "Returnerer en overvåkningslistemating.",
index 6c311d0..8591eba 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtruj po znacznikach.",
        "apihelp-feedrecentchanges-param-target": "Pokaż tylko zmiany na stronach linkowanych z tej strony.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Pokaż zmiany na stronach linkujących do wybranej strony.",
-       "apihelp-feedrecentchanges-param-categories": "Pokaż zmiany tylko na stronach będących we wszystkich tych kategoriach.",
-       "apihelp-feedrecentchanges-param-categories_any": "Pokaż zmiany tylko na stronach będących w jednej z tych kategorii.",
        "apihelp-feedrecentchanges-example-simple": "Pokaż ostatnie zmiany.",
        "apihelp-feedrecentchanges-example-30days": "Pokaż ostatnie zmiany z 30 dni.",
        "apihelp-feedwatchlist-summary": "Zwraca kanał listy obserwowanych.",
index 408b419..fec224e 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrar por tag.",
        "apihelp-feedrecentchanges-param-target": "Mostrar apenas as alterações nas páginas vinculadas por esta página.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Mostra as alterações nas páginas vigiadas à página selecionada.",
-       "apihelp-feedrecentchanges-param-categories": "Mostre apenas as alterações em páginas em todas essas categorias.",
-       "apihelp-feedrecentchanges-param-categories_any": "Mostre apenas as alterações em páginas em qualquer uma das categorias.",
        "apihelp-feedrecentchanges-example-simple": "Mostrar as mudanças recentes.",
        "apihelp-feedrecentchanges-example-30days": "Mostrar as mudanças recentes por 30 dias.",
        "apihelp-feedwatchlist-summary": "Retornar um feed da lista de páginas vigiadas.",
index aa697fb..c18160a 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrar por etiqueta.",
        "apihelp-feedrecentchanges-param-target": "Mostrar apenas mudanças em páginas afluentes a esta.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Mostrar mudanças em páginas com hiperligações para a página selecionada.",
-       "apihelp-feedrecentchanges-param-categories": "Mostrar apenas mudanças nas páginas que estão em todas estas categorias.",
-       "apihelp-feedrecentchanges-param-categories_any": "Mostrar apenas mudanças nas páginas que estão em qualquer uma das categorias.",
        "apihelp-feedrecentchanges-example-simple": "Mostrar mudanças recentes.",
        "apihelp-feedrecentchanges-example-30days": "Mostrar as mudanças recentes de 30 dias.",
        "apihelp-feedwatchlist-summary": "Devolve um ''feed'' das páginas vigiadas.",
        "apihelp-parse-param-disablepp": "Em vez deste, usar <var>$1disablelimitreport</var>.",
        "apihelp-parse-param-disableeditsection": "Omitir as hiperligações para edição da secção no resultado da análise sintática.",
        "apihelp-parse-param-disabletidy": "Não fazer a limpeza do HTML (isto é, o ''tidy'') no resultado da análise sintática.",
+       "apihelp-parse-param-disablestylededuplication": "Não desduplica as folhas de estilo incluídas na saída do analisador sintático.",
        "apihelp-parse-param-generatexml": "Gerar a árvore de análise XML (requer o modelo de conteúdo <code>$1</code>; substituído por <kbd>$2prop=parsetree</kbd>).",
        "apihelp-parse-param-preview": "Executar a análise em modo de antevisão.",
        "apihelp-parse-param-sectionpreview": "Executar a análise em modo de antevisão (também ativa o modo de antevisão).",
index e769880..fc0de4e 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "{{doc-apihelp-param|feedrecentchanges|tagfilter}}",
        "apihelp-feedrecentchanges-param-target": "{{doc-apihelp-param|feedrecentchanges|target}}",
        "apihelp-feedrecentchanges-param-showlinkedto": "{{doc-apihelp-param|feedrecentchanges|showlinkedto}}",
-       "apihelp-feedrecentchanges-param-categories": "{{doc-apihelp-param|feedrecentchanges|categories}}",
-       "apihelp-feedrecentchanges-param-categories_any": "{{doc-apihelp-param|feedrecentchanges|categories_any}}",
        "apihelp-feedrecentchanges-example-simple": "{{doc-apihelp-example|feedrecentchanges}}",
        "apihelp-feedrecentchanges-example-30days": "{{doc-apihelp-example|feedrecentchanges}}",
        "apihelp-feedwatchlist-summary": "{{doc-apihelp-summary|feedwatchlist}}",
index 9ee3527..215e2ff 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Фильтр по меткам.",
        "apihelp-feedrecentchanges-param-target": "Показать только правки на страницах, на которые ссылается данная.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Показать правки на страницах, ссылающихся на данную.",
-       "apihelp-feedrecentchanges-param-categories": "Показать только правки на страницах, включённых во все данные категории.",
-       "apihelp-feedrecentchanges-param-categories_any": "Показать только правки на страницах, включённых в хотя бы одну из данных категорий.",
        "apihelp-feedrecentchanges-example-simple": "Список последних изменений.",
        "apihelp-feedrecentchanges-example-30days": "Список последних изменений за 30 дней.",
        "apihelp-feedwatchlist-summary": "Возвращает ленту списка наблюдения.",
index 8e5228a..e4cff6a 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Filtrera efter tagg.",
        "apihelp-feedrecentchanges-param-target": "Visa endast ändringarna av sidor som den här sidan länkar till.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Visa ändringarna på sidor som är länkade till den valda sidan i stället.",
-       "apihelp-feedrecentchanges-param-categories": "Visa endast ändringar på sidor i alla dessa kategorier.",
-       "apihelp-feedrecentchanges-param-categories_any": "Visa endast ändringar på sidor i någon av kategorierna istället.",
        "apihelp-feedrecentchanges-example-simple": "Visa senaste ändringar",
        "apihelp-feedrecentchanges-example-30days": "Visa senaste ändringar för 30 dygn",
        "apihelp-feedwatchlist-summary": "Returnerar ett flöde från bevakningslistan.",
index ca0b0a8..f55f65e 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "Фільтрувати за теґом.",
        "apihelp-feedrecentchanges-param-target": "Показати лише зміни на сторінках, на які посилається ця сторінка.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Показати натомість лише зміни на сторінках, які посилаються на цю сторінку.",
-       "apihelp-feedrecentchanges-param-categories": "Показати лише зміни сторінок у всіх цих категоріях.",
-       "apihelp-feedrecentchanges-param-categories_any": "Показати натомість лише зміни на сторінках у будь-якій з цих категорій.",
        "apihelp-feedrecentchanges-example-simple": "Показати нещодавні зміни.",
        "apihelp-feedrecentchanges-example-30days": "Показати нещодавні зміни за 30 днів.",
        "apihelp-feedwatchlist-summary": "Видає стрічку списку спостереження.",
index d09ccad..5eec830 100644 (file)
        "apihelp-feedrecentchanges-param-tagfilter": "按标签过滤。",
        "apihelp-feedrecentchanges-param-target": "仅仅显示从该页面链出的那些页面的变更。",
        "apihelp-feedrecentchanges-param-showlinkedto": "仅仅显示链入到该页面的那些页面的变更。",
-       "apihelp-feedrecentchanges-param-categories": "只显示所有这些分类中的页面上的更改。",
-       "apihelp-feedrecentchanges-param-categories_any": "只显示这些分类以外页面的更改。",
        "apihelp-feedrecentchanges-example-simple": "显示最近更改。",
        "apihelp-feedrecentchanges-example-30days": "显示最近30天的更改。",
        "apihelp-feedwatchlist-summary": "返回监视列表纲要。",
index b8e36bc..cd0734d 100644 (file)
@@ -272,7 +272,7 @@ class AuthPluginPrimaryAuthenticationProvider
                        if ( $failed ) {
                                throw new \UnexpectedValueException(
                                        "AuthPlugin failed to reset password for $username in the following domains: "
-                                               . join( ' ', $failed )
+                                               . implode( ' ', $failed )
                                );
                        }
                }
index d5ff6cb..71fcd8b 100644 (file)
@@ -300,7 +300,7 @@ class MessageCache {
                }
 
                if ( !$success ) {
-                       $cacheKey = $this->clusterCache->makeKey( 'messages', $code ); # Key in memc for messages
+                       $cacheKey = $this->clusterCache->makeKey( 'messages', $code );
                        # Try the global cache. If it is empty, try to acquire a lock. If
                        # the lock can't be acquired, wait for the other thread to finish
                        # and then try the global cache a second time.
@@ -613,7 +613,7 @@ class MessageCache {
                                // load() calls do try to refresh the cache with replica DB data
                                $this->mCache[$code]['LATEST'] = time();
                                // Pre-emptively update the local datacenter cache so things like edit filter and
-                               // blacklist changes are reflect immediately, as these often use MediaWiki: pages.
+                               // blacklist changes are reflected immediately; these often use MediaWiki: pages.
                                // The datacenter handling replace() calls should be the same one handling edits
                                // as they require HTTP POST.
                                $this->saveToCaches( $this->mCache[$code], 'all', $code );
@@ -622,19 +622,7 @@ class MessageCache {
 
                                // Relay the purge. Touching this check key expires cache contents
                                // and local cache (APC) validation hash across all datacenters.
-                               $this->wanCache->touchCheckKey( $this->wanCache->makeKey( 'messages', $code ) );
-                               // Also delete cached sidebar... just in case it is affected
-                               // @TODO: shouldn't this be $code === $wgLanguageCode?
-                               if ( $code === 'en' ) {
-                                       // Purge all language sidebars, e.g. on ?action=purge to the sidebar messages
-                                       $codes = array_keys( Language::fetchLanguageNames() );
-                               } else {
-                                       // Purge only the sidebar for this language
-                                       $codes = [ $code ];
-                               }
-                               foreach ( $codes as $code ) {
-                                       $this->wanCache->delete( $this->wanCache->makeKey( 'sidebar', $code ) );
-                               }
+                               $this->wanCache->touchCheckKey( $this->getCheckKey( $code ) );
 
                                // Purge the message in the message blob store
                                $resourceloader = RequestContext::getMain()->getOutput()->getResourceLoader();
@@ -701,7 +689,7 @@ class MessageCache {
                $value = $this->wanCache->get(
                        $this->wanCache->makeKey( 'messages', $code, 'hash', 'v1' ),
                        $curTTL,
-                       [ $this->wanCache->makeKey( 'messages', $code ) ]
+                       [ $this->getCheckKey( $code ) ]
                );
 
                if ( $value ) {
@@ -906,7 +894,7 @@ class MessageCache {
                if ( $useDB ) {
                        $uckey = $wgContLang->ucfirst( $lckey );
 
-                       if ( !isset( $alreadyTried[ $langcode ] ) ) {
+                       if ( !isset( $alreadyTried[$langcode] ) ) {
                                $message = $this->getMsgFromNamespace(
                                        $this->getMessagePageName( $langcode, $uckey ),
                                        $langcode
@@ -915,7 +903,7 @@ class MessageCache {
                                if ( $message !== false ) {
                                        return $message;
                                }
-                               $alreadyTried[ $langcode ] = true;
+                               $alreadyTried[$langcode] = true;
                        }
                } else {
                        $uckey = null;
@@ -932,7 +920,7 @@ class MessageCache {
                        $fallbackChain = Language::getFallbacksFor( $langcode );
 
                        foreach ( $fallbackChain as $code ) {
-                               if ( isset( $alreadyTried[ $code ] ) ) {
+                               if ( isset( $alreadyTried[$code] ) ) {
                                        continue;
                                }
 
@@ -942,7 +930,7 @@ class MessageCache {
                                if ( $message !== false ) {
                                        return $message;
                                }
-                               $alreadyTried[ $code ] = true;
+                               $alreadyTried[$code] = true;
                        }
                }
 
@@ -985,13 +973,12 @@ class MessageCache {
                if ( isset( $this->mCache[$code][$title] ) ) {
                        $entry = $this->mCache[$code][$title];
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
-                               // The message exists, so make sure a string is returned.
+                               // The message exists and is not '!TOO BIG'
                                return (string)substr( $entry, 1 );
                        } elseif ( $entry === '!NONEXISTENT' ) {
                                return false;
-                       } elseif ( $entry === '!TOO BIG' ) {
-                               // Fall through and try invididual message cache below
                        }
+                       // Fall through and try invididual message cache below
                } else {
                        // XXX: This is not cached in process cache, should it?
                        $message = false;
@@ -1077,11 +1064,11 @@ class MessageCache {
        /**
         * @param string $message
         * @param bool $interface
-        * @param string $language Language code
+        * @param Language $language
         * @param Title $title
         * @return string
         */
-       function transform( $message, $interface = false, $language = null, $title = null ) {
+       public function transform( $message, $interface = false, $language = null, $title = null ) {
                // Avoid creating parser if nothing to transform
                if ( strpos( $message, '{{' ) === false ) {
                        return $message;
@@ -1110,7 +1097,7 @@ class MessageCache {
        /**
         * @return Parser
         */
-       function getParser() {
+       public function getParser() {
                global $wgParser, $wgParserConf;
 
                if ( !$this->mParser && isset( $wgParser ) ) {
@@ -1174,11 +1161,11 @@ class MessageCache {
                return $res;
        }
 
-       function disable() {
+       public function disable() {
                $this->mDisable = true;
        }
 
-       function enable() {
+       public function enable() {
                $this->mDisable = false;
        }
 
@@ -1199,13 +1186,14 @@ class MessageCache {
        }
 
        /**
-        * Clear all stored messages. Mainly used after a mass rebuild.
+        * Clear all stored messages in global and local cache
+        *
+        * Mainly used after a mass rebuild
         */
        function clear() {
                $langs = Language::fetchLanguageNames( null, 'mw' );
                foreach ( array_keys( $langs ) as $code ) {
-                       # Global and local caches
-                       $this->wanCache->touchCheckKey( $this->wanCache->makeKey( 'messages', $code ) );
+                       $this->wanCache->touchCheckKey( $this->getCheckKey( $code ) );
                }
 
                $this->mLoadedLanguages = [];
@@ -1283,6 +1271,14 @@ class MessageCache {
                }
        }
 
+       /**
+        * @param string $code Language code
+        * @return string WAN cache key usable as a "check key" against language page edits
+        */
+       public function getCheckKey( $code ) {
+               return $this->wanCache->makeKey( 'messages', $code );
+       }
+
        /**
         * @param Content|null $content Content or null if the message page does not exist
         * @return string|bool|null Returns false if $content is null and null on error
index 7e4dd00..b30b82d 100644 (file)
@@ -181,6 +181,28 @@ class ChangeTags {
                return $msg;
        }
 
+       /**
+        * Get truncated message for the tag's long description.
+        *
+        * @param string $tag Tag name.
+        * @param int $length Maximum length of truncated message, including ellipsis.
+        * @param IContextSource $context
+        *
+        * @return string Truncated long tag description.
+        */
+       public static function truncateTagDescription( $tag, $length, IContextSource $context ) {
+               $originalDesc = self::tagLongDescriptionMessage( $tag, $context );
+               // If there is no tag description, return empty string
+               if ( !$originalDesc ) {
+                       return '';
+               }
+
+               $taglessDesc = Sanitizer::stripAllTags( $originalDesc->parse() );
+               $escapedDesc = Sanitizer::escapeHtmlAllowEntities( $taglessDesc );
+
+               return $context->getLanguage()->truncateForVisual( $escapedDesc, $length );
+       }
+
        /**
         * Add tags to a change given its rc_id, rev_id and/or log_id
         *
index eb28b30..156e315 100644 (file)
@@ -61,7 +61,7 @@ class DatabaseOracle extends Database {
        }
 
        function __destruct() {
-               if ( $this->mOpened ) {
+               if ( $this->opened ) {
                        Wikimedia\suppressWarnings();
                        $this->close();
                        Wikimedia\restoreWarnings();
@@ -100,21 +100,21 @@ class DatabaseOracle extends Database {
                }
 
                $this->close();
-               $this->mUser = $user;
-               $this->mPassword = $password;
+               $this->user = $user;
+               $this->password = $password;
                // changed internal variables functions
                // mServer now holds the TNS endpoint
                // mDBname is schema name if different from username
                if ( !$server ) {
                        // backward compatibillity (server used to be null and TNS was supplied in dbname)
-                       $this->mServer = $dbName;
-                       $this->mDBname = $user;
+                       $this->server = $dbName;
+                       $this->dbName = $user;
                } else {
-                       $this->mServer = $server;
+                       $this->server = $server;
                        if ( !$dbName ) {
-                               $this->mDBname = $user;
+                               $this->dbName = $user;
                        } else {
-                               $this->mDBname = $dbName;
+                               $this->dbName = $dbName;
                        }
                }
 
@@ -126,53 +126,53 @@ class DatabaseOracle extends Database {
                        $this->setFlag( DBO_PERSISTENT );
                }
 
-               $session_mode = $this->mFlags & DBO_SYSDBA ? OCI_SYSDBA : OCI_DEFAULT;
+               $session_mode = $this->flags & DBO_SYSDBA ? OCI_SYSDBA : OCI_DEFAULT;
 
                Wikimedia\suppressWarnings();
-               if ( $this->mFlags & DBO_PERSISTENT ) {
-                       $this->mConn = oci_pconnect(
-                               $this->mUser,
-                               $this->mPassword,
-                               $this->mServer,
+               if ( $this->flags & DBO_PERSISTENT ) {
+                       $this->conn = oci_pconnect(
+                               $this->user,
+                               $this->password,
+                               $this->server,
                                $this->defaultCharset,
                                $session_mode
                        );
-               } elseif ( $this->mFlags & DBO_DEFAULT ) {
-                       $this->mConn = oci_new_connect(
-                               $this->mUser,
-                               $this->mPassword,
-                               $this->mServer,
+               } elseif ( $this->flags & DBO_DEFAULT ) {
+                       $this->conn = oci_new_connect(
+                               $this->user,
+                               $this->password,
+                               $this->server,
                                $this->defaultCharset,
                                $session_mode
                        );
                } else {
-                       $this->mConn = oci_connect(
-                               $this->mUser,
-                               $this->mPassword,
-                               $this->mServer,
+                       $this->conn = oci_connect(
+                               $this->user,
+                               $this->password,
+                               $this->server,
                                $this->defaultCharset,
                                $session_mode
                        );
                }
                Wikimedia\restoreWarnings();
 
-               if ( $this->mUser != $this->mDBname ) {
+               if ( $this->user != $this->dbName ) {
                        // change current schema in session
-                       $this->selectDB( $this->mDBname );
+                       $this->selectDB( $this->dbName );
                }
 
-               if ( !$this->mConn ) {
+               if ( !$this->conn ) {
                        throw new DBConnectionError( $this, $this->lastError() );
                }
 
-               $this->mOpened = true;
+               $this->opened = true;
 
                # removed putenv calls because they interfere with the system globaly
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
                $this->doQuery( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
 
-               return $this->mConn;
+               return $this->conn;
        }
 
        /**
@@ -181,11 +181,11 @@ class DatabaseOracle extends Database {
         * @return bool
         */
        protected function closeConnection() {
-               return oci_close( $this->mConn );
+               return oci_close( $this->conn );
        }
 
        function execFlags() {
-               return $this->mTrxLevel ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
+               return $this->trxLevel ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
        }
 
        protected function doQuery( $sql ) {
@@ -217,9 +217,9 @@ class DatabaseOracle extends Database {
 
                Wikimedia\suppressWarnings();
 
-               $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql );
+               $this->mLastResult = $stmt = oci_parse( $this->conn, $sql );
                if ( $stmt === false ) {
-                       $e = oci_error( $this->mConn );
+                       $e = oci_error( $this->conn );
                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
 
                        return false;
@@ -335,20 +335,20 @@ class DatabaseOracle extends Database {
        }
 
        function lastError() {
-               if ( $this->mConn === false ) {
+               if ( $this->conn === false ) {
                        $e = oci_error();
                } else {
-                       $e = oci_error( $this->mConn );
+                       $e = oci_error( $this->conn );
                }
 
                return $e['message'];
        }
 
        function lastErrno() {
-               if ( $this->mConn === false ) {
+               if ( $this->conn === false ) {
                        $e = oci_error();
                } else {
-                       $e = oci_error( $this->mConn );
+                       $e = oci_error( $this->conn );
                }
 
                return $e['code'];
@@ -470,9 +470,9 @@ class DatabaseOracle extends Database {
                }
                $sql .= ')';
 
-               $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql );
+               $this->mLastResult = $stmt = oci_parse( $this->conn, $sql );
                if ( $stmt === false ) {
-                       $e = oci_error( $this->mConn );
+                       $e = oci_error( $this->conn );
                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
 
                        return false;
@@ -502,7 +502,7 @@ class DatabaseOracle extends Database {
                                }
                        } else {
                                /** @var OCI_Lob[] $lob */
-                               $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB );
+                               $lob[$col] = oci_new_descriptor( $this->conn, OCI_D_LOB );
                                if ( $lob[$col] === false ) {
                                        $e = oci_error( $stmt );
                                        throw new DBUnexpectedError( $this, "Cannot create LOB descriptor: " . $e['message'] );
@@ -545,8 +545,8 @@ class DatabaseOracle extends Database {
                        }
                }
 
-               if ( !$this->mTrxLevel ) {
-                       oci_commit( $this->mConn );
+               if ( !$this->trxLevel ) {
+                       oci_commit( $this->conn );
                }
 
                return oci_free_statement( $stmt );
@@ -658,13 +658,13 @@ class DatabaseOracle extends Database {
                        FROM all_sequences asq, all_tab_columns atc
                        WHERE decode(
                                        atc.table_name,
-                                       '{$this->mTablePrefix}MWUSER',
-                                       '{$this->mTablePrefix}USER',
+                                       '{$this->tablePrefix}MWUSER',
+                                       '{$this->tablePrefix}USER',
                                        atc.table_name
                                ) || '_' ||
-                               atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
-                               AND asq.sequence_owner = upper('{$this->mDBname}')
-                               AND atc.owner = upper('{$this->mDBname}')" );
+                               atc.column_name || '_SEQ' = '{$this->tablePrefix}' || asq.sequence_name
+                               AND asq.sequence_owner = upper('{$this->dbName}')
+                               AND atc.owner = upper('{$this->dbName}')" );
 
                        while ( ( $row = $result->fetchRow() ) !== false ) {
                                $this->sequenceData[$row[1]] = [
@@ -730,9 +730,9 @@ class DatabaseOracle extends Database {
                $newName = strtoupper( $newName );
                $oldName = strtoupper( $oldName );
 
-               $tabName = substr( $newName, strlen( $this->mTablePrefix ) );
+               $tabName = substr( $newName, strlen( $this->tablePrefix ) );
                $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
-               $newPrefix = strtoupper( $this->mTablePrefix );
+               $newPrefix = strtoupper( $this->tablePrefix );
 
                return $this->doQuery( "BEGIN DUPLICATE_TABLE( '$tabName', " .
                        "'$oldPrefix', '$newPrefix', $temporary ); END;" );
@@ -744,7 +744,7 @@ class DatabaseOracle extends Database {
                        $listWhere = ' AND table_name LIKE \'' . strtoupper( $prefix ) . '%\'';
                }
 
-               $owner = strtoupper( $this->mDBname );
+               $owner = strtoupper( $this->dbName );
                $result = $this->doQuery( "SELECT table_name FROM all_tables " .
                        "WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
 
@@ -805,7 +805,7 @@ class DatabaseOracle extends Database {
                );
                $row = $rset->fetchRow();
                if ( !$row ) {
-                       return oci_server_version( $this->mConn );
+                       return oci_server_version( $this->conn );
                }
 
                return $row['version'];
@@ -822,7 +822,7 @@ class DatabaseOracle extends Database {
                $table = $this->tableName( $table );
                $table = strtoupper( $this->removeIdentifierQuotes( $table ) );
                $index = strtoupper( $index );
-               $owner = strtoupper( $this->mDBname );
+               $owner = strtoupper( $this->dbName );
                $sql = "SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
                $res = $this->doQuery( $sql );
                if ( $res ) {
@@ -844,7 +844,7 @@ class DatabaseOracle extends Database {
        function tableExists( $table, $fname = __METHOD__ ) {
                $table = $this->tableName( $table );
                $table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
-               $owner = $this->addQuotes( strtoupper( $this->mDBname ) );
+               $owner = $this->addQuotes( strtoupper( $this->dbName ) );
                $sql = "SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
                $res = $this->doQuery( $sql );
                if ( $res && $res->numRows() > 0 ) {
@@ -890,7 +890,7 @@ class DatabaseOracle extends Database {
                }
 
                $fieldInfoStmt = oci_parse(
-                       $this->mConn,
+                       $this->conn,
                        'SELECT * FROM wiki_field_info_full WHERE table_name ' .
                                $tableWhere . ' and column_name = \'' . $field . '\''
                );
@@ -935,25 +935,25 @@ class DatabaseOracle extends Database {
        }
 
        protected function doBegin( $fname = __METHOD__ ) {
-               $this->mTrxLevel = 1;
+               $this->trxLevel = 1;
                $this->doQuery( 'SET CONSTRAINTS ALL DEFERRED' );
        }
 
        protected function doCommit( $fname = __METHOD__ ) {
-               if ( $this->mTrxLevel ) {
-                       $ret = oci_commit( $this->mConn );
+               if ( $this->trxLevel ) {
+                       $ret = oci_commit( $this->conn );
                        if ( !$ret ) {
                                throw new DBUnexpectedError( $this, $this->lastError() );
                        }
-                       $this->mTrxLevel = 0;
+                       $this->trxLevel = 0;
                        $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
                }
        }
 
        protected function doRollback( $fname = __METHOD__ ) {
-               if ( $this->mTrxLevel ) {
-                       oci_rollback( $this->mConn );
-                       $this->mTrxLevel = 0;
+               if ( $this->trxLevel ) {
+                       oci_rollback( $this->conn );
+                       $this->trxLevel = 0;
                        $this->doQuery( 'SET CONSTRAINTS ALL IMMEDIATE' );
                }
        }
@@ -1041,12 +1041,12 @@ class DatabaseOracle extends Database {
        }
 
        function selectDB( $db ) {
-               $this->mDBname = $db;
-               if ( $db == null || $db == $this->mUser ) {
+               $this->dbName = $db;
+               if ( $db == null || $db == $this->user ) {
                        return true;
                }
                $sql = 'ALTER SESSION SET CURRENT_SCHEMA=' . strtoupper( $db );
-               $stmt = oci_parse( $this->mConn, $sql );
+               $stmt = oci_parse( $this->conn, $sql );
                Wikimedia\suppressWarnings();
                $success = oci_execute( $stmt );
                Wikimedia\restoreWarnings();
@@ -1245,9 +1245,9 @@ class DatabaseOracle extends Database {
                        $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
                }
 
-               $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql );
+               $this->mLastResult = $stmt = oci_parse( $this->conn, $sql );
                if ( $stmt === false ) {
-                       $e = oci_error( $this->mConn );
+                       $e = oci_error( $this->conn );
                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
 
                        return false;
@@ -1276,7 +1276,7 @@ class DatabaseOracle extends Database {
                                }
                        } else {
                                /** @var OCI_Lob[] $lob */
-                               $lob[$col] = oci_new_descriptor( $this->mConn, OCI_D_LOB );
+                               $lob[$col] = oci_new_descriptor( $this->conn, OCI_D_LOB );
                                if ( $lob[$col] === false ) {
                                        $e = oci_error( $stmt );
                                        throw new DBUnexpectedError( $this, "Cannot create LOB descriptor: " . $e['message'] );
@@ -1319,8 +1319,8 @@ class DatabaseOracle extends Database {
                        }
                }
 
-               if ( !$this->mTrxLevel ) {
-                       oci_commit( $this->mConn );
+               if ( !$this->trxLevel ) {
+                       oci_commit( $this->conn );
                }
 
                return oci_free_statement( $stmt );
@@ -1340,11 +1340,11 @@ class DatabaseOracle extends Database {
        }
 
        function getDBname() {
-               return $this->mDBname;
+               return $this->dbName;
        }
 
        function getServer() {
-               return $this->mServer;
+               return $this->server;
        }
 
        public function buildGroupConcatField(
index ad1f172..2f882b8 100644 (file)
@@ -101,9 +101,7 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
                $pd = [];
                if ( $config->get( 'SiteStatsAsyncFactor' ) ) {
                        // Lock the table so we don't have double DB/memcached updates
-                       if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
-                               || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout
-                       ) {
+                       if ( !$dbw->lock( $lockKey, __METHOD__, 0 ) ) {
                                $this->doUpdatePendingDeltas();
 
                                return;
index 16f226c..b3e9422 100644 (file)
@@ -189,7 +189,7 @@ class MWException extends Exception {
                } elseif ( self::isCommandLine() ) {
                        $message = $this->getText();
                        // T17602: STDERR may not be available
-                       if ( defined( 'STDERR' ) ) {
+                       if ( !defined( 'MW_PHPUNIT_TEST' ) && defined( 'STDERR' ) ) {
                                fwrite( STDERR, $message );
                        } else {
                                echo $message;
diff --git a/includes/import/ImportableOldRevision.php b/includes/import/ImportableOldRevision.php
new file mode 100644 (file)
index 0000000..6d1e242
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @since 1.31
+ */
+interface ImportableOldRevision {
+
+       /**
+        * @since 1.31
+        * @return User
+        */
+       public function getUserObj();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getUser();
+
+       /**
+        * @since 1.31
+        * @return Title
+        */
+       public function getTitle();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getTimestamp();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getComment();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getModel();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getFormat();
+
+       /**
+        * @since 1.31
+        * @return Content
+        */
+       public function getContent();
+
+       /**
+        * @since 1.31
+        * @return bool
+        */
+       public function getMinor();
+
+       /**
+        * @since 1.31
+        * @return bool|string
+        */
+       public function getSha1Base36();
+
+}
diff --git a/includes/import/ImportableOldRevisionImporter.php b/includes/import/ImportableOldRevisionImporter.php
new file mode 100644 (file)
index 0000000..33fad3e
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+
+use Psr\Log\LoggerInterface;
+use Wikimedia\Rdbms\LoadBalancer;
+
+/**
+ * @since 1.31
+ */
+class ImportableOldRevisionImporter implements OldRevisionImporter {
+
+       /**
+        * @var LoggerInterface
+        */
+       private $logger;
+
+       /**
+        * @var bool
+        */
+       private $doUpdates;
+
+       /**
+        * @var LoadBalancer
+        */
+       private $loadBalancer;
+
+       /**
+        * @param bool $doUpdates
+        * @param LoggerInterface $logger
+        * @param LoadBalancer $loadBalancer
+        */
+       public function __construct(
+               $doUpdates,
+               LoggerInterface $logger,
+               LoadBalancer $loadBalancer
+       ) {
+               $this->doUpdates = $doUpdates;
+               $this->logger = $logger;
+               $this->loadBalancer = $loadBalancer;
+       }
+
+       public function import( ImportableOldRevision $importableRevision, $doUpdates = true ) {
+               $dbw = $this->loadBalancer->getConnectionRef( DB_MASTER );
+
+               # Sneak a single revision into place
+               $user = $importableRevision->getUserObj() ?: User::newFromName( $importableRevision->getUser() );
+               if ( $user ) {
+                       $userId = intval( $user->getId() );
+                       $userText = $user->getName();
+               } else {
+                       $userId = 0;
+                       $userText = $importableRevision->getUser();
+                       $user = new User;
+               }
+
+               // avoid memory leak...?
+               Title::clearCaches();
+
+               $page = WikiPage::factory( $importableRevision->getTitle() );
+               $page->loadPageData( 'fromdbmaster' );
+               if ( !$page->exists() ) {
+                       // must create the page...
+                       $pageId = $page->insertOn( $dbw );
+                       $created = true;
+                       $oldcountable = null;
+               } else {
+                       $pageId = $page->getId();
+                       $created = false;
+
+                       // Note: sha1 has been in XML dumps since 2012. If you have an
+                       // older dump, the duplicate detection here won't work.
+                       $prior = $dbw->selectField( 'revision', '1',
+                               [ 'rev_page' => $pageId,
+                                       'rev_timestamp' => $dbw->timestamp( $importableRevision->getTimestamp() ),
+                                       'rev_sha1' => $importableRevision->getSha1Base36() ],
+                               __METHOD__
+                       );
+                       if ( $prior ) {
+                               // @todo FIXME: This could fail slightly for multiple matches :P
+                               $this->logger->debug( __METHOD__ . ": skipping existing revision for [[" .
+                                       $importableRevision->getTitle()->getPrefixedText() . "]], timestamp " .
+                                       $importableRevision->getTimestamp() . "\n" );
+                               return false;
+                       }
+               }
+
+               if ( !$pageId ) {
+                       // This seems to happen if two clients simultaneously try to import the
+                       // same page
+                       $this->logger->debug( __METHOD__ . ': got invalid $pageId when importing revision of [[' .
+                               $importableRevision->getTitle()->getPrefixedText() . ']], timestamp ' .
+                               $importableRevision->getTimestamp() . "\n" );
+                       return false;
+               }
+
+               // Select previous version to make size diffs correct
+               // @todo This assumes that multiple revisions of the same page are imported
+               // in order from oldest to newest.
+               $prevId = $dbw->selectField( 'revision', 'rev_id',
+                       [
+                               'rev_page' => $pageId,
+                               'rev_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $importableRevision->getTimestamp() ) ),
+                       ],
+                       __METHOD__,
+                       [ 'ORDER BY' => [
+                               'rev_timestamp DESC',
+                               'rev_id DESC', // timestamp is not unique per page
+                       ]
+                       ]
+               );
+
+               # @todo FIXME: Use original rev_id optionally (better for backups)
+               # Insert the row
+               $revision = new Revision( [
+                       'title' => $importableRevision->getTitle(),
+                       'page' => $pageId,
+                       'content_model' => $importableRevision->getModel(),
+                       'content_format' => $importableRevision->getFormat(),
+                       // XXX: just set 'content' => $wikiRevision->getContent()?
+                       'text' => $importableRevision->getContent()->serialize( $importableRevision->getFormat() ),
+                       'comment' => $importableRevision->getComment(),
+                       'user' => $userId,
+                       'user_text' => $userText,
+                       'timestamp' => $importableRevision->getTimestamp(),
+                       'minor_edit' => $importableRevision->getMinor(),
+                       'parent_id' => $prevId,
+               ] );
+               $revision->insertOn( $dbw );
+               $changed = $page->updateIfNewerOn( $dbw, $revision );
+
+               if ( $changed !== false && $this->doUpdates ) {
+                       $this->logger->debug( __METHOD__ . ": running updates\n" );
+                       // countable/oldcountable stuff is handled in WikiImporter::finishImportPage
+                       $page->doEditUpdates(
+                               $revision,
+                               $user,
+                               [ 'created' => $created, 'oldcountable' => 'no-change' ]
+                       );
+               }
+
+               return true;
+       }
+
+}
diff --git a/includes/import/ImportableUploadRevision.php b/includes/import/ImportableUploadRevision.php
new file mode 100644 (file)
index 0000000..3f60112
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @since 1.31
+ */
+interface ImportableUploadRevision {
+
+       /**
+        * @since 1.31
+        * @return string Archive name of a revision if archived.
+        */
+       public function getArchiveName();
+
+       /**
+        * @since 1.31
+        * @return Title
+        */
+       public function getTitle();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getTimestamp();
+
+       /**
+        * @since 1.31
+        * @return string|null HTTP source of revision to be used for downloading.
+        */
+       public function getSrc();
+
+       /**
+        * @since 1.31
+        * @return string Local file source of the revision.
+        */
+       public function getFileSrc();
+
+       /**
+        * @since 1.31
+        * @return bool Is the return of getFileSrc only temporary?
+        */
+       public function isTempSrc();
+
+       /**
+        * @since 1.31
+        * @return string|bool sha1 of the revision, false if not set or errors occour.
+        */
+       public function getSha1();
+
+       /**
+        * @since 1.31
+        * @return User
+        */
+       public function getUserObj();
+
+       /**
+        * @since 1.31
+        * @return string The username of the user that created this revision
+        */
+       public function getUser();
+
+       /**
+        * @since 1.31
+        * @return string
+        */
+       public function getComment();
+
+}
diff --git a/includes/import/ImportableUploadRevisionImporter.php b/includes/import/ImportableUploadRevisionImporter.php
new file mode 100644 (file)
index 0000000..495b3d6
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+
+use Psr\Log\LoggerInterface;
+
+/**
+ * @since 1.31
+ */
+class ImportableUploadRevisionImporter implements UploadRevisionImporter {
+
+       /**
+        * @var LoggerInterface
+        */
+       private $logger;
+
+       /**
+        * @var bool
+        */
+       private $enableUploads;
+
+       /**
+        * @param bool $enableUploads
+        * @param LoggerInterface $logger
+        */
+       public function __construct(
+               $enableUploads,
+               LoggerInterface $logger
+       ) {
+               $this->enableUploads = $enableUploads;
+               $this->logger = $logger;
+       }
+
+       /**
+        * @return StatusValue
+        */
+       private function newNotOkStatus() {
+               $statusValue = new StatusValue();
+               $statusValue->setOK( false );
+               return $statusValue;
+       }
+
+       public function import( ImportableUploadRevision $importableRevision ) {
+               # Construct a file
+               $archiveName = $importableRevision->getArchiveName();
+               if ( $archiveName ) {
+                       $this->logger->debug( __METHOD__ . "Importing archived file as $archiveName\n" );
+                       $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
+                               RepoGroup::singleton()->getLocalRepo(), $archiveName );
+               } else {
+                       $file = wfLocalFile( $importableRevision->getTitle() );
+                       $file->load( File::READ_LATEST );
+                       $this->logger->debug( __METHOD__ . 'Importing new file as ' . $file->getName() . "\n" );
+                       if ( $file->exists() && $file->getTimestamp() > $importableRevision->getTimestamp() ) {
+                               $archiveName = $file->getTimestamp() . '!' . $file->getName();
+                               $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
+                                       RepoGroup::singleton()->getLocalRepo(), $archiveName );
+                               $this->logger->debug( __METHOD__ . "File already exists; importing as $archiveName\n" );
+                       }
+               }
+               if ( !$file ) {
+                       $this->logger->debug( __METHOD__ . ': Bad file for ' . $importableRevision->getTitle() . "\n" );
+                       return $this->newNotOkStatus();
+               }
+
+               # Get the file source or download if necessary
+               $source = $importableRevision->getFileSrc();
+               $autoDeleteSource = $importableRevision->isTempSrc();
+               if ( !strlen( $source ) ) {
+                       $source = $this->downloadSource( $importableRevision );
+                       $autoDeleteSource = true;
+               }
+               if ( !strlen( $source ) ) {
+                       $this->logger->debug( __METHOD__ . ": Could not fetch remote file.\n" );
+                       return $this->newNotOkStatus();
+               }
+
+               $tmpFile = new TempFSFile( $source );
+               if ( $autoDeleteSource ) {
+                       $tmpFile->autocollect();
+               }
+
+               $sha1File = ltrim( sha1_file( $source ), '0' );
+               $sha1 = $importableRevision->getSha1();
+               if ( $sha1 && ( $sha1 !== $sha1File ) ) {
+                       $this->logger->debug( __METHOD__ . ": Corrupt file $source.\n" );
+                       return $this->newNotOkStatus();
+               }
+
+               $user = $importableRevision->getUserObj() ?: User::newFromName( $importableRevision->getUser() );
+
+               # Do the actual upload
+               if ( $archiveName ) {
+                       $status = $file->uploadOld( $source, $archiveName,
+                               $importableRevision->getTimestamp(), $importableRevision->getComment(), $user );
+               } else {
+                       $flags = 0;
+                       $status = $file->upload(
+                               $source,
+                               $importableRevision->getComment(),
+                               $importableRevision->getComment(),
+                               $flags,
+                               false,
+                               $importableRevision->getTimestamp(),
+                               $user
+                       );
+               }
+
+               if ( $status->isGood() ) {
+                       $this->logger->debug( __METHOD__ . ": Successful\n" );
+               } else {
+                       $this->logger->debug( __METHOD__ . ': failed: ' . $status->getHTML() . "\n" );
+               }
+
+               return $status;
+       }
+
+       /**
+        * @deprecated DO NOT CALL ME.
+        * This method was introduced when factoring UploadImporter out of WikiRevision.
+        * It only has 1 use by the deprecated downloadSource method in WikiRevision.
+        * Do not use this in new code.
+        *
+        * @param ImportableUploadRevision $wikiRevision
+        *
+        * @return bool|string
+        */
+       public function downloadSource( ImportableUploadRevision $wikiRevision ) {
+               if ( !$this->enableUploads ) {
+                       return false;
+               }
+
+               $tempo = tempnam( wfTempDir(), 'download' );
+               $f = fopen( $tempo, 'wb' );
+               if ( !$f ) {
+                       $this->logger->debug( "IMPORT: couldn't write to temp file $tempo\n" );
+                       return false;
+               }
+
+               // @todo FIXME!
+               $src = $wikiRevision->getSrc();
+               $data = Http::get( $src, [], __METHOD__ );
+               if ( !$data ) {
+                       $this->logger->debug( "IMPORT: couldn't fetch source $src\n" );
+                       fclose( $f );
+                       unlink( $tempo );
+                       return false;
+               }
+
+               fwrite( $f, $data );
+               fclose( $f );
+
+               return $tempo;
+       }
+
+}
diff --git a/includes/import/OldRevisionImporter.php b/includes/import/OldRevisionImporter.php
new file mode 100644 (file)
index 0000000..72af43b
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @since 1.31
+ */
+interface OldRevisionImporter {
+
+       /**
+        * @since 1.31
+        *
+        * @param ImportableOldRevision $importableRevision
+        *
+        * @return bool Success
+        */
+       public function import( ImportableOldRevision $importableRevision );
+
+}
diff --git a/includes/import/UploadRevisionImporter.php b/includes/import/UploadRevisionImporter.php
new file mode 100644 (file)
index 0000000..966fc11
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @since 1.31
+ */
+interface UploadRevisionImporter {
+
+       /**
+        * @since 1.31
+        *
+        * @param ImportableUploadRevision $importableUploadRevision
+        *
+        * @return StatusValue On success, the value member contains the
+        *     archive name, or an empty string if it was a new file.
+        */
+       public function import( ImportableUploadRevision $importableUploadRevision );
+
+}
index 3513f8c..4325a1a 100644 (file)
@@ -23,6 +23,8 @@
  * @file
  * @ingroup SpecialPage
  */
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Represents a revision, log entry or upload during the import process.
@@ -32,7 +34,7 @@
  *
  * @ingroup SpecialPage
  */
-class WikiRevision {
+class WikiRevision implements ImportableUploadRevision, ImportableOldRevision {
 
        /**
         * @since 1.17
@@ -170,9 +172,9 @@ class WikiRevision {
 
        /**
         * @since 1.12.2
-        * @var mixed
+        * @var string|null
         */
-       protected $src;
+       protected $src = null;
 
        /**
         * @since 1.18
@@ -298,7 +300,7 @@ class WikiRevision {
 
        /**
         * @since 1.12.2
-        * @param mixed $src
+        * @param string|null $src
         */
        public function setSrc( $src ) {
                $this->src = $src;
@@ -494,7 +496,7 @@ class WikiRevision {
 
        /**
         * @since 1.12.2
-        * @return mixed
+        * @return string|null
         */
        public function getSrc() {
                return $this->src;
@@ -511,6 +513,17 @@ class WikiRevision {
                return false;
        }
 
+       /**
+        * @since 1.31
+        * @return bool|string
+        */
+       public function getSha1Base36() {
+               if ( $this->sha1base36 ) {
+                       return $this->sha1base36;
+               }
+               return false;
+       }
+
        /**
         * @since 1.17
         * @return string
@@ -577,106 +590,16 @@ class WikiRevision {
 
        /**
         * @since 1.4.1
+        * @deprecated in 1.31. Use OldRevisionImporter::import
         * @return bool
         */
        public function importOldRevision() {
-               $dbw = wfGetDB( DB_MASTER );
-
-               # Sneak a single revision into place
-               $user = $this->getUserObj() ?: User::newFromName( $this->getUser() );
-               if ( $user ) {
-                       $userId = intval( $user->getId() );
-                       $userText = $user->getName();
-               } else {
-                       $userId = 0;
-                       $userText = $this->getUser();
-                       $user = new User;
-               }
-
-               // avoid memory leak...?
-               Title::clearCaches();
-
-               $page = WikiPage::factory( $this->title );
-               $page->loadPageData( 'fromdbmaster' );
-               if ( !$page->exists() ) {
-                       // must create the page...
-                       $pageId = $page->insertOn( $dbw );
-                       $created = true;
-                       $oldcountable = null;
+               if ( $this->mNoUpdates ) {
+                       $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporterNoUpdates();
                } else {
-                       $pageId = $page->getId();
-                       $created = false;
-
-                       // Note: sha1 has been in XML dumps since 2012. If you have an
-                       // older dump, the duplicate detection here won't work.
-                       $prior = $dbw->selectField( 'revision', '1',
-                               [ 'rev_page' => $pageId,
-                                       'rev_timestamp' => $dbw->timestamp( $this->timestamp ),
-                                       'rev_sha1' => $this->sha1base36 ],
-                               __METHOD__
-                       );
-                       if ( $prior ) {
-                               // @todo FIXME: This could fail slightly for multiple matches :P
-                               wfDebug( __METHOD__ . ": skipping existing revision for [[" .
-                                       $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n" );
-                               return false;
-                       }
-               }
-
-               if ( !$pageId ) {
-                       // This seems to happen if two clients simultaneously try to import the
-                       // same page
-                       wfDebug( __METHOD__ . ': got invalid $pageId when importing revision of [[' .
-                               $this->title->getPrefixedText() . ']], timestamp ' . $this->timestamp . "\n" );
-                       return false;
+                       $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporter();
                }
-
-               // Select previous version to make size diffs correct
-               // @todo This assumes that multiple revisions of the same page are imported
-               // in order from oldest to newest.
-               $prevId = $dbw->selectField( 'revision', 'rev_id',
-                       [
-                               'rev_page' => $pageId,
-                               'rev_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $this->timestamp ) ),
-                       ],
-                       __METHOD__,
-                       [ 'ORDER BY' => [
-                                       'rev_timestamp DESC',
-                                       'rev_id DESC', // timestamp is not unique per page
-                               ]
-                       ]
-               );
-
-               # @todo FIXME: Use original rev_id optionally (better for backups)
-               # Insert the row
-               $revision = new Revision( [
-                       'title' => $this->title,
-                       'page' => $pageId,
-                       'content_model' => $this->getModel(),
-                       'content_format' => $this->getFormat(),
-                       // XXX: just set 'content' => $this->getContent()?
-                       'text' => $this->getContent()->serialize( $this->getFormat() ),
-                       'comment' => $this->getComment(),
-                       'user' => $userId,
-                       'user_text' => $userText,
-                       'timestamp' => $this->timestamp,
-                       'minor_edit' => $this->minor,
-                       'parent_id' => $prevId,
-                       ] );
-               $revision->insertOn( $dbw );
-               $changed = $page->updateIfNewerOn( $dbw, $revision );
-
-               if ( $changed !== false && !$this->mNoUpdates ) {
-                       wfDebug( __METHOD__ . ": running updates\n" );
-                       // countable/oldcountable stuff is handled in WikiImporter::finishImportPage
-                       $page->doEditUpdates(
-                               $revision,
-                               $user,
-                               [ 'created' => $created, 'oldcountable' => 'no-change' ]
-                       );
-               }
-
-               return true;
+               return $importer->import( $this );
        }
 
        /**
@@ -737,106 +660,26 @@ class WikiRevision {
 
        /**
         * @since 1.12.2
+        * @deprecated in 1.31. Use UploadImporter::import
         * @return bool
         */
        public function importUpload() {
-               # Construct a file
-               $archiveName = $this->getArchiveName();
-               if ( $archiveName ) {
-                       wfDebug( __METHOD__ . "Importing archived file as $archiveName\n" );
-                       $file = OldLocalFile::newFromArchiveName( $this->getTitle(),
-                               RepoGroup::singleton()->getLocalRepo(), $archiveName );
-               } else {
-                       $file = wfLocalFile( $this->getTitle() );
-                       $file->load( File::READ_LATEST );
-                       wfDebug( __METHOD__ . 'Importing new file as ' . $file->getName() . "\n" );
-                       if ( $file->exists() && $file->getTimestamp() > $this->getTimestamp() ) {
-                               $archiveName = $file->getTimestamp() . '!' . $file->getName();
-                               $file = OldLocalFile::newFromArchiveName( $this->getTitle(),
-                                       RepoGroup::singleton()->getLocalRepo(), $archiveName );
-                               wfDebug( __METHOD__ . "File already exists; importing as $archiveName\n" );
-                       }
-               }
-               if ( !$file ) {
-                       wfDebug( __METHOD__ . ': Bad file for ' . $this->getTitle() . "\n" );
-                       return false;
-               }
-
-               # Get the file source or download if necessary
-               $source = $this->getFileSrc();
-               $autoDeleteSource = $this->isTempSrc();
-               if ( !strlen( $source ) ) {
-                       $source = $this->downloadSource();
-                       $autoDeleteSource = true;
-               }
-               if ( !strlen( $source ) ) {
-                       wfDebug( __METHOD__ . ": Could not fetch remote file.\n" );
-                       return false;
-               }
-
-               $tmpFile = new TempFSFile( $source );
-               if ( $autoDeleteSource ) {
-                       $tmpFile->autocollect();
-               }
-
-               $sha1File = ltrim( sha1_file( $source ), '0' );
-               $sha1 = $this->getSha1();
-               if ( $sha1 && ( $sha1 !== $sha1File ) ) {
-                       wfDebug( __METHOD__ . ": Corrupt file $source.\n" );
-                       return false;
-               }
-
-               $user = $this->getUserObj() ?: User::newFromName( $this->getUser() );
-
-               # Do the actual upload
-               if ( $archiveName ) {
-                       $status = $file->uploadOld( $source, $archiveName,
-                               $this->getTimestamp(), $this->getComment(), $user );
-               } else {
-                       $flags = 0;
-                       $status = $file->upload( $source, $this->getComment(), $this->getComment(),
-                               $flags, false, $this->getTimestamp(), $user );
-               }
-
-               if ( $status->isGood() ) {
-                       wfDebug( __METHOD__ . ": Successful\n" );
-                       return true;
-               } else {
-                       wfDebug( __METHOD__ . ': failed: ' . $status->getHTML() . "\n" );
-                       return false;
-               }
+               $importer = MediaWikiServices::getInstance()->getWikiRevisionUploadImporter();
+               $statusValue = $importer->import( $this );
+               return $statusValue->isGood();
        }
 
        /**
         * @since 1.12.2
+        * @deprecated in 1.31. Use UploadImporter::downloadSource
         * @return bool|string
         */
        public function downloadSource() {
-               if ( !$this->config->get( 'EnableUploads' ) ) {
-                       return false;
-               }
-
-               $tempo = tempnam( wfTempDir(), 'download' );
-               $f = fopen( $tempo, 'wb' );
-               if ( !$f ) {
-                       wfDebug( "IMPORT: couldn't write to temp file $tempo\n" );
-                       return false;
-               }
-
-               // @todo FIXME!
-               $src = $this->getSrc();
-               $data = Http::get( $src, [], __METHOD__ );
-               if ( !$data ) {
-                       wfDebug( "IMPORT: couldn't fetch source $src\n" );
-                       fclose( $f );
-                       unlink( $tempo );
-                       return false;
-               }
-
-               fwrite( $f, $data );
-               fclose( $f );
-
-               return $tempo;
+               $importer = new ImportableUploadRevisionImporter(
+                       $this->config->get( 'EnableUploads' ),
+                       LoggerFactory::getInstance( 'UploadRevisionImporter' )
+               );
+               return $importer->downloadSource( $this );
        }
 
 }
index 5b24d7c..92eef95 100644 (file)
@@ -63,7 +63,7 @@
        "config-apc": "[http://www.php.net/apc APC] ta instaláu",
        "config-apcu": "[http://www.php.net/apcu APCu] ta instaláu",
        "config-wincache": "[https://www.iis.net/download/WinCacheForPhp WinCache] ta instaláu",
-       "config-no-cache-apcu": "<strong>Warning:</strong> Non pudo atopase[http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] o [http://www.iis.net/download/WinCacheForPhp WinCache].\nEl caxé d'oxetos nun ta activáu.",
+       "config-no-cache-apcu": "<strong>Atención:</strong> Nun pudo alcontrase [http://www.php.net/apcu APCu] o [http://www.iis.net/download/WinCacheForPhp WinCache].\nLa caché d'oxetos nun ta activada.",
        "config-mod-security": "<strong>Alvertencia:</strong> El to servidor web tien activáu [https://modsecurity.org/mod_security]/mod_security2 .Munches de les sos configuraciones comunes pueden causar problemes a MediaWiki o otru software que dexe a los usuarios publicar conteníu arbitrario. De ser posible, tendríes de desactivalo. Si non, consulta la  [https://modsecurity.org/documentation/ mod_security documentation] o contacta col alministrador del to servidor si atopes erros aleatorios.",
        "config-diff3-bad": "Nun s'alcontró GNU diff3.",
        "config-git": "Alcontróse'l software de control de versiones Git: <code>$1</code>.",
index c1332b1..1b9a146 100644 (file)
@@ -24,7 +24,7 @@
                        "Pyscowicz"
                ]
        },
-       "config-desc": "MediaWiki-asennin",
+       "config-desc": "Asennin MediaWikiä varten",
        "config-title": "MediaWikin version $1 asennus",
        "config-information": "Tiedot",
        "config-localsettings-upgrade": "<code>LocalSettings.php</code>-tiedosto havaittiin.\nKirjoita muuttujan <code>$wgUpgradeKey</code> arvo alla olevaan kenttään päivittääksesi asennuksen.\nLöydät sen <code>LocalSettings.php</code>-tiedostosta.",
@@ -37,7 +37,7 @@
        "config-session-error": "Istunnon aloittaminen epäonnistui: $1",
        "config-session-expired": "Istuntotietosi näyttävät olevan vanhentuneita.\nIstuntojen elinajaksi on määritelty $1.\nVoit muuttaa tätä asetusta vaihtamalla kohtaa <code>session.gc_maxlifetime</code> php.ini-tiedostossa.\nKäynnistä asennusprosessi uudelleen.",
        "config-no-session": "Istuntosi tiedot menetettiin!\nTarkista php.ini-tiedostosi ja varmista, että <code>session.save_path</code> on asetettu sopivaan kansioon.",
-       "config-your-language": "Asennuksen kieli",
+       "config-your-language": "Kielesi:",
        "config-your-language-help": "Valitse kieli, jota haluat käyttää asennuksen ajan.",
        "config-wiki-language": "Wikin kieli",
        "config-wiki-language-help": "Valitse kieli, jota wikissä tullaan etupäässä käyttämään.",
        "config-no-cli-uploads-check": "<strong>Varoitus:</strong> Tiedostojen lähetyshakemistoa (<code>$1</code>) ei ole tarkistettu haavoittuvuuksien varalta komentoriviasennuksen aikana.",
        "config-brokenlibxml": "Järjestelmässäsi on käytössä PHP:n ja libxml2:n versioyhdistelmä, joka ei toimi kunnolla ja voi aiheuttaa tiedon vahingoittumista MediaWikissä ja muissa web-sovelluksissa.\nPäivitä libxml2 versioon 2.7.3 tai uudempaan ([https://bugs.php.net/bug.php?id=45996 bug filed with PHP]).\nAsennus keskeytetty.",
        "config-suhosin-max-value-length": "Suhosin on asennettu ja se rajoittaa GET-parametrin <code>length</code> $1 tavuun.\nMediaWikin ResourceLoader-komponentti pystyy toimimaan tämän kanssa, mutta ohjelmiston suorituskyky heikkenee.\nMikäli mahdollista, aseta muuttuja <code>suhosin.get.max_value_length</code> arvoon 1024 (tai suurempaan) tiedostossa <code>php.ini</code> ja aseta myös <code>$wgResourceLoaderMaxQueryLength</code> samaksi arvoksi tiedostossa <code>LocalSettings.php</code>.",
-       "config-db-type": "Tietokannan tyyppi",
-       "config-db-host": "Tietokantapalvelin",
+       "config-db-type": "Tietokannan tyyppi:",
+       "config-db-host": "Tietokantapalvelin:",
        "config-db-host-help": "Jos tietokantapalvelimesi sijaitsee eri palvelimella, syötä palvelimen nimi tai ip-osoite tähän.\n\nJos käytössäsi on ulkoinen palveluntarjoaja, pitäisi palvelimen nimen löytyä yrityksen ohjesivuilta.\n\nJos asennat MediaWikiä Windows-palvelimelle ja käytät MySQL:ää ei palvelimen nimi \"localhost\" välttämättä toimi. Tässä tapauksessa koita käyttää osoitetta 127.0.0.1.\n\nJos käytät PostgreSQL:ää jätä tämä kenttä tyhjäksi.",
        "config-db-host-oracle": "Tietokannan TNS:",
        "config-db-wiki-settings": "Identifioi tämä wiki",
-       "config-db-name": "Tietokannan nimi",
+       "config-db-name": "Tietokannan nimi:",
        "config-db-name-help": "Valitse wikiäsi kuvaava nimi.\nNimessä ei saa olla välilyöntejä.\n\nMikäli et pysty itse hallitsemaan tietokantojasi, pyydä palveluntarjoajaasi luomaan tietokanta tai tee se palveluntarjoajasi hallintapaneelissa.",
        "config-db-name-oracle": "Tietokannan rakenne:",
        "config-db-install-account": "Asennuksessa käytettävä käyttäjätili",
-       "config-db-username": "Tietokannan käyttäjätunnus",
-       "config-db-password": "Tietokannan salasana",
+       "config-db-username": "Tietokannan käyttäjätunnus:",
+       "config-db-password": "Tietokannan salasana:",
        "config-db-install-username": "Syötä käyttäjänimi jota käytetään muodostettaessa yhteys tietokantaan asennuksen aikana.\nTämä ei ole MediaWiki tilin käyttäjänimi; tämä on tietokannan käyttäjänimi.",
        "config-db-install-password": "Syötä salasana jota käytetään muodostettaessa yhteys tietokantaan asennuksen aikana.\nTämä ei ole MediaWiki tilin salasana; tämä on tietokannan salasana.",
        "config-db-install-help": "Anna käyttäjätunnus ja salasana, joita käytetään asennuksen aikana.",
        "config-mssql-web-auth": "Valitse varmennuksen tyyppi, jota verkkopalvelin käyttää yhdistäessään tietokantapalvelimeen wikin tavallisen toiminnan aikana.\nJos valitset \"{{int:config-mssql-windowsauth}}\", käytetään verkkopalvelimen käyttäjän kirjautumistietoja.",
        "config-mssql-sqlauth": "SQL Server varmennus",
        "config-mssql-windowsauth": "Windows-varmennus",
-       "config-site-name": "Wikin nimi",
+       "config-site-name": "Wikin nimi:",
        "config-site-name-help": "Tämä näkyy selaimen otsikkona ja muissa kohdissa.",
        "config-site-name-blank": "Kirjoita sivuston nimi.",
-       "config-project-namespace": "Projektinimiavaruus",
+       "config-project-namespace": "Projektinimiavaruus:",
        "config-ns-generic": "Projekti",
        "config-ns-site-name": "Sama kuin wikin nimi: $1",
        "config-ns-other": "Muu (määritä)",
        "config-ns-conflict": "Määritelty nimiavaruus \"<nowiki>$1</nowiki>\" on ristiriidassa MediaWikin oletusnimiavaruuksien kanssa.\nSyötä joku muu nimiavaruus.",
        "config-admin-box": "Ylläpitäjän tili",
        "config-admin-name": "Käyttäjänimesi:",
-       "config-admin-password": "Salasana",
-       "config-admin-password-confirm": "Salasana uudelleen",
+       "config-admin-password": "Salasana:",
+       "config-admin-password-confirm": "Salasana uudelleen:",
        "config-admin-help": "Syötä käyttäjänimi tähän, esimerkiksi \"Matti Meikäläinen\".\nTätä nimeä käytetään kirjauduttaessa wikiin.",
        "config-admin-name-blank": "Anna ylläpitäjän käyttäjänimi.",
        "config-admin-name-invalid": "Annettu nimi \"<nowiki>$1</nowiki>\" on virheellinen.\nSyötä toinen nimi.",
        "config-admin-password-blank": "Syötä ylläpitäjän salasana.",
        "config-admin-password-mismatch": "Antamasi salasanat eivät täsmää.",
-       "config-admin-email": "Sähköpostiosoite",
+       "config-admin-email": "Sähköpostiosoite:",
        "config-admin-email-help": "Syötä sähköpostiosoite johon vastaanotetaan viestit muilta wikin käyttäjiltä, nollataan salasana ja ilmoitetaan tarkkailulistalla olevista sivuista. Kenttä voidaan jättää myös tyhjäksi.",
        "config-admin-error-user": "Sisäinen virhe luodessa ylläpitäjää nimellä \"<nowiki>$1</nowiki>\".",
        "config-admin-error-password": "Sisäinen virhe asetettaessa salasanaa ylläpitäjälle \"<nowiki>$1</nowiki>\":\n<pre>$2</pre>",
        "config-upload-enable": "Ota käyttöön tiedostojen lataaminen",
        "config-upload-deleted": "Poistettujen tiedostojen hakemisto:",
        "config-upload-deleted-help": "Valitse hakemisto johon poistetut tiedostot arkistoidaan.\nHakemiston ei tulisi olla käytettävissä internetverkosta.",
-       "config-logo": "Logon URL-osoite",
+       "config-logo": "Logon URL-osoite:",
        "config-logo-help": "MediaWikin oletusulkoasussa on paikka 135x160 pikselin kokoiselle logolle sivupalkin yläpuolella.\nTallenna sopivan kokoinen kuva ja lisää URL tähän.\n\nVoit käyttää muuttujia <code>$wgStylePath</code> tai <code>$wgScriptPath</code>, jos logosi on määritelty suhteessa näihin polkuihin.\n\nJos et halua logoa, jätä tämä kenttä tyhjäksi.",
        "config-instantcommons": "Aktivoi Instant Commons",
        "config-instantcommons-help": "[https://www.mediawiki.org/wiki/InstantCommons Instant Commons] on ominaisuus, joka antaa wikien käyttää kuvia, ääniä ja muuta mediaa [https://commons.wikimedia.org/ Wikimedia Commons] -sivustolta.\nTehdäkseen tämän MediaWiki tarvitsee Internet-yhteyden.\n\nLisätietoja tästä ominaisuudesta, mukaan lukien ohjeet, kuinka sen voi asettaa muille wikeille kuin Wikimedia Commons, löytyy [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos ohjeista].",
        "config-install-keys": "Muodostetaan salausavaimia",
        "config-insecure-keys": "<strong>Varoitus:</strong> Asennuksen aikana {{PLURAL:$2|luotu turva-avain|luodut turva-avaimet}} ($1) {{PLURAL:$2|ei|eivät}} ole täysin {{PLURAL:$2|turvallinen|turvallisia}}. Harkitse {{PLURAL:$2|sen|niiden}} muuttamista manuaalisesti.",
        "config-install-updates": "Estä tarpeettomien päivitysten asennus",
+       "config-install-updates-failed": "<strong>Virhe:</strong> Päivitysavainten lisääminen taulukoihin epäonnistui seuraavalla virheellä: $1",
        "config-install-sysop": "Luodaan ylläpitäjän tiliä",
        "config-install-subscribe-fail": "Liittyminen mediawiki-announce listalle epäonnistui: $1",
        "config-install-subscribe-notpossible": "cURL-ohjelmaa ei ole asennettu eikä <code>allow_url_fopen</code> ole saatavilla.",
        "config-install-mainpage-failed": "Etusivun lisääminen ei onnistunut: $1",
        "config-install-done": "<strong>Onnittelut!</strong>\nOlet asentanut MediaWikin.\n\nAsennusohjelma on luonut <code>LocalSettings.php</code> -tiedoston.\nSiinä on kaikki MediaWikin asetukset.\n\nLataa tiedosto ja laita se MediaWikin asennushakemistoon (sama kuin missä on index.php). Lataamisen olisi pitänyt alkaa automaattisesti.\n\nMikäli latausta ei tarjottu tai keskeytit latauksen, käynnistä se uudestaan tästä linkistä:\n\n$3\n\n<strong>Huom:</strong> Mikäli et nyt lataa tiedostoa, luotu tiedosto ei ole saatavissa myöhemmin, jos poistut asennuksesta lataamatta sitä.\n\nKun olet laittanut tiedoston oikeaan paikkaan, voit <strong>[$2 mennä wikiisi]</strong>.",
        "config-install-done-path": "<strong>Onnittelut!</strong>\nOlet asentanut MediaWikin.\n\nAsennusohjelma on luonut <code>LocalSettings.php</code> -tiedoston.\nSiinä on kaikki MediaWikin asetukset.\n\nLataa tiedosto ja laita se sijaintiin <code>$4</code>. Lataamisen olisi pitänyt alkaa automaattisesti.\n\nMikäli latausta ei tarjottu tai keskeytit latauksen, käynnistä se uudestaan tästä linkistä:\n\n$3\n\n<strong>Huom:</strong> Mikäli et nyt lataa tiedostoa, luotu tiedosto ei ole saatavissa myöhemmin, jos poistut asennuksesta lataamatta sitä.\n\nKun olet laittanut tiedoston oikeaan paikkaan, voit <strong>[$2 mennä wikiisi]</strong>.",
+       "config-install-success": "MediaWiki on asennettu onnistuneesti. Voit nyt vierailla <$1$2> katsellaksesi wikiäsi. Jos sinulla on kysyttävää, \ntutustu usein kysyttyjen kysymysten luetteloon: <https://www.mediawiki.org/wiki/Manual:FAQ> tai käytä yhtä sivulle linkitettyä tukifoorumia.",
        "config-download-localsettings": "Lataa <code>LocalSettings.php</code>",
        "config-help": "ohje",
        "config-help-tooltip": "Klikkaa laajentaaksesi",
index b3aa137..953b672 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Ianbu",
-                       "唐吉訶德的侍從"
+                       "唐吉訶德的侍從",
+                       "Yoxem"
                ]
        },
        "config-desc": "MediaWiki的安裝程式",
@@ -13,7 +14,7 @@
        "config-localsettings-key": "Seng-kip--ê bi̍t-bé:",
        "config-localsettings-badkey": "Lí phah--ê bi̍t-bé bô chèng-khak.",
        "config-upgrade-key-missing": "已經有一个MediaWiki矣。若要升級,請共下面這逝加去<code>LocalSettings.php</code>的下跤:\n\n$1",
-       "config-localsettings-incomplete": "這馬的<code>LocalSettings.php</code>可能無齊全,因為無設變量$1。請佇<code>LocalSettings.php</code>設彼个變量,並且揤「{{int:Config-continue}}」。",
+       "config-localsettings-incomplete": "Chit-má--ê <code>LocalSettings.php</code> khó-lêng bô chiâu-chn̂g, in-ūi bô siat piān-liōng $1. Chhiáⁿ tī <code>LocalSettings.php</code> siat hit-ê piān-liōng, pēng-chhiá chhi̍h \"{{int:Config-continue}}\".",
        "config-localsettings-connection-error": "An error was encountered when connecting to the database 用<code>LocalSettings.php</code>的設定去連接資料庫的時陣有一个錯誤發生,請改遮的設定了,才閣試。\n\n$1",
        "config-session-error": "連線開始了的錯誤:$1",
        "config-session-expired": "你連線資料已經過時矣,連線的使用期限是設做$1。你會使改共php.ini的<code>session.gc_maxlifetime</code>改較長,並且重新安裝動作。",
        "config-help-restart": "你敢欲共你拍的佮保存的資料攏清掉,並且重開始安裝的動作?",
        "config-restart": "是,重來",
        "config-welcome": "=== 環境檢測 ===\n這馬欲做基本的檢測,看環境是毋是適合裝 MediaWiki。\n若你愛有支援,才裝會起來,請共遮的資訊記起來。",
-       "config-copyright": "=== 版權聲明佮授權條款 ===\n\n$1\n\n本程式是自由軟體;你會當照自由軟體基金會所發表的 GNU 通用公共授權條款規定,共本程式重新發佈抑是修改;無論你是照本授權條款的第二版抑第二版以後的任何版本(你會當家己選) 。\n\n本程式發佈的目的是希望會當提供幫助,但是 <strong>無負任何擔保責任</strong>;抑無表示講對 <strong>販賣性</strong> 抑 <strong>特定用途的適用性</strong> 的情形擔保。詳情請參照 GNU 通用公共授權。\n\n你應該已隨本程式收著 <doclink href=\"Copying\">GNU 通用公共授權條款的副本</doclink>;若無,請寫批通知自由軟體基金會,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA,或 [https://www.gnu.org/copyleft/gpl.html 線頂看]。",
+       "config-copyright": "=== Pán-koân seng-bêng kap siū-koân tiâu-khoán ===\n\n$1\n\nPún têng-sek sī chū-iû nńg-thé; lí thang chiàu Chū-iû Nńg-thé Ki-kim-hoē só͘ hoat-piáu--ê GNU Thong-iōng Kong-kiōng Siū-koân Tiâu-khoán kui-tēng, kā pún têng-sek têng hoat-pò͘ iah-sī siu-kái; bô-lūn lí sī chiàu pún siū-koân tiâu-khoán--ê tē 2 pán iah koh khah sin--ê pán-pún (lí thang ka-kī kéng).\n\nPún têng-sek hoat-pò͘--ê bo̍k-tek sī ǹg-bāng ē-tàng pang-chān, m̄-koh <strong>bô hù jīm-hô tam-pó͘ chek-jīm</strong>; iah bô piáu-sī kóng tùi <strong>hoàn-bē-sèng</strong> iah <strong>te̍k-tēng iōng-tô͘--ê sek-iōng-sèng</strong>--ê chêng-hêng tam-pó͘. Siông-sè chhiáⁿ chham-khó GNU Thong-iōng Kong-kiōng Siū-koân.\n\nLí èng-kai tùi pún têng-sek siu-tio̍h <doclink href=\"Copying\">GNU Thong-iōng Kong-kiōng Siū-koân--ê Hù-pún</doclink>; nā-bô, chhiáⁿ siá-phoe thong-tī Chū-iû Nńg-thé KI-kim-hoē, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, iah-sī [https://www.gnu.org/copyleft/gpl.html soàⁿ-téng khoàⁿ].",
        "config-sidebar": "* [www.mediawiki.org/wiki/MediaWiki/zh-hant MediaWiki 頭頁]\n* [www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/zh 使用者指南]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/zh 管理者指南]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh-hant 四常問題集]\n----\n* <doclink href=Readme>讀我說明</doclink>\n* <doclink href=ReleaseNotes>發行說明</doclink>\n* <doclink href=Copying>版權聲明</doclink>\n* <doclink href=UpgradeDoc>升級</doclink>",
        "config-env-good": "環境檢查已完成。\n你會當安裝 MediaWiki。",
-       "config-env-bad": "環境檢查已完成。\n你無法度安裝 MediaWiki。",
+       "config-env-bad": "Khoân-kèng kiám-cha oân-sêng--ah.\nLí bô-hoat-tō͘ an-chng MediaWiki.",
        "config-env-php": "PHP $1 已經安裝。",
        "config-unicode-using-intl": "用 [https://pecl.php.net/intl intl PECL 擴充套件] 做 Unicode 正規化。",
-       "config-unicode-pure-php-warning": "<strong>警告:</strong> 無法度用 [https://pecl.php.net/intl intl PECL 擴充套件] 處理 Unicode 正規化,所以退回用純 PHP 實作的正規化程式,這種方式處理速度較慢。\n\n若你的網站瀏覽人數誠濟,你應該先看 [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/zh Unicode 正規化]。",
+       "config-unicode-pure-php-warning": "<strong>Kéng-kò:</strong> Bô-hoat-tō͘ iōng [https://pecl.php.net/intl intl PECL extension] chhú-lí Unicode chèng-kui-hoà, só͘-í thè kàu iōng sûn PHP si̍t-chok--ê chèng-kui-hoà têng-sek, chit khoán hong-sek chhú-lí sok-tō͘ khah bān. Nā lí--ê bāng-chām liú-lám--ê lâng chiâⁿ chē, lí èng-kai ài khoàⁿ [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/zh Unicode chèng-kui-hoà].",
        "config-unicode-update-warning": "<strong>警告</strong>:這馬安裝的 Unicode 正規化包裝程式用舊版 [http://site.icu-project.org/ ICU 計劃] 的程式庫。\n若你需要用 Unicode,你應該先進行 [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations 升級]。",
        "config-no-db": "揣無適合的資料庫驅動程式!你需要安裝 PHP 資料庫驅動程式。\n這馬支援下跤類型的資料庫: $1 。\n\n若你是家己編譯 PHP,你需要重新設定並且開資料庫客戶端,譬如:用 <code>./configure --with-mysqli</code> 指令參數。\n如你是用 Debian 或 Ubuntu 的套件安裝,你著需要閣另外安裝,例:<code>php5-mysql</code> 套件。",
-       "config-outdated-sqlite": "<strong>警告:</strong>你已經安裝 SQLite $1,毋閣伊的版本比會當裝的版本 $2閣較舊。所以你無法度用 SQLite。",
-       "config-no-fts3": "<strong>警告:</strong> SQLite 佇編譯的時陣無包括 [//sqlite.org/fts3.html FTS3 模組],後台搜揣功能就會無法度用。",
+       "config-outdated-sqlite": "<strong>Kéng-kò:</strong> Lí í-keng an-chng SQLite $1, m̄-koh i--ê pán-pún pí thang-chng--ê pán-pún $2 khah kū. Só͘-í lí bô-hoat-tō͘ ēng SQLite.",
+       "config-no-fts3": "<strong>Kéng-kò: </strong> SQLite tī pian-e̍k--ê sî-chūn bô pau-koat  [//sqlite.org/fts3.html FTS3 module], āu-tâi chhiau-chhoē kong-lêng tiō ē bô-hoat-tō͘ iōng.",
        "mainpagetext": "'''MediaWiki已經裝好矣。'''",
        "mainpagedocfooter": "請查看[https://meta.wikimedia.org/wiki/Help:Contents 用者說明書]的資料通使用wiki 軟體\n\n== 入門 ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings 配置的設定]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki時常問答]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki的公布列單]"
 }
index 74b8ac1..0ca73d3 100644 (file)
@@ -68,7 +68,7 @@
        "config-apc": "[http://www.php.net/apc APC] är installerat",
        "config-apcu": "[http://www.php.net/apcu APCu] är installerat",
        "config-wincache": "[https://www.iis.net/download/WinCacheForPhp WinCache] är installerat",
-       "config-no-cache-apcu": "'''Varning:''' Kunde inte hitta [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] eller [http://www.iis.net/download/WinCacheForPhp WinCache].\nCachelagring av objekt är inte aktiverat.",
+       "config-no-cache-apcu": "<strong>Varning:</strong> Kunde inte hitta [http://www.php.net/apcu APCu] eller [http://www.iis.net/download/WinCacheForPhp WinCache].\nCachelagring av objekt är inte aktiverat.",
        "config-mod-security": "'''Varning:''' Din webbserver har [https://modsecurity.org/ mod_security] aktiverat. Om felaktigt konfigurerat kan den skapa problem för MediaWiki eller annan programvara som tillåter användaren att posta godtyckligt innehåll.\nTitta på [https://modsecurity.org/documentation/ mod_security-dokumentationen] eller kontakta din värd om du påträffar slumpmässiga fel.",
        "config-diff3-bad": "GNU diff3 hittades inte.",
        "config-git": "Hittade Git-mjukvara för versionskontroll: <code>$1</code>.",
        "config-cache-options": "Inställningar för cachelagring av objekt:",
        "config-cache-help": "Cachelagring av objekt används för att förbättra hastigheten på MediaWiki genom att cachelagra data som används ofta.\nMedelstora till stora webbplatser är starkt uppmuntrade att aktivera detta, och små webbplatser kommer även att se fördelar.",
        "config-cache-none": "Ingen cachelagring (ingen funktionalitet tas bort, men hastighet kan påverkas på större wiki-webbplatser)",
-       "config-cache-accel": "Cachelagring av PHP-objekt (APC, APCu, XCache eller WinCache)",
+       "config-cache-accel": "Cachelagring av PHP-objekt (APC, APCu eller WinCache)",
        "config-cache-memcached": "Använda Memcached (kräver ytterligare inställningar och konfiguration)",
        "config-memcached-servers": "Memcached-servrar:",
        "config-memcached-help": "Lista över IP-adresser som ska användas för Memcached.\nBör ange en per rad och specificera den port som ska användas. Till exempel:\n 127.0.0.1:11211\n 192.168.1.25:1234",
index a92ae96..d97e4f9 100644 (file)
@@ -76,10 +76,9 @@ class RecentChangesUpdateJob extends Job {
                $lockKey = wfWikiID() . ':recentchanges-prune';
 
                $dbw = wfGetDB( DB_MASTER );
-               if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
-                       || !$dbw->lock( $lockKey, __METHOD__, 1 )
-               ) {
-                       return; // already in progress
+               if ( !$dbw->lock( $lockKey, __METHOD__, 0 ) ) {
+                       // already in progress
+                       return;
                }
 
                $factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
@@ -138,7 +137,7 @@ class RecentChangesUpdateJob extends Job {
                                $dbw->setSessionOptions( [ 'connTimeout' => 900 ] );
 
                                $lockKey = wfWikiID() . '-activeusers';
-                               if ( !$dbw->lockIsFree( $lockKey, __METHOD__ ) || !$dbw->lock( $lockKey, __METHOD__, 1 ) ) {
+                               if ( !$dbw->lock( $lockKey, __METHOD__, 0 ) ) {
                                        // Exclusive update (avoids duplicate entries)… it's usually fine to just drop out here,
                                        // if the Job is already running.
                                        return;
diff --git a/includes/jobqueue/jobs/UserGroupExpiryJob.php b/includes/jobqueue/jobs/UserGroupExpiryJob.php
new file mode 100644 (file)
index 0000000..0945e58
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Job that purges expired user group memberships.
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+class UserGroupExpiryJob extends Job {
+       public function __construct( $params = false ) {
+               parent::__construct( 'userGroupExpiry', Title::newMainPage(), $params );
+               $this->removeDuplicates = true;
+       }
+
+       /**
+        * Run the job
+        * @return bool Success
+        */
+       public function run() {
+               UserGroupMembership::purgeExpired();
+
+               return true;
+       }
+}
index a6fd11a..9470413 100644 (file)
@@ -22,6 +22,7 @@
 
 /**
  * @since 1.25
+ * @deprecated since 1.31, use Message::listParam() instead
  */
 class DeferredStringifier {
        /** @var callable Callback used for result string generation */
index 0e09f16..7bab20a 100644 (file)
@@ -30,6 +30,7 @@
  */
 interface IExpiringStore {
        // Constants for TTL values, in seconds
+       const TTL_SECOND = 1;
        const TTL_MINUTE = 60;
        const TTL_HOUR = 3600;
        const TTL_DAY = 86400; // 24 * 3600
index eec766b..bcd95c1 100644 (file)
@@ -1536,7 +1536,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
        }
 
        /**
-        * Locally set a key to expire soon if it is stale based on $purgeTimestamp
+        * Set a key to soon expire in the local cluster if it pre-dates $purgeTimestamp
         *
         * This sets stale keys' time-to-live at HOLDOFF_TTL seconds, which both avoids
         * broadcasting in mcrouter setups and also avoids races with new tombstones.
@@ -1568,7 +1568,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
        }
 
        /**
-        * Locally set a "check" key to expire soon if it is stale based on $purgeTimestamp
+        * Set a "check" key to soon expire in the local cluster if it pre-dates $purgeTimestamp
         *
         * @param string $key Cache key
         * @param int $purgeTimestamp UNIX timestamp of purge
@@ -1581,7 +1581,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                if ( $purge && $purge[self::FLD_TIME] < $purgeTimestamp ) {
                        $isStale = true;
                        $this->logger->warning( "Reaping stale check key '$key'." );
-                       $ok = $this->cache->changeTTL( self::TIME_KEY_PREFIX . $key, 1 );
+                       $ok = $this->cache->changeTTL( self::TIME_KEY_PREFIX . $key, self::TTL_SECOND );
                        if ( !$ok ) {
                                $this->logger->error( "Could not complete reap of check key '$key'." );
                        }
@@ -1824,7 +1824,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                                'cmd' => 'set',
                                'key' => $key,
                                'val' => 'PURGED:$UNIXTIME$:' . (int)$holdoff,
-                               'ttl' => max( $ttl, 1 ),
+                               'ttl' => max( $ttl, self::TTL_SECOND ),
                                'sbt' => true, // substitute $UNIXTIME$ with actual microtime
                        ] );
 
index 4fcd885..88e276f 100644 (file)
@@ -124,7 +124,7 @@ class ChronologyProtector implements LoggerAwareInterface {
                        $this->startupPositions[$masterName] instanceof DBMasterPos
                ) {
                        $pos = $this->startupPositions[$masterName];
-                       $this->logger->info( __METHOD__ . ": LB for '$masterName' set to pos $pos\n" );
+                       $this->logger->debug( __METHOD__ . ": LB for '$masterName' set to pos $pos\n" );
                        $lb->waitFor( $pos );
                }
        }
@@ -148,11 +148,11 @@ class ChronologyProtector implements LoggerAwareInterface {
                if ( $lb->getServerCount() > 1 ) {
                        $pos = $lb->getMasterPos();
                        if ( $pos ) {
-                               $this->logger->info( __METHOD__ . ": LB for '$masterName' has pos $pos\n" );
+                               $this->logger->debug( __METHOD__ . ": LB for '$masterName' has pos $pos\n" );
                                $this->shutdownPositions[$masterName] = $pos;
                        }
                } else {
-                       $this->logger->info( __METHOD__ . ": DB '$masterName' touched\n" );
+                       $this->logger->debug( __METHOD__ . ": DB '$masterName' touched\n" );
                }
                $this->shutdownTouchDBs[$masterName] = 1;
        }
@@ -186,7 +186,7 @@ class ChronologyProtector implements LoggerAwareInterface {
                        return []; // nothing to save
                }
 
-               $this->logger->info( __METHOD__ . ": saving master pos for " .
+               $this->logger->debug( __METHOD__ . ": saving master pos for " .
                        implode( ', ', array_keys( $this->shutdownPositions ) ) . "\n"
                );
 
@@ -299,10 +299,10 @@ class ChronologyProtector implements LoggerAwareInterface {
                        }
 
                        $this->startupPositions = $data ? $data['positions'] : [];
-                       $this->logger->info( __METHOD__ . ": key is {$this->key} (read)\n" );
+                       $this->logger->debug( __METHOD__ . ": key is {$this->key} (read)\n" );
                } else {
                        $this->startupPositions = [];
-                       $this->logger->info( __METHOD__ . ": key is {$this->key} (unread)\n" );
+                       $this->logger->debug( __METHOD__ . ": key is {$this->key} (unread)\n" );
                }
        }
 
index d1814e1..572a798 100644 (file)
@@ -59,19 +59,19 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        const SMALL_WRITE_ROWS = 100;
 
        /** @var string SQL query */
-       protected $mLastQuery = '';
+       protected $lastQuery = '';
        /** @var float|bool UNIX timestamp of last write query */
-       protected $mLastWriteTime = false;
+       protected $lastWriteTime = false;
        /** @var string|bool */
-       protected $mPHPError = false;
+       protected $phpError = false;
        /** @var string */
-       protected $mServer;
+       protected $server;
        /** @var string */
-       protected $mUser;
+       protected $user;
        /** @var string */
-       protected $mPassword;
+       protected $password;
        /** @var string */
-       protected $mDBname;
+       protected $dbName;
        /** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
        protected $tableAliases = [];
        /** @var bool Whether this PHP instance is for a CLI script */
@@ -89,35 +89,33 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        protected $errorLogger;
 
        /** @var resource|null Database connection */
-       protected $mConn = null;
+       protected $conn = null;
        /** @var bool */
-       protected $mOpened = false;
+       protected $opened = false;
 
        /** @var array[] List of (callable, method name) */
-       protected $mTrxIdleCallbacks = [];
+       protected $trxIdleCallbacks = [];
        /** @var array[] List of (callable, method name) */
-       protected $mTrxPreCommitCallbacks = [];
+       protected $trxPreCommitCallbacks = [];
        /** @var array[] List of (callable, method name) */
-       protected $mTrxEndCallbacks = [];
+       protected $trxEndCallbacks = [];
        /** @var callable[] Map of (name => callable) */
-       protected $mTrxRecurringCallbacks = [];
+       protected $trxRecurringCallbacks = [];
        /** @var bool Whether to suppress triggering of transaction end callbacks */
-       protected $mTrxEndCallbacksSuppressed = false;
+       protected $trxEndCallbacksSuppressed = false;
 
        /** @var string */
-       protected $mTablePrefix = '';
+       protected $tablePrefix = '';
        /** @var string */
-       protected $mSchema = '';
+       protected $schema = '';
        /** @var int */
-       protected $mFlags;
+       protected $flags;
        /** @var array */
-       protected $mLBInfo = [];
-       /** @var bool|null */
-       protected $mDefaultBigSelects = null;
+       protected $lbInfo = [];
        /** @var array|bool */
-       protected $mSchemaVars = false;
+       protected $schemaVars = false;
        /** @var array */
-       protected $mSessionVars = [];
+       protected $sessionVars = [];
        /** @var array|null */
        protected $preparedArgs;
        /** @var string|bool|null Stashed value of html_errors INI setting */
@@ -135,94 +133,94 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         *
         * @var int
         */
-       protected $mTrxLevel = 0;
+       protected $trxLevel = 0;
        /**
         * Either a short hexidecimal string if a transaction is active or ""
         *
         * @var string
-        * @see Database::mTrxLevel
+        * @see Database::trxLevel
         */
-       protected $mTrxShortId = '';
+       protected $trxShortId = '';
        /**
         * The UNIX time that the transaction started. Callers can assume that if
         * snapshot isolation is used, then the data is *at least* up to date to that
         * point (possibly more up-to-date since the first SELECT defines the snapshot).
         *
         * @var float|null
-        * @see Database::mTrxLevel
+        * @see Database::trxLevel
         */
-       private $mTrxTimestamp = null;
+       private $trxTimestamp = null;
        /** @var float Lag estimate at the time of BEGIN */
-       private $mTrxReplicaLag = null;
+       private $trxReplicaLag = null;
        /**
         * Remembers the function name given for starting the most recent transaction via begin().
         * Used to provide additional context for error reporting.
         *
         * @var string
-        * @see Database::mTrxLevel
+        * @see Database::trxLevel
         */
-       private $mTrxFname = null;
+       private $trxFname = null;
        /**
         * Record if possible write queries were done in the last transaction started
         *
         * @var bool
-        * @see Database::mTrxLevel
+        * @see Database::trxLevel
         */
-       private $mTrxDoneWrites = false;
+       private $trxDoneWrites = false;
        /**
         * Record if the current transaction was started implicitly due to DBO_TRX being set.
         *
         * @var bool
-        * @see Database::mTrxLevel
+        * @see Database::trxLevel
         */
-       private $mTrxAutomatic = false;
+       private $trxAutomatic = false;
        /**
         * Array of levels of atomicity within transactions
         *
         * @var array
         */
-       private $mTrxAtomicLevels = [];
+       private $trxAtomicLevels = [];
        /**
         * Record if the current transaction was started implicitly by Database::startAtomic
         *
         * @var bool
         */
-       private $mTrxAutomaticAtomic = false;
+       private $trxAutomaticAtomic = false;
        /**
         * Track the write query callers of the current transaction
         *
         * @var string[]
         */
-       private $mTrxWriteCallers = [];
+       private $trxWriteCallers = [];
        /**
         * @var float Seconds spent in write queries for the current transaction
         */
-       private $mTrxWriteDuration = 0.0;
+       private $trxWriteDuration = 0.0;
        /**
         * @var int Number of write queries for the current transaction
         */
-       private $mTrxWriteQueryCount = 0;
+       private $trxWriteQueryCount = 0;
        /**
         * @var int Number of rows affected by write queries for the current transaction
         */
-       private $mTrxWriteAffectedRows = 0;
+       private $trxWriteAffectedRows = 0;
        /**
-        * @var float Like mTrxWriteQueryCount but excludes lock-bound, easy to replicate, queries
+        * @var float Like trxWriteQueryCount but excludes lock-bound, easy to replicate, queries
         */
-       private $mTrxWriteAdjDuration = 0.0;
+       private $trxWriteAdjDuration = 0.0;
        /**
-        * @var int Number of write queries counted in mTrxWriteAdjDuration
+        * @var int Number of write queries counted in trxWriteAdjDuration
         */
-       private $mTrxWriteAdjQueryCount = 0;
+       private $trxWriteAdjQueryCount = 0;
        /**
         * @var float RTT time estimate
         */
-       private $mRTTEstimate = 0.0;
+       private $rttEstimate = 0.0;
 
        /** @var array Map of (name => 1) for locks obtained via lock() */
-       private $mNamedLocksHeld = [];
+       private $namedLocksHeld = [];
        /** @var array Map of (table name => 1) for TEMPORARY tables */
-       protected $mSessionTempTables = [];
+       protected $sessionTempTables = [];
 
        /** @var IDatabase|null Lazy handle to the master DB this server replicates from */
        private $lazyMasterHandle;
@@ -230,7 +228,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /** @var float UNIX timestamp */
        protected $lastPing = 0.0;
 
-       /** @var int[] Prior mFlags values */
+       /** @var int[] Prior flags member variable values */
        private $priorFlags = [];
 
        /** @var object|string Class name or object With profileIn/profileOut methods */
@@ -252,23 +250,23 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                $password = $params['password'];
                $dbName = $params['dbname'];
 
-               $this->mSchema = $params['schema'];
-               $this->mTablePrefix = $params['tablePrefix'];
+               $this->schema = $params['schema'];
+               $this->tablePrefix = $params['tablePrefix'];
 
                $this->cliMode = $params['cliMode'];
                // Agent name is added to SQL queries in a comment, so make sure it can't break out
                $this->agent = str_replace( '/', '-', $params['agent'] );
 
-               $this->mFlags = $params['flags'];
-               if ( $this->mFlags & self::DBO_DEFAULT ) {
+               $this->flags = $params['flags'];
+               if ( $this->flags & self::DBO_DEFAULT ) {
                        if ( $this->cliMode ) {
-                               $this->mFlags &= ~self::DBO_TRX;
+                               $this->flags &= ~self::DBO_TRX;
                        } else {
-                               $this->mFlags |= self::DBO_TRX;
+                               $this->flags |= self::DBO_TRX;
                        }
                }
 
-               $this->mSessionVars = $params['variables'];
+               $this->sessionVars = $params['variables'];
 
                $this->srvCache = isset( $params['srvCache'] )
                        ? $params['srvCache']
@@ -290,9 +288,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                // Set the domain object after open() sets the relevant fields
-               if ( $this->mDBname != '' ) {
+               if ( $this->dbName != '' ) {
                        // Domains with server scope but a table prefix are not used by IDatabase classes
-                       $this->currentDomain = new DatabaseDomain( $this->mDBname, null, $this->mTablePrefix );
+                       $this->currentDomain = new DatabaseDomain( $this->dbName, null, $this->tablePrefix );
                }
        }
 
@@ -464,9 +462,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                if ( $ignoreErrors !== null ) {
                        // setFlag()/clearFlag() do not allow DBO_IGNORE changes for sanity
                        if ( $ignoreErrors ) {
-                               $this->mFlags |= self::DBO_IGNORE;
+                               $this->flags |= self::DBO_IGNORE;
                        } else {
-                               $this->mFlags &= ~self::DBO_IGNORE;
+                               $this->flags &= ~self::DBO_IGNORE;
                        }
                }
 
@@ -474,19 +472,19 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        public function trxLevel() {
-               return $this->mTrxLevel;
+               return $this->trxLevel;
        }
 
        public function trxTimestamp() {
-               return $this->mTrxLevel ? $this->mTrxTimestamp : null;
+               return $this->trxLevel ? $this->trxTimestamp : null;
        }
 
        public function tablePrefix( $prefix = null ) {
-               $old = $this->mTablePrefix;
+               $old = $this->tablePrefix;
                if ( $prefix !== null ) {
-                       $this->mTablePrefix = $prefix;
-                       $this->currentDomain = ( $this->mDBname != '' )
-                               ? new DatabaseDomain( $this->mDBname, null, $this->mTablePrefix )
+                       $this->tablePrefix = $prefix;
+                       $this->currentDomain = ( $this->dbName != '' )
+                               ? new DatabaseDomain( $this->dbName, null, $this->tablePrefix )
                                : DatabaseDomain::newUnspecified();
                }
 
@@ -494,9 +492,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        public function dbSchema( $schema = null ) {
-               $old = $this->mSchema;
+               $old = $this->schema;
                if ( $schema !== null ) {
-                       $this->mSchema = $schema;
+                       $this->schema = $schema;
                }
 
                return $old;
@@ -504,10 +502,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
        public function getLBInfo( $name = null ) {
                if ( is_null( $name ) ) {
-                       return $this->mLBInfo;
+                       return $this->lbInfo;
                } else {
-                       if ( array_key_exists( $name, $this->mLBInfo ) ) {
-                               return $this->mLBInfo[$name];
+                       if ( array_key_exists( $name, $this->lbInfo ) ) {
+                               return $this->lbInfo[$name];
                        } else {
                                return null;
                        }
@@ -516,9 +514,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
        public function setLBInfo( $name, $value = null ) {
                if ( is_null( $value ) ) {
-                       $this->mLBInfo = $name;
+                       $this->lbInfo = $name;
                } else {
-                       $this->mLBInfo[$name] = $value;
+                       $this->lbInfo[$name] = $value;
                }
        }
 
@@ -544,55 +542,55 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        public function lastQuery() {
-               return $this->mLastQuery;
+               return $this->lastQuery;
        }
 
        public function doneWrites() {
-               return (bool)$this->mLastWriteTime;
+               return (bool)$this->lastWriteTime;
        }
 
        public function lastDoneWrites() {
-               return $this->mLastWriteTime ?: false;
+               return $this->lastWriteTime ?: false;
        }
 
        public function writesPending() {
-               return $this->mTrxLevel && $this->mTrxDoneWrites;
+               return $this->trxLevel && $this->trxDoneWrites;
        }
 
        public function writesOrCallbacksPending() {
-               return $this->mTrxLevel && (
-                       $this->mTrxDoneWrites || $this->mTrxIdleCallbacks || $this->mTrxPreCommitCallbacks
+               return $this->trxLevel && (
+                       $this->trxDoneWrites || $this->trxIdleCallbacks || $this->trxPreCommitCallbacks
                );
        }
 
        public function pendingWriteQueryDuration( $type = self::ESTIMATE_TOTAL ) {
-               if ( !$this->mTrxLevel ) {
+               if ( !$this->trxLevel ) {
                        return false;
-               } elseif ( !$this->mTrxDoneWrites ) {
+               } elseif ( !$this->trxDoneWrites ) {
                        return 0.0;
                }
 
                switch ( $type ) {
                        case self::ESTIMATE_DB_APPLY:
                                $this->ping( $rtt );
-                               $rttAdjTotal = $this->mTrxWriteAdjQueryCount * $rtt;
-                               $applyTime = max( $this->mTrxWriteAdjDuration - $rttAdjTotal, 0 );
+                               $rttAdjTotal = $this->trxWriteAdjQueryCount * $rtt;
+                               $applyTime = max( $this->trxWriteAdjDuration - $rttAdjTotal, 0 );
                                // For omitted queries, make them count as something at least
-                               $omitted = $this->mTrxWriteQueryCount - $this->mTrxWriteAdjQueryCount;
+                               $omitted = $this->trxWriteQueryCount - $this->trxWriteAdjQueryCount;
                                $applyTime += self::TINY_WRITE_SEC * $omitted;
 
                                return $applyTime;
                        default: // everything
-                               return $this->mTrxWriteDuration;
+                               return $this->trxWriteDuration;
                }
        }
 
        public function pendingWriteCallers() {
-               return $this->mTrxLevel ? $this->mTrxWriteCallers : [];
+               return $this->trxLevel ? $this->trxWriteCallers : [];
        }
 
        public function pendingWriteRowsAffected() {
-               return $this->mTrxWriteAffectedRows;
+               return $this->trxWriteAffectedRows;
        }
 
        /**
@@ -602,15 +600,15 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @return array
         */
        protected function pendingWriteAndCallbackCallers() {
-               if ( !$this->mTrxLevel ) {
+               if ( !$this->trxLevel ) {
                        return [];
                }
 
-               $fnames = $this->mTrxWriteCallers;
+               $fnames = $this->trxWriteCallers;
                foreach ( [
-                       $this->mTrxIdleCallbacks,
-                       $this->mTrxPreCommitCallbacks,
-                       $this->mTrxEndCallbacks
+                       $this->trxIdleCallbacks,
+                       $this->trxPreCommitCallbacks,
+                       $this->trxEndCallbacks
                ] as $callbacks ) {
                        foreach ( $callbacks as $callback ) {
                                $fnames[] = $callback[1];
@@ -621,7 +619,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        public function isOpen() {
-               return $this->mOpened;
+               return $this->opened;
        }
 
        public function setFlag( $flag, $remember = self::REMEMBER_NOTHING ) {
@@ -630,9 +628,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                if ( $remember === self::REMEMBER_PRIOR ) {
-                       array_push( $this->priorFlags, $this->mFlags );
+                       array_push( $this->priorFlags, $this->flags );
                }
-               $this->mFlags |= $flag;
+               $this->flags |= $flag;
        }
 
        public function clearFlag( $flag, $remember = self::REMEMBER_NOTHING ) {
@@ -641,9 +639,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                if ( $remember === self::REMEMBER_PRIOR ) {
-                       array_push( $this->priorFlags, $this->mFlags );
+                       array_push( $this->priorFlags, $this->flags );
                }
-               $this->mFlags &= ~$flag;
+               $this->flags &= ~$flag;
        }
 
        public function restoreFlags( $state = self::RESTORE_PRIOR ) {
@@ -652,15 +650,15 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                if ( $state === self::RESTORE_INITIAL ) {
-                       $this->mFlags = reset( $this->priorFlags );
+                       $this->flags = reset( $this->priorFlags );
                        $this->priorFlags = [];
                } else {
-                       $this->mFlags = array_pop( $this->priorFlags );
+                       $this->flags = array_pop( $this->priorFlags );
                }
        }
 
        public function getFlag( $flag ) {
-               return !!( $this->mFlags & $flag );
+               return !!( $this->flags & $flag );
        }
 
        /**
@@ -701,7 +699,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * Set a custom error handler for logging errors during database connection
         */
        protected function installErrorHandler() {
-               $this->mPHPError = false;
+               $this->phpError = false;
                $this->htmlErrors = ini_set( 'html_errors', '0' );
                set_error_handler( [ $this, 'connectionErrorLogger' ] );
        }
@@ -724,8 +722,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @return string|bool Last PHP error for this DB (typically connection errors)
         */
        protected function getLastPHPError() {
-               if ( $this->mPHPError ) {
-                       $error = preg_replace( '!\[<a.*</a>\]!', '', $this->mPHPError );
+               if ( $this->phpError ) {
+                       $error = preg_replace( '!\[<a.*</a>\]!', '', $this->phpError );
                        $error = preg_replace( '!^.*?:\s?(.*)$!', '$1', $error );
 
                        return $error;
@@ -742,7 +740,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @param string $errstr
         */
        public function connectionErrorLogger( $errno, $errstr ) {
-               $this->mPHPError = $errstr;
+               $this->phpError = $errstr;
        }
 
        /**
@@ -754,32 +752,32 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        protected function getLogContext( array $extras = [] ) {
                return array_merge(
                        [
-                               'db_server' => $this->mServer,
-                               'db_name' => $this->mDBname,
-                               'db_user' => $this->mUser,
+                               'db_server' => $this->server,
+                               'db_name' => $this->dbName,
+                               'db_user' => $this->user,
                        ],
                        $extras
                );
        }
 
        public function close() {
-               if ( $this->mConn ) {
+               if ( $this->conn ) {
                        if ( $this->trxLevel() ) {
                                $this->commit( __METHOD__, self::FLUSHING_INTERNAL );
                        }
 
                        $closed = $this->closeConnection();
-                       $this->mConn = false;
+                       $this->conn = false;
                } elseif (
-                       $this->mTrxIdleCallbacks ||
-                       $this->mTrxPreCommitCallbacks ||
-                       $this->mTrxEndCallbacks
+                       $this->trxIdleCallbacks ||
+                       $this->trxPreCommitCallbacks ||
+                       $this->trxEndCallbacks
                ) { // sanity
                        throw new RuntimeException( "Transaction callbacks still pending." );
                } else {
                        $closed = true;
                }
-               $this->mOpened = false;
+               $this->opened = false;
 
                return $closed;
        }
@@ -868,7 +866,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        $sql,
                        $matches
                ) ) {
-                       $this->mSessionTempTables[$matches[1]] = 1;
+                       $this->sessionTempTables[$matches[1]] = 1;
 
                        return true;
                } elseif ( preg_match(
@@ -876,8 +874,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        $sql,
                        $matches
                ) ) {
-                       $isTemp = isset( $this->mSessionTempTables[$matches[1]] );
-                       unset( $this->mSessionTempTables[$matches[1]] );
+                       $isTemp = isset( $this->sessionTempTables[$matches[1]] );
+                       unset( $this->sessionTempTables[$matches[1]] );
 
                        return $isTemp;
                } elseif ( preg_match(
@@ -885,13 +883,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        $sql,
                        $matches
                ) ) {
-                       return isset( $this->mSessionTempTables[$matches[1]] );
+                       return isset( $this->sessionTempTables[$matches[1]] );
                } elseif ( preg_match(
                        '/^(?:INSERT\s+(?:\w+\s+)?INTO|UPDATE|DELETE\s+FROM)\s+[`"\']?(\w+)[`"\']?/i',
                        $sql,
                        $matches
                ) ) {
-                       return isset( $this->mSessionTempTables[$matches[1]] );
+                       return isset( $this->sessionTempTables[$matches[1]] );
                }
 
                return false;
@@ -899,7 +897,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
        public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) {
                $priorWritesPending = $this->writesOrCallbacksPending();
-               $this->mLastQuery = $sql;
+               $this->lastQuery = $sql;
 
                $isWrite = $this->isWriteQuery( $sql );
                if ( $isWrite ) {
@@ -922,7 +920,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                throw new DBReadOnlyError( $this, "Database is read-only: $reason" );
                        }
                        # Set a flag indicating that writes have been done
-                       $this->mLastWriteTime = microtime( true );
+                       $this->lastWriteTime = microtime( true );
                }
 
                # Add trace comment to the begin of the sql string, right after the operator.
@@ -930,22 +928,22 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                $commentedSql = preg_replace( '/\s|$/', " /* $fname {$this->agent} */ ", $sql, 1 );
 
                # Start implicit transactions that wrap the request if DBO_TRX is enabled
-               if ( !$this->mTrxLevel && $this->getFlag( self::DBO_TRX )
+               if ( !$this->trxLevel && $this->getFlag( self::DBO_TRX )
                        && $this->isTransactableQuery( $sql )
                ) {
                        $this->begin( __METHOD__ . " ($fname)", self::TRANSACTION_INTERNAL );
-                       $this->mTrxAutomatic = true;
+                       $this->trxAutomatic = true;
                }
 
                # Keep track of whether the transaction has write queries pending
-               if ( $this->mTrxLevel && !$this->mTrxDoneWrites && $isWrite ) {
-                       $this->mTrxDoneWrites = true;
+               if ( $this->trxLevel && !$this->trxDoneWrites && $isWrite ) {
+                       $this->trxDoneWrites = true;
                        $this->trxProfiler->transactionWritingIn(
-                               $this->mServer, $this->mDBname, $this->mTrxShortId );
+                               $this->server, $this->dbName, $this->trxShortId );
                }
 
                if ( $this->getFlag( self::DBO_DEBUG ) ) {
-                       $this->queryLogger->debug( "{$this->mDBname} {$commentedSql}" );
+                       $this->queryLogger->debug( "{$this->dbName} {$commentedSql}" );
                }
 
                # Avoid fatals if close() was called
@@ -1024,7 +1022,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                # Include query transaction state
-               $queryProf .= $this->mTrxShortId ? " [TRX#{$this->mTrxShortId}]" : "";
+               $queryProf .= $this->trxShortId ? " [TRX#{$this->trxShortId}]" : "";
 
                $startTime = microtime( true );
                if ( $this->profiler ) {
@@ -1042,14 +1040,14 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
                if ( $ret !== false ) {
                        $this->lastPing = $startTime;
-                       if ( $isWrite && $this->mTrxLevel ) {
+                       if ( $isWrite && $this->trxLevel ) {
                                $this->updateTrxWriteQueryTime( $sql, $queryRuntime, $this->affectedRows() );
-                               $this->mTrxWriteCallers[] = $fname;
+                               $this->trxWriteCallers[] = $fname;
                        }
                }
 
                if ( $sql === self::PING_QUERY ) {
-                       $this->mRTTEstimate = $queryRuntime;
+                       $this->rttEstimate = $queryRuntime;
                }
 
                $this->trxProfiler->recordQueryCompletion(
@@ -1089,12 +1087,12 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        }
                }
 
-               $this->mTrxWriteDuration += $runtime;
-               $this->mTrxWriteQueryCount += 1;
-               $this->mTrxWriteAffectedRows += $affected;
+               $this->trxWriteDuration += $runtime;
+               $this->trxWriteQueryCount += 1;
+               $this->trxWriteAffectedRows += $affected;
                if ( $indicativeOfReplicaRuntime ) {
-                       $this->mTrxWriteAdjDuration += $runtime;
-                       $this->mTrxWriteAdjQueryCount += 1;
+                       $this->trxWriteAdjDuration += $runtime;
+                       $this->trxWriteAdjQueryCount += 1;
                }
        }
 
@@ -1113,7 +1111,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                # Dropped connections also mean that named locks are automatically released.
                # Only allow error suppression in autocommit mode or when the lost transaction
                # didn't matter anyway (aside from DBO_TRX snapshot loss).
-               if ( $this->mNamedLocksHeld ) {
+               if ( $this->namedLocksHeld ) {
                        return false; // possible critical section violation
                } elseif ( $sql === 'COMMIT' ) {
                        return !$priorWritesPending; // nothing written anyway? (T127428)
@@ -1134,13 +1132,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @return null|Exception
         */
        private function handleSessionLoss() {
-               $this->mTrxLevel = 0;
-               $this->mTrxIdleCallbacks = []; // T67263
-               $this->mTrxPreCommitCallbacks = []; // T67263
-               $this->mSessionTempTables = [];
-               $this->mNamedLocksHeld = [];
+               $this->trxLevel = 0;
+               $this->trxIdleCallbacks = []; // T67263
+               $this->trxPreCommitCallbacks = []; // T67263
+               $this->sessionTempTables = [];
+               $this->namedLocksHeld = [];
                try {
-                       // Handle callbacks in mTrxEndCallbacks
+                       // Handle callbacks in trxEndCallbacks
                        $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK );
                        $this->runTransactionListenerCallbacks( self::TRIGGER_ROLLBACK );
                        return null;
@@ -1405,13 +1403,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                $this->tableNamesWithIndexClauseOrJOIN(
                                        $table, $useIndexes, $ignoreIndexes, $join_conds );
                } elseif ( $table != '' ) {
-                       if ( $table[0] == ' ' ) {
-                               $from = ' FROM ' . $table;
-                       } else {
-                               $from = ' FROM ' .
-                                       $this->tableNamesWithIndexClauseOrJOIN(
-                                               [ $table ], $useIndexes, $ignoreIndexes, [] );
-                       }
+                       $from = ' FROM ' .
+                               $this->tableNamesWithIndexClauseOrJOIN(
+                                       [ $table ], $useIndexes, $ignoreIndexes, [] );
                } else {
                        $from = '';
                }