class ApiClearHasMsg extends ApiBase {
public function execute() {
$user = $this->getUser();
- if ( $this->getRequest()->wasPosted() ) {
- $user->setNewtalk( false );
- } else {
- DeferredUpdates::addCallableUpdate( function () use ( $user ) {
- $user->setNewtalk( false );
- } );
- }
+ $user->setNewtalk( false );
$this->getResult()->addValue( null, $this->getModuleName(), 'success' );
}
"apisandbox-sending-request": "Sending API request...",
"apisandbox-loading-results": "Receiving API results...",
"apisandbox-results-error": "An error occurred while loading the API query response: $1.",
+ "apisandbox-request-params-json": "JSON parameters:",
"apisandbox-request-url-label": "Request URL:",
"apisandbox-request-time": "Request time: {{PLURAL:$1|$1 ms}}",
"apisandbox-results-fixtoken": "Correct token and resubmit",
"apisandbox-sending-request": "JavaScript message displayed while the request is being sent.",
"apisandbox-loading-results": "JavaScript message displayed while the response is being read.",
"apisandbox-results-error": "Displayed as an error message from JavaScript when the request failed.\n\nParameters:\n* $1 - Error message",
+ "apisandbox-request-params-json": "Label for text field display the request parameters as JSON.",
"apisandbox-request-url-label": "Label for the text field displaying the URL used to make this request.",
"apisandbox-request-time": "Label and value for displaying the time taken by the request.\n\nParameters:\n* $1 - Time taken in milliseconds",
"apisandbox-results-fixtoken": "JavaScript button label",
'apisandbox-sending-request',
'apisandbox-loading-results',
'apisandbox-results-error',
+ 'apisandbox-request-params-json',
'apisandbox-request-url-label',
'apisandbox-request-time',
'apisandbox-results-fixtoken',
.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator.mw-apisandbox-clickable-indicator {
cursor: pointer;
}
+
+.mw-apisandbox-textInputCode .oo-ui-inputWidget-input {
+ font-family: monospace, 'Courier';
+ font-size: 0.8125em;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+}
}
$.when.apply( $, deferreds ).done( function () {
+ var jsonInput;
+
if ( $.inArray( false, arguments ) !== -1 ) {
windowManager.openWindow( 'errorAlert', {
title: Util.parseMsg( 'apisandbox-submit-invalid-fields-title' ),
label: Util.parseMsg( 'apisandbox-request-url-label' )
}
).$element,
+ new OO.ui.FieldLayout(
+ jsonInput = new OO.ui.TextInputWidget( {
+ classes: [ 'mw-apisandbox-textInputCode' ],
+ readOnly: true,
+ multiline: true,
+ autosize: true,
+ maxRows: 6,
+ value: JSON.stringify( displayParams, null, '\t' )
+ } ), {
+ label: Util.parseMsg( 'apisandbox-request-params-json' )
+ }
+ ).$element,
$result
);
ApiSandbox.updateUI();
booklet.setPage( '|results|' );
+ // Resize the multiline input once visible
+ jsonInput.adjustSize();
+
location.href = oldhash = '#' + query;
api.post( params, {
* - 'boolean': The field is a boolean.
* - 'toggleLocal': The field represents {@link #getLocal this.getLocal()}.
* Editing should directly call {@link #toggleLocal this.toggleLocal()}.
+ * @return {boolean} return.calendarComponent Whether this field is part of a calendar, e.g.
+ * part of the date instead of the time.
* @return {number} return.size Maximum number of characters in the field (when
* the 'intercalary' component is falsey). If 0, the field should be hidden entirely.
* @return {Object.<string,number>} return.intercalarySize Map from
}
spec = {
component: null,
+ calendarComponent: false,
editable: false,
type: 'static',
value: params.slice( 1 ).join( '|' ),
c = params[ 0 ] === '#' ? '' : ':';
return {
component: 'zone',
+ calendarComponent: false,
editable: true,
type: 'toggleLocal',
size: 5 + c.length,
case 'full':
spec = {
component: 'zone',
+ calendarComponent: false,
editable: true,
type: 'toggleLocal',
values: params[ 0 ] === 'short' ? this.shortZones : this.fullZones,
$field = $( '<span>' )
.width( sz )
.data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder', placeholder );
+ if ( spec.type !== 'static' ) {
+ $field.prop( 'tabIndex', -1 );
+ $field.on( 'focus', this.onFieldFocus.bind( this, $field ) );
+ }
if ( spec.type === 'static' ) {
$field.text( spec.value );
} else {
* @param {jQuery.Event} e Focus event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldFocus = function ( $field ) {
+ var spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
if ( !this.isDisabled() ) {
if ( this.getValueAsDate() === null ) {
this.setValue( this.formatter.getDefaultDate() );
}
if ( this.calendar ) {
- this.calendar.toggle( true );
+ this.calendar.toggle( !!spec.calendarComponent );
}
}
};
case 'year|#':
spec = {
component: 'Year',
+ calendarComponent: true,
type: 'number',
size: 4,
zeropad: false
case 'season|#':
spec = {
component: 'Season',
+ calendarComponent: true,
type: 'number',
size: 1,
intercalarySize: { 1: 0 },
case 'season|full':
spec = {
component: 'Season',
+ calendarComponent: true,
type: 'string',
intercalarySize: { 1: 0 },
values: {
case 'dow|full':
spec = {
component: 'DOW',
+ calendarComponent: true,
editable: false,
type: 'string',
intercalarySize: { 1: 0 },
case 'day|0':
spec = {
component: 'Day',
+ calendarComponent: true,
type: 'string',
size: 2,
intercalarySize: { 1: 13 },
case 'second|0':
spec = {
component: tag.charAt( 0 ).toUpperCase() + tag.slice( 1 ),
+ calendarComponent: false,
type: 'number',
size: 2,
zeropad: params[ 0 ] === '0'
case 'millisecond|0':
spec = {
component: 'Millisecond',
+ calendarComponent: false,
type: 'number',
size: 3,
zeropad: params[ 0 ] === '0'
/**
* Provides various methods needed for formatting dates and times. This
- * implementation implments the proleptic Gregorian calendar over years
+ * implementation implements the proleptic Gregorian calendar over years
* 0000–9999.
*
* @class
case 'year|0':
spec = {
component: 'year',
+ calendarComponent: true,
type: 'number',
size: 4,
zeropad: params[ 0 ] === '0'
case 'month|full':
spec = {
component: 'month',
+ calendarComponent: true,
type: 'string',
values: params[ 0 ] === 'short' ? this.shortMonthNames : this.fullMonthNames
};
case 'dow|full':
spec = {
component: 'dow',
+ calendarComponent: true,
editable: false,
type: 'string',
values: params[ 0 ] === 'short' ? this.shortDayNames : this.fullDayNames
case 'month|0':
case 'day|#':
case 'day|0':
+ spec = {
+ component: tag,
+ calendarComponent: true,
+ type: 'number',
+ size: 2,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
case 'hour|#':
case 'hour|0':
case 'minute|#':
case 'second|0':
spec = {
component: tag,
+ calendarComponent: false,
type: 'number',
size: 2,
zeropad: params[ 0 ] === '0'
case 'hour|012':
spec = {
component: 'hour12',
+ calendarComponent: false,
type: 'number',
size: 2,
zeropad: params[ 0 ] === '012'
case 'hour|period':
spec = {
component: 'hour12period',
+ calendarComponent: false,
type: 'boolean',
values: this.hour12Periods
};
case 'millisecond|0':
spec = {
component: 'millisecond',
+ calendarComponent: false,
type: 'number',
size: 3,
zeropad: params[ 0 ] === '0'
// We add 5 Revisions for this test. Their corresponding text id's
// are stored in the following 5 variables.
- private $textId1;
- private $textId2;
- private $textId3;
- private $textId4;
- private $textId5;
+ protected static $textId1;
+ protected static $textId2;
+ protected static $textId3;
+ protected static $textId4;
+ protected static $textId5;
/**
* @var Exception|null As the current MediaWikiTestCase::run is not
* we catch the exception and store it until we are in setUp and may
* finally rethrow the exception without crashing the test suite.
*/
- private $exceptionFromAddDBData;
+ protected static $exceptionFromAddDBDataOnce;
/**
* @var FetchText The (mocked) FetchText that is to test
throw new MWException( "Could not determine text id" );
}
- function addDBData() {
- $this->tablesUsed[] = 'page';
- $this->tablesUsed[] = 'revision';
- $this->tablesUsed[] = 'text';
-
+ function addDBDataOnce() {
$wikitextNamespace = $this->getDefaultWikitextNS();
try {
$title = Title::newFromText( 'FetchTextTestPage1', $wikitextNamespace );
$page = WikiPage::factory( $title );
- $this->textId1 = $this->addRevision(
+ self::$textId1 = $this->addRevision(
$page,
"FetchTextTestPage1Text1",
"FetchTextTestPage1Summary1"
$title = Title::newFromText( 'FetchTextTestPage2', $wikitextNamespace );
$page = WikiPage::factory( $title );
- $this->textId2 = $this->addRevision(
+ self::$textId2 = $this->addRevision(
$page,
"FetchTextTestPage2Text1",
"FetchTextTestPage2Summary1"
);
- $this->textId3 = $this->addRevision(
+ self::$textId3 = $this->addRevision(
$page,
"FetchTextTestPage2Text2",
"FetchTextTestPage2Summary2"
);
- $this->textId4 = $this->addRevision(
+ self::$textId4 = $this->addRevision(
$page,
"FetchTextTestPage2Text3",
"FetchTextTestPage2Summary3"
);
- $this->textId5 = $this->addRevision(
+ self::$textId5 = $this->addRevision(
$page,
"FetchTextTestPage2Text4 some additional Text ",
"FetchTextTestPage2Summary4 extra "
);
} catch ( Exception $e ) {
// We'd love to pass $e directly. However, ... see
- // documentation of exceptionFromAddDBData
- $this->exceptionFromAddDBData = $e;
+ // documentation of exceptionFromAddDBDataOnce
+ self::$exceptionFromAddDBDataOnce = $e;
}
}
parent::setUp();
// Check if any Exception is stored for rethrowing from addDBData
- if ( $this->exceptionFromAddDBData !== null ) {
- throw $this->exceptionFromAddDBData;
+ if ( self::$exceptionFromAddDBDataOnce !== null ) {
+ throw self::$exceptionFromAddDBDataOnce;
}
$this->fetchText = new SemiMockedFetchText();
// provider would not know the required ids.
function testExistingSimple() {
- $this->assertFilter( $this->textId2,
- $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
+ $this->assertFilter( self::$textId2,
+ self::$textId2 . "\n23\nFetchTextTestPage2Text1" );
}
function testExistingSimpleWithNewline() {
- $this->assertFilter( $this->textId2 . "\n",
- $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
+ $this->assertFilter( self::$textId2 . "\n",
+ self::$textId2 . "\n23\nFetchTextTestPage2Text1" );
}
function testExistingSeveral() {
- $this->assertFilter( "$this->textId1\n$this->textId5\n"
- . "$this->textId3\n$this->textId3",
- implode( "", [
- $this->textId1 . "\n23\nFetchTextTestPage1Text1",
- $this->textId5 . "\n44\nFetchTextTestPage2Text4 "
+ $this->assertFilter(
+ join( "\n", [
+ self::$textId1,
+ self::$textId5,
+ self::$textId3,
+ self::$textId3,
+ ] ),
+ implode( '', [
+ self::$textId1 . "\n23\nFetchTextTestPage1Text1",
+ self::$textId5 . "\n44\nFetchTextTestPage2Text4 "
. "some additional Text",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2"
+ self::$textId3 . "\n23\nFetchTextTestPage2Text2",
+ self::$textId3 . "\n23\nFetchTextTestPage2Text2"
] ) );
}
}
function testNonExisting() {
- $this->assertFilter( $this->textId5 + 10, ( $this->textId5 + 10 ) . "\n-1\n" );
+ $this->assertFilter( self::$textId5 + 10, ( self::$textId5 + 10 ) . "\n-1\n" );
}
function testNegativeInteger() {
function testFloatingPointNumberExisting() {
// float -> int -> revision
- $this->assertFilter( $this->textId3 + 0.14159,
- $this->textId3 . "\n23\nFetchTextTestPage2Text2" );
+ $this->assertFilter( self::$textId3 + 0.14159,
+ self::$textId3 . "\n23\nFetchTextTestPage2Text2" );
}
function testFloatingPointNumberNonExisting() {
- $this->assertFilter( $this->textId5 + 3.14159,
- ( $this->textId5 + 3 ) . "\n-1\n" );
+ $this->assertFilter( self::$textId5 + 3.14159,
+ ( self::$textId5 + 3 ) . "\n-1\n" );
}
function testCharacters() {
}
function testMix() {
- $this->assertFilter( "ab\n" . $this->textId4 . ".5cd\n\nefg\n" . $this->textId2
- . "\n" . $this->textId3,
+ $this->assertFilter( "ab\n" . self::$textId4 . ".5cd\n\nefg\n" . self::$textId2
+ . "\n" . self::$textId3,
implode( "", [
"0\n-1\n",
- $this->textId4 . "\n23\nFetchTextTestPage2Text3",
+ self::$textId4 . "\n23\nFetchTextTestPage2Text3",
"0\n-1\n",
"0\n-1\n",
- $this->textId2 . "\n23\nFetchTextTestPage2Text1",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2"
+ self::$textId2 . "\n23\nFetchTextTestPage2Text1",
+ self::$textId3 . "\n23\nFetchTextTestPage2Text2"
] ) );
}
}