'HTMLTextField' => __DIR__ . '/includes/htmlform/HTMLTextField.php',
'HTMLTextFieldWithButton' => __DIR__ . '/includes/htmlform/HTMLTextFieldWithButton.php',
'HTMLTitleTextField' => __DIR__ . '/includes/htmlform/HTMLTitleTextField.php',
+ 'HTMLUserTextField' => __DIR__ . '/includes/htmlform/HTMLUserTextField.php',
'HWLDFWordAccumulator' => __DIR__ . '/includes/diff/DairikiDiff.php',
'HashBagOStuff' => __DIR__ . '/includes/libs/objectcache/HashBagOStuff.php',
'HashConfig' => __DIR__ . '/includes/config/HashConfig.php',
'MediaWiki\\Logger\\Spi' => __DIR__ . '/includes/debug/logger/Spi.php',
'MediaWiki\\Widget\\NamespaceInputWidget' => __DIR__ . '/includes/widget/NamespaceInputWidget.php',
'MediaWiki\\Widget\\TitleInputWidget' => __DIR__ . '/includes/widget/TitleInputWidget.php',
+ 'MediaWiki\\Widget\\UserInputWidget' => __DIR__ . '/includes/widget/UserInputWidget.php',
'MemCachedClientforWiki' => __DIR__ . '/includes/objectcache/MemcachedClient.php',
'MemcLockManager' => __DIR__ . '/includes/filebackend/lockmanager/MemcLockManager.php',
'MemcachedBagOStuff' => __DIR__ . '/includes/objectcache/MemcachedBagOStuff.php',
'password' => 'HTMLTextField',
'url' => 'HTMLTextField',
'title' => 'HTMLTitleTextField',
+ 'user' => 'HTMLUserTextField',
);
public $mFieldData;
--- /dev/null
+<?php
+
+use MediaWiki\Widget\UserInputWidget;
+
+/**
+ * Implements a text input field for user names.
+ * Automatically auto-completes if using the OOUI display format.
+ *
+ * FIXME: Does not work for forms that support GET requests.
+ *
+ * Optional parameters:
+ * 'exists' - Whether to validate that the user already exists
+ *
+ * @since 1.26
+ */
+class HTMLUserTextField extends HTMLTextField {
+ public function __construct( $params ) {
+ $params += array(
+ 'exists' => false,
+ );
+
+ parent::__construct( $params );
+ }
+
+ public function validate( $value, $alldata ) {
+ // check, if a user exists with the given username
+ $user = User::newFromName( $value );
+
+ if ( !$user ) {
+ return $this->msg( 'htmlform-user-not-valid', $value )->parse();
+ } else if ( $this->mParams['exists'] && $user->getId() === 0 ) {
+ return $this->msg( 'htmlform-user-not-exists', $user->getName() )->parse();
+ }
+
+ return parent::validate( $value, $alldata );
+ }
+
+ protected function getInputWidget( $params ) {
+ $this->mParent->getOutput()->addModules( 'mediawiki.widgets' );
+
+ return new UserInputWidget( $params );
+ }
+}
--- /dev/null
+<?php
+/**
+ * MediaWiki Widgets \96 UserInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+namespace MediaWiki\Widget;
+
+use OOUI\TextInputWidget;
+
+/**
+ * User input widget.
+ */
+class UserInputWidget extends TextInputWidget {
+ /**
+ * @param array $config Configuration options
+ */
+ public function __construct( array $config = array() ) {
+ // Parent constructor
+ parent::__construct( array_merge( $config, array( 'infusable' => true ) ) );
+
+ // Initialization
+ $this->addClasses( array( 'mw-widget-userInputWidget' ) );
+ }
+
+ protected function getJavaScriptClassName() {
+ return 'mw.widgets.UserInputWidget';
+ }
+}
"htmlform-title-badnamespace": "[[:$1]] is not in the \"{{ns:$2}}\" namespace.",
"htmlform-title-not-creatable": "\"$1\" is not a creatable page title",
"htmlform-title-not-exists": "[[:$1]] does not exist.",
+ "htmlform-user-not-exists": "<strong>$1</strong> does not exist.",
+ "htmlform-user-not-valid": "<strong>$1</strong> isn't a valid username.",
"sqlite-has-fts": "$1 with full-text search support",
"sqlite-no-fts": "$1 without full-text search support",
"logentry-delete-delete": "$1 {{GENDER:$2|deleted}} page $3",
"htmlform-title-badnamespace": "Error message shown if the page title provided by the user is not in the required namespace. $1 is the page, $2 is the numerical namespace index.",
"htmlform-title-not-creatable": "Error message shown if the page title provided by the user is not creatable (a special page). $1 is the page title.",
"htmlform-title-not-exists": "Error message shown if the page title provided by the user does not exist. $1 is the page title.",
+ "htmlform-user-not-exists": "Error message shown if a user with the name provided by the user does not exist. $1 is the username.",
+ "htmlform-user-not-valid": "Error message shown if the name provided by the user isn't a valid username. $1 is the username.",
"sqlite-has-fts": "Shown on [[Special:Version]].\nParameters:\n* $1 - version",
"sqlite-no-fts": "Shown on [[Special:Version]].\nParameters:\n* $1 - version",
"logentry-delete-delete": "{{Logentry|[[Special:Log/delete]]}}",
'resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js',
'resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js',
'resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js',
),
'skinStyles' => array(
'default' => array(
--- /dev/null
+/*!
+ * MediaWiki Widgets - UserInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+ /**
+ * Creates a mw.widgets.UserInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ * @mixins OO.ui.mixin.LookupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [limit=10] Number of results to show
+ */
+ mw.widgets.UserInputWidget = function MwWidgetsUserInputWidget( config ) {
+ // Config initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.TextInputWidget.call( this, $.extend( {}, config, { autocomplete: false } ) );
+
+ // Mixin constructors
+ OO.ui.mixin.LookupElement.call( this, config );
+
+ // Properties
+ this.limit = config.limit || 10;
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-userInputWidget' );
+ this.lookupMenu.$element.addClass( 'mw-widget-userInputWidget-menu' );
+ };
+
+ /* Inheritance */
+
+ OO.inheritClass( mw.widgets.UserInputWidget, OO.ui.TextInputWidget );
+
+ OO.mixinClass( mw.widgets.UserInputWidget, OO.ui.mixin.LookupElement );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.UserInputWidget.prototype.onLookupMenuItemChoose = function ( item ) {
+ this.closeLookupMenu();
+ this.setLookupsDisabled( true );
+ this.setValue( item.getData() );
+ this.setLookupsDisabled( false );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.UserInputWidget.prototype.focus = function () {
+ var retval;
+
+ // Prevent programmatic focus from opening the menu
+ this.setLookupsDisabled( true );
+
+ // Parent method
+ retval = OO.ui.TextInputWidget.prototype.focus.apply( this, arguments );
+
+ this.setLookupsDisabled( false );
+
+ return retval;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.UserInputWidget.prototype.getLookupRequest = function () {
+ var inputValue = this.value;
+
+ return new mw.Api().get( {
+ action: 'query',
+ list: 'allusers',
+ // Prefix of list=allusers is case sensitive. Normalise first
+ // character to uppercase so that "fo" may yield "Foo".
+ auprefix: inputValue[0].toUpperCase() + inputValue.slice( 1 ),
+ aulimit: this.limit
+ } );
+ };
+
+ /**
+ * Get lookup cache item from server response data.
+ *
+ * @method
+ * @param {Mixed} data Response from server
+ */
+ mw.widgets.UserInputWidget.prototype.getLookupCacheDataFromResponse = function ( data ) {
+ return data.query || {};
+ };
+
+ /**
+ * Get list of menu items from a server response.
+ *
+ * @param {Object} data Query result
+ * @returns {OO.ui.MenuOptionWidget[]} Menu items
+ */
+ mw.widgets.UserInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
+ var len, i, user,
+ users = data.allusers,
+ items = [];
+
+ for ( i = 0, len = users.length; i < len; i++ ) {
+ user = users[i] || {};
+ items.push( new OO.ui.MenuOptionWidget( {
+ label: user.name,
+ data: user.name
+ } ) );
+ }
+
+ return items;
+ };
+
+}( jQuery, mediaWiki ) );