Daniel Werner has submitted this change and it was merged. Change subject: Refactor wikibase.store - introduce AbstractedRepoApi ......................................................................
Refactor wikibase.store - introduce AbstractedRepoApi * Remove the useless wikibase.EntityStore.js * Create a new module wikibase.RepoApi which holds basic API functions (useful for the client as we have way less dependencies) * Create wikibase.AbstractedRepoApi which extends the above with abstraction features (useful for the repo) * Added missing dependency for wb.utilities while I was on it Change-Id: If0f4ba3a3b4ff28330860ab308e71c8afaca6a6b --- M client/resources/Resources.php M lib/WikibaseLib.hooks.php M lib/resources/Resources.php M lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js M lib/resources/jquery.wikibase/jquery.wikibase.claimview.js M lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js M lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js M lib/resources/jquery.wikibase/jquery.wikibase.statementview.js A lib/resources/wikibase.RepoApi/wikibase.AbstractedRepoApi.js R lib/resources/wikibase.RepoApi/wikibase.RepoApi.js R lib/resources/wikibase.RepoApi/wikibase.RepoApiError.js D lib/resources/wikibase.store/wikibase.EntityStore.js R lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApi.tests.js R lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApiError.tests.js M repo/tests/selenium/statements/statements_spec.rb 15 files changed, 379 insertions(+), 335 deletions(-) Approvals: Daniel Werner: Verified; Looks good to me, approved jenkins-bot: Checked diff --git a/client/resources/Resources.php b/client/resources/Resources.php index 06a0ed9..2a117a0 100644 --- a/client/resources/Resources.php +++ b/client/resources/Resources.php @@ -56,7 +56,8 @@ 'mediawiki.jqueryMsg', 'wikibase.client.currentSite', 'wikibase.sites', - 'wikibase.store', + 'wikibase.RepoApi', + 'wikibase.RepoApiError', 'wikibase.ui.Tooltip' ), 'messages' => array( diff --git a/lib/WikibaseLib.hooks.php b/lib/WikibaseLib.hooks.php index 435ae16..f04d7af 100644 --- a/lib/WikibaseLib.hooks.php +++ b/lib/WikibaseLib.hooks.php @@ -128,8 +128,8 @@ 'tests/qunit/wikibase.Site.tests.js', - 'tests/qunit/wikibase.store/wikibase.RepoApi.tests.js', - 'tests/qunit/wikibase.store/wikibase.RepoApiError.tests.js', + 'tests/qunit/wikibase.RepoApi/wikibase.RepoApi.tests.js', + 'tests/qunit/wikibase.RepoApi/wikibase.RepoApiError.tests.js', 'tests/qunit/wikibase.ui.AliasesEditTool.tests.js', 'tests/qunit/wikibase.ui.DescriptionEditTool.tests.js', @@ -172,6 +172,7 @@ 'dependencies' => array( 'wikibase.tests.qunit.testrunner', 'wikibase', + 'wikibase.AbstractedRepoApi', 'wikibase.parsers', 'wikibase.store', 'wikibase.utilities', diff --git a/lib/resources/Resources.php b/lib/resources/Resources.php index 0276448..3a3986f 100644 --- a/lib/resources/Resources.php +++ b/lib/resources/Resources.php @@ -126,16 +126,9 @@ 'scripts' => array( 'wikibase.store/store.js', 'wikibase.store/store.FetchedContent.js', - 'wikibase.store/wikibase.EntityStore.js', // TODO: get rid of this - 'wikibase.store/wikibase.RepoApi.js', // TODO: move ), 'dependencies' => array( - 'jquery.json', - 'user.tokens', - 'wikibase.datamodel', - 'wikibase.serialization.entities', - 'wikibase.repoAccess', - 'wikibase.RepoApiError', + 'wikibase', 'mediawiki.Title', ) ), @@ -150,9 +143,33 @@ ) ), + 'wikibase.AbstractedRepoApi' => $moduleTemplate + array( + 'scripts' => array( + 'wikibase.RepoApi/wikibase.AbstractedRepoApi.js', + ), + 'dependencies' => array( + 'wikibase.datamodel', + 'wikibase.serialization.entities', + 'wikibase.RepoApi', + 'wikibase.utilities', + ) + ), + + 'wikibase.RepoApi' => $moduleTemplate + array( + 'scripts' => array( + 'wikibase.RepoApi/wikibase.RepoApi.js', + ), + 'dependencies' => array( + 'jquery.json', + 'user.tokens', + 'wikibase.repoAccess', + 'wikibase', + ) + ), + 'wikibase.RepoApiError' => $moduleTemplate + array( 'scripts' => array( - 'wikibase.store/wikibase.RepoApiError.js', + 'wikibase.RepoApi/wikibase.RepoApiError.js', ), 'messages' => array( 'wikibase-error-unexpected', @@ -186,6 +203,7 @@ 'wikibase.utilities/wikibase.utilities.ui.css', ), 'dependencies' => array( + 'dataValues.util', 'wikibase', 'jquery.tipsy', 'mediawiki.language', @@ -345,7 +363,7 @@ 'wikibase.utilities', 'wikibase.utilities.jQuery', 'wikibase.utilities.jQuery.ui.tagadata', - 'wikibase.store', + 'wikibase.AbstractedRepoApi', ), 'messages' => array( 'wikibase-cancel', @@ -524,6 +542,7 @@ 'jquery.nativeEventHandler', 'jquery.wikibase.entityselector', 'wikibase.datamodel', + 'wikibase.AbstractedRepoApi', 'wikibase.store', // required for getting datatype from entityselector selected property 'mediawiki.legacy.shared', 'jquery.ui.TemplatedWidget', @@ -555,6 +574,7 @@ 'dependencies' => array( 'jquery.wikibase.snakview', 'jquery.wikibase.snaklistview', + 'wikibase.AbstractedRepoApi', ), 'messages' => array( 'wikibase-addqualifier', @@ -570,6 +590,7 @@ 'dependencies' => array( 'jquery.wikibase.snaklistview', 'jquery.wikibase.toolbarcontroller', + 'wikibase.AbstractedRepoApi', ) ), @@ -582,6 +603,7 @@ 'jquery.wikibase.listview', 'jquery.wikibase.referenceview', 'jquery.wikibase.toolbarcontroller', + 'wikibase.AbstractedRepoApi', 'wikibase.utilities', ), 'messages' => array( @@ -598,6 +620,7 @@ 'dependencies' => array( 'jquery.wikibase.claimview', 'jquery.wikibase.toolbarcontroller', + 'wikibase.AbstractedRepoApi', 'wikibase.templates', 'wikibase.utilities.ClaimGuidGenerator', ), diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js index 341b909..8fe6724 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js @@ -426,10 +426,10 @@ */ _removeClaimApiCall: function( claim ) { var guid = claim.getGuid(), - api = new wb.RepoApi(), + abstractedApi = new wb.AbstractedRepoApi(), revStore = wb.getRevisionStore(); - return api.removeClaim( + return abstractedApi.removeClaim( guid, revStore.getClaimRevision( guid ) ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js index b5acad9..3544c4b 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js @@ -394,7 +394,7 @@ */ _saveClaimApiCall: function() { var self = this, - api = new wb.RepoApi(), + abstractedApi = new wb.AbstractedRepoApi(), revStore = wb.getRevisionStore(), guid; @@ -405,7 +405,7 @@ guid = guidGenerator.newGuid( mw.config.get( 'wbEntityId' ) ); } - return api.setClaim( this._instantiateClaim( guid ), revStore.getClaimRevision( guid ) ) + return abstractedApi.setClaim( this._instantiateClaim( guid ), revStore.getClaimRevision( guid ) ) .done( function( savedClaim, pageInfo ) { // Update revision store: revStore.setClaimRevision( pageInfo.lastrevid, savedClaim.getGuid() ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js b/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js index beccfff..ca1b88d 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js @@ -168,10 +168,10 @@ _saveReferenceApiCall: function() { var self = this, guid = this.option( 'statementGuid' ), - api = new wb.RepoApi(), + abstractedApi = new wb.AbstractedRepoApi(), revStore = wb.getRevisionStore(); - return api.setReference( + return abstractedApi.setReference( guid, this.value().getSnaks(), revStore.getClaimRevision( guid ), diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js b/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js index c66c978..98f51c2 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js @@ -204,7 +204,7 @@ .on( 'entityselectorselect', function( e, ui ) { // entity chosen in entity selector but we still need the data type of the entity, so // we have to make a separate API call: - var api = new wb.RepoApi(), + var abstractedApi = new wb.AbstractedRepoApi(), language = mw.config.get( 'wgUserLanguage' ), entityId = ui.item.id; @@ -217,7 +217,7 @@ ); } - api.getEntities( entityId, null, [ language ] ).done( function( entities ) { + abstractedApi.getEntities( entityId, null, [ language ] ).done( function( entities ) { var entity = entities[ entityId ]; // update local store with newest information about selected property diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js b/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js index d652248..fec0625 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js @@ -231,10 +231,10 @@ * @return {jQuery.Promise} */ _removeReferenceApiCall: function( reference ) { - var api = new wb.RepoApi(), + var abstractedApi = new wb.AbstractedRepoApi(), guid = this.value().getGuid(); - return api.removeReferences( + return abstractedApi.removeReferences( guid, reference.getHash(), wb.getRevisionStore().getClaimRevision( guid ) diff --git a/lib/resources/wikibase.RepoApi/wikibase.AbstractedRepoApi.js b/lib/resources/wikibase.RepoApi/wikibase.AbstractedRepoApi.js new file mode 100644 index 0000000..5f0eacf --- /dev/null +++ b/lib/resources/wikibase.RepoApi/wikibase.AbstractedRepoApi.js @@ -0,0 +1,269 @@ +/** + * @file + * @ingroup WikibaseLib + * @licence GNU GPL v2+ + * @author Daniel Werner < daniel.wer...@wikimedia.de > + * @author Tobias Gritschacher + * @author H. Snater < mediaw...@snater.com > + * @author Marius Hoch < h...@online.de > + */ +( function( mw, wb, $ ) { +'use strict'; + +/** + * Provides abstraced access functions for the wikibase Repo Api + * + * @constructor + * @since 0.4 + */ +wb.AbstractedRepoApi = function wbAbstractedRepoApi() {}; + +$.extend( wb.AbstractedRepoApi.prototype, { + + /** + * wikibase.RepoApi object for internal usage. By having this initialized in the prototype, we can + * share one instance for all instances of the wikibase API. + * @type wb.RepoApi + */ + _repoApi: new wb.RepoApi(), + + /** + * Removes an existing claim. + * + * @param {String} claimGuid The GUID of the Claim to be removed (wb.Claim.getGuid) + * @param {Number} baseRevId + * @return {jQuery.Promise} When resolved, the first parameter in callbacks is the related + * page info which holds the revision ID of the related entity. + */ + removeClaim: function( claimGuid, baseRevId ) { + var deferred = $.Deferred(); + + this._repoApi.removeClaim( claimGuid, baseRevId ) + .done( function( result ) { + deferred.resolve( result.pageinfo ); + } ).fail( function() { + deferred.reject.apply( deferred, arguments ); + } ); + + return deferred.promise(); + }, + + /** + * Will remove one or more existing References of a Statement. + * + * @since 0.4 + * + * @param {string} statementGuid + * @param {string|string[]} referenceHashes One or more hashes of the References to be removed. + * @param {number} baseRevId + * @return {jQuery.Promise} Done callbacks will receive new base revision ID as first parameter. + */ + removeReferences: function( statementGuid, referenceHashes, baseRevId ) { + return this._abstract( + this._repoApi.removeReferences( statementGuid, referenceHashes, baseRevId ), + function( result ) { + return [ result.pageinfo ]; + } + ); + }, + + /** + * Will set a new Reference for a Statement. + * + * @since 0.4 + * + * @param {string} statementGuid + * @param {wb.SnakList} snaks + * @param {number} baseRevId + * @param {string} [referenceHash] A hash of the reference that should be updated. + * If not provided, a new reference is created. + * @return {jQuery.Promise} If resolved, this will get a wb.Reference object as first parameter + * and the last base revision as second parameter. + */ + setReference: function( statementGuid, snaks, baseRevId, referenceHash ) { + var snakJson = snaks.toJSON(); + return this._abstract( + this._repoApi.setReference( statementGuid, snakJson, baseRevId, referenceHash ), + function( result ) { + return [ + wb.Reference.newFromJSON( result.reference ), + result.pageinfo + ]; + } + ); + }, + + /** + * Gets one or more Entities. + * + * @param {String[]|String} ids + * @param {String[]|String} [props] Key(s) of property/ies to retrieve from the API + * default: null (will return all properties) + * @param {String[]} [languages] + * default: null (will return results in all languages) + * @param {String[]|String} [sort] Key(s) of property/ies to sort on + * default: null (unsorted) + * @param {String} [dir] Sort direction may be 'ascending' or 'descending' + * default: null (ascending) + * @return {jQuery.Promise} If successful, the first parameter of the done callbacks will be + * an object with keys of the entity's IDs and values of the requested entities + * represented as wb.Entity objects. If a requested Entity does not exist, it will not + * be represented in the result. + * + * @todo Requires more? tests! + */ + getEntities: function( ids, props, languages, sort, dir ) { + return this._abstract( + this._repoApi.getEntities( ids, props, languages, sort, dir ), + function( result ) { + var entities = {}, + unserializer = ( new wb.serialization.SerializerFactory() ).newUnserializerFor( wb.Entity ); + + $.each( result.entities, function( id, entityData ) { + if( !entityData.id ) { + return; // missing entity + } + + var entity = unserializer.unserialize( entityData ); + entities[ entity.getId() ] = entity; + } ); + + return [ entities ]; + } + ); + }, + + /** + * Creates/Updates an entire claim. + * + * @param {wb.Claim|wb.Statement} claim + * @param {Number} baseRevId + * @return {jQuery.Promise} + */ + setClaim: function( claim, baseRevId ) { + var claimJson = claim.toJSON(); + return this._abstract( + this._repoApi.setClaim( claimJson, baseRevId ), + function( result ) { + return [ + wb.Claim.newFromJSON( result.claim ), + result.pageinfo + ]; + } + ); + }, + + /** + * Creates a claim. + * @todo Needs testing. It would be necessary to create a property for creating a claim. + * The API does not support setting a data type for an entity at the moment. + * + * @param {String} entityId Entity id + * @param {Number} baseRevId revision id + * @param {wb.Snak} mainSnak The new Claim's Main Snak. + * @return {jQuery.Promise} When resolved, the first parameter in callbacks is the saved + * wb.Claim object which holds its final GUID. + */ + createClaim: function( entityId, baseRevId, mainSnak ) { + var params = this._claimApiParams( mainSnak ); + return this._abstract( + this._repoApi.createClaim( + entityId, baseRevId, params.snaktype, params.property, params.value + ), + this._claimApiCallback + ); + }, + + /** + * Changes the Main Snak of an existing claim. + * @todo Needs testing just like createClaim()! + * + * @param {String} claimGuid The GUID of the Claim to be changed (wb.Claim.getGuid) + * @param {Number} baseRevId + * @param {wb.Snak} mainSnak The new value to be set as the claims Main Snak. + * @return {jQuery.Promise} When resolved, the first parameter in callbacks is the changed + * wb.Claim object with the updated Main Snak. + */ + setClaimValue: function( claimGuid, baseRevId, mainSnak ) { + var params = this._claimApiParams( mainSnak ); + return this._abstract( + this._repoApi.setClaimValue( + claimGuid, baseRevId, params.snaktype, params.property, params.value + ), + this._claimApiCallback + ); + }, + + /** + * Helper function for createClaim and setClaimValue. Both have very similar parameters. + * + * @since 0.4 + * + * @param {wb.Snak} mainSnak + * @return {object} + * + * @throws {Error} If no Snak instance is given as second parameter + */ + _claimApiParams: function( mainSnak ) { + if( !mainSnak instanceof wb.Snak ) { + throw new Error( 'A wikibase.Snak object is required as Main Snak' ); + } + var snakJson = mainSnak.toJSON(), + params = { + snaktype: mainSnak.getType(), + // NOTE: currently 'wbsetclaimvalue' API allows to change snak type but not property, + // set it anyhow. Returned promise won't propagate the API warning we will get here. + property: snakJson.property + }; + + if( snakJson.datavalue !== undefined ) { + params.value = snakJson.datavalue.value; + } else { + params.value = null; + } + + return params; + }, + + /** + * Handles the results of claim api calls + * + * @since 0.4 + * + * @param {object} result + * @return {object} + */ + _claimApiCallback: function( result ) { + return [ + wb.Claim.newFromJSON( result.claim ), + result.pageinfo + ]; + }, + + /** + * This will do certain things to the given data and return a $.promise + * + * @since 0.4 + * + * @param {jQuery.Promise} apiPromise + * @param {Function} callbackForAbstraction Called when the request is resolved, will get all + * parameters the original resolved post promise gets. Can return an array whose members + * will then serve as parameters for the public promise. + * @return {jQuery.Promise} + */ + _abstract: function( apiPromise, callbackForAbstraction ) { + var deferred = $.Deferred(), + self = this; + + apiPromise + .done( function() { + var args = callbackForAbstraction.apply( self, arguments ); + deferred.resolve.apply( deferred, args ); + } ) + .fail( deferred.reject ); + + return deferred.promise(); + } +} ); + +}( mediaWiki, wikibase, jQuery ) ); diff --git a/lib/resources/wikibase.store/wikibase.RepoApi.js b/lib/resources/wikibase.RepoApi/wikibase.RepoApi.js similarity index 66% rename from lib/resources/wikibase.store/wikibase.RepoApi.js rename to lib/resources/wikibase.RepoApi/wikibase.RepoApi.js index dc16409..1d7fb6e 100644 --- a/lib/resources/wikibase.store/wikibase.RepoApi.js +++ b/lib/resources/wikibase.RepoApi/wikibase.RepoApi.js @@ -7,11 +7,10 @@ * @author H. Snater < mediaw...@snater.com > * @author Marius Hoch < h...@online.de > */ -( function( mw, wb, $, undefined ) { +( function( mw, wb, $ ) { 'use strict'; -var PARENT = wb.EntityStore, - REPO_API = mw.config.get( 'wbRepoUrl' ) + mw.config.get( 'wbRepoScriptPath' ) + '/api.php', +var REPO_API = mw.config.get( 'wbRepoUrl' ) + mw.config.get( 'wbRepoScriptPath' ) + '/api.php', LOCAL_API = mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/api.php'; if( LOCAL_API === REPO_API ) { @@ -21,13 +20,13 @@ /** * Constructor to create an API object for interaction with the repo Wikibase API. - * This implements the wikibase.EntityStore, so this represents the server sided store which will - * be accessed via the API. + * * @constructor - * @extends wb.EntityStore * @since 0.4 (since 0.3 as wb.Api without support for client usage) */ -wb.RepoApi = wb.utilities.inherit( 'WbRepoApi', PARENT, { +wb.RepoApi = function wbRepoApi() {}; + +$.extend( wb.RepoApi.prototype, { /** * mediaWiki.Api object for internal usage. By having this initialized in the prototype, we can @@ -86,12 +85,7 @@ * default: null (unsorted) * @param {String} [dir] Sort direction may be 'ascending' or 'descending' * default: null (ascending) - * @return {jQuery.Promise} If successful, the first parameter of the done callbacks will be - * an object with keys of the entity's IDs and values of the requested entities - * represented as wb.Entity objects. If a requested Entity does not exist, it will not - * be represented in the result. - * - * @todo Requires tests! + * @return {jQuery.Promise} */ getEntities: function( ids, props, languages, sort, dir ) { var params = { @@ -103,21 +97,7 @@ dir: dir || undefined }; - return this._getAndPromiseWithAbstraction( params, function( result ) { - var entities = {}, - unserializer = ( new wb.serialization.SerializerFactory() ).newUnserializerFor( wb.Entity ); - - $.each( result.entities, function( id, entityData ) { - if( !entityData.id ) { - return; // missing entity - } - - var entity = unserializer.unserialize( entityData ); - entities[ entity.getId() ] = entity; - } ); - - return [ entities ]; - } ); + return this.get( params ); }, /** @@ -216,43 +196,44 @@ /** * Creates/Updates an entire claim. * - * @param {wb.Claim|wb.Statement} claim + * @param {object} claim * @param {Number} baseRevId * @return {jQuery.Promise} */ setClaim: function( claim, baseRevId ) { var params = { action: 'wbsetclaim', - claim:$.toJSON( claim.toJSON() ), + claim: $.toJSON( claim ), baserevid: baseRevId }; - return this._postAndPromiseWithAbstraction( params, function( result ) { - return [ - wb.Claim.newFromJSON( result.claim ), - result.pageinfo - ]; - } ); + return this.post( params ); }, /** * Creates a claim. - * @todo Needs testing. It would be necessary to create a property for creating a claim. - * The API does not support setting a data type for an entity at the moment. * * @param {String} entityId Entity id * @param {Number} baseRevId revision id - * @param {wb.Snak} mainSnak The new Claim's Main Snak. - * @return {jQuery.Promise} When resolved, the first parameter in callbacks is the saved - * wb.Claim object which holds its final GUID. - * - * @throws {Error} If no Snak instance is given in the third parameter + * @param {string} snaktype The type of the snak + * @param {string} property Id of the snaks property + * @param {object} value The value to set the datavalue of the the main snak of the claim to + * @return {jQuery.Promise} */ - createClaim: function( entityId, baseRevId, mainSnak ) { - return this._claimApiCall( baseRevId, mainSnak, { + createClaim: function( entityId, baseRevId, snakType, property, value ) { + var params = { action: 'wbcreateclaim', - entity: entityId - } ); + entity: entityId, + baserevid: baseRevId, + snaktype: snakType, + property: property + }; + + if ( value ) { + params.value = $.toJSON( value ); + } + + return this.post( params ); }, /** @@ -260,77 +241,41 @@ * * @param {String} claimGuid The GUID of the Claim to be removed (wb.Claim.getGuid) * @param {Number} baseRevId - * @return {jQuery.Promise} When resolved, the first parameter in callbacks is the related - * page info which holds the revision ID of the related entity. + * @return {jQuery.Promise} */ removeClaim: function( claimGuid, baseRevId ) { - var deferred = $.Deferred(); - - this.post( { + return this.post( { action: 'wbremoveclaims', claim: claimGuid - } ).done( function( result ) { - deferred.resolve( result.pageinfo ); - } ).fail( function() { - deferred.reject.apply( deferred, arguments ); } ); - - return deferred.promise(); }, /** * Changes the Main Snak of an existing claim. - * @todo Needs testing just like createClaim()! * * @param {String} claimGuid The GUID of the Claim to be changed (wb.Claim.getGuid) * @param {Number} baseRevId - * @param {wb.Snak} mainSnak The new value to be set as the claims Main Snak. - * @return {jQuery.Promise} When resolved, the first parameter in callbacks is the changed - * wb.Claim object with the updated Main Snak. - * - * @throws {Error} If no Snak instance is given in the third parameter - */ - setClaimValue: function( claimGuid, baseRevId, mainSnak ) { - return this._claimApiCall( baseRevId, mainSnak, { - action: 'wbsetclaimvalue', - claim: claimGuid - } ); - }, - - /** - * Helper function for 'wbcreateclaim' and 'wbsetclaimvalue'. Both have very similar handling - * and both will return a $.Promise which returns information about the changed/created claim - * and the pageinfo in its callback. - * - * @param {Number} baseRevId - * @param {wb.Snak} mainSnak - * @param {Object} params 'action' and 'entity' or 'claim' parameter information + * @param {string} snaktype The type of the snak + * @param {string} property Id of the snaks property + * @param {object} value The value to set the datavalue of the the main snak of the claim to * @return {jQuery.Promise} */ - _claimApiCall: function( baseRevId, mainSnak, params ) { - if( !( mainSnak instanceof wb.Snak ) ) { - throw new Error( 'A wikibase.Snak object is required as Main Snak' ); - } - var snakJson = mainSnak.toJSON(); - - $.extend( params, { + setClaimValue: function( claimGuid, baseRevId, snakType, property, value ) { + var params = { + action: 'wbsetclaimvalue', + claim: claimGuid, baserevid: baseRevId, - snaktype: mainSnak.getType(), + snaktype: snakType, // NOTE: currently 'wbsetclaimvalue' API allows to change snak type but not property, - // set it anyhow. Returned promise won't propagate the API warning we will get here. - property: snakJson.property - } ); + // set it anyhow. The abstracted API won't propagate the API warning we will get here. + property: property + }; - if( snakJson.datavalue !== undefined ) { - params.value = $.toJSON( snakJson.datavalue.value ); + if ( value ) { + params.value = $.toJSON( value ); } - return this._postAndPromiseWithAbstraction( params, function( result ) { - return [ - wb.Claim.newFromJSON( result.claim ), - result.pageinfo - ]; - } ); + return this.post( params ); }, /** @@ -339,18 +284,17 @@ * @since 0.4 * * @param {string} statementGuid - * @param {wb.SnakList} snaks + * @param {object} snaks * @param {number} baseRevId * @param {string} [referenceHash] A hash of the reference that should be updated. * If not provided, a new reference is created. - * @return jQuery.Promise If resolved, this will get a wb.Reference object as first parameter - * and the last base revision as second parameter. + * @return {jQuery.Promise} */ setReference: function( statementGuid, snaks, baseRevId, referenceHash ) { var params = { action: 'wbsetreference', statement: statementGuid, - snaks: $.toJSON( snaks.toJSON() ), + snaks: $.toJSON( snaks ), baserevid: baseRevId }; @@ -358,12 +302,7 @@ params.reference = referenceHash; } - return this._postAndPromiseWithAbstraction( params, function( result ) { - return [ - wb.Reference.newFromJSON( result.reference ), - result.pageinfo - ]; - } ); + return this.post( params ); }, /** @@ -374,7 +313,7 @@ * @param {string} statementGuid * @param {string|string[]} referenceHashes One or more hashes of the References to be removed. * @param {number} baseRevId - * @return jQuery.Promise Done callbacks will receive new base revision ID as first parameter. + * @return {jQuery.Promise} */ removeReferences: function( statementGuid, referenceHashes, baseRevId ) { var params = { @@ -384,9 +323,7 @@ baserevid: baseRevId }; - return this._postAndPromiseWithAbstraction( params, function( result ) { - return [ result.pageinfo ]; - } ); + return this.post( params ); }, /** @@ -536,7 +473,6 @@ } }, - /** * Performs an API get request. * @see mw.Api.get @@ -548,51 +484,9 @@ var options = {}; this._extendRepoCallParams( params, options ); - return this._api.get( params, options ); - }, - - /** - * Same as post() or get() but will return a jQuery.Promise which will resolve with some - * different arguments, specified in a callback. - * - * @since 0.4 - * - * @param {string} method Either 'post' or 'get' - * @param params - * @param {Function} callbackForAbstraction Called when post request is resolved, will get all - * parameters the original resolved post promise gets. Can return an array whose members - * will then serve as parameters for the public promise. - * @return jQuery.Promise - */ - _requestAndPromiseWithAbstraction: function( method, params, callbackForAbstraction ) { - var deferred = $.Deferred(), - self = this; - - this[ method ]( params ) - .done( function() { - var args = callbackForAbstraction.apply( self, arguments ); - deferred.resolve.apply( deferred, args ); - } ) - .fail( deferred.reject ); - - return deferred.promise(); - }, - - /** - * @see _requestAndPromiseWithAbstraction - */ - _postAndPromiseWithAbstraction: function( params, callbackForAbstraction ) { - return this._requestAndPromiseWithAbstraction( 'post', params, callbackForAbstraction ); - }, - - /** - * @see _requestAndPromiseWithAbstraction - */ - _getAndPromiseWithAbstraction: function( params, callbackForAbstraction ) { - return this._requestAndPromiseWithAbstraction( 'get', params, callbackForAbstraction ); + return this._api.get( params, options ) + .fail( this._logFailure ); } } ); - - // TODO: step by step implementation of the store, starting with basic claim stuff }( mediaWiki, wikibase, jQuery ) ); diff --git a/lib/resources/wikibase.store/wikibase.RepoApiError.js b/lib/resources/wikibase.RepoApi/wikibase.RepoApiError.js similarity index 100% rename from lib/resources/wikibase.store/wikibase.RepoApiError.js rename to lib/resources/wikibase.RepoApi/wikibase.RepoApiError.js diff --git a/lib/resources/wikibase.store/wikibase.EntityStore.js b/lib/resources/wikibase.store/wikibase.EntityStore.js deleted file mode 100644 index 7b02500..0000000 --- a/lib/resources/wikibase.store/wikibase.EntityStore.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @file - * @ingroup WikibaseLib - * @licence GNU GPL v2+ - * @author Daniel Werner - */ -( function( wb, dv, $, undefined ) { -'use strict'; - -/** - * Interface definition for generic entity store. - * @constructor - * @abstract - * @since 0.2 - * - * @todo which parameters will be available in the promises callbacks? - * @todo probably the cleanest solution if there will be deriving constructors for all kinds of - * entities. ItemStore, PropertyStore etc... wb.RepoApi could still be an implementation for - * more than just one of these. - */ -wb.EntityStore = function WbEntityStore() {}; - -$.extend( wb.EntityStore.prototype, { - /** - * Stores a single claim for one entity. Returns a promise which will be resolved/rejected - * depending on the operations success. - * - * @param {String} entityId - * @param {wb.Claim} claim - * @returns jQuery.Promise - */ - storeClaim: wb.utilities.abstractMember, - - /** - * Loads an entities claims. Returns a promise which will be resolved/rejected depending on - * the operation's success. - * - * @param {String} entityId - * @returns jQuery.Promise - */ - getClaims: wb.utilities.abstractMember, - - /** - * Stores a single qualifier (Auxiliary Snak) for an existing claim. Returns a promise which - * will be resolved/rejected depending on the operation's success. - * - * @param {String} GUID for identifying the claim - * @param {wb.Snak} qualifier - * @returns jQuery.Promise - */ - setClaimQualifier: wb.utilities.abstractMember, - - /** - * Removes a single qualifier (Auxiliary Snak) of a claim. Returns a promise which will be - * resolved/rejected depending on the operation's success. - * - * @param {String} GUID for identifying the claim - * @param {wb.Snak} qualifier Has to exactly match the qualifier which should be removed. - * @returns jQuery.Promise - */ - removeClaimQualifier: wb.utilities.abstractMember, - - /** - * @param {String} GUID for identifying the claim - * @param {dv.DataValue} - * @returns jQuery.Promise - */ - setClaimValue: wb.utilities.abstractMember, - - /** - * This will add or overwrite a single source reference for an existing statement. Returns a - * promise which will be resolved/rejected depending on the operation's success. - * - * @param {String} GUID for identifying the statement - * @param {wb.Snak[]} reference A set of Snaks which represent describe the reference - * @param {String} [refHash] If set, the given reference will overwrite this one - * @returns jQuery.Promise - */ - setStatementReference: wb.utilities.abstractMember, - - /** - * Removes a single source reference for an existing statement. Returns a promise which will be - * resolved/rejected depending on the operation's success. - * - * @param {String} GUID for identifying the statement - * @param {String} refHash for identifying the reference - * @returns jQuery.Promise - */ - removeStatementReference: wb.utilities.abstractMember, - - /** - * Sets the rank for a statement, overwrites the current rank. - * - * @param {String} GUID for identifying the statement - * @param {Number} rank The new rank. - * @returns jQuery.Promise - */ - setStatementRank: wb.utilities.abstractMember, - - /** - * This will add or replace an entity. Returns a promise which will be resolved when the entity - * has been stored successfully. The promise will be rejected if some error occurred while - * storing the entity. - * - * @param {wb.Entity} entity - * @param {String} [id] for overwriting an existing entity - * @returns jQuery.Promise - */ - setEntity: wb.utilities.abstractMember, - - /** - * Loads one or more entities from the store. A promise will be returned. When resolved the - * entities will be available in registered callbacks. - * - * @param {String|String[]|wb.SiteLink} criteria - * @returns jQuery.Promise - */ - getEntities: function( criteria ) { - var accessFn, - sample = $.isArray( criteria ) ? criteria[0] : criteria; - - if( typeof sample === 'string' ) { - accessFn = this.getEntitiesByIds; - } - else if( sample instanceof wb.SiteLink ) { - accessFn = this.getEntityBySiteLink; - } - - return accessFn( criteria ); - }, - - /** - * Loads one or more entities with the given IDs from the store. - * - * @param {String|String[]} IDs - * @returns jQuery.Promise - */ - getEntitiesByIds: wb.utilities.abstractMember, - - /** - * Loads one or more entities which link to the given site from the store. - * - * @todo this is something Item specific! - * - * @param {Title|Title[]} IDs - * @returns jQuery.Promise - */ - getEntityBySiteLink: wb.utilities.abstractMember -} ); - -}( wikibase, dataValues, jQuery ) ); diff --git a/lib/tests/qunit/wikibase.store/wikibase.RepoApi.tests.js b/lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApi.tests.js similarity index 96% rename from lib/tests/qunit/wikibase.store/wikibase.RepoApi.tests.js rename to lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApi.tests.js index 12789af..3dfed5a 100644 --- a/lib/tests/qunit/wikibase.store/wikibase.RepoApi.tests.js +++ b/lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApi.tests.js @@ -18,6 +18,13 @@ var api = new wb.RepoApi(); /** + * wb.AbstractedRepoApi object + * @var {Object} + */ + // @FIXME: Don't mix the plain RepoApi with the abstracted one + var abstractedApi = new wb.AbstractedRepoApi(); + + /** * Queue used run asynchronous tests synchronously. * @var {jQuery} */ @@ -191,12 +198,12 @@ } ); testrun.queue( qkey, function() { - api.getEntities( entity.id, typesApiPropName ).done( function( entities ) { + abstractedApi.getEntities( entity.id, typesApiPropName ).done( function( entities ) { assert.ok( entities[ entity.id ] instanceof wb.Entity, 'Entity "' + entity.id + '", the ' + type + ' has been set for, has been' + - 'returned by wb.RepoApi.getEntities.' + 'returned by wb.AbstractedRepoApi.getEntities.' ); var entityData = entities[ entity.id ].toMap(); diff --git a/lib/tests/qunit/wikibase.store/wikibase.RepoApiError.tests.js b/lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApiError.tests.js similarity index 100% rename from lib/tests/qunit/wikibase.store/wikibase.RepoApiError.tests.js rename to lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApiError.tests.js diff --git a/repo/tests/selenium/statements/statements_spec.rb b/repo/tests/selenium/statements/statements_spec.rb index 3adfd63..947bbd2 100644 --- a/repo/tests/selenium/statements/statements_spec.rb +++ b/repo/tests/selenium/statements/statements_spec.rb @@ -145,7 +145,7 @@ end it "should check error handling" do on_page(ItemPage) do |page| - js_snippet = "wikibase.RepoApi.prototype.setClaim ="+ + js_snippet = "wikibase.AbstractedRepoApi.prototype.setClaim ="+ "function(claim,baseRevId){var d = new $.Deferred();return d.reject('some_error_code',{error:{info:'some info'}});}" page.navigate_to items[0]["url"] page.wait_for_entity_to_load -- To view, visit https://gerrit.wikimedia.org/r/58223 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If0f4ba3a3b4ff28330860ab308e71c8afaca6a6b Gerrit-PatchSet: 9 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Hoo man <h...@online.de> Gerrit-Reviewer: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Daniel Werner <daniel.wer...@wikimedia.de> Gerrit-Reviewer: Henning Snater <henning.sna...@wikimedia.de> Gerrit-Reviewer: Hoo man <h...@online.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits