jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/341577 )
Change subject: Add item selector to lexeme language textfield.
......................................................................
Add item selector to lexeme language textfield.
* introduces LanguageLookupWidget built on TextInputWidget and
LookupElement using wbsearchentities
* adds classes that make it possible to createLanguageLookupWidget from PHP
Bug: T160515
Change-Id: I6ed726c3cfb223705c466548d856e13e5ab4ac37
---
M extension.json
A resources/special/NewLexeme.js
A resources/special/__namespace.js
A resources/widgets/LanguageLookupWidget.js
A resources/widgets/__namespace.js
A src/Specials/HTMLForm/LanguageLookupWidget.php
A src/Specials/HTMLForm/LanguageLookupWidgetField.php
M src/Specials/SpecialNewLexeme.php
M src/WikibaseLexeme.hooks.php
A tests/phpunit/mediawiki/Specials/HTMLForm/LanguageLookupWidgetFieldTest.php
A tests/qunit/widgets/LanguageLookupWidget.tests.js
11 files changed, 353 insertions(+), 13 deletions(-)
Approvals:
Jonas Kress (WMDE): Looks good to me, approved
Aleksey Bekh-Ivanov (WMDE): Looks good to me, but someone else must approve
jenkins-bot: Verified
diff --git a/extension.json b/extension.json
index f9e7268..7de5c99 100644
--- a/extension.json
+++ b/extension.json
@@ -31,6 +31,9 @@
],
"WikibaseClientEntityTypes": [
"Wikibase\\Lexeme\\WikibaseLexemeHooks::onWikibaseEntityTypes"
+ ],
+ "ResourceLoaderTestModules": [
+
"Wikibase\\Lexeme\\WikibaseLexemeHooks::onResourceLoaderTestModules"
]
},
"MessagesDirs": {
@@ -90,6 +93,27 @@
"wikibase.serialization.TermMapDeserializer"
]
},
+ "wikibase.lexeme.widgets.LanguageLookupWidget": {
+ "scripts": [
+ "widgets/__namespace.js",
+ "widgets/LanguageLookupWidget.js"
+ ],
+ "dependencies": [
+ "oojs-ui-core",
+ "oojs-ui-widgets",
+ "wikibase.lexeme"
+ ]
+ },
+ "wikibase.lexeme.special.NewLexeme": {
+ "scripts": [
+ "special/__namespace.js",
+ "special/NewLexeme.js"
+ ],
+ "dependencies": [
+ "mw.config.values.wbRepo",
+ "wikibase.lexeme.widgets.LanguageLookupWidget"
+ ]
+ },
"wikibase.lexeme.styles": {
"position": "top",
"styles": [
diff --git a/resources/special/NewLexeme.js b/resources/special/NewLexeme.js
new file mode 100644
index 0000000..aef17db
--- /dev/null
+++ b/resources/special/NewLexeme.js
@@ -0,0 +1,20 @@
+( function ( $, mw, wb ) {
+ 'use strict';
+
+ var repoConfig = mw.config.get( 'wbRepo' ),
+ repoApiUrl = repoConfig.url + repoConfig.scriptPath +
'/api.php',
+ lookup = wb.lexeme.widgets.LanguageLookupWidget.static.infuse(
+ 'wb-newlexeme-lexeme-language'
+ );
+
+ lookup.initialize( {
+ apiUrl: repoApiUrl,
+ language: mw.config.get( 'wgUserLanguage' ),
+ timeout: 8000
+ } );
+
+}(
+ jQuery,
+ mediaWiki,
+ wikibase
+) );
diff --git a/resources/special/__namespace.js b/resources/special/__namespace.js
new file mode 100644
index 0000000..f87ea07
--- /dev/null
+++ b/resources/special/__namespace.js
@@ -0,0 +1 @@
+wikibase.lexeme.special = wikibase.lexeme.special || {};
diff --git a/resources/widgets/LanguageLookupWidget.js
b/resources/widgets/LanguageLookupWidget.js
new file mode 100644
index 0000000..0bf062d
--- /dev/null
+++ b/resources/widgets/LanguageLookupWidget.js
@@ -0,0 +1,132 @@
+(function ( $, mw, wb ) {
+ 'use strict';
+
+ /**
+ * @see OO.ui.TextInputWidget
+ *
+ * @param config
+ *
+ * @license GPL-2.0+
+ */
+ var LanguageLookupWidget = function ( config ) {
+ OO.ui.TextInputWidget.call( this, config );
+ OO.ui.mixin.LookupElement.call( this, config );
+ };
+
+ OO.inheritClass( LanguageLookupWidget, OO.ui.TextInputWidget );
+ OO.mixinClass( LanguageLookupWidget, OO.ui.mixin.LookupElement );
+
+ $.extend( LanguageLookupWidget.prototype, {
+
+ /**
+ * @property {string}
+ */
+ _language: null,
+
+ /**
+ * @property {string}
+ */
+ _apiUrl: null,
+
+ /**
+ * @property {integer}
+ */
+ _timeout: null,
+
+ /**
+ * @property {boolean}
+ */
+ _isInitialized: false,
+
+ /**
+ * Used to inject dependencies into the widget, since the
element gets instantiated
+ * automatically from OOJS
+ *
+ * @param {Object} options containing apiUrl, language and
timeout
+ */
+ initialize: function ( options ) {
+ if ( !options.apiUrl || !options.language ||
!options.timeout ) {
+ throw new Error( 'apiUrl, language and timeout
need to be specified.' );
+ }
+
+ this._language = options.language;
+ this._apiUrl = options.apiUrl;
+ this._timeout = options.timeout;
+
+ this._isInitialized = true;
+ },
+
+ /**
+ * @see OO.ui.mixin.LookupElement.prototype.getLookupRequest
+ */
+ getLookupRequest: function () {
+ var term = this.getValue(),
+ deferred = $.Deferred();
+
+ if ( !this._isInitialized ) {
+ throw new Error( 'The LanguageLookupWidget has
not been properly initialized.' );
+ }
+
+ $.ajax( {
+ url: this._apiUrl,
+ timeout: this._timeout,
+ dataType: 'json',
+ data: this._getSearchApiParameters( term )
+ } )
+ .done( function ( response ) {
+ if ( response.error ) {
+ deferred.reject(
response.error.info );
+ return;
+ }
+
+ deferred.resolve( response.search );
+ } )
+ .fail( function ( jqXHR, textStatus ) {
+ deferred.reject( textStatus );
+ } );
+
+ return deferred.promise( {
+ abort: function () {
+ }
+ } );
+ },
+
+ /**
+ * @see
OO.ui.mixin.LookupElement.prototype.getLookupCacheDataFromResponse
+ */
+ getLookupCacheDataFromResponse: function ( response ) {
+ return response || [];
+ },
+
+ /**
+ * @see
OO.ui.mixin.LookupElement.prototype.getLookupMenuOptionsFromData
+ */
+ getLookupMenuOptionsFromData: function ( data ) {
+ var items = [],
+ i;
+
+ for ( i = 0; i < data.length; i++ ) {
+ items.push( new OO.ui.MenuOptionWidget( {
+ data: data[ i ].id,
+ label: data[ i ].label
+ } ) );
+ }
+
+ return items;
+ },
+
+ _getSearchApiParameters: function ( term ) {
+ return {
+ action: 'wbsearchentities',
+ search: term,
+ format: 'json',
+ language: this._language,
+ uselang: this._language,
+ type: 'item'
+ };
+ }
+ } );
+
+ wb.lexeme.widgets.LanguageLookupWidget = LanguageLookupWidget;
+
+})( jQuery, mediaWiki, wikibase );
diff --git a/resources/widgets/__namespace.js b/resources/widgets/__namespace.js
new file mode 100644
index 0000000..1c95fde
--- /dev/null
+++ b/resources/widgets/__namespace.js
@@ -0,0 +1 @@
+wikibase.lexeme.widgets = wikibase.lexeme.widgets || {};
diff --git a/src/Specials/HTMLForm/LanguageLookupWidget.php
b/src/Specials/HTMLForm/LanguageLookupWidget.php
new file mode 100644
index 0000000..8971df4
--- /dev/null
+++ b/src/Specials/HTMLForm/LanguageLookupWidget.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Wikibase\Lexeme\Specials\HTMLForm;
+
+use OOUI\TextInputWidget;
+
+/**
+ * Needed to infuse the LanguageLookupWidget into an existing form field in
the frontend
+ *
+ * @license GPL-2.0+
+ */
+class LanguageLookupWidget extends TextInputWidget {
+
+ protected function getJavaScriptClassName() {
+ return 'wikibase.lexeme.widgets.LanguageLookupWidget';
+ }
+
+}
diff --git a/src/Specials/HTMLForm/LanguageLookupWidgetField.php
b/src/Specials/HTMLForm/LanguageLookupWidgetField.php
new file mode 100644
index 0000000..8faaab0
--- /dev/null
+++ b/src/Specials/HTMLForm/LanguageLookupWidgetField.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Wikibase\Lexeme\Specials\HTMLForm;
+
+use Wikibase\Repo\Specials\HTMLForm\HTMLItemReferenceField;
+
+/**
+ * Passes LanguageLookupWidget instead of OOUI\TextInputWidget to the frontend
+ *
+ * @license GPL-2.0+
+ */
+class LanguageLookupWidgetField extends HTMLItemReferenceField {
+
+ protected function getInputWidget( $params ) {
+ return new LanguageLookupWidget( $params );
+ }
+
+}
diff --git a/src/Specials/SpecialNewLexeme.php
b/src/Specials/SpecialNewLexeme.php
index 027d02b..c5af2b2 100644
--- a/src/Specials/SpecialNewLexeme.php
+++ b/src/Specials/SpecialNewLexeme.php
@@ -2,6 +2,7 @@
namespace Wikibase\Lexeme\Specials;
+use OutputPage;
use Status;
use Wikibase\CopyrightMessageBuilder;
use Wikibase\DataModel\Entity\EntityDocument;
@@ -11,6 +12,7 @@
use Wikibase\DataModel\Term\TermList;
use Wikibase\Lexeme\DataModel\Lexeme;
use Wikibase\Lib\Store\EntityNamespaceLookup;
+use Wikibase\Lexeme\Specials\HTMLForm\LanguageLookupWidgetField;
use Wikibase\Repo\Specials\HTMLForm\HTMLContentLanguageField;
use Wikibase\Repo\Specials\HTMLForm\HTMLItemReferenceField;
use Wikibase\Repo\Specials\HTMLForm\HTMLTrimmedTextField;
@@ -66,12 +68,6 @@
*/
protected function getFormFields() {
return [
- self::FIELD_LEMMA_LANGUAGE => [
- 'name' => self::FIELD_LEMMA_LANGUAGE,
- 'class' => HTMLContentLanguageField::class,
- 'id' => 'wb-newlexeme-lemma-language',
- 'label-message' =>
'wikibase-newlexeme-lemma-language',
- ],
self::FIELD_LEMMA => [
'name' => self::FIELD_LEMMA,
'class' => HTMLTrimmedTextField::class,
@@ -80,18 +76,24 @@
'placeholder-message' =>
'wikibase-lemma-edit-placeholder',
'label-message' => 'wikibase-newlexeme-lemma'
],
+ self::FIELD_LEMMA_LANGUAGE => [
+ 'name' => self::FIELD_LEMMA_LANGUAGE,
+ 'class' => HTMLContentLanguageField::class,
+ 'id' => 'wb-newlexeme-lemma-language',
+ 'label-message' =>
'wikibase-newlexeme-lemma-language',
+ ],
+ self::FIELD_LEXEME_LANGUAGE => [
+ 'name' => self::FIELD_LEXEME_LANGUAGE,
+ 'class' => LanguageLookupWidgetField::class,
+ 'id' => 'wb-newlexeme-lexeme-language',
+ 'label-message' =>
'wikibase-newlexeme-language',
+ 'required' => true,
+ ],
self::FIELD_LEXICAL_CATEGORY => [
'name' => self::FIELD_LEXICAL_CATEGORY,
'class' => HTMLItemReferenceField::class,
'id' => 'wb-newlexeme-lexicalCategory',
'label-message' =>
'wikibase-newlexeme-lexicalcategory',
- 'required' => true,
- ],
- self::FIELD_LEXEME_LANGUAGE => [
- 'name' => self::FIELD_LEXEME_LANGUAGE,
- 'class' => HTMLItemReferenceField::class,
- 'id' => 'wb-newlexeme-lexeme-language',
- 'label-message' =>
'wikibase-newlexeme-language',
'required' => true,
]
];
@@ -163,4 +165,9 @@
return [];
}
+ protected function displayBeforeForm( OutputPage $output ) {
+ parent::displayBeforeForm( $output );
+ $output->addModules( 'wikibase.lexeme.special.NewLexeme' );
+ }
+
}
diff --git a/src/WikibaseLexeme.hooks.php b/src/WikibaseLexeme.hooks.php
index 2c9a040..10c4762 100644
--- a/src/WikibaseLexeme.hooks.php
+++ b/src/WikibaseLexeme.hooks.php
@@ -3,6 +3,7 @@
namespace Wikibase\Lexeme;
use MediaWiki\MediaWikiServices;
+use ResourceLoader;
/**
* MediaWiki hook handlers for the Wikibase Lexeme extension.
@@ -76,4 +77,20 @@
);
}
+ public static function onResourceLoaderTestModules( array
&$testModules, ResourceLoader $rl ) {
+ $testModules['qunit']['WikibaseLexeme.tests'] = [
+ 'scripts' => [
+
'tests/qunit/widgets/LanguageLookupWidget.tests.js',
+ ],
+ 'dependencies' => [
+ 'wikibase.lexeme.widgets.LanguageLookupWidget',
+ 'oojs-ui'
+ ],
+ 'localBasePath' => dirname( __DIR__ ),
+ 'remoteExtPath' => 'WikibaseLexeme',
+ ];
+
+ return true;
+ }
+
}
diff --git
a/tests/phpunit/mediawiki/Specials/HTMLForm/LanguageLookupWidgetFieldTest.php
b/tests/phpunit/mediawiki/Specials/HTMLForm/LanguageLookupWidgetFieldTest.php
new file mode 100644
index 0000000..affd1a9
--- /dev/null
+++
b/tests/phpunit/mediawiki/Specials/HTMLForm/LanguageLookupWidgetFieldTest.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Wikibase\Lexeme\Tests\Specials\HTMLForm;
+
+use ReflectionClass;
+use Wikibase\Lexeme\Specials\HTMLForm\LanguageLookupWidget;
+use Wikibase\Lexeme\Specials\HTMLForm\LanguageLookupWidgetField;
+
+/**
+ * @covers Wikibase\Lexeme\Specials\HTMLForm\LanguageLookupWidgetField
+ *
+ * @group Wikibase
+ *
+ * @license GPL-2.0+
+ */
+class LanguageLookupWidgetFieldTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetInputWidget_returnsLanguageLookupWidget() {
+ $getInputWidget = ( new ReflectionClass(
LanguageLookupWidgetField::class ) )
+ ->getMethod( 'getInputWidget' );
+ $getInputWidget->setAccessible( true );
+
+ $this->assertInstanceOf(
+ LanguageLookupWidget::class,
+ $getInputWidget->invokeArgs( new
LanguageLookupWidgetField( [ 'fieldname' => '' ] ), [ [] ] )
+ );
+ }
+
+}
diff --git a/tests/qunit/widgets/LanguageLookupWidget.tests.js
b/tests/qunit/widgets/LanguageLookupWidget.tests.js
new file mode 100644
index 0000000..c5d9adf
--- /dev/null
+++ b/tests/qunit/widgets/LanguageLookupWidget.tests.js
@@ -0,0 +1,73 @@
+/**
+ * @license GPL-2.0+
+ */
+( function ( wb, $, QUnit ) {
+ QUnit.module( 'wikibase.lexeme.widgets.LanguageLookupWidget' );
+
+ var newInitializedLanguageLookupWidget = function () {
+ var widget = new wb.lexeme.widgets.LanguageLookupWidget();
+
+ widget.initialize( {
+ apiUrl: '-',
+ language: '-',
+ timeout: 100
+ } );
+
+ return widget;
+ };
+
+ var stubWbsearchentitiesResponse = function ( response ) {
+ $.ajax = function () {
+ var deferred = $.Deferred().resolve( response );
+ return deferred.promise();
+ }
+ };
+
+ QUnit.test( 'getLookupRequest returns request results', function (
assert ) {
+ var widget = newInitializedLanguageLookupWidget(),
+ searchEntitiesResults = [ { id: 'Q123', label:
'English' }, { id: 'Q234', label: 'German' } ];
+
+ stubWbsearchentitiesResponse( { search: searchEntitiesResults }
);
+
+ widget.getLookupRequest().done( function ( items ) {
+ assert.deepEqual( items, searchEntitiesResults );
+ } );
+ } );
+
+ QUnit.test( 'getLookupMenuOptionsFromData returns suggestions from
results', function ( assert ) {
+ var widget = newInitializedLanguageLookupWidget(),
+ searchEntitiesResults = [ { id: 'Q123', label:
'English' }, { id: 'Q234', label: 'German' } ],
+ suggestions = widget.getLookupMenuOptionsFromData(
searchEntitiesResults );
+
+ assert.equal( searchEntitiesResults.length, suggestions.length
);
+ assert.equal( searchEntitiesResults[ 0 ].label, suggestions[ 0
].label );
+ assert.equal( searchEntitiesResults[ 0 ].data, suggestions[ 0
].id );
+ assert.equal( searchEntitiesResults[ 1 ].label, suggestions[ 1
].label );
+ assert.equal( searchEntitiesResults[ 1 ].data, suggestions[ 1
].id );
+ } );
+
+ QUnit.test( 'initialize throws error when required parameters are not
provided', function ( assert ) {
+ var widget = new wb.lexeme.widgets.LanguageLookupWidget();
+
+ assert.throws( function () {
+ widget.initialize( { apiUrl: null, language: 'en',
timeout: 100 } );
+ } );
+ assert.throws( function () {
+ widget.initialize( { apiUrl: 'some-url', language:
null, timeout: 100 } );
+ } );
+ assert.throws( function () {
+ widget.initialize( { apiUrl: 'some-url', language:
'en', timeout: null } );
+ } );
+ } );
+
+ QUnit.test( 'getLookupRequest if the LanguageLookupWidget was not
initialized', function ( assert ) {
+ var widget = new wb.lexeme.widgets.LanguageLookupWidget();
+
+ stubWbsearchentitiesResponse( { search: [] } );
+
+ assert.throws( function () {
+ widget.getLookupRequest();
+ } );
+ } )
+
+}( wikibase, jQuery, QUnit ) );
--
To view, visit https://gerrit.wikimedia.org/r/341577
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I6ed726c3cfb223705c466548d856e13e5ab4ac37
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/WikibaseLexeme
Gerrit-Branch: master
Gerrit-Owner: Jakob <[email protected]>
Gerrit-Reviewer: Aleksey Bekh-Ivanov (WMDE) <[email protected]>
Gerrit-Reviewer: Jakob <[email protected]>
Gerrit-Reviewer: Jonas Kress (WMDE) <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: WMDE-leszek <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits