Adrian Lang has uploaded a new change for review. https://gerrit.wikimedia.org/r/201182
Change subject: [WIP] Use API for formatting in JS ...................................................................... [WIP] Use API for formatting in JS Doesn't work, since the API does not provide language fallback. Also, I think it would make more sense to implement EntityIdFormatters based on the formatterStore and parserStore instances passed into ViewFactory. That would mean language fallback (once implemented) has to be used in the formatters provided by WikibaseRepo. Thus, the ValueView can also make use of the language fallbacks :) We also want to have a caching decorator for the EntityIdFormatters, or for the formatters and parsers. The latter might increase memory usage too much, though. Bug: T88426 Change-Id: I641d8c46009f59e2b11284cb949322ae4d186b60 --- A view/resources/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.js M view/resources/wikibase/entityIdFormatter/resources.php M view/resources/wikibase/view/ViewFactory.js M view/resources/wikibase/view/resources.php A view/tests/qunit/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.tests.js M view/tests/qunit/wikibase/entityIdFormatter/resources.php 6 files changed, 247 insertions(+), 118 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/82/201182/1 diff --git a/view/resources/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.js b/view/resources/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.js new file mode 100644 index 0000000..1ba9308 --- /dev/null +++ b/view/resources/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.js @@ -0,0 +1,37 @@ +( function( $, wb, util ) { + 'use strict'; + + /** + * @param {wikibase.api.RepoApi} repoApi + */ + wb.entityIdFormatter.ApiEntityIdPlainFormatter = util.inherit( + 'ApiEntityIdPlainFormatter', + wb.entityIdFormatter.EntityIdPlainFormatter, + function( repoApi ) { + if( !repoApi || !( repoApi instanceof wb.api.RepoApi ) ) { + throw new Error( 'Required RepoApi instance not passed' ); + } + this._repoApi = repoApi; + }, + { + _repoApi: null, + + format: function( entityId ) { + var deferred = $.Deferred(), + self = this; + this._repoApi.parseValue( 'wikibase-entityid', [ entityId ] ).done( function( apiResponse ) { + return self._repoApi.formatValue( apiResponse.results[0], null, null, 'text/plain' ).done( function( response ) { + deferred.resolve( response.result ); + } ).fail( function() { + deferred.resolve( entityId ); + } ); + } ).fail( function() { + deferred.resolve( entityId ); + } ); + + return deferred.promise(); + } + + } + ); +}( jQuery, wikibase, util ) ); diff --git a/view/resources/wikibase/entityIdFormatter/resources.php b/view/resources/wikibase/entityIdFormatter/resources.php index 95e1b7e..a2932ef 100644 --- a/view/resources/wikibase/entityIdFormatter/resources.php +++ b/view/resources/wikibase/entityIdFormatter/resources.php @@ -22,6 +22,17 @@ 'wikibase.view.__namespace', ) ), + 'wikibase.entityIdFormatter.ApiEntityIdPlainFormatter' => $moduleTemplate + array( + 'scripts' => array( + 'ApiEntityIdPlainFormatter.js' + ), + 'dependencies' => array( + 'util.inherit', + 'wikibase.api.RepoApi', + 'wikibase.entityIdFormatter.__namespace', + 'wikibase.entityIdFormatter.EntityIdPlainFormatter', + ) + ), 'wikibase.entityIdFormatter.EntityIdHtmlFormatter' => $moduleTemplate + array( 'scripts' => array( 'EntityIdHtmlFormatter.js' diff --git a/view/resources/wikibase/view/ViewFactory.js b/view/resources/wikibase/view/ViewFactory.js index 8f4a055..4d42040 100644 --- a/view/resources/wikibase/view/ViewFactory.js +++ b/view/resources/wikibase/view/ViewFactory.js @@ -1,133 +1,133 @@ ( function( $, wb ) { - 'use strict'; +'use strict'; - var MODULE = wb.view; +var MODULE = wb.view; - /** - * A factory for creating view widgets - * - * @class wikibase.view.ViewFactory - * @licence GNU GPL v2+ - * @since 0.5 - * @author Adrian Heine < adrian.he...@wikimedia.de > - * @constructor - * - * @param {util.ContentLanguages} contentLanguages - * Required by the `ValueView` for limiting the list of available languages for - * particular `jQuery.valueview.Expert` instances like the `Expert` responsible - * for `MonoLingualTextValue`s. - * @param {dataTypes.DataTypeStore} dataTypeStore - * Required by the `snakview` for retrieving and evaluating a proper `dataTypes.DataType` - * object when interacting on a "value" `Variation`. - * @param {wikibase.entityChangers.EntityChangersFactory} entityChangersFactory - * Required to store changed data. - * @param {wikibase.store.EntityStore} entityStore - * Required for dynamically gathering `Entity`/`Property` information. - * @param {jQuery.valueview.ExpertStore} expertStore - * Required by the `ValueView` for constructing `expert`s for different value types. - * @param {valueFormatters.ValueFormatterStore} formatterStore - * Required by the `ValueView` for formatting entered values. - * @param {util.MessageProvider} messageProvider - * Required by the `ValueView` for showing the user interface in the correct language. - * @param {valueParsers.ValueParserStore} parserStore - * Required by the `ValueView` for parsing entered values. - * @param {string[]} userLanguages An array of language codes, the first being the UI language - * Required for showing the user interface in the correct language and for showing terms - * in all languages requested by the user. - */ - var SELF = MODULE.ViewFactory = function ViewFactory( - contentLanguages, - dataTypeStore, - entityChangersFactory, - entityStore, - expertStore, - formatterStore, - messageProvider, - parserStore, - userLanguages - ) { - this._contentLanguages = contentLanguages; - this._dataTypeStore = dataTypeStore; - this._entityChangersFactory = entityChangersFactory; - this._entityStore = entityStore; - this._expertStore = expertStore; - this._formatterStore = formatterStore; - this._messageProvider = messageProvider; - this._parserStore = parserStore; - // Maybe make userLanguages an argument to getEntityView instead of to the constructor - this._userLanguages = userLanguages; - }; +/** + * A factory for creating view widgets + * + * @class wikibase.view.ViewFactory + * @licence GNU GPL v2+ + * @since 0.5 + * @author Adrian Heine < adrian.he...@wikimedia.de > + * @constructor + * + * @param {util.ContentLanguages} contentLanguages + * Required by the `ValueView` for limiting the list of available languages for + * particular `jQuery.valueview.Expert` instances like the `Expert` responsible + * for `MonoLingualTextValue`s. + * @param {dataTypes.DataTypeStore} dataTypeStore + * Required by the `snakview` for retrieving and evaluating a proper `dataTypes.DataType` + * object when interacting on a "value" `Variation`. + * @param {wikibase.entityChangers.EntityChangersFactory} entityChangersFactory + * Required to store changed data. + * @param {wikibase.store.EntityStore} entityStore + * Required for dynamically gathering `Entity`/`Property` information. + * @param {jQuery.valueview.ExpertStore} expertStore + * Required by the `ValueView` for constructing `expert`s for different value types. + * @param {valueFormatters.ValueFormatterStore} formatterStore + * Required by the `ValueView` for formatting entered values. + * @param {util.MessageProvider} messageProvider + * Required by the `ValueView` for showing the user interface in the correct language. + * @param {valueParsers.ValueParserStore} parserStore + * Required by the `ValueView` for parsing entered values. + * @param {string[]} userLanguages An array of language codes, the first being the UI language + * Required for showing the user interface in the correct language and for showing terms + * in all languages requested by the user. + */ +var SELF = MODULE.ViewFactory = function ViewFactory( + contentLanguages, + dataTypeStore, + entityChangersFactory, + entityStore, + expertStore, + formatterStore, + messageProvider, + parserStore, + userLanguages +) { + this._contentLanguages = contentLanguages; + this._dataTypeStore = dataTypeStore; + this._entityChangersFactory = entityChangersFactory; + this._entityStore = entityStore; + this._expertStore = expertStore; + this._formatterStore = formatterStore; + this._messageProvider = messageProvider; + this._parserStore = parserStore; + // Maybe make userLanguages an argument to getEntityView instead of to the constructor + this._userLanguages = userLanguages; +}; - /** - * @property {util.ContentLanguages} - * @private - **/ - SELF.prototype._contentLanguages = null; +/** + * @property {util.ContentLanguages} + * @private + **/ +SELF.prototype._contentLanguages = null; - /** - * @property {dataTypes.DataTypeStore} - * @private - **/ - SELF.prototype._dataTypeStore = null; +/** + * @property {dataTypes.DataTypeStore} + * @private + **/ +SELF.prototype._dataTypeStore = null; - /** - * @property {wikibase.entityChangers.EntityChangersFactory} - * @private - **/ - SELF.prototype._entityChangersFactory = null; +/** + * @property {wikibase.entityChangers.EntityChangersFactory} + * @private + **/ +SELF.prototype._entityChangersFactory = null; - /** - * @property {wikibase.store.EntityStore} - * @private - **/ - SELF.prototype._entityStore = null; +/** + * @property {wikibase.store.EntityStore} + * @private + **/ +SELF.prototype._entityStore = null; - /** - * @property {jQuery.valueview.ExpertStore} - * @private - **/ - SELF.prototype._expertStore = null; +/** + * @property {jQuery.valueview.ExpertStore} + * @private + **/ +SELF.prototype._expertStore = null; - /** - * @property {valueFormatters.ValueFormatterStore} - * @private - **/ - SELF.prototype._formatterStore = null; +/** + * @property {valueFormatters.ValueFormatterStore} + * @private + **/ +SELF.prototype._formatterStore = null; - /** - * @property {util.MessageProvider} - * @private - **/ - SELF.prototype._messageProvider = null; +/** + * @property {util.MessageProvider} + * @private + **/ +SELF.prototype._messageProvider = null; - /** - * @property {valueParsers.ValueParserStore} - * @private - **/ - SELF.prototype._parserStore = null; +/** + * @property {valueParsers.ValueParserStore} + * @private + **/ +SELF.prototype._parserStore = null; - /** - * @property {string[]} - * @private - **/ - SELF.prototype._userLanguages = null; +/** + * @property {string[]} + * @private + **/ +SELF.prototype._userLanguages = null; - /** - * Construct a suitable view for the given entity on the given DOM element - * - * @param {wikibase.datamodel.Entity} entity - * @param {jQuery} $dom - * @return {jQuery.wikibase.entityview} The constructed entity view - * @throws {Error} If there is no view for the given entity type - **/ - SELF.prototype.getEntityView = function( entity, $dom ) { - return this._getView( - entity.getType() + 'view', - $dom, - { - dataTypeStore: this._dataTypeStore, - entityChangersFactory: this._entityChangersFactory, - entityIdPlainFormatter: new wb.entityIdFormatter.SimpleEntityIdPlainFormatter( this._entityStore ), +/** + * Construct a suitable view for the given entity on the given DOM element + * + * @param {wikibase.datamodel.Entity} entity + * @param {jQuery} $dom + * @return {jQuery.wikibase.entityview} The constructed entity view + * @throws {Error} If there is no view for the given entity type + **/ +SELF.prototype.getEntityView = function( entity, $dom ) { + return this._getView( + entity.getType() + 'view', + $dom, + { + dataTypeStore: this._dataTypeStore, + entityChangersFactory: this._entityChangersFactory, + entityIdPlainFormatter: new wb.entityIdFormatter.ApiEntityIdPlainFormatter( new wb.api.RepoApi( new mw.Api() ) ), entityStore: this._entityStore, languages: this._userLanguages, value: entity, diff --git a/view/resources/wikibase/view/resources.php b/view/resources/wikibase/view/resources.php index 899cfd9..2833887 100644 --- a/view/resources/wikibase/view/resources.php +++ b/view/resources/wikibase/view/resources.php @@ -26,7 +26,7 @@ 'dependencies' => array( 'jquery.wikibase.itemview', 'jquery.wikibase.propertyview', - 'wikibase.entityIdFormatter.SimpleEntityIdPlainFormatter', + 'wikibase.entityIdFormatter.ApiEntityIdPlainFormatter', 'wikibase.view.__namespace', 'wikibase.ValueViewBuilder' ) diff --git a/view/tests/qunit/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.tests.js b/view/tests/qunit/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.tests.js new file mode 100644 index 0000000..bc751df --- /dev/null +++ b/view/tests/qunit/wikibase/entityIdFormatter/ApiEntityIdPlainFormatter.tests.js @@ -0,0 +1,71 @@ +( function( $, sinon, QUnit, wb, mw ) { + 'use strict'; + + QUnit.module( 'wikibase.entityIdFormatter.ApiEntityIdPlainFormatter' ); + + var api = new wb.api.RepoApi( {} ); + api.parseValue = function( dataType, values ) { + var deferred = $.Deferred(); + if( values[0] === 'Q2' ) { + deferred.reject(); + } else { + deferred.resolve( + { results: [ { value: { 'entity-type': 'item', 'numeric-id': Number( values[0].substr( 1 ) ) } } ] } + ); + } + return deferred.promise(); + }; + api.formatValue = function( value ) { + var deferred = $.Deferred(); + if( value.value[ 'numeric-id' ] === 3 ) { + deferred.reject(); + } else { + deferred.resolve( { result: 'Label' } ); + } + return deferred.promise(); + }; + + function newFormatter() { + return new wb.entityIdFormatter.ApiEntityIdPlainFormatter( api ); + } + + QUnit.test( 'constructor throws error if no RepoApi is passed', function( assert ) { + assert.throws( function() { + return new wb.entityIdFormatter.ApiEntityIdPlainFormatter(); + } ); + } ); + + QUnit.test( 'constructor throws error if RepoApi is not instance of RepoApi', function( assert ) { + assert.throws( function() { + return new wb.entityIdFormatter.ApiEntityIdPlainFormatter( {} ); + } ); + } ); + + QUnit.test( 'format uses parser and formatter', function( assert ) { + var formatter = newFormatter(); + var done = assert.async(); + formatter.format( 'Q1' ).done( function( res ) { + assert.equal( res, 'Label' ); + done(); + } ); + } ); + + QUnit.test( 'format falls back to the entity id when parsing fails', function( assert ) { + var formatter = newFormatter(); + var done = assert.async(); + formatter.format( 'Q2' ).done( function( res ) { + assert.equal( res, 'Q2' ); + done(); + } ); + } ); + + QUnit.test( 'format falls back to the entity id when formatting fails', function( assert ) { + var formatter = newFormatter(); + var done = assert.async(); + formatter.format( 'Q3' ).done( function( res ) { + assert.equal( res, 'Q3' ); + done(); + } ); + } ); + +}( jQuery, sinon, QUnit, wikibase, mediaWiki ) ); diff --git a/view/tests/qunit/wikibase/entityIdFormatter/resources.php b/view/tests/qunit/wikibase/entityIdFormatter/resources.php index 6065a08..5dba3ce 100644 --- a/view/tests/qunit/wikibase/entityIdFormatter/resources.php +++ b/view/tests/qunit/wikibase/entityIdFormatter/resources.php @@ -50,6 +50,16 @@ ), ), + 'wikibase.entityIdFormatter.ApiEntityIdPlainFormatter.tests' => $moduleTemplate + array( + 'scripts' => array( + 'ApiEntityIdPlainFormatter.tests.js', + ), + 'dependencies' => array( + 'wikibase.api.RepoApi', + 'wikibase.entityIdFormatter.ApiEntityIdPlainFormatter', + ), + ), + ); return $modules; -- To view, visit https://gerrit.wikimedia.org/r/201182 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I641d8c46009f59e2b11284cb949322ae4d186b60 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Adrian Lang <adrian.he...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits