private function showForm() {
global $wgOut, $wgUser, $wgRequest;
+ $conf = RequestContext::getMain()->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
+
if ( $wgUser->isAllowed( 'suppressrevision' ) ) {
$suppress = "<tr id=\"wpDeleteSuppressRow\">
<td></td>
$suppress = '';
}
+ $wgOut->addModules( 'mediawiki.action.delete.file' );
+
$checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $wgUser->isWatched( $this->title );
$form = Xml::openElement( 'form', [ 'method' => 'post', 'action' => $this->getAction(),
'id' => 'mw-img-deleteconfirm' ] ) .
Xml::label( wfMessage( 'filedelete-otherreason' )->text(), 'wpReason' ) .
"</td>
<td class='mw-input'>" .
- Xml::input( 'wpReason', 60, $wgRequest->getText( 'wpReason' ),
- [ 'type' => 'text', 'maxlength' => '255', 'tabindex' => '2', 'id' => 'wpReason' ] ) .
+ Xml::input( 'wpReason', 60, $wgRequest->getText( 'wpReason' ), [
+ 'type' => 'text',
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ 'maxlength' => $oldCommentSchema ? 255 : CommentStore::COMMENT_CHARACTER_LIMIT,
+ 'tabindex' => '2',
+ 'id' => 'wpReason'
+ ] ) .
"</td>
</tr>
{$suppress}";
$textAttribs['class'][] = $this->mClass;
}
+ if ( isset( $this->mParams['maxlength-unit'] ) ) {
+ $textAttribs['data-mw-maxlength-unit'] = $this->mParams['maxlength-unit'];
+ }
+
$allowedParams = [
'required',
'autofocus',
'disabled',
'tabindex',
'maxlength', // gets dynamic with javascript, see mediawiki.htmlform.js
+ 'maxlength-unit', // 'bytes' or 'codepoints', see mediawiki.htmlform.js
];
$textAttribs += $this->getAttributes( $allowedParams );
# TextInput
$textAttribs = [
'name' => $this->mName . '-other',
- 'size' => $this->getSize(),
- 'class' => [ 'mw-htmlform-select-and-other-field' ],
- 'data-id-select' => $this->mID . '-select',
'value' => $value[2],
];
'textinput' => $textAttribs,
'dropdowninput' => $dropdownInputAttribs,
'or' => false,
+ 'classes' => [ 'mw-htmlform-select-and-other-field' ],
+ 'data' => [
+ 'maxlengthUnit' => isset( $this->mParams['maxlength-unit'] )
+ ? $this->mParams['maxlength-unit'] : 'bytes'
+ ],
] );
}
$outputPage->setPageTitle( wfMessage( 'delete-confirm', $title->getPrefixedText() ) );
$outputPage->addBacklinkSubtitle( $title );
$outputPage->setRobotPolicy( 'noindex,nofollow' );
+ $outputPage->addModules( 'mediawiki.action.delete' );
$backlinkCache = $title->getBacklinkCache();
if ( $backlinkCache->hasLinks( 'pagelinks' ) || $backlinkCache->hasLinks( 'templatelinks' ) ) {
]
);
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ $conf = $this->getContext()->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
$fields[] = new OOUI\FieldLayout(
new OOUI\TextInputWidget( [
'name' => 'wpReason',
'inputId' => 'wpReason',
'tabIndex' => 2,
- 'maxLength' => 255,
+ 'maxLength' => $oldCommentSchema ? 255 : CommentStore::COMMENT_CHARACTER_LIMIT,
'infusable' => true,
'value' => $reason,
'autofocus' => true,
$suggestedDurations = self::getSuggestedDurations();
+ $conf = $this->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
+
$a = [
'Target' => [
'type' => 'user',
],
'Reason' => [
'type' => 'selectandother',
- 'maxlength' => 255,
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ 'maxlength' => $oldCommentSchema ? 255 : CommentStore::COMMENT_CHARACTER_LIMIT,
+ 'maxlength-unit' => 'codepoints',
'label-message' => 'ipbreason',
'options-message' => 'ipbreason-dropdown',
],
// Show form if the user can submit
if ( $this->isAllowed ) {
+ $conf = $this->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
+
$form = Xml::openElement( 'form', [ 'method' => 'post',
'action' => $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] ),
'id' => 'mw-revdel-form-revisions' ] ) .
Xml::label( $this->msg( 'tags-edit-reason' )->text(), 'wpReason' ) .
'</td>' .
'<td class="mw-input">' .
- Xml::input(
- 'wpReason',
- 60,
- $this->reason,
- [ 'id' => 'wpReason', 'maxlength' => 100 ]
- ) .
+ Xml::input( 'wpReason', 60, $this->reason, [
+ 'id' => 'wpReason',
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ // "- 155" is to leave room for the auto-generated part of the log entry.
+ 'maxlength' => $oldCommentSchema ? 100 : CommentStore::COMMENT_CHARACTER_LIMIT - 155,
+ ] ) .
'</td>' .
"</tr><tr>\n" .
'<td></td>' .
$out->addHTML( "</div>\n" );
}
- // Byte limit (not string length limit) for wpReason and wpNewTitleMain
- // is enforced in the mediawiki.special.movePage module
+ // Length limit for wpReason and wpNewTitleMain is enforced in the
+ // mediawiki.special.movePage module
$immovableNamespaces = [];
foreach ( array_keys( $this->getLanguage()->getNamespaces() ) as $nsId ) {
]
);
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ $conf = $this->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
$fields[] = new OOUI\FieldLayout(
new OOUI\TextInputWidget( [
'name' => 'wpReason',
'id' => 'wpReason',
- 'maxLength' => 200,
+ 'maxLength' => $oldCommentSchema ? 200 : CommentStore::COMMENT_CHARACTER_LIMIT,
'infusable' => true,
'value' => $this->reason,
] ),
// Show form if the user can submit
if ( $this->mIsAllowed ) {
+ $out->addModules( [ 'mediawiki.special.revisionDelete' ] );
$out->addModuleStyles( 'mediawiki.special' );
+ $conf = $this->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
+
$form = Xml::openElement( 'form', [ 'method' => 'post',
'action' => $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] ),
'id' => 'mw-revdel-form-revisions' ] ) .
Xml::label( $this->msg( 'revdelete-otherreason' )->text(), 'wpReason' ) .
'</td>' .
'<td class="mw-input">' .
- Xml::input(
- 'wpReason',
- 60,
- $this->otherReason,
- [ 'id' => 'wpReason', 'maxlength' => 100 ]
- ) .
+ Xml::input( 'wpReason', 60, $this->otherReason, [
+ 'id' => 'wpReason',
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ // "- 155" is to leave room for the 'wpRevDeleteReasonList' value.
+ 'maxlength' => $oldCommentSchema ? 100 : CommentStore::COMMENT_CHARACTER_LIMIT - 155,
+ ] ) .
'</td>' .
"</tr><tr>\n" .
'<td></td>' .
'content' => new OOUI\HtmlSnippet( $this->msg( 'undeleteextrahelp' )->parseAsBlock() )
] );
+ $conf = $this->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
+
$fields[] = new OOUI\FieldLayout(
new OOUI\TextInputWidget( [
'name' => 'wpComment',
'infusable' => true,
'value' => $this->mComment,
'autofocus' => true,
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ 'maxLength' => $oldCommentSchema ? 255 : CommentStore::COMMENT_CHARACTER_LIMIT,
] ),
[
'label' => $this->msg( 'undeletecomment' )->text(),
->rawParams( $userToolLinks )->parse()
);
if ( $canChangeAny ) {
+ $conf = $this->getConfig();
+ $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
$this->getOutput()->addHTML(
$this->msg( 'userrights-groups-help', $user->getName() )->parse() .
$grouplist .
Xml::label( $this->msg( 'userrights-reason' )->text(), 'wpReason' ) .
"</td>
<td class='mw-input'>" .
- Xml::input( 'user-reason', 60, $this->getRequest()->getVal( 'user-reason', false ),
- [ 'id' => 'wpReason', 'maxlength' => 255 ] ) .
+ Xml::input( 'user-reason', 60, $this->getRequest()->getVal( 'user-reason', false ), [
+ 'id' => 'wpReason',
+ // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
+ // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
+ // Unicode codepoints (or 255 UTF-8 bytes for old schema).
+ 'maxlength' => $oldCommentSchema ? 255 : CommentStore::COMMENT_CHARACTER_LIMIT,
+ ] ) .
"</td>
</tr>
<tr>
/* MediaWiki Action */
+ 'mediawiki.action.delete' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.delete.js',
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'jquery.lengthLimit',
+ ],
+ 'messages' => [
+ // @todo Load this message in content language
+ 'colon-separator',
+ ],
+ ],
+ 'mediawiki.action.delete.file' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.delete.file.js',
+ 'dependencies' => [
+ 'jquery.lengthLimit',
+ ],
+ 'messages' => [
+ // @todo Load this message in content language
+ 'colon-separator',
+ ],
+ ],
'mediawiki.action.edit' => [
'scripts' => [
'resources/src/mediawiki.action/mediawiki.action.edit.js',
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.edittags.js',
'dependencies' => [
'jquery.chosen',
+ 'jquery.lengthLimit',
],
'messages' => [
'tags-edit-chosen-placeholder',
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.recentchanges.js',
'targets' => [ 'desktop', 'mobile' ],
],
+ 'mediawiki.special.revisionDelete' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.revisionDelete.js',
+ 'messages' => [
+ // @todo Load this message in content language
+ 'colon-separator',
+ ],
+ 'dependencies' => [
+ 'jquery.lengthLimit',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
'mediawiki.special.search' => [
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.js',
'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.css',
],
'mediawiki.special.undelete' => [
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js',
+ 'dependencies' => [
+ 'mediawiki.widgets.visibleLengthLimit',
+ 'mediawiki.widgets',
+ ],
],
'mediawiki.special.unwatchedPages' => [
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js',
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userrights.js',
'dependencies' => [
'mediawiki.notification.convertmessagebox',
+ 'jquery.lengthLimit',
],
],
'mediawiki.special.watchlist' => [
--- /dev/null
+/*!
+ * JavaScript for Special:RevisionDelete
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var colonSeparator = mw.message( 'colon-separator' ).text(),
+ summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ $wpDeleteReasonList = $( '#wpDeleteReasonList' ),
+ $wpReason = $( '#wpReason' ),
+ filterFn = function ( input ) {
+ // Should be built the same as in SpecialRevisionDelete::submit()
+ var comment = $wpDeleteReasonList.val();
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ };
+
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ if ( summaryCodePointLimit ) {
+ $wpReason.codePointLimit( summaryCodePointLimit, filterFn );
+ } else if ( summaryByteLimit ) {
+ $wpReason.bytePointLimit( summaryByteLimit, filterFn );
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
--- /dev/null
+/*!
+ * Scripts for action=delete at domready
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var colonSeparator = mw.message( 'colon-separator' ).text(),
+ summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ reasonList = OO.ui.infuse( $( '#wpDeleteReasonList' ).closest( '.oo-ui-widget' ) ),
+ reason = OO.ui.infuse( $( '#wpReason' ).closest( '.oo-ui-widget' ) ),
+ filterFn = function ( input ) {
+ // Should be built the same as in Article::delete()
+ var comment = reasonList.getValue();
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ };
+
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ if ( summaryCodePointLimit ) {
+ reason.$input.codePointLimit( summaryCodePointLimit, filterFn );
+ } else if ( summaryByteLimit ) {
+ reason.$input.bytePointLimit( summaryByteLimit, filterFn );
+ }
+ } );
+}( mediaWiki, jQuery ) );
*/
( function ( mw, $ ) {
$( function () {
- var $tagList = $( '#mw-edittags-tag-list' );
+ var summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ $wpReason = $( '#wpReason' ),
+ $tagList = $( '#mw-edittags-tag-list' );
+
if ( $tagList.length ) {
$tagList.chosen( {
/* eslint-disable camelcase */
$( '#mw-edittags-remove-all' ).prop( 'checked', false );
}
} );
+
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ // use maxLength because it's leaving room for log entry text.
+ if ( summaryCodePointLimit ) {
+ $wpReason.codePointLimit();
+ } else if ( summaryByteLimit ) {
+ $wpReason.bytePointLimit();
+ }
} );
+
}( mediaWiki, jQuery ) );
*/
( function ( mw, $ ) {
$( function () {
+ var summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ wpReason = OO.ui.infuse( $( '#wpReason' ) );
+
// Infuse for pretty dropdown
OO.ui.infuse( $( '#wpNewTitle' ) );
- // Limit to bytes, not characters
- mw.widgets.visibleByteLimit( OO.ui.infuse( $( '#wpReason' ) ) );
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ if ( summaryCodePointLimit ) {
+ mw.widgets.visibleCodePointLimit( wpReason, summaryCodePointLimit );
+ } else if ( summaryByteLimit ) {
+ mw.widgets.visibleByteLimit( wpReason, summaryByteLimit );
+ }
// Infuse for nicer "help" popup
if ( $( '#wpMovetalk-field' ).length ) {
OO.ui.infuse( $( '#wpMovetalk-field' ) );
--- /dev/null
+/*!
+ * JavaScript for Special:RevisionDelete
+ */
+( function ( mw, $ ) {
+ var colonSeparator = mw.message( 'colon-separator' ).text(),
+ summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ $wpRevDeleteReasonList = $( '#wpRevDeleteReasonList' ),
+ $wpReason = $( '#wpReason' ),
+ filterFn = function ( input ) {
+ // Should be built the same as in SpecialRevisionDelete::submit()
+ var comment = $wpRevDeleteReasonList.val();
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ };
+
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ if ( summaryCodePointLimit ) {
+ $wpReason.codePointLimit( summaryCodePointLimit, filterFn );
+ } else if ( summaryByteLimit ) {
+ $wpReason.bytePointLimit( summaryByteLimit, filterFn );
+ }
+
+}( mediaWiki, jQuery ) );
/*!
* JavaScript for Special:Undelete
*/
-jQuery( function ( $ ) {
- $( '#mw-undelete-invert' ).click( function () {
- $( '.mw-undelete-revlist input[type="checkbox"]' ).prop( 'checked', function ( i, val ) {
- return !val;
+( function ( mw, $ ) {
+ $( function () {
+ var summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ wpComment = OO.ui.infuse( $( '#wpComment' ).closest( '.oo-ui-widget' ) );
+
+ $( '#mw-undelete-invert' ).click( function () {
+ $( '.mw-undelete-revlist input[type="checkbox"]' ).prop( 'checked', function ( i, val ) {
+ return !val;
+ } );
} );
+
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ if ( summaryCodePointLimit ) {
+ mw.widgets.visibleCodePointLimit( wpComment, summaryCodePointLimit );
+ } else if ( summaryByteLimit ) {
+ mw.widgets.visibleByteLimit( wpComment, summaryByteLimit );
+ }
} );
-} );
+}( mediaWiki, jQuery ) );
/*!
* JavaScript for Special:UserRights
*/
-( function ( $ ) {
- var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' );
+( function ( mw, $ ) {
+ var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' ),
+ summaryCodePointLimit = mw.config.get( 'wgCommentCodePointLimit' ),
+ summaryByteLimit = mw.config.get( 'wgCommentByteLimit' ),
+ $wpReason = $( '#wpReason' );
+
// Replace successbox with notifications
convertmessagebox();
$( '.mw-userrights-nested select' ).on( 'change', function ( e ) {
$( e.target.parentNode ).find( 'input' ).toggle( $( e.target ).val() === 'other' );
} );
-}( jQuery ) );
+
+ // Limit to bytes or UTF-8 codepoints, depending on MediaWiki's configuration
+ if ( summaryCodePointLimit ) {
+ $wpReason.codePointLimit( summaryCodePointLimit );
+ } else if ( summaryByteLimit ) {
+ $wpReason.bytePointLimit( summaryByteLimit );
+ }
+
+}( mediaWiki, jQuery ) );
$root
.find( '.mw-htmlform-select-and-other-field' )
.each( function () {
- var $this = $( this ),
+ var $reasonList, currentValReasonList, maxlengthUnit, lengthLimiter, widget,
+ $this = $( this ),
+ $widget = $this.closest( '.oo-ui-widget[data-ooui]' );
+
+ if ( $widget ) {
+ mw.loader.using( 'mediawiki.widgets.SelectWithInputWidget', function () {
+ widget = OO.ui.Widget.static.infuse( $widget );
+ maxlengthUnit = widget.getData().maxlengthUnit;
+ lengthLimiter = maxlengthUnit === 'codepoints' ? 'codePointLimit' : 'byteLimit';
+ widget.textinput.$input[ lengthLimiter ]( function ( input ) {
+ // Should be built the same as in HTMLSelectAndOtherField::loadDataFromRequest
+ var comment = widget.dropdowninput.getValue();
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ } );
+ } );
+ } else {
// find the reason list
- $reasonList = $root.find( '#' + $this.data( 'id-select' ) ),
+ $reasonList = $root.find( '#' + $this.data( 'id-select' ) );
// cache the current selection to avoid expensive lookup
currentValReasonList = $reasonList.val();
- $reasonList.change( function () {
- currentValReasonList = $reasonList.val();
- } );
+ $reasonList.change( function () {
+ currentValReasonList = $reasonList.val();
+ } );
- $this.byteLimit( function ( input ) {
- // Should be built the same as in HTMLSelectAndOtherField::loadDataFromRequest
- var comment = currentValReasonList;
- if ( comment === 'other' ) {
- comment = input;
- } else if ( input !== '' ) {
- // Entry from drop down menu + additional comment
- comment += colonSeparator + input;
- }
- return comment;
- } );
+ // Select the function for the length limit
+ maxlengthUnit = $this.data( 'mw-maxlength-unit' );
+ lengthLimiter = maxlengthUnit === 'codepoints' ? 'codePointLimit' : 'byteLimit';
+ $this[ lengthLimiter ]( function ( input ) {
+ // Should be built the same as in HTMLSelectAndOtherField::loadDataFromRequest
+ var comment = currentValReasonList;
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ } );
+ }
} );
} );