* 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 ====
* (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:
* The Block typehint only refers to blocks stored in the database. It should be
updated to AbstractBlock in cases where any type of block could be expected.
* FileRepoStatus, deprecated in 1.25, has been removed.
+* The LegacyHookPreAuthenticationProvider class, deprecated since its creation
+ in 1.27, has been removed.
+* IP::isValidBlock(), deprecated in 1.30, has been removed.
* …
=== Deprecations in 1.34 ===
"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",
"wikimedia/avro": "1.8.0",
"wikimedia/testing-access-wrapper": "~1.0",
"wmde/hamcrest-html-matchers": "^0.1.0",
- "mediawiki/mediawiki-phan-config": "0.5.0"
+ "mediawiki/mediawiki-phan-config": "0.6.0"
},
"replace": {
"symfony/polyfill-ctype": "1.99",
pcntl_signal_dispatch();
} else {
declare( ticks = 1 ) {
+ // @phan-suppress-next-line PhanPluginDuplicateExpressionAssignment
$status = $status;
}
}
use MediaWiki\Shell\Shell;
use Wikimedia\ScopedCallback;
use Wikimedia\WrappedString;
+use Wikimedia\AtEase\AtEase;
/**
* Load an extension
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'] ) ) {
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
*
}
// 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
# 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" );
}
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.
if ( session_id() !== $session->getId() ) {
session_id( $session->getId() );
}
- Wikimedia\quietCall( 'session_start' );
+ AtEase::quietCall( 'session_start' );
}
/**
$this->initializeMutableRevisionFromArray( $revision, $fields );
if ( isset( $fields['content'] ) && is_array( $fields['content'] ) ) {
+ // @phan-suppress-next-line PhanTypeNoPropertiesForeach
foreach ( $fields['content'] as $role => $content ) {
$revision->setContent( $role, $content );
}
}
// Check if the uploaded file is sane
- wfDebug( __METHOD__ . " about to verify\n" );
- $this->verifyUpload();
+ if ( $this->mParams['chunk'] ) {
+ $maxSize = UploadBase::getMaxUploadSize();
+ if ( $this->mParams['filesize'] > $maxSize ) {
+ $this->dieWithError( 'file-too-large' );
+ }
+ if ( !$this->mUpload->getTitle() ) {
+ $this->dieWithError( 'illegal-filename' );
+ }
+ } elseif ( $this->mParams['async'] && $this->mParams['filekey'] ) {
+ // defer verification to background process
+ } else {
+ wfDebug( __METHOD__ . " about to verify\n" );
+ $this->verifyUpload();
+ }
// Check if the user has the rights to modify or overwrite the requested title
// (This check is irrelevant if stashing is already requested, since the errors
+++ /dev/null
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Auth
- */
-
-namespace MediaWiki\Auth;
-
-/**
- * A pre-authentication provider to call some legacy hooks.
- * @ingroup Auth
- * @since 1.27
- * @deprecated since 1.27
- */
-class LegacyHookPreAuthenticationProvider extends AbstractPreAuthenticationProvider {
- public function __construct() {
- wfDeprecated( self::class, '1.27' );
- }
-}
$date = $lang->userTimeAndDate( $ts, $user );
if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) {
$link = MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
- $title !== null ? $title : $rev->getTitle(),
+ $title ?? $rev->getTitle(),
$date,
[ 'class' => 'mw-changeslist-date' ],
[ 'oldid' => $rev->getId() ]
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] ) ) {
}
$this->add( $name, $otherConfig );
-
- // recover the pointer of the other config repository
- if ( $otherCurrentObj === $otherConfig ) {
- end( $this->configItems['private'] );
- }
}
// disable $other
* @return string
*/
public function getErrors( $errors ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.28' );
return $this->getErrorsOrWarnings( $errors, 'error' );
}
}
protected function updateWatchlistNotification() {
- $casTimestamp = ( $this->params['notifTime'] !== null )
- ? $this->params['notifTime']
- : $this->params['curTime'];
+ $casTimestamp = $this->params['notifTime'] ?? $this->params['curTime'];
$dbw = wfGetDB( DB_MASTER );
$dbw->update( 'watchlist',
|| preg_match( '/^' . RE_IPV6_ADD . '$/', $ip ) );
}
- /**
- * Validate an IP range (valid address with a valid CIDR prefix).
- * SIIT IPv4-translated addresses are rejected.
- * @note canonicalize() tries to convert translated addresses to IPv4.
- *
- * @deprecated since 1.30. Use the equivalent IP::isValidRange().
- * @param string $ipRange
- * @return bool True if it is valid
- */
- public static function isValidBlock( $ipRange ) {
- wfDeprecated( __METHOD__, '1.30' );
- return self::isValidRange( $ipRange );
- }
-
/**
* Validate an IP range (valid address with a valid CIDR prefix).
* SIIT IPv4-translated addresses are rejected.
if ( $rcode >= 200 && $rcode <= 299 ) { // OK
$this->authCreds = [
'auth_token' => $rhdrs['x-auth-token'],
- 'storage_url' => ( $this->swiftStorageUrl !== null )
- ? $this->swiftStorageUrl
- : $rhdrs['x-storage-url']
+ 'storage_url' => $this->swiftStorageUrl ?? $rhdrs['x-storage-url']
];
$this->srvCache->set( $cacheKey, $this->authCreds, ceil( $this->authTTL / 2 ) );
public function notify( RecentChange $rc, $actionComment = null ) {
$params = $this->params;
/** @var RCFeedFormatter $formatter */
+ // @phan-suppress-next-line PhanTypeExpectedObjectOrClassName
$formatter = is_object( $params['formatter'] ) ? $params['formatter'] : new $params['formatter'];
$line = $formatter->getLine( $params, $rc, $actionComment );
// This class will eventually be abstract. SearchEngine implementations
// already have to extend this class anyways to provide the actual
// search results.
- wfDeprecated( __METHOD__, 1.32 );
+ wfDeprecated( __METHOD__, '1.32' );
}
$this->containedSyntax = $containedSyntax;
$this->hasMoreResults = $hasMoreResults;
use Profiler;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;
+use Wikimedia\AtEase\AtEase;
/**
* Class used for executing shell commands
// 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 ) {
/**
* 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' ] );
*/
private function parseParams( FormOptions $opts, $par ) {
# Get parameters
- $par = $par !== null ? $par : '';
+ $par = $par ?? '';
$parms = explode( '/', $par );
$symsForAll = [ '*', 'all' ];
if ( $parms[0] != '' &&
public $namespace = '';
/**
- * @var \Wikimedia\Rdbms\Database
+ * @var IDatabase
*/
public $mDb;
}
$request = $this->getRequest();
- $par = ( $par !== null ) ? $par : '';
+ $par = $par ?? '';
$parms = explode( '/', $par );
$symsForAll = [ '*', 'user' ];
"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!",
"boteditletter": "b",
"unpatrolledletter": "!",
"number_of_watching_users_RCview": "[$1]",
- "number_of_watching_users_pageview": "[$1 watching {{PLURAL:$1|user|users}}]",
"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\".",
"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]]",
"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)",
"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.",
'img_link' => [ '1', 'liŋka=$1', 'link=$1' ],
];
+$defaultDateFormat = 'mdy';
+
+$dateFormats = [
+ 'mdy time' => 'G.i',
+ 'mdy date' => 'xg j "b." Y',
+ 'mdy both' => 'xg j "b." Y "dii." G.i',
+];
+
$separatorTransformTable = [ ',' => "\u{00A0}", '.' => ',' ];
$linkTrail = '/^(:?[a-zàáâçčʒǯđðéèêëǧǥȟíìîïıǩŋñóòôõßšŧúùûýÿüžþæøåäö]+)(.*)$/sDu';
'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',
* @return {string} Parsed message
*/
parser: function () {
- var text;
- if ( mw.config.get( 'wgUserLanguage' ) === 'qqx' ) {
+ var text = this.map.get( this.key );
+ if (
+ mw.config.get( 'wgUserLanguage' ) === 'qqx' &&
+ ( !text || text === '(' + this.key + ')' )
+ ) {
text = '(' + this.key + '$*)';
- } else {
- text = this.map.get( this.key );
}
return mw.format.apply( null, [ text ].concat( this.parameters ) );
},
var wikiText;
if ( !Object.prototype.hasOwnProperty.call( this.astCache, key ) ) {
- if ( mw.config.get( 'wgUserLanguage' ) === 'qqx' ) {
+ wikiText = this.settings.messages.get( key );
+ if (
+ mw.config.get( 'wgUserLanguage' ) === 'qqx' &&
+ ( !wikiText || wikiText === '(' + key + ')' )
+ ) {
wikiText = '(' + key + '$*)';
- } else {
- wikiText = this.settings.messages.get( key );
- if ( typeof wikiText !== 'string' ) {
- wikiText = '⧼' + key + '⧽';
- }
+ } else if ( typeof wikiText !== 'string' ) {
+ wikiText = '⧼' + key + '⧽';
}
wikiText = mw.internalDoTransformFormatForQqx( wikiText, replacements );
this.astCache[ key ] = this.wikiTextToAst( wikiText );
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();
+ } );
} );
}() );
*/
class MediaWikiVersionFetcherTest extends MediaWikiTestCase {
- use MediaWikiCoversValidator;
-
public function testReturnsResult() {
global $wgVersion;
$versionFetcher = new MediaWikiVersionFetcher();
*/
class MWMessagePackTest extends MediaWikiTestCase {
- use MediaWikiCoversValidator;
-
/**
* Provides test cases for MWMessagePackTest::testMessagePack
*
*/
class ResourceLoaderSkinModuleTest extends MediaWikiTestCase {
- use MediaWikiCoversValidator;
-
public static function provideGetStyles() {
// phpcs:disable Generic.Files.LineLength
return [
*/
class ShellTest extends MediaWikiTestCase {
- use MediaWikiCoversValidator;
-
public function testIsDisabled() {
$this->assertInternalType( 'bool', Shell::isDisabled() ); // sanity
}
*/
class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase {
- use MediaWikiCoversValidator;
-
/**
* @return PHPUnit_Framework_MockObject_MockObject|CommentStore
*/
);
mw.config.set( 'wgUserLanguage', 'qqx' );
+
$bar = $( '<b>' ).text( 'bar' );
- assert.strictEqual( mw.message( 'foo', $bar, 'baz' ).parse(), '(foo: <b>bar</b>, baz)', 'qqx message with parameters' );
+ mw.messages.set( 'qqx-message', '(qqx-message)' );
+ mw.messages.set( 'non-qqx-message', '<b>hello world</b>' );
+
+ assert.strictEqual( mw.message( 'missing-message' ).parse(), '(missing-message)', 'qqx message (missing)' );
+ assert.strictEqual( mw.message( 'missing-message', $bar, 'baz' ).parse(), '(missing-message: <b>bar</b>, baz)', 'qqx message (missing) with parameters' );
+ assert.strictEqual( mw.message( 'qqx-message' ).parse(), '(qqx-message)', 'qqx message (defined)' );
+ assert.strictEqual( mw.message( 'qqx-message', $bar, 'baz' ).parse(), '(qqx-message: <b>bar</b>, baz)', 'qqx message (defined) with parameters' );
+ assert.strictEqual( mw.message( 'non-qqx-message' ).parse(), '<b>hello world</b>', 'non-qqx message in qqx mode' );
} );
QUnit.test( 'setParserDefaults', function ( assert ) {
);
mw.config.set( 'wgUserLanguage', 'qqx' );
- assert.strictEqual( mw.message( 'foo' ).plain(), '(foo)', 'qqx message' );
- assert.strictEqual( mw.message( 'foo', 'bar', 'baz' ).plain(), '(foo: bar, baz)', 'qqx message with parameters' );
+
+ mw.messages.set( 'qqx-message', '(qqx-message)' );
+ mw.messages.set( 'non-qqx-message', 'hello world' );
+
+ assert.strictEqual( mw.message( 'missing-message' ).plain(), '(missing-message)', 'qqx message (missing)' );
+ assert.strictEqual( mw.message( 'missing-message', 'bar', 'baz' ).plain(), '(missing-message: bar, baz)', 'qqx message (missing) with parameters' );
+ assert.strictEqual( mw.message( 'qqx-message' ).plain(), '(qqx-message)', 'qqx message (defined)' );
+ assert.strictEqual( mw.message( 'qqx-message', 'bar', 'baz' ).plain(), '(qqx-message: bar, baz)', 'qqx message (defined) with parameters' );
+ assert.strictEqual( mw.message( 'non-qqx-message' ).plain(), 'hello world', 'non-qqx message in qqx mode' );
} );
QUnit.test( 'mw.msg', function ( assert ) {