Henning Snater has uploaded a new change for review. https://gerrit.wikimedia.org/r/53325
Change subject: (bug 44683) Implementing setClaim API module in the JS API ...................................................................... (bug 44683) Implementing setClaim API module in the JS API Stub implementation of wbsetclaim API module. This change set also implements some equals() and toJSON() methods for wb.Reference, wb.Claim and wb.Statement not yet implemented but required for actually using the API method later on. Change-Id: I0e1d341549e253bfb411bc61960bbd57ad569c84 --- M lib/WikibaseLib.hooks.php M lib/resources/wikibase.datamodel/wikibase.Claim.js M lib/resources/wikibase.datamodel/wikibase.Reference.js M lib/resources/wikibase.datamodel/wikibase.Statement.js M lib/resources/wikibase.store/wikibase.RepoApi.js M lib/tests/qunit/wikibase.datamodel/Wikibase.claim.tests.js M lib/tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js A lib/tests/qunit/wikibase.datamodel/wikibase.Statement.tests.js 8 files changed, 560 insertions(+), 17 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/25/53325/1 diff --git a/lib/WikibaseLib.hooks.php b/lib/WikibaseLib.hooks.php index e6198f4..5ab0a72 100644 --- a/lib/WikibaseLib.hooks.php +++ b/lib/WikibaseLib.hooks.php @@ -129,6 +129,7 @@ 'tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js', 'tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js', 'tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js', + 'tests/qunit/wikibase.datamodel/wikibase.Statement.tests.js', 'tests/qunit/wikibase.datamodel/datamodel.Entity.tests.js', 'tests/qunit/wikibase.datamodel/datamodel.Item.tests.js', 'tests/qunit/wikibase.datamodel/datamodel.Property.tests.js', diff --git a/lib/resources/wikibase.datamodel/wikibase.Claim.js b/lib/resources/wikibase.datamodel/wikibase.Claim.js index a28d618..2ff245e 100644 --- a/lib/resources/wikibase.datamodel/wikibase.Claim.js +++ b/lib/resources/wikibase.datamodel/wikibase.Claim.js @@ -31,8 +31,7 @@ _mainSnak: null, /** - * @type wb.Snak[] - * @todo think about implementing a SnakList rather than having an Array here + * @type {wb.SnakList} */ _qualifiers: null, @@ -107,10 +106,33 @@ equals: function( claim ) { return this === claim || ( // snaks have no IDs, so we don't have to worry about comparing any - claim instanceof wb.Claim + claim instanceof this.constructor && this._mainSnak.equals( claim.getMainSnak() ) && this._qualifiers.equals( claim.getQualifiers() ) ); + }, + + /** + * Returns a JSON structure representing this claim. + * @since 0.4 + * + * @return {Object} + */ + toJSON: function() { + var json = { + type: this.constructor.TYPE, + mainsnak: this._mainSnak.toJSON() + }; + + if ( this._guid ) { + json.id = this._guid; + } + + if ( this._qualifiers ) { + json.qualifiers = this._qualifiers.toJSON(); + } + + return json; } }; @@ -129,9 +151,7 @@ isStatement = json.type === 'statement'; if ( json.qualifiers !== undefined ) { - $.each( json.qualifiers, function( i, qualifier ) { - qualifiers.addSnak( wb.Snak.newFromJSON( qualifier ) ); - } ); + qualifiers = wb.SnakList.newFromJSON( json.qualifiers ); } if ( isStatement && json.references !== undefined ) { @@ -149,4 +169,11 @@ return new wb.Claim( mainSnak, qualifiers, guid ); }; +/** + * String to identify if the object is a statement or a claim. + * @since 0.4 + * @type {string} + */ +wb.Claim.TYPE = 'claim'; + }( wikibase, jQuery ) ); diff --git a/lib/resources/wikibase.datamodel/wikibase.Reference.js b/lib/resources/wikibase.datamodel/wikibase.Reference.js index cf71051..8d3f34d 100644 --- a/lib/resources/wikibase.datamodel/wikibase.Reference.js +++ b/lib/resources/wikibase.datamodel/wikibase.Reference.js @@ -65,7 +65,37 @@ */ setSnaks: function( snaks ) { this._snaks = new wb.SnakList( snaks ); + }, + + /** + * Will return whether a given reference equals this one. This will compare the reference's + * snaks only and not involve checking the hash. + * + * @param {wb.Reference} reference + * @return {boolean} + */ + equals: function( reference ) { + return ( this._snaks.equals( reference.getSnaks() ) ); + }, + + /** + * Returns a JSON structure representing this reference. + * @since 0.4 + * + * @return {Object} + */ + toJSON: function() { + var json = { + snaks: this._snaks.toJSON() + }; + + if ( this._hash ) { + json.hash = this._hash; + } + + return json; } + }; wb.Reference.newFromJSON = function( json ) { diff --git a/lib/resources/wikibase.datamodel/wikibase.Statement.js b/lib/resources/wikibase.datamodel/wikibase.Statement.js index ff8db7d..9758e64 100644 --- a/lib/resources/wikibase.datamodel/wikibase.Statement.js +++ b/lib/resources/wikibase.datamodel/wikibase.Statement.js @@ -11,7 +11,7 @@ constructor = function( mainSnak, qualifiers, references, rank, guid ) { PARENT.call( this, mainSnak, qualifiers, guid ); this.setReferences( references || [] ); - this.setRank( rank === undefined ? this.RANK.NORMAL : rank ); + this.setRank( rank === undefined ? this.constructor.RANK.NORMAL : rank ); }; /** @@ -23,15 +23,14 @@ * * @param {wb.Snak} mainSnak * @param {wb.Snak[]} [qualifiers] - * @param {Array} [references] An array of arrays of Snaks or empty array + * @param {wb.Reference[]} [references] An array of references or an empty array * @param {Number} [rank] * @param {String|null} [guid] The Global Unique Identifier of this Statement. Can be omitted or null * if this is a new Statement, not yet stored in the database and associated with some entity. */ wb.Statement = wb.utilities.inherit( 'WbStatement', PARENT, constructor, { /** - * @type Array - * @todo determine whether we should rather model a Reference object for this + * @type {wb.Reference[]} * @todo think about implementing a ReferenceList/ClaimList rather than having an Array here */ _references: null, @@ -43,10 +42,10 @@ _rank: null, /** - * Returns all of the statements references. + * Returns all of the statement's references. * * sufficient - * @return {Array} An array of arrays of Snaks or an empty array. + * @return {wb.Reference[]|null} An array of references or an empty array. */ getReferences: function() { return this._references; @@ -55,7 +54,7 @@ /** * Overwrites the current set of the statements references. * - * @param {Array} references An array of arrays of Snaks or an empty array. + * @param {wb.Reference[]} references An array of references or an empty array. */ setReferences: function( references ) { if( !$.isArray( references ) ) { @@ -80,14 +79,85 @@ */ setRank: function( rank ) { // check if given rank is a known rank, then set it. Otherwise, throw error! - for( var i in wb.Statement.RANK ) { - if( wb.Statement.RANK[i] === rank ) { + for( var i in this.constructor.RANK ) { + if( this.constructor.RANK[i] === rank ) { this._rank = rank; return; } } throw new Error( 'Can not set unknown Statement rank "' + rank + '"' ); + }, + + /** + * Returns whether this statement is equal to another statement. + * @see wb.Claim.equals + * @since 0.4 + * + * @param {wb.Statement} statement + * @return {boolean} + */ + equals: function( statement ) { + if ( this === statement ) { + return true; + } else if ( + !( statement instanceof this.constructor ) + || !PARENT.prototype.equals.call( this, statement ) + || this._references.length !== statement.getReferences().length + || this._rank !== statement.getRank() + ) { + return false; + } + + // Check if references are equal: + var equals = true; + $.each( this._references, function( myI, myReference ) { + var found = false; + $.each( statement.getReferences(), function( yourI, yourReference ) { + if ( myReference.equals( yourReference ) ) { + found = true; + return false; + } + } ); + if ( !found ) { + equals = false; + return false; + } + } ); + + return equals; + }, + + /** + * Returns a JSON structure representing this statement. + * @since 0.4 + * + * @return {Object} + */ + toJSON: function() { + var self = this, + json = PARENT.prototype.toJSON.call( this ); + + json.type = this.constructor.TYPE; + + if ( this._references && this._references.length > 0 ) { + json.references = []; + $.each( this._references, function( i, reference ) { + json.references.push( reference.toJSON() ); + } ); + } + + if ( this._rank ) { + $.each( this.constructor.RANK, function ( rank, i ) { + if ( self._rank === i ) { + json.rank = rank.toLowerCase(); + return false; + } + } ); + } + + return json; } + } ); /** @@ -100,4 +170,9 @@ DEPRECATED: 0 }; +/** + * @see wb.Claim.TYPE + */ +wb.Statement.TYPE = 'statement'; + }( wikibase, jQuery ) ); diff --git a/lib/resources/wikibase.store/wikibase.RepoApi.js b/lib/resources/wikibase.store/wikibase.RepoApi.js index 14adcca..550ab11 100644 --- a/lib/resources/wikibase.store/wikibase.RepoApi.js +++ b/lib/resources/wikibase.store/wikibase.RepoApi.js @@ -214,6 +214,21 @@ }, /** + * Creates/Updates an entire claim. + * + * @param {wb.Claim|wb.Statement} claim + * @param {Number} baseRevId + * @return {jQuery.Promise} + */ + setClaim: function( claim, baseRevId ) { + return this.post( { + action: 'wbsetclaim', + claim: claim.toJSON(), + baserevid: baseRevId + } ); + }, + + /** * 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. diff --git a/lib/tests/qunit/wikibase.datamodel/Wikibase.claim.tests.js b/lib/tests/qunit/wikibase.datamodel/Wikibase.claim.tests.js index c390294..beddf2d 100644 --- a/lib/tests/qunit/wikibase.datamodel/Wikibase.claim.tests.js +++ b/lib/tests/qunit/wikibase.datamodel/Wikibase.claim.tests.js @@ -7,12 +7,13 @@ * * @licence GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > + * @author H. Snater < mediaw...@snater.com > */ ( function( wb, dv, $, QUnit ) { 'use strict'; - QUnit.module( 'wikibase.datamodel.claim.js', QUnit.newMwEnvironment() ); + QUnit.module( 'wikibase.datamodel.Claim', QUnit.newWbEnvironment() ); QUnit.test( 'constructor', function( assert ) { var argumentLists = [ @@ -77,4 +78,108 @@ } ); } ); + QUnit.test( 'equals()', function( assert ) { + var claims_equal = { + a: [ + new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ), + new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ) + ], + b: [ + new wb.Claim( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ), + new wb.Claim( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ) + ], + c: [ + new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ), + new wb.Statement( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ) + ] + }, + claims_unequal = { + a: [ + new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( 'other string' ) ) ), + new wb.Claim( new wb.PropertySomeValueSnak( 9001 ) ), + new wb.Claim( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ) + ], + b: [ + new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( 'other string' ) ) ), + new wb.Claim( new wb.PropertySomeValueSnak( 9001 ) ), + new wb.Claim( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 43, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ) + ] + }; + + // Compare equal claims: + $.each( claims_equal, function( key, claims ) { + assert.ok( + claims[0].equals( claims[1] ), + 'Claims "' + key + '" are equal.' + ); + } ); + + // Compare "unequal" references to the "equal" references with the same key: + $.each( claims_unequal, function( key, claims ) { + $.each( claims, function( i, claim ) { + assert.ok( + !claim.equals( claims_equal[key][0] ), + 'Unequal claim "' + key + '[' + i + ']" is recognized being unequal.' + ); + } ) + } ); + } ); + + QUnit.test( 'toJSON()', function( assert ) { + var claim = new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( '~=[,,_,,]:3' ) ) ); + + assert.ok( + claim.equals( wb.Claim.newFromJSON( claim.toJSON() ) ), + 'Exported simple claim to JSON.' + ); + + claim = new wb.Claim( + new wb.PropertyNoValueSnak( 42 ), + new wb.SnakList( + [ + new wb.PropertyNoValueSnak( 9001 ), + new wb.PropertySomeValueSnak( 42 ), + new wb.PropertyValueSnak( 23, new dv.StringValue( '~=[,,_,,]:3' ) ) + ] + ) + ); + + assert.ok( + claim.equals( wb.Claim.newFromJSON( claim.toJSON() ) ), + 'Exported complex claim to JSON.' + ); + } ); + }( wikibase, dataValues, jQuery, QUnit ) ); diff --git a/lib/tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js b/lib/tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js index b7f662a..0f66265 100644 --- a/lib/tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js +++ b/lib/tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js @@ -8,12 +8,13 @@ * @licence GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > * @author Daniel Werner < daniel.wer...@wikimedia.de > + * @author H. Snater < mediaw...@snater.com > */ ( function( wb, dv, $, QUnit, undefined ) { 'use strict'; - QUnit.module( 'wikibase.datamodel.reference.js', QUnit.newMwEnvironment() ); + QUnit.module( 'wikibase.datamodel.Reference', QUnit.newWbEnvironment() ); var snakLists = [ new wb.SnakList( [ @@ -73,4 +74,92 @@ ); } ); + QUnit.test( 'equals()', function( assert ) { + var references_equal = { + a: [ + new wb.Reference(), + new wb.Reference() + ], + b: [ + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ), + 'hash12390213' + ), + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ), + 'hash12390213' + ) + ] + }, + references_unequal = { + a: [ + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ) + ], + b: [ + new wb.Reference(), + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 345, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ) + ] + }; + + // Compare equal references: + $.each( references_equal, function( key, references ) { + assert.ok( + references[0].equals( references[1] ), + 'References "' + key + '" are equal.' + ); + } ); + + // Compare "unequal" references to the "equal" references with the same key: + $.each( references_unequal, function( key, references ) { + $.each( references, function( i, reference ) { + assert.ok( + !reference.equals( references_equal[key][0] ), + 'Unequal reference "' + key + '[' + i + ']" is recognized being unequal.' + ); + } ) + } ); + + } ); + + QUnit.test( 'toJSON()', function( assert ) { + var reference = new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ), + 'hash12390213' + ); + + assert.ok( + reference.equals( wb.Reference.newFromJSON( reference.toJSON() ) ), + 'Exported reference to JSON.' + ); + } ); + }( wikibase, dataValues, jQuery, QUnit ) ); diff --git a/lib/tests/qunit/wikibase.datamodel/wikibase.Statement.tests.js b/lib/tests/qunit/wikibase.datamodel/wikibase.Statement.tests.js new file mode 100644 index 0000000..35a78e7 --- /dev/null +++ b/lib/tests/qunit/wikibase.datamodel/wikibase.Statement.tests.js @@ -0,0 +1,201 @@ +/** + * QUnit tests for wikibase.Statement + * @see https://www.mediawiki.org/wiki/Extension:Wikibase + * + * @since 0.4 + * @ingroup WikibaseLib + * + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + */ + +( function( wb, dv, $, QUnit ) { + 'use strict'; + + QUnit.module( 'wikibase.datamodel.statement', QUnit.newWbEnvironment() ); + + QUnit.test( 'equals()', function( assert ) { + var statements_equal = { + a: [ + new wb.Statement( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ), + new wb.Statement( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ) + ], + b: [ + new wb.Statement( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ), + [ + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 3, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 245 ) + ] + ) + ), + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 856, new dv.StringValue( 'another string' ) ), + new wb.PropertySomeValueSnak( 97 ) + ] + ) + ) + ], + wb.Statement.RANK.PREFERRED + ), + new wb.Statement( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ), + [ + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 3, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 245 ) + ] + ) + ), + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 856, new dv.StringValue( 'another string' ) ), + new wb.PropertySomeValueSnak( 97 ) + ] + ) + ) + ], + wb.Statement.RANK.PREFERRED + ) + ] + }, + statements_unequal = { + a: [ + new wb.Statement( new wb.PropertyValueSnak( 41, new dv.StringValue( 'string' ) ) ), + new wb.Claim( new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ) ), + new wb.Statement( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ) + ], + b: [ + new wb.Statement( new wb.PropertyValueSnak( 41, new dv.StringValue( 'string' ) ) ), + new wb.Statement( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ) + ), + new wb.Statement( + new wb.PropertyValueSnak( 42, new dv.StringValue( 'string' ) ), + new wb.SnakList( + [ + new wb.PropertyValueSnak( 2, new dv.StringValue( 'some string' ) ), + new wb.PropertySomeValueSnak( 9001 ) + ] + ), + [ + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 3, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 245 ) + ] + ) + ), + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 123, new dv.StringValue( 'another string' ) ), + new wb.PropertySomeValueSnak( 97 ) + ] + ) + ) + ], + wb.Statement.RANK.PREFERRED + ) + ] + }; + + // Compare equal statements: + $.each( statements_equal, function( key, statements ) { + assert.ok( + statements[0].equals( statements[1] ), + 'Statements "' + key + '" are equal.' + ); + } ); + + // Compare "unequal" references to the "equal" references with the same key: + $.each( statements_unequal, function( key, statements ) { + $.each( statements, function( i, statement ) { + assert.ok( + !statements_equal[key][0].equals( statement ), + 'Unequal statement "' + key + '[' + i + ']" is recognized being unequal.' + ); + } ) + } ); + } ); + + QUnit.test( 'toJSON', function( assert ) { + var statement = new wb.Statement( new wb.PropertyNoValueSnak( 42 ) ); + + assert.ok( + statement.equals( wb.Claim.newFromJSON( statement.toJSON() ) ), + 'Exported simple statement to JSON.' + ); + + statement = new wb.Statement( + new wb.PropertyValueSnak( 23, new dv.StringValue( '~=[,,_,,]:3' ) ), + new wb.SnakList( + [ + new wb.PropertyNoValueSnak( 9001 ), + new wb.PropertySomeValueSnak( 42 ) + ] + ), + [ + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 3, new dv.StringValue( 'string' ) ), + new wb.PropertySomeValueSnak( 245 ) + ] + ) + ), + new wb.Reference( + new wb.SnakList( + [ + new wb.PropertyValueSnak( 856, new dv.StringValue( 'another string' ) ), + new wb.PropertySomeValueSnak( 97 ) + ] + ) + ) + ], + wb.Statement.RANK.PREFERRED + ); + + assert.ok( + statement.equals( wb.Claim.newFromJSON( statement.toJSON() ) ), + 'Exported complex statement to JSON.' + ); + + } ); + +}( wikibase, dataValues, jQuery, QUnit ) ); -- To view, visit https://gerrit.wikimedia.org/r/53325 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0e1d341549e253bfb411bc61960bbd57ad569c84 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits