public function selectSQLText(
$table, $vars, $conds = '', $fname = __METHOD__, $options = [], $join_conds = []
) {
+ if ( is_string( $options ) ) {
+ $options = [ $options ];
+ }
+
// Change the FOR UPDATE option as necessary based on the join conditions. Then pass
// to the parent function to get the actual SQL text.
// In Postgres when using FOR UPDATE, only the main table and tables that are inner joined
$forUpdateKey = array_search( 'FOR UPDATE', $options, true );
if ( $forUpdateKey !== false && $join_conds ) {
unset( $options[$forUpdateKey] );
+ $options['FOR UPDATE'] = [];
+
+ // All tables not in $join_conds are good
+ foreach ( $table as $alias => $name ) {
+ if ( is_numeric( $alias ) ) {
+ $alias = $name;
+ }
+ if ( !isset( $join_conds[$alias] ) ) {
+ $options['FOR UPDATE'][] = $alias;
+ }
+ }
foreach ( $join_conds as $table_cond => $join_cond ) {
if ( 0 === preg_match( '/^(?:LEFT|RIGHT|FULL)(?: OUTER)? JOIN$/i', $join_cond[0] ) ) {
$options['FOR UPDATE'][] = $table_cond;
}
}
+
+ // Quote alias names so $this->tableName() won't mangle them
+ $options['FOR UPDATE'] = array_map( function ( $name ) use ( $table ) {
+ return isset( $table[$name] ) ? $this->addIdentifierQuotes( $name ) : $name;
+ }, $options['FOR UPDATE'] );
}
if ( isset( $options['ORDER BY'] ) && $options['ORDER BY'] == 'NULL' ) {
* @param IDatabase $db Object throwing the error
* @param string $error Error text
*/
- function __construct( IDatabase $db = null, $error = 'unknown error' ) {
+ public function __construct( IDatabase $db = null, $error = 'unknown error' ) {
$msg = 'Cannot access the database';
if ( trim( $error ) != '' ) {
$msg .= ": $error";
* @param IDatabase $db Object which threw the error
* @param string $error A simple error message to be used for debugging
*/
- function __construct( IDatabase $db = null, $error ) {
+ public function __construct( IDatabase $db = null, $error ) {
$this->db = $db;
parent::__construct( $error );
}
/** @var string[] Message parameters */
protected $params;
- function __construct( IDatabase $db = null, $error, array $params = [] ) {
+ public function __construct( IDatabase $db = null, $error, array $params = [] ) {
parent::__construct( $db, $error );
$this->params = $params;
}
* @param string $sql
* @param string $fname
*/
- function __construct( IDatabase $db, $error, $errno, $sql, $fname ) {
+ public function __construct( IDatabase $db, $error, $errno, $sql, $fname ) {
if ( $db instanceof Database && $db->wasConnectionError( $errno ) ) {
$message = "A connection error occured. \n" .
"Query: $sql\n" .
* @ingroup Database
*/
class DBTransactionSizeError extends DBTransactionError {
- function getKey() {
+ public function getKey() {
return 'transaction-duration-limit-exceeded';
}
}
$watchlistHeader .= $this->msg( 'wlheader-enotif' )->parse() . "\n";
}
if ( $showUpdatedMarker ) {
- $watchlistHeader .= $this->msg( 'wlheader-showupdated' )->parse() . "\n";
+ $watchlistHeader .= $this->msg(
+ $this->isStructuredFilterUiEnabled() ?
+ 'rcfilters-watchlist-showupdated' :
+ 'wlheader-showupdated'
+ )->parse() . "\n";
}
}
$form .= Html::rawElement(
wfDebugLog( 'fileupload', $status );
if ( $status->isOK() ) {
- wfDebugLog( 'fileupload', 'Download by URL completed successfuly.' );
+ wfDebugLog( 'fileupload', 'Download by URL completed successfully.' );
} else {
wfDebugLog(
'fileupload',
"rcfilters-liveupdates-button-title-off": "Display new changes as they happen",
"rcfilters-watchlist-markSeen-button": "Mark all changes as seen",
"rcfilters-watchlist-editWatchlist-button": "Edit your list of watched pages",
+ "rcfilters-watchlist-showupdated": "Changes to pages you haven't visited since the changes occurred are in <strong>bold</strong>, with solid markers.",
"rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
"rclistfromreset": "Reset date selection",
"rclistfrom": "Show new changes starting from $2, $3",
"rcfilters-liveupdates-button-title-off": "Title for the button to enable or disable live updates on [[Special:RecentChanges]] when the feature is OFF.",
"rcfilters-watchlist-markSeen-button": "Label for the button to mark all changes as seen on [[Special:Watchlist]] when using the structured filters interface.",
"rcfilters-watchlist-editWatchlist-button": "Label for the button to edit the watched pages on [[Special:Watchlist]] when using the structured filters interface.",
+ "rcfilters-watchlist-showupdated": "Message at the top of [[Special:Watchlist]] when the Structured filters are enabled that describes what unseen changes look like.",
"rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
"rclistfromreset": "Used on [[Special:RecentChanges]] to reset a selection of a certain date range.",
"rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
CREATE TABLE image_comment_temp (
imgcomment_name TEXT NOT NULL,
- imgcomment_comment_id INTEGER NOT NULL,
- PRIMARY KEY (imgcomment_name, imgcomment_comment_id)
+ imgcomment_description_id INTEGER NOT NULL,
+ PRIMARY KEY (imgcomment_name, imgcomment_description_id)
);
CREATE UNIQUE INDEX imgcomment_name ON image_comment_temp (imgcomment_name);
CREATE TABLE image_comment_temp (
imgcomment_name TEXT NOT NULL,
- imgcomment_comment_id INTEGER NOT NULL,
- PRIMARY KEY (imgcomment_name, imgcomment_comment_id)
+ imgcomment_description_id INTEGER NOT NULL,
+ PRIMARY KEY (imgcomment_name, imgcomment_description_id)
);
CREATE UNIQUE INDEX imgcomment_name ON image_comment_temp (imgcomment_name);
.mw-rcfilters-ui-rcTopSectionWidget {
&-topLinks {
- width: 100%;
+ &-table {
+ width: 100%;
+ }
+
+ &-top {
+ display: block;
+ width: 100%;
+
+ .mw-recentchanges-toplinks {
+ margin-bottom: 0.5em;
+ }
+ }
}
&-savedLinks {
&-table {
display: table;
width: 100%;
+
+ &-placeholder {
+ width: 100%;
+ }
}
&-row {
mw.rcfilters.ui.RcTopSectionWidget = function MwRcfiltersUiRcTopSectionWidget(
savedLinksListWidget, $topLinks, config
) {
- var topLinksCookieName = 'rcfilters-toplinks-collapsed-state',
+ var toplinksTitle,
+ topLinksCookieName = 'rcfilters-toplinks-collapsed-state',
topLinksCookie = mw.cookie.get( topLinksCookieName ),
topLinksCookieValue = topLinksCookie || 'collapsed',
- toplinksTitle;
+ widget = this;
+
config = config || {};
// Parent
mw.rcfilters.ui.RcTopSectionWidget.parent.call( this, config );
+ this.$topLinks = $topLinks;
+
toplinksTitle = new OO.ui.ButtonWidget( {
framed: false,
indicator: topLinksCookieValue === 'collapsed' ? 'down' : 'up',
label: $( '<span>' ).append( mw.message( 'rcfilters-other-review-tools' ).parse() ).contents()
} );
- $topLinks
+ this.$topLinks
.addClass( 'mw-rcfilters-ui-ready' )
.makeCollapsible( {
collapsed: topLinksCookieValue === 'collapsed',
.on( 'beforeExpand.mw-collapsible', function () {
mw.cookie.set( topLinksCookieName, 'expanded' );
toplinksTitle.setIndicator( 'up' );
+ widget.switchTopLinks( 'expanded' );
} )
.on( 'beforeCollapse.mw-collapsible', function () {
mw.cookie.set( topLinksCookieName, 'collapsed' );
toplinksTitle.setIndicator( 'down' );
+ widget.switchTopLinks( 'collapsed' );
} );
- $topLinks.find( '.mw-recentchanges-toplinks-title' ).replaceWith( toplinksTitle.$element );
+ this.$topLinks.find( '.mw-recentchanges-toplinks-title' ).replaceWith( toplinksTitle.$element );
+
+ // Create two positions for the toplinks to toggle between
+ // in the table (first cell) or up above it
+ this.$top = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-topLinks-top' );
+ this.$tableTopLinks = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-topLinks-table' );
+ // Initialize
this.$element
.addClass( 'mw-rcfilters-ui-rcTopSectionWidget' )
- .addClass( 'mw-rcfilters-ui-table' )
.append(
+ this.$top,
$( '<div>' )
- .addClass( 'mw-rcfilters-ui-row' )
+ .addClass( 'mw-rcfilters-ui-table' )
.append(
$( '<div>' )
- .addClass( 'mw-rcfilters-ui-cell' )
- .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-topLinks' )
- .append( $topLinks )
- )
- .append(
- !mw.user.isAnon() ?
- $( '<div>' )
- .addClass( 'mw-rcfilters-ui-cell' )
- .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-savedLinks' )
- .append( savedLinksListWidget.$element ) :
- null
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ this.$tableTopLinks,
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table-placeholder' )
+ .addClass( 'mw-rcfilters-ui-cell' ),
+ !mw.user.isAnon() ?
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-savedLinks' )
+ .append( savedLinksListWidget.$element ) :
+ null
+ )
)
);
+
+ // Initialize top links position
+ widget.switchTopLinks( topLinksCookieValue );
};
/* Initialization */
OO.inheritClass( mw.rcfilters.ui.RcTopSectionWidget, OO.ui.Widget );
+
+ /**
+ * Switch the top links widget from inside the table (when collapsed)
+ * to the 'top' (when open)
+ *
+ * @param {string} [state] The state of the top links widget: 'expanded' or 'collapsed'
+ */
+ mw.rcfilters.ui.RcTopSectionWidget.prototype.switchTopLinks = function ( state ) {
+ state = state || 'expanded';
+
+ if ( state === 'expanded' ) {
+ this.$top.append( this.$topLinks );
+ } else {
+ this.$tableTopLinks.append( this.$topLinks );
+ }
+ };
}( mediaWiki ) );
$this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
}
+ $extraFields[$pk] = $this->db->nextSequenceValue( "{$table}_{$pk}_seq" );
$this->db->insert( $table, $extraFields + $fields, __METHOD__ );
$id = $this->db->insertId();
if ( $usesTemp ) {
}
public static function provideInsertRoundTrip() {
+ $db = wfGetDB( DB_REPLICA ); // for timestamps
+
$msgComment = new Message( 'parentheses', [ 'message comment' ] );
$textCommentMsg = new RawMessage( '$1', [ 'text comment' ] );
$nestedMsgComment = new Message( [ 'parentheses', 'rawmessage' ], [ new Message( 'mainpage' ) ] );
$ipbfields = [
'ipb_range_start' => '',
'ipb_range_end' => '',
+ 'ipb_by' => 0,
+ 'ipb_timestamp' => $db->timestamp(),
+ 'ipb_expiry' => $db->getInfinity(),
];
$revfields = [
'rev_page' => 42,
'rev_text_id' => 42,
'rev_len' => 0,
+ 'rev_user' => 0,
+ 'rev_user_text' => '',
+ 'rev_timestamp' => $db->timestamp(),
];
$comStoreComment = new CommentStoreComment(
null, 'comment store comment', null, [ 'foo' => 'bar' ]