/**
* Set to a filename to log rate limiter hits.
+ *
+ * @deprecated since 1.23, use $wgDebugLogGroups['ratelimit'] instead
*/
$wgRateLimitLog = null;
* @return void
*/
function logError( $status ) {
- wfDebugLog( 'poolcounter', "Pool key '{$this->key}':"
+ wfDebugLog( 'poolcounter', "Pool key '{$this->key}': "
. $status->getMessage()->inLanguage( 'en' )->useDatabase( false )->text() );
}
);
}
+// Back compatibility for $wgRateLimitLog deprecated with 1.23
+if ( $wgRateLimitLog && ! array_key_exists( 'ratelimit', $wgDebugLogGroups ) ) {
+ $wgDebugLogGroups['ratelimit'] = $wgRateLimitLog;
+}
+
wfProfileOut( $fname . '-defaults2' );
wfProfileIn( $fname . '-misc1' );
*
* @param $key string, usually a key from the list you are generating this link from.
* @param $item array, of list item data containing some of a specific set of keys.
- * The "id" and "class" keys will be used as attributes for the list item,
+ * The "id", "class" and "itemtitle" keys will be used as attributes for the list item,
* if "active" contains a value of true a "active" class will also be appended to class.
*
* @param $options array
* list item directly so they will not be passed to makeLink
* (however the link will still support a tooltip and accesskey from it)
* If you need an id or class on a single link you should include a "links"
- * array with just one link item inside of it.
+ * array with just one link item inside of it. If you want to add a title
+ * to the list item itself, you can set "itemtitle" to the value.
* $options is also passed on to makeLink calls
*
* @return string
} else {
$link = $item;
// These keys are used by makeListItem and shouldn't be passed on to the link
- foreach ( array( 'id', 'class', 'active', 'tag' ) as $k ) {
+ foreach ( array( 'id', 'class', 'active', 'tag', 'itemtitle' ) as $k ) {
unset( $link[$k] );
}
if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
$attrs['class'] .= ' active';
$attrs['class'] = trim( $attrs['class'] );
}
+ if ( isset( $item['itemtitle'] ) ) {
+ $attrs['title'] = $item['itemtitle'];
+ }
return Html::rawElement( isset( $options['tag'] ) ? $options['tag'] : 'li', $attrs, $html );
}
return false;
}
- global $wgMemc, $wgRateLimitLog;
+ global $wgMemc;
wfProfileIn( __METHOD__ );
$limits = $wgRateLimits[$action];
// Already pinged?
if ( $count ) {
if ( $count >= $max ) {
- wfDebug( __METHOD__ . ": tripped! $key at $count $summary\n" );
- if ( $wgRateLimitLog ) {
- wfSuppressWarnings();
- file_put_contents( $wgRateLimitLog, wfTimestamp( TS_MW ) . ' ' . wfWikiID() . ': ' . $this->getName() . " tripped $key at $count $summary\n", FILE_APPEND );
- wfRestoreWarnings();
- }
+ wfDebugLog( 'ratelimit', $this->getName() . " tripped! $key at $count $summary");
$triggered = true;
} else {
wfDebug( __METHOD__ . ": ok. $key at $count $summary\n" );
$this->fld_patrolled = isset( $prop['patrolled'] );
$this->fld_tags = isset( $prop['tags'] );
+ // Most of this code will use the 'contributions' group DB, which can map to slaves
+ // with extra user based indexes or partioning by user. The additional metadata
+ // queries should use a regular slave since the lookup pattern is not all by user.
+ $dbSecondary = $this->getDB(); // any random slave
+
// TODO: if the query is going only against the revision table, should this be done?
$this->selectNamedDB( 'contributions', DB_SLAVE, 'contributions' );
$revIds[] = $row->rev_parent_id;
}
}
- $this->parentLens = Revision::getParentLengths( $this->getDB(), $revIds );
+ $this->parentLens = Revision::getParentLengths( $dbSecondary, $revIds );
$res->rewind(); // reset
}
}
protected function doGetFileStat( array $params ) {
- $params['concurrency'] = 1;
- $stats = $this->doGetFileStatMulti( array( 'srcs' => array( $params['src'] ) ) + $params );
+ $params = array( 'srcs' => array( $params['src'] ), 'concurrency' => 1 ) + $params;
+ unset( $params['src'] );
+ $stats = $this->doGetFileStatMulti( $params );
return reset( $stats );
}
//1.23
array( 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ),
array( 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ),
+ array( 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ),
// KEEP THIS AT THE BOTTOM!!
array( 'doRebuildDuplicateFunction' ),
// show from this onward link
$timestamp = wfTimestampNow();
$now = $lang->userTimeAndDate( $timestamp, $user );
- $tl = $this->makeOptionsLink(
- $now, array( 'from' => $timestamp ), $nondefaults
- );
-
+ $timenow = $lang->userTime( $timestamp, $user );
+ $datenow = $lang->userDate( $timestamp, $user );
$rclinks = $this->msg( 'rclinks' )->rawParams( $cl, $dl, $lang->pipeList( $links ) )
->parse();
- $rclistfrom = $this->msg( 'rclistfrom' )->rawParams( $tl )->parse();
+ $rclistfrom = $this->makeOptionsLink(
+ $this->msg( 'rclistfrom' )->rawParams( $now, $timenow, $datenow )->parse(),
+ array( 'from' => $timestamp ),
+ $nondefaults
+ );
return "{$note}$rclinks<br />$rclistfrom";
}
To finish logging in, you must set a new password here:',
'resetpass-temp-password' => 'Temporary password:',
'resetpass-abort-generic' => 'Password change has been aborted by an extension.',
-'resetpass-expired' => 'Your password has expired. Please set a new password to login.',
-'resetpass-expired-soft' => 'Your password has expired, and needs to be reset. Please choose a new password now, or click cancel to reset it later.',
+'resetpass-expired' => 'Your password has expired. Please set a new password to log in.',
+'resetpass-expired-soft' => 'Your password has expired and needs to be reset. Please choose a new password now, or click "{{int:resetpass-submit-cancel}}" to reset it later.',
# Special:PasswordReset
'passwordreset' => 'Reset password',
'recentchanges-legend-newpage' => '(also see [[Special:NewPages|list of new pages]])',
'recentchanges-legend-plusminus' => '(<em>±123</em>)', # only translate this message to other languages if you have to change it
'rcnotefrom' => 'Below are the changes since <strong>$2</strong> (up to <strong>$1</strong> shown).',
-'rclistfrom' => 'Show new changes starting from $1',
+'rclistfrom' => 'Show new changes starting from $2, $3',
'rcshowhideminor' => '$1 minor edits',
'rcshowhideminor-show' => 'Show',
'rcshowhideminor-hide' => 'Hide',
'delete-warning-toobig' => 'This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.
Deleting it may disrupt database operations of {{SITENAME}};
proceed with caution.',
-'deleting-backlinks-warning' => "'''Warning:''' Other pages link to or transclude from the page you are about to delete.",
+'deleting-backlinks-warning' => "'''Warning:''' Other pages link to or transclude the page you are about to delete.",
# Rollback
'rollback' => 'Roll back edits',
A plus/minus sign with a number for the legend.',
'rcnotefrom' => 'This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.
-The corresponding message is {{msg-mw|Rclistfrom}} (without split of date and time, [[bugzilla:19104|Bug 19104]]).
+The corresponding message is {{msg-mw|Rclistfrom}} (split into date and time).
Parameters:
* $1 - the maximum number of changes that are displayed
'rclistfrom' => 'Used on [[Special:RecentChanges]].
Parameters:
-* $1 - a link to the revision of a specific date and time. The date and the time are the link description (without split of date and time, [[bugzilla:19104|Bug 19104]]).
+* $1 - Revision of a specific date and time. The date and the time adds to the rclistfrom description. No longer used.
+* $2 - Revision of a specific time. The time adds to the rclistfrom link description (with split of date and time).
+* $3 - Revision of a specific date. The date adds to the rclistfrom link description (with split of date and time).
The corresponding message is {{msg-mw|Rcnotefrom}}.',
'rcshowhideminor' => 'Option text in [[Special:RecentChanges]]. Parameters:
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.mwuser ADD user_password_expires TIMESTAMP(6) WITH TIME ZONE NULL DEFAULT NULL;
"authors": [
"DCLXVI",
"Hristofor.mirchev",
- "පසිඳු කාවින්ද"
+ "පසිඳු කාවින්ද",
+ "Mitzev"
]
},
"ooui-dialog-action-close": "Затваряне",
+ "ooui-outline-control-remove": "Премахване на обекти",
"ooui-toolbar-more": "Още"
}
\ No newline at end of file
"ooui-dialog-action-close": "Schließen",
"ooui-outline-control-move-down": "Element nach unten verschieben",
"ooui-outline-control-move-up": "Element nach oben verschieben",
+ "ooui-outline-control-remove": "Element entfernen",
"ooui-toolbar-more": "Mehr"
}
\ No newline at end of file
"ooui-dialog-action-close": "Fermer",
"ooui-outline-control-move-down": "Faire descendre l’élément",
"ooui-outline-control-move-up": "Faire monter l’élément",
+ "ooui-outline-control-remove": "Supprimer l’élément",
"ooui-toolbar-more": "Plus"
}
\ No newline at end of file
"ooui-dialog-action-close": "Začinić",
"ooui-outline-control-move-down": "Zapisk dele přesunyć",
"ooui-outline-control-move-up": "Zapisk horje přesunyć",
+ "ooui-outline-control-remove": "Zapisk wotstronić",
"ooui-toolbar-more": "Wjace"
}
\ No newline at end of file
"ooui-dialog-action-close": "Chiudi",
"ooui-outline-control-move-down": "Sposta in basso",
"ooui-outline-control-move-up": "Sposta in alto",
+ "ooui-outline-control-remove": "Rimuovi elemento",
"ooui-toolbar-more": "Altro"
}
\ No newline at end of file
"ooui-dialog-action-close": "閉じる",
"ooui-outline-control-move-down": "項目を下に移動させる",
"ooui-outline-control-move-up": "項目を上に移動させる",
+ "ooui-outline-control-remove": "項目を除去",
"ooui-toolbar-more": "その他"
}
\ No newline at end of file
"ooui-dialog-action-close": "Затвори",
"ooui-outline-control-move-down": "Помести надолу",
"ooui-outline-control-move-up": "Помести нагоре",
+ "ooui-outline-control-remove": "Отстрани ставка",
"ooui-toolbar-more": "Повеќе"
}
\ No newline at end of file
"ooui-dialog-action-close": "Cufi",
"ooui-outline-control-move-down": "Gad buusi",
"ooui-outline-control-move-up": "Ol baasi",
+ "ooui-outline-control-remove": "Balleessi",
"ooui-toolbar-more": "Dabalata"
}
\ No newline at end of file
"Ty221",
"WTM",
"Woytecr",
- "Wpedzich"
+ "Wpedzich",
+ "Jacenty359"
]
},
"ooui-dialog-action-close": "Zamknij",
"ooui-outline-control-move-down": "Przenieś niżej",
"ooui-outline-control-move-up": "Przenieś wyżej",
+ "ooui-outline-control-remove": "Usuń przedmiot",
"ooui-toolbar-more": "Więcej"
}
\ No newline at end of file
"ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
"ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
"ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
- "ooui-outline-control-remove": "Tool tip for a button that removes items from a list",
+ "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
"ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}"
}
\ No newline at end of file
"ooui-dialog-action-close": "Închide",
"ooui-outline-control-move-down": "Mută elementul mai jos",
"ooui-outline-control-move-up": "Mută elementul mai sus",
+ "ooui-outline-control-remove": "Elimină elementul",
"ooui-toolbar-more": "Mai mult"
}
\ No newline at end of file
"ooui-dialog-action-close": "Закрыть",
"ooui-outline-control-move-down": "Переместить элемент вниз",
"ooui-outline-control-move-up": "Переместить элемент вверх",
+ "ooui-outline-control-remove": "Удалить пункт",
"ooui-toolbar-more": "Ещё"
}
\ No newline at end of file
"ooui-dialog-action-close": "Zapri",
"ooui-outline-control-move-down": "Prestavi predmet nižje",
"ooui-outline-control-move-up": "Prestavi predmet višje",
+ "ooui-outline-control-remove": "Odstrani vnos",
"ooui-toolbar-more": "Več"
}
\ No newline at end of file
"ooui-dialog-action-close": "Затвори",
"ooui-outline-control-move-down": "Премести ставку на доле",
"ooui-outline-control-move-up": "Премести ставку на горе",
+ "ooui-outline-control-remove": "Уклони ставку",
"ooui-toolbar-more": "Више"
}
\ No newline at end of file
"ooui-dialog-action-close": "关闭",
"ooui-outline-control-move-down": "下移项",
"ooui-outline-control-move-up": "上移项",
+ "ooui-outline-control-remove": "移除项",
"ooui-toolbar-more": "更多"
}
\ No newline at end of file
"ooui-dialog-action-close": "關閉",
"ooui-outline-control-move-down": "向下移項",
"ooui-outline-control-move-up": "向上移項",
+ "ooui-outline-control-remove": "移除項",
"ooui-toolbar-more": "更多"
}
\ No newline at end of file
/*!
- * OOjs UI v0.1.0-pre (51f922ba17)
+ * OOjs UI v0.1.0-pre (f3bc5c6)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: Fri Feb 28 2014 16:33:26 GMT-0800 (PST)
+ * Date: Mon Mar 03 2014 17:03:30 GMT-0800 (PST)
*/
( function () {
if ( this.outlined ) {
this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
}
- // Event 'focus' does not bubble, but 'focusin' does
- this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
+ if ( this.autoFocus ) {
+ // Event 'focus' does not bubble, but 'focusin' does
+ this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
+ }
// Initialization
this.$element.addClass( 'oo-ui-bookletLayout' );
var selectedItem,
page = this.pages[name];
- if ( this.outlined ) {
- selectedItem = this.outlineWidget.getSelectedItem();
- if ( selectedItem && selectedItem.getData() !== name ) {
- this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+ if ( name !== this.currentPageName ) {
+ if ( this.outlined ) {
+ selectedItem = this.outlineWidget.getSelectedItem();
+ if ( selectedItem && selectedItem.getData() !== name ) {
+ this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+ }
}
- }
-
- if ( page ) {
- if ( this.currentPageName && this.pages[this.currentPageName] ) {
- this.pages[this.currentPageName].setActive( false );
+ if ( page ) {
+ if ( this.currentPageName && this.pages[this.currentPageName] ) {
+ this.pages[this.currentPageName].setActive( false );
+ }
+ this.currentPageName = name;
+ this.stackLayout.setItem( page );
+ page.setActive( true );
+ this.emit( 'set', page );
}
- this.currentPageName = name;
- this.stackLayout.setItem( page );
- page.setActive( true );
- this.emit( 'set', page );
}
};
* @chainable
*/
OO.ui.StackLayout.prototype.setItem = function ( item ) {
- if ( !this.continuous ) {
- this.$items.css( 'display', '' );
- }
- if ( $.inArray( item, this.items ) !== -1 ) {
+ if ( item !== this.currentItem ) {
if ( !this.continuous ) {
- item.$element.css( 'display', 'block' );
+ this.$items.css( 'display', '' );
}
- } else {
- item = null;
+ if ( $.inArray( item, this.items ) !== -1 ) {
+ if ( !this.continuous ) {
+ item.$element.css( 'display', 'block' );
+ }
+ } else {
+ item = null;
+ }
+ this.currentItem = item;
+ this.emit( 'set', item );
}
- this.currentItem = item;
- this.emit( 'set', item );
return this;
};
/*!
- * OOjs UI v0.1.0-pre (51f922ba17)
+ * OOjs UI v0.1.0-pre (f3bc5c6)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: Fri Feb 28 2014 16:33:26 GMT-0800 (PST)
+ * Date: Mon Mar 03 2014 17:03:30 GMT-0800 (PST)
*/
/* Textures */
display: inline-block;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
+ -ms-transition: opacity 200ms;
-o-transition: opacity 200ms;
transition: opacity 200ms;
}
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
- -o-user-select: none;
user-select: none;
+ -webkit-touch-callout: none;
}
.oo-ui-toolbar-actions .oo-ui-popupWidget {
opacity: 0.125;
-webkit-transition: opacity 500ms ease-in-out;
-moz-transition: opacity 500ms ease-in-out;
+ -ms-transition: opacity 500ms ease-in-out;
-o-transition: opacity 500ms ease-in-out;
transition: opacity 500ms ease-in-out;
}
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
+ -webkit-touch-callout: none;
}
.oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
}
.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
- -webkit-transition: width 100ms, height 100ms, left 100ms;
- -moz-transition: width 100ms, height 100ms, left 100ms;
- -o-transition: width 100ms, height 100ms, left 100ms;
- transition: width 100ms, height 100ms, left 100ms;
- -webkit-transition-timing-function: ease-in-out;
- -moz-transition-timing-function: ease-in-out;
- -o-transition-timing-function: ease-in-out;
- transition-timing-function: ease-in-out;
+ -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+ -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+ -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+ -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+ transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
}
.oo-ui-popupWidget-head {
.oo-ui-indicator-up {
background-image: /* @embed */ url(images/indicators/up.svg);
-}
\ No newline at end of file
+}
--- /dev/null
+<?php
+
+/**
+ * @covers SkinTemplate
+ *
+ * @group Output
+ *
+ * @licence GNU GPL v2+
+ * @author Bene* < benestar.wikimedia@gmail.com >
+ */
+
+class SkinTemplateTest extends MediaWikiTestCase {
+
+ /**
+ * @dataProvider makeListItemProvider
+ */
+ public function testMakeListItem( $expected, $key, $item, $options, $message ) {
+ $template = $this->getMockForAbstractClass( 'BaseTemplate' );
+
+ $this->assertEquals(
+ $expected,
+ $template->makeListItem( $key, $item, $options ),
+ $message
+ );
+ }
+
+ public function makeListItemProvider() {
+ return array(
+ array(
+ '<li class="class" title="itemtitle"><a href="url" title="title">text</a></li>',
+ '',
+ array( 'class' => 'class', 'itemtitle' => 'itemtitle', 'href' => 'url', 'title' => 'title', 'text' => 'text' ),
+ array(),
+ 'Test makteListItem with normal values'
+ )
+ );
+ }
+}