jenkins-bot has submitted this change and it was merged. Change subject: Introduce wikibase.view.ViewFactory ......................................................................
Introduce wikibase.view.ViewFactory Bug: T87434 Change-Id: I0ff09c7621f478bf05a87a072954d405971750eb --- M repo/resources/Resources.php M repo/resources/wikibase.ui.entityViewInit.js A view/resources/ViewFactory.js M view/resources/resources.php A view/tests/qunit/ViewFactory.tests.js M view/tests/qunit/resources.php 6 files changed, 301 insertions(+), 30 deletions(-) Approvals: Aude: Looks good to me, approved jenkins-bot: Verified diff --git a/repo/resources/Resources.php b/repo/resources/Resources.php index 9f7ff08..db598b2 100644 --- a/repo/resources/Resources.php +++ b/repo/resources/Resources.php @@ -148,8 +148,6 @@ 'dependencies' => array( 'mediawiki.user', 'mw.config.values.wbRepo', - 'jquery.wikibase.itemview', - 'jquery.wikibase.propertyview', 'jquery.wikibase.toolbarcontroller', 'jquery.wikibase.toolbarcontroller.definitions.addtoolbar.statementgrouplistview-statementgroupview', 'jquery.wikibase.toolbarcontroller.definitions.addtoolbar.statementlistview-statementview', @@ -180,7 +178,7 @@ 'wikibase.store.CombiningEntityStore', 'wikibase.store.FetchedContentUnserializer', 'wikibase.store.MwConfigEntityStore', - 'wikibase.ValueViewBuilder', + 'wikibase.view.ViewFactory', 'wikibase.WikibaseContentLanguages' ), 'messages' => array( diff --git a/repo/resources/wikibase.ui.entityViewInit.js b/repo/resources/wikibase.ui.entityViewInit.js index d225ae6..895b747 100644 --- a/repo/resources/wikibase.ui.entityViewInit.js +++ b/repo/resources/wikibase.ui.entityViewInit.js @@ -107,12 +107,12 @@ /** * Builds an entity store. - * @todo Move to a top-level factory or application scope * * @param {wikibase.api.RepoApi} repoApi + * @param {string} languageCode The language code of the ui language * @return {wikibase.store.CombiningEntityStore} */ - function buildEntityStore( repoApi ) { + function buildEntityStore( repoApi, languageCode ) { // Deserializer for fetched content whose content is a wb.datamodel.Entity: var fetchedEntityDeserializer = new wb.store.FetchedContentUnserializer( new wb.serialization.EntityDeserializer() @@ -123,10 +123,9 @@ new wb.store.ApiEntityStore( repoApi, fetchedEntityDeserializer, - [ mw.config.get( 'wgUserLanguage' ) ] + [ languageCode ] ) ] ); - } /** @@ -140,46 +139,39 @@ var repoConfig = mw.config.get( 'wbRepo' ); var mwApi = wb.api.getLocationAgnosticMwApi( repoConfig.url + repoConfig.scriptPath + '/api.php' ); var repoApi = new wb.api.RepoApi( mwApi ), - entityStore = buildEntityStore( repoApi ), + userLanguages = getUserLanguages(), + entityStore = buildEntityStore( repoApi, userLanguages[0] ), revisionStore = new wb.RevisionStore( mw.config.get( 'wgCurRevisionId' ) ), entityChangersFactory = new wb.entityChangers.EntityChangersFactory( repoApi, revisionStore, entity ), - contentLanguages = new wikibase.WikibaseContentLanguages(); - - var viewName = entity.getType() + 'view'; - - if( !$.wikibase[ viewName ] ) { - throw new Error( 'View for entity type ' + entity.getType() + ' does not exist' ); - } - - $entityview[ viewName ]( { - value: entity, - languages: getUserLanguages(), - entityChangersFactory: entityChangersFactory, - entityStore: entityStore, - valueViewBuilder: new wb.ValueViewBuilder( + contentLanguages = new wikibase.WikibaseContentLanguages(), + viewFactory = new wikibase.view.ViewFactory( + contentLanguages, + dataTypeStore, + entityChangersFactory, + entityStore, getExpertsStore( dataTypeStore ), getFormatterStore( repoApi, dataTypeStore ), - getParserStore( repoApi ), - mw.config.get( 'wgUserLanguage' ), { getMessage: function( key, params ) { return mw.msg.apply( mw, [ key ].concat( params ) ); } }, - contentLanguages - ), - dataTypeStore: dataTypeStore - } ); + getParserStore( repoApi ), + userLanguages + ); - return viewName; + var entityView = viewFactory.getEntityView( entity, $entityview ); + + return entityView.widgetName; } /** - * @return {string[]} + * @return {string[]} An ordered list of languages the user wants to use, the first being her + * preferred language, and thus the UI language (currently wgUserLanguage). */ function getUserLanguages() { var userLanguages = mw.config.get( 'wbUserSpecifiedLanguages' ), diff --git a/view/resources/ViewFactory.js b/view/resources/ViewFactory.js new file mode 100644 index 0000000..248d512 --- /dev/null +++ b/view/resources/ViewFactory.js @@ -0,0 +1,168 @@ +( function( $, wb ) { + 'use strict'; + + 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; + }; + + /** + * @property {util.ContentLanguages} + * @private + **/ + SELF.prototype._contentLanguages = null; + + /** + * @property {dataTypes.DataTypeStore} + * @private + **/ + SELF.prototype._dataTypeStore = null; + + /** + * @property {wikibase.entityChangers.EntityChangersFactory} + * @private + **/ + SELF.prototype._entityChangersFactory = null; + + /** + * @property {wikibase.store.EntityStore} + * @private + **/ + SELF.prototype._entityStore = null; + + /** + * @property {jQuery.valueview.ExpertStore} + * @private + **/ + SELF.prototype._expertStore = null; + + /** + * @property {valueFormatters.ValueFormatterStore} + * @private + **/ + SELF.prototype._formatterStore = null; + + /** + * @property {util.MessageProvider} + * @private + **/ + SELF.prototype._messageProvider = null; + + /** + * @property {valueParsers.ValueParserStore} + * @private + **/ + SELF.prototype._parserStore = 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, + entityStore: this._entityStore, + languages: this._userLanguages, + value: entity, + valueViewBuilder: this._getValueViewBuilder() + } + ); + }; + + /** + * @private + * @return {wikibase.ValueViewBuilder} + **/ + SELF.prototype._getValueViewBuilder = function() { + return new wb.ValueViewBuilder( + this._expertStore, + this._formatterStore, + this._parserStore, + this._userLanguages && this._userLanguages[0], + this._messageProvider, + this._contentLanguages + ); + }; + + /** + * @private + * @return {Object} The constructed view + * @throws {Error} If there is no view with the given name + **/ + SELF.prototype._getView = function( viewName, $dom, options ) { + if( !$.wikibase[ viewName ] ) { + throw new Error( 'View ' + viewName + ' does not exist' ); + } + + $dom[ viewName ]( options ); + + return $dom.data( viewName ); + }; + +}( jQuery, wikibase ) ); diff --git a/view/resources/resources.php b/view/resources/resources.php index b47358d..edd593d 100644 --- a/view/resources/resources.php +++ b/view/resources/resources.php @@ -19,6 +19,17 @@ 'namespace.js' ), ), + 'wikibase.view.ViewFactory' => $moduleTemplate + array( + 'scripts' => array( + 'ViewFactory.js' + ), + 'dependencies' => array( + 'jquery.wikibase.itemview', + 'jquery.wikibase.propertyview', + 'wikibase.view.__namespace', + 'wikibase.ValueViewBuilder' + ) + ), ); return $modules; diff --git a/view/tests/qunit/ViewFactory.tests.js b/view/tests/qunit/ViewFactory.tests.js new file mode 100644 index 0000000..e614346 --- /dev/null +++ b/view/tests/qunit/ViewFactory.tests.js @@ -0,0 +1,92 @@ +( function( $, sinon, QUnit, wb, ViewFactory ) { + 'use strict'; + + QUnit.module( 'wikibase.view.ViewFactory' ); + + QUnit.test( 'is constructable', function( assert ) { + assert.ok( new ViewFactory() instanceof ViewFactory ); + } ); + + function getEntityStub( type ) { + return { + getType: function() { + return type; + } + }; + } + + QUnit.test( 'getEntityView constructs correct views', function( assert ) { + var viewFactory = new ViewFactory(), + fooView = {}, + $dom = $( '<div/>' ), + FooView = $dom.fooview = $.wikibase.fooview = sinon.spy(); + $dom.data = sinon.spy( function() { return fooView; } ); + + var res = viewFactory.getEntityView( getEntityStub( 'foo' ), $dom ); + + assert.strictEqual( res, fooView ); + sinon.assert.calledOnce( FooView ); + } ); + + QUnit.test( 'getEntityView throws on incorrect views', function( assert ) { + var viewFactory = new ViewFactory(); + + assert.throws( + function() { + viewFactory.getEntityView( getEntityStub( 'unknown' ) ); + }, + new Error( 'View unknownview does not exist' ) + ); + } ); + + QUnit.test( 'getEntityView passes correct options to views', function( assert ) { + var contentLanguages = {}, + dataTypeStore = {}, + entity = getEntityStub( 'foo' ), + entityChangersFactory = {}, + entityStore = {}, + expertStore = {}, + formatterStore = {}, + messageProvider = {}, + parserStore = {}, + userLanguages = [], + viewFactory = new ViewFactory( + contentLanguages, + dataTypeStore, + entityChangersFactory, + entityStore, + expertStore, + formatterStore, + messageProvider, + parserStore, + userLanguages + ), + $dom = $( '<div/>' ), + FooView = $dom.fooview = $.wikibase.fooview = sinon.spy(); + + sinon.spy( wb, 'ValueViewBuilder' ); + + viewFactory.getEntityView( entity, $dom ); + + sinon.assert.calledWith( wb.ValueViewBuilder, + expertStore, + formatterStore, + parserStore, + userLanguages[0], + messageProvider, + contentLanguages + ); + + sinon.assert.calledWith( FooView, { + dataTypeStore: dataTypeStore, + entityChangersFactory: entityChangersFactory, + entityStore: entityStore, + languages: userLanguages, + value: entity, + valueViewBuilder: wb.ValueViewBuilder.thisValues[0] + } ); + + wb.ValueViewBuilder.restore(); + } ); + +}( jQuery, sinon, QUnit, wikibase, wikibase.view.ViewFactory ) ); diff --git a/view/tests/qunit/resources.php b/view/tests/qunit/resources.php index 36c81a2..5e0bc17 100644 --- a/view/tests/qunit/resources.php +++ b/view/tests/qunit/resources.php @@ -15,6 +15,16 @@ $modules = array( + 'wikibase.view.ViewFactory.tests' => $moduleTemplate + array( + 'scripts' => array( + 'ViewFactory.tests.js', + ), + 'dependencies' => array( + 'wikibase.view.ViewFactory', + 'wikibase.ValueViewBuilder' + ), + ), + ); return $modules; -- To view, visit https://gerrit.wikimedia.org/r/188357 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I0ff09c7621f478bf05a87a072954d405971750eb Gerrit-PatchSet: 8 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Adrian Lang <adrian.he...@wikimedia.de> Gerrit-Reviewer: Adrian Lang <adrian.he...@wikimedia.de> Gerrit-Reviewer: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Henning Snater <henning.sna...@wikimedia.de> Gerrit-Reviewer: Jeroen De Dauw <jeroended...@gmail.com> Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits