Merge "Linker: Fix fatal error for "/* */" in an edit summary"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sun, 19 May 2019 21:37:51 +0000 (21:37 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sun, 19 May 2019 21:37:51 +0000 (21:37 +0000)
40 files changed:
RELEASE-NOTES-1.34
composer.json
docs/hooks.txt
includes/GlobalFunctions.php
includes/OutputHandler.php
includes/api/ApiMain.php
includes/api/ApiQueryAllImages.php
includes/api/ApiQueryAllLinks.php
includes/api/ApiQueryAllPages.php
includes/api/ApiQueryAllUsers.php
includes/api/i18n/en.json
includes/api/i18n/qqq.json
includes/changes/ChangesList.php
includes/config/ConfigRepository.php
includes/diff/DiffEngine.php
includes/installer/Installer.php
includes/media/DjVuImage.php
includes/media/FormatMetadata.php
includes/shell/Command.php
includes/skins/Skin.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/QueryPage.php
includes/specials/SpecialAllMessages.php
includes/specials/SpecialRedirect.php
includes/specials/pagers/BlockListPager.php
includes/specials/pagers/DeletedContribsPager.php
includes/specials/pagers/UsersPager.php
includes/user/UserGroupMembership.php
languages/i18n/en.json
languages/i18n/qqq.json
maintenance/update.php
resources/Resources.php
resources/src/mediawiki.content.json.less
resources/src/mediawiki.page.ready.js
tests/phpunit/includes/MediaWikiVersionFetcherTest.php
tests/phpunit/includes/changes/OldChangesListTest.php
tests/phpunit/includes/libs/MWMessagePackTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderSkinModuleTest.php
tests/phpunit/includes/shell/ShellTest.php
tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php

index 917609b..d9ac7bf 100644 (file)
@@ -59,6 +59,7 @@ For notes on 1.33.x and older releases, see HISTORY.
 * Updated composer/spdx-licenses from 1.4.0 to 1.5.1 (dev-only).
 * Updated mediawiki/codesniffer from 25.0.0 to 26.0.0 (dev-only).
 * Updated cssjanus/cssjanus from 1.2.1 to 1.3.0.
+* Updated wikimedia/at-ease from 1.2.0 to 2.0.0.
 * …
 
 ==== Removed external libraries ====
@@ -86,6 +87,9 @@ because of Phabricator reports.
 * (T152908) Added language support for N'Ko (nqo).
 
 === Breaking changes in 1.34 ===
+* The global functions wfSuppressWarnings and wfRestoreWarnings, deprecated in
+  1.26, have been removed. Use Wikimedia\AtEase\AtEase::suppressWarnings() and
+  Wikimedia\AtEase\AtEase::restoreWarnings() directly.
 * Preferences class, deprecated in 1.31, has been removed.
 * The following parts of code, deprecated in 1.32, were removed in favor of
   built-in PHP functions:
index b1242c5..11680ff 100644 (file)
@@ -34,7 +34,7 @@
                "php": ">=5.6.99",
                "psr/log": "1.0.2",
                "wikimedia/assert": "0.2.2",
-               "wikimedia/at-ease": "1.2.0",
+               "wikimedia/at-ease": "2.0.0",
                "wikimedia/base-convert": "2.0.0",
                "wikimedia/cdb": "1.4.1",
                "wikimedia/cldr-plural-rule-parser": "1.0.0",
index 1419d0a..7f8b192 100644 (file)
@@ -3568,7 +3568,10 @@ hook. If your extension absolutely, positively must prevent some files from
 being uploaded, use UploadVerifyFile or UploadVerifyUpload.
 $upload: (object) An instance of UploadBase, with all info about the upload
 $user: (object) An instance of User, the user uploading this file
-$props: (array) File properties, as returned by FSFile::getPropsFromPath()
+$props: (array|null) File properties, as returned by
+  MWFileProps::getPropsFromPath(). Note this is not always guaranteed to be set,
+  e.g. in test scenarios. Call MWFileProps::getPropsFromPath() yourself in case
+  you need the information.
 &$error: output: If the file stashing should be prevented, set this to the
   reason in the form of [ messagename, param1, param2, ... ] or a
   MessageSpecifier instance (you might want to use ApiMessage to provide machine
@@ -3597,7 +3600,10 @@ MIME type (same as UploadVerifyFile) and the information entered by the user
 (upload comment, file page contents etc.).
 $upload: (object) An instance of UploadBase, with all info about the upload
 $user: (object) An instance of User, the user uploading this file
-$props: (array) File properties, as returned by FSFile::getPropsFromPath()
+$props: (array|null) File properties, as returned by
+  MWFileProps::getPropsFromPath(). Note this is not always guaranteed to be set,
+  e.g. in test scenarios. Call MWFileProps::getPropsFromPath() yourself in case
+  you need the information.
 $comment: (string) Upload log comment (also used as edit summary)
 $pageText: (string) File description page text (only used for new uploads)
 &$error: output: If the file upload should be prevented, set this to the reason
index 486dfe4..7256eab 100644 (file)
@@ -32,6 +32,7 @@ use MediaWiki\Session\SessionManager;
 use MediaWiki\Shell\Shell;
 use Wikimedia\ScopedCallback;
 use Wikimedia\WrappedString;
+use Wikimedia\AtEase\AtEase;
 
 /**
  * Load an extension
@@ -799,9 +800,9 @@ function wfParseUrl( $url ) {
        if ( $wasRelative ) {
                $url = "http:$url";
        }
-       Wikimedia\suppressWarnings();
+       AtEase::suppressWarnings();
        $bits = parse_url( $url );
-       Wikimedia\restoreWarnings();
+       AtEase::restoreWarnings();
        // parse_url() returns an array without scheme for some invalid URLs, e.g.
        // parse_url("%0Ahttp://example.com") == [ 'host' => '%0Ahttp', 'path' => 'example.com' ]
        if ( !$bits || !isset( $bits['scheme'] ) ) {
@@ -1846,24 +1847,6 @@ function wfNegotiateType( $cprefs, $sprefs ) {
        return $besttype;
 }
 
-/**
- * Reference-counted warning suppression
- *
- * @deprecated since 1.26, use Wikimedia\suppressWarnings() directly
- * @param bool $end
- */
-function wfSuppressWarnings( $end = false ) {
-       Wikimedia\suppressWarnings( $end );
-}
-
-/**
- * @deprecated since 1.26, use Wikimedia\restoreWarnings() directly
- * Restore error level to previous value
- */
-function wfRestoreWarnings() {
-       Wikimedia\restoreWarnings();
-}
-
 /**
  * Get a timestamp string in one of various formats
  *
@@ -1990,9 +1973,9 @@ function wfMkdirParents( $dir, $mode = null, $caller = null ) {
        }
 
        // Turn off the normal warning, we're doing our own below
-       Wikimedia\suppressWarnings();
+       AtEase::suppressWarnings();
        $ok = mkdir( $dir, $mode, true ); // PHP5 <3
-       Wikimedia\restoreWarnings();
+       AtEase::restoreWarnings();
 
        if ( !$ok ) {
                // directory may have been created on another request since we last checked
@@ -2230,9 +2213,9 @@ function wfMerge( $old, $mine, $yours, &$result, &$mergeAttemptResult = null ) {
 
        # This check may also protect against code injection in
        # case of broken installations.
-       Wikimedia\suppressWarnings();
+       AtEase::suppressWarnings();
        $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
-       Wikimedia\restoreWarnings();
+       AtEase::restoreWarnings();
 
        if ( !$haveDiff3 ) {
                wfDebug( "diff3 not found\n" );
@@ -2314,9 +2297,9 @@ function wfDiff( $before, $after, $params = '-u' ) {
        }
 
        global $wgDiff;
-       Wikimedia\suppressWarnings();
+       AtEase::suppressWarnings();
        $haveDiff = $wgDiff && file_exists( $wgDiff );
-       Wikimedia\restoreWarnings();
+       AtEase::restoreWarnings();
 
        # This check may also protect against code injection in
        # case of broken installations.
@@ -2492,7 +2475,7 @@ function wfSetupSession( $sessionId = false ) {
        if ( session_id() !== $session->getId() ) {
                session_id( $session->getId() );
        }
-       Wikimedia\quietCall( 'session_start' );
+       AtEase::quietCall( 'session_start' );
 }
 
 /**
index 16c3784..ba9e2d7 100644 (file)
@@ -62,7 +62,7 @@ class OutputHandler {
                /// @todo FIXME: this sort of dupes some code in WebRequest::getRequestUrl()
                if ( isset( $_SERVER['REQUEST_URI'] ) ) {
                        // Strip the query string...
-                       list( $path ) = explode( '?', $_SERVER['REQUEST_URI'], 2 );
+                       $path = explode( '?', $_SERVER['REQUEST_URI'], 2 )[0];
                } elseif ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
                        // Probably IIS. QUERY_STRING appears separately.
                        $path = $_SERVER['SCRIPT_NAME'];
index 588e31a..1a7175a 100644 (file)
@@ -1838,7 +1838,7 @@ class ApiMain extends ApiBase {
         */
        protected function printResult( $httpCode = 0 ) {
                if ( $this->getConfig()->get( 'DebugAPI' ) !== false ) {
-                       $this->addWarning( 'apiwarn-wgDebugAPI' );
+                       $this->addWarning( 'apiwarn-wgdebugapi' );
                }
 
                $printer = $this->mPrinter;
index acd11fd..40cd149 100644 (file)
@@ -406,7 +406,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
        protected function getExamplesMessages() {
                return [
                        'action=query&list=allimages&aifrom=B'
-                               => 'apihelp-query+allimages-example-B',
+                               => 'apihelp-query+allimages-example-b',
                        'action=query&list=allimages&aiprop=user|timestamp|url&' .
                                'aisort=timestamp&aidir=older'
                                => 'apihelp-query+allimages-example-recent',
index fc23caa..1fc5ece 100644 (file)
@@ -291,7 +291,7 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
 
                return [
                        "action=query&list={$name}&{$p}from=B&{$p}prop=ids|title"
-                               => "apihelp-$path-example-B",
+                               => "apihelp-$path-example-b",
                        "action=query&list={$name}&{$p}unique=&{$p}from=B"
                                => "apihelp-$path-example-unique",
                        "action=query&generator={$name}&g{$p}unique=&g{$p}from=B"
index 08f3ea3..ba830ae 100644 (file)
@@ -342,7 +342,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
        protected function getExamplesMessages() {
                return [
                        'action=query&list=allpages&apfrom=B'
-                               => 'apihelp-query+allpages-example-B',
+                               => 'apihelp-query+allpages-example-b',
                        'action=query&generator=allpages&gaplimit=4&gapfrom=T&prop=info'
                                => 'apihelp-query+allpages-example-generator',
                        'action=query&generator=allpages&gaplimit=2&' .
index 161cfb4..59e92e1 100644 (file)
@@ -393,7 +393,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
        protected function getExamplesMessages() {
                return [
                        'action=query&list=allusers&aufrom=Y'
-                               => 'apihelp-query+allusers-example-Y',
+                               => 'apihelp-query+allusers-example-y',
                ];
        }
 
index aded1f9..380627d 100644 (file)
        "apihelp-query+allfileusages-paramvalue-prop-title": "Adds the title of the file.",
        "apihelp-query+allfileusages-param-limit": "How many total items to return.",
        "apihelp-query+allfileusages-param-dir": "The direction in which to list.",
-       "apihelp-query+allfileusages-example-B": "List file titles, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
+       "apihelp-query+allfileusages-example-b": "List file titles, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
        "apihelp-query+allfileusages-example-unique": "List unique file titles.",
        "apihelp-query+allfileusages-example-unique-generator": "Gets all file titles, marking the missing ones.",
        "apihelp-query+allfileusages-example-generator": "Gets pages containing the files.",
        "apihelp-query+allimages-param-filterbots": "How to filter files uploaded by bots. Can only be used with $1sort=timestamp. Cannot be used together with $1user.",
        "apihelp-query+allimages-param-mime": "What MIME types to search for, e.g. <kbd>image/jpeg</kbd>.",
        "apihelp-query+allimages-param-limit": "How many images in total to return.",
-       "apihelp-query+allimages-example-B": "Show a list of files starting at the letter <kbd>B</kbd>.",
+       "apihelp-query+allimages-example-b": "Show a list of files starting at the letter <kbd>B</kbd>.",
        "apihelp-query+allimages-example-recent": "Show a list of recently uploaded files, similar to [[Special:NewFiles]].",
        "apihelp-query+allimages-example-mimetypes": "Show a list of files with MIME type <kbd>image/png</kbd> or <kbd>image/gif</kbd>",
        "apihelp-query+allimages-example-generator": "Show info about 4 files starting at the letter <kbd>T</kbd>.",
        "apihelp-query+alllinks-param-namespace": "The namespace to enumerate.",
        "apihelp-query+alllinks-param-limit": "How many total items to return.",
        "apihelp-query+alllinks-param-dir": "The direction in which to list.",
-       "apihelp-query+alllinks-example-B": "List linked titles, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
+       "apihelp-query+alllinks-example-b": "List linked titles, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
        "apihelp-query+alllinks-example-unique": "List unique linked titles.",
        "apihelp-query+alllinks-example-unique-generator": "Gets all linked titles, marking the missing ones.",
        "apihelp-query+alllinks-example-generator": "Gets pages containing the links.",
        "apihelp-query+allpages-param-dir": "The direction in which to list.",
        "apihelp-query+allpages-param-filterlanglinks": "Filter based on whether a page has langlinks. Note that this may not consider langlinks added by extensions.",
        "apihelp-query+allpages-param-prexpiry": "Which protection expiry to filter the page on:\n;indefinite:Get only pages with indefinite protection expiry.\n;definite:Get only pages with a definite (specific) protection expiry.\n;all:Get pages with any protections expiry.",
-       "apihelp-query+allpages-example-B": "Show a list of pages starting at the letter <kbd>B</kbd>.",
+       "apihelp-query+allpages-example-b": "Show a list of pages starting at the letter <kbd>B</kbd>.",
        "apihelp-query+allpages-example-generator": "Show info about 4 pages starting at the letter <kbd>T</kbd>.",
        "apihelp-query+allpages-example-generator-revisions": "Show content of first 2 non-redirect pages beginning at <kbd>Re</kbd>.",
 
        "apihelp-query+allredirects-param-namespace": "The namespace to enumerate.",
        "apihelp-query+allredirects-param-limit": "How many total items to return.",
        "apihelp-query+allredirects-param-dir": "The direction in which to list.",
-       "apihelp-query+allredirects-example-B": "List target pages, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
+       "apihelp-query+allredirects-example-b": "List target pages, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
        "apihelp-query+allredirects-example-unique": "List unique target pages.",
        "apihelp-query+allredirects-example-unique-generator": "Gets all target pages, marking the missing ones.",
        "apihelp-query+allredirects-example-generator": "Gets pages containing the redirects.",
        "apihelp-query+alltransclusions-param-namespace": "The namespace to enumerate.",
        "apihelp-query+alltransclusions-param-limit": "How many total items to return.",
        "apihelp-query+alltransclusions-param-dir": "The direction in which to list.",
-       "apihelp-query+alltransclusions-example-B": "List transcluded titles, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
+       "apihelp-query+alltransclusions-example-b": "List transcluded titles, including missing ones, with page IDs they are from, starting at <kbd>B</kbd>.",
        "apihelp-query+alltransclusions-example-unique": "List unique transcluded titles.",
        "apihelp-query+alltransclusions-example-unique-generator": "Gets all transcluded titles, marking the missing ones.",
        "apihelp-query+alltransclusions-example-generator": "Gets pages containing the transclusions.",
        "apihelp-query+allusers-param-witheditsonly": "Only list users who have made edits.",
        "apihelp-query+allusers-param-activeusers": "Only list users active in the last $1 {{PLURAL:$1|day|days}}.",
        "apihelp-query+allusers-param-attachedwiki": "With <kbd>$1prop=centralids</kbd>, also indicate whether the user is attached with the wiki identified by this ID.",
-       "apihelp-query+allusers-example-Y": "List users starting at <kbd>Y</kbd>.",
+       "apihelp-query+allusers-example-y": "List users starting at <kbd>Y</kbd>.",
 
        "apihelp-query+authmanagerinfo-summary": "Retrieve information about the current authentication status.",
        "apihelp-query+authmanagerinfo-param-securitysensitiveoperation": "Test whether the user's current authentication status is sufficient for the specified security-sensitive operation.",
        "apiwarn-validationfailed-cannotset": "cannot be set by this module.",
        "apiwarn-validationfailed-keytoolong": "key too long (no more than $1 bytes allowed).",
        "apiwarn-validationfailed": "Validation error for <kbd>$1</kbd>: $2",
-       "apiwarn-wgDebugAPI": "<strong>Security Warning</strong>: <var>$wgDebugAPI</var> is enabled.",
+       "apiwarn-wgdebugapi": "<strong>Security Warning</strong>: <var>$wgDebugAPI</var> is enabled.",
 
        "api-feed-error-title": "Error ($1)",
        "api-usage-docref": "See $1 for API usage.",
index 06ac6a7..d1dcfe9 100644 (file)
        "apihelp-query+allfileusages-paramvalue-prop-title": "{{doc-apihelp-paramvalue|query+allfileusages|prop|title}}",
        "apihelp-query+allfileusages-param-limit": "{{doc-apihelp-param|query+allfileusages|limit}}",
        "apihelp-query+allfileusages-param-dir": "{{doc-apihelp-param|query+allfileusages|dir}}",
-       "apihelp-query+allfileusages-example-B": "{{doc-apihelp-example|query+allfileusages}}",
+       "apihelp-query+allfileusages-example-b": "{{doc-apihelp-example|query+allfileusages}}",
        "apihelp-query+allfileusages-example-unique": "{{doc-apihelp-example|query+allfileusages}}",
        "apihelp-query+allfileusages-example-unique-generator": "{{doc-apihelp-example|query+allfileusages}}",
        "apihelp-query+allfileusages-example-generator": "{{doc-apihelp-example|query+allfileusages}}",
        "apihelp-query+allimages-param-filterbots": "{{doc-apihelp-param|query+allimages|filterbots}}",
        "apihelp-query+allimages-param-mime": "{{doc-apihelp-param|query+allimages|mime}}",
        "apihelp-query+allimages-param-limit": "{{doc-apihelp-param|query+allimages|limit}}",
-       "apihelp-query+allimages-example-B": "{{doc-apihelp-example|query+allimages}}",
+       "apihelp-query+allimages-example-b": "{{doc-apihelp-example|query+allimages}}",
        "apihelp-query+allimages-example-recent": "{{doc-apihelp-example|query+allimages}}",
        "apihelp-query+allimages-example-mimetypes": "{{doc-apihelp-example|query+allimages}}",
        "apihelp-query+allimages-example-generator": "{{doc-apihelp-example|query+allimages}}",
        "apihelp-query+alllinks-param-namespace": "{{doc-apihelp-param|query+alllinks|namespace}}",
        "apihelp-query+alllinks-param-limit": "{{doc-apihelp-param|query+alllinks|limit}}",
        "apihelp-query+alllinks-param-dir": "{{doc-apihelp-param|query+alllinks|dir}}",
-       "apihelp-query+alllinks-example-B": "{{doc-apihelp-example|query+alllinks}}",
+       "apihelp-query+alllinks-example-b": "{{doc-apihelp-example|query+alllinks}}",
        "apihelp-query+alllinks-example-unique": "{{doc-apihelp-example|query+alllinks}}",
        "apihelp-query+alllinks-example-unique-generator": "{{doc-apihelp-example|query+alllinks}}",
        "apihelp-query+alllinks-example-generator": "{{doc-apihelp-example|query+alllinks}}",
        "apihelp-query+allpages-param-dir": "{{doc-apihelp-param|query+allpages|dir}}",
        "apihelp-query+allpages-param-filterlanglinks": "{{doc-apihelp-param|query+allpages|filterlanglinks}}",
        "apihelp-query+allpages-param-prexpiry": "{{doc-apihelp-param|query+allpages|prexpiry}}",
-       "apihelp-query+allpages-example-B": "{{doc-apihelp-example|query+allpages}}",
+       "apihelp-query+allpages-example-b": "{{doc-apihelp-example|query+allpages}}",
        "apihelp-query+allpages-example-generator": "{{doc-apihelp-example|query+allpages}}",
        "apihelp-query+allpages-example-generator-revisions": "{{doc-apihelp-example|query+allpages}}",
        "apihelp-query+allredirects-summary": "{{doc-apihelp-summary|query+allredirects}}",
        "apihelp-query+allredirects-param-namespace": "{{doc-apihelp-param|query+allredirects|namespace}}",
        "apihelp-query+allredirects-param-limit": "{{doc-apihelp-param|query+allredirects|limit}}",
        "apihelp-query+allredirects-param-dir": "{{doc-apihelp-param|query+allredirects|dir}}",
-       "apihelp-query+allredirects-example-B": "{{doc-apihelp-example|query+allredirects}}",
+       "apihelp-query+allredirects-example-b": "{{doc-apihelp-example|query+allredirects}}",
        "apihelp-query+allredirects-example-unique": "{{doc-apihelp-example|query+allredirects}}",
        "apihelp-query+allredirects-example-unique-generator": "{{doc-apihelp-example|query+allredirects}}",
        "apihelp-query+allredirects-example-generator": "{{doc-apihelp-example|query+allredirects}}",
        "apihelp-query+alltransclusions-param-namespace": "{{doc-apihelp-param|query+alltransclusions|namespace}}",
        "apihelp-query+alltransclusions-param-limit": "{{doc-apihelp-param|query+alltransclusions|limit}}",
        "apihelp-query+alltransclusions-param-dir": "{{doc-apihelp-param|query+alltransclusions|dir}}",
-       "apihelp-query+alltransclusions-example-B": "{{doc-apihelp-example|query+alltransclusions}}",
+       "apihelp-query+alltransclusions-example-b": "{{doc-apihelp-example|query+alltransclusions}}",
        "apihelp-query+alltransclusions-example-unique": "{{doc-apihelp-example|query+alltransclusions}}",
        "apihelp-query+alltransclusions-example-unique-generator": "{{doc-apihelp-example|query+alltransclusions}}",
        "apihelp-query+alltransclusions-example-generator": "{{doc-apihelp-example|query+alltransclusions}}",
        "apihelp-query+allusers-param-witheditsonly": "{{doc-apihelp-param|query+allusers|witheditsonly}}",
        "apihelp-query+allusers-param-activeusers": "{{doc-apihelp-param|query+allusers|activeusers|params=* $1 - Value of [[mw:Manual:$wgActiveUserDays]]|paramstart=2}}",
        "apihelp-query+allusers-param-attachedwiki": "{{doc-apihelp-param|query+allusers|attachedwiki}}",
-       "apihelp-query+allusers-example-Y": "{{doc-apihelp-example|query+allusers}}",
+       "apihelp-query+allusers-example-y": "{{doc-apihelp-example|query+allusers}}",
        "apihelp-query+authmanagerinfo-summary": "{{doc-apihelp-summary|query+authmanagerinfo}}",
        "apihelp-query+authmanagerinfo-param-securitysensitiveoperation": "{{doc-apihelp-param|query+authmanagerinfo|securitysensitiveoperation}}",
        "apihelp-query+authmanagerinfo-param-requestsfor": "{{doc-apihelp-param|query+authmanagerinfo|requestsfor}}",
        "apiwarn-validationfailed-cannotset": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
        "apiwarn-validationfailed-keytoolong": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.\n\nParameters:\n* $1 - Maximum allowed key length in bytes.",
        "apiwarn-validationfailed": "{{doc-apierror}}\n\nParameters:\n* $1 - User preference name.\n* $2 - Failure message, such as {{msg-mw|apiwarn-validationfailed-badpref}}. Probably already ends with punctuation",
-       "apiwarn-wgDebugAPI": "{{doc-apierror}}",
+       "apiwarn-wgdebugapi": "{{doc-apierror}}",
        "api-feed-error-title": "Used as a feed item title when an error occurs in <kbd>action=feedwatchlist</kbd>.\n\nParameters:\n* $1 - API error code\n{{Identical|Error}}",
        "api-usage-docref": "\n\nParameters:\n* $1 - URL of the API auto-generated documentation.",
        "api-usage-mailinglist-ref": "{{doc-apierror}} Also used in the error response.",
index 6f6887b..37a49be 100644 (file)
@@ -640,7 +640,7 @@ class ChangesList extends ContextSource {
                return $this->watchMsgCache->getWithSetCallback(
                        "watching-users-msg:$count",
                        function () use ( $count ) {
-                               return $this->msg( 'number_of_watching_users_RCview' )
+                               return $this->msg( 'number-of-watching-users-for-recent-changes' )
                                        ->numParams( $count )->escaped();
                        }
                );
index 2874c33..d48eb0e 100644 (file)
@@ -189,19 +189,12 @@ class ConfigRepository implements SalvageableService {
        public function salvage( SalvageableService $other ) {
                Assert::parameterType( self::class, $other, '$other' );
 
-               /** @var ConfigRepository $other */
-               $otherCurrentObj = $other->current();
                foreach ( $other->configItems['public'] as $name => $otherConfig ) {
                        if ( isset( $this->configItems['public'][$name] ) ) {
                                continue;
                        }
 
                        $this->add( $name, $otherConfig );
-
-                       // recover the pointer of the other config repository
-                       if ( $otherCurrentObj === $otherConfig ) {
-                               end( $this->configItems['public'] );
-                       }
                }
                foreach ( $other->configItems['private'] as $name => $otherConfig ) {
                        if ( isset( $this->configItems['private'][$name] ) ) {
@@ -209,11 +202,6 @@ class ConfigRepository implements SalvageableService {
                        }
 
                        $this->add( $name, $otherConfig );
-
-                       // recover the pointer of the other config repository
-                       if ( $otherCurrentObj === $otherConfig ) {
-                               end( $this->configItems['private'] );
-                       }
                }
 
                // disable $other
index 546a12c..ce507d7 100644 (file)
@@ -506,13 +506,13 @@ class DiffEngine {
 
                // value_to_add_forward: a 0 or 1 that we add to the start
                // offset to make it odd/even
-               if ( ( $M & 1 ) == 1 ) {
+               if ( $M & 1 ) {
                        $value_to_add_forward = 1;
                } else {
                        $value_to_add_forward = 0;
                }
 
-               if ( ( $N & 1 ) == 1 ) {
+               if ( $N & 1 ) {
                        $value_to_add_backward = 1;
                } else {
                        $value_to_add_backward = 0;
@@ -530,7 +530,7 @@ class DiffEngine {
                $V1[$limit_min_1] = $N;
                $limit = min( $this->maxDifferences, ceil( ( $N + $M ) / 2 ) );
 
-               if ( ( $delta & 1 ) == 1 ) {
+               if ( $delta & 1 ) {
                        for ( $d = 0; $d <= $limit; ++$d ) {
                                $start_diag = max( $value_to_add_forward + $start_forward, -$d );
                                $end_diag = min( $end_forward, $d );
index 5c3d1d0..26f9bf0 100644 (file)
@@ -494,7 +494,7 @@ abstract class Installer {
 
                $good = true;
                // Must go here because an old version of PCRE can prevent other checks from completing
-               list( $pcreVersion ) = explode( ' ', PCRE_VERSION, 2 );
+               $pcreVersion = explode( ' ', PCRE_VERSION, 2 )[0];
                if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
                        $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
                        $good = false;
index fde43f4..13a39ed 100644 (file)
@@ -111,7 +111,7 @@ class DjVuImage {
                                $this->dumpForm( $file, $chunkLength, $indent + 1 );
                        } else {
                                fseek( $file, $chunkLength, SEEK_CUR );
-                               if ( ( $chunkLength & 1 ) == 1 ) {
+                               if ( $chunkLength & 1 ) {
                                        // Padding byte between chunks
                                        fseek( $file, 1, SEEK_CUR );
                                }
@@ -169,7 +169,7 @@ class DjVuImage {
        private function skipChunk( $file, $chunkLength ) {
                fseek( $file, $chunkLength, SEEK_CUR );
 
-               if ( ( $chunkLength & 0x01 ) == 1 && !feof( $file ) ) {
+               if ( ( $chunkLength & 1 ) && !feof( $file ) ) {
                        // padding byte
                        fseek( $file, 1, SEEK_CUR );
                }
index 345b3cb..333c610 100644 (file)
@@ -1181,7 +1181,7 @@ class FormatMetadata extends ContextSource {
                $langName = Language::fetchLanguageName( $lowLang );
                if ( $langName === '' ) {
                        // try just the base language name. (aka en-US -> en ).
-                       list( $langPrefix ) = explode( '-', $lowLang, 2 );
+                       $langPrefix = explode( '-', $lowLang, 2 )[0];
                        $langName = Language::fetchLanguageName( $langPrefix );
                        if ( $langName === '' ) {
                                // give up.
index 109097a..20b9445 100644 (file)
@@ -26,6 +26,7 @@ use MediaWiki\ShellDisabledError;
 use Profiler;
 use Psr\Log\LoggerAwareTrait;
 use Psr\Log\NullLogger;
+use Wikimedia\AtEase\AtEase;
 
 /**
  * Class used for executing shell commands
@@ -431,9 +432,9 @@ class Command {
                        // TODO replace with clear_last_error when requirements are bumped to PHP7
                        set_error_handler( function () {
                        }, 0 );
-                       \Wikimedia\suppressWarnings();
+                       AtEase::suppressWarnings();
                        trigger_error( '' );
-                       \Wikimedia\restoreWarnings();
+                       AtEase::restoreWarnings();
                        restore_error_handler();
 
                        $readPipes = array_filter( $pipes, function ( $fd ) use ( $desc ) {
index 7254746..d355db6 100644 (file)
@@ -55,7 +55,8 @@ abstract class Skin extends ContextSource {
         * @return array Associative array of strings
         */
        static function getSkinNames() {
-               return SkinFactory::getDefaultInstance()->getSkinNames();
+               $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
+               return $skinFactory->getSkinNames();
        }
 
        /**
@@ -517,6 +518,7 @@ abstract class Skin extends ContextSource {
        function getCategoryLinks() {
                $out = $this->getOutput();
                $allCats = $out->getCategoryLinks();
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
 
                if ( $allCats === [] ) {
                        return '';
@@ -531,10 +533,10 @@ abstract class Skin extends ContextSource {
                if ( !empty( $allCats['normal'] ) ) {
                        $t = $embed . implode( $pop . $embed, $allCats['normal'] ) . $pop;
 
-                       $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) )->escaped();
+                       $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) );
                        $linkPage = $this->msg( 'pagecategorieslink' )->inContentLanguage()->text();
                        $title = Title::newFromText( $linkPage );
-                       $link = $title ? Linker::link( $title, $msg ) : $msg;
+                       $link = $title ? $linkRenderer->makeLink( $title, $msg->text() ) : $msg->escaped();
                        $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
                                $link . $colon . '<ul>' . $t . '</ul></div>';
                }
@@ -582,6 +584,7 @@ abstract class Skin extends ContextSource {
         */
        function drawCategoryBrowser( $tree ) {
                $return = '';
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
 
                foreach ( $tree as $element => $parent ) {
                        if ( empty( $parent ) ) {
@@ -594,7 +597,7 @@ abstract class Skin extends ContextSource {
 
                        # add our current element to the list
                        $eltitle = Title::newFromText( $element );
-                       $return .= Linker::link( $eltitle, htmlspecialchars( $eltitle->getText() ) );
+                       $return .= $linkRenderer->makeLink( $eltitle, $eltitle->getText() );
                }
 
                return $return;
@@ -716,6 +719,7 @@ abstract class Skin extends ContextSource {
        function getUndeleteLink() {
                $action = $this->getRequest()->getVal( 'action', 'view' );
                $title = $this->getTitle();
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
 
                if ( ( !$title->exists() || $action == 'history' ) &&
                        $title->quickUserCan( 'deletedhistory', $this->getUser() )
@@ -730,9 +734,9 @@ abstract class Skin extends ContextSource {
                                }
 
                                return $this->msg( $msg )->rawParams(
-                                       Linker::linkKnown(
+                                       $linkRenderer->makeKnownLink(
                                                SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
-                                               $this->msg( 'restorelink' )->numParams( $n )->escaped() )
+                                               $this->msg( 'restorelink' )->numParams( $n )->text() )
                                        )->escaped();
                        }
                }
@@ -745,6 +749,7 @@ abstract class Skin extends ContextSource {
         * @return string
         */
        function subPageSubtitle( $out = null ) {
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( $out === null ) {
                        $out = $this->getOutput();
                }
@@ -774,9 +779,8 @@ abstract class Skin extends ContextSource {
                                        $linkObj = Title::newFromText( $growinglink );
 
                                        if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
-                                               $getlink = Linker::linkKnown(
-                                                       $linkObj,
-                                                       htmlspecialchars( $display )
+                                               $getlink = $linkRenderer->makeKnownLink(
+                                                       $linkObj, $display
                                                );
 
                                                $c++;
@@ -820,6 +824,7 @@ abstract class Skin extends ContextSource {
         * @return string
         */
        function getCopyright( $type = 'detect' ) {
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( $type == 'detect' ) {
                        if ( !$this->isRevisionCurrent()
                                && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
@@ -840,7 +845,9 @@ abstract class Skin extends ContextSource {
 
                if ( $config->get( 'RightsPage' ) ) {
                        $title = Title::newFromText( $config->get( 'RightsPage' ) );
-                       $link = Linker::linkKnown( $title, $config->get( 'RightsText' ) );
+                       $link = $linkRenderer->makeKnownLink(
+                               $title, new HtmlArmor( $config->get( 'RightsText' ) )
+                       );
                } elseif ( $config->get( 'RightsUrl' ) ) {
                        $link = Linker::makeExternalLink( $config->get( 'RightsUrl' ), $config->get( 'RightsText' ) );
                } elseif ( $config->get( 'RightsText' ) ) {
@@ -996,9 +1003,10 @@ abstract class Skin extends ContextSource {
         * @return string
         */
        function mainPageLink() {
-               $s = Linker::linkKnown(
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+               $s = $linkRenderer->makeKnownLink(
                        Title::newMainPage(),
-                       $this->msg( 'mainpage' )->escaped()
+                       $this->msg( 'mainpage' )->text()
                );
 
                return $s;
@@ -1012,13 +1020,14 @@ abstract class Skin extends ContextSource {
         */
        public function footerLink( $desc, $page ) {
                $title = $this->footerLinkTitle( $desc, $page );
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( !$title ) {
                        return '';
                }
 
-               return Linker::linkKnown(
+               return $linkRenderer->makeKnownLink(
                        $title,
-                       $this->msg( $desc )->escaped()
+                       $this->msg( $desc )->text()
                );
        }
 
@@ -1438,6 +1447,7 @@ abstract class Skin extends ContextSource {
                $user = $this->getUser();
                $newtalks = $user->getNewMessageLinks();
                $out = $this->getOutput();
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
 
                // Allow extensions to disable or modify the new messages alert
                if ( !Hooks::run( 'GetNewMessagesAlert', [ &$newMessagesAlert, $newtalks, $user, $out ] ) ) {
@@ -1468,16 +1478,16 @@ abstract class Skin extends ContextSource {
                        // 999 signifies "more than one revision". We don't know how many, and even if we did,
                        // the number of revisions or authors is not necessarily the same as the number of
                        // "messages".
-                       $newMessagesLink = Linker::linkKnown(
+                       $newMessagesLink = $linkRenderer->makeKnownLink(
                                $uTalkTitle,
-                               $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
+                               $this->msg( 'newmessageslinkplural' )->params( $plural )->text(),
                                [],
                                $uTalkTitle->isRedirect() ? [ 'redirect' => 'no' ] : []
                        );
 
-                       $newMessagesDiffLink = Linker::linkKnown(
+                       $newMessagesDiffLink = $linkRenderer->makeKnownLink(
                                $uTalkTitle,
-                               $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
+                               $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->text(),
                                [],
                                $lastSeenRev !== null
                                        ? [ 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' ]
@@ -1634,11 +1644,12 @@ abstract class Skin extends ContextSource {
 
                $result = '<span class="mw-editsection"><span class="mw-editsection-bracket">[</span>';
 
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                $linksHtml = [];
                foreach ( $links as $k => $linkDetails ) {
-                       $linksHtml[] = Linker::linkKnown(
+                       $linksHtml[] = $linkRenderer->makeKnownLink(
                                $linkDetails['targetTitle'],
-                               htmlspecialchars( $linkDetails['text'] ),
+                               $linkDetails['text'],
                                $linkDetails['attribs'],
                                $linkDetails['query']
                        );
index 2470b41..a9debb3 100644 (file)
@@ -159,7 +159,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
 
                        [
                                'name' => 'userExpLevel',
-                               'title' => 'rcfilters-filtergroup-userExpLevel',
+                               'title' => 'rcfilters-filtergroup-user-experience-level',
                                'class' => ChangesListStringOptionsFilterGroup::class,
                                'isFullCoverage' => true,
                                'filters' => [
@@ -354,7 +354,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
 
                        [
                                'name' => 'lastRevision',
-                               'title' => 'rcfilters-filtergroup-lastRevision',
+                               'title' => 'rcfilters-filtergroup-lastrevision',
                                'class' => ChangesListBooleanFilterGroup::class,
                                'priority' => -7,
                                'filters' => [
index 46873b1..b8fde7d 100644 (file)
@@ -384,7 +384,7 @@ abstract class QueryPage extends SpecialPage {
 
        /**
         * Get a DB connection to be used for slow recache queries
-        * @return \Wikimedia\Rdbms\Database
+        * @return IDatabase
         */
        function getRecacheDB() {
                return wfGetDB( DB_REPLICA, [ $this->getName(), 'QueryPage::recache', 'vslow' ] );
index 878440d..f6b8b90 100644 (file)
@@ -43,7 +43,7 @@ class SpecialAllMessages extends SpecialPage {
                $this->setHeaders();
 
                if ( !$this->getConfig()->get( 'UseDatabaseMessages' ) ) {
-                       $out->addWikiMsg( 'allmessagesnotsupportedDB' );
+                       $out->addWikiMsg( 'allmessages-not-supported-database' );
 
                        return;
                }
@@ -77,10 +77,10 @@ class SpecialAllMessages extends SpecialPage {
                                'type' => 'radio',
                                'name' => 'filter',
                                'label-message' => 'allmessages-filter',
-                               'options' => [
-                                       $this->msg( 'allmessages-filter-unmodified' )->text() => 'unmodified',
-                                       $this->msg( 'allmessages-filter-all' )->text() => 'all',
-                                       $this->msg( 'allmessages-filter-modified' )->text() => 'modified',
+                               'options-messages' => [
+                                       'allmessages-filter-unmodified' => 'unmodified',
+                                       'allmessages-filter-all' => 'all',
+                                       'allmessages-filter-modified' => 'modified',
                                ],
                                'default' => 'all',
                                'flatlist' => true,
index c4e4635..49f1b3c 100644 (file)
@@ -61,8 +61,8 @@ class SpecialRedirect extends FormSpecialPage {
        function setParameter( $subpage ) {
                // parse $subpage to pull out the parts
                $parts = explode( '/', $subpage, 2 );
-               $this->mType = count( $parts ) > 0 ? $parts[0] : null;
-               $this->mValue = count( $parts ) > 1 ? $parts[1] : null;
+               $this->mType = $parts[0];
+               $this->mValue = $parts[1] ?? null;
        }
 
        /**
index d09b345..a2dbb72 100644 (file)
@@ -249,6 +249,7 @@ class BlockListPager extends TablePager {
         */
        private function getRestrictionListHTML( stdClass $row ) {
                $items = [];
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
 
                foreach ( $this->restrictions as $restriction ) {
                        if ( $restriction->getBlockId() !== (int)$row->ipb_id ) {
@@ -261,20 +262,20 @@ class BlockListPager extends TablePager {
                                                $items[$restriction->getType()][] = Html::rawElement(
                                                        'li',
                                                        [],
-                                                       Linker::link( $restriction->getTitle() )
+                                                       $linkRenderer->makeLink( $restriction->getTitle() )
                                                );
                                        }
                                        break;
                                case NamespaceRestriction::TYPE:
                                        $text = $restriction->getValue() === NS_MAIN
-                                               ? $this->msg( 'blanknamespace' )
+                                               ? $this->msg( 'blanknamespace' )->text()
                                                : $this->getLanguage()->getFormattedNsText(
                                                        $restriction->getValue()
                                                );
                                        $items[$restriction->getType()][] = Html::rawElement(
                                                'li',
                                                [],
-                                               Linker::link(
+                                               $linkRenderer->makeLink(
                                                        SpecialPage::getTitleValueFor( 'Allpages' ),
                                                        $text,
                                                        [],
index 56b799b..11a8532 100644 (file)
@@ -50,7 +50,7 @@ class DeletedContribsPager extends IndexPager {
        public $namespace = '';
 
        /**
-        * @var \Wikimedia\Rdbms\Database
+        * @var IDatabase
         */
        public $mDb;
 
index d08eb89..57b575b 100644 (file)
@@ -277,7 +277,7 @@ class UsersPager extends AlphabeticPager {
         * @return string
         */
        function getPageHeader() {
-               list( $self ) = explode( '/', $this->getTitle()->getPrefixedDBkey() );
+               $self = explode( '/', $this->getTitle()->getPrefixedDBkey(), 2 )[0];
 
                $groupOptions = [ $this->msg( 'group-all' )->text() => '' ];
                foreach ( $this->getAllGroups() as $group => $groupText ) {
index acd6970..e06df9f 100644 (file)
@@ -395,12 +395,13 @@ class UserGroupMembership {
 
                // link to the group description page, if it exists
                $linkTitle = self::getGroupPage( $group );
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( $linkTitle ) {
                        if ( $format === 'wiki' ) {
                                $linkPage = $linkTitle->getFullText();
                                $groupLink = "[[$linkPage|$groupName]]";
                        } else {
-                               $groupLink = Linker::link( $linkTitle, htmlspecialchars( $groupName ) );
+                               $groupLink = $linkRenderer->makeLink( $linkTitle, $groupName );
                        }
                } else {
                        $groupLink = htmlspecialchars( $groupName );
index 15edfc0..71f5633 100644 (file)
        "virus-scanfailed": "scan failed (code $1)",
        "virus-unknownscanner": "unknown antivirus:",
        "logouttext": "<strong>You are now logged out.</strong>\n\nNote that some pages may continue to be displayed as if you were still logged in, until you clear your browser cache.",
+       "logging-out-notify": "You are being logged out, please wait.",
+       "logout-failed": "Cannot log out now: $1",
        "cannotlogoutnow-title": "Cannot log out now",
        "cannotlogoutnow-text": "Logging out is not possible when using $1.",
        "welcomeuser": "Welcome, $1!",
        "rcfilters-filter-editsbyself-description": "Your own contributions.",
        "rcfilters-filter-editsbyother-label": "Changes by others",
        "rcfilters-filter-editsbyother-description": "All changes except your own.",
-       "rcfilters-filtergroup-userExpLevel": "User registration and experience",
+       "rcfilters-filtergroup-user-experience-level": "User registration and experience",
        "rcfilters-filter-user-experience-level-registered-label": "Registered",
        "rcfilters-filter-user-experience-level-registered-description": "Logged-in editors.",
        "rcfilters-filter-user-experience-level-unregistered-label": "Unregistered",
        "rcfilters-hideminor-conflicts-typeofchange-global": "The \"Minor edits\" filter conflicts with one or more Type of change filters, because certain types of change cannot be designated as \"minor\". The conflicting filters are marked in the Active filters area, above.",
        "rcfilters-hideminor-conflicts-typeofchange": "Certain types of change cannot be designated as \"minor\", so this filter conflicts with the following Type of Change filters: $1",
        "rcfilters-typeofchange-conflicts-hideminor": "This Type of change filter conflicts with the \"Minor edits\" filter. Certain types of change cannot be designated as \"minor\".",
-       "rcfilters-filtergroup-lastRevision": "Latest revisions",
+       "rcfilters-filtergroup-lastrevision": "Latest revisions",
        "rcfilters-filter-lastrevision-label": "Latest revision",
        "rcfilters-filter-lastrevision-description": "Only the most recent change to a page.",
        "rcfilters-filter-previousrevision-label": "Not the latest revision",
        "newpageletter": "N",
        "boteditletter": "b",
        "unpatrolledletter": "!",
-       "number_of_watching_users_RCview": "[$1]",
-       "number_of_watching_users_pageview": "[$1 watching {{PLURAL:$1|user|users}}]",
+       "number-of-watching-users-for-recent-changes": "[$1]",
        "rc-change-size": "$1",
        "rc-change-size-new": "$1 {{PLURAL:$1|byte|bytes}} after change",
        "newsectionsummary": "/* $1 */ new section",
        "img-auth-nopathinfo": "Missing path information.\nYour server must be set up to pass the REQUEST_URI and/or PATH_INFO variables.\nIf it is, try enabling $wgUsePathInfo.\nSee https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "img-auth-notindir": "Requested path is not in the configured upload directory.",
        "img-auth-badtitle": "Unable to construct a valid title from \"$1\".",
-       "img-auth-nologinnWL": "You are not logged in and \"$1\" is not in the whitelist.",
        "img-auth-nofile": "File \"$1\" does not exist.",
        "img-auth-isdir": "You are trying to access a directory \"$1\".\nOnly file access is allowed.",
        "img-auth-streaming": "Streaming \"$1\".",
        "allmessagesdefault": "Default message text",
        "allmessagescurrent": "Current message text",
        "allmessagestext": "This is a list of system messages available in the MediaWiki namespace.\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [https://translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
-       "allmessagesnotsupportedDB": "This page cannot be used because <strong>$wgUseDatabaseMessages</strong> has been disabled.",
+       "allmessages-not-supported-database": "This page cannot be used because <strong>$wgUseDatabaseMessages</strong> has been disabled.",
        "allmessages-filter-legend": "Filter",
        "allmessages-filter": "Filter by customization state:",
        "allmessages-filter-unmodified": "Unmodified",
index 972e37a..4c835af 100644 (file)
        "virus-scanfailed": "Used as error message. \"scan\" stands for \"virus scan\". Parameters:\n* $1 - exit code of virus scanner",
        "virus-unknownscanner": "Used as error message. This message is followed by the virus scanner name.",
        "logouttext": "Log out message. Parameters:\n* $1 - (Unused) an URL to [[Special:Userlogin]] containing <code>returnto</code> and <code>returntoquery</code> parameters",
+       "logging-out-notify": "The message when the user is being logged out",
+       "logout-failed": "Message when log out fails in notification popup. Parameters:\n* $1 - Error message",
        "cannotlogoutnow-title": "Error page title shown when logging out is not possible.",
        "cannotlogoutnow-text": "Error page text shown when logging out is not possible. Parameters:\n* $1 - Session type in use that makes it not possible to log out, from a message like {{msg-mw|sessionprovider-mediawiki-session-cookiesessionprovider}}.",
        "welcomeuser": "Text for a welcome heading that users see after registering a user account.\n\nParameters:\n* $1 - the username of the new user. See [[phab:T44215]]",
        "rcfilters-filter-editsbyself-description": "Description for the filter for showing edits made by the current user.",
        "rcfilters-filter-editsbyother-label": "Label for the filter for showing edits made by anyone other than the current user.",
        "rcfilters-filter-editsbyother-description": "Description for the filter for showing edits made by anyone other than the current user.",
-       "rcfilters-filtergroup-userExpLevel": "Title for the filter group for user experience levels.",
+       "rcfilters-filtergroup-user-experience-level": "Title for the filter group for user experience levels.",
        "rcfilters-filter-user-experience-level-registered-label": "Label for the filter for showing edits made by logged-in editors.",
        "rcfilters-filter-user-experience-level-registered-description": "Description for the filter for showing edits made by logged-in editors.",
        "rcfilters-filter-user-experience-level-unregistered-label": "Label for the filter for showing edits made by anonymous editors.",
        "rcfilters-hideminor-conflicts-typeofchange-global": "The \"Minor edits\" filter is conflicting with one or more Type of Change filters, because certain types of change cannot be designated as \"minor.\" The conflicting filters are marked in the Active Filters area, above.\n\n\"Type of Change\" is {{msg-mw|Rcfilters-filtergroup-changetype}}.",
        "rcfilters-hideminor-conflicts-typeofchange": "Tooltip shown when hovering over the Minor edits tag, when a Type of Change filter is also selected.\n\n\"Minor edits\" is {{msg-mw|rcfilters-filter-minor-label}}.\n\n\"Type of change\" is {{msg-mw|rcfilters-filtergroup-changetype}}.\n\nThis indicates that no results will be shown.  Parameters:\n* $1 - Comma-separated string of selected Type of Change filters, e.g. \"Category, Logged Actions\"\n* $2 - Count of selected User Experience Level filters, for PLURAL",
        "rcfilters-typeofchange-conflicts-hideminor": "Tooltip shown when hovering over a Type of change filter tag, when the Minor edits filter is also selected.\n\n\"Minor edits\" is {{msg-mw|rcfilters-filter-minor-label}}.\n\n\"Type of change\" is {{msg-mw|rcfilters-filtergroup-changetype}}.\n\nThis indicates that no results will be shown.",
-       "rcfilters-filtergroup-lastRevision": "Title for the filter group for last revision",
+       "rcfilters-filtergroup-lastrevision": "Title for the filter group for last revision",
        "rcfilters-filter-lastrevision-label": "Title for the filter for showing changes on last revision of a page.",
        "rcfilters-filter-lastrevision-description": "Description for the filter for showing changes on last revision of a page.",
        "rcfilters-filter-previousrevision-label": "Title for the filter for showing changes on previous revisions of a page.",
        "newpageletter": "Very short form of \"'''new page'''\". Used in [[Special:RecentChanges]], [[Special:Watchlist]] and [[Special:Contributions]].\n\n{{Rc single letters}}",
        "boteditletter": "Abbreviation of \"'''bot'''\". Appears in [[Special:RecentChanges]] and [[Special:Watchlist]].\n\n{{Rc single letters}}",
        "unpatrolledletter": "{{optional}}\n\nUsed in {{msg-mw|Recentchanges-label-legend}}, meaning \"unpatrolled\".\n\n{{Rc single letters}}",
-       "number_of_watching_users_RCview": "{{notranslate}}\nParameters:\n* $1 - number of users who are watching",
-       "number_of_watching_users_pageview": "Used if <code>$wgPageShowWatchingUsers</code> is true.\n* $1 - number of watching user(s)",
+       "number-of-watching-users-for-recent-changes": "{{notranslate}}\nParameters:\n* $1 - number of users who are watching",
        "rc-change-size": "{{optional}}\nDoes not work under $wgMiserMode ([[mwr:48986|r48986]]).\n\nParameters:\n* $1 - size of diff",
        "rc-change-size-new": "Tooltip when hovering a change list diff size. Parameters:\n* $1 - the resulting new size (in bytes)",
        "newsectionsummary": "Default summary when adding a new section to a page. Parameters:\n* $1 - section title",
        "img-auth-nopathinfo": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Missing PATH_INFO - see english description\n{{Doc-important|This is plain text. Do not use any wiki syntax.}}",
        "img-auth-notindir": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: When the specified path is not in upload directory.",
        "img-auth-badtitle": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Bad title, $1 is the invalid title",
-       "img-auth-nologinnWL": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Logged in and file not whitelisted.  $1 is the file not in whitelist.",
        "img-auth-nofile": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Non existent file, $1 is the file that does not exist.",
        "img-auth-isdir": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Trying to access a directory instead of a file, $1 is the directory.",
        "img-auth-streaming": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Is now streaming file specified by $1.",
        "allmessagesdefault": "The header for the lower row of each column in the table of [[Special:AllMessages]].",
        "allmessagescurrent": "The header for the upper row of each column in the table of [[Special:AllMessages]].",
        "allmessagestext": "Summary displayed at the top of [[Special:AllMessages]].",
-       "allmessagesnotsupportedDB": "This message is displayed on [[Special:AllMessages]] on wikis were the configuration variable $wgUseDatabaseMessages is disabled. It means that the MediaWiki namespace is not used.",
+       "allmessages-not-supported-database": "This message is displayed on [[Special:AllMessages]] on wikis were the configuration variable $wgUseDatabaseMessages is disabled. It means that the MediaWiki namespace is not used.",
        "allmessages-filter-legend": "Used in [[Special:AllMessages]].\n\n{{Identical|Filter}}",
        "allmessages-filter": "Option used in [[Special:AllMessages]].",
        "allmessages-filter-unmodified": "Used in [[Special:AllMessages]].",
index 50fb6dc..b6c7ae4 100755 (executable)
@@ -64,7 +64,7 @@ class UpdateMediaWiki extends Maintenance {
        function compatChecks() {
                $minimumPcreVersion = Installer::MINIMUM_PCRE_VERSION;
 
-               list( $pcreVersion ) = explode( ' ', PCRE_VERSION, 2 );
+               $pcreVersion = explode( ' ', PCRE_VERSION, 2 )[0];
                if ( version_compare( $pcreVersion, $minimumPcreVersion, '<' ) ) {
                        $this->fatalError(
                                "PCRE $minimumPcreVersion or later is required.\n" .
index 6b0b233..4c359ee 100644 (file)
@@ -1704,8 +1704,14 @@ return [
                'dependencies' => [
                        'jquery.accessKeyLabel',
                        'jquery.checkboxShiftClick',
+                       'mediawiki.notify',
+                       'mediawiki.api'
                ],
                'targets' => [ 'desktop', 'mobile' ],
+               'messages' => [
+                       'logout-failed',
+                       'logging-out-notify'
+               ]
        ],
        'mediawiki.page.startup' => [
                'scripts' => 'resources/src/mediawiki.page.startup.js',
index 63a652d..8f4fccc 100644 (file)
@@ -18,9 +18,6 @@
        padding: 0.5em 1em;
 }
 
-/* TODO: Remove this old class once the content caches have cleared */
-/* stylelint-disable-next-line selector-class-pattern */
-.mw-json .value,
 .mw-json-value,
 .mw-json-single-value {
        background-color: #dcfae3;
index 12009d1..630e3a6 100644 (file)
                        window.print();
                        e.preventDefault();
                } );
+
+               // Turn logout to a POST action
+               $( '#pt-logout a' ).on( 'click', function ( e ) {
+                       var api = new mw.Api(), returnUrl;
+                       returnUrl = $( '#pt-logout a' ).attr( 'href' );
+                       mw.notify(
+                               mw.message( 'logging-out-notify' ),
+                               { tag: 'logout', autoHide: false }
+                       );
+                       api.postWithToken( 'csrf', {
+                               action: 'logout'
+                       } ).done( function () {
+                               // Horrible hack until deprecation of logoutToken in GET is done
+                               returnUrl = returnUrl.replace( /logoutToken=.+?($|&)/g, 'logoutToken=%2B%5C' );
+                               window.location = returnUrl;
+                       } ).fail( function ( e ) {
+                               mw.notify(
+                                       mw.message( 'logout-failed', e ),
+                                       { type: 'error', tag: 'logout', autoHide: false }
+                               );
+                       } );
+                       e.preventDefault();
+               } );
        } );
 
 }() );
index cb234b2..9803081 100644 (file)
@@ -12,8 +12,6 @@
  */
 class MediaWikiVersionFetcherTest extends MediaWikiTestCase {
 
-       use MediaWikiCoversValidator;
-
        public function testReturnsResult() {
                global $wgVersion;
                $versionFetcher = new MediaWikiVersionFetcher();
index 91dc731..f4048b4 100644 (file)
@@ -143,7 +143,7 @@ class OldChangesListTest extends MediaWikiLangTestCase {
                $recentChange->numberofWatchingusers = 100;
 
                $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
-               $this->assertRegExp( "/(number_of_watching_users_RCview: 100)/", $line );
+               $this->assertRegExp( "/(number-of-watching-users-for-recent-changes: 100)/", $line );
        }
 
        public function testRecentChangesLine_watchlistCssClass() {
index 3890cf8..e9bffe1 100644 (file)
@@ -5,8 +5,6 @@
  */
 class MWMessagePackTest extends MediaWikiTestCase {
 
-       use MediaWikiCoversValidator;
-
        /**
         * Provides test cases for MWMessagePackTest::testMessagePack
         *
index 231979d..23b0cb9 100644 (file)
@@ -7,8 +7,6 @@ use Wikimedia\TestingAccessWrapper;
  */
 class ResourceLoaderSkinModuleTest extends MediaWikiTestCase {
 
-       use MediaWikiCoversValidator;
-
        public static function provideGetStyles() {
                // phpcs:disable Generic.Files.LineLength
                return [
index 3c05583..5fb3ac0 100644 (file)
@@ -10,8 +10,6 @@ use Wikimedia\TestingAccessWrapper;
  */
 class ShellTest extends MediaWikiTestCase {
 
-       use MediaWikiCoversValidator;
-
        public function testIsDisabled() {
                $this->assertInternalType( 'bool', Shell::isDisabled() ); // sanity
        }
index 3ba8773..0b1d013 100644 (file)
@@ -10,8 +10,6 @@ use Wikimedia\TestingAccessWrapper;
  */
 class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase {
 
-       use MediaWikiCoversValidator;
-
        /**
         * @return PHPUnit_Framework_MockObject_MockObject|CommentStore
         */