Merge "Allow ResourceLoaderImage modules without data URIs"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 9 Jul 2018 14:24:36 +0000 (14:24 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 9 Jul 2018 14:24:36 +0000 (14:24 +0000)
270 files changed:
.eslintrc.json
.phpcs.xml
includes/Block.php
includes/Category.php
includes/CommentStore.php
includes/DefaultSettings.php
includes/Defines.php
includes/EditPage.php
includes/FileDeleteForm.php
includes/FormOptions.php
includes/GlobalFunctions.php
includes/Html.php
includes/Linker.php
includes/MWNamespace.php
includes/MWTimestamp.php
includes/MagicWord.php
includes/MediaWiki.php
includes/Message.php
includes/OutputPage.php
includes/Pingback.php
includes/ProtectionForm.php
includes/Revision.php
includes/SiteConfiguration.php
includes/Status.php
includes/Storage/DerivedPageDataUpdater.php
includes/Storage/NameTableStore.php
includes/Storage/PageUpdater.php
includes/Storage/RevisionFactory.php
includes/Storage/RevisionLookup.php
includes/Storage/RevisionStore.php
includes/Storage/SqlBlobStore.php
includes/StubObject.php
includes/TemplateParser.php
includes/Title.php
includes/WebRequest.php
includes/WikiMap.php
includes/Xml.php
includes/api/ApiBase.php
includes/api/ApiDelete.php
includes/api/ApiMain.php
includes/api/ApiModuleManager.php
includes/api/ApiPageSet.php
includes/api/ApiQueryAllDeletedRevisions.php
includes/api/ApiQueryAllRevisions.php
includes/api/ApiQueryBacklinksprop.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryIWBacklinks.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryLangBacklinks.php
includes/api/ApiQueryQueryPage.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryRevisionsBase.php
includes/api/ApiResult.php
includes/api/i18n/mk.json
includes/auth/AbstractPasswordPrimaryAuthenticationProvider.php
includes/auth/AuthManager.php
includes/auth/AuthenticationResponse.php
includes/auth/Throttler.php
includes/cache/LinkCache.php
includes/cache/MessageBlobStore.php
includes/cache/MessageCache.php
includes/changes/CategoryMembershipChange.php
includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/changes/OldChangesList.php
includes/changes/RecentChange.php
includes/changetags/ChangeTags.php
includes/content/AbstractContent.php
includes/content/CodeContentHandler.php
includes/content/Content.php
includes/content/ContentHandler.php
includes/content/MessageContent.php
includes/content/TextContent.php
includes/content/TextContentHandler.php
includes/db/CloneDatabase.php
includes/db/PatchFileLocation.php
includes/debug/logger/monolog/LineFormatter.php
includes/deferred/SearchUpdate.php
includes/diff/DairikiDiff.php
includes/diff/DifferenceEngine.php
includes/exception/LocalizedException.php
includes/exception/MWExceptionHandler.php
includes/export/DumpPipeOutput.php
includes/externalstore/ExternalStoreDB.php
includes/filerepo/file/OldLocalFile.php
includes/htmlform/HTMLForm.php
includes/http/MWHttpRequest.php
includes/installer/CliInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerOptions.php
includes/installer/WebInstallerPage.php
includes/interwiki/Interwiki.php
includes/jobqueue/JobRunner.php
includes/jobqueue/JobSpecification.php
includes/libs/Cookie.php
includes/libs/MapCacheLRU.php
includes/libs/ProcessCacheLRU.php
includes/libs/StatusValue.php
includes/libs/Timing.php
includes/libs/filebackend/FileBackend.php
includes/libs/filebackend/FileBackendStore.php
includes/libs/filebackend/SwiftFileBackend.php
includes/libs/filebackend/filejournal/FileJournal.php
includes/libs/lockmanager/ScopedLock.php
includes/libs/mime/MimeAnalyzer.php
includes/libs/mime/XmlTypeCheck.php
includes/libs/objectcache/BagOStuff.php
includes/libs/objectcache/WANObjectCache.php
includes/libs/rdbms/database/DBConnRef.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseMysqlBase.php
includes/libs/rdbms/database/DatabaseMysqli.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/database/IDatabase.php
includes/libs/rdbms/database/IMaintainableDatabase.php
includes/libs/rdbms/exception/DBConnectionError.php
includes/libs/rdbms/exception/DBError.php
includes/libs/rdbms/exception/DBQueryError.php
includes/libs/rdbms/lbfactory/ILBFactory.php
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/redis/RedisConnRef.php
includes/libs/redis/RedisConnectionPool.php
includes/logging/LogEntry.php
includes/logging/LogEventsList.php
includes/logging/LogFormatter.php
includes/logging/PatrolLog.php
includes/mail/MailAddress.php
includes/media/BmpHandler.php
includes/media/MediaHandler.php
includes/media/MediaTransformOutput.php
includes/media/TiffHandler.php
includes/media/XCF.php
includes/page/Article.php
includes/page/PageArchive.php
includes/page/WikiPage.php
includes/pager/IndexPager.php
includes/parser/CoreParserFunctions.php
includes/parser/Parser.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/parser/Sanitizer.php
includes/poolcounter/PoolWorkArticleView.php
includes/preferences/DefaultPreferencesFactory.php
includes/profiler/Profiler.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderImageModule.php
includes/resourceloader/ResourceLoaderLanguageDataModule.php
includes/resourceloader/ResourceLoaderLanguageNamesModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderSpecialCharacterDataModule.php
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/search/SearchDatabase.php
includes/search/SearchEngine.php
includes/search/SearchEngineFactory.php
includes/search/SearchHighlighter.php
includes/search/SearchResult.php
includes/session/CookieSessionProvider.php
includes/session/Session.php
includes/session/SessionBackend.php
includes/site/SiteSQLStore.php
includes/skins/BaseTemplate.php
includes/skins/QuickTemplate.php
includes/skins/Skin.php
includes/skins/SkinTemplate.php
includes/specialpage/AuthManagerSpecialPage.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialBlock.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUpload.php
includes/specials/forms/PreferencesFormLegacy.php
includes/specials/forms/PreferencesFormOOUI.php
includes/specials/pagers/ActiveUsersPager.php
includes/specials/pagers/UsersPager.php
includes/tidy/RaggettBase.php
includes/tidy/RaggettExternal.php
includes/tidy/RaggettInternalHHVM.php
includes/tidy/RaggettInternalPHP.php
includes/title/MalformedTitleException.php
includes/upload/UploadBase.php
includes/upload/UploadStash.php
includes/user/PasswordReset.php
includes/user/User.php
includes/user/UserGroupMembership.php
includes/utils/MWRestrictions.php
includes/utils/ZipDirectoryReader.php
includes/watcheditem/WatchedItemStoreInterface.php
languages/ConverterRule.php
languages/Language.php
languages/LanguageConverter.php
languages/classes/LanguageFi.php
languages/i18n/ary.json
languages/i18n/be-tarask.json
languages/i18n/fa.json
languages/i18n/hr.json
languages/i18n/inh.json
languages/i18n/io.json
languages/i18n/pl.json
languages/i18n/pt.json
languages/i18n/ru.json
languages/i18n/sk.json
languages/i18n/te.json
languages/i18n/tr.json
languages/i18n/uk.json
languages/i18n/ur.json
languages/i18n/zh-hans.json
maintenance/Maintenance.php
maintenance/backup.inc
maintenance/dumpTextPass.php
maintenance/populateContentTables.php
package.json
resources/Resources.php
resources/src/jquery.tablesorter/jquery.tablesorter.js
resources/src/mediawiki.Title/Title.js
resources/src/mediawiki.Uri/Uri.js
resources/src/mediawiki.api/upload.js
resources/src/mediawiki.debug/debug.js
resources/src/mediawiki.jqueryMsg/mediawiki.jqueryMsg.js
resources/src/mediawiki.language/mediawiki.language.numbers.js
resources/src/mediawiki.page.watch.ajax.js
resources/src/mediawiki.special.apisandbox/apisandbox.js
resources/src/mediawiki.special.upload/upload.js
resources/src/mediawiki.visibleTimeout.js
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
tests/common/TestsAutoLoader.php
tests/parser/ParserTestRunner.php
tests/phan/config.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/ActorMigrationTest.php
tests/phpunit/includes/CommentStoreTest.php
tests/phpunit/includes/PageArchiveTest.php
tests/phpunit/includes/RevisionDbTestBase.php
tests/phpunit/includes/RevisionMcrReadNewDbTest.php [new file with mode: 0644]
tests/phpunit/includes/RevisionTest.php
tests/phpunit/includes/Storage/McrReadNewRevisionStoreDbTest.php [new file with mode: 0644]
tests/phpunit/includes/Storage/McrReadNewSchemaOverride.php [new file with mode: 0644]
tests/phpunit/includes/Storage/McrRevisionStoreDbTest.php
tests/phpunit/includes/Storage/McrWriteBothRevisionStoreDbTest.php
tests/phpunit/includes/Storage/McrWriteBothSchemaOverride.php
tests/phpunit/includes/Storage/PreMcrRevisionStoreDbTest.php
tests/phpunit/includes/Storage/RevisionStoreTest.php
tests/phpunit/includes/TestLogger.php
tests/phpunit/includes/api/RandomImageGenerator.php
tests/phpunit/includes/api/query/ApiQueryTestBase.php
tests/phpunit/includes/db/LBFactoryTest.php
tests/phpunit/includes/db/LoadBalancerTest.php
tests/phpunit/includes/libs/rdbms/database/DBConnRefTest.php
tests/phpunit/includes/media/MediaWikiMediaTestCase.php
tests/phpunit/includes/page/WikiPageDbTestBase.php
tests/phpunit/includes/page/WikiPageMcrReadNewDbTest.php [new file with mode: 0644]
tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php
tests/phpunit/includes/session/TestUtils.php
tests/phpunit/mocks/content/DummyContentForTesting.php
tests/phpunit/mocks/content/DummyContentHandlerForTesting.php
tests/phpunit/mocks/content/DummyNonTextContent.php
tests/phpunit/mocks/content/DummyNonTextContentHandler.php
tests/phpunit/mocks/content/DummySerializeErrorContentHandler.php
tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js
thumb.php

index 64b5ea7..844895d 100644 (file)
@@ -11,6 +11,7 @@
                "OO": false
        },
        "rules": {
-               "dot-notation": 0
+               "dot-notation": 0,
+               "max-len": 0
        }
 }
index e15eca0..8d33f69 100644 (file)
@@ -7,7 +7,6 @@
                <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamTag" />
                <exclude name="MediaWiki.Commenting.FunctionComment.MissingReturn" />
                <exclude name="MediaWiki.Commenting.FunctionComment.ExtraParamComment" />
-               <exclude name="MediaWiki.Commenting.FunctionComment.DefaultNullTypeParam" />
                <exclude name="MediaWiki.Commenting.FunctionComment.WrongStyle" />
                <exclude name="MediaWiki.Commenting.PhpunitAnnotations.NotClassTrait" />
                <exclude name="MediaWiki.Commenting.IllegalSingleLineComment.IllegalSingleLineCommentStart" />
index a7b8035..1d2e341 100644 (file)
@@ -299,7 +299,7 @@ class Block {
         *     1) A block directly on the given user or IP
         *     2) A rangeblock encompassing the given IP (smallest first)
         *     3) An autoblock on the given IP
-        * @param User|string $vagueTarget Also search for blocks affecting this target.  Doesn't
+        * @param User|string|null $vagueTarget Also search for blocks affecting this target.  Doesn't
         *     make any sense to use TYPE_AUTO / TYPE_ID here. Leave blank to skip IP lookups.
         * @throws MWException
         * @return bool Whether a relevant block was found
@@ -405,7 +405,7 @@ class Block {
        /**
         * Get a set of SQL conditions which will select rangeblocks encompassing a given range
         * @param string $start Hexadecimal IP representation
-        * @param string $end Hexadecimal IP representation, or null to use $start = $end
+        * @param string|null $end Hexadecimal IP representation, or null to use $start = $end
         * @return string
         */
        public static function getRangeCond( $start, $end = null ) {
@@ -519,7 +519,7 @@ class Block {
         * Insert a block into the block table. Will fail if there is a conflicting
         * block (same name and options) already in the database.
         *
-        * @param IDatabase $dbw If you have one available
+        * @param IDatabase|null $dbw If you have one available
         * @return bool|array False on failure, assoc array on success:
         *      ('id' => block ID, 'autoIds' => array of autoblock IDs)
         */
@@ -1162,7 +1162,7 @@ class Block {
         *     Calling this with a user, IP address or range will not select autoblocks, and will
         *     only select a block where the targets match exactly (so looking for blocks on
         *     1.2.3.4 will not select 1.2.0.0/16 or even 1.2.3.4/32)
-        * @param string|User|int $vagueTarget As above, but we will search for *any* block which
+        * @param string|User|int|null $vagueTarget As above, but we will search for *any* block which
         *     affects that target (so for an IP address, get ranges containing that IP; and also
         *     get any relevant autoblocks). Leave empty or blank to skip IP-based lookups.
         * @param bool $fromMaster Whether to use the DB_MASTER database
index 41ecc65..fe3dd0d 100644 (file)
@@ -171,7 +171,7 @@ class Category {
         *   fields are null, the resulting Category object will represent an empty
         *   category if a title object was given. If the fields are null and no
         *   title was given, this method fails and returns false.
-        * @param Title $title Optional title object for the category represented by
+        * @param Title|null $title Optional title object for the category represented by
         *   the given row. May be provided if it is already known, to avoid having
         *   to re-create a title object later.
         * @return Category|false
index 6b94d58..8a1901c 100644 (file)
@@ -158,7 +158,7 @@ class CommentStore {
         *
         * @since 1.30
         * @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
-        * @param string $key A key such as "rev_comment" identifying the comment
+        * @param string|null $key A key such as "rev_comment" identifying the comment
         *  field being fetched.
         * @return string[] to include in the `$vars` to `IDatabase->select()`. All
         *  fields are aliased, so `+` is safe to use.
@@ -191,7 +191,7 @@ class CommentStore {
         *
         * @since 1.30
         * @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
-        * @param string $key A key such as "rev_comment" identifying the comment
+        * @param string|null $key A key such as "rev_comment" identifying the comment
         *  field being fetched.
         * @return array With three keys:
         *   - tables: (string[]) to include in the `$table` to `IDatabase->select()`
@@ -381,7 +381,7 @@ class CommentStore {
         * @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
         * @param string $key A key such as "rev_comment" identifying the comment
         *  field being fetched.
-        * @param object|array $row Result row.
+        * @param object|array|null $row Result row.
         * @param bool $fallback If true, fall back as well as possible instead of throwing an exception.
         * @return CommentStoreComment
         */
@@ -415,7 +415,7 @@ class CommentStore {
         * @param IDatabase $db Database handle to use for lookup
         * @param string $key A key such as "rev_comment" identifying the comment
         *  field being fetched.
-        * @param object|array $row Result row.
+        * @param object|array|null $row Result row.
         * @param bool $fallback If true, fall back as well as possible instead of throwing an exception.
         * @return CommentStoreComment
         */
@@ -567,7 +567,7 @@ class CommentStore {
         * @param IDatabase $dbw Database handle to insert on
         * @param string $key A key such as "rev_comment" identifying the comment
         *  field being fetched.
-        * @param string|Message|CommentStoreComment $comment As for `self::createComment()`
+        * @param string|Message|CommentStoreComment|null $comment As for `self::createComment()`
         * @param array|null $data As for `self::createComment()`
         * @return array Fields for the insert or update
         */
@@ -606,7 +606,7 @@ class CommentStore {
         * @param IDatabase $dbw Database handle to insert on
         * @param string $key A key such as "rev_comment" identifying the comment
         *  field being fetched.
-        * @param string|Message|CommentStoreComment $comment As for `self::createComment()`
+        * @param string|Message|CommentStoreComment|null $comment As for `self::createComment()`
         * @param array|null $data As for `self::createComment()`
         * @return array Two values:
         *  - array Fields for the insert or update
index 488fef0..f3bc9cc 100644 (file)
@@ -8892,13 +8892,23 @@ $wgInterwikiPrefixDisplayTypes = [];
 $wgCommentTableSchemaMigrationStage = MIGRATION_OLD;
 
 /**
- * RevisionStore table schema migration stage (content, slots, content_models & slot_roles tables)
+ * RevisionStore table schema migration stage (content, slots, content_models & slot_roles tables).
+ * Use the SCHEMA_COMPAT_XXX flags. Supported values:
+ *
+ * - SCHEMA_COMPAT_OLD
+ * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
+ * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
+ * - SCHEMA_COMPAT_OLD
+ *
+ * Note that reading the old and new schema at the same time is not supported.
+ * Attempting to set both read bits in $wgMultiContentRevisionSchemaMigrationStage
+ * will result in an InvalidArgumentException.
  *
  * @see Task: https://phabricator.wikimedia.org/T174028
  * @see Commit: https://gerrit.wikimedia.org/r/#/c/378724/
  *
  * @since 1.32
- * @var int One of the MIGRATION_* constants
+ * @var int An appropriate combination of SCHEMA_COMPAT_XXX flags.
  */
 $wgMultiContentRevisionSchemaMigrationStage = MIGRATION_OLD;
 
index e5261e7..72cddd2 100644 (file)
@@ -270,11 +270,34 @@ define( 'CONTENT_FORMAT_XML', 'application/xml' );
 define( 'SHELL_MAX_ARG_STRLEN', '100000' );
 /**@}*/
 
+/**@{
+ * Schema compatibility flags.
+ *
+ * Used as flags in a bit field that indicates whether the old or new schema (or both)
+ * are read or written.
+ *
+ * - SCHEMA_COMPAT_WRITE_OLD: Whether information is written to the old schema.
+ * - SCHEMA_COMPAT_READ_OLD: Whether information stored in the old schema is read.
+ * - SCHEMA_COMPAT_WRITE_NEW: Whether information is written to the new schema.
+ * - SCHEMA_COMPAT_READ_NEW: Whether information stored in the new schema is read.
+ */
+define( 'SCHEMA_COMPAT_WRITE_OLD', 0x01 );
+define( 'SCHEMA_COMPAT_READ_OLD', 0x02 );
+define( 'SCHEMA_COMPAT_WRITE_NEW', 0x10 );
+define( 'SCHEMA_COMPAT_READ_NEW', 0x20 );
+define( 'SCHEMA_COMPAT_WRITE_BOTH', SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_WRITE_NEW );
+define( 'SCHEMA_COMPAT_READ_BOTH', SCHEMA_COMPAT_READ_OLD | SCHEMA_COMPAT_READ_NEW );
+define( 'SCHEMA_COMPAT_OLD', SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_OLD );
+define( 'SCHEMA_COMPAT_NEW', SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_NEW );
+/**@}*/
+
 /**@{
  * Schema change migration flags.
  *
  * Used as values of a feature flag for an orderly transition from an old
- * schema to a new schema.
+ * schema to a new schema. The numeric values of these constants are compatible with the
+ * SCHEMA_COMPAT_XXX bitfield semantics. High bits are used to ensure that the numeric
+ * ordering follows the order in which the migration stages should be used.
  *
  * - MIGRATION_OLD: Only read and write the old schema. The new schema need not
  *   even exist. This is used from when the patch is merged until the schema
@@ -289,8 +312,8 @@ define( 'SHELL_MAX_ARG_STRLEN', '100000' );
  * - MIGRATION_NEW: Only read and write the new schema. The old schema (and the
  *   feature flag) may now be removed.
  */
-define( 'MIGRATION_OLD', 0 );
-define( 'MIGRATION_WRITE_BOTH', 1 );
-define( 'MIGRATION_WRITE_NEW', 2 );
-define( 'MIGRATION_NEW', 3 );
+define( 'MIGRATION_OLD', 0x00000000 | SCHEMA_COMPAT_OLD );
+define( 'MIGRATION_WRITE_BOTH', 0x10000000 | SCHEMA_COMPAT_READ_BOTH | SCHEMA_COMPAT_WRITE_BOTH );
+define( 'MIGRATION_WRITE_NEW', 0x20000000 | SCHEMA_COMPAT_READ_BOTH | SCHEMA_COMPAT_WRITE_NEW );
+define( 'MIGRATION_NEW', 0x30000000 | SCHEMA_COMPAT_NEW );
 /**@}*/
index de89ab4..dfb2b43 100644 (file)
@@ -3193,8 +3193,8 @@ ERROR;
         * Builds a standard summary input with a label.
         *
         * @param string $summary The value of the summary input
-        * @param string $labelText The html to place inside the label
-        * @param array $inputAttrs Array of attrs to use on the input
+        * @param string|null $labelText The html to place inside the label
+        * @param array|null $inputAttrs Array of attrs to use on the input
         *
         * @return OOUI\FieldLayout OOUI FieldLayout with Label and Input
         */
@@ -3327,8 +3327,8 @@ ERROR;
         * The $textoverride method can be used by subclasses overriding showContentForm
         * to pass back to this method.
         *
-        * @param array $customAttribs Array of html attributes to use in the textarea
-        * @param string $textoverride Optional text to override $this->textarea1 with
+        * @param array|null $customAttribs Array of html attributes to use in the textarea
+        * @param string|null $textoverride Optional text to override $this->textarea1 with
         */
        protected function showTextbox1( $customAttribs = null, $textoverride = null ) {
                if ( $this->wasDeletedSinceLastEdit() && $this->formtype == 'save' ) {
@@ -4026,7 +4026,7 @@ ERROR;
         * Shows a bulletin board style toolbar for common editing functions.
         * It can be disabled in the user preferences.
         *
-        * @param Title $title Title object for the page being edited (optional)
+        * @param Title|null $title Title object for the page being edited (optional)
         * @return string
         */
        public static function getEditToolbar( $title = null ) {
index 898005e..ce75037 100644 (file)
@@ -148,7 +148,7 @@ class FileDeleteForm {
         * @param string &$oldimage Archive name
         * @param string $reason Reason of the deletion
         * @param bool $suppress Whether to mark all deleted versions as restricted
-        * @param User $user User object performing the request
+        * @param User|null $user User object performing the request
         * @param array $tags Tags to apply to the deletion action
         * @throws MWException
         * @return Status
index 53c8d3b..53ddac9 100644 (file)
@@ -336,7 +336,7 @@ class FormOptions implements ArrayAccess {
         * available for accessing with getValue() or consumeValue() etc.
         *
         * @param WebRequest $r The request to fetch values from
-        * @param array $optionKeys Which options to fetch the values for (default:
+        * @param array|null $optionKeys Which options to fetch the values for (default:
         *     all of them). Note that passing an empty array will also result in
         *     values for all keys being fetched.
         * @throws MWException If the type of any option is invalid
index d0229bc..543978b 100644 (file)
@@ -1443,7 +1443,7 @@ function wfHostname() {
  * If $wgShowHostnames is true, the script will also set 'wgHostname' to the
  * hostname of the server handling the request.
  *
- * @param string $nonce Value from OutputPage::getCSPNonce
+ * @param string|null $nonce Value from OutputPage::getCSPNonce
  * @return string|WrappedString HTML
  */
 function wfReportTime( $nonce = null ) {
@@ -1980,7 +1980,7 @@ function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
  * For dealing with nullable timestamp columns in the database.
  *
  * @param int $outputtype
- * @param string $ts
+ * @param string|null $ts
  * @return string
  */
 function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
@@ -2058,8 +2058,8 @@ function wfTempDir() {
  * Make directory, and make all parent directories if they don't exist
  *
  * @param string $dir Full path to directory to create
- * @param int $mode Chmod value to use, default is $wgDirectoryMode
- * @param string $caller Optional caller param for debugging.
+ * @param int|null $mode Chmod value to use, default is $wgDirectoryMode
+ * @param string|null $caller Optional caller param for debugging.
  * @throws MWException
  * @return bool
  */
@@ -2317,7 +2317,7 @@ function wfShellWikiCmd( $script, array $parameters = [], array $options = [] )
  * @param string $mine
  * @param string $yours
  * @param string &$result
- * @param string &$mergeAttemptResult
+ * @param string|null &$mergeAttemptResult
  * @return bool
  */
 function wfMerge( $old, $mine, $yours, &$result, &$mergeAttemptResult = null ) {
@@ -3200,7 +3200,7 @@ function wfUnpack( $format, $data, $length = false ) {
  *
  * @param string $name The image name to check
  * @param Title|bool $contextTitle The page on which the image occurs, if known
- * @param string $blacklist Wikitext of a file blacklist
+ * @param string|null $blacklist Wikitext of a file blacklist
  * @return bool
  */
 function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
index 0016426..3dd21c1 100644 (file)
@@ -557,7 +557,7 @@ class Html {
         * literal "</script>" or (for XML) literal "]]>".
         *
         * @param string $contents JavaScript
-        * @param string $nonce Nonce for CSP header, from OutputPage::getCSPNonce()
+        * @param string|null $nonce Nonce for CSP header, from OutputPage::getCSPNonce()
         * @return string Raw HTML
         */
        public static function inlineScript( $contents, $nonce = null ) {
@@ -582,7 +582,7 @@ class Html {
         * "<script src=foo.js></script>".
         *
         * @param string $url
-        * @param string $nonce Nonce for CSP header, from OutputPage::getCSPNonce()
+        * @param string|null $nonce Nonce for CSP header, from OutputPage::getCSPNonce()
         * @return string Raw HTML
         */
        public static function linkedScript( $url, $nonce = null ) {
index 89a6a10..b807ecc 100644 (file)
@@ -904,7 +904,7 @@ class Linker {
         *   red if the user has no edits?
         * @param int $flags Customisation flags (e.g. Linker::TOOL_LINKS_NOBLOCK
         *   and Linker::TOOL_LINKS_EMAIL).
-        * @param int $edits User edit count (optional, for performance)
+        * @param int|null $edits User edit count (optional, for performance)
         * @return string HTML fragment
         */
        public static function userToolLinks(
@@ -966,7 +966,7 @@ class Linker {
         * @since 1.16.3
         * @param int $userId User identifier
         * @param string $userText User name or IP address
-        * @param int $edits User edit count (optional, for performance)
+        * @param int|null $edits User edit count (optional, for performance)
         * @return string
         */
        public static function userToolLinksRedContribs( $userId, $userText, $edits = null ) {
@@ -1678,7 +1678,7 @@ class Linker {
         * @since 1.16.3. $context added in 1.20. $options added in 1.21
         *
         * @param Revision $rev
-        * @param IContextSource $context Context to use or null for the main context.
+        * @param IContextSource|null $context Context to use or null for the main context.
         * @param array $options
         * @return string
         */
index 1df5d51..e03a29b 100644 (file)
@@ -477,7 +477,7 @@ class MWNamespace {
         *
         * @since 1.23
         * @param int $index Index to check
-        * @param User $user User to check
+        * @param User|null $user User to check
         * @return array
         */
        public static function getRestrictionLevels( $index, User $user = null ) {
index 7f3649e..d28169f 100644 (file)
@@ -138,9 +138,9 @@ class MWTimestamp extends ConvertibleTimestamp {
         * Generate a purely relative timestamp, i.e., represent the time elapsed between
         * the given base timestamp and this object.
         *
-        * @param MWTimestamp $relativeTo Relative base timestamp (defaults to now)
-        * @param User $user Use to use offset for
-        * @param Language $lang Language to use
+        * @param MWTimestamp|null $relativeTo Relative base timestamp (defaults to now)
+        * @param User|null $user Use to use offset for
+        * @param Language|null $lang Language to use
         * @param array $chosenIntervals Intervals to use to represent it
         * @return string Relative timestamp
         */
index 17a4a0f..9cef700 100644 (file)
@@ -257,7 +257,7 @@ class MagicWord {
         *
         * Use factory instead: MagicWord::get
         *
-        * @param string $id The internal name of the magic word
+        * @param string|null $id The internal name of the magic word
         * @param string[]|string $syn synonyms for the magic word
         * @param bool $cs If magic word is case sensitive
         */
index bcc3633..b11239a 100644 (file)
@@ -568,7 +568,7 @@ class MediaWiki {
 
        /**
         * @see MediaWiki::preOutputCommit()
-        * @param callable $postCommitWork [default: null]
+        * @param callable|null $postCommitWork [default: null]
         * @since 1.26
         */
        public function doPreOutputCommit( callable $postCommitWork = null ) {
@@ -580,7 +580,7 @@ class MediaWiki {
         * the user can receive a response (in case commit fails)
         *
         * @param IContextSource $context
-        * @param callable $postCommitWork [default: null]
+        * @param callable|null $postCommitWork [default: null]
         * @since 1.27
         */
        public static function preOutputCommit(
index 84ab7ca..a499035 100644 (file)
@@ -242,7 +242,7 @@ class Message implements MessageSpecifier, Serializable {
         * message keys to try and use the first non-empty message for, or a
         * MessageSpecifier to copy from.
         * @param array $params Message parameters.
-        * @param Language $language [optional] Language to use (defaults to current user language).
+        * @param Language|null $language [optional] Language to use (defaults to current user language).
         * @throws InvalidArgumentException
         */
        public function __construct( $key, $params = [], Language $language = null ) {
index 4ce49fd..3b4b14a 100644 (file)
@@ -469,7 +469,7 @@ class OutputPage extends ContextSource {
         * Internal use only. Use OutputPage::addModules() if possible.
         *
         * @param string $file URL to file (absolute path, protocol-relative, or full url)
-        * @param string $unused Previously used to change the cache-busting query parameter
+        * @param string|null $unused Previously used to change the cache-busting query parameter
         */
        public function addScriptFile( $file, $unused = null ) {
                if ( substr( $file, 0, 1 ) !== '/' && !preg_match( '#^[a-z]*://#i', $file ) ) {
@@ -1929,7 +1929,7 @@ class OutputPage extends ContextSource {
         * @param bool $interface Use interface language ($wgLang instead of
         *   $wgContLang) while parsing language sensitive magic words like GRAMMAR and PLURAL.
         *   This also disables LanguageConverter.
-        * @param Language $language Target language object, will override $interface
+        * @param Language|null $language Target language object, will override $interface
         * @throws MWException
         * @return string HTML
         */
@@ -2533,7 +2533,7 @@ class OutputPage extends ContextSource {
         * Output a standard permission error page
         *
         * @param array $errors Error message keys or [key, param...] arrays
-        * @param string $action Action that was denied or null if unknown
+        * @param string|null $action Action that was denied or null if unknown
         */
        public function showPermissionsErrorPage( array $errors, $action = null ) {
                foreach ( $errors as $key => $error ) {
@@ -2623,7 +2623,7 @@ class OutputPage extends ContextSource {
         * Format a list of error messages
         *
         * @param array $errors Array of arrays returned by Title::getUserPermissionsErrors
-        * @param string $action Action that was denied or null if unknown
+        * @param string|null $action Action that was denied or null if unknown
         * @return string The wikitext error-messages, formatted into a list.
         */
        public function formatPermissionsErrorMessage( array $errors, $action = null ) {
@@ -2708,7 +2708,7 @@ class OutputPage extends ContextSource {
         *
         * @param Title $title Title to link
         * @param array $query Query string parameters
-        * @param string $text Text of the link (input is not escaped)
+        * @param string|null $text Text of the link (input is not escaped)
         * @param array $options Options array to pass to Linker
         */
        public function addReturnTo( $title, array $query = [], $text = null, $options = [] ) {
@@ -2723,9 +2723,9 @@ class OutputPage extends ContextSource {
         * Add a "return to" link pointing to a specified title,
         * or the title indicated in the request, or else the main page
         *
-        * @param mixed $unused
-        * @param Title|string $returnto Title or String to return to
-        * @param string $returntoquery Query string for the return to link
+        * @param mixed|null $unused
+        * @param Title|string|null $returnto Title or String to return to
+        * @param string|null $returntoquery Query string for the return to link
         */
        public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
                if ( $returnto == null ) {
@@ -3055,7 +3055,7 @@ class OutputPage extends ContextSource {
         * Add one or more variables to be set in mw.config in JavaScript
         *
         * @param string|array $keys Key or array of key/value pairs
-        * @param mixed $value [optional] Value of the configuration variable
+        * @param mixed|null $value [optional] Value of the configuration variable
         */
        public function addJsConfigVars( $keys, $value = null ) {
                if ( is_array( $keys ) ) {
index 64b54f1..ee608c2 100644 (file)
@@ -50,8 +50,8 @@ class Pingback {
        protected $id;
 
        /**
-        * @param Config $config
-        * @param LoggerInterface $logger
+        * @param Config|null $config
+        * @param LoggerInterface|null $logger
         */
        public function __construct( Config $config = null, LoggerInterface $logger = null ) {
                $this->config = $config ?: RequestContext::getMain()->getConfig();
index 51c2923..1f3de50 100644 (file)
@@ -196,7 +196,7 @@ class ProtectionForm {
        /**
         * Show the input form with optional error message
         *
-        * @param string $err Error message or null if there's no error
+        * @param string|null $err Error message or null if there's no error
         */
        function show( $err = null ) {
                $out = $this->mContext->getOutput();
index dc15f97..d6ff384 100644 (file)
@@ -887,7 +887,7 @@ class Revision implements IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to $user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @since 1.21
         * @return Content|null
index 8e77956..1eaedc2 100644 (file)
@@ -180,7 +180,7 @@ class SiteConfiguration {
         * Retrieves a configuration setting for a given wiki.
         * @param string $settingName ID of the setting name to retrieve
         * @param string $wiki Wiki ID of the wiki in question.
-        * @param string $suffix The suffix of the wiki in question.
+        * @param string|null $suffix The suffix of the wiki in question.
         * @param array $params List of parameters. $.'key' is replaced by $value in all returned data.
         * @param array $wikiTags The tags assigned to the wiki.
         * @return mixed The value of the setting requested.
@@ -294,7 +294,7 @@ class SiteConfiguration {
        /**
         * Gets all settings for a wiki
         * @param string $wiki Wiki ID of the wiki in question.
-        * @param string $suffix The suffix of the wiki in question.
+        * @param string|null $suffix The suffix of the wiki in question.
         * @param array $params List of parameters. $.'key' is replaced by $value in all returned data.
         * @param array $wikiTags The tags assigned to the wiki.
         * @return array Array of settings requested.
@@ -325,7 +325,7 @@ class SiteConfiguration {
         * Retrieves a configuration setting for a given wiki, forced to a boolean.
         * @param string $setting ID of the setting name to retrieve
         * @param string $wiki Wiki ID of the wiki in question.
-        * @param string $suffix The suffix of the wiki in question.
+        * @param string|null $suffix The suffix of the wiki in question.
         * @param array $wikiTags The tags assigned to the wiki.
         * @return bool The value of the setting requested.
         */
@@ -364,7 +364,7 @@ class SiteConfiguration {
         * Retrieves the value of a given setting, and places it in its corresponding global variable.
         * @param string $setting ID of the setting name to retrieve
         * @param string $wiki Wiki ID of the wiki in question.
-        * @param string $suffix The suffix of the wiki in question.
+        * @param string|null $suffix The suffix of the wiki in question.
         * @param array $params List of parameters. $.'key' is replaced by $value in all returned data.
         * @param array $wikiTags The tags assigned to the wiki.
         */
@@ -399,7 +399,7 @@ class SiteConfiguration {
        /**
         * Retrieves the values of all settings, and places them in their corresponding global variables.
         * @param string $wiki Wiki ID of the wiki in question.
-        * @param string $suffix The suffix of the wiki in question.
+        * @param string|null $suffix The suffix of the wiki in question.
         * @param array $params List of parameters. $.'key' is replaced by $value in all returned data.
         * @param array $wikiTags The tags assigned to the wiki.
         */
index f17f173..8cd72a5 100644 (file)
@@ -171,7 +171,7 @@ class Status extends StatusValue {
         * @param string|bool $shortContext A short enclosing context message name, to
         *        be used when there is a single error
         * @param string|bool $longContext A long enclosing context message name, for a list
-        * @param string|Language $lang Language to use for processing messages
+        * @param string|Language|null $lang Language to use for processing messages
         * @return string
         */
        public function getWikiText( $shortContext = false, $longContext = false, $lang = null ) {
@@ -227,7 +227,7 @@ class Status extends StatusValue {
         *
         * @param string|string[]|bool $shortContext A message name or an array of message names.
         * @param string|string[]|bool $longContext A message name or an array of message names.
-        * @param string|Language $lang Language to use for processing messages
+        * @param string|Language|null $lang Language to use for processing messages
         * @return Message
         */
        public function getMessage( $shortContext = false, $longContext = false, $lang = null ) {
@@ -279,7 +279,7 @@ class Status extends StatusValue {
         * If $error is an array, the "params" field is a list of parameters for the message.
         *
         * @param array|string $error Code string or (key: code string, params: string[]) map
-        * @param string|Language $lang Language to use for processing messages
+        * @param string|Language|null $lang Language to use for processing messages
         * @return Message
         */
        protected function getErrorMessage( $error, $lang = null ) {
@@ -324,7 +324,7 @@ class Status extends StatusValue {
        /**
         * Return an array with a Message object for each error.
         * @param array $errors
-        * @param string|Language $lang Language to use for processing messages
+        * @param string|Language|null $lang Language to use for processing messages
         * @return Message[]
         */
        protected function getErrorMessageArray( $errors, $lang = null ) {
index 8da812a..73463b5 100644 (file)
@@ -241,7 +241,7 @@ class DerivedPageDataUpdater implements IDBAccessObject {
         * @param JobQueueGroup $jobQueueGroup
         * @param MessageCache $messageCache
         * @param Language $contentLanguage
-        * @param LoggerInterface $saveParseLogger
+        * @param LoggerInterface|null $saveParseLogger
         */
        public function __construct(
                WikiPage $wikiPage,
index 1982d02..3516ffe 100644 (file)
@@ -70,10 +70,10 @@ class NameTableStore {
         * @param string $table
         * @param string $idField
         * @param string $nameField
-        * @param callable $normalizationCallback Normalization to be applied to names before being
+        * @param callable|null $normalizationCallback Normalization to be applied to names before being
         * saved or queried. This should be a callback that accepts and returns a single string.
         * @param bool|string $wikiId The ID of the target wiki database. Use false for the local wiki.
-        * @param callable $insertCallback Callback to change insert fields accordingly.
+        * @param callable|null $insertCallback Callback to change insert fields accordingly.
         * This parameter was introduced in 1.32
         */
        public function __construct(
@@ -109,8 +109,20 @@ class NameTableStore {
                return $this->loadBalancer->getConnection( $index, [], $this->wikiId, $flags );
        }
 
+       /**
+        * Gets the cache key for names.
+        *
+        * The cache key is constructed based on the wiki ID passed to the constructor, and allows
+        * sharing of name tables cached for a specific database between wikis.
+        *
+        * @return string
+        */
        private function getCacheKey() {
-               return $this->cache->makeKey( 'NameTableSqlStore', $this->table, $this->wikiId );
+               return $this->cache->makeGlobalKey(
+                       'NameTableSqlStore',
+                       $this->table,
+                       $this->loadBalancer->resolveDomainID( $this->wikiId )
+               );
        }
 
        /**
index 2376d16..67928f9 100644 (file)
@@ -344,6 +344,10 @@ class PageUpdater {
                // TODO: MCR: check the role and the content's model against the list of supported
                // roles, see T194046.
 
+               if ( $role !== 'main' ) {
+                       throw new InvalidArgumentException( 'Only the main slot is presently supported' );
+               }
+
                $this->slotsUpdate->modifyContent( $role, $content );
        }
 
index 86e8c06..2c45468 100644 (file)
@@ -77,7 +77,7 @@ interface RevisionFactory {
         *        Use RevisionStore::getArchiveQueryInfo() to build a query that yields the
         *        required fields.
         * @param int $queryFlags Flags for lazy loading behavior, see IDBAccessObject::READ_XXX.
-        * @param Title $title
+        * @param Title|null $title
         * @param array $overrides An associative array that allows fields in $row to be overwritten.
         *        Keys in this array correspond to field names in $row without the "ar_" prefix, so
         *        $overrides['user'] will override $row->ar_user, etc.
index 45cd184..a6e2930 100644 (file)
@@ -84,7 +84,7 @@ interface RevisionLookup extends IDBAccessObject {
         * MCR migration note: this replaces Revision::getPrevious
         *
         * @param RevisionRecord $rev
-        * @param Title $title if known (optional)
+        * @param Title|null $title if known (optional)
         *
         * @return RevisionRecord|null
         */
@@ -96,7 +96,7 @@ interface RevisionLookup extends IDBAccessObject {
         * MCR migration note: this replaces Revision::getNext
         *
         * @param RevisionRecord $rev
-        * @param Title $title if known (optional)
+        * @param Title|null $title if known (optional)
         *
         * @return RevisionRecord|null
         */
index 12bee1e..b01bdd8 100644 (file)
@@ -122,7 +122,7 @@ class RevisionStore
         */
        private $slotRoleStore;
 
-       /** @var int One of the MIGRATION_* constants */
+       /** @var int An appropriate combination of SCHEMA_COMPAT_XXX flags. */
        private $mcrMigrationStage;
 
        /**
@@ -134,9 +134,11 @@ class RevisionStore
         * @param CommentStore $commentStore
         * @param NameTableStore $contentModelStore
         * @param NameTableStore $slotRoleStore
-        * @param int $migrationStage
+        * @param int $mcrMigrationStage An appropriate combination of SCHEMA_COMPAT_XXX flags
         * @param ActorMigration $actorMigration
         * @param bool|string $wikiId
+        *
+        * @throws MWException if $mcrMigrationStage or $wikiId is invalid.
         */
        public function __construct(
                LoadBalancer $loadBalancer,
@@ -145,12 +147,39 @@ class RevisionStore
                CommentStore $commentStore,
                NameTableStore $contentModelStore,
                NameTableStore $slotRoleStore,
-               $migrationStage,
+               $mcrMigrationStage,
                ActorMigration $actorMigration,
                $wikiId = false
        ) {
                Assert::parameterType( 'string|boolean', $wikiId, '$wikiId' );
-               Assert::parameterType( 'integer', $migrationStage, '$migrationStage' );
+               Assert::parameterType( 'integer', $mcrMigrationStage, '$mcrMigrationStage' );
+               Assert::parameter(
+                       ( $mcrMigrationStage & SCHEMA_COMPAT_READ_BOTH ) !== SCHEMA_COMPAT_READ_BOTH,
+                       '$mcrMigrationStage',
+                       'Reading from the old and the new schema at the same time is not supported.'
+               );
+               Assert::parameter(
+                       ( $mcrMigrationStage & SCHEMA_COMPAT_READ_BOTH ) !== 0,
+                       '$mcrMigrationStage',
+                       'Reading needs to be enabled for the old or the new schema.'
+               );
+               Assert::parameter(
+                       ( $mcrMigrationStage & SCHEMA_COMPAT_WRITE_BOTH ) !== 0,
+                       '$mcrMigrationStage',
+                       'Writing needs to be enabled for the old or the new schema.'
+               );
+               Assert::parameter(
+                       ( $mcrMigrationStage & SCHEMA_COMPAT_READ_OLD ) === 0
+                       || ( $mcrMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) !== 0,
+                       '$mcrMigrationStage',
+                       'Cannot read the old schema when not also writing it.'
+               );
+               Assert::parameter(
+                       ( $mcrMigrationStage & SCHEMA_COMPAT_READ_NEW ) === 0
+                       || ( $mcrMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) !== 0,
+                       '$mcrMigrationStage',
+                       'Cannot read the new schema when not also writing it.'
+               );
 
                $this->loadBalancer = $loadBalancer;
                $this->blobStore = $blobStore;
@@ -158,12 +187,21 @@ class RevisionStore
                $this->commentStore = $commentStore;
                $this->contentModelStore = $contentModelStore;
                $this->slotRoleStore = $slotRoleStore;
-               $this->mcrMigrationStage = $migrationStage;
+               $this->mcrMigrationStage = $mcrMigrationStage;
                $this->actorMigration = $actorMigration;
                $this->wikiId = $wikiId;
                $this->logger = new NullLogger();
        }
 
+       /**
+        * @param int $flags A combination of SCHEMA_COMPAT_XXX flags.
+        * @return bool True if all the given flags were set in the $mcrMigrationStage
+        *         parameter passed to the constructor.
+        */
+       private function hasMcrSchemaFlags( $flags ) {
+               return ( $this->mcrMigrationStage & $flags ) === $flags;
+       }
+
        public function setLogger( LoggerInterface $logger ) {
                $this->logger = $logger;
        }
@@ -188,10 +226,14 @@ class RevisionStore
         * @throws MWException
         */
        public function setContentHandlerUseDB( $contentHandlerUseDB ) {
-               if ( !$contentHandlerUseDB && $this->mcrMigrationStage > MIGRATION_OLD ) {
-                       throw new MWException(
-                               'Content model must be stored in the database for multi content revision migration.'
-                       );
+               if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW )
+                       || $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW )
+               ) {
+                       if ( !$contentHandlerUseDB ) {
+                               throw new MWException(
+                                       'Content model must be stored in the database for multi content revision migration.'
+                               );
+                       }
                }
                $this->contentHandlerUseDB = $contentHandlerUseDB;
        }
@@ -372,11 +414,17 @@ class RevisionStore
                        );
                }
 
-               // While inserting into the old schema make sure only the main slot is allowed.
-               // TODO: support extra slots in MIGRATION_WRITE_BOTH mode!
-               if ( $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH && $slotRoles !== [ 'main' ] ) {
+               // If we are not writing into the new schema, we can't support extra slots.
+               if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) && $slotRoles !== [ 'main' ] ) {
                        throw new InvalidArgumentException(
-                               'Only the main slot is supported with MCR migration mode <= MIGRATION_WRITE_BOTH!'
+                               'Only the main slot is supported when not writing to the MCR enabled schema!'
+                       );
+               }
+
+               // As long as we are not reading from the new schema, we don't want to write extra slots.
+               if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) && $slotRoles !== [ 'main' ] ) {
+                       throw new InvalidArgumentException(
+                               'Only the main slot is supported when not reading from the MCR enabled schema!'
                        );
                }
 
@@ -433,7 +481,7 @@ class RevisionStore
                );
 
                // Trigger exception if the main slot is missing.
-               // Technically, this could go away with MIGRATION_NEW: while
+               // Technically, this could go away after MCR migration: while
                // calling code may require a main slot to exist, RevisionStore
                // really should not know or care about that requirement.
                $rev->getSlot( 'main', RevisionRecord::RAW );
@@ -506,7 +554,9 @@ class RevisionStore
                                $newSlots[$role] = $slot;
 
                                // Write the main slot's text ID to the revision table for backwards compatibility
-                               if ( $slot->getRole() === 'main' && $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH ) {
+                               if ( $slot->getRole() === 'main'
+                                       && $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD )
+                               ) {
                                        $blobAddress = $slot->getAddress();
                                        $this->updateRevisionTextId( $dbw, $revisionId, $blobAddress );
                                }
@@ -576,11 +626,13 @@ class RevisionStore
                }
 
                // Write the main slot's text ID to the revision table for backwards compatibility
-               if ( $protoSlot->getRole() === 'main' && $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH ) {
+               if ( $protoSlot->getRole() === 'main'
+                       && $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD )
+               ) {
                        $this->updateRevisionTextId( $dbw, $revisionId, $blobAddress );
                }
 
-               if ( $this->mcrMigrationStage >= MIGRATION_WRITE_BOTH ) {
+               if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) ) {
                        if ( $protoSlot->hasContentId() ) {
                                $contentId = $protoSlot->getContentId();
                        } else {
@@ -705,8 +757,8 @@ class RevisionStore
                        $revisionRow['rev_id'] = $rev->getId();
                }
 
-               if ( $this->mcrMigrationStage <= MIGRATION_WRITE_BOTH ) {
-                       // In non MCR more this IF section will relate to the main slot
+               if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD ) ) {
+                       // In non MCR mode this IF section will relate to the main slot
                        $mainSlot = $rev->getSlot( 'main' );
                        $model = $mainSlot->getModel();
                        $format = $mainSlot->getFormat();
@@ -1042,7 +1094,7 @@ class RevisionStore
                $blobFlags = null;
 
                if ( is_object( $row ) ) {
-                       if ( $this->mcrMigrationStage >= MIGRATION_NEW ) {
+                       if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) ) {
                                // Don't emulate from a row when using the new schema.
                                // Emulating from an array is still OK.
                                throw new LogicException( 'Can\'t emulate the main slot when using MCR schema.' );
@@ -1425,10 +1477,7 @@ class RevisionStore
                $queryFlags,
                Title $title
        ) {
-               if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
-                       // TODO: in MIGRATION_WRITE_BOTH, we could use the old and the new method:
-                       // e.g. call emulateMainSlot_1_29() if loadSlotRecords() fails.
-
+               if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) ) {
                        $mainSlot = $this->emulateMainSlot_1_29( $revisionRow, $queryFlags, $title );
                        $slots = new RevisionSlots( [ 'main' => $mainSlot ] );
                } else {
@@ -1610,8 +1659,8 @@ class RevisionStore
                }
 
                if ( !empty( $fields['text_id'] ) ) {
-                       if ( $this->mcrMigrationStage >= MIGRATION_NEW ) {
-                               throw new MWException( "Cannot use text_id field with MCR schema" );
+                       if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
+                               throw new MWException( "The text_id field is only available in the pre-MCR schema" );
                        }
 
                        if ( !empty( $fields['content'] ) ) {
@@ -1843,7 +1892,7 @@ class RevisionStore
         *
         * @param array $conditions
         * @param int $flags (optional)
-        * @param Title $title
+        * @param Title|null $title
         *
         * @return RevisionRecord|null
         */
@@ -1879,7 +1928,7 @@ class RevisionStore
         * @param IDatabase $db
         * @param array $conditions
         * @param int $flags (optional)
-        * @param Title $title
+        * @param Title|null $title
         *
         * @return RevisionRecord|null
         */
@@ -1967,7 +2016,8 @@ class RevisionStore
        /**
         * Finds the ID of a content row for a given revision and slot role.
         * This can be used to re-use content rows even while the content ID
-        * is still missing from SlotRecords, in MIGRATION_WRITE_BOTH mode.
+        * is still missing from SlotRecords, when writing to both the old and
+        * the new schema during MCR schema migration.
         *
         * @todo remove after MCR schema migration is complete.
         *
@@ -1978,7 +2028,7 @@ class RevisionStore
         * @return int|null
         */
        private function findSlotContentId( IDatabase $db, $revId, $role ) {
-               if ( $this->mcrMigrationStage < MIGRATION_WRITE_BOTH ) {
+               if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) ) {
                        return null;
                }
 
@@ -2014,8 +2064,8 @@ class RevisionStore
         *  - 'page': Join with the page table, and select fields to identify the page
         *  - 'user': Join with the user table, and select the user name
         *  - 'text': Join with the text table, and select fields to load page text. This
-        *    option is deprecated in MW 1.32 with MCR migration stage MIGRATION_WRITE_BOTH,
-        *    and disallowed with MIGRATION_MEW.
+        *    option is deprecated in MW 1.32 when the MCR migration flag SCHEMA_COMPAT_WRITE_NEW
+        *    is set, and disallowed when SCHEMA_COMPAT_READ_OLD is not set.
         *
         * @return array With three keys:
         *  - tables: (string[]) to include in the `$table` to `IDatabase->select()`
@@ -2051,7 +2101,7 @@ class RevisionStore
                $ret['fields'] = array_merge( $ret['fields'], $actorQuery['fields'] );
                $ret['joins'] = array_merge( $ret['joins'], $actorQuery['joins'] );
 
-               if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
+               if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
                        $ret['fields'][] = 'rev_text_id';
 
                        if ( $this->contentHandlerUseDB ) {
@@ -2083,9 +2133,12 @@ class RevisionStore
                }
 
                if ( in_array( 'text', $options, true ) ) {
-                       if ( $this->mcrMigrationStage === MIGRATION_NEW ) {
+                       if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD ) ) {
                                throw new InvalidArgumentException( 'text table can no longer be joined directly' );
-                       } elseif ( $this->mcrMigrationStage >= MIGRATION_WRITE_BOTH ) {
+                       } elseif ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
+                               // NOTE: even when this class is set to not read from the old schema, callers
+                               // should still be able to join against the text table, as long as we are still
+                               // writing the old schema for compatibility.
                                wfDeprecated( __METHOD__ . ' with `text` option', '1.32' );
                        }
 
@@ -2121,7 +2174,7 @@ class RevisionStore
                        'joins'  => [],
                ];
 
-               if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
+               if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
                        $db = $this->getDBConnectionRef( DB_REPLICA );
                        $ret['tables']['slots'] = 'revision';
 
@@ -2142,10 +2195,6 @@ class RevisionStore
                                        $ret['fields']['model_name'] = 'NULL';
                                }
                        }
-
-                       // XXX: in MIGRATION_WRITE_BOTH mode, emulate *and* select - using a UNION?
-                       // See Anomie's idea at <https://gerrit.wikimedia.org/r/c/416465/
-                       // 8..10/includes/Storage/RevisionStore.php#2113>
                } else {
                        $ret['tables'][] = 'slots';
                        $ret['tables'][] = 'slot_roles';
@@ -2208,7 +2257,7 @@ class RevisionStore
                        'joins' => $commentQuery['joins'] + $actorQuery['joins'],
                ];
 
-               if ( $this->mcrMigrationStage < MIGRATION_NEW ) {
+               if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_OLD ) ) {
                        $ret['fields'][] = 'ar_text_id';
 
                        if ( $this->contentHandlerUseDB ) {
@@ -2273,7 +2322,7 @@ class RevisionStore
         * MCR migration note: this replaces Revision::getPrevious
         *
         * @param RevisionRecord $rev
-        * @param Title $title if known (optional)
+        * @param Title|null $title if known (optional)
         *
         * @return RevisionRecord|null
         */
@@ -2294,7 +2343,7 @@ class RevisionStore
         * MCR migration note: this replaces Revision::getNext
         *
         * @param RevisionRecord $rev
-        * @param Title $title if known (optional)
+        * @param Title|null $title if known (optional)
         *
         * @return RevisionRecord|null
         */
index fb3ef94..48ffe2c 100644 (file)
@@ -267,8 +267,7 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
 
                // No negative caching; negative hits on text rows may be due to corrupted replica DBs
                $blob = $this->cache->getWithSetCallback(
-                       // TODO: change key, since this is not necessarily revision text!
-                       $this->cache->makeKey( 'revisiontext', 'textid', $blobAddress ),
+                       $this->getCacheKey( $blobAddress ),
                        $this->getCacheTTL(),
                        function ( $unused, &$ttl, &$setOpts ) use ( $blobAddress, $queryFlags ) {
                                list( $index ) = DBAccessObjectUtils::getDBOptions( $queryFlags );
@@ -356,6 +355,25 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
                return $blob;
        }
 
+       /**
+        * Get a cache key for a given Blob address.
+        *
+        * The cache key is constructed in a way that allows cached blobs from the same database
+        * to be re-used between wikis. For example, enwiki and frwiki will use the same cache keys
+        * for blobs from the wikidatawiki database.
+        *
+        * @param string $blobAddress
+        * @return string
+        */
+       private function getCacheKey( $blobAddress ) {
+               return $this->cache->makeGlobalKey(
+                       'BlobStore',
+                       'address',
+                       $this->dbLoadBalancer->resolveDomainID( $this->wikiId ),
+                       $blobAddress
+               );
+       }
+
        /**
         * Expand a raw data blob according to the flags given.
         *
@@ -370,7 +388,8 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
         * @param string|string[] $flags Blob flags, such as 'external' or 'gzip'.
         *   Note that not including 'utf-8' in $flags will cause the data to be decoded
         *   according to the legacy encoding specified via setLegacyEncoding.
-        * @param string|null $cacheKey May be used for caching if given
+        * @param string|null $cacheKey A blob address for use in the cache key. If not given,
+        *   caching is disabled.
         *
         * @return false|string The expanded blob or false on failure
         */
@@ -387,13 +406,10 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
                                return false;
                        }
 
-                       if ( $cacheKey && $this->wikiId === false ) {
-                               // Make use of the wiki-local revision text cache.
+                       if ( $cacheKey ) {
                                // The cached value should be decompressed, so handle that and return here.
-                               // NOTE: we rely on $this->cache being the right cache for $this->wikiId!
                                return $this->cache->getWithSetCallback(
-                                       // TODO: change key, since this is not necessarily revision text!
-                                       $this->cache->makeKey( 'revisiontext', 'textid', $cacheKey ),
+                                       $this->getCacheKey( $cacheKey ),
                                        $this->getCacheTTL(),
                                        function () use ( $url, $flags ) {
                                                // No negative caching per BlobStore::getBlob()
index 067f11f..9213076 100644 (file)
@@ -56,8 +56,8 @@ class StubObject {
        protected $params;
 
        /**
-        * @param string $global Name of the global variable.
-        * @param string|callable $class Name of the class of the real object
+        * @param string|null $global Name of the global variable.
+        * @param string|callable|null $class Name of the class of the real object
         *                               or a factory function to call
         * @param array $params Parameters to pass to constructor of the real object.
         */
index 2293dab..9271e3f 100644 (file)
@@ -46,7 +46,7 @@ class TemplateParser {
        protected $compileFlags = LightnCandy::FLAG_ERROR_EXCEPTION;
 
        /**
-        * @param string $templateDir
+        * @param string|null $templateDir
         * @param bool $forceRecompile
         */
        public function __construct( $templateDir = null, $forceRecompile = false ) {
index f6e5912..8586ad7 100644 (file)
@@ -2086,7 +2086,7 @@ class Title implements LinkTarget {
         * May provide false positives, but should never provide a false negative.
         *
         * @param string $action Action that permission needs to be checked for
-        * @param User $user User to check (since 1.19); $wgUser will be used if not provided.
+        * @param User|null $user User to check (since 1.19); $wgUser will be used if not provided.
         * @return bool
         */
        public function quickUserCan( $action, $user = null ) {
@@ -2097,7 +2097,7 @@ class Title implements LinkTarget {
         * Can $user perform $action on this page?
         *
         * @param string $action Action that permission needs to be checked for
-        * @param User $user User to check (since 1.19); $wgUser will be used if not
+        * @param User|null $user User to check (since 1.19); $wgUser will be used if not
         *   provided.
         * @param string $rigor Same format as Title::getUserPermissionsErrors()
         * @return bool
@@ -3139,7 +3139,7 @@ class Title implements LinkTarget {
         * Public for usage by LiquidThreads.
         *
         * @param array $rows Array of db result objects
-        * @param string $oldFashionedRestrictions Comma-separated set of permission keys
+        * @param string|null $oldFashionedRestrictions Comma-separated set of permission keys
         * indicating who can move or edit the page from the page table, (pre 1.10) rows.
         * Edit and move sections are separated by a colon
         * Example: "edit=autoconfirmed,sysop:move=sysop"
@@ -3211,7 +3211,7 @@ class Title implements LinkTarget {
        /**
         * Load restrictions from the page_restrictions table
         *
-        * @param string $oldFashionedRestrictions Comma-separated set of permission keys
+        * @param string|null $oldFashionedRestrictions Comma-separated set of permission keys
         * indicating who can move or edit the page from the page table, (pre 1.10) rows.
         * Edit and move sections are separated by a colon
         * Example: "edit=autoconfirmed,sysop:move=sysop"
@@ -4681,7 +4681,7 @@ class Title implements LinkTarget {
        /**
         * Updates page_touched for this page; called from LinksUpdate.php
         *
-        * @param string $purgeTime [optional] TS_MW timestamp
+        * @param string|null $purgeTime [optional] TS_MW timestamp
         * @return bool True if the update succeeded
         */
        public function invalidateCache( $purgeTime = null ) {
@@ -4752,7 +4752,7 @@ class Title implements LinkTarget {
        /**
         * Get the timestamp when this page was updated since the user last saw it.
         *
-        * @param User $user
+        * @param User|null $user
         * @return string|null
         */
        public function getNotificationTimestamp( $user = null ) {
index b499d86..f3edebc 100644 (file)
@@ -484,7 +484,7 @@ class WebRequest {
         * If no source and no default, returns null.
         *
         * @param string $name
-        * @param array $default Optional default (or null)
+        * @param array|null $default Optional default (or null)
         * @return array|null
         */
        public function getArray( $name, $default = null ) {
@@ -503,7 +503,7 @@ class WebRequest {
         * If an array is returned, contents are guaranteed to be integers.
         *
         * @param string $name
-        * @param array $default Option default (or null)
+        * @param array|null $default Option default (or null)
         * @return array Array of ints
         */
        public function getIntArray( $name, $default = null ) {
@@ -776,8 +776,8 @@ class WebRequest {
         * Get a cookie from the $_COOKIE jar
         *
         * @param string $key The name of the cookie
-        * @param string $prefix A prefix to use for the cookie name, if not $wgCookiePrefix
-        * @param mixed $default What to return if the value isn't found
+        * @param string|null $prefix A prefix to use for the cookie name, if not $wgCookiePrefix
+        * @param mixed|null $default What to return if the value isn't found
         * @return mixed Cookie value or $default if the cookie not set
         */
        public function getCookie( $key, $prefix = null, $default = null ) {
index 90ebc4b..9dc3bfe 100644 (file)
@@ -131,7 +131,7 @@ class WikiMap {
         *
         * @param string $wikiID Wiki'd id (generally database name)
         * @param string $user User name (must be normalised before calling this function!)
-        * @param string $text Link's text; optional, default to "User:$user"
+        * @param string|null $text Link's text; optional, default to "User:$user"
         * @return string HTML link or false if the wiki was not found
         */
        public static function foreignUserLink( $wikiID, $user, $text = null ) {
@@ -143,7 +143,7 @@ class WikiMap {
         *
         * @param string $wikiID Wiki'd id (generally database name)
         * @param string $page Page name (must be normalised before calling this function!)
-        * @param string $text Link's text; optional, default to $page
+        * @param string|null $text Link's text; optional, default to $page
         * @return string|false HTML link or false if the wiki was not found
         */
        public static function makeForeignLink( $wikiID, $page, $text = null ) {
index 40be80b..8c65461 100644 (file)
@@ -31,7 +31,7 @@ class Xml {
         * characters (<, >, &) are escaped but illegals are not touched.
         *
         * @param string $element Element name
-        * @param array $attribs Name=>value pairs. Values will be escaped.
+        * @param array|null $attribs Name=>value pairs. Values will be escaped.
         * @param string $contents Null to make an open tag only; '' for a contentless closed tag (default)
         * @param bool $allowShortTag Whether '' in $contents will result in a contentless closed tag
         * @return string
@@ -103,7 +103,7 @@ class Xml {
         * This opens an XML element
         *
         * @param string $element Name of the element
-        * @param array $attribs Array of attributes, see Xml::expandAttributes()
+        * @param array|null $attribs Array of attributes, see Xml::expandAttributes()
         * @return string
         */
        public static function openElement( $element, $attribs = null ) {
@@ -136,7 +136,7 @@ class Xml {
         * Create a date selector
         *
         * @param string $selected The month which should be selected, default ''.
-        * @param string $allmonths Value of a special item denoting all month.
+        * @param string|null $allmonths Value of a special item denoting all month.
         *   Null to not include (default).
         * @param string $id Element identifier
         * @return string Html string containing the month selector
@@ -197,7 +197,7 @@ class Xml {
         *
         * @param string $selected The language code of the selected language
         * @param bool $customisedOnly If true only languages which have some content are listed
-        * @param string $inLanguage The ISO code of the language to display the select list in (optional)
+        * @param string|null $inLanguage The ISO code of the language to display the select list in
         * @param array $overrideAttrs Override the attributes of the select tag (since 1.20)
         * @param Message|null $msg Label message key (since 1.20)
         * @return array Array containing 2 items: label HTML and select list HTML
@@ -477,7 +477,7 @@ class Xml {
        /**
         * Convenience function to build an HTML drop-down list item.
         * @param string $text Text for this item. Will be HTML escaped
-        * @param string $value Form submission value; if empty, use text
+        * @param string|null $value Form submission value; if empty, use text
         * @param bool $selected If true, will be the default selected item
         * @param array $attribs Optional additional HTML attributes
         * @return string HTML
@@ -503,7 +503,7 @@ class Xml {
         * @param string $other Text for the "Other reasons" option
         * @param string $selected Option which should be pre-selected
         * @param string $class CSS classes for the drop-down
-        * @param int $tabindex Value of the tabindex attribute
+        * @param int|null $tabindex Value of the tabindex attribute
         * @return string
         */
        public static function listDropDown( $name = '', $list = '', $other = '',
@@ -758,7 +758,7 @@ class Xml {
         * @param array $fields Associative array, key is the name of a message that
         *   contains a description for the field, value is an HTML string
         *   containing the appropriate input.
-        * @param string $submitLabel The name of a message containing a label for
+        * @param string|null $submitLabel The name of a message containing a label for
         *   the submit button.
         * @param array $submitAttribs The attributes to add to the submit button
         * @return string HTML form.
@@ -799,7 +799,7 @@ class Xml {
         * Build a table of data
         * @param array $rows An array of arrays of strings, each to be a row in a table
         * @param array $attribs An array of attributes to apply to the table tag [optional]
-        * @param array $headers An array of strings to use as table headers [optional]
+        * @param array|null $headers An array of strings to use as table headers [optional]
         * @return string
         */
        public static function buildTable( $rows, $attribs = [], $headers = null ) {
index 943ee22..be4eeef 100644 (file)
@@ -1100,7 +1100,7 @@ abstract class ApiBase extends ContextSource {
         * Return true if we're to watch the page, false if not, null if no change.
         * @param string $watchlist Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
         * @param Title $titleObj The page under consideration
-        * @param string $userOption The user option to consider when $watchlist=preferences.
+        * @param string|null $userOption The user option to consider when $watchlist=preferences.
         *    If not set will use watchdefault always and watchcreations if $titleObj doesn't exist.
         * @return bool
         */
@@ -1574,7 +1574,7 @@ abstract class ApiBase extends ContextSource {
         * @param int &$value Parameter value
         * @param int|null $min Minimum value
         * @param int|null $max Maximum value for users
-        * @param int $botMax Maximum value for sysops/bots
+        * @param int|null $botMax Maximum value for sysops/bots
         * @param bool $enforceLimits Whether to enforce (die) if value is outside limits
         */
        protected function validateLimit( $paramName, &$value, $min, $max, $botMax = null,
@@ -1744,7 +1744,7 @@ abstract class ApiBase extends ContextSource {
         * Set a watch (or unwatch) based the based on a watchlist parameter.
         * @param string $watch Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
         * @param Title $titleObj The article's title to change
-        * @param string $userOption The user option to consider when $watch=preferences
+        * @param string|null $userOption The user option to consider when $watch=preferences
         */
        protected function setWatch( $watch, $titleObj, $userOption = null ) {
                $value = $this->getWatchlistValue( $watch, $titleObj, $userOption );
@@ -1812,7 +1812,7 @@ abstract class ApiBase extends ContextSource {
         * @since 1.25
         * @param string|array|Message $msg
         * @param IContextSource $context
-        * @param array $params
+        * @param array|null $params
         * @return Message|null
         */
        public static function makeMessage( $msg, IContextSource $context, array $params = null ) {
index a63dee6..ec857b7 100644 (file)
@@ -139,7 +139,7 @@ class ApiDelete extends ApiBase {
         * @param Page $page Object to work on
         * @param User $user User doing the action
         * @param string $oldimage Archive name
-        * @param string &$reason Reason for the deletion. Autogenerated if null.
+        * @param string|null &$reason Reason for the deletion. Autogenerated if null.
         * @param bool $suppress Whether to mark all deleted versions as restricted
         * @param array $tags Tags to tag the deletion with
         * @return Status
index f324eff..610ecf5 100644 (file)
@@ -165,7 +165,7 @@ class ApiMain extends ApiBase {
        /**
         * Constructs an instance of ApiMain that utilizes the module and format specified by $request.
         *
-        * @param IContextSource|WebRequest $context If this is an instance of
+        * @param IContextSource|WebRequest|null $context If this is an instance of
         *    FauxRequest, errors are thrown and no printing occurs
         * @param bool $enableWrite Should be set to true if the api may modify data
         */
@@ -1616,7 +1616,7 @@ class ApiMain extends ApiBase {
        /**
         * Log the preceding request
         * @param float $time Time in seconds
-        * @param Exception $e Exception caught while processing the request
+        * @param Exception|null $e Exception caught while processing the request
         */
        protected function logRequest( $time, $e = null ) {
                $request = $this->getRequest();
index fec55aa..d2df013 100644 (file)
@@ -143,7 +143,7 @@ class ApiModuleManager extends ContextSource {
         * Get module instance by name, or instantiate it if it does not exist
         *
         * @param string $moduleName Module name
-        * @param string $group Optionally validate that the module is in a specific group
+        * @param string|null $group Optionally validate that the module is in a specific group
         * @param bool $ignoreCache If true, force-creates a new instance and does not cache it
         *
         * @return ApiBase|null The new module instance, or null if failed
@@ -205,7 +205,7 @@ class ApiModuleManager extends ContextSource {
 
        /**
         * Get an array of modules in a specific group or all if no group is set.
-        * @param string $group Optional group filter
+        * @param string|null $group Optional group filter
         * @return array List of module names
         */
        public function getNames( $group = null ) {
@@ -224,7 +224,7 @@ class ApiModuleManager extends ContextSource {
 
        /**
         * Create an array of (moduleName => moduleClass) for a specific group or for all.
-        * @param string $group Name of the group to get or null for all
+        * @param string|null $group Name of the group to get or null for all
         * @return array Name=>class map
         */
        public function getNamesWithClasses( $group = null ) {
@@ -256,7 +256,7 @@ class ApiModuleManager extends ContextSource {
        /**
         * Returns true if the specific module is defined at all or in a specific group.
         * @param string $moduleName Module name
-        * @param string $group Group name to check against, or null to check all groups,
+        * @param string|null $group Group name to check against, or null to check all groups,
         * @return bool True if defined
         */
        public function isDefined( $moduleName, $group = null ) {
index 515ebc5..a32b288 100644 (file)
@@ -460,7 +460,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Get a list of redirect resolutions - maps a title to its redirect
         * target. Includes generator data for redirect source when available.
-        * @param ApiResult $result
+        * @param ApiResult|null $result
         * @return array Array of prefixed_title (string) => Title object
         * @since 1.21
         */
@@ -507,7 +507,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Get a list of title normalizations - maps a title to its normalized
         * version in the form of result array.
-        * @param ApiResult $result
+        * @param ApiResult|null $result
         * @return array Array of raw_prefixed_title (string) => prefixed_title (string)
         * @since 1.21
         */
@@ -542,7 +542,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Get a list of title conversions - maps a title to its converted
         * version as a result array.
-        * @param ApiResult $result
+        * @param ApiResult|null $result
         * @return array Array of (from, to) strings
         * @since 1.21
         */
@@ -573,7 +573,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Get a list of interwiki titles - maps a title to its interwiki
         * prefix as result.
-        * @param ApiResult $result
+        * @param ApiResult|null $result
         * @param bool $iwUrl
         * @return array Array of raw_prefixed_title (string) => interwiki_prefix (string)
         * @since 1.21
@@ -692,7 +692,7 @@ class ApiPageSet extends ApiBase {
 
        /**
         * Revision IDs that were not found in the database as result array.
-        * @param ApiResult $result
+        * @param ApiResult|null $result
         * @return array Array of revision IDs
         * @since 1.21
         */
index be12977..ee13f3d 100644 (file)
@@ -35,7 +35,7 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         * @return void
         */
        protected function run( ApiPageSet $resultPageSet = null ) {
index 3af2459..a0e71a5 100644 (file)
@@ -33,7 +33,7 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         * @return void
         */
        protected function run( ApiPageSet $resultPageSet = null ) {
index b338ed6..bfacc51 100644 (file)
@@ -88,7 +88,7 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         */
        private function run( ApiPageSet $resultPageSet = null ) {
                $settings = self::$settings[$this->getModuleName()];
index 3ad45bb..b9ed9f2 100644 (file)
@@ -320,7 +320,7 @@ abstract class ApiQueryBase extends ApiBase {
         * Add an option such as LIMIT or USE INDEX. If an option was set
         * before, the old value will be overwritten
         * @param string $name Option name
-        * @param string|string[] $value Option value
+        * @param string|string[]|null $value Option value
         */
        protected function addOption( $name, $value = null ) {
                if ( is_null( $value ) ) {
@@ -402,8 +402,8 @@ abstract class ApiQueryBase extends ApiBase {
        }
 
        /**
-        * @param string $query
-        * @param string $protocol
+        * @param string|null $query
+        * @param string|null $protocol
         * @return null|string
         */
        public function prepareUrlQuerySearchString( $query = null, $protocol = null ) {
@@ -503,7 +503,7 @@ abstract class ApiQueryBase extends ApiBase {
         * Same as addPageSubItems(), but one element of $data at a time
         * @param int $pageId Page ID
         * @param array $item Data array à la ApiResult
-        * @param string $elemname XML element name. If null, getModuleName()
+        * @param string|null $elemname XML element name. If null, getModuleName()
         *  is used
         * @return bool Whether the element fit in the result
         */
index 90aed6e..7193eeb 100644 (file)
@@ -42,7 +42,7 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         * @return void
         */
        public function run( $resultPageSet = null ) {
index e447f4f..177b248 100644 (file)
@@ -359,7 +359,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
         * @param File $file
         * @param array $prop Array of properties to get (in the keys)
         * @param ApiResult $result
-        * @param array $thumbParams Containing 'width' and 'height' items, or null
+        * @param array|null $thumbParams Containing 'width' and 'height' items, or null
         * @param array|bool|string $opts Options for data fetching.
         *   This is an array consisting of the keys:
         *    'version': The metadata version for the metadata option
index 9b99312..7145d4d 100644 (file)
@@ -42,7 +42,7 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         * @return void
         */
        public function run( $resultPageSet = null ) {
index a828e11..8758d9c 100644 (file)
@@ -49,7 +49,7 @@ class ApiQueryQueryPage extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         */
        public function run( $resultPageSet = null ) {
                $params = $this->extractRequestParams();
index f3af226..f870d45 100644 (file)
@@ -136,7 +136,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        /**
         * Generates and outputs the result of this query based upon the provided parameters.
         *
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         */
        public function run( $resultPageSet = null ) {
                $user = $this->getUser();
index f888434..87c6f9d 100644 (file)
@@ -44,7 +44,7 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param ApiPageSet $resultPageSet
+        * @param ApiPageSet|null $resultPageSet
         * @return void
         */
        abstract protected function run( ApiPageSet $resultPageSet = null );
index df71830..3b7c181 100644 (file)
@@ -723,7 +723,7 @@ class ApiResult implements ApiSerializable {
         * @since 1.25
         * @param array &$arr
         * @param string $type See ApiResult::META_TYPE
-        * @param string $kvpKeyName See ApiResult::META_KVP_KEY_NAME
+        * @param string|null $kvpKeyName See ApiResult::META_KVP_KEY_NAME
         */
        public static function setArrayType( array &$arr, $type, $kvpKeyName = null ) {
                if ( !in_array( $type, [
@@ -742,7 +742,7 @@ class ApiResult implements ApiSerializable {
         * @since 1.25
         * @param array|string|null $path See ApiResult::addValue()
         * @param string $tag See ApiResult::META_TYPE
-        * @param string $kvpKeyName See ApiResult::META_KVP_KEY_NAME
+        * @param string|null $kvpKeyName See ApiResult::META_KVP_KEY_NAME
         */
        public function addArrayType( $path, $tag, $kvpKeyName = null ) {
                $arr = &$this->path( $path );
@@ -754,7 +754,7 @@ class ApiResult implements ApiSerializable {
         * @since 1.25
         * @param array &$arr
         * @param string $type See ApiResult::META_TYPE
-        * @param string $kvpKeyName See ApiResult::META_KVP_KEY_NAME
+        * @param string|null $kvpKeyName See ApiResult::META_KVP_KEY_NAME
         */
        public static function setArrayTypeRecursive( array &$arr, $type, $kvpKeyName = null ) {
                self::setArrayType( $arr, $type, $kvpKeyName );
@@ -770,7 +770,7 @@ class ApiResult implements ApiSerializable {
         * @since 1.25
         * @param array|string|null $path See ApiResult::addValue()
         * @param string $tag See ApiResult::META_TYPE
-        * @param string $kvpKeyName See ApiResult::META_KVP_KEY_NAME
+        * @param string|null $kvpKeyName See ApiResult::META_KVP_KEY_NAME
         */
        public function addArrayTypeRecursive( $path, $tag, $kvpKeyName = null ) {
                $arr = &$this->path( $path );
@@ -1050,7 +1050,7 @@ class ApiResult implements ApiSerializable {
         *
         * @since 1.25
         * @param array|object $data
-        * @param array &$metadata Store metadata here, if provided
+        * @param array|null &$metadata Store metadata here, if provided
         * @return array|object
         */
        public static function stripMetadataNonRecursive( $data, &$metadata = null ) {
index 3cec5d4..47ab23f 100644 (file)
        "apihelp-options-summary": "Смени ги нагодувањата на тековниот корисник.",
        "apihelp-options-extended-description": "Можат да се зададат само можностите заведени во јадрото или во едно од воспоставените додатоци, или пак можности со клуч кој ја има претставката <code>userjs-</code> (предвиден за употреба од кориснички скрипти).",
        "apihelp-options-param-reset": "Ги враќа поставките по основно.",
-       "apihelp-options-param-resetkinds": "Ð\9fисок на типови можности за повраток кога е зададена можноста <var>$1reset</var>.",
+       "apihelp-options-param-resetkinds": "Сисок на типови можности за повраток кога е зададена можноста <var>$1reset</var>.",
        "apihelp-options-param-change": "Список на промени во форматот name=value (на пр. skin=vector). Вредностите не треба да содржат исправени црти. Ако не зададете вредност (дури ни знак за равенство), на пр., можност|другаможност|..., ќе биде зададена вредноста на можноста по основно.",
        "apihelp-options-param-optionname": "Назив на можноста што треба да ѝ се зададе на вредноста дадена од <var>$1optionvalue</var>.",
        "apihelp-options-param-optionvalue": "Вредноста на можноста укажана од <var>$1optionname</var>. Може да содржи исправени црти.",
index f5bfc2a..3d26767 100644 (file)
@@ -113,7 +113,7 @@ abstract class AbstractPasswordPrimaryAuthenticationProvider
         *
         * @param string $username
         * @param Status $status From $this->checkPasswordValidity()
-        * @param mixed $data Passed through to $this->getPasswordResetData()
+        * @param mixed|null $data Passed through to $this->getPasswordResetData()
         */
        protected function setPasswordResetFlag( $username, Status $status, $data = null ) {
                $reset = $this->getPasswordResetData( $username, $data );
index 3260ce4..ca59ec7 100644 (file)
@@ -2249,7 +2249,7 @@ class AuthManager implements LoggerAwareInterface {
         * Fetch authentication data from the current session
         * @protected For use by AuthenticationProviders
         * @param string $key
-        * @param mixed $default
+        * @param mixed|null $default
         * @return mixed
         */
        public function getAuthenticationSessionData( $key, $default = null ) {
index 956c985..8cb33aa 100644 (file)
@@ -199,7 +199,7 @@ class AuthenticationResponse {
        /**
         * @param AuthenticationRequest[] $reqs AuthenticationRequests needed to continue
         * @param string $redirectTarget URL
-        * @param mixed $redirectApiData Data suitable for adding to an ApiResult
+        * @param mixed|null $redirectApiData Data suitable for adding to an ApiResult
         * @return AuthenticationResponse
         * @see AuthenticationResponse::REDIRECT
         */
index 717b592..e6d9bd8 100644 (file)
@@ -52,7 +52,7 @@ class Throttler implements LoggerAwareInterface {
        protected $warningLimit;
 
        /**
-        * @param array $conditions An array of arrays describing throttling conditions.
+        * @param array|null $conditions An array of arrays describing throttling conditions.
         *     Defaults to $wgPasswordAttemptThrottle. See documentation of that variable for format.
         * @param array $params Parameters (all optional):
         *   - type: throttle type, used as a namespace for counters,
index 7cbb86f..58ed771 100644 (file)
@@ -75,7 +75,7 @@ class LinkCache {
         * in order to avoid link table inconsistency), which was later removed
         * for performance on wikis with a high edit rate.
         *
-        * @param bool $update
+        * @param bool|null $update
         * @return bool
         */
        public function forUpdate( $update = null ) {
@@ -125,7 +125,7 @@ class LinkCache {
         * @param int $id Page's ID
         * @param LinkTarget $target
         * @param int $len Text's length
-        * @param int $redir Whether the page is a redirect
+        * @param int|null $redir Whether the page is a redirect
         * @param int $revision Latest revision's ID
         * @param string|null $model Latest revision's content model ID
         * @param string|null $lang Language code of the page, if not the content language
index b262eab..65e659d 100644 (file)
@@ -50,8 +50,8 @@ class MessageBlobStore implements LoggerAwareInterface {
        protected $wanCache;
 
        /**
-        * @param ResourceLoader $rl
-        * @param LoggerInterface $logger
+        * @param ResourceLoader|null $rl
+        * @param LoggerInterface|null $logger
         */
        public function __construct( ResourceLoader $rl = null, LoggerInterface $logger = null ) {
                $this->resourceloader = $rl;
index 93959db..78fb24a 100644 (file)
@@ -239,7 +239,7 @@ class MessageCache {
         * is disabled.
         *
         * @param string $code Language to which load messages
-        * @param int $mode Use MessageCache::FOR_UPDATE to skip process cache [optional]
+        * @param int|null $mode Use MessageCache::FOR_UPDATE to skip process cache [optional]
         * @throws InvalidArgumentException
         * @return bool
         */
@@ -383,7 +383,7 @@ class MessageCache {
        /**
         * @param string $code
         * @param array &$where List of wfDebug() comments
-        * @param int $mode Use MessageCache::FOR_UPDATE to use DB_MASTER
+        * @param int|null $mode Use MessageCache::FOR_UPDATE to use DB_MASTER
         * @return bool|string True on success or one of ("cantacquire", "disabled")
         */
        protected function loadFromDBWithLock( $code, array &$where, $mode = null ) {
@@ -445,7 +445,7 @@ class MessageCache {
         * on-demand from the database later.
         *
         * @param string $code Language code
-        * @param int $mode Use MessageCache::FOR_UPDATE to skip process cache
+        * @param int|null $mode Use MessageCache::FOR_UPDATE to skip process cache
         * @return array Loaded messages for storing in caches
         */
        protected function loadFromDB( $code, $mode = null ) {
@@ -1063,8 +1063,8 @@ class MessageCache {
        /**
         * @param string $message
         * @param bool $interface
-        * @param Language $language
-        * @param Title $title
+        * @param Language|null $language
+        * @param Title|null $title
         * @return string
         */
        public function transform( $message, $interface = false, $language = null, $title = null ) {
@@ -1117,10 +1117,10 @@ class MessageCache {
 
        /**
         * @param string $text
-        * @param Title $title
+        * @param Title|null $title
         * @param bool $linestart Whether or not this is at the start of a line
         * @param bool $interface Whether this is an interface message
-        * @param Language|string $language Language code
+        * @param Language|string|null $language Language code
         * @return ParserOutput|string
         */
        public function parse( $text, $title = null, $linestart = true,
index a49fb4c..e745203 100644 (file)
@@ -59,7 +59,7 @@ class CategoryMembershipChange {
 
        /**
         * @param Title $pageTitle Title instance of the categorized page
-        * @param Revision $revision Latest Revision instance of the categorized page
+        * @param Revision|null $revision Latest Revision instance of the categorized page
         *
         * @throws MWException
         */
@@ -142,7 +142,7 @@ class CategoryMembershipChange {
        /**
         * @param string $timestamp Timestamp of the recent change to occur in TS_MW format
         * @param Title $categoryTitle Title of the category a page is being added to or removed from
-        * @param User $user User object of the user that made the change
+        * @param User|null $user User object of the user that made the change
         * @param string $comment Change summary
         * @param Title $pageTitle Title of the page that is being added or removed
         * @param string $lastTimestamp Parent revision timestamp of this change in TS_MW format
index 57c4026..facf29e 100644 (file)
@@ -107,7 +107,7 @@ class ChangesList extends ContextSource {
         *
         * @param RecentChange &$rc Passed by reference
         * @param bool $watched (default false)
-        * @param int $linenumber (default null)
+        * @param int|null $linenumber (default null)
         *
         * @return string|bool
         */
@@ -249,7 +249,7 @@ class ChangesList extends ContextSource {
         * bot edit, or unpatrolled edit. In English it typically contains "N", "m", "b", or "!".
         *
         * @param string $flag One key of $wgRecentChangesFlags
-        * @param IContextSource $context
+        * @param IContextSource|null $context
         * @return string HTML
         */
        public static function flag( $flag, IContextSource $context = null ) {
@@ -310,7 +310,7 @@ class ChangesList extends ContextSource {
         *
         * @param int $old Number of bytes
         * @param int $new Number of bytes
-        * @param IContextSource $context
+        * @param IContextSource|null $context
         * @return string
         */
        public static function showCharacterDifference( $old, $new, IContextSource $context = null ) {
@@ -363,7 +363,7 @@ class ChangesList extends ContextSource {
         * Format the character difference of one or several changes.
         *
         * @param RecentChange $old
-        * @param RecentChange $new Last change to use, if not provided, $old will be used
+        * @param RecentChange|null $new Last change to use, if not provided, $old will be used
         * @return string HTML fragment
         */
        public function formatCharacterDifference( RecentChange $old, RecentChange $new = null ) {
@@ -628,7 +628,7 @@ class ChangesList extends ContextSource {
         * field of this revision, if it's marked as deleted.
         * @param RCCacheEntry|RecentChange $rc
         * @param int $field
-        * @param User $user User object to check, or null to use $wgUser
+        * @param User|null $user User object to check, or null to use $wgUser
         * @return bool
         */
        public static function userCan( $rc, $field, User $user = null ) {
index ada02ce..a593d27 100644 (file)
@@ -93,7 +93,7 @@ class EnhancedChangesList extends ChangesList {
         *
         * @param RecentChange &$rc
         * @param bool $watched
-        * @param int $linenumber (default null)
+        * @param int|null $linenumber (default null)
         *
         * @return string
         */
index 51ee481..7ba12fb 100644 (file)
@@ -27,7 +27,7 @@ class OldChangesList extends ChangesList {
         *
         * @param RecentChange &$rc Passed by reference
         * @param bool $watched (default false)
-        * @param int $linenumber (default null)
+        * @param int|null $linenumber (default null)
         *
         * @return string|bool
         */
index 904090f..819f170 100644 (file)
@@ -490,7 +490,7 @@ class RecentChange {
 
        /**
         * Notify all the feeds about the change.
-        * @param array $feeds Optional feeds to send to, defaults to $wgRCFeeds
+        * @param array|null $feeds Optional feeds to send to, defaults to $wgRCFeeds
         */
        public function notifyRCFeeds( array $feeds = null ) {
                global $wgRCFeeds;
@@ -556,7 +556,7 @@ class RecentChange {
         *
         * @param RecentChange|int $change RecentChange or corresponding rc_id
         * @param bool $auto For automatic patrol
-        * @param string|string[] $tags Change tags to add to the patrol log entry
+        * @param string|string[]|null $tags Change tags to add to the patrol log entry
         *   ($user should be able to add the specified tags before this is called)
         * @return array See doMarkPatrolled(), or null if $change is not an existing rc_id
         */
@@ -581,7 +581,7 @@ class RecentChange {
         * 'markedaspatrollederror-noautopatrol' as errors
         * @param User $user User object doing the action
         * @param bool $auto For automatic patrol
-        * @param string|string[] $tags Change tags to add to the patrol log entry
+        * @param string|string[]|null $tags Change tags to add to the patrol log entry
         *   ($user should be able to add the specified tags before this is called)
         * @return array Array of permissions errors, see Title::getUserPermissionsErrors()
         */
@@ -932,7 +932,7 @@ class RecentChange {
         *
         * @param string $timestamp Timestamp of the recent change to occur
         * @param Title $categoryTitle Title of the category a page is being added to or removed from
-        * @param User $user User object of the user that made the change
+        * @param User|null $user User object of the user that made the change
         * @param string $comment Change summary
         * @param Title $pageTitle Title of the page that is being added or removed
         * @param int $oldRevId Parent revision ID of this change
@@ -941,7 +941,7 @@ class RecentChange {
         * @param bool $bot true, if the change was made by a bot
         * @param string $ip IP address of the user, if the change was made anonymously
         * @param int $deleted Indicates whether the change has been deleted
-        * @param bool $added true, if the category was added, false for removed
+        * @param bool|null $added true, if the category was added, false for removed
         *
         * @return RecentChange
         */
index 97f124b..7874640 100644 (file)
@@ -213,7 +213,7 @@ class ChangeTags {
         * @param int|null $rc_id The rc_id of the change to add the tags to
         * @param int|null $rev_id The rev_id of the change to add the tags to
         * @param int|null $log_id The log_id of the change to add the tags to
-        * @param string $params Params to put in the ct_params field of table 'change_tag'
+        * @param string|null $params Params to put in the ct_params field of table 'change_tag'
         * @param RecentChange|null $rc Recent change, in case the tagging accompanies the action
         * (this should normally be the case)
         *
@@ -244,7 +244,7 @@ class ChangeTags {
         * Pass a variable whose value is null if the rev_id is not relevant or unknown.
         * @param int|null &$log_id The log_id of the change to add the tags to.
         * Pass a variable whose value is null if the log_id is not relevant or unknown.
-        * @param string $params Params to put in the ct_params field of table
+        * @param string|null $params Params to put in the ct_params field of table
         * 'change_tag' when adding tags
         * @param RecentChange|null $rc Recent change being tagged, in case the tagging accompanies
         * the action
@@ -941,7 +941,7 @@ class ChangeTags {
         * @param string $tag
         * @param string $reason
         * @param User $user Who to attribute the action to
-        * @param int $tagCount For deletion only, how many usages the tag had before
+        * @param int|null $tagCount For deletion only, how many usages the tag had before
         * it was deleted.
         * @param array $logEntryTags Change tags to apply to the entry
         * that will be created in the tag management log
index b21eadc..284cab2 100644 (file)
@@ -43,7 +43,7 @@ abstract class AbstractContent implements Content {
        protected $model_id;
 
        /**
-        * @param string $modelId
+        * @param string|null $modelId
         *
         * @since 1.21
         */
@@ -145,7 +145,7 @@ abstract class AbstractContent implements Content {
        /**
         * @since 1.21
         *
-        * @param string $format
+        * @param string|null $format
         *
         * @return string
         *
@@ -182,7 +182,7 @@ abstract class AbstractContent implements Content {
        /**
         * @since 1.21
         *
-        * @param Content $that
+        * @param Content|null $that
         *
         * @return bool
         *
@@ -219,9 +219,9 @@ abstract class AbstractContent implements Content {
         * @since 1.21
         *
         * @param Title $title
-        * @param Content $old
+        * @param Content|null $old
         * @param bool $recursive
-        * @param ParserOutput $parserOutput
+        * @param ParserOutput|null $parserOutput
         *
         * @return DataUpdate[]
         *
index dfd46c8..e350fb3 100644 (file)
@@ -32,7 +32,7 @@ abstract class CodeContentHandler extends TextContentHandler {
         * Returns the English language, because code is English, and should be handled as such.
         *
         * @param Title $title
-        * @param Content $content
+        * @param Content|null $content
         *
         * @return Language
         *
@@ -46,7 +46,7 @@ abstract class CodeContentHandler extends TextContentHandler {
         * Returns the English language, because code is English, and should be handled as such.
         *
         * @param Title $title
-        * @param Content $content
+        * @param Content|null $content
         *
         * @return Language
         *
index 3e58782..000bff2 100644 (file)
@@ -162,7 +162,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param string $format The desired serialization format, or null for the default format.
+        * @param string|null $format The desired serialization format, or null for the default format.
         *
         * @return string Serialized form of this Content object.
         */
@@ -210,7 +210,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param Content $that The Content object to compare to.
+        * @param Content|null $that The Content object to compare to.
         *
         * @return bool True if this Content object is equal to $that, false otherwise.
         */
@@ -262,8 +262,8 @@ interface Content {
         *       may call ParserOutput::recordOption() on the output object.
         *
         * @param Title $title The page title to use as a context for rendering.
-        * @param int $revId Optional revision ID being rendered.
-        * @param ParserOptions $options Any parser options.
+        * @param int|null $revId Optional revision ID being rendered.
+        * @param ParserOptions|null $options Any parser options.
         * @param bool $generateHtml Whether to generate HTML (default: true). If false,
         *        the result of calling getText() on the ParserOutput object returned by
         *        this method is undefined.
@@ -296,12 +296,12 @@ interface Content {
         *   AbstractContent does.
         *
         * @param Title $title The context for determining the necessary updates
-        * @param Content $old An optional Content object representing the
+        * @param Content|null $old An optional Content object representing the
         *    previous content, i.e. the content being replaced by this Content
         *    object.
         * @param bool $recursive Whether to include recursive updates (default:
         *    false).
-        * @param ParserOutput $parserOutput Optional ParserOutput object.
+        * @param ParserOutput|null $parserOutput Optional ParserOutput object.
         *    Provide if you have one handy, to avoid re-parsing of the content.
         *
         * @return DataUpdate[] A list of DataUpdate objects for putting information
index 3b54494..3c5ee26 100644 (file)
@@ -70,7 +70,7 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param Content $content
+        * @param Content|null $content
         *
         * @throws MWException If the content is not an instance of TextContent and
         * wgContentHandlerTextFallback was set to 'fail'.
@@ -115,11 +115,11 @@ abstract class ContentHandler {
         *
         * @param string $text The textual representation, will be
         *    unserialized to create the Content object
-        * @param Title $title The title of the page this text belongs to.
+        * @param Title|null $title The title of the page this text belongs to.
         *    Required if $modelId is not provided.
-        * @param string $modelId The model to deserialize to. If not provided,
+        * @param string|null $modelId The model to deserialize to. If not provided,
         *    $title->getContentModel() is used.
-        * @param string $format The format to use for deserialization. If not
+        * @param string|null $format The format to use for deserialization. If not
         *    given, the model's default format is used.
         *
         * @throws MWException If model ID or format is not supported or if the text can not be
@@ -420,7 +420,7 @@ abstract class ContentHandler {
         * @since 1.21
         *
         * @param Content $content The Content object to serialize
-        * @param string $format The desired serialization format
+        * @param string|null $format The desired serialization format
         *
         * @return string Serialized form of the content
         */
@@ -446,7 +446,7 @@ abstract class ContentHandler {
         * @since 1.21
         *
         * @param string $blob Serialized form of the content
-        * @param string $format The format used for serialization
+        * @param string|null $format The format used for serialization
         *
         * @return Content The Content object created by deserializing $blob
         */
@@ -654,7 +654,7 @@ abstract class ContentHandler {
         * @since 1.21
         *
         * @param Title $title The page to determine the language for.
-        * @param Content $content The page's content, if you have it handy, to avoid reloading it.
+        * @param Content|null $content The page's content, if you have it handy, to avoid reloading it.
         *
         * @return Language The page's language
         */
@@ -689,7 +689,7 @@ abstract class ContentHandler {
         * @since 1.21
         *
         * @param Title $title The page to determine the language for.
-        * @param Content $content The page's content, if you have it handy, to avoid reloading it.
+        * @param Content|null $content The page's content, if you have it handy, to avoid reloading it.
         *
         * @return Language The page's language for viewing
         */
@@ -1310,7 +1310,7 @@ abstract class ContentHandler {
         * Specific content handlers may override it if they need different content handling.
         *
         * @param WikiPage $page
-        * @param ParserCache $cache
+        * @param ParserCache|null $cache
         * @return ParserOutput
         */
        public function getParserOutputForIndexing( WikiPage $page, ParserCache $cache = null ) {
index 4b58989..b21c6f4 100644 (file)
@@ -42,7 +42,7 @@ class MessageContent extends AbstractContent {
 
        /**
         * @param Message|string $msg A Message object, or a message key.
-        * @param string[] $params An optional array of message parameters.
+        * @param string[]|null $params An optional array of message parameters.
         */
        public function __construct( $msg, $params = null ) {
                # XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
@@ -148,8 +148,8 @@ class MessageContent extends AbstractContent {
 
        /**
         * @param Title $title Unused.
-        * @param int $revId Unused.
-        * @param ParserOptions $options Unused.
+        * @param int|null $revId Unused.
+        * @param ParserOptions|null $options Unused.
         * @param bool $generateHtml Whether to generate HTML (default: true).
         *
         * @return ParserOutput
index 71f65b3..2494177 100644 (file)
@@ -194,7 +194,7 @@ class TextContent extends AbstractContent {
         * @since 1.21
         *
         * @param Content $that The other content object to compare this content object to.
-        * @param Language $lang The language object to use for text segmentation.
+        * @param Language|null $lang The language object to use for text segmentation.
         *    If not given, $wgContentLang is used.
         *
         * @return Diff A diff representing the changes that would have to be
index 4a7944c..0978ffc 100644 (file)
@@ -38,7 +38,7 @@ class TextContentHandler extends ContentHandler {
         * Returns the content's text as-is.
         *
         * @param Content $content
-        * @param string $format The serialization format to check
+        * @param string|null $format The serialization format to check
         *
         * @return mixed
         */
@@ -108,7 +108,7 @@ class TextContentHandler extends ContentHandler {
         * @since 1.21
         *
         * @param string $text Serialized form of the content
-        * @param string $format The format used for serialization
+        * @param string|null $format The format used for serialization
         *
         * @return Content The TextContent object wrapping $text
         */
index 64c33df..20b08ed 100644 (file)
@@ -46,7 +46,7 @@ class CloneDatabase {
         * @param IMaintainableDatabase $db A database subclass
         * @param array $tablesToClone An array of tables to clone, unprefixed
         * @param string $newTablePrefix Prefix to assign to the tables
-        * @param string $oldTablePrefix Prefix on current tables, if not $wgDBprefix
+        * @param string|null $oldTablePrefix Prefix on current tables, if not $wgDBprefix
         * @param bool $dropCurrentTables
         */
        public function __construct( IMaintainableDatabase $db, array $tablesToClone,
index 013724c..d2787fa 100644 (file)
@@ -45,7 +45,7 @@ trait PatchFileLocation {
         *
         * @param IDatabase $db
         * @param string $name The script name (relative to $patchDir, without the '.sql' suffix)
-        * @param string $patchDir The directory to find the script in. Use __DIR__ to search in the
+        * @param string|null $patchDir The directory to find the script in. Use __DIR__ to search in the
         *        directory the calling code is located in. If omitted, the "maintenance"
         *        directory will be used, where the scripts used by the updater are located.
         *
index 62d45d4..8537d71 100644 (file)
@@ -42,8 +42,8 @@ use MWExceptionHandler;
 class LineFormatter extends MonologLineFormatter {
 
        /**
-        * @param string $format The format of the message
-        * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
+        * @param string|null $format The format of the message
+        * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
         * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
         * @param bool $ignoreEmptyContextAndExtra
         * @param bool $includeStacktraces
index 2766bcb..0d1de1a 100644 (file)
@@ -113,7 +113,7 @@ class SearchUpdate implements DeferrableUpdate {
         * If you're using a real search engine, you'll probably want to override
         * this behavior and do something nicer with the original wikitext.
         * @param string $text
-        * @param SearchEngine $se Search engine
+        * @param SearchEngine|null $se Search engine
         * @return string
         */
        public function updateText( $text, SearchEngine $se = null ) {
index d76af31..063f826 100644 (file)
@@ -66,7 +66,7 @@ abstract class DiffOp {
        }
 
        /**
-        * @param int $i
+        * @param int|null $i
         * @return string[]|string|null
         */
        public function getClosing( $i = null ) {
index a77dab8..1d9ad05 100644 (file)
@@ -102,7 +102,7 @@ class DifferenceEngine extends ContextSource {
        /**#@-*/
 
        /**
-        * @param IContextSource $context Context to use, anything else will be ignored
+        * @param IContextSource|null $context Context to use, anything else will be ignored
         * @param int $old Old ID we want to show and diff with.
         * @param string|int $new Either revision ID or 'prev' or 'next'. Default: 0.
         * @param int $rcid Deprecated, no longer used!
index f5f8c84..c0182d5 100644 (file)
@@ -46,7 +46,8 @@ class LocalizedException extends Exception implements ILocalizedException {
        /**
         * @param string|array|MessageSpecifier $messageSpec See Message::newFromSpecifier
         * @param int $code
-        * @param Exception|Throwable $previous The previous exception used for the exception chaining.
+        * @param Exception|Throwable|null $previous The previous exception used for the exception
+        *  chaining.
         */
        public function __construct( $messageSpec, $code = 0, $previous = null ) {
                $this->messageSpec = $messageSpec;
index 9039cfc..00dca9d 100644 (file)
@@ -161,8 +161,8 @@ class MWExceptionHandler {
         *
         * @param int $level Error level raised
         * @param string $message
-        * @param string $file
-        * @param int $line
+        * @param string|null $file
+        * @param int|null $line
         * @return bool
         *
         * @see logError()
@@ -231,12 +231,12 @@ class MWExceptionHandler {
         *
         * @since 1.25
         *
-        * @param int $level Error level raised
-        * @param string $message Error message
-        * @param string $file File that error was raised in
-        * @param int $line Line number error was raised at
-        * @param array $context Active symbol table point of error
-        * @param array $trace Backtrace at point of error (undocumented HHVM
+        * @param int|null $level Error level raised
+        * @param string|null $message Error message
+        * @param string|null $file File that error was raised in
+        * @param int|null $line Line number error was raised at
+        * @param array|null $context Active symbol table point of error
+        * @param array|null $trace Backtrace at point of error (undocumented HHVM
         *     feature)
         * @return bool Always returns false
         */
index ce899ed..26010da 100644 (file)
@@ -34,7 +34,7 @@ class DumpPipeOutput extends DumpFileOutput {
 
        /**
         * @param string $command
-        * @param string $file
+        * @param string|null $file
         */
        function __construct( $command, $file = null ) {
                if ( !is_null( $file ) ) {
index 45a6baf..422e1fb 100644 (file)
@@ -194,6 +194,10 @@ class ExternalStoreDB extends ExternalStoreMedium {
                static $externalBlobCache = [];
 
                $cacheID = ( $itemID === false ) ? "$cluster/$id" : "$cluster/$id/";
+
+               $wiki = $this->params['wiki'] ?? false;
+               $cacheID = ( $wiki === false ) ? $cacheID : "$cacheID@$wiki";
+
                if ( isset( $externalBlobCache[$cacheID] ) ) {
                        wfDebugLog( 'ExternalStoreDB-cache',
                                "ExternalStoreDB::fetchBlob cache hit on $cacheID" );
index b5c44f2..9759b79 100644 (file)
@@ -41,7 +41,7 @@ class OldLocalFile extends LocalFile {
        /**
         * @param Title $title
         * @param FileRepo $repo
-        * @param string|int $time
+        * @param string|int|null $time
         * @return self
         * @throws MWException
         */
index b5fb87f..cec3bfb 100644 (file)
@@ -301,7 +301,7 @@ class HTMLForm extends ContextSource {
         * Build a new HTMLForm from an array of field attributes
         *
         * @param array $descriptor Array of Field constructs, as described above
-        * @param IContextSource $context Available since 1.18, will become compulsory in 1.18.
+        * @param IContextSource|null $context Available since 1.18, will become compulsory in 1.18.
         *     Obviates the need to call $form->setTitle()
         * @param string $messagePrefix A prefix to go in front of default messages
         */
index 70691b4..71e08a8 100644 (file)
@@ -87,7 +87,7 @@ abstract class MWHttpRequest implements LoggerAwareInterface {
         * @param string $url Url to use. If protocol-relative, will be expanded to an http:// URL
         * @param array $options (optional) extra params to pass (see Http::request())
         * @param string $caller The method making this request, for profiling
-        * @param Profiler $profiler An instance of the profiler for profiling, or null
+        * @param Profiler|null $profiler An instance of the profiler for profiling, or null
         */
        public function __construct(
                $url, array $options = [], $caller = __METHOD__, $profiler = null
index 845408a..4f531da 100644 (file)
@@ -47,7 +47,7 @@ class CliInstaller extends Installer {
 
        /**
         * @param string $siteName
-        * @param string $admin
+        * @param string|null $admin
         * @param array $option
         */
        function __construct( $siteName, $admin = null, array $option = [] ) {
index 1cd76b9..939301d 100644 (file)
@@ -109,7 +109,7 @@ abstract class DatabaseUpdater {
        /**
         * @param Database &$db To perform updates on
         * @param bool $shared Whether to perform updates on shared tables
-        * @param Maintenance $maintenance Maintenance object which created us
+        * @param Maintenance|null $maintenance Maintenance object which created us
         */
        protected function __construct( Database &$db, $shared, Maintenance $maintenance = null ) {
                $this->db = $db;
@@ -516,7 +516,7 @@ abstract class DatabaseUpdater {
         * Obviously, only use this for updates that occur after the updatelog table was
         * created!
         * @param string $key Name of key to insert
-        * @param string $val [optional] Value to insert along with the key
+        * @param string|null $val [optional] Value to insert along with the key
         */
        public function insertUpdateRow( $key, $val = null ) {
                $this->db->clearFlag( DBO_DDLMODE );
@@ -659,7 +659,7 @@ abstract class DatabaseUpdater {
         *
         * @param string $path Path to the patch file
         * @param bool $isFullPath Whether to treat $path as a relative or not
-        * @param string $msg Description of the patch
+        * @param string|null $msg Description of the patch
         * @return bool False if patch is skipped.
         */
        protected function applyPatch( $path, $isFullPath = false, $msg = null ) {
index 0890bc4..3905ba0 100644 (file)
@@ -531,7 +531,7 @@ abstract class Installer {
         * Installer variables are typically prefixed by an underscore.
         *
         * @param string $name
-        * @param mixed $default
+        * @param mixed|null $default
         *
         * @return mixed
         */
index 4142e6f..2ba221f 100644 (file)
@@ -472,7 +472,7 @@ class WebInstaller extends Installer {
         * Get a session variable.
         *
         * @param string $name
-        * @param array $default
+        * @param array|null $default
         *
         * @return array
         */
@@ -758,7 +758,7 @@ class WebInstaller extends Installer {
         */
        public function label( $msg, $forId, $contents, $helpData = "" ) {
                if ( strval( $msg ) == '' ) {
-                       $labelText = '\u{00A0}';
+                       $labelText = "\u{00A0}";
                } else {
                        $labelText = wfMessage( $msg )->escaped();
                }
@@ -1047,7 +1047,7 @@ class WebInstaller extends Installer {
 
                        $items[$value] =
                                Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
-                               '\u{00A0}' .
+                               "\u{00A0}" .
                                Xml::tags( 'label', [ 'for' => $id ], $this->parse(
                                        isset( $params['itemLabels'] ) ?
                                                wfMessage( $params['itemLabels'][$value] )->plain() :
index 7f0d27d..382ed3b 100644 (file)
@@ -412,7 +412,7 @@ class WebInstallerOptions extends WebInstallerPage {
 
                return '<p>' .
                        Html::element( 'img', [ 'src' => $this->getVar( 'wgRightsIcon' ) ] ) .
-                       '\u{00A0}\u{00A0}' .
+                       "\u{00A0}\u{00A0}" .
                        htmlspecialchars( $this->getVar( 'wgRightsText' ) ) .
                        "</p>\n" .
                        "<p style=\"text-align: center;\">" .
index 3aad6f8..1c5fa0e 100644 (file)
@@ -145,7 +145,7 @@ abstract class WebInstallerPage {
 
        /**
         * @param string $var
-        * @param mixed $default
+        * @param mixed|null $default
         *
         * @return mixed
         */
index e6a943d..832883b 100644 (file)
@@ -111,7 +111,7 @@ class Interwiki {
        /**
         * Get the URL for a particular title (or with $1 if no title given)
         *
-        * @param string $title What text to put for the article name
+        * @param string|null $title What text to put for the article name
         * @return string The URL
         * @note Prior to 1.19 The getURL with an argument was broken.
         *       If you if you use this arg in an extension that supports MW earlier
index a85613a..7c5d0ae 100644 (file)
@@ -69,7 +69,7 @@ class JobRunner implements LoggerAwareInterface {
        }
 
        /**
-        * @param LoggerInterface $logger
+        * @param LoggerInterface|null $logger
         */
        public function __construct( LoggerInterface $logger = null ) {
                if ( $logger === null ) {
index af5646a..d060c1c 100644 (file)
@@ -117,7 +117,7 @@ class JobSpecification implements IJobSpecification {
         * @param string $type
         * @param array $params Map of key/values
         * @param array $opts Map of key/values; includes 'removeDuplicates'
-        * @param Title $title Optional descriptive title
+        * @param Title|null $title Optional descriptive title
         */
        public function __construct(
                $type, array $params, array $opts = [], Title $title = null
index a67b919..c0ab0a0 100644 (file)
@@ -86,7 +86,7 @@ class Cookie {
         * not a big problem in practice, but there are test cases)
         *
         * @param string $domain The domain to validate
-        * @param string $originDomain (optional) the domain the cookie originates from
+        * @param string|null $originDomain (optional) the domain the cookie originates from
         * @return bool
         */
        public static function validateCookieDomain( $domain, $originDomain = null ) {
index bca8c05..595dc1a 100644 (file)
@@ -247,7 +247,7 @@ class MapCacheLRU implements IExpiringStore, Serializable {
        /**
         * Clear one or several cache entries, or all cache entries
         *
-        * @param string|array $keys
+        * @param string|array|null $keys
         * @return void
         */
        public function clear( $keys = null ) {
index eb32d98..f0cd83e 100644 (file)
@@ -83,7 +83,7 @@ class ProcessCacheLRU {
        /**
         * Clear one or several cache entries, or all cache entries.
         *
-        * @param string|array $keys
+        * @param string|array|null $keys
         * @return void
         */
        public function clear( $keys = null ) {
index 3bdafe1..16cb1ed 100644 (file)
@@ -75,7 +75,7 @@ class StatusValue {
        /**
         * Factory function for good results
         *
-        * @param mixed $value
+        * @param mixed|null $value
         * @return static
         */
        public static function newGood( $value = null ) {
@@ -162,7 +162,7 @@ class StatusValue {
         * Change operation result
         *
         * @param bool $ok Whether the operation completed
-        * @param mixed $value
+        * @param mixed|null $value
         */
        public function setResult( $ok, $value = null ) {
                $this->ok = (bool)$ok;
index 04a13e2..65a9247 100644 (file)
@@ -83,7 +83,7 @@ class Timing implements LoggerAwareInterface {
        }
 
        /**
-        * @param string $markName The name of the mark that should
+        * @param string|null $markName The name of the mark that should
         *  be cleared. If not specified, all marks will be cleared.
         */
        public function clearMarks( $markName = null ) {
@@ -117,7 +117,7 @@ class Timing implements LoggerAwareInterface {
         *
         * @param string $measureName
         * @param string $startMark
-        * @param string $endMark
+        * @param string|null $endMark
         * @return array|bool The measure that has been created, or false if either
         *  the start mark or the end mark do not exist.
         */
index 785cb72..6d5efa2 100644 (file)
@@ -1267,7 +1267,7 @@ abstract class FileBackend implements LoggerAwareInterface {
         *
         * @see FileBackend::getFileStat()
         *
-        * @param array $paths Storage paths (optional)
+        * @param array|null $paths Storage paths (optional)
         */
        abstract public function clearCache( array $paths = null );
 
index 6c1dc53..118464c 100644 (file)
@@ -1299,7 +1299,7 @@ abstract class FileBackendStore extends FileBackend {
         *
         * @see FileBackend::clearCache()
         *
-        * @param array $paths Storage paths (optional)
+        * @param array|null $paths Storage paths (optional)
         */
        protected function doClearCache( array $paths = null ) {
        }
index 2f7bc1e..143f854 100644 (file)
@@ -1737,8 +1737,8 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @param array $creds From getAuthentication()
-        * @param string $container
-        * @param string $object
+        * @param string|null $container
+        * @param string|null $object
         * @return string
         */
        protected function storageUrl( array $creds, $container = null, $object = null ) {
index 9343fcc..47be4eb 100644 (file)
@@ -149,9 +149,9 @@ abstract class FileJournal {
         * Get an array of file change log entries.
         * A starting change ID and/or limit can be specified.
         *
-        * @param int $start Starting change ID or null
+        * @param int|null $start Starting change ID or null
         * @param int $limit Maximum number of items to return
-        * @param string &$next Updated to the ID of the next entry.
+        * @param string|null &$next Updated to the ID of the next entry.
         * @return array List of associative arrays, each having:
         *     id         : unique, monotonic, ID for this change
         *     batch_uuid : UUID for an operation batch
index 6261335..d877db0 100644 (file)
@@ -85,7 +85,7 @@ class ScopedLock {
         * This is useful for early release of locks before function scope is destroyed.
         * This is the same as setting the lock object to null.
         *
-        * @param ScopedLock &$lock
+        * @param ScopedLock|null &$lock
         * @since 1.21
         */
        public static function release( ScopedLock &$lock = null ) {
index 4a16679..77c377b 100644 (file)
@@ -1029,9 +1029,9 @@ EOT;
         * @todo analyse file if need be
         * @todo look at multiple extension, separately and together.
         *
-        * @param string $path Full path to the image file, in case we have to look at the contents
+        * @param string|null $path Full path to the image file, in case we have to look at the contents
         *        (if null, only the MIME type is used to determine the media type code).
-        * @param string $mime MIME type. If null it will be guessed using guessMimeType.
+        * @param string|null $mime MIME type. If null it will be guessed using guessMimeType.
         *
         * @return string A value to be used with the MEDIATYPE_xxx constants.
         */
index e231113..9cfaf67 100644 (file)
@@ -91,7 +91,7 @@ class XmlTypeCheck {
         *  result stored in $this->filterMatchType.
         *
         * @param string $input a filename or string containing the XML element
-        * @param callable $filterCallback (optional)
+        * @param callable|null $filterCallback (optional)
         *        Function to call to do additional custom validity checks from the
         *        SAX element handler event. This gives you access to the element
         *        namespace, name, attributes, and text contents.
@@ -114,7 +114,7 @@ class XmlTypeCheck {
         * Alternative constructor: from filename
         *
         * @param string $fname the filename of an XML document
-        * @param callable $filterCallback (optional)
+        * @param callable|null $filterCallback (optional)
         *        Function to call to do additional custom validity checks from the
         *        SAX element handler event. This gives you access to the element
         *        namespace, name, and attributes, but not to text contents.
@@ -129,7 +129,7 @@ class XmlTypeCheck {
         * Alternative constructor: from string
         *
         * @param string $string a string containing an XML element
-        * @param callable $filterCallback (optional)
+        * @param callable|null $filterCallback (optional)
         *        Function to call to do additional custom validity checks from the
         *        SAX element handler event. This gives you access to the element
         *        namespace, name, and attributes, but not to text contents.
index e58a0bb..0100fb2 100644 (file)
@@ -185,7 +185,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         *
         * @param string $key
         * @param int $flags Bitfield of BagOStuff::READ_* constants [optional]
-        * @param int $oldFlags [unused]
+        * @param int|null $oldFlags [unused]
         * @return mixed Returns false on failure and if the item does not exist
         */
        public function get( $key, $flags = 0, $oldFlags = null ) {
@@ -774,7 +774,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         *
         * @since 1.27
         * @param string $class Key class
-        * @param string $component [optional] Key component (starting with a key collection name)
+        * @param string|null $component [optional] Key component (starting with a key collection name)
         * @return string Colon-delimited list of $keyspace followed by escaped components of $args
         */
        public function makeGlobalKey( $class, $component = null ) {
@@ -786,7 +786,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         *
         * @since 1.27
         * @param string $class Key class
-        * @param string $component [optional] Key component (starting with a key collection name)
+        * @param string|null $component [optional] Key component (starting with a key collection name)
         * @return string Colon-delimited list of $keyspace followed by escaped components of $args
         */
        public function makeKey( $class, $component = null ) {
index 0913322..e30e061 100644 (file)
@@ -291,9 +291,9 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         * That method has cache slam avoiding features for hot/expensive keys.
         *
         * @param string $key Cache key made from makeKey() or makeGlobalKey()
-        * @param mixed &$curTTL Approximate TTL left on the key if present/tombstoned [returned]
+        * @param mixed|null &$curTTL Approximate TTL left on the key if present/tombstoned [returned]
         * @param array $checkKeys List of "check" keys
-        * @param float &$asOf UNIX timestamp of cached value; null on failure [returned]
+        * @param float|null &$asOf UNIX timestamp of cached value; null on failure [returned]
         * @return mixed Value of cache key or false on failure
         */
        final public function get( $key, &$curTTL = null, array $checkKeys = [], &$asOf = null ) {
@@ -1133,7 +1133,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         * @param int $ttl
         * @param callback $callback
         * @param array $opts Options map for getWithSetCallback()
-        * @param float &$asOf Cache generation timestamp of returned value [returned]
+        * @param float|null &$asOf Cache generation timestamp of returned value [returned]
         * @return mixed
         * @note Callable type hints are not used to avoid class-autoloading
         */
@@ -1600,7 +1600,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
        /**
         * @see BagOStuff::makeKey()
         * @param string $class Key class
-        * @param string $component [optional] Key component (starting with a key collection name)
+        * @param string|null $component [optional] Key component (starting with a key collection name)
         * @return string Colon-delimited list of $keyspace followed by escaped components of $args
         * @since 1.27
         */
@@ -1611,7 +1611,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
        /**
         * @see BagOStuff::makeGlobalKey()
         * @param string $class Key class
-        * @param string $component [optional] Key component (starting with a key collection name)
+        * @param string|null $component [optional] Key component (starting with a key collection name)
         * @return string Colon-delimited list of $keyspace followed by escaped components of $args
         * @since 1.27
         */
index b414a2a..50fdc27 100644 (file)
@@ -167,6 +167,9 @@ class DBConnRef implements IDatabase {
                return $this->__call( __FUNCTION__, func_get_args() );
        }
 
+       /**
+        * @codeCoverageIgnore
+        */
        public function getWikiID() {
                return $this->getDomainID();
        }
index 3054156..8d1e25f 100644 (file)
@@ -4113,7 +4113,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @see WANObjectCache::getWithSetCallback()
         *
         * @param IDatabase $db1
-        * @param IDatabase $db2 [optional]
+        * @param IDatabase|null $db2 [optional]
         * @return array Map of values:
         *   - lag: highest lag of any of the DBs or false on error (e.g. replication stopped)
         *   - since: oldest UNIX timestamp of any of the DB lag estimates
index bbc656d..3ecfca9 100644 (file)
@@ -498,7 +498,7 @@ abstract class DatabaseMysqlBase extends Database {
        /**
         * Returns the text of the error message from previous MySQL operation
         *
-        * @param resource $conn Raw connection
+        * @param resource|null $conn Raw connection
         * @return string
         */
        abstract protected function mysqlError( $conn = null );
@@ -1457,7 +1457,7 @@ abstract class DatabaseMysqlBase extends Database {
        /**
         * List all tables on the database
         *
-        * @param string $prefix Only show tables with this prefix, e.g. mw_
+        * @param string|null $prefix Only show tables with this prefix, e.g. mw_
         * @param string $fname Calling function name
         * @return array
         */
@@ -1511,7 +1511,7 @@ abstract class DatabaseMysqlBase extends Database {
        /**
         * Lists VIEWs in the database
         *
-        * @param string $prefix Only show VIEWs with this prefix, eg.
+        * @param string|null $prefix Only show VIEWs with this prefix, eg.
         * unit_test_, or $wgDBprefix. Default: null, would return all views.
         * @param string $fname Name of calling function
         * @return array
@@ -1547,7 +1547,7 @@ abstract class DatabaseMysqlBase extends Database {
         * Differentiates between a TABLE and a VIEW.
         *
         * @param string $name Name of the TABLE/VIEW to test
-        * @param string $prefix
+        * @param string|null $prefix
         * @return bool
         * @since 1.22
         */
index ec69b9d..6d9dabd 100644 (file)
@@ -296,7 +296,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        }
 
        /**
-        * @param mysqli $conn Optional connection object
+        * @param mysqli|null $conn Optional connection object
         * @return string
         */
        protected function mysqlError( $conn = null ) {
index d86c5ce..ca44572 100644 (file)
@@ -1036,7 +1036,7 @@ class DatabaseSqlite extends Database {
        /**
         * List all tables on the database
         *
-        * @param string $prefix Only show tables with this prefix, e.g. mw_
+        * @param string|null $prefix Only show tables with this prefix, e.g. mw_
         * @param string $fname Calling function name
         *
         * @return array
index 2145129..723051c 100644 (file)
@@ -166,14 +166,14 @@ interface IDatabase {
 
        /**
         * Get/set the table prefix.
-        * @param string $prefix The table prefix to set, or omitted to leave it unchanged.
+        * @param string|null $prefix The table prefix to set, or omitted to leave it unchanged.
         * @return string The previous table prefix.
         */
        public function tablePrefix( $prefix = null );
 
        /**
         * Get/set the db schema.
-        * @param string $schema The database schema to set, or omitted to leave it unchanged.
+        * @param string|null $schema The database schema to set, or omitted to leave it unchanged.
         * @return string The previous db schema.
         */
        public function dbSchema( $schema = null );
@@ -182,7 +182,7 @@ interface IDatabase {
         * Get properties passed down from the server info array of the load
         * balancer.
         *
-        * @param string $name The entry of the info array to get, or null to get the
+        * @param string|null $name The entry of the info array to get, or null to get the
         *   whole array
         *
         * @return array|mixed|null
@@ -195,7 +195,7 @@ interface IDatabase {
         * parameters, the member with the given name is set to the given value.
         *
         * @param string $name
-        * @param array $value
+        * @param array|null $value
         */
        public function setLBInfo( $name, $value = null );
 
@@ -1698,7 +1698,7 @@ interface IDatabase {
         * @since 1.31
         * @see IDatabase::startAtomic
         * @param string $fname
-        * @param AtomicSectionIdentifier $sectionId Section ID from startAtomic();
+        * @param AtomicSectionIdentifier|null $sectionId Section ID from startAtomic();
         *   passing this enables cancellation of unclosed nested sections [optional]
         * @throws DBError
         */
@@ -1882,7 +1882,7 @@ interface IDatabase {
         * The result is unquoted, and needs to be passed through addQuotes()
         * before it can be included in raw SQL.
         *
-        * @param string|int $ts
+        * @param string|int|null $ts
         *
         * @return string
         */
index 18e3cbb..5706435 100644 (file)
@@ -183,7 +183,7 @@ interface IMaintainableDatabase extends IDatabase {
        /**
         * Lists all the VIEWs in the database
         *
-        * @param string $prefix Only show VIEWs with this prefix, eg. unit_test_
+        * @param string|null $prefix Only show VIEWs with this prefix, eg. unit_test_
         * @param string $fname Name of calling function
         * @throws RuntimeException
         * @return array
@@ -279,7 +279,7 @@ interface IMaintainableDatabase extends IDatabase {
        /**
         * List all tables on the database
         *
-        * @param string $prefix Only show tables with this prefix, e.g. mw_
+        * @param string|null $prefix Only show tables with this prefix, e.g. mw_
         * @param string $fname Calling function name
         * @throws DBError
         * @return array
index 4c5bc9a..4ed2b31 100644 (file)
@@ -25,7 +25,7 @@ namespace Wikimedia\Rdbms;
  */
 class DBConnectionError extends DBExpectedError {
        /**
-        * @param IDatabase $db Object throwing the error
+        * @param IDatabase|null $db Object throwing the error
         * @param string $error Error text
         */
        public function __construct( IDatabase $db = null, $error = 'unknown error' ) {
index 1a5f4a3..6b67b45 100644 (file)
@@ -33,7 +33,7 @@ class DBError extends RuntimeException {
 
        /**
         * Construct a database error
-        * @param IDatabase $db Object which threw the error
+        * @param IDatabase|null $db Object which threw the error
         * @param string $error A simple error message to be used for debugging
         * @param \Exception|\Throwable|null $prev Previous exception
         */
index 0be08cd..4bdd8f6 100644 (file)
@@ -40,7 +40,7 @@ class DBQueryError extends DBExpectedError {
         * @param int|string $errno
         * @param string $sql
         * @param string $fname
-        * @param string $message Optional message, intended for subclases (optional)
+        * @param string|null $message Optional message, intended for subclases (optional)
         */
        public function __construct( IDatabase $db, $error, $errno, $sql, $fname, $message = null ) {
                if ( $message === null ) {
index 85ab115..222d7d1 100644 (file)
@@ -67,6 +67,22 @@ interface ILBFactory {
         */
        public function destroy();
 
+       /**
+        * Get the local (and default) database domain ID of connection handles
+        *
+        * @see DatabaseDomain
+        * @return string Database domain ID; this specifies DB name, schema, and table prefix
+        * @since 1.32
+        */
+       public function getLocalDomainID();
+
+       /**
+        * @param DatabaseDomain|string|bool $domain Database domain
+        * @return string Value of $domain if provided or the local domain otherwise
+        * @since 1.32
+        */
+       public function resolveDomainID( $domain );
+
        /**
         * Create a new load balancer object. The resulting object will be untracked,
         * not chronology-protected, and the caller is responsible for cleaning it up.
@@ -229,7 +245,7 @@ interface ILBFactory {
 
        /**
         * Determine if any master connection has pending/written changes from this request
-        * @param float $age How many seconds ago is "recent" [defaults to LB lag wait timeout]
+        * @param float|null $age How many seconds ago is "recent" [defaults to LB lag wait timeout]
         * @return bool
         */
        public function hasOrMadeRecentMasterChanges( $age = null );
index 856bd32..e47e75e 100644 (file)
@@ -152,6 +152,14 @@ abstract class LBFactory implements ILBFactory {
                $this->forEachLBCallMethod( 'disable' );
        }
 
+       public function getLocalDomainID() {
+               return $this->localDomain->getId();
+       }
+
+       public function resolveDomainID( $domain ) {
+               return ( $domain !== false ) ? (string)$domain : $this->getLocalDomainID();
+       }
+
        public function shutdown(
                $mode = self::SHUTDOWN_CHRONPROT_SYNC,
                callable $workCallback = null,
index 4eaa4e8..0ff6a32 100644 (file)
@@ -120,6 +120,22 @@ interface ILoadBalancer {
         */
        public function __construct( array $params );
 
+       /**
+        * Get the local (and default) database domain ID of connection handles
+        *
+        * @see DatabaseDomain
+        * @return string Database domain ID; this specifies DB name, schema, and table prefix
+        * @since 1.31
+        */
+       public function getLocalDomainID();
+
+       /**
+        * @param DatabaseDomain|string|bool $domain Database domain
+        * @return string Value of $domain if provided or the local domain otherwise
+        * @since 1.32
+        */
+       public function resolveDomainID( $domain );
+
        /**
         * Get the index of the reader connection, which may be a replica DB
         *
@@ -154,7 +170,7 @@ interface ILoadBalancer {
         * This can be used a faster proxy for waitForAll()
         *
         * @param DBMasterPos|bool $pos Master position or false
-        * @param int $timeout Max seconds to wait; default is mWaitTimeout
+        * @param int|null $timeout Max seconds to wait; default is mWaitTimeout
         * @return bool Success (able to connect and no timeouts reached)
         */
        public function waitForOne( $pos, $timeout = null );
@@ -163,7 +179,7 @@ interface ILoadBalancer {
         * Set the master wait position and wait for ALL replica DBs to catch up to it
         *
         * @param DBMasterPos|bool $pos Master position or false
-        * @param int $timeout Max seconds to wait; default is mWaitTimeout
+        * @param int|null $timeout Max seconds to wait; default is mWaitTimeout
         * @return bool Success (able to connect and no timeouts reached)
         */
        public function waitForAll( $pos, $timeout = null );
@@ -486,7 +502,7 @@ interface ILoadBalancer {
         * Check if this load balancer object had any recent or still
         * pending writes issued against it by this PHP thread
         *
-        * @param float $age How many seconds ago is "recent" [defaults to mWaitTimeout]
+        * @param float|null $age How many seconds ago is "recent" [defaults to mWaitTimeout]
         * @return bool
         */
        public function hasOrMadeRecentMasterChanges( $age = null );
index fe0c622..f2f9eb0 100644 (file)
@@ -269,17 +269,14 @@ class LoadBalancer implements ILoadBalancer {
                $this->defaultGroup = $params['defaultGroup'] ?? null;
        }
 
-       /**
-        * Get the local (and default) database domain ID of connection handles
-        *
-        * @see DatabaseDomain
-        * @return string Database domain ID; this specifies DB name, schema, and table prefix
-        * @since 1.31
-        */
        public function getLocalDomainID() {
                return $this->localDomain->getId();
        }
 
+       public function resolveDomainID( $domain ) {
+               return ( $domain !== false ) ? (string)$domain : $this->getLocalDomainID();
+       }
+
        /**
         * Get a LoadMonitor instance
         *
@@ -606,7 +603,7 @@ class LoadBalancer implements ILoadBalancer {
         * Wait for a given replica DB to catch up to the master pos stored in $this
         * @param int $index Server index
         * @param bool $open Check the server even if a new connection has to be made
-        * @param int $timeout Max seconds to wait; default is "waitTimeout" given to __construct()
+        * @param int|null $timeout Max seconds to wait; default is "waitTimeout" given to __construct()
         * @return bool
         */
        protected function doWait( $index, $open = false, $timeout = null ) {
@@ -848,19 +845,19 @@ class LoadBalancer implements ILoadBalancer {
        }
 
        public function getConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
-               $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+               $domain = $this->resolveDomainID( $domain );
 
                return new DBConnRef( $this, $this->getConnection( $db, $groups, $domain, $flags ) );
        }
 
        public function getLazyConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
-               $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+               $domain = $this->resolveDomainID( $domain );
 
                return new DBConnRef( $this, [ $db, $groups, $domain, $flags ] );
        }
 
        public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
-               $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+               $domain = $this->resolveDomainID( $domain );
 
                return new MaintainableDBConnRef(
                        $this, $this->getConnection( $db, $groups, $domain, $flags ) );
index bbcb267..a73fac1 100644 (file)
@@ -154,8 +154,8 @@ class RedisConnRef implements LoggerAwareInterface {
         * See: https://github.com/phpredis/phpredis#scan
         *
         * @param int &$iterator
-        * @param string $pattern
-        * @param int $count
+        * @param string|null $pattern
+        * @param int|null $count
         * @return array $res
         */
        public function scan( &$iterator, $pattern = null, $count = null ) {
@@ -169,8 +169,8 @@ class RedisConnRef implements LoggerAwareInterface {
         *
         * @param string $key
         * @param int &$iterator
-        * @param string $pattern
-        * @param int $count
+        * @param string|null $pattern
+        * @param int|null $count
         * @return array $res
         */
        public function sScan( $key, &$iterator, $pattern = null, $count = null ) {
@@ -184,8 +184,8 @@ class RedisConnRef implements LoggerAwareInterface {
         *
         * @param string $key
         * @param int &$iterator
-        * @param string $pattern
-        * @param int $count
+        * @param string|null $pattern
+        * @param int|null $count
         * @return array $res
         */
        public function hScan( $key, &$iterator, $pattern = null, $count = null ) {
@@ -199,8 +199,8 @@ class RedisConnRef implements LoggerAwareInterface {
         *
         * @param string $key
         * @param int &$iterator
-        * @param string $pattern
-        * @param int $count
+        * @param string|null $pattern
+        * @param int|null $count
         * @return array $res
         */
        public function zScan( $key, &$iterator, $pattern = null, $count = null ) {
index 82cc233..aa60242 100644 (file)
@@ -168,7 +168,7 @@ class RedisConnectionPool implements LoggerAwareInterface {
         *
         * @param string $server A hostname/port combination or the absolute path of a UNIX socket.
         *                       If a hostname is specified but no port, port 6379 will be used.
-        * @param LoggerInterface $logger PSR-3 logger intance. [optional]
+        * @param LoggerInterface|null $logger PSR-3 logger intance. [optional]
         * @return RedisConnRef|bool Returns false on failure
         * @throws MWException
         */
@@ -382,7 +382,7 @@ class RedisConnectionPool implements LoggerAwareInterface {
         * Adjust or reset the connection handle read timeout value
         *
         * @param Redis $conn
-        * @param int $timeout Optional
+        * @param int|null $timeout Optional
         */
        public function resetTimeout( Redis $conn, $timeout = null ) {
                $conn->setOption( Redis::OPT_READ_TIMEOUT, $timeout ?: $this->readTimeout );
index e9e338d..39e679b 100644 (file)
@@ -625,7 +625,7 @@ class ManualLogEntry extends LogEntryBase {
        /**
         * Insert the entry into the `logging` table.
         *
-        * @param IDatabase $dbw
+        * @param IDatabase|null $dbw
         * @return int ID of the log entry
         * @throws MWException
         */
index 7b8ffef..17d15d6 100644 (file)
@@ -101,9 +101,9 @@ class LogEventsList extends ContextSource {
         * @param int|string $year Use 0 to start with no year preselected.
         * @param int|string $month A month in the 1..12 range. Use 0 to start with no month
         *  preselected.
-        * @param array $filter
+        * @param array|null $filter
         * @param string $tagFilter Tag to select by default
-        * @param string $action
+        * @param string|null $action
         */
        public function showOptions( $types = [], $user = '', $page = '', $pattern = false, $year = 0,
                $month = 0, $filter = null, $tagFilter = '', $action = null
@@ -524,7 +524,7 @@ class LogEventsList extends ContextSource {
         *
         * @param stdClass $row
         * @param int $field
-        * @param User $user User to check, or null to use $wgUser
+        * @param User|null $user User to check, or null to use $wgUser
         * @return bool
         */
        public static function userCan( $row, $field, User $user = null ) {
@@ -537,7 +537,7 @@ class LogEventsList extends ContextSource {
         *
         * @param int $bitfield Current field
         * @param int $field
-        * @param User $user User to check, or null to use $wgUser
+        * @param User|null $user User to check, or null to use $wgUser
         * @return bool
         */
        public static function userCanBitfield( $bitfield, $field, User $user = null ) {
@@ -745,7 +745,7 @@ class LogEventsList extends ContextSource {
         *
         * @param IDatabase $db
         * @param string $audience Public/user
-        * @param User $user User to check, or null to use $wgUser
+        * @param User|null $user User to check, or null to use $wgUser
         * @return string|bool String on success, false on failure.
         */
        public static function getExcludeClause( $db, $audience = 'public', User $user = null ) {
index 54f2d58..d59c6aa 100644 (file)
@@ -639,7 +639,7 @@ class LogFormatter {
        /**
         * Helper to make a link to the page, taking the plaintext
         * value in consideration.
-        * @param Title $title The page
+        * @param Title|null $title The page
         * @param array $parameters Query parameters
         * @param string|null $html Linktext of the link as raw html
         * @throws MWException
index 9b2e098..d737a4b 100644 (file)
@@ -33,8 +33,8 @@ class PatrolLog {
         *
         * @param int|RecentChange $rc Change identifier or RecentChange object
         * @param bool $auto Was this patrol event automatic?
-        * @param User $user User performing the action or null to use $wgUser
-        * @param string|string[] $tags Change tags to add to the patrol log entry
+        * @param User|null $user User performing the action or null to use $wgUser
+        * @param string|string[]|null $tags Change tags to add to the patrol log entry
         *   ($user should be able to add the specified tags before this is called)
         *
         * @return bool
index b9d9414..1b66c38 100644 (file)
@@ -47,8 +47,8 @@ class MailAddress {
 
        /**
         * @param string $address String with an email address, or a User object
-        * @param string $name Human-readable name if a string address is given
-        * @param string $realName Human-readable real name if a string address is given
+        * @param string|null $name Human-readable name if a string address is given
+        * @param string|null $realName Human-readable real name if a string address is given
         */
        function __construct( $address, $name = null, $realName = null ) {
                if ( is_object( $address ) && $address instanceof User ) {
index 0229ac1..ed6e76f 100644 (file)
@@ -41,7 +41,7 @@ class BmpHandler extends BitmapHandler {
         *
         * @param string $text
         * @param string $mime
-        * @param array $params
+        * @param array|null $params
         * @return array
         */
        function getThumbType( $text, $mime, $params = null ) {
index c76930c..4583632 100644 (file)
@@ -284,7 +284,7 @@ abstract class MediaHandler {
         *
         * @param string $ext Extension of original file
         * @param string $mime MIME type of original file
-        * @param array $params Handler specific rendering parameters
+        * @param array|null $params Handler specific rendering parameters
         * @return array Thumbnail extension and MIME type
         */
        function getThumbType( $ext, $mime, $params = null ) {
index 4aeaac4..dba1b60 100644 (file)
@@ -236,7 +236,7 @@ abstract class MediaTransformOutput {
        }
 
        /**
-        * @param string $title
+        * @param string|null $title
         * @param string|array $params Query parameters to add
         * @return array
         */
index f0f4cda..441513e 100644 (file)
@@ -61,7 +61,7 @@ class TiffHandler extends ExifBitmapHandler {
        /**
         * @param string $ext
         * @param string $mime
-        * @param array $params
+        * @param array|null $params
         * @return bool
         */
        function getThumbType( $ext, $mime, $params = null ) {
index 491fef2..0cb618f 100644 (file)
@@ -46,7 +46,7 @@ class XCFHandler extends BitmapHandler {
         *
         * @param string $ext
         * @param string $mime
-        * @param array $params
+        * @param array|null $params
         * @return array
         */
        function getThumbType( $ext, $mime, $params = null ) {
index 51136ff..abf32d7 100644 (file)
@@ -85,7 +85,7 @@ class Article implements Page {
        /**
         * Constructor and clear the article
         * @param Title $title Reference to a Title object.
-        * @param int $oldId Revision ID, null to fetch from request, zero for current
+        * @param int|null $oldId Revision ID, null to fetch from request, zero for current
         */
        public function __construct( Title $title, $oldId = null ) {
                $this->mOldId = $oldId;
@@ -1962,7 +1962,7 @@ class Article implements Page {
         * @since 1.16 (r52326) for LiquidThreads
         *
         * @param int|null $oldid Revision ID or null
-        * @param User $user The relevant user
+        * @param User|null $user The relevant user
         * @return ParserOutput|bool ParserOutput or false if the given revision ID is not found
         */
        public function getParserOutput( $oldid = null, User $user = null ) {
@@ -2615,8 +2615,8 @@ class Article implements Page {
        /**
         * @param string $reason
         * @param bool $suppress
-        * @param int $u1 Unused
-        * @param bool $u2 Unused
+        * @param int|null $u1 Unused
+        * @param bool|null $u2 Unused
         * @param string &$error
         * @return bool
         */
index 8b42020..9681ece 100644 (file)
@@ -387,8 +387,8 @@ class PageArchive {
         * @param string $comment
         * @param array $fileVersions
         * @param bool $unsuppress
-        * @param User $user User performing the action, or null to use $wgUser
-        * @param string|string[] $tags Change tags to add to log entry
+        * @param User|null $user User performing the action, or null to use $wgUser
+        * @param string|string[]|null $tags Change tags to add to log entry
         *   ($user should be able to add the specified tags before this is called)
         * @return array|bool array(number of file revisions restored, number of image revisions
         *   restored, log message) on success, false on failure.
index 261c954..5facc62 100644 (file)
@@ -768,7 +768,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to $wgUser
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return Content|null The content of the current revision
         *
@@ -808,7 +808,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return int User ID for the user that made the last article revision
         */
@@ -827,7 +827,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return User|null
         */
@@ -846,7 +846,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return string Username of the user that made the last article revision
         */
@@ -864,7 +864,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return string Comment stored for the last article revision
         */
@@ -1306,10 +1306,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param IDatabase $dbw
         * @param Revision $revision For ID number, and text used to set
         *   length and redirect status fields
-        * @param int $lastRevision If given, will not overwrite the page field
+        * @param int|null $lastRevision If given, will not overwrite the page field
         *   when different from the currently set value.
         *   Giving 0 indicates the new page flag should be set on.
-        * @param bool $lastRevIsRedirect If given, will optimize adding and
+        * @param bool|null $lastRevIsRedirect If given, will optimize adding and
         *   removing rows in redirect table.
         * @return bool Success; false if the page row was missing or page_latest changed
         */
@@ -1774,8 +1774,8 @@ class WikiPage implements Page, IDBAccessObject {
         * restores or repeats. The new revision is expected to have the exact same content as
         * the given original revision. This is used with rollbacks and with dummy "null" revisions
         * which are created to record things like page moves.
-        * @param User $user The user doing the edit
-        * @param string $serialFormat IGNORED.
+        * @param User|null $user The user doing the edit
+        * @param string|null $serialFormat IGNORED.
         * @param array|null $tags Change tags to apply to this edit
         * Callers are responsible for permission checks
         * (with ChangeTags::canAddTagsAccompanyingChange)
@@ -1987,7 +1987,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param int &$cascade Set to false if cascading protection isn't allowed.
         * @param string $reason
         * @param User $user The user updating the restrictions
-        * @param string|string[] $tags Change tags to add to the pages and protection log entries
+        * @param string|string[]|null $tags Change tags to add to the pages and protection log entries
         *   ($user should be able to add the specified tags before this is called)
         * @return Status Status object; if action is taken, $status->value is the log_id of the
         *   protection log entry.
@@ -2403,10 +2403,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param string $reason Delete reason for deletion log
         * @param bool $suppress Suppress all revisions and log the deletion in
         *        the suppression log instead of the deletion log
-        * @param int $u1 Unused
-        * @param bool $u2 Unused
+        * @param int|null $u1 Unused
+        * @param bool|null $u2 Unused
         * @param array|string &$error Array of errors to append to
-        * @param User $user The deleting user
+        * @param User|null $user The deleting user
         * @return bool True if successful
         */
        public function doDeleteArticle(
@@ -2425,10 +2425,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param string $reason Delete reason for deletion log
         * @param bool $suppress Suppress all revisions and log the deletion in
         *   the suppression log instead of the deletion log
-        * @param int $u1 Unused
-        * @param bool $u2 Unused
+        * @param int|null $u1 Unused
+        * @param bool|null $u2 Unused
         * @param array|string &$error Array of errors to append to
-        * @param User $deleter The deleting user
+        * @param User|null $deleter The deleting user
         * @param array $tags Tags to apply to the deletion action
         * @param string $logsubtype
         * @return Status Status object; if successful, $status->value is the log_id of the
@@ -2542,7 +2542,19 @@ class WikiPage implements Page, IDBAccessObject {
                        // Fetch all rows in case the DB needs that to properly lock them.
                }
 
-               // Get all of the page revisions
+               // If SCHEMA_COMPAT_WRITE_OLD is set, also select all extra fields we still write,
+               // so we can copy it to the archive table.
+               // We know the fields exist, otherwise SCHEMA_COMPAT_WRITE_OLD could not function.
+               if ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
+                       $revQuery['fields'][] = 'rev_text_id';
+
+                       if ( $wgContentHandlerUseDB ) {
+                               $revQuery['fields'][] = 'rev_content_model';
+                               $revQuery['fields'][] = 'rev_content_format';
+                       }
+               }
+
+                       // Get all of the page revisions
                $res = $dbw->select(
                        $revQuery['tables'],
                        $revQuery['fields'],
@@ -2584,17 +2596,15 @@ class WikiPage implements Page, IDBAccessObject {
                        ] + $commentStore->insert( $dbw, 'ar_comment', $comment )
                                + $actorMigration->getInsertValues( $dbw, 'ar_user', $user );
 
-                       if ( $wgMultiContentRevisionSchemaMigrationStage < MIGRATION_NEW ) {
+                       if ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
                                $rowInsert['ar_text_id'] = $row->rev_text_id;
-                       }
 
-                       if (
-                               $wgContentHandlerUseDB &&
-                               $wgMultiContentRevisionSchemaMigrationStage <= MIGRATION_WRITE_BOTH
-                       ) {
-                               $rowInsert['ar_content_model'] = $row->rev_content_model;
-                               $rowInsert['ar_content_format'] = $row->rev_content_format;
+                               if ( $wgContentHandlerUseDB ) {
+                                       $rowInsert['ar_content_model'] = $row->rev_content_model;
+                                       $rowInsert['ar_content_format'] = $row->rev_content_format;
+                               }
                        }
+
                        $rowsInsert[] = $rowInsert;
                        $revids[] = $row->rev_id;
 
index 2323142..b00ec3a 100644 (file)
@@ -456,8 +456,8 @@ abstract class IndexPager extends ContextSource implements Pager {
         * Make a self-link
         *
         * @param string $text Text displayed on the link
-        * @param array $query Associative array of parameter to be in the query string
-        * @param string $type Link type used to create additional attributes, like "rel", "class" or
+        * @param array|null $query Associative array of parameter to be in the query string
+        * @param string|null $type Link type used to create additional attributes, like "rel", "class" or
         *  "title". Valid values (non-exhaustive list): 'first', 'last', 'prev', 'next', 'asc', 'desc'.
         * @return string HTML fragment
         */
index 99ca07a..10da0b0 100644 (file)
@@ -112,7 +112,7 @@ class CoreParserFunctions {
        /**
         * @param Parser $parser
         * @param string $date
-        * @param string $defaultPref
+        * @param string|null $defaultPref
         *
         * @return string
         */
@@ -165,7 +165,7 @@ class CoreParserFunctions {
         *
         * @param Parser $parser
         * @param string $s The text to encode.
-        * @param string $arg (optional): The type of encoding.
+        * @param string|null $arg (optional): The type of encoding.
         * @return string
         */
        public static function urlencode( $parser, $s = '', $arg = null ) {
@@ -292,7 +292,7 @@ class CoreParserFunctions {
        /**
         * @param Parser $parser
         * @param string $num
-        * @param string $arg
+        * @param string|null $arg
         * @return string
         */
        public static function formatnum( $parser, $num = '', $arg = null ) {
@@ -556,7 +556,7 @@ class CoreParserFunctions {
         * Note: function name changed to "mwnamespace" rather than "namespace"
         * to not break PHP 5.3
         * @param Parser $parser
-        * @param string $title
+        * @param string|null $title
         * @return mixed|string
         */
        public static function mwnamespace( $parser, $title = null ) {
@@ -613,7 +613,7 @@ class CoreParserFunctions {
         * Functions to get and normalize pagenames, corresponding to the magic words
         * of the same names
         * @param Parser $parser
-        * @param string $title
+        * @param string|null $title
         * @return string
         */
        public static function pagename( $parser, $title = null ) {
@@ -721,8 +721,8 @@ class CoreParserFunctions {
         * can't be called too many times per page.
         * @param Parser $parser
         * @param string $name
-        * @param string $arg1
-        * @param string $arg2
+        * @param string|null $arg1
+        * @param string|null $arg2
         * @return string
         */
        public static function pagesincategory( $parser, $name = '', $arg1 = null, $arg2 = null ) {
@@ -789,7 +789,7 @@ class CoreParserFunctions {
         *
         * @param Parser $parser
         * @param string $page Name of page to check (Default: empty string)
-        * @param string $raw Should number be human readable with commas or just number
+        * @param string|null $raw Should number be human readable with commas or just number
         * @return string
         */
        public static function pagesize( $parser, $page = '', $raw = null ) {
@@ -1141,7 +1141,7 @@ class CoreParserFunctions {
        /**
         * Get the pageid of a specified page
         * @param Parser $parser
-        * @param string $title Title to get the pageid from
+        * @param string|null $title Title to get the pageid from
         * @return int|null|string
         * @since 1.23
         */
@@ -1186,7 +1186,7 @@ class CoreParserFunctions {
        /**
         * Get the id from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the id from
+        * @param string|null $title Title to get the id from
         * @return int|null|string
         * @since 1.23
         */
@@ -1203,7 +1203,7 @@ class CoreParserFunctions {
        /**
         * Get the day from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the day from
+        * @param string|null $title Title to get the day from
         * @return string
         * @since 1.23
         */
@@ -1220,7 +1220,7 @@ class CoreParserFunctions {
        /**
         * Get the day with leading zeros from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the day from
+        * @param string|null $title Title to get the day from
         * @return string
         * @since 1.23
         */
@@ -1237,7 +1237,7 @@ class CoreParserFunctions {
        /**
         * Get the month with leading zeros from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the month from
+        * @param string|null $title Title to get the month from
         * @return string
         * @since 1.23
         */
@@ -1254,7 +1254,7 @@ class CoreParserFunctions {
        /**
         * Get the month from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the month from
+        * @param string|null $title Title to get the month from
         * @return string
         * @since 1.23
         */
@@ -1271,7 +1271,7 @@ class CoreParserFunctions {
        /**
         * Get the year from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the year from
+        * @param string|null $title Title to get the year from
         * @return string
         * @since 1.23
         */
@@ -1288,7 +1288,7 @@ class CoreParserFunctions {
        /**
         * Get the timestamp from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the timestamp from
+        * @param string|null $title Title to get the timestamp from
         * @return string
         * @since 1.23
         */
@@ -1305,7 +1305,7 @@ class CoreParserFunctions {
        /**
         * Get the user from the last revision of a specified page.
         * @param Parser $parser
-        * @param string $title Title to get the user from
+        * @param string|null $title Title to get the user from
         * @return string
         * @since 1.23
         */
index 0270828..fd5ccb8 100644 (file)
@@ -401,7 +401,7 @@ class Parser {
         * @param ParserOptions $options
         * @param bool $linestart
         * @param bool $clearState
-        * @param int $revid Number to pass in {{REVISIONID}}
+        * @param int|null $revid Number to pass in {{REVISIONID}}
         * @return ParserOutput A ParserOutput
         */
        public function parse(
@@ -683,7 +683,7 @@ class Parser {
         * Also removes comments.
         * Do not call this function recursively.
         * @param string $text
-        * @param Title $title
+        * @param Title|null $title
         * @param ParserOptions $options
         * @param int|null $revid
         * @param bool|PPFrame $frame
@@ -789,7 +789,7 @@ class Parser {
        /**
         * Accessor/mutator for the Title object
         *
-        * @param Title $x Title object or null to just get the current one
+        * @param Title|null $x Title object or null to just get the current one
         * @return Title
         */
        public function Title( $x = null ) {
@@ -843,7 +843,7 @@ class Parser {
        /**
         * Accessor/mutator for the ParserOptions object
         *
-        * @param ParserOptions $x New value or null to just get the current one
+        * @param ParserOptions|null $x New value or null to just get the current one
         * @return ParserOptions Current ParserOptions object
         */
        public function Options( $x = null ) {
@@ -1914,7 +1914,7 @@ class Parser {
         * @since 1.21
         * @param string|bool $url Optional URL, to extract the domain from for rel =>
         *   nofollow if appropriate
-        * @param Title $title Optional Title, for wgNoFollowNsExceptions lookups
+        * @param Title|null $title Optional Title, for wgNoFollowNsExceptions lookups
         * @return string|null Rel attribute for $url
         */
        public static function getExternalLinkRel( $url = false, $title = null ) {
index 5959281..3a7a1d6 100644 (file)
@@ -932,8 +932,8 @@ class ParserOptions {
         * @warning For interaction with the parser cache, use
         *  WikiPage::makeParserOptions(), ContentHandler::makeParserOptions(), or
         *  ParserOptions::newCanonical() instead.
-        * @param User $user
-        * @param Language $lang
+        * @param User|null $user
+        * @param Language|null $lang
         */
        public function __construct( $user = null, $lang = null ) {
                if ( $user === null ) {
@@ -1271,7 +1271,7 @@ class ParserOptions {
         *
         * @since 1.17
         * @param string[] $forOptions
-        * @param Title $title Used to get the content language of the page (since r97636)
+        * @param Title|null $title Used to get the content language of the page (since r97636)
         * @return string Page rendering hash
         */
        public function optionsHash( $forOptions, $title = null ) {
index 265d151..182648a 100644 (file)
@@ -770,7 +770,7 @@ class ParserOutput extends CacheTime {
         * Add one or more variables to be set in mw.config in JavaScript.
         *
         * @param string|array $keys Key or array of key/value pairs.
-        * @param mixed $value [optional] Value of the configuration variable.
+        * @param mixed|null $value [optional] Value of the configuration variable.
         * @since 1.23
         */
        public function addJsConfigVars( $keys, $value = null ) {
index 21498f8..71b71e0 100644 (file)
@@ -463,12 +463,12 @@ class Sanitizer {
         * Cleans up HTML, removes dangerous tags and attributes, and
         * removes HTML comments
         * @param string $text
-        * @param callable $processCallback Callback to do any variable or parameter
+        * @param callable|null $processCallback Callback to do any variable or parameter
         *   replacements in HTML attribute values
         * @param array|bool $args Arguments for the processing callback
         * @param array $extratags For any extra tags to include
         * @param array $removetags For any tags (default or extra) to exclude
-        * @param callable $warnCallback (Deprecated) Callback allowing the
+        * @param callable|null $warnCallback (Deprecated) Callback allowing the
         *   addition of a tracking category when bad input is encountered.
         *   DO NOT ADD NEW PARAMETERS AFTER $warnCallback, since it will be
         *   removed shortly.
index 7b888ab..4af86ae 100644 (file)
@@ -53,7 +53,7 @@ class PoolWorkArticleView extends PoolCounterWork {
         * @param int $revid ID of the revision being parsed.
         * @param bool $useParserCache Whether to use the parser cache.
         *   operation.
-        * @param Content|string $content Content to parse or null to load it; may
+        * @param Content|string|null $content Content to parse or null to load it; may
         *   also be given as a wikitext string, for BC.
         */
        public function __construct( WikiPage $page, ParserOptions $parserOptions,
index 03e4bdb..bcd15b3 100644 (file)
@@ -1080,7 +1080,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                if ( $this->config->get( 'StructuredChangeFiltersShowPreference' ) ) {
                        $defaultPreferences['rcenhancedfilters-disable'] = [
                                'type' => 'toggle',
-                               'section' => 'rc/opt-out',
+                               'section' => 'rc/optoutrc',
                                'label-message' => 'rcfilters-preference-label',
                                'help-message' => 'rcfilters-preference-help',
                        ];
@@ -1283,7 +1283,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                if ( $this->config->get( 'StructuredChangeFiltersShowWatchlistPreference' ) ) {
                        $defaultPreferences['wlenhancedfilters-disable'] = [
                                'type' => 'toggle',
-                               'section' => 'watchlist/opt-out',
+                               'section' => 'watchlist/optoutwatchlist',
                                'label-message' => 'rcfilters-watchlist-preference-label',
                                'help-message' => 'rcfilters-watchlist-preference-help',
                        ];
index d02011f..bf4ddc7 100644 (file)
@@ -165,7 +165,7 @@ abstract class Profiler {
        abstract public function scopedProfileIn( $section );
 
        /**
-        * @param SectionProfileCallback &$section
+        * @param SectionProfileCallback|null &$section
         */
        public function scopedProfileOut( SectionProfileCallback &$section = null ) {
                $section = null;
index 80eb598..aa632c3 100644 (file)
@@ -238,8 +238,8 @@ class ResourceLoader implements LoggerAwareInterface {
 
        /**
         * Register core modules and runs registration hooks.
-        * @param Config $config [optional]
-        * @param LoggerInterface $logger [optional]
+        * @param Config|null $config [optional]
+        * @param LoggerInterface|null $logger [optional]
         */
        public function __construct( Config $config = null, LoggerInterface $logger = null ) {
                global $IP;
@@ -317,7 +317,7 @@ class ResourceLoader implements LoggerAwareInterface {
         * Register a module with the ResourceLoader system.
         *
         * @param mixed $name Name of module as a string or List of name/object pairs as an array
-        * @param array $info Module info array. For backwards compatibility with 1.17alpha,
+        * @param array|null $info Module info array. For backwards compatibility with 1.17alpha,
         *   this may also be a ResourceLoaderModule object. Optional when using
         *   multiple-registration calling style.
         * @throws MWException If a duplicate module registration is attempted
@@ -446,7 +446,7 @@ class ResourceLoader implements LoggerAwareInterface {
         * Source IDs are typically the same as the Wiki ID or database name (e.g. lowercase a-z).
         *
         * @param array|string $id Source ID (string), or [ id1 => loadUrl, id2 => loadUrl, ... ]
-        * @param string|array $loadUrl load.php url (string), or array with loadUrl key for
+        * @param string|array|null $loadUrl load.php url (string), or array with loadUrl key for
         *  backwards-compatibility.
         * @throws MWException
         */
@@ -1308,7 +1308,7 @@ MESSAGE;
         *         Set the state of modules with the given names to the given states
         *
         * @param string $name
-        * @param string $state
+        * @param string|null $state
         * @return string JavaScript code
         */
        public static function makeLoaderStateScript( $name, $state = null ) {
@@ -1406,11 +1406,11 @@ MESSAGE;
         *        Registers modules with the given names and parameters.
         *
         * @param string $name Module name
-        * @param string $version Module version hash
-        * @param array $dependencies List of module names on which this module depends
-        * @param string $group Group which the module is in
-        * @param string $source Source of the module, or 'local' if not foreign
-        * @param string $skip Script body of the skip function
+        * @param string|null $version Module version hash
+        * @param array|null $dependencies List of module names on which this module depends
+        * @param string|null $group Group which the module is in
+        * @param string|null $source Source of the module, or 'local' if not foreign
+        * @param string|null $skip Script body of the skip function
         * @return string JavaScript code
         */
        public static function makeLoaderRegisterScript( $name, $version = null,
@@ -1464,7 +1464,7 @@ MESSAGE;
         *       Register sources with the given IDs and properties.
         *
         * @param string $id Source ID
-        * @param string $loadUrl load.php url
+        * @param string|null $loadUrl load.php url
         * @return string JavaScript code
         */
        public static function makeLoaderSourcesScript( $id, $loadUrl = null ) {
@@ -1501,7 +1501,8 @@ MESSAGE;
         * startup module if the client has adequate support for MediaWiki JavaScript code.
         *
         * @param string $script JavaScript code
-        * @param string $nonce [optional] Content-Security-Policy nonce (from OutputPage::getCSPNonce)
+        * @param string|null $nonce [optional] Content-Security-Policy nonce
+        *  (from OutputPage::getCSPNonce)
         * @return string|WrappedString HTML
         */
        public static function makeInlineScript( $script, $nonce = null ) {
@@ -1643,10 +1644,10 @@ MESSAGE;
         * @param array $modules
         * @param string $lang
         * @param string $skin
-        * @param string $user
-        * @param string $version
+        * @param string|null $user
+        * @param string|null $version
         * @param bool $debug
-        * @param string $only
+        * @param string|null $only
         * @param bool $printable
         * @param bool $handheld
         * @param array $extraQuery
index 20faf8b..8d08366 100644 (file)
@@ -405,7 +405,8 @@ class ResourceLoaderClientHtml {
         * @param array $modules One or more module names
         * @param string $only ResourceLoaderModule TYPE_ class constant
         * @param array $extraQuery [optional] Array with extra query parameters for the request
-        * @param string $nonce [optional] Content-Security-Policy nonce (from OutputPage::getCSPNonce)
+        * @param string|null $nonce [optional] Content-Security-Policy nonce
+        *  (from OutputPage::getCSPNonce)
         * @return string|WrappedStringList HTML
         */
        public static function makeLoad( ResourceLoaderContext $mainContext, array $modules, $only,
index 68ea0c0..b2ca291 100644 (file)
@@ -153,10 +153,10 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *
         * @param array $options List of options; if not given or empty, an empty module will be
         *     constructed
-        * @param string $localBasePath Base path to prepend to all local paths in $options. Defaults
-        *     to $IP
-        * @param string $remoteBasePath Base path to prepend to all remote paths in $options. Defaults
-        *     to $wgResourceBasePath
+        * @param string|null $localBasePath Base path to prepend to all local paths in $options.
+        *     Defaults to $IP
+        * @param string|null $remoteBasePath Base path to prepend to all remote paths in $options.
+        *     Defaults to $wgResourceBasePath
         *
         * Below is a description for the $options array:
         * @throws InvalidArgumentException
@@ -298,9 +298,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * Implementation note: the amount of global state used in this function is staggering.
         *
         * @param array $options Module definition
-        * @param string $localBasePath Path to use if not provided in module definition. Defaults
+        * @param string|null $localBasePath Path to use if not provided in module definition. Defaults
         *     to $IP
-        * @param string $remoteBasePath Path to use if not provided in module definition. Defaults
+        * @param string|null $remoteBasePath Path to use if not provided in module definition. Defaults
         *     to $wgResourceBasePath
         * @return array Array( localBasePath, remoteBasePath )
         */
@@ -653,7 +653,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *
         * @param array $list List of lists to select from
         * @param string $key Key to look for in $map
-        * @param string $fallback Key to look for in $list if $key doesn't exist
+        * @param string|null $fallback Key to look for in $list if $key doesn't exist
         * @return array List of elements from $map which matched $key or $fallback,
         *  or an empty list in case of no match
         */
@@ -826,7 +826,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @private
         * @param array $styles Map of media type to file paths to read, remap, and concatenate
         * @param bool $flip
-        * @param ResourceLoaderContext $context
+        * @param ResourceLoaderContext|null $context
         * @return array List of concatenated and remapped CSS data from $styles,
         *     keyed by media type
         * @throws MWException
index 9311f6f..b711cbd 100644 (file)
@@ -52,7 +52,7 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
         *
         * @param array $options List of options; if not given or empty, an empty module will be
         *     constructed
-        * @param string $localBasePath Base path to prepend to all local paths in $options. Defaults
+        * @param string|null $localBasePath Base path to prepend to all local paths in $options. Defaults
         *     to $IP
         *
         * Below is a description for the $options array:
@@ -447,7 +447,7 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
         * Extract a local base path from module definition information.
         *
         * @param array $options Module definition
-        * @param string $localBasePath Path to use if not provided in module definition. Defaults
+        * @param string|null $localBasePath Path to use if not provided in module definition. Defaults
         *     to $IP
         * @return string Local base path
         */
index e78484a..f6716e7 100644 (file)
@@ -72,7 +72,7 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderModule {
        }
 
        /**
-        * @param ResourceLoaderContext $context
+        * @param ResourceLoaderContext|null $context
         * @return array
         */
        public function getDependencies( ResourceLoaderContext $context = null ) {
index 57260ba..72ccf66 100644 (file)
@@ -60,7 +60,7 @@ class ResourceLoaderLanguageNamesModule extends ResourceLoaderModule {
        }
 
        /**
-        * @param ResourceLoaderContext $context
+        * @param ResourceLoaderContext|null $context
         * @return array
         */
        public function getDependencies( ResourceLoaderContext $context = null ) {
index 609abb8..7018f16 100644 (file)
@@ -347,7 +347,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         * Note: It is expected that $context will be made non-optional in the near
         * future.
         *
-        * @param ResourceLoaderContext $context
+        * @param ResourceLoaderContext|null $context
         * @return array List of module names as strings
         */
        public function getDependencies( ResourceLoaderContext $context = null ) {
index a0061e3..0ad7fe4 100644 (file)
@@ -61,7 +61,7 @@ class ResourceLoaderSpecialCharacterDataModule extends ResourceLoaderModule {
        }
 
        /**
-        * @param ResourceLoaderContext $context
+        * @param ResourceLoaderContext|null $context
         * @return array
         */
        public function getDependencies( ResourceLoaderContext $context = null ) {
index ffa55c0..0d40ad7 100644 (file)
@@ -32,7 +32,7 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
        protected $targets = [ 'desktop', 'mobile' ];
 
        /**
-        * @param ResourceLoaderContext $context
+        * @param ResourceLoaderContext|null $context
         * @return array List of module names as strings
         */
        public function getDependencies( ResourceLoaderContext $context = null ) {
index ff5de0d..b699b36 100644 (file)
@@ -76,7 +76,8 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
        protected $group;
 
        /**
-        * @param array $options For back-compat, this can be omitted in favour of overwriting getPages.
+        * @param array|null $options For back-compat, this can be omitted in favour of overwriting
+        *  getPages.
         */
        public function __construct( array $options = null ) {
                if ( is_null( $options ) ) {
index 643c2c1..f2929a3 100644 (file)
@@ -35,7 +35,7 @@ class SearchDatabase extends SearchEngine {
        protected $db;
 
        /**
-        * @param IDatabase $db The database to search from
+        * @param IDatabase|null $db The database to search from
         */
        public function __construct( IDatabase $db = null ) {
                if ( $db ) {
index b2bacda..63c4610 100644 (file)
@@ -505,7 +505,7 @@ abstract class SearchEngine {
         *
         * @todo This isn't ideal, we'd really like to have content-specific handling here
         * @param Title $t Title we're indexing
-        * @param Content $c Content of the page to index
+        * @param Content|null $c Content of the page to index
         * @return string
         */
        public function getTextFromContent( Title $t, Content $c = null ) {
index 8cdca57..ecb6f43 100644 (file)
@@ -19,7 +19,7 @@ class SearchEngineFactory {
 
        /**
         * Create SearchEngine of the given type.
-        * @param string $type
+        * @param string|null $type
         * @return SearchEngine
         */
        public function create( $type = null ) {
index 20462cf..a97429e 100644 (file)
@@ -327,8 +327,8 @@ class SearchHighlighter {
         * @param string $text
         * @param int $start
         * @param int $end
-        * @param int &$posStart (out) actual start position
-        * @param int &$posEnd (out) actual end position
+        * @param int|null &$posStart (out) actual start position
+        * @param int|null &$posEnd (out) actual end position
         * @return string
         */
        function extract( $text, $start, $end, &$posStart = null, &$posEnd = null ) {
index 2f20d9d..bd19a84 100644 (file)
@@ -66,7 +66,7 @@ class SearchResult {
         * Return a new SearchResult and initializes it with a title.
         *
         * @param Title $title
-        * @param SearchResultSet $parentSet
+        * @param SearchResultSet|null $parentSet
         * @return SearchResult
         */
        public static function newFromTitle( $title, SearchResultSet $parentSet = null ) {
index 74925bd..aaa522a 100644 (file)
@@ -339,7 +339,7 @@ class CookieSessionProvider extends SessionProvider {
         * @param \WebRequest $request
         * @param string $key
         * @param string $prefix
-        * @param mixed $default
+        * @param mixed|null $default
         * @return mixed
         */
        protected function getCookie( $request, $key, $prefix, $default = null ) {
index e9a03f2..3dc8299 100644 (file)
@@ -291,7 +291,7 @@ final class Session implements \Countable, \Iterator, \ArrayAccess {
        /**
         * Fetch a value from the session
         * @param string|int $key
-        * @param mixed $default Returned if $this->exists( $key ) would be false
+        * @param mixed|null $default Returned if $this->exists( $key ) would be false
         * @return mixed
         */
        public function get( $key, $default = null ) {
@@ -522,7 +522,7 @@ final class Session implements \Countable, \Iterator, \ArrayAccess {
        /**
         * Fetch a value from the session that was set with self::setSecret()
         * @param string|int $key
-        * @param mixed $default Returned if $this->exists( $key ) would be false or decryption fails
+        * @param mixed|null $default Returned if $this->exists( $key ) would be false or decryption fails
         * @return mixed
         */
        public function getSecret( $key, $default = null ) {
index a376037..58163c6 100644 (file)
@@ -457,7 +457,7 @@ final class SessionBackend {
 
        /**
         * Set the "logged out" timestamp
-        * @param int $ts
+        * @param int|null $ts
         */
        public function setLoggedOutTimestamp( $ts = null ) {
                $ts = (int)$ts;
index e0b8d27..91d9ef7 100644 (file)
@@ -39,7 +39,7 @@ class SiteSQLStore {
         *             or MediaWikiServices::getSiteLookup() instead.
         *
         * @param null $sitesTable IGNORED
-        * @param null $cache IGNORED
+        * @param BagOStuff|null $cache IGNORED
         *
         * @return SiteStore
         */
index c1c856d..5c4d812 100644 (file)
@@ -575,7 +575,7 @@ abstract class BaseTemplate extends QuickTemplate {
         * If you pass "flat" as an option then the returned array will be a flat array
         * of footer icons instead of a key/value array of footerlinks arrays broken
         * up into categories.
-        * @param string $option
+        * @param string|null $option
         * @return array|mixed
         */
        function getFooterLinks( $option = null ) {
@@ -612,7 +612,7 @@ abstract class BaseTemplate extends QuickTemplate {
         * in the list of footer icons. This is mostly useful for skins which only
         * display the text from footericons instead of the images and don't want a
         * duplicate copyright statement because footerlinks already rendered one.
-        * @param string $option
+        * @param string|null $option
         * @return array
         */
        function getFooterIcons( $option = null ) {
index 296c133..969ac51 100644 (file)
@@ -35,7 +35,7 @@ abstract class QuickTemplate {
        protected $config;
 
        /**
-        * @param Config $config
+        * @param Config|null $config
         */
        function __construct( Config $config = null ) {
                $this->data = [];
@@ -73,7 +73,7 @@ abstract class QuickTemplate {
         * Gets the template data requested
         * @since 1.22
         * @param string $name Key for the data
-        * @param mixed $default Optional default (or null)
+        * @param mixed|null $default Optional default (or null)
         * @return mixed The value of the data requested or the deafult
         */
        public function get( $name, $default = null ) {
index 51be3b6..dde60f5 100644 (file)
@@ -391,13 +391,13 @@ abstract class Skin extends ContextSource {
 
        /**
         * Outputs the HTML generated by other functions.
-        * @param OutputPage $out
+        * @param OutputPage|null $out
         */
        abstract function outputPage( OutputPage $out = null );
 
        /**
         * @param array $data
-        * @param string $nonce OutputPage::getCSPNonce()
+        * @param string|null $nonce OutputPage::getCSPNonce()
         * @return string|WrappedString HTML
         */
        static function makeVariablesScript( $data, $nonce = null ) {
@@ -739,7 +739,7 @@ abstract class Skin extends ContextSource {
        }
 
        /**
-        * @param OutputPage $out Defaults to $this->getOutput() if left as null
+        * @param OutputPage|null $out Defaults to $this->getOutput() if left as null
         * @return string
         */
        function subPageSubtitle( $out = null ) {
@@ -1605,7 +1605,7 @@ abstract class Skin extends ContextSource {
         *   the current page, if the section is included from a template)
         * @param string $section The designation of the section being pointed to,
         *   to be included in the link, like "&section=$section"
-        * @param string $tooltip The tooltip to use for the link: will be escaped
+        * @param string|null $tooltip The tooltip to use for the link: will be escaped
         *   and wrapped in the 'editsectionhint' message
         * @param string $lang Language code
         * @return string HTML to use for edit link
index 507688d..7fc0c3a 100644 (file)
@@ -206,7 +206,7 @@ class SkinTemplate extends Skin {
        /**
         * initialize various variables and generate the template
         *
-        * @param OutputPage $out
+        * @param OutputPage|null $out
         */
        function outputPage( OutputPage $out = null ) {
                Profiler::instance()->setTemplated( true );
@@ -508,7 +508,7 @@ class SkinTemplate extends Skin {
         *
         * @since 1.31
         *
-        * @param array $personalTools
+        * @param array|null $personalTools
         * @param array $options
         * @return string
         */
index 557bd9c..1476e85 100644 (file)
@@ -70,7 +70,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
         * Used to preserve POST data over a HTTP redirect.
         *
         * @param array $data
-        * @param bool $wasPosted
+        * @param bool|null $wasPosted
         */
        protected function setRequest( array $data, $wasPosted = null ) {
                $request = $this->getContext()->getRequest();
@@ -223,7 +223,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
         * Load or initialize $authAction, $authRequests and $subPage.
         * Subclasses should call this from execute() or otherwise ensure the variables are initialized.
         * @param string $subPage Subpage of the special page.
-        * @param string $authAction Override auth action specified in request (this is useful
+        * @param string|null $authAction Override auth action specified in request (this is useful
         *    when the form needs to be changed from <action> to <action>_CONTINUE after a successful
         *    authentication step)
         * @param bool $reset Regenerate the requests even if a cached version is available
@@ -730,7 +730,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
         * Get an array value, or a default if it does not exist.
         * @param array $array
         * @param string $fieldName
-        * @param mixed $default
+        * @param mixed|null $default
         * @return mixed
         */
        protected static function getField( array $array, $fieldName, $default = null ) {
index 3082101..d5c889a 100644 (file)
@@ -1491,7 +1491,7 @@ class LoginForm extends SpecialPage {
        ];
 
        /**
-        * @param WebRequest $request
+        * @param WebRequest|null $request
         */
        public function __construct( $request = null ) {
                wfDeprecated( 'LoginForm', '1.27' );
index 5db8066..7a39b3c 100644 (file)
@@ -182,7 +182,7 @@ class SpecialPage implements MessageLocalizer {
        /**
         * Get or set whether this special page is listed in Special:SpecialPages
         * @since 1.6
-        * @param bool $x
+        * @param bool|null $x
         * @return bool
         */
        function listed( $x = null ) {
@@ -220,7 +220,7 @@ class SpecialPage implements MessageLocalizer {
 
        /**
         * Whether the special page is being evaluated via transclusion
-        * @param bool $x
+        * @param bool|null $x
         * @return bool
         */
        function including( $x = null ) {
@@ -388,7 +388,8 @@ class SpecialPage implements MessageLocalizer {
         * Note that this does not in any way check that the user is authorized to use this special page
         * (use checkPermissions() for that).
         *
-        * @param string $level A security level. Can be an arbitrary string, defaults to the page name.
+        * @param string|null $level A security level. Can be an arbitrary string, defaults to the page
+        *   name.
         * @return bool False means a redirect to the reauthentication page has been set and processing
         *   of the special page should be aborted.
         * @throws ErrorPageError If the security level cannot be met, even with reauthentication.
index b3cb806..b3b63b0 100644 (file)
@@ -415,7 +415,7 @@ class SpecialPageFactory {
         * Return categorised listable special pages which are available
         * for the current user, and everyone.
         *
-        * @param User $user User object to check permissions, $wgUser will be used
+        * @param User|null $user User object to check permissions, $wgUser will be used
         *        if not provided
         * @return array ( string => Specialpage )
         */
index bc632b1..92c6f50 100644 (file)
@@ -494,7 +494,7 @@ class SpecialBlock extends FormSpecialPage {
         * @todo Should be in Block.php?
         * @param string $par Subpage parameter passed to setup, or data value from
         *     the HTMLForm
-        * @param WebRequest $request Optionally try and get data from a request too
+        * @param WebRequest|null $request Optionally try and get data from a request too
         * @return array [ User|string|null, Block::TYPE_ constant|null ]
         */
        public static function getTargetAndType( $par, WebRequest $request = null ) {
@@ -1005,7 +1005,7 @@ class SpecialBlock extends FormSpecialPage {
        /**
         * Process the form on POST submission.
         * @param array $data
-        * @param HTMLForm $form
+        * @param HTMLForm|null $form
         * @return bool|array True for success, false for didn't-try, array of errors on failure
         */
        public function onSubmit( array $data, HTMLForm $form = null ) {
index c514300..4f97ba2 100644 (file)
@@ -151,8 +151,6 @@ class SpecialChangeEmail extends FormSpecialPage {
         * @return Status
         */
        private function attemptChange( User $user, $newaddr ) {
-               $authManager = AuthManager::singleton();
-
                if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
                        return Status::newFatal( 'invalidemailaddress' );
                }
index 4a939d4..d7ce414 100644 (file)
@@ -267,7 +267,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
         *
         * @param User $user
         * @param string $editToken Edit token
-        * @param Config $config optional for backwards compatibility
+        * @param Config|null $config optional for backwards compatibility
         * @return string|null Null on success or string on error
         */
        public static function getPermissionsError( $user, $editToken, Config $config = null ) {
index 6848d2c..2a8a09d 100644 (file)
@@ -140,7 +140,7 @@ class SpecialPrefixindex extends SpecialAllPages {
        /**
         * @param int $namespace
         * @param string $prefix
-        * @param string $from List all pages from this name (default false)
+        * @param string|null $from List all pages from this name (default false)
         */
        protected function showPrefixChunk( $namespace, $prefix, $from = null ) {
                global $wgContLang;
index 540dbc6..3069bd8 100644 (file)
@@ -129,7 +129,7 @@ class SpecialUndelete extends SpecialPage {
         * specific title if one is set.
         *
         * @param string $permission
-        * @param User $user
+        * @param User|null $user
         * @return bool
         */
        protected function isAllowed( $permission, User $user = null ) {
index 2eeafe6..e52945a 100644 (file)
@@ -33,7 +33,7 @@ use MediaWiki\MediaWikiServices;
 class SpecialUpload extends SpecialPage {
        /**
         * Get data POSTed through the form and assign them to the object
-        * @param WebRequest $request Data posted.
+        * @param WebRequest|null $request Data posted.
         */
        public function __construct( $request = null ) {
                parent::__construct( 'Upload', 'upload' );
@@ -587,7 +587,7 @@ class SpecialUpload extends SpecialPage {
         * @param string $license
         * @param string $copyStatus
         * @param string $source
-        * @param Config $config Configuration object to load data from
+        * @param Config|null $config Configuration object to load data from
         * @return string
         */
        public static function getInitialPageText( $comment = '', $license = '',
index cae895f..c1f1026 100644 (file)
@@ -130,7 +130,8 @@ class PreferencesFormLegacy extends HTMLForm {
         * @return string
         */
        function getLegend( $key ) {
-               $legend = parent::getLegend( $key );
+               $aliasKey = ( $key === 'optoutwatchlist' || $key === 'optoutrc' ) ? 'opt-out' : $key;
+               $legend = parent::getLegend( $aliasKey );
                Hooks::run( 'PreferencesGetLegend', [ $this, $key, &$legend ] );
                return $legend;
        }
index 423e2bb..cfa8f8f 100644 (file)
@@ -227,7 +227,8 @@ class PreferencesFormOOUI extends OOUIHTMLForm {
         * @return string
         */
        function getLegend( $key ) {
-               $legend = parent::getLegend( $key );
+               $aliasKey = ( $key === 'optoutwatchlist' || $key === 'optoutrc' ) ? 'opt-out' : $key;
+               $legend = parent::getLegend( $aliasKey );
                Hooks::run( 'PreferencesGetLegend', [ $this, $key, &$legend ] );
                return $legend;
        }
index 26ed499..87c849a 100644 (file)
@@ -44,7 +44,7 @@ class ActiveUsersPager extends UsersPager {
        private $blockStatusByUid;
 
        /**
-        * @param IContextSource $context
+        * @param IContextSource|null $context
         * @param FormOptions $opts
         */
        function __construct( IContextSource $context = null, FormOptions $opts ) {
index 23f9f83..aa757e6 100644 (file)
@@ -38,9 +38,9 @@ class UsersPager extends AlphabeticPager {
        protected $userGroupCache;
 
        /**
-        * @param IContextSource $context
-        * @param array $par (Default null)
-        * @param bool $including Whether this page is being transcluded in
+        * @param IContextSource|null $context
+        * @param array|null $par (Default null)
+        * @param bool|null $including Whether this page is being transcluded in
         * another page
         */
        function __construct( IContextSource $context = null, $par = null, $including = null ) {
index 245982e..ccef56b 100644 (file)
@@ -41,7 +41,7 @@ abstract class RaggettBase extends TidyDriverBase {
         * Perform a clean/repair operation
         * @param string $text HTML to check
         * @param bool $stderr Whether to read result from STDERR rather than STDOUT
-        * @param int &$retval Exit code (-1 on internal error)
+        * @param int|null &$retval Exit code (-1 on internal error)
         * @return null|string
         * @throws MWException
         */
index b59423a..2809ea4 100644 (file)
@@ -9,7 +9,7 @@ class RaggettExternal extends RaggettBase {
         *
         * @param string $text HTML to check
         * @param bool $stderr Whether to read result from STDERR rather than STDOUT
-        * @param int &$retval Exit code (-1 on internal error)
+        * @param int|null &$retval Exit code (-1 on internal error)
         * @return string|null
         */
        protected function cleanWrapped( $text, $stderr = false, &$retval = null ) {
index bb83d6a..65d37f4 100644 (file)
@@ -9,7 +9,7 @@ class RaggettInternalHHVM extends RaggettBase {
         *
         * @param string $text HTML to check
         * @param bool $stderr Whether to read result from error status instead of output
-        * @param int &$retval Exit code (-1 on internal error)
+        * @param int|null &$retval Exit code (-1 on internal error)
         * @return string|null
         */
        protected function cleanWrapped( $text, $stderr = false, &$retval = null ) {
index e5642d9..e7724b0 100644 (file)
@@ -9,7 +9,7 @@ class RaggettInternalPHP extends RaggettBase {
         *
         * @param string $text HTML to check
         * @param bool $stderr Whether to read result from error status instead of output
-        * @param int &$retval Exit code (-1 on internal error)
+        * @param int|null &$retval Exit code (-1 on internal error)
         * @return string|null
         */
        protected function cleanWrapped( $text, $stderr = false, &$retval = null ) {
index 213343f..47660e3 100644 (file)
@@ -29,7 +29,7 @@ class MalformedTitleException extends Exception implements ILocalizedException {
 
        /**
         * @param string $errorMessage Localisation message describing the error (since MW 1.26)
-        * @param string $titleText The invalid title text (since MW 1.26)
+        * @param string|null $titleText The invalid title text (since MW 1.26)
         * @param string[] $errorMessageParameters Additional parameters for the error message.
         * $titleText will be appended if it's not null. (since MW 1.26)
         */
index 87b96ac..dcebb60 100644 (file)
@@ -247,7 +247,7 @@ abstract class UploadBase {
 
        /**
         * @param string $tempPath File system path to temporary file containing the upload
-        * @param int $fileSize
+        * @param int|null $fileSize
         */
        protected function setTempFile( $tempPath, $fileSize = null ) {
                $this->mTempPath = $tempPath;
@@ -1103,7 +1103,7 @@ abstract class UploadBase {
         * file again.
         *
         * @deprecated since 1.28 Use tryStashFile() instead
-        * @param User $user
+        * @param User|null $user
         * @return UploadStashFile Stashed file
         * @throws UploadStashBadPathException
         * @throws UploadStashFileException
@@ -1116,7 +1116,7 @@ abstract class UploadBase {
        /**
         * Implementation for stashFile() and tryStashFile().
         *
-        * @param User $user
+        * @param User|null $user
         * @return UploadStashFile Stashed file
         */
        protected function doStashFile( User $user = null ) {
@@ -1529,7 +1529,7 @@ abstract class UploadBase {
         * @todo Replace this with a whitelist filter!
         * @param string $element
         * @param array $attribs
-        * @param array $data
+        * @param array|null $data
         * @return bool
         */
        public function checkSvgScriptCallback( $element, $attribs, $data = null ) {
index e55ab1f..4e40dce 100644 (file)
@@ -81,7 +81,7 @@ class UploadStash {
         * (should replace it eventually).
         *
         * @param FileRepo $repo
-        * @param User $user (default null)
+        * @param User|null $user
         */
        public function __construct( FileRepo $repo, $user = null ) {
                // this might change based on wiki's configuration.
@@ -202,7 +202,7 @@ class UploadStash {
         * database, along with other metadata.
         *
         * @param string $path Path to file you want stashed
-        * @param string $sourceType The type of upload that generated this file
+        * @param string|null $sourceType The type of upload that generated this file
         *   (currently, I believe, 'file' or null)
         * @throws UploadStashBadPathException
         * @throws UploadStashFileException
@@ -777,7 +777,8 @@ class UploadStashException extends MWException implements ILocalizedException {
        /**
         * @param string|array|MessageSpecifier $messageSpec See Message::newFromSpecifier
         * @param int $code Exception code
-        * @param Exception|Throwable $previous The previous exception used for the exception chaining.
+        * @param Exception|Throwable|null $previous The previous exception used for the exception
+        *  chaining.
         */
        public function __construct( $messageSpec, $code = 0, $previous = null ) {
                $this->messageSpec = $messageSpec;
index faf09ee..e7825e4 100644 (file)
@@ -122,8 +122,8 @@ class PasswordReset implements LoggerAwareInterface {
         *
         * @since 1.29 Fourth argument for displayPassword removed.
         * @param User $performingUser The user that does the password reset
-        * @param string $username The user whose password is reset
-        * @param string $email Alternative way to specify the user
+        * @param string|null $username The user whose password is reset
+        * @param string|null $email Alternative way to specify the user
         * @return StatusValue Will contain the passwords as a username => password array if the
         *   $displayPassword flag was set
         * @throws LogicException When the user is not allowed to perform the action
index 4e6e83a..ea8cd57 100644 (file)
@@ -759,7 +759,8 @@ class User implements IDBAccessObject, UserIdentity {
         * will be loaded once more from the database when accessing them.
         *
         * @param stdClass $row A row from the user table
-        * @param array $data Further data to load into the object (see User::loadFromRow for valid keys)
+        * @param array|null $data Further data to load into the object
+        *  (see User::loadFromRow for valid keys)
         * @return User
         */
        public static function newFromRow( $row, $data = null ) {
@@ -1062,7 +1063,7 @@ class User implements IDBAccessObject, UserIdentity {
         * @param string|array $groups A single group name or an array of group names
         * @param int $limit Max number of users to return. The actual limit will never exceed 5000
         *   records; larger values are ignored.
-        * @param int $after ID the user to start after
+        * @param int|null $after ID the user to start after
         * @return UserArrayFromResult
         */
        public static function findUsersByGroup( $groups, $limit = 5000, $after = null ) {
@@ -1465,7 +1466,7 @@ class User implements IDBAccessObject, UserIdentity {
         * Initialize this object from a row from the user table.
         *
         * @param stdClass $row Row from the user table to load.
-        * @param array $data Further user data to load into the object
+        * @param array|null $data Further user data to load into the object
         *
         *  user_groups   Array of arrays or stdClass result rows out of the user_groups
         *                table. Previously you were supposed to pass an array of strings
@@ -2692,7 +2693,7 @@ class User implements IDBAccessObject, UserIdentity {
        /**
         * Update the 'You have new messages!' status.
         * @param bool $val Whether the user has new messages
-        * @param Revision $curRev New, as yet unseen revision of the user talk
+        * @param Revision|null $curRev New, as yet unseen revision of the user talk
         *   page. Ignored if null or !$val.
         */
        public function setNewtalk( $val, $curRev = null ) {
@@ -3133,7 +3134,7 @@ class User implements IDBAccessObject, UserIdentity {
         * Get the user's current setting for a given option.
         *
         * @param string $oname The option to check
-        * @param string|array $defaultOverride A default value returned if the option does not exist
+        * @param string|array|null $defaultOverride A default value returned if the option does not exist
         * @param bool $ignoreHidden Whether to ignore the effects of $wgHiddenPrefs
         * @return string|array|int|null User's current value for the option
         * @see getBoolOption()
@@ -3328,7 +3329,7 @@ class User implements IDBAccessObject, UserIdentity {
         *
         * @see User::listOptionKinds
         * @param IContextSource $context
-        * @param array $options Assoc. array with options keys to check as keys.
+        * @param array|null $options Assoc. array with options keys to check as keys.
         *   Defaults to $this->mOptions.
         * @return array The key => kind mapping data
         */
@@ -3690,7 +3691,7 @@ class User implements IDBAccessObject, UserIdentity {
         * never expire.)
         *
         * @param string $group Name of the group to add
-        * @param string $expiry Optional expiry timestamp in any format acceptable to
+        * @param string|null $expiry Optional expiry timestamp in any format acceptable to
         *   wfTimestamp(), or null if the group assignment should not expire
         * @return bool
         */
@@ -4068,7 +4069,7 @@ class User implements IDBAccessObject, UserIdentity {
         *
         * @param WebRequest|null $request WebRequest object to use; $wgRequest will be used if null
         *        is passed.
-        * @param bool $secure Whether to force secure/insecure cookies or use default
+        * @param bool|null $secure Whether to force secure/insecure cookies or use default
         * @param bool $rememberMe Whether to add a Token cookie for elongated sessions
         */
        public function setCookies( $request = null, $secure = null, $rememberMe = false ) {
@@ -4617,7 +4618,7 @@ class User implements IDBAccessObject, UserIdentity {
         * @param string $val Input value to compare
         * @param string|array $salt Optional function-specific data for hashing
         * @param WebRequest|null $request Object to use or null to use $wgRequest
-        * @param int $maxage Fail tokens older than this, in seconds
+        * @param int|null $maxage Fail tokens older than this, in seconds
         * @return bool Whether the token matches
         */
        public function matchEditToken( $val, $salt = '', $request = null, $maxage = null ) {
@@ -4631,7 +4632,7 @@ class User implements IDBAccessObject, UserIdentity {
         * @param string $val Input value to compare
         * @param string|array $salt Optional function-specific data for hashing
         * @param WebRequest|null $request Object to use or null to use $wgRequest
-        * @param int $maxage Fail tokens older than this, in seconds
+        * @param int|null $maxage Fail tokens older than this, in seconds
         * @return bool Whether the token matches
         */
        public function matchEditTokenNoSuffix( $val, $salt = '', $request = null, $maxage = null ) {
@@ -4682,7 +4683,7 @@ class User implements IDBAccessObject, UserIdentity {
         * @param string $body Message body
         * @param User|null $from Optional sending user; if unspecified, default
         *   $wgPasswordSender will be used.
-        * @param string $replyto Reply-To address
+        * @param string|null $replyto Reply-To address
         * @return Status
         */
        public function sendMail( $subject, $body, $from = null, $replyto = null ) {
@@ -5446,7 +5447,7 @@ class User implements IDBAccessObject, UserIdentity {
        /**
         * Load the user options either from cache, the database or an array
         *
-        * @param array $data Rows for the current user out of the user_properties table
+        * @param array|null $data Rows for the current user out of the user_properties table
         */
        protected function loadOptions( $data = null ) {
                global $wgContLang;
index 89cdc5f..cf985cb 100644 (file)
@@ -46,7 +46,7 @@ class UserGroupMembership {
 
        /**
         * @param int $userId The ID of the user who belongs to the group
-        * @param string $group The internal group name
+        * @param string|null $group The internal group name
         * @param string|null $expiry Timestamp of expiry in TS_MW format, or null if no expiry
         */
        public function __construct( $userId = 0, $group = null, $expiry = null ) {
index caf88a1..d4f1a92 100644 (file)
@@ -26,7 +26,7 @@ class MWRestrictions {
        private $ipAddresses = [ '0.0.0.0/0', '::/0' ];
 
        /**
-        * @param array $restrictions
+        * @param array|null $restrictions
         * @throws InvalidArgumentException
         */
        protected function __construct( array $restrictions = null ) {
index 20bad13..46f3bbc 100644 (file)
@@ -511,7 +511,7 @@ class ZipDirectoryReader {
         * in the file to satisfy the request, an exception will be thrown.
         *
         * @param int $start The byte offset of the start of the block.
-        * @param int $length The number of bytes to return. If omitted, the remainder
+        * @param int|null $length The number of bytes to return. If omitted, the remainder
         *    of the file will be returned.
         *
         * @return string
index 30d1cbb..99a051d 100644 (file)
@@ -264,7 +264,7 @@ interface WatchedItemStoreInterface {
         * @since 1.31
         *
         * @param User $user
-        * @param int $unreadLimit
+        * @param int|null $unreadLimit
         *
         * @return int|bool The number of unread notifications
         *                  true if greater than or equal to $unreadLimit
index 8dfe00f..dc61519 100644 (file)
@@ -330,7 +330,7 @@ class ConverterRule {
 
        /**
         * Parse rules and flags.
-        * @param string $variant Variant language code
+        * @param string|null $variant Variant language code
         */
        public function parse( $variant = null ) {
                if ( !$variant ) {
index 28469ef..3253957 100644 (file)
@@ -1090,7 +1090,7 @@ class Language {
         * @param string $ts 14-character timestamp
         *      YYYYMMDDHHMMSS
         *      01234567890123
-        * @param DateTimeZone $zone Timezone of $ts
+        * @param DateTimeZone|null $zone Timezone of $ts
         * @param int &$ttl The amount of time (in seconds) the output may be cached for.
         * Only makes sense if $ts is the current time.
         * @todo handling of "o" format character for Iranian, Hebrew, Hijri & Thai?
@@ -4076,7 +4076,7 @@ class Language {
         * match up with it.
         *
         * @param string $str The validated block duration in English
-        * @param User $user User object to use timezone from or null for $wgUser
+        * @param User|null $user User object to use timezone from or null for $wgUser
         * @param int $now Current timestamp, for formatting relative block durations
         * @return string Somehow translated block duration
         * @see LanguageFi.php for example implementation
index ce35717..dcc2cf3 100644 (file)
@@ -211,7 +211,7 @@ class LanguageConverter {
 
        /**
         * Validate the variant
-        * @param string $variant The variant to validate
+        * @param string|null $variant The variant to validate
         * @return mixed Returns the variant if it is valid, null otherwise
         */
        public function validateVariant( $variant = null ) {
index 54ff421..b2bae18 100644 (file)
@@ -84,7 +84,7 @@ class LanguageFi extends Language {
 
        /**
         * @param string $str
-        * @param User $user User object to use timezone from or null for $wgUser
+        * @param User|null $user User object to use timezone from or null for $wgUser
         * @param int $now Current timestamp, for formatting relative block durations
         * @return string
         */
index 005737d..fb7eec7 100644 (file)
@@ -11,7 +11,8 @@
                        "Macofe",
                        "MtDu",
                        "Abdeaitali",
-                       "Reda Benkhadra"
+                       "Reda Benkhadra",
+                       "Anass Sedrati"
                ]
        },
        "tog-underline": "Ṣetter l-lyanaṫ:",
        "exif-giffilecomment": "ṫ-ṫĝliq dial milef GIF",
        "exif-intellectualgenre": "noĝ l-madda",
        "exif-scenecode": "cod mċhd IPTC",
+       "exif-orientation-1": "عادي",
        "exif-orientation-4": "mḍwwer ofoqiyyen",
        "exif-orientation-8": "mḍwwer 90° <abbr title=\"Ĝks (ṫ-ṫijah) Ĝaqarib s-Saĝa\">ĜĜS</abbr>",
        "exif-componentsconfiguration-0": "ma kayn-ċ",
index ae9c950..597499a 100644 (file)
        "file-deleted-duplicate": "Ідэнтычны файл ([[:$1]]) ужо раней выдаляўся. Вам трэба паглядзець гісторыю выдаленьняў гэтага файлу перад яго паўторнай загрузкай.",
        "file-deleted-duplicate-notitle": "Файл, ідэнтычны гэтаму файлу, раней ужо быў выдалены, а назва файла была забароненая.\nВам трэба зьвярнуцца да некага з правамі прагляду зьвестак забароненых файлаў, каб прааналізаваць сытуацыю перад тым, як загружаць файл ізноў.",
        "uploadwarning": "Папярэджаньне",
-       "uploadwarning-text": "Калі ласка, зьмяніце апісаньне файла ніжэй і паспрабуйце ізноў.",
+       "uploadwarning-text": "Калі ласка, зьмяніце апісаньне файлу ніжэй і паспрабуйце ізноў.",
        "uploadwarning-text-nostash": "Калі ласка, загрузіце файл ізноў, зьмніце апісаньне ніжэй і паспрабуйце яшчэ раз.",
        "savefile": "Захаваць файл",
-       "uploaddisabled": "Загрузка файлаў забароненая",
+       "uploaddisabled": "Загрузка файлаў забароненая.",
        "copyuploaddisabled": "Загрузка праз URL-адрас адключаная.",
        "uploaddisabledtext": "Загрузка файлаў забароненая.",
        "php-uploaddisabledtext": "Загрузка файлаў была адключаная ў парамэтрах канфігурацыі PHP. Калі ласка, праверце значэньне парамэтра «file_uploads».",
index f27a9cd..ad23eff 100644 (file)
        "recentchanges-label-minor": "این یک ویرایش جزئی است",
        "recentchanges-label-bot": "این ویرایش را یک ربات انجام داده است",
        "recentchanges-label-unpatrolled": "این ویرایش هنوز گشت‌زنی نشده است",
-       "recentchanges-label-plusminus": "حجم صفحه به اندازه این مقدار بایت تغییر یافته است",
+       "recentchanges-label-plusminus": "حجم صفحه به اندازه این مقدار بایت تغییر یافته است.",
        "recentchanges-legend-heading": "<strong>اختصارها:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (همچنین به [[Special:NewPages|فهرست صفحات تازه]] نگاه کنید)",
        "recentchanges-legend-plusminus": "(<em>±۱۲۳</em>)",
index 2eeb713..4ad908c 100644 (file)
        "dellogpage": "Evidencija brisanja",
        "dellogpagetext": "Dolje je popis nedavnih brisanja.\nSva vremena su prema poslužiteljevom vremenu.",
        "deletionlog": "evidencija brisanja",
+       "logentry-create-create": "$1 {{GENDER:$2|stvorio|stvorila}} je stranicu $3",
        "reverted": "Vraćeno na prijašnju inačicu",
        "deletecomment": "Razlog:",
        "deleteotherreason": "Drugi/dodatni razlog:",
index 370d9a4..01fc2fd 100644 (file)
        "excontentauthor": "чухьнахьадар: «$1», цу оагIон цаI марка воаца автор ва [[Special:Contributions/$2|$2]] ([[User talk:$2|дувцара оагIув]])",
        "delete-confirm": "$1 — дӀаяккхар",
        "delete-legend": "ДӀаяккхар",
-       "confirmdeletetext": "Оаш дIадийхад бIарчча дIадаккхар оагIон а (е сурта), цун деррига хувцара истори а. '''Дехар да''', бакъде шоай из бокъонца де безам болаш долга а, из дича хургдар кхеташ долга а, из дар укх [[{{MediaWiki:Policy-url}}|бокъонашца]] долга.",
+       "historywarning": "<strong>Теркам:</strong> Хьо дӀаяккха гӀертача оагӀон тоадара истори я $1 {{PLURAL:$1|эрш}} чулоацаш:",
+       "confirmdeletetext": "Оаш дIадийхад еррига оагIув (е сурт) дIаяккхар а, цун деррига хувцара истори дIаяккхар а. '''Дехар да''', бакъде шоай из бокъонца де безам болаш долга а, из дича хургдар кхеташ долга а, из хьадар укх [[{{MediaWiki:Policy-url}}|бокъонашца]] долга а.",
        "actioncomplete": "Кхоачашдаьд",
        "actionfailed": "Кхоачашдаьдац",
        "deletedtext": "«$1» дIаяьккхай.\nХьажа $2 тIехьара дIадаккхарий хьаязъяьрга бIаргтохаргболаш.",
        "deletecomment": "Бахьан:",
        "deleteotherreason": "Кхыдола бахьан/тIатохар:",
        "deletereasonotherlist": "Кхыдола бахьан",
+       "deleting-backlinks-warning": "'''ДӀахьалхадаккхар:''' Iа дӀайоаккхаш йолча оагIонна тӀатовжаш я [[Special:WhatLinksHere/{{FULLPAGENAME}}|кхыйола оагӀонаш]].",
        "rollbacklink": "юхаяккха",
        "rollbacklinkcount": "юхататта $1 {{PLURAL:$1|нийсдар}}",
        "rollback-success": "{{GENDER:$3|$1}} яха доакъашхочо тоадаьр юхататтад; юхайоалаяьй {{GENDER:$4|$2}} доакъашхочун эрш.",
index b095455..5f06f9b 100644 (file)
        "timezoneregion-europe": "Europa",
        "timezoneregion-indian": "Indiana Oceano",
        "timezoneregion-pacific": "Pacifico",
-       "allowemail": "Permisez e-posti de altra uzanti",
+       "allowemail": "Permisez e-posti de altra uzeri",
        "email-allow-new-users-label": "Permisez e-posti de la nova uzeri",
        "email-blacklist-label": "Impedez la sequanta uzeri sendar e-posto a me:",
        "prefs-namespaces": "Nomari",
        "prefs-help-email": "Informar vua adreso di e-posto esas fakultativa, tamen ol bezonesos se vu oblivior vua pasovorto e bezonor la sendo di nova pasovorto.",
        "prefs-help-email-others": "Vu povas anke selektar se permisos altri skribar a vu per e-posto, per ligilo en vua uzanto-pagino o diskuto-pagino.\nVua e-posto adreso ne revelesos, kande l'altri skribos a vu.",
        "prefs-help-email-required": "E-postala adreso es bezonata.",
-       "prefs-info": "Bazala informeso",
+       "prefs-info": "Bazala informo",
        "prefs-i18n": "Internacioniigo",
        "prefs-signature": "Signaturo",
        "prefs-timeoffset": "Registro dil tempo",
index 60c36a9..e630c19 100644 (file)
@@ -98,7 +98,8 @@
                        "Anwar2",
                        "Acamicamacaraca",
                        "DeRudySoulStorm",
-                       "Railfail536"
+                       "Railfail536",
+                       "Vlad5250"
                ]
        },
        "tog-underline": "Podkreślenie linków:",
        "right-browsearchive": "Przeszukiwanie usuniętych stron",
        "right-undelete": "Odtwarzanie usuniętych stron",
        "right-suppressrevision": "Podgląd, ukrywanie i odkrywanie wersji ukrytych przed wszystkimi",
-       "right-viewsuppressed": "Umożliwia zobaczenie wersji ukrytych przed każdym użytkownikiem",
+       "right-viewsuppressed": "Podgląd wersji ukrytych przed każdym użytkownikiem",
        "right-suppressionlog": "Podgląd rejestru ukrywania",
        "right-block": "Blokowanie użytkownikom możliwości edycji",
        "right-blockemail": "Blokowanie użytkownikom możliwości wysyłania wiadomości",
index 0220365..26ec459 100644 (file)
        "viewhelppage": "Ver página de ajuda",
        "categorypage": "Ver página de categoria",
        "viewtalkpage": "Ver discussão",
-       "otherlanguages": "Em outros idiomas",
+       "otherlanguages": "Noutras línguas",
        "redirectedfrom": "(Redirecionado de $1)",
        "redirectpagesub": "Página de redirecionamento",
        "redirectto": "Redireciona para:",
        "nowikiemailtext": "Este utilizador optou por não receber correio eletrónico de outros utilizadores.",
        "emailnotarget": "O nome do destinatário não existe ou é inválido.",
        "emailtarget": "Introduza o nome do destinatário",
-       "emailusername": "Nome de Utilizador:",
+       "emailusername": "Utilizador:",
        "emailusernamesubmit": "Enviar",
        "email-legend": "Enviar uma mensagem a outro utilizador da wiki {{SITENAME}}",
        "emailfrom": "De:",
index e52721f..3f61034 100644 (file)
                        "Happy13241",
                        "Vcohen",
                        "AttemptToCallNil",
-                       "Stjn"
+                       "Stjn",
+                       "Vlad5250"
                ]
        },
        "tog-underline": "Подчёркивание ссылок:",
        "pagetitle": "$1 — {{SITENAME}}",
        "pagetitle-view-mainpage": "{{SITENAME}}",
        "backlinksubtitle": "← $1",
-       "retrievedfrom": "Источник — «$1»",
+       "retrievedfrom": "Источник — $1",
        "youhavenewmessages": "{{PLURAL:$3|Вы получили}} $1 ($2).",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|Вы получили}} $1 от {{PLURAL:$3|$3 участника|$3 участников|1=другого участника}} ($2).",
        "youhavenewmessagesmanyusers": "Вы получили $1 от множества пользователей ($2).",
        "mergelog": "Журнал объединений",
        "revertmerge": "Разделить",
        "mergelogpagetext": "Ниже приведён список последних объединений историй страниц.",
-       "history-title": "$1 — история изменений",
-       "difference-title": "$1 — различия между версиями",
+       "history-title": "$1: история изменений",
+       "difference-title": "$1: различия между версиями",
        "difference-title-multipage": "Разница между страницами «$1» и «$2»",
        "difference-multipage": "(Различия между страницами)",
        "lineno": "Строка $1:",
        "userrights-irreversible-marker": "$1*",
        "userrights-no-shorten-expiry-marker": "$1#",
        "userrights-expiry-current": "Истекает $1",
-       "userrights-expiry-none": "Ð\9dикогда",
+       "userrights-expiry-none": "Ð\91еÑ\81Ñ\81Ñ\80оÑ\87но",
        "userrights-expiry": "Права истекают:",
        "userrights-expiry-existing": "$2, $3",
        "userrights-expiry-othertime": "Другое время:",
        "right-movefile": "переименование файлов",
        "right-suppressredirect": "подавление перенаправлений при переименовании страниц",
        "right-upload": "загрузка файлов",
-       "right-reupload": "запиÑ\81Ñ\8c Ñ\84айлов Ð¿Ð¾Ð²ÐµÑ\80Ñ\85 Ñ\81Ñ\83Ñ\89еÑ\81Ñ\82вÑ\83Ñ\8eÑ\89иÑ\85",
+       "right-reupload": "пеÑ\80езапиÑ\81Ñ\8c Ñ\81Ñ\83Ñ\89еÑ\81Ñ\82вÑ\83Ñ\8eÑ\89иÑ\85 Ñ\84айлов",
        "right-reupload-own": "перезапись файлов тем же участником",
        "right-reupload-shared": "подмена файлов из общих хранилищ локальными",
        "right-upload_by_url": "загрузка файлов с адреса URL",
        "right-purge": "очистка кэша страниц без подтверждения",
        "right-autoconfirmed": "обход ограничений скорости на IP-адрес",
        "right-bot": "автоматический процесс",
-       "right-nominornewtalk": "малые правки на СО участников не создают для них уведомление о новом сообщении",
+       "right-nominornewtalk": "малые правки на страницах обсуждений участников не создают для них уведомление о новом сообщении",
        "right-apihighlimits": "уменьшение ограничений на выполнение API-запросов",
        "right-writeapi": "использование API для записи",
        "right-delete": "удаление страниц",
        "filerevert-success": "'''[[Media:$1|$1]]''' был возвращён к [$4 версии от $3, $2].",
        "filerevert-badversion": "Не существует предыдущей локальной версии этого файла с указанной меткой времени.",
        "filerevert-identical": "Текущая версия файла уже идентична выбранной.",
-       "filedelete": "$1 — удаление",
+       "filedelete": "$1: удаление",
        "filedelete-legend": "Удалить файл",
        "filedelete-intro": "Вы собираетесь удалить файл '''[[Media:$1|$1]]''' со всей его историей.",
        "filedelete-intro-old": "Вы удаляете версию <strong>[[Media:$1|$1]]</strong> от [$4 $3, $2].",
        "excontent": "содержимое: «$1»",
        "excontentauthor": "содержимое: «$1», единственным автором которого был [[Special:Contributions/$2|$2]] ([[User talk:$2|обсуждение]])",
        "exbeforeblank": "содержимое до очистки: «$1»",
-       "delete-confirm": "$1 — удаление",
+       "delete-confirm": "$1: удаление",
        "delete-legend": "Удаление",
        "historywarning": "<strong>Внимание:</strong> Вы собираетесь удалить страницу, у которой есть история правок, содержащая $1 {{PLURAL:$1|версию|версии|версий}}:",
        "historyaction-submit": "Показать",
        "anoncontribs": "Вклад",
        "contribsub2": "Вклад {{GENDER:$3|$1}} ($2)",
        "contributions-userdoesnotexist": "Не зарегистрировано учётной записи «$1».",
-       "nocontribs": "Ð\98зменений, Ñ\81ооÑ\82веÑ\82Ñ\81Ñ\82вÑ\83Ñ\8eÑ\89иÑ\85 Ð·Ð°Ð´Ð°Ð½Ð½Ñ\8bм Ñ\83Ñ\81ловиÑ\8fм, Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾ Ð½Ðµ Ð±Ñ\8bло.",
+       "nocontribs": "Ð\98зменений, Ñ\81ооÑ\82веÑ\82Ñ\81Ñ\82вÑ\83Ñ\8eÑ\89иÑ\85 Ð·Ð°Ð´Ð°Ð½Ð½Ñ\8bм Ñ\83Ñ\81ловиÑ\8fм, Ð½Ðµ Ð½Ð°Ð¹Ð´ÐµÐ½о.",
        "uctop": "(текущая)",
        "month": "С месяца (и ранее):",
        "year": "С года (и ранее):",
index f1ff7f0..1592aeb 100644 (file)
        "table_pager_limit_submit": "Spustiť",
        "table_pager_empty": "Bez výsledkov",
        "autosumm-blank": "Odstránený obsah stránky",
-       "autosumm-replace": "Nahrádzam stránku textom „$1“",
+       "autosumm-replace": "Obsah stránky nahradený textom „$1“",
        "autoredircomment": "Presmerovanie na [[$1]]",
+       "autosumm-removed-redirect": "Zrušené presmerovanie na [[$1]]",
+       "autosumm-changed-redirect-target": "Cieľ presmerovania zmenený z [[$1]] na [[$2]]",
        "autosumm-new": "Vytvorená stránka „$1“",
        "autosumm-newblank": "Vytvorená prázdna stránka",
        "lag-warn-normal": "Úpravy za {{PLURAL:$1|poslednú sekundu|posledné $1 sekundy|posledných $1 sekúnd}} nemusia byť v tomto zozname zobrazené.",
index 416a168..9d131fd 100644 (file)
        "recentchangesdays": "ఇటీవలి మార్పులు లో చూపించవలసిన రోజులు:",
        "recentchangesdays-max": "గరిష్ఠంగా $1 {{PLURAL:$1|రోజు|రోజులు}}",
        "recentchangescount": "అప్రమేయంగా చూపించాల్సిన దిద్దుబాట్ల సంఖ్య:",
-       "prefs-help-recentchangescount": "à°\87ది à°\87à°\9fà±\80వలి à°®à°¾à°°à±\8dà°ªà±\81à°²à±\81, à°ªà±\87à°\9cà±\80 à°\9aà°°à°¿à°¤à±\8dà°°à°²à±\81, à°®à°°à°¿à°¯à±\81 à°\9aà°¿à°\9fà±\8dà°\9fాలà°\95à±\81 à°µà°°à±\8dతిసà±\8dà°¤à±\81à°\82ది.",
-       "prefs-help-watchlist-token2": "మీ వీక్షణజాబితా యొక్క జాలవడ్డింపుకు చెందిన రహస్య తాళమిది.\nఈ తాళం తెలిసిన ఎవరైనా మీ వీక్షణజాబితాను చదవగలుగుతారు. అందుచేత దీన్ని ఎవరికీ ఇవ్వకండి.\n[[Special:ResetTokens|దాన్ని మార్చాలంటే ఇక్కడ నొక్కండి]].",
+       "prefs-help-recentchangescount": "à°\97à°°à°¿à°·à±\8dà°  à°¸à°\82à°\96à±\8dà°¯: 1000",
+       "prefs-help-watchlist-token2": "మీ వీక్షణజాబితా యొక్క జాలవడ్డింపుకు చెందిన రహస్య తాళమిది.\nఈ తాళం తెలిసిన ఎవరైనా మీ వీక్షణజాబితాను చదవగలుగుతారు. అందుచేత దీన్ని ఎవరికీ ఇవ్వకండి.\nఅవసరమైతే [[Special:ResetTokens|దాన్ని మార్చుకోవచ్చు]].",
        "savedprefs": "మీ అభిరుచులను భద్రపరిచాం.",
        "savedrights": "{{GENDER:$1|$1}} వాడుకరి గుంపులు భద్రమయ్యాయి.",
        "timezonelegend": "కాల మండలం:",
        "right-siteadmin": "డేటాబేసును లాక్, అన్‌లాక్ చెయ్యి",
        "right-override-export-depth": "5 లింకుల లోతు వరకు ఉన్న పేజీలతో సహా, పేజీలను ఎగుమతి చెయ్యి",
        "right-sendemail": "ఇతర వాడుకరులకు ఈ-మెయిలు పంపించడం",
-       "right-managechangetags": "డేటాబేసులో [[Special:Tags|ట్యాగుల]]ను సృష్టించడం, తొలగించడం",
+       "right-managechangetags": "[[Special:Tags|ట్యాగుల]]ను సృష్టించడం, (అ)చేతనం చెయ్యడం",
        "right-applychangetags": "తన మార్పులతో [[Special:Tags|ట్యాగుల]]ను ఆపాదించడం",
        "right-changetags": "విడి కూర్పులకు, చిట్టా పద్దులకు ఏవైనా [[Special:Tags|ట్యాగుల]]ను చేర్చడం, తొలగించడం",
-       "right-deletechangetags": "[[ప్రత్యేక:Tags|ట్యాగులను]] డేటాబేసు నుండి తొలగించు",
+       "right-deletechangetags": "[[Special:Tags|ట్యాగులను]] డేటాబేసు నుండి తొలగించు",
        "grant-generic": "\"$1\" హక్కుల కట్ట",
        "grant-group-email": "ఈమెయిలు పంపించడం",
        "grant-group-administration": "నిర్వాహక చర్యలు చేపట్టడం",
        "pageswithprop-prophidden-binary": "binary లక్షణం విలువ దాచబడింది ($1)",
        "doubleredirects": "జంట దారిమార్పులు",
        "doubleredirectstext": "ఇతర దారిమార్పు పుటలకి తీసుకెళ్ళే దారిమార్పులని ఈ పుట చూపిస్తుంది.\nప్రతీ వరుసలో మొదటి మరియు రెండవ దారిమార్పులకు లంకెలు, ఆలానే రెండవ దారిమార్పు పుట యొక్క లక్ష్యం ఉన్నాయి. సాధారణంగా ఈ రెండవ దారిమార్పు యొక్క లక్ష్యమే \"అసలైనది\", అదే మొదటి దారిమార్పు యొక్క లక్ష్యంగా ఉండాలి.\n<del>కొట్టివేయబడిన</del> పద్దులు పరిష్కరించబడ్డవి.",
-       "double-redirect-fixed-move": "[[$1]]ని తరలించారు, అది ప్రస్తుతం [[$2]]కి దారిమార్పు.",
+       "double-redirect-fixed-move": "[[$1]]ని తరలించారు.\nదాన్ని ఆటోమేటిగ్గా తాజాకరించాం. ప్రస్తుతం అది [[$2]]కి దారిమార్పు చేస్తోంది.",
        "double-redirect-fixed-maintenance": "[[$1]] కు జమిలి దారిమార్పును [[$2]] కు అప్రమేయంగా సరిచేస్తున్నాం.",
        "double-redirect-fixer": "దారిమార్పు సరిద్దువారు",
        "brokenredirects": "తెగిపోయిన దారిమార్పులు",
index 45c0836..e5e01ba 100644 (file)
        "resetpass-temp-password": "Geçici parola:",
        "resetpass-abort-generic": "Parola değişikliği bir uzantı tarafından iptal edildi.",
        "resetpass-expired": "Parolanızın süresi bitti. Lütfen, giriş için yeni bir parola oluşturun.",
-       "resetpass-expired-soft": "Parolanızın süresi bitti ve değiştirilmesi gerekiyor. Lütfen, yeni bir parola seçin veya daha sonra oluşturmak için \"{{int:authprovider-resetpass-skip-label}}\" butonuna tıklayın.",
-       "resetpass-validity-soft": "Parolanız geçerli değil: $1\n\nLütfen yeni bir şifre belirleyin ya da daha sonra sıfırlamak için \"{{int:authprovider-resetpass-skip-label}}\" bağlantısını tıklayın.",
+       "resetpass-expired-soft": "Parolanızın süresi bitti ve değiştirilmesi gerekiyor. Lütfen, yeni bir parola seçin veya daha sonra değiştirmek için \"{{int:authprovider-resetpass-skip-label}}\" düğmesine tıklayın.",
+       "resetpass-validity-soft": "Parolanız geçerli değil: $1\n\nLütfen yeni bir şifre belirleyin ya da daha sonra değiştirmek için \"{{int:authprovider-resetpass-skip-label}}\" bağlantısını tıklayın.",
        "passwordreset": "Parola sıfırlama",
        "passwordreset-text-one": "Parolanızı sıfırlamak için bu formu doldurun.",
        "passwordreset-text-many": "{{PLURAL:$1|E-posta ile geçici bir parola almak için alanlardan birini doldurun.}}",
        "stub-threshold-disabled": "Devre dışı",
        "recentchangesdays": "Son değişikliklerde gösterilecek günler:",
        "recentchangesdays-max": "(en fazla $1 {{PLURAL:$1|gün|gün}})",
-       "recentchangescount": "Varsayılan olarak gösterilecek değişiklik sayısı:",
-       "prefs-help-recentchangescount": "Bu, son değişiklikleri, sayfa geçmişlerini ve günlükleri içerir.",
-       "prefs-help-watchlist-token2": "Bu izleme listenizin gizli anahtarıdır. Anahtarı bilen herkes izleme listenizi görebilir. Bu nedenle kimseyle paylaşmayın. [[Special:ResetTokens|Bu anahtarı sıfırlamak isterseniz buraya tıklayın]].",
+       "recentchangescount": "Son değişiliklerde, sayfa geçmişlerinde ve günlüklerde varsayılan olarak gösterilecek değişiklik sayısı:",
+       "prefs-help-recentchangescount": "Azami sayı: 1000",
+       "prefs-help-watchlist-token2": "Bu izleme listenizin gizli anahtarıdır.\nAnahtarı bilen herkes izleme listenizi görebilir, bu nedenle kimseyle paylaşmayın.\nEğer isterseniz, [[Special:ResetTokens|sıfırlayabilirsiniz]].",
        "savedprefs": "Tercihleriniz kaydedildi.",
        "savedrights": "{{GENDER:$1|$1}} için kullanıcı grupları kaydedildi.",
        "timezonelegend": "Zaman dilimi:",
        "prefs-files": "Dosyalar",
        "prefs-custom-css": "Özel CSS",
        "prefs-custom-js": "Özel JS",
-       "prefs-common-config": "Tüm temalar için paylaşılan CSS/JS:",
+       "prefs-common-config": "Tüm temalar için paylaşılan CSS/JSON/Javascript:",
        "prefs-reset-intro": "Bu sayfayı tercihlerinizi site varsayılanına döndürmek için kullanabilirsiniz. Bu geri alınamaz.",
        "prefs-emailconfirm-label": "E-posta doğrulaması:",
        "youremail": "E-posta:",
        "userrights-groupsmember": "İçinde olduğu gruplar:",
        "userrights-groupsmember-auto": "Saklı olarak içinde olduğu gruplar:",
        "userrights-groupsmember-type": "$1",
-       "userrights-groups-help": "Bu kullanıcının içinde olduğu grupları değiştirebilirsiniz:\n* Seçili bir kutu, kullanıcının o gruba dahil olduğunu anlatır.\n* Seçilmemiş bir kutu, kullanıcının o gruba dahil olmadığını anlatır.\n* *, grubu bir kez ekledikten sonra kaldıramayacağınızı veya tam tersi kaldırdıktan sonra ekleyemeyeceğiniz belirtir.\n* #, grubun sona erme zamanını yalnızca öne çekebileceğinizi, ileri alamayacağınızı belirtir.",
+       "userrights-groups-help": "Bu kullanıcının içinde olduğu grupları değiştirebilirsiniz:\n* Seçili bir kutu, kullanıcının o gruba dahil olduğunu anlatır.\n* Seçilmemiş bir kutu, kullanıcının o gruba dahil olmadığını anlatır.\n* *, grubu bir kez ekledikten sonra kaldıramayacağınızı veya tam tersi kaldırdıktan sonra ekleyemeyeceğiniz belirtir.\n* #, grup üyeliğinin sona erme zamanını yalnızca öne çekebileceğinizi, ileri alamayacağınızı belirtir.",
        "userrights-reason": "Neden:",
        "userrights-no-interwiki": "Diğer vikilerdeki kullanıcıların izinlerini değiştirmeye yetkiniz yok.",
        "userrights-nodatabase": "$1 veritabanı mevcut veya bölgesel değil",
        "right-siteadmin": "Veritabanını kilitle ve kilidi aç",
        "right-override-export-depth": "Sayfaları, derinlik 5'e kadar bağlantılı sayfalarla beraber, dışa aktar",
        "right-sendemail": "Diğer kullanıcılara e-posta gönder",
-       "right-managechangetags": "Veritabanında [[Special:Tags|etiket]] oluşturma veya silme",
+       "right-managechangetags": "[[Special:Tags|Etiket]] oluşturma ve (de)aktive etme",
        "right-applychangetags": "Değişiklikleriyle beraber [[Special:Tags|etiketleri]] uygula",
        "right-changetags": "Tekil sürümler ve günlük kayıtlarına rastgele [[Special:Tags|etiket]] ekleme veya çıkarma",
        "grant-group-email": "E-posta gönder",
        "grant-group-other": "Çeşitli aktivite",
        "grant-createeditmovepage": "Sayfaları oluşturma, düzenleme ve taşıma",
-       "grant-editmycssjs": "Kullanıcı CSS/JavaScript'ini düzenle",
+       "grant-editmycssjs": "Kullanıcı CSS/JSON/JavaScript'ini düzenle",
        "grant-editmyoptions": "Kullanıcı tercihlerini Düzenle",
        "grant-editmywatchlist": "İzleme listeni düzenle",
        "grant-editprotected": "Korumalı sayfaları Düzenle",
        "rcfilters-savedqueries-rename": "Yeniden adlandır",
        "rcfilters-savedqueries-setdefault": "Varsayılan olarak belirle",
        "rcfilters-savedqueries-unsetdefault": "Varsayılan olmaktan çıkar",
-       "rcfilters-savedqueries-remove": "Kaldır",
+       "rcfilters-savedqueries-remove": "Sil",
        "rcfilters-savedqueries-new-name-label": "Ad",
        "rcfilters-savedqueries-new-name-placeholder": "Süzgecin amacını tanımlayın",
        "rcfilters-savedqueries-apply-label": "Süzgeç oluştur",
        "rcfilters-empty-filter": "Etkin süzgeç bulunmuyor. Tüm katkıları gösteriliyor.",
        "rcfilters-filterlist-title": "Süzgeçler",
        "rcfilters-filterlist-whatsthis": "Bunlar nasıl çalışır?",
-       "rcfilters-filterlist-feedbacklink": "Bu (yeni) süzgeç araçları konusunda ne düşündüğünüzü bize bildirin",
+       "rcfilters-filterlist-feedbacklink": "Bu süzgeç araçları konusunda ne düşündüğünüzü bize bildirin",
        "rcfilters-highlightbutton-title": "Sonuçları vurgula",
        "rcfilters-highlightmenu-title": "Bir renk seçin",
        "rcfilters-highlightmenu-help": "Bu özelliği vurgulamak için bir renk seçin",
        "rcfilters-filterlist-noresults": "Süzgeç bulunamadı",
        "rcfilters-noresults-conflict": "Arama kriterleri çelişkili olduğu için hiçbir sonuç bulunamadı",
-       "rcfilters-filtergroup-authorship": "Düzenleme sahipliği",
+       "rcfilters-filtergroup-authorship": "Katkı sahipliği",
        "rcfilters-filter-editsbyself-label": "Senin değişiklikleriniz",
        "rcfilters-filter-editsbyself-description": "Kendi katkılarınız.",
        "rcfilters-filter-editsbyother-label": "Başkalarının düzenlemeleri",
        "rcfilters-filter-editsbyother-description": "Kendi düzenlemeleriniz hariç bütün düzenlemeler.",
-       "rcfilters-filtergroup-userExpLevel": "Deneyim düzeyi (yalnızca kayıtlı kullanıcılar için)",
+       "rcfilters-filtergroup-userExpLevel": "Kullanıcı kaydı ve deneyim",
        "rcfilters-filter-user-experience-level-registered-label": "Kayıtlı",
        "rcfilters-filter-user-experience-level-registered-description": "Oturum açmış editörler.",
        "rcfilters-filter-user-experience-level-unregistered-label": "Kayıtlı olmayan",
        "rcfilters-filter-user-experience-level-newcomer-label": "Yeni gelenler",
        "rcfilters-filter-user-experience-level-newcomer-description": "10'dan az düzenlemesi veya 4 günden az etkinliği olan kayıtlı kullanıcılar.",
        "rcfilters-filter-user-experience-level-learner-label": "Öğreniciler",
-       "rcfilters-filter-user-experience-level-learner-description": "\"Yeni gelenler\"den daha fazla gün boyunca etkinlik ve daha fazla düzenleme, ancak \"Deneyimli kullanıcılar\"dan daha az etkinlik ve düzenleme.",
+       "rcfilters-filter-user-experience-level-learner-description": "Deneyimi \"Yeni gelenler\" ve \"Deneyimli kullanıcılar\" arasındaki editörler.",
        "rcfilters-filter-user-experience-level-experienced-label": "Deneyimli kullanıcılar",
-       "rcfilters-filter-user-experience-level-experienced-description": "30'dan fazla gün etkinlik ve 500'den fazla düzenleme.",
+       "rcfilters-filter-user-experience-level-experienced-description": "30'dan fazla gün etkinliğe ve 500'den fazla düzenlemeye sahip kayıtlı editörler.",
        "rcfilters-filtergroup-automated": "Otomatikleştirilmiş katkılar",
        "rcfilters-filter-bots-label": "Bot",
        "rcfilters-filter-bots-description": "Otomatikleştirilmiş araçlar tarafından yapılan düzenlemeler.",
index 4dce507..867af79 100644 (file)
        "anoncontribs": "Внесок",
        "contribsub2": "Для {{GENDER:$3|$1}} ($2)",
        "contributions-userdoesnotexist": "Обліковий запис користувача  «$1» не зареєстровано.",
-       "nocontribs": "Редагувань, що задовольняють заданим умовам не знайдено.",
+       "nocontribs": "Редагувань, що задовольняють заданим умовам, не знайдено.",
        "uctop": "(поточна)",
        "month": "До місяця (включно):",
        "year": "До року (включно):",
        "semicolon-separator": ";&#32;",
        "comma-separator": ",&#32;",
        "colon-separator": ":&#32;",
-       "pipe-separator": "&#32;&#32;",
+       "pipe-separator": "&#32;|&#32;",
        "word-separator": "&#32;",
        "ellipsis": "...",
        "percent": "$1%",
index af79df3..f84bf57 100644 (file)
        "listingcontinuesabbrev": "جاری۔",
        "index-category": "فہرست شدہ صفحات",
        "noindex-category": "غیر فہرست شدہ صفحات",
-       "broken-file-category": "فائل کے شکستہ روابط کے حامل صفحات",
+       "broken-file-category": "فائلوں کے شکستہ روابط پر مشتمل صفحات",
        "categoryviewer-pagedlinks": "($1) ($2)",
        "about": "تعارف",
        "article": "صفحہ مواد",
        "userinvalidconfigtitle": "<strong>انتباہ:</strong> یہاں «$1» نام سے کوئی پوشاک موجود نہیں۔ شخصی .css اور .js کے صفحات اپنے عنوان میں چھوٹے حروف استعمال کرتے ہیں، مثلاً {{ns:user}}:Foo/Vector.css کی بجائے {{ns:user}}:Foo/vector.css",
        "updated": "(اپ ڈیٹڈ)",
        "note": "'''نوٹ:'''",
-       "previewnote": "'''یاد رکھیں، یہ صرف نمائش ہے ۔آپ کی ترامیم ابھی محفوظ نہیں کی گئیں۔'''",
+       "previewnote": "<strong>یاد رکھیں، یہ صرف نمائش ہے۔</strong>\nآپ کی ترامیم ابھی محفوظ نہیں کی گئیں!",
        "continue-editing": "خانہ ترمیم میں جائیں",
        "previewconflict": "اس نمائش میں خانہ ترمیم کے اوپر موجود متن جس انداز میں ظاہر ہو رہا ہے، محفوظ کرنے کے بعد اسی طرح نظر آئے گا۔",
        "session_fail_preview": "معذرت! نشست کے مواد میں خامی کی وجہ سے آپ کی  ترمیم مکمل نہیں ہو سکی۔\n\nشاید آپ اپنے کھاتے سے خارج ہو گئے ہیں۔ <strong>براہ کرم اس بات کی تصدیق کر لیں کہ آپ داخل ہیں اور دوبارہ کوشش کریں۔</strong> اگر آپ کو پھر بھی مشکل پیش آرہی ہو تو ایک بار [[Special:UserLogout|خارج ہو کر]] واپس داخل ہو جائیں اور اپنے براؤزر کو جانچ لیں کہ آیا وہ اس سائٹ کی کوکیز اخذ کر رہا ہے یا نہیں۔",
index fad61bf..30a5434 100644 (file)
        "nonwrite-api-promise-error": "“Promise-Non-Write-API-Action”HTTP报头已发送,但请求是一个API编写模块。",
        "internalerror": "内部错误",
        "internalerror_info": "内部错误:$1",
-       "internalerror-fatal-exception": "类型“$1”的致命错误",
+       "internalerror-fatal-exception": "类型“$1”的致命例外",
        "filecopyerror": "无法将文件“$1”复制到“$2”。",
        "filerenameerror": "无法将文件“$1”重命名为“$2”。",
        "filedeleteerror": "无法删除文件“$1”。",
        "resetpass-submit-loggedin": "更改密码",
        "resetpass-submit-cancel": "取消",
        "resetpass-wrong-oldpass": "临时密码或当前密码无效。您可能已经更改了您的密码,或者请求了新的临时密码。",
-       "resetpass-recycled": "请将您的密码更改为除当前密码以外的其他密码。",
+       "resetpass-recycled": "请将您的密码更改成与当前密码不同的密码。",
        "resetpass-temp-emailed": "您使用了通过电子邮件发送的临时密码登录。要完成登录,您必须在此设置一个新密码:",
        "resetpass-temp-password": "临时密码:",
        "resetpass-abort-generic": "密码更改已经被扩展程序中止。",
        "exif-photometricinterpretation-1": "黑白(黑为0)",
        "exif-photometricinterpretation-4": "透明遮罩",
        "exif-photometricinterpretation-5": "分隔(可能是CMYK)",
+       "exif-photometricinterpretation-9": "CIE L*a*b*(ICC编码)",
+       "exif-photometricinterpretation-10": "CIE L*a*b*(ITU编码)",
        "exif-photometricinterpretation-32803": "色彩滤镜矩阵",
+       "exif-photometricinterpretation-34892": "线性原始",
        "exif-unknowndate": "未知日期",
        "exif-orientation-1": "标准",
        "exif-orientation-2": "水平翻转",
index 866f959..c4a7594 100644 (file)
@@ -253,7 +253,7 @@ abstract class Maintenance {
         * this will return an array.
         *
         * @param string $name The name of the param
-        * @param mixed $default Anything you want, default null
+        * @param mixed|null $default Anything you want, default null
         * @return mixed
         */
        protected function getOption( $name, $default = null ) {
@@ -309,7 +309,7 @@ abstract class Maintenance {
        /**
         * Get an argument.
         * @param int $argId The integer value (from zero) for the arg
-        * @param mixed $default The default if it doesn't exist
+        * @param mixed|null $default The default if it doesn't exist
         * @return mixed
         */
        protected function getArg( $argId = 0, $default = null ) {
@@ -359,7 +359,7 @@ abstract class Maintenance {
 
        /**
         * Return input from stdin.
-        * @param int $len The number of bytes to read. If null, just return the handle.
+        * @param int|null $len The number of bytes to read. If null, just return the handle.
         *   Maintenance::STDIN_ALL returns the full length
         * @return mixed
         */
@@ -388,7 +388,7 @@ abstract class Maintenance {
         * Throw some output to the user. Scripts can call this with no fears,
         * as we handle all --quiet stuff here
         * @param string $out The text to show to the user
-        * @param mixed $channel Unique identifier for the channel. See function outputChanneled.
+        * @param mixed|null $channel Unique identifier for the channel. See function outputChanneled.
         */
        protected function output( $out, $channel = null ) {
                // This is sometimes called very early, before Setup.php is included.
@@ -464,7 +464,7 @@ abstract class Maintenance {
         * same channel are concatenated, but any intervening messages in another
         * channel start a new line.
         * @param string $msg The message without trailing newline
-        * @param string $channel Channel identifier or null for no
+        * @param string|null $channel Channel identifier or null for no
         *     channel. Channel comparison uses ===.
         */
        public function outputChanneled( $msg, $channel = null ) {
@@ -661,7 +661,7 @@ abstract class Maintenance {
         * Run a child maintenance script. Pass all of the current arguments
         * to it.
         * @param string $maintClass A name of a child maintenance class
-        * @param string $classFile Full path of where the child is
+        * @param string|null $classFile Full path of where the child is
         * @return Maintenance
         */
        public function runChild( $maintClass, $classFile = null ) {
@@ -922,9 +922,9 @@ abstract class Maintenance {
         * $mOptions becomes an array with keys set to the option names
         * $mArgs becomes a zero-based array containing the non-option arguments
         *
-        * @param string $self The name of the script, if any
-        * @param array $opts An array of options, in form of key=>value
-        * @param array $args An array of command line arguments
+        * @param string|null $self The name of the script, if any
+        * @param array|null $opts An array of options, in form of key=>value
+        * @param array|null $args An array of command line arguments
         */
        public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) {
                # If we were given opts or args, set those and return early
index 21d9bb1..6eeb81b 100644 (file)
@@ -76,7 +76,7 @@ class BackupDumper extends Maintenance {
        private $stubText = false; // include rev_text_id instead of text; for 2-pass dump
 
        /**
-        * @param array $args For backward compatibility
+        * @param array|null $args For backward compatibility
         */
        function __construct( $args = null ) {
                parent::__construct();
index 59a6b51..95dd4da 100644 (file)
@@ -100,7 +100,7 @@ class TextPassDumper extends BackupDumper {
        protected $db;
 
        /**
-        * @param array $args For backward compatibility
+        * @param array|null $args For backward compatibility
         */
        function __construct( $args = null ) {
                parent::__construct();
index eee534f..b550cc2 100644 (file)
@@ -72,9 +72,10 @@ class PopulateContentTables extends Maintenance {
 
                $t0 = microtime( true );
 
-               if ( $wgMultiContentRevisionSchemaMigrationStage < MIGRATION_WRITE_BOTH ) {
+               if ( ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) === 0 ) {
                        $this->writeln(
-                               "...cannot update while \$wgMultiContentRevisionSchemaMigrationStage < MIGRATION_WRITE_BOTH"
+                               '...cannot update while \$wgMultiContentRevisionSchemaMigrationStage '
+                               . 'does not have the SCHEMA_COMPAT_WRITE_NEW bit set.'
                        );
                        return false;
                }
index 45533aa..070fad8 100644 (file)
   },
   "devDependencies": {
     "deepmerge": "1.3.2",
-    "eslint": "4.9.0",
-    "eslint-config-wikimedia": "0.5.0",
+    "eslint": "5.0.1",
+    "eslint-config-wikimedia": "0.6.0",
     "eslint-plugin-qunit": "3.2.1",
     "grunt": "1.0.3",
     "grunt-banana-checker": "0.6.0",
     "grunt-contrib-copy": "1.0.0",
     "grunt-contrib-watch": "1.1.0",
-    "grunt-eslint": "20.1.0",
+    "grunt-eslint": "21.0.0",
     "grunt-jsonlint": "1.1.0",
     "grunt-karma": "2.0.0",
     "grunt-stylelint": "0.10.0",
index b724306..c41fcd6 100644 (file)
@@ -84,8 +84,7 @@ return [
         *     The highest level, this stylesheet contains extra common styles for classes like
         *     .firstHeading, #contentSub, et cetera which are not outputted by MediaWiki but are common
         *     to skins like MonoBook, Vector, etc... Essentially this level is for styles that are
-        *     common to MonoBook clones. And since practically every skin that currently exists within
-        *     core is a MonoBook clone, all our core skins currently use this level.
+        *     common to MonoBook clones.
         *
         * These modules are typically loaded by addModuleStyles(), which has absolutely no concept of
         * dependency management. As a result they contain duplicate stylesheet references instead of
index 552c0c3..64d394c 100644 (file)
                if ( ts.collationTable ) {
                        // Build array of key names
                        for ( key in ts.collationTable ) {
-                               // Check hasOwn to be safe
-                               if ( ts.collationTable.hasOwnProperty( key ) ) {
-                                       keys.push( mw.RegExp.escape( key ) );
-                               }
+                               keys.push( mw.RegExp.escape( key ) );
                        }
                        if ( keys.length ) {
                                ts.collationRegex = new RegExp( keys.join( '|' ), 'ig' );
index 2b76187..c02af98 100644 (file)
                                tiff: 'tif',
                                ogv: 'ogg'
                        };
-               if ( squish.hasOwnProperty( lower ) ) {
+               if ( Object.prototype.hasOwnProperty.call( squish, lower ) ) {
                        return squish[ lower ];
                } else if ( /^[0-9a-z]+$/.test( lower ) ) {
                        return lower;
index 7467d50..eb7cff0 100644 (file)
                                        // Copy data over from existing URI object
                                        for ( prop in uri ) {
                                                // Only copy direct properties, not inherited ones
-                                               if ( uri.hasOwnProperty( prop ) ) {
+                                               if ( Object.prototype.hasOwnProperty.call( uri, prop ) ) {
                                                        // Deep copy object properties
                                                        if ( Array.isArray( uri[ prop ] ) || $.isPlainObject( uri[ prop ] ) ) {
                                                                this[ prop ] = $.extend( true, {}, uri[ prop ] );
index 29bd59a..f343321 100644 (file)
@@ -40,9 +40,7 @@
        function getFirstKey( obj ) {
                var key;
                for ( key in obj ) {
-                       if ( obj.hasOwnProperty( key ) ) {
-                               return key;
-                       }
+                       return key;
                }
        }
 
index 3f5a5db..37c0fac 100644 (file)
                        };
 
                        for ( id in panes ) {
-                               if ( !panes.hasOwnProperty( id ) ) {
-                                       continue;
-                               }
-
                                $( '<div>' )
                                        .prop( {
                                                className: 'mw-debug-pane',
                                        .appendTo( $table );
 
                                for ( key in data ) {
-                                       if ( !data.hasOwnProperty( key ) ) {
-                                               continue;
-                                       }
-
                                        $( '<tr>' )
                                                .append( $( '<th>' ).text( key ) )
                                                .append( $( '<td>' ).text( data[ key ] ) )
index 4f9e43a..437800a 100644 (file)
                getAst: function ( key ) {
                        var wikiText;
 
-                       if ( !this.astCache.hasOwnProperty( key ) ) {
+                       if ( !Object.prototype.hasOwnProperty.call( this.astCache, key ) ) {
                                wikiText = this.settings.messages.get( key );
                                if ( typeof wikiText !== 'string' ) {
                                        wikiText = '⧼' + key + '⧽';
                        return oldParser.apply( this );
                }
 
-               if ( !this.map.hasOwnProperty( this.format ) ) {
+               if ( !Object.prototype.hasOwnProperty.call( this.map, this.format ) ) {
                        this.map[ this.format ] = mw.jqueryMsg.getMessageFunction( {
                                messages: this.map,
                                // For format 'escaped', escaping part is handled by mediawiki.js
index 267210c..f4194d3 100644 (file)
                for ( i = 0; i < arguments.length; i++ ) {
                        table = arguments[ i ];
                        for ( key in table ) {
-                               if ( table.hasOwnProperty( key ) ) {
-                                       // The thousand separator should be deleted
-                                       flipped[ table[ key ] ] = key === ',' ? '' : key;
-                               }
+                               // The thousand separator should be deleted
+                               flipped[ table[ key ] ] = key === ',' ? '' : key;
                        }
                }
 
                        if ( transformTable ) {
                                convertedNumber = '';
                                for ( i = 0; i < numberString.length; i++ ) {
-                                       if ( transformTable.hasOwnProperty( numberString[ i ] ) ) {
+                                       if ( Object.prototype.hasOwnProperty.call( transformTable, numberString[ i ] ) ) {
                                                convertedNumber += transformTable[ numberString[ i ] ];
                                        } else {
                                                convertedNumber += numberString[ i ];
index 5b41876..2002b9f 100644 (file)
 
                actionPaths = mw.config.get( 'wgActionPaths' );
                for ( key in actionPaths ) {
-                       if ( actionPaths.hasOwnProperty( key ) ) {
-                               parts = actionPaths[ key ].split( '$1' );
-                               parts = parts.map( mw.RegExp.escape );
-                               m = new RegExp( parts.join( '(.+)' ) ).exec( url );
-                               if ( m && m[ 1 ] ) {
-                                       return key;
-                               }
-
+                       parts = actionPaths[ key ].split( '$1' );
+                       parts = parts.map( mw.RegExp.escape );
+                       m = new RegExp( parts.join( '(.+)' ) ).exec( url );
+                       if ( m && m[ 1 ] ) {
+                               return key;
                        }
                }
 
index f936658..7c0d232 100644 (file)
                        var apiPromise,
                                deferred = $.Deferred();
 
-                       if ( moduleInfoCache.hasOwnProperty( module ) ) {
+                       if ( Object.prototype.hasOwnProperty.call( moduleInfoCache, module ) ) {
                                return deferred
                                        .resolve( moduleInfoCache[ module ] )
                                        .promise( { abort: function () {} } );
 
                                subpages = page.getSubpages();
                                for ( i = 0; i < subpages.length; i++ ) {
-                                       if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+                                       if ( Object.prototype.hasOwnProperty.call( pages, subpages[ i ].key ) ) {
                                                checkPages.push( pages[ subpages[ i ].key ] );
                                        }
                                }
                                        if ( page.getSubpages ) {
                                                subpages = page.getSubpages();
                                                for ( j = 0; j < subpages.length; j++ ) {
-                                                       if ( !pages.hasOwnProperty( subpages[ j ].key ) ) {
+                                                       if ( !Object.prototype.hasOwnProperty.call( pages, subpages[ j ].key ) ) {
                                                                subpages[ j ].indentLevel = page.indentLevel + 1;
                                                                pages[ subpages[ j ].key ] = new ApiSandbox.PageLayout( subpages[ j ] );
                                                        }
                                page.getQueryParams( params, displayParams );
                                subpages = page.getSubpages();
                                for ( i = 0; i < subpages.length; i++ ) {
-                                       if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+                                       if ( Object.prototype.hasOwnProperty.call( pages, subpages[ i ].key ) ) {
                                                checkPages.push( pages[ subpages[ i ].key ] );
                                        }
                                }
 
                                // Force a 'fm' format with wrappedhtml=1, if available
                                if ( params.format !== undefined ) {
-                                       if ( availableFormats.hasOwnProperty( params.format + 'fm' ) ) {
+                                       if ( Object.prototype.hasOwnProperty.call( availableFormats, params.format + 'fm' ) ) {
                                                params.format = params.format + 'fm';
                                        }
                                        if ( params.format.substr( -2 ) === 'fm' ) {
 
                                subpages = page.getSubpages();
                                for ( i = 0; i < subpages.length; i++ ) {
-                                       if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+                                       if ( Object.prototype.hasOwnProperty.call( pages, subpages[ i ].key ) ) {
                                                checkPages.push( pages[ subpages[ i ].key ] );
                                        }
                                }
                                page.apiCheckValid();
                                subpages = page.getSubpages();
                                for ( i = 0; i < subpages.length; i++ ) {
-                                       if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+                                       if ( Object.prototype.hasOwnProperty.call( pages, subpages[ i ].key ) ) {
                                                checkPages.push( pages[ subpages[ i ].key ] );
                                        }
                                }
                                                }
                                        }
                                        if ( params ) {
-                                               tmp.widget.setApiValue( params.hasOwnProperty( name ) ? params[ name ] : undefined );
+                                               tmp.widget.setApiValue( Object.prototype.hasOwnProperty.call( params, name ) ? params[ name ] : undefined );
                                        }
                                } else {
                                        newVars = {};
                                        buttons = [],
                                        filterFmModules = function ( v ) {
                                                return v.substr( -2 ) !== 'fm' ||
-                                                       !availableFormats.hasOwnProperty( v.substr( 0, v.length - 2 ) );
+                                                       !Object.prototype.hasOwnProperty.call( availableFormats, v.substr( 0, v.length - 2 ) );
                                        };
 
                                // This is something of a hack. We always want the 'format' and
                        this.loadFromQueryParams = params;
                } else {
                        $.each( this.widgets, function ( name, widget ) {
-                               var v = params.hasOwnProperty( name ) ? params[ name ] : undefined;
+                               var v = Object.prototype.hasOwnProperty.call( params, name ) ? params[ name ] : undefined;
                                widget.setApiValue( v );
                        } );
                        this.updateTemplatedParameters( params );
index 144659a..da54ad2 100644 (file)
@@ -37,7 +37,7 @@
                                clearTimeout( this.timeoutID );
                        }
                        // Check response cache
-                       if ( this.responseCache.hasOwnProperty( this.nameToCheck ) ) {
+                       if ( Object.prototype.hasOwnProperty.call( this.responseCache, this.nameToCheck ) ) {
                                this.setWarning( this.responseCache[ this.nameToCheck ] );
                                return;
                        }
                        var template = $element.val(),
                                $spinner;
 
-                       if ( this.responseCache.hasOwnProperty( template ) ) {
+                       if ( Object.prototype.hasOwnProperty.call( this.responseCache, template ) ) {
                                this.showPreview( this.responseCache[ template ], $previewContainer );
                                return;
                        }
index e2bbd68..bac0674 100644 (file)
                 *  corresponding call to set().
                 */
                clear: function ( visibleTimeoutId ) {
-                       if ( activeTimeouts.hasOwnProperty( visibleTimeoutId ) ) {
+                       if ( Object.prototype.hasOwnProperty.call( activeTimeouts, visibleTimeoutId ) ) {
                                activeTimeouts[ visibleTimeoutId ]();
                        }
                }
index 2340f9c..6ee9595 100644 (file)
                var api = this.getApi(),
                        cache = this.constructor.static.interwikiPrefixesPromiseCache,
                        key = api.defaults.ajax.url;
-               if ( !cache.hasOwnProperty( key ) ) {
+               if ( !Object.prototype.hasOwnProperty.call( cache, key ) ) {
                        cache[ key ] = api.get( {
                                action: 'query',
                                meta: 'siteinfo',
index 88c541e..3911faa 100644 (file)
@@ -152,6 +152,7 @@ $wgAutoloadClasses += [
        'MediaWiki\Tests\Storage\McrSchemaDetection' => "$testDir/phpunit/includes/Storage/McrSchemaDetection.php",
        'MediaWiki\Tests\Storage\McrSchemaOverride' => "$testDir/phpunit/includes/Storage/McrSchemaOverride.php",
        'MediaWiki\Tests\Storage\McrWriteBothSchemaOverride' => "$testDir/phpunit/includes/Storage/McrWriteBothSchemaOverride.php",
+       'MediaWiki\Tests\Storage\McrReadNewSchemaOverride' => "$testDir/phpunit/includes/Storage/McrReadNewSchemaOverride.php",
        'MediaWiki\Tests\Storage\RevisionSlotsTest' => "$testDir/phpunit/includes/Storage/RevisionSlotsTest.php",
        'MediaWiki\Tests\Storage\RevisionRecordTests' => "$testDir/phpunit/includes/Storage/RevisionRecordTests.php",
        'MediaWiki\Tests\Storage\RevisionStoreDbTestBase' => "$testDir/phpunit/includes/Storage/RevisionStoreDbTestBase.php",
index 60a5881..ceee432 100644 (file)
@@ -773,7 +773,7 @@ class ParserTestRunner {
        /**
         * Get a Parser object
         *
-        * @param string $preprocessor
+        * @param string|null $preprocessor
         * @return Parser
         */
        function getParser( $preprocessor = null ) {
@@ -1264,6 +1264,7 @@ class ParserTestRunner {
                $this->dbClone = new CloneDatabase( $this->db, $this->listTables(), $prefix );
                $this->dbClone->useTemporaryTables( $temporary );
                $this->dbClone->cloneTableStructure();
+               CloneDatabase::changePrefix( $prefix );
 
                if ( $dbType == 'oracle' ) {
                        $this->db->query( 'BEGIN FILL_WIKI_INFO; END;' );
index 61d86bd..bcb3379 100644 (file)
@@ -327,10 +327,6 @@ return [
                "PhanTypeMismatchArgument",
                // approximate error count: 13
                "PhanTypeMismatchArgumentInternal",
-               // approximate error count: 6
-               "PhanTypeMismatchDeclaredParam",
-               // approximate error count: 111
-               "PhanTypeMismatchDeclaredParamNullable",
                // approximate error count: 5
                "PhanTypeMismatchDimAssignment",
                // approximate error count: 2
index e8ab412..82739a7 100644 (file)
@@ -715,7 +715,7 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
         *
         * @param array|string $pairs Key to the global variable, or an array
         *  of key/value pairs.
-        * @param mixed $value Value to set the global to (ignored
+        * @param mixed|null $value Value to set the global to (ignored
         *  if an array is given as first argument).
         *
         * @note To allow changes to global variables to take effect on global service instances,
@@ -883,7 +883,8 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
         *
         * @since 1.27
         *
-        * @param Config $configOverrides Configuration overrides for the new MediaWikiServices instance.
+        * @param Config|null $configOverrides Configuration overrides for the new MediaWikiServices
+        *        instance.
         * @param callable[] $services An associative array of services to re-define. Keys are service
         *        names, values are callables.
         *
@@ -963,7 +964,7 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
         *   in which case the next two parameters are ignored; or a single string
         *   identifying a group, to use with the next two parameters.
         * @param string|null $newKey
-        * @param mixed $newValue
+        * @param mixed|null $newValue
         */
        public function setGroupPermissions( $newPerms, $newKey = null, $newValue = null ) {
                global $wgGroupPermissions;
@@ -1083,8 +1084,8 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
         * @since 1.25 ($namespace in 1.28)
         * @param string|Title $pageName Page name or title
         * @param string $text Page's content
-        * @param int $namespace Namespace id (name cannot already contain namespace)
-        * @param User $user If null, static::getTestSysop()->getUser() is used.
+        * @param int|null $namespace Namespace id (name cannot already contain namespace)
+        * @param User|null $user If null, static::getTestSysop()->getUser() is used.
         * @return array Title object and page id
         */
        protected function insertPage(
@@ -1287,7 +1288,7 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
         * Otherwise, it will clone the tables and change the prefix.
         *
         * @param IMaintainableDatabase $db Database to use
-        * @param string $prefix Prefix to use for test tables. If not given, the prefix is determined
+        * @param string|null $prefix Prefix to use for test tables. If not given, the prefix is determined
         *        automatically for $db.
         * @return bool True if tables were cloned, false if only the prefix was changed
         */
index 1b0c848..d28be7a 100644 (file)
@@ -470,16 +470,17 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
                }
 
                $stages = [
-                       MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
-                       MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
-                       MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
-                       MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
+                       MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
+                       MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
+                               MIGRATION_NEW ],
+                       MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+                       MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
                ];
 
                $nameKey = $key . '_text';
                $actorKey = $key === 'ipb_by' ? 'ipb_by_actor' : substr( $key, 0, -5 ) . '_actor';
 
-               foreach ( $stages as $writeStage => $readRange ) {
+               foreach ( $stages as $writeStage => $possibleReadStages ) {
                        if ( $key === 'ipb_by' ) {
                                $extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
                        }
@@ -512,7 +513,7 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
                                $callback( $id, $extraFields );
                        }
 
-                       for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
+                       foreach ( $possibleReadStages as $readStage ) {
                                $r = $this->makeMigration( $readStage );
 
                                $queryInfo = $r->getJoin( $key );
index a510897..c41361c 100644 (file)
@@ -367,13 +367,14 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                ];
 
                $stages = [
-                       MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
-                       MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
-                       MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
-                       MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
+                       MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
+                       MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
+                               MIGRATION_NEW ],
+                       MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+                       MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
                ];
 
-               foreach ( $stages as $writeStage => $readRange ) {
+               foreach ( $stages as $writeStage => $possibleReadStages ) {
                        if ( $key === 'ipb_reason' ) {
                                $extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
                        }
@@ -406,7 +407,7 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                $callback( $id );
                        }
 
-                       for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
+                       foreach ( $possibleReadStages as $readStage ) {
                                $rstore = $this->makeStore( $readStage );
 
                                $fieldRow = $this->db->selectRow(
@@ -460,13 +461,14 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                ];
 
                $stages = [
-                       MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
-                       MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
-                       MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
-                       MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
+                       MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
+                       MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
+                               MIGRATION_NEW ],
+                       MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+                       MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
                ];
 
-               foreach ( $stages as $writeStage => $readRange ) {
+               foreach ( $stages as $writeStage => $possibleReadStages ) {
                        if ( $key === 'ipb_reason' ) {
                                $extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
                        }
@@ -499,7 +501,7 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                $callback( $id );
                        }
 
-                       for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
+                       foreach ( $possibleReadStages as $readStage ) {
                                $rstore = $this->makeStoreWithKey( $readStage, $key );
 
                                $fieldRow = $this->db->selectRow(
index 623d4a6..15a991e 100644 (file)
@@ -52,6 +52,7 @@ class PageArchiveTest extends MediaWikiTestCase {
 
                $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
                $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', MIGRATION_OLD );
+               $this->setMwGlobals( 'wgMultiContentRevisionSchemaMigrationStage', SCHEMA_COMPAT_OLD );
                $this->overrideMwServices();
 
                // First create our dummy page
@@ -135,6 +136,7 @@ class PageArchiveTest extends MediaWikiTestCase {
         */
        public function testListRevisions() {
                $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
+               $this->setMwGlobals( 'wgMultiContentRevisionSchemaMigrationStage', SCHEMA_COMPAT_OLD );
                $this->overrideMwServices();
 
                $revisions = $this->archivedPage->listRevisions();
index 73050e0..e17f855 100644 (file)
@@ -1412,7 +1412,8 @@ abstract class RevisionDbTestBase extends MediaWikiTestCase {
                $rev = $this->testPage->getRevision();
 
                // Clear any previous cache for the revision during creation
-               $key = $cache->makeGlobalKey( RevisionStore::ROW_CACHE_KEY,
+               $key = $cache->makeGlobalKey(
+                       RevisionStore::ROW_CACHE_KEY,
                        $db->getDomainID(),
                        $rev->getPage(),
                        $rev->getId()
diff --git a/tests/phpunit/includes/RevisionMcrReadNewDbTest.php b/tests/phpunit/includes/RevisionMcrReadNewDbTest.php
new file mode 100644 (file)
index 0000000..1054b7d
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+use MediaWiki\Tests\Storage\McrReadNewSchemaOverride;
+
+/**
+ * Tests Revision against the intermediate MCR DB schema for use during schema migration.
+ *
+ * @covers Revision
+ *
+ * @group Revision
+ * @group Storage
+ * @group ContentHandler
+ * @group Database
+ * @group medium
+ */
+class RevisionMcrReadNewDbTest extends RevisionDbTestBase {
+
+       use McrReadNewSchemaOverride;
+
+       protected function getContentHandlerUseDB() {
+               return true;
+       }
+
+}
index 6de37af..7ef1182 100644 (file)
@@ -895,7 +895,12 @@ class RevisionTest extends MediaWikiTestCase {
                        )
                );
 
-               $cacheKey = $cache->makeKey( 'revisiontext', 'textid', 'tt:7777' );
+               $cacheKey = $cache->makeGlobalKey(
+                       'BlobStore',
+                       'address',
+                       $lb->getLocalDomainID(),
+                       'tt:7777'
+               );
                $this->assertSame( 'AAAABBAAA', $cache->get( $cacheKey ) );
        }
 
diff --git a/tests/phpunit/includes/Storage/McrReadNewRevisionStoreDbTest.php b/tests/phpunit/includes/Storage/McrReadNewRevisionStoreDbTest.php
new file mode 100644 (file)
index 0000000..cbae4c7
--- /dev/null
@@ -0,0 +1,252 @@
+<?php
+namespace MediaWiki\Tests\Storage;
+
+use CommentStoreComment;
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\SlotRecord;
+use TextContent;
+use Title;
+use WikitextContent;
+
+/**
+ * Tests RevisionStore against the intermediate MCR DB schema for use during schema migration.
+ *
+ * @covers \MediaWiki\Storage\RevisionStore
+ *
+ * @group RevisionStore
+ * @group Storage
+ * @group Database
+ * @group medium
+ */
+class McrReadNewRevisionStoreDbTest extends RevisionStoreDbTestBase {
+
+       use McrReadNewSchemaOverride;
+
+       protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
+               $numberOfSlots = count( $rev->getSlotRoles() );
+
+               // new schema is written
+               $this->assertSelect(
+                       'slots',
+                       [ 'count(*)' ],
+                       [ 'slot_revision_id' => $rev->getId() ],
+                       [ [ (string)$numberOfSlots ] ]
+               );
+
+               $store = MediaWikiServices::getInstance()->getRevisionStore();
+               $revQuery = $store->getSlotsQueryInfo( [ 'content' ] );
+
+               $this->assertSelect(
+                       $revQuery['tables'],
+                       [ 'count(*)' ],
+                       [
+                               'slot_revision_id' => $rev->getId(),
+                       ],
+                       [ [ (string)$numberOfSlots ] ],
+                       [],
+                       $revQuery['joins']
+               );
+
+               // Legacy schema is still being written
+               $this->assertSelect(
+                       [ 'revision', 'text' ],
+                       [ 'count(*)' ],
+                       [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
+                       [ [ 1 ] ],
+                       [],
+                       [ 'text' => [ 'INNER JOIN', [ 'rev_text_id = old_id' ] ] ]
+               );
+
+               parent::assertRevisionExistsInDatabase( $rev );
+       }
+
+       /**
+        * @param SlotRecord $a
+        * @param SlotRecord $b
+        */
+       protected function assertSameSlotContent( SlotRecord $a, SlotRecord $b ) {
+               parent::assertSameSlotContent( $a, $b );
+
+               // Assert that the same content ID has been used
+               $this->assertSame( $a->getContentId(), $b->getContentId() );
+       }
+
+       public function provideInsertRevisionOn_successes() {
+               foreach ( parent::provideInsertRevisionOn_successes() as $case ) {
+                       yield $case;
+               }
+
+               yield 'Multi-slot revision insertion' => [
+                       [
+                               'content' => [
+                                       'main' => new WikitextContent( 'Chicken' ),
+                                       'aux' => new TextContent( 'Egg' ),
+                               ],
+                               'page' => true,
+                               'comment' => $this->getRandomCommentStoreComment(),
+                               'timestamp' => '20171117010101',
+                               'user' => true,
+                       ],
+               ];
+       }
+
+       public function provideNewNullRevision() {
+               foreach ( parent::provideNewNullRevision() as $case ) {
+                       yield $case;
+               }
+
+               yield [
+                       Title::newFromText( 'UTPage_notAutoCreated' ),
+                       [
+                               'content' => [
+                                       'main' => new WikitextContent( 'Chicken' ),
+                                       'aux' => new WikitextContent( 'Omelet' ),
+                               ],
+                       ],
+                       CommentStoreComment::newUnsavedComment( __METHOD__ . ' comment multi' ),
+               ];
+       }
+
+       public function testGetQueryInfo_NoSlotDataJoin() {
+               $store = MediaWikiServices::getInstance()->getRevisionStore();
+               $queryInfo = $store->getQueryInfo();
+
+               // with the new schema enabled, query info should not join the main slot info
+               $this->assertFalse( array_key_exists( 'a_slot_data', $queryInfo['tables'] ) );
+               $this->assertFalse( array_key_exists( 'a_slot_data', $queryInfo['joins'] ) );
+       }
+
+       public function provideGetArchiveQueryInfo() {
+               yield [
+                       [
+                               'tables' => [
+                                       'archive',
+                               ],
+                               'fields' => array_merge(
+                                       $this->getDefaultArchiveFields( false ),
+                                       [
+                                               'ar_comment_text' => 'ar_comment',
+                                               'ar_comment_data' => 'NULL',
+                                               'ar_comment_cid' => 'NULL',
+                                               'ar_user_text' => 'ar_user_text',
+                                               'ar_user' => 'ar_user',
+                                               'ar_actor' => 'NULL',
+                                       ]
+                               ),
+                               'joins' => [
+                               ],
+                       ]
+               ];
+       }
+
+       public function provideGetQueryInfo() {
+               // TODO: more option variations
+               yield [
+                       [ 'page', 'user' ],
+                       [
+                               'tables' => [
+                                       'revision',
+                                       'page',
+                                       'user',
+                               ],
+                               'fields' => array_merge(
+                                       $this->getDefaultQueryFields( false ),
+                                       $this->getCommentQueryFields(),
+                                       $this->getActorQueryFields(),
+                                       [
+                                               'page_namespace',
+                                               'page_title',
+                                               'page_id',
+                                               'page_latest',
+                                               'page_is_redirect',
+                                               'page_len',
+                                               'user_name',
+                                       ]
+                               ),
+                               'joins' => [
+                                       'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
+                                       'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+                               ],
+                       ]
+               ];
+       }
+
+       public function provideGetSlotsQueryInfo() {
+               yield [
+                       [],
+                       [
+                               'tables' => [
+                                       'slots',
+                                       'slot_roles',
+                               ],
+                               'fields' => array_merge(
+                                       [
+                                               'slot_revision_id',
+                                               'slot_content_id',
+                                               'slot_origin',
+                                               'role_name',
+                                       ]
+                               ),
+                               'joins' => [
+                                       'slot_roles' => [ 'INNER JOIN', [ 'slot_role_id = role_id' ] ],
+                               ],
+                       ]
+               ];
+               yield [
+                       [ 'content' ],
+                       [
+                               'tables' => [
+                                       'slots',
+                                       'slot_roles',
+                                       'content',
+                                       'content_models',
+                               ],
+                               'fields' => array_merge(
+                                       [
+                                               'slot_revision_id',
+                                               'slot_content_id',
+                                               'slot_origin',
+                                               'role_name',
+                                               'content_size',
+                                               'content_sha1',
+                                               'content_address',
+                                               'model_name',
+                                       ]
+                               ),
+                               'joins' => [
+                                       'slot_roles' => [ 'INNER JOIN', [ 'slot_role_id = role_id' ] ],
+                                       'content' => [ 'INNER JOIN', [ 'slot_content_id = content_id' ] ],
+                                       'content_models' => [ 'INNER JOIN', [ 'content_model = model_id' ] ],
+                               ],
+                       ]
+               ];
+       }
+
+       public function provideNewMutableRevisionFromArray() {
+               foreach ( parent::provideNewMutableRevisionFromArray() as $case ) {
+                       yield $case;
+               }
+
+               yield 'Basic array, multiple roles' => [
+                       [
+                               'id' => 2,
+                               'page' => 1,
+                               'timestamp' => '20171017114835',
+                               'user_text' => '111.0.1.2',
+                               'user' => 0,
+                               'minor_edit' => false,
+                               'deleted' => 0,
+                               'len' => 29,
+                               'parent_id' => 1,
+                               'sha1' => '89qs83keq9c9ccw9olvvm4oc9oq50ii',
+                               'comment' => 'Goat Comment!',
+                               'content' => [
+                                       'main' => new WikitextContent( 'Söme Cöntent' ),
+                                       'aux' => new TextContent( 'Öther Cöntent' ),
+                               ]
+                       ]
+               ];
+       }
+
+}
diff --git a/tests/phpunit/includes/Storage/McrReadNewSchemaOverride.php b/tests/phpunit/includes/Storage/McrReadNewSchemaOverride.php
new file mode 100644 (file)
index 0000000..1958333
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+namespace MediaWiki\Tests\Storage;
+
+use Wikimedia\Rdbms\IMaintainableDatabase;
+use MediaWiki\DB\PatchFileLocation;
+
+/**
+ * Trait providing schema overrides that allow tests to run against the intermediate MCR database
+ * schema for use during schema migration.
+ */
+trait McrReadNewSchemaOverride {
+
+       use PatchFileLocation;
+       use McrSchemaDetection;
+
+       /**
+        * @return int
+        */
+       protected function getMcrMigrationStage() {
+               return SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW;
+       }
+
+       /**
+        * @return string[]
+        */
+       protected function getMcrTablesToReset() {
+               return [ 'content', 'content_models', 'slots', 'slot_roles' ];
+       }
+
+       /**
+        * @override MediaWikiTestCase::getSchemaOverrides
+        * @return array[]
+        */
+       protected function getSchemaOverrides( IMaintainableDatabase $db ) {
+               $overrides = [
+                       'scripts' => [],
+                       'drop' => [],
+                       'create' => [],
+                       'alter' => [],
+               ];
+
+               if ( !$this->hasMcrTables( $db ) ) {
+                       $overrides['create'] = [ 'slots', 'content', 'slot_roles', 'content_models', ];
+                       $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-slot_roles' );
+                       $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-content_models' );
+                       $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-content' );
+                       $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'patch-slots' );
+               }
+
+               if ( !$this->hasPreMcrFields( $db ) ) {
+                       $overrides['alter'][] = 'revision';
+                       $overrides['scripts'][] = $this->getSqlPatchPath( $db, 'create-pre-mcr-fields', __DIR__ );
+               }
+
+               return $overrides;
+       }
+
+}
index 5bf49d3..9a118d7 100644 (file)
@@ -26,6 +26,7 @@ class McrRevisionStoreDbTest extends RevisionStoreDbTestBase {
        protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
                $numberOfSlots = count( $rev->getSlotRoles() );
 
+               // new schema is written
                $this->assertSelect(
                        'slots',
                        [ 'count(*)' ],
@@ -47,13 +48,6 @@ class McrRevisionStoreDbTest extends RevisionStoreDbTestBase {
                        $revQuery['joins']
                );
 
-               $this->assertSelect(
-                       'content',
-                       [ 'count(*)' ],
-                       [ 'content_address' => $rev->getSlot( 'main' )->getAddress() ],
-                       [ [ 1 ] ]
-               );
-
                parent::assertRevisionExistsInDatabase( $rev );
        }
 
index f03d403..9d5dc29 100644 (file)
@@ -32,6 +32,7 @@ class McrWriteBothRevisionStoreDbTest extends RevisionStoreDbTestBase {
        }
 
        protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
+               // New schema is being written
                $this->assertSelect(
                        'slots',
                        [ 'count(*)' ],
@@ -46,6 +47,16 @@ class McrWriteBothRevisionStoreDbTest extends RevisionStoreDbTestBase {
                        [ [ '1' ] ]
                );
 
+               // Legacy schema is still being written
+               $this->assertSelect(
+                       [ 'revision', 'text' ],
+                       [ 'count(*)' ],
+                       [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
+                       [ [ 1 ] ],
+                       [],
+                       [ 'text' => [ 'INNER JOIN', [ 'rev_text_id = old_id' ] ] ]
+               );
+
                parent::assertRevisionExistsInDatabase( $rev );
        }
 
index 2a54dbe..7275f90 100644 (file)
@@ -17,7 +17,7 @@ trait McrWriteBothSchemaOverride {
         * @return int
         */
        protected function getMcrMigrationStage() {
-               return MIGRATION_WRITE_BOTH;
+               return SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD;
        }
 
        /**
index 7cc3131..cee5f96 100644 (file)
@@ -2,6 +2,7 @@
 namespace MediaWiki\Tests\Storage;
 
 use InvalidArgumentException;
+use MediaWiki\Storage\RevisionRecord;
 use Revision;
 use WikitextContent;
 
@@ -29,6 +30,20 @@ class PreMcrRevisionStoreDbTest extends RevisionStoreDbTestBase {
                return $row;
        }
 
+       protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
+               // Legacy schema is still being written
+               $this->assertSelect(
+                       [ 'revision', 'text' ],
+                       [ 'count(*)' ],
+                       [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
+                       [ [ 1 ] ],
+                       [],
+                       [ 'text' => [ 'INNER JOIN', [ 'rev_text_id = old_id' ] ] ]
+               );
+
+               parent::assertRevisionExistsInDatabase( $rev );
+       }
+
        public function provideGetArchiveQueryInfo() {
                yield [
                        [
index 727697c..90bd57a 100644 (file)
@@ -86,13 +86,17 @@ class RevisionStoreTest extends MediaWikiTestCase {
 
        public function provideSetContentHandlerUseDB() {
                return [
-                       // ContentHandlerUseDB can be true of false pre migration
-                       [ false, MIGRATION_OLD, false ],
-                       [ true, MIGRATION_OLD, false ],
-                       // During migration it can not be false
-                       [ false, MIGRATION_WRITE_BOTH, true ],
-                       // But it can be true
-                       [ true, MIGRATION_WRITE_BOTH, false ],
+                       // ContentHandlerUseDB can be true of false pre migration.
+                       [ false, SCHEMA_COMPAT_OLD, false ],
+                       [ true, SCHEMA_COMPAT_OLD, false ],
+                       // During and after migration it can not be false...
+                       [ false, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, true ],
+                       [ false, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, true ],
+                       [ false, SCHEMA_COMPAT_NEW, true ],
+                       // ...but it can be true.
+                       [ true, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, false ],
+                       [ true, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, false ],
+                       [ true, SCHEMA_COMPAT_NEW, false ],
                ];
        }
 
@@ -482,8 +486,13 @@ class RevisionStoreTest extends MediaWikiTestCase {
 
        public function provideMigrationConstruction() {
                return [
-                       [ MIGRATION_OLD, false ],
-                       [ MIGRATION_WRITE_BOTH, false ],
+                       [ SCHEMA_COMPAT_OLD, false ],
+                       [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, false ],
+                       [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, false ],
+                       [ SCHEMA_COMPAT_NEW, false ],
+                       [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_BOTH, true ],
+                       [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_BOTH, true ],
+                       [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_BOTH, true ],
                ];
        }
 
index 17a4182..e50e1bc 100644 (file)
@@ -38,7 +38,7 @@ class TestLogger extends \Psr\Log\AbstractLogger {
 
        /**
         * @param bool $collect Whether to collect logs. @see setCollect()
-        * @param callable $filter Filter logs before collecting/printing. Signature is
+        * @param callable|null $filter Filter logs before collecting/printing. Signature is
         *  string|null function ( string $message, string $level, array $context );
         * @param bool $collectContext Whether to keep the context passed to log
         *             (since 1.29, @see setCollectContext()).
index 7fd5f1d..75e73be 100644 (file)
@@ -105,7 +105,7 @@ class RandomImageGenerator {
         *
         * @param int $number Number of filenames to write
         * @param string $format Optional, must be understood by ImageMagick, such as 'jpg' or 'gif'
-        * @param string $dir Directory, optional (will default to current working directory)
+        * @param string|null $dir Directory, optional (will default to current working directory)
         * @return array Filenames we just wrote
         */
        function writeImages( $number, $format = 'jpg', $dir = null ) {
index e7588cb..08af755 100644 (file)
@@ -87,9 +87,9 @@ STR;
         * Checks that the request's result matches the expected results.
         * Assumes no rawcontinue and a complete batch.
         * @param array $values Array is a two element array( request, expected_results )
-        * @param array $session
+        * @param array|null $session
         * @param bool $appendModule
-        * @param User $user
+        * @param User|null $user
         */
        protected function check( $values, array $session = null,
                $appendModule = false, User $user = null
index 82ca66a..5cd55ba 100644 (file)
@@ -74,6 +74,10 @@ class LBFactoryTest extends MediaWikiTestCase {
                ];
        }
 
+       /**
+        * @covers LBFactory::getLocalDomainID()
+        * @covers LBFactory::resolveDomainID()
+        */
        public function testLBFactorySimpleServer() {
                global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgDBtype, $wgSQLiteDataDir;
 
@@ -99,6 +103,9 @@ class LBFactoryTest extends MediaWikiTestCase {
                $dbr = $lb->getConnection( DB_REPLICA );
                $this->assertTrue( $dbr->getLBInfo( 'master' ), 'DB_REPLICA also gets the master' );
 
+               $this->assertSame( 'my_test_wiki', $factory->resolveDomainID( 'my_test_wiki' ) );
+               $this->assertSame( $factory->getLocalDomainID(), $factory->resolveDomainID( false ) );
+
                $factory->shutdown();
                $lb->closeAll();
        }
index d6b43e5..5a748cc 100644 (file)
@@ -48,6 +48,10 @@ class LoadBalancerTest extends MediaWikiTestCase {
                ];
        }
 
+       /**
+        * @covers LoadBalancer::getLocalDomainID()
+        * @covers LoadBalancer::resolveDomainID()
+        */
        public function testWithoutReplica() {
                global $wgDBname;
 
@@ -64,6 +68,9 @@ class LoadBalancerTest extends MediaWikiTestCase {
                $ld = DatabaseDomain::newFromId( $lb->getLocalDomainID() );
                $this->assertEquals( $wgDBname, $ld->getDatabase(), 'local domain DB set' );
                $this->assertEquals( $this->dbPrefix(), $ld->getTablePrefix(), 'local domain prefix set' );
+               $this->assertSame( 'my_test_wiki', $lb->resolveDomainID( 'my_test_wiki' ) );
+               $this->assertSame( $ld->getId(), $lb->resolveDomainID( false ) );
+               $this->assertSame( $ld->getId(), $lb->resolveDomainID( $ld ) );
 
                $this->assertFalse( $called );
                $dbw = $lb->getConnection( DB_MASTER );
index c3cddc6..e130b23 100644 (file)
@@ -12,6 +12,7 @@ use Wikimedia\Rdbms\ResultWrapper;
  */
 class DBConnRefTest extends PHPUnit\Framework\TestCase {
 
+       use MediaWikiCoversValidator;
        use PHPUnit4And6Compat;
 
        /**
@@ -106,18 +107,9 @@ class DBConnRefTest extends PHPUnit\Framework\TestCase {
                new DBConnRef( $lb, 17 ); // bad constructor argument
        }
 
-       public function testGetWikiID() {
-               $lb = $this->getMock( ILoadBalancer::class );
-
-               // getWikiID is optimized to not create a connection
-               $lb->expects( $this->never() )
-                       ->method( 'getConnection' );
-
-               $ref = new DBConnRef( $lb, [ DB_REPLICA, [], 'dummy', 0 ] );
-
-               $this->assertSame( 'dummy', $ref->getWikiID() );
-       }
-
+       /**
+        * @covers Wikimedia\Rdbms\DBConnRef::getDomainId
+        */
        public function testGetDomainID() {
                $lb = $this->getMock( ILoadBalancer::class );
 
index a4e8056..7a536df 100644 (file)
@@ -70,7 +70,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
         *
         * File must be in the path returned by getFilePath()
         * @param string $name File name
-        * @param string $type MIME type [optional]
+        * @param string|null $type MIME type [optional]
         * @return UnregisteredLocalFile
         */
        protected function dataFile( $name, $type = null ) {
index e0364c4..fa15a12 100644 (file)
@@ -104,7 +104,7 @@ abstract class WikiPageDbTestBase extends MediaWikiLangTestCase {
        /**
         * @param string|Title|WikiPage $page
         * @param string $text
-        * @param int $model
+        * @param int|null $model
         *
         * @return WikiPage
         */
diff --git a/tests/phpunit/includes/page/WikiPageMcrReadNewDbTest.php b/tests/phpunit/includes/page/WikiPageMcrReadNewDbTest.php
new file mode 100644 (file)
index 0000000..9e2ff09
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+use MediaWiki\Tests\Storage\McrReadNewSchemaOverride;
+
+/**
+ * Tests WikiPage against the intermediate MCR DB schema for use during schema migration.
+ *
+ * @covers WikiPage
+ *
+ * @group WikiPage
+ * @group Storage
+ * @group ContentHandler
+ * @group Database
+ * @group medium
+ */
+class WikiPageMcrReadNewDbTest extends WikiPageDbTestBase {
+
+       use McrReadNewSchemaOverride;
+
+       protected function getContentHandlerUseDB() {
+               return true;
+       }
+
+}
index 810d1fe..86956f2 100644 (file)
@@ -589,4 +589,49 @@ mw.loader.register( [
                );
        }
 
+       /**
+        * @covers ResourceLoaderStartupModule::getAllModuleHashes
+        * @covers ResourceLoaderStartupModule::getDefinitionSummary
+        */
+       public function testGetVersionHash_varyModule() {
+               $context1 = $this->getResourceLoaderContext();
+               $rl1 = $context1->getResourceLoader();
+               $rl1->register( [
+                       'test.a' => new ResourceLoaderTestModule(),
+                       'test.b' => new ResourceLoaderTestModule(),
+               ] );
+               $module = new ResourceLoaderStartupModule();
+               $version1 = $module->getVersionHash( $context1 );
+
+               $context2 = $this->getResourceLoaderContext();
+               $rl2 = $context2->getResourceLoader();
+               $rl2->register( [
+                       'test.b' => new ResourceLoaderTestModule(),
+                       'test.c' => new ResourceLoaderTestModule(),
+               ] );
+               $module = new ResourceLoaderStartupModule();
+               $version2 = $module->getVersionHash( $context2 );
+
+               $context3 = $this->getResourceLoaderContext();
+               $rl3 = $context3->getResourceLoader();
+               $rl3->register( [
+                       'test.a' => new ResourceLoaderTestModule(),
+                       'test.b' => new ResourceLoaderTestModule( [ 'script' => 'different' ] ),
+               ] );
+               $module = new ResourceLoaderStartupModule();
+               $version3 = $module->getVersionHash( $context3 );
+
+               $this->assertEquals(
+                       $version1,
+                       $version2,
+                       'Module name is insignificant'
+               );
+
+               $this->assertNotEquals(
+                       $version1,
+                       $version3,
+                       'Hash change of any module impacts startup hash'
+               );
+       }
+
 }
index 5db1ad0..ef8fb4e 100644 (file)
@@ -78,9 +78,9 @@ class TestUtils {
        /**
         * If you need a Session for testing but don't want to create a backend to
         * construct one, use this.
-        * @param object $backend Object to serve as the SessionBackend
+        * @param object|null $backend Object to serve as the SessionBackend
         * @param int $index
-        * @param LoggerInterface $logger
+        * @param LoggerInterface|null $logger
         * @return Session
         */
        public static function getDummySession( $backend = null, $index = -1, $logger = null ) {
index e8259d3..6bc7c44 100644 (file)
@@ -94,7 +94,7 @@ class DummyContentForTesting extends AbstractContent {
 
        /**
         * @param Title $title
-        * @param int $revId Unused.
+        * @param int|null $revId Unused.
         * @param null|ParserOptions $options
         * @param bool $generateHtml Whether to generate Html (default: true). If false, the result
         *  of calling getText() on the ParserOutput object returned by this method is undefined.
index b71577c..f203907 100644 (file)
@@ -10,7 +10,7 @@ class DummyContentHandlerForTesting extends ContentHandler {
         * @see ContentHandler::serializeContent
         *
         * @param Content $content
-        * @param string $format
+        * @param string|null $format
         *
         * @return string
         */
@@ -22,7 +22,7 @@ class DummyContentHandlerForTesting extends ContentHandler {
         * @see ContentHandler::unserializeContent
         *
         * @param string $blob
-        * @param string $format Unused.
+        * @param string|null $format Unused.
         *
         * @return Content
         */
index 91bb186..e65f522 100644 (file)
@@ -92,7 +92,7 @@ class DummyNonTextContent extends AbstractContent {
 
        /**
         * @param Title $title
-        * @param int $revId Unused.
+        * @param int|null $revId Unused.
         * @param null|ParserOptions $options
         * @param bool $generateHtml Whether to generate Html (default: true). If false, the result
         *  of calling getText() on the ParserOutput object returned by this method is undefined.
index 9d91d4a..3294953 100644 (file)
@@ -10,7 +10,7 @@ class DummyNonTextContentHandler extends DummyContentHandlerForTesting {
         * @see ContentHandler::serializeContent
         *
         * @param Content $content
-        * @param string $format
+        * @param string|null $format
         *
         * @return string
         */
@@ -22,7 +22,7 @@ class DummyNonTextContentHandler extends DummyContentHandlerForTesting {
         * @see ContentHandler::unserializeContent
         *
         * @param string $blob
-        * @param string $format Unused.
+        * @param string|null $format Unused.
         *
         * @return Content
         */
index 720547a..4a462c0 100644 (file)
@@ -29,7 +29,7 @@ class DummySerializeErrorContentHandler extends DummyContentHandlerForTesting {
         * @see ContentHandler::unserializeContent
         *
         * @param string $blob
-        * @param string $format
+        * @param string|null $format
         *
         * @return Content
         */
index 4afc16b..de593d5 100644 (file)
@@ -49,6 +49,7 @@
                        $element.css( 'height' );
                        // eslint-disable-next-line no-unused-expressions
                        el.innerHTML;
+                       // eslint-disable-next-line no-self-assign
                        el.className = el.className;
                        // eslint-disable-next-line no-unused-expressions
                        document.documentElement.clientHeight;
index b59116e..cc74c89 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -626,7 +626,7 @@ function wfThumbErrorText( $status, $msgText ) {
  *
  * @param int $status
  * @param string $msgHtml HTML
- * @param string $msgText Short error description, for internal logging. Defaults to $msgHtml.
+ * @param string|null $msgText Short error description, for internal logging. Defaults to $msgHtml.
  *   Only used for HTTP 500 errors.
  * @param array $context Error context, for internal logging. Only used for HTTP 500 errors.
  * @return void