Henning Snater has uploaded a new change for review.
https://gerrit.wikimedia.org/r/77862
Change subject: Introduced 'qualifiers-order' parameter in ClaimSerializer
......................................................................
Introduced 'qualifiers-order' parameter in ClaimSerializer
(bug 52391) Since, in the serialized JSON structure, the qualifiers are
encapsulated
in an object indexed by property id, the 'qualifiers-order' parameter specifies
the
order of those property ids.
Change-Id: I6f8399b621dddb6c84082db5fd35286a2ecd438c
---
M .jshintignore
M lib/includes/serializers/ClaimSerializer.php
M lib/resources/wikibase.datamodel/wikibase.Claim.js
M lib/resources/wikibase.datamodel/wikibase.SnakList.js
M lib/tests/phpunit/serializers/ClaimSerializerTest.php
M lib/tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js
M repo/tests/phpunit/includes/api/SetClaimTest.php
7 files changed, 226 insertions(+), 25 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase
refs/changes/62/77862/1
diff --git a/.jshintignore b/.jshintignore
index fa3e01d..efaecd6 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -25,7 +25,6 @@
./lib/tests/qunit/wikibase.datamodel/datamodel.Property.tests.js
./lib/tests/qunit/wikibase.datamodel/Wikibase.claim.tests.js
./lib/tests/qunit/wikibase.datamodel/Wikibase.reference.tests.js
-./lib/tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js
./lib/tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js
./lib/tests/qunit/wikibase.datamodel/wikibase.Statement.tests.js
./lib/tests/qunit/wikibase.RepoApi/wikibase.RepoApiError.tests.js
diff --git a/lib/includes/serializers/ClaimSerializer.php
b/lib/includes/serializers/ClaimSerializer.php
index f041c8e..5a1e01c 100644
--- a/lib/includes/serializers/ClaimSerializer.php
+++ b/lib/includes/serializers/ClaimSerializer.php
@@ -109,6 +109,12 @@
if ( $qualifiers !== array() ) {
$serialization['qualifiers'] = $qualifiers;
+
+ $serialization['qualifiers-order'] = array();
+ foreach( $qualifiers as $propertyId => $snaks ) {
+ $serialization['qualifiers-order'][] =
$propertyId;
+ }
+ $this->setIndexedTagName(
$serialization['qualifiers-order'], 'qualifiers-order' );
}
$serialization['type'] = $claim instanceof Statement ?
'statement' : 'claim';
@@ -181,8 +187,35 @@
$claim->setGuid( $serialization['id'] );
if ( array_key_exists( 'qualifiers', $serialization ) ) {
+ $sortedQualifiers = array();
+
+ if( !array_key_exists( 'qualifiers-order',
$serialization ) ) {
+ $sortedQualifiers =
$serialization['qualifiers'];
+
+ } else {
+ foreach( $serialization['qualifiers-order'] as
$propertyId ) {
+ if( !isset(
$serialization['qualifiers'][$propertyId] ) ) {
+ throw new MWException( 'No
snaks with property id "' . $propertyId . '" '
+ . 'found in
"qualifiers" parameter although specified in '
+ . '"qualifiers-order"'
);
+ }
+
+ $sortedQualifiers[$propertyId] =
$serialization['qualifiers'][$propertyId];
+ }
+
+ $missingProperties = array_diff(
+ array_keys( $sortedQualifiers ),
+ array_keys(
$serialization['qualifiers'] )
+ );
+
+ if( count( $missingProperties ) > 0 ) {
+ throw new MWException( 'Property ids '
. implode( ', ', $missingProperties )
+ . ' have not been specified in
"qualifiers-order"' );
+ }
+ }
+
$snaksUnserializer = new ByPropertyListUnserializer(
$snakUnserializer );
- $snaks = $snaksUnserializer->newFromSerialization(
$serialization['qualifiers'] );
+ $snaks = $snaksUnserializer->newFromSerialization(
$sortedQualifiers );
$claim->setQualifiers( new \Wikibase\SnakList( $snaks )
);
}
diff --git a/lib/resources/wikibase.datamodel/wikibase.Claim.js
b/lib/resources/wikibase.datamodel/wikibase.Claim.js
index 1f0aa75..94b7199 100644
--- a/lib/resources/wikibase.datamodel/wikibase.Claim.js
+++ b/lib/resources/wikibase.datamodel/wikibase.Claim.js
@@ -139,6 +139,7 @@
if ( this._qualifiers ) {
json.qualifiers = this._qualifiers.toJSON();
+ json['qualifiers-order'] =
this._qualifiers.getPropertyOrder();
}
return json;
@@ -162,7 +163,7 @@
isStatement = json.type === 'statement';
if ( json.qualifiers !== undefined ) {
- qualifiers = wb.SnakList.newFromJSON( json.qualifiers );
+ qualifiers = wb.SnakList.newFromJSON( json.qualifiers,
json['qualifiers-order'] );
}
if ( isStatement && json.references !== undefined ) {
diff --git a/lib/resources/wikibase.datamodel/wikibase.SnakList.js
b/lib/resources/wikibase.datamodel/wikibase.SnakList.js
index 6b05b17..97384c1 100644
--- a/lib/resources/wikibase.datamodel/wikibase.SnakList.js
+++ b/lib/resources/wikibase.datamodel/wikibase.SnakList.js
@@ -152,6 +152,22 @@
},
/**
+ * Returns a list of property ids representing the order of the snaks
grouped by property.
+ *
+ * @return {string[]}
+ */
+ getPropertyOrder: function() {
+ var json = this.toJSON(),
+ propertyIds = [];
+
+ $.each( json, function( propertyId, snak ) {
+ propertyIds.push( propertyId );
+ } );
+
+ return propertyIds;
+ },
+
+ /**
* Returns a simple JSON structure representing this Snak. The
structure will be a map, having
* property IDs as keys and an array of the Snak's JSON as values.
*
@@ -190,17 +206,45 @@
/**
* Creates a new Snak Object from a given JSON structure.
*
- * @param {String} json
- * @return wb.Snak|null
+ * @param {string} json
+ * @param {string[]} [order] List of property ids defining the order of the
snaks grouped by
+ * property.
+ * @return {wikibase.SnakList|null}
*/
-SELF.newFromJSON = function( json ) {
+SELF.newFromJSON = function( json, order ) {
var snaksList = new SELF();
- $.each( json, function( propertyId, snaksPerProperty ) {
- $.each( snaksPerProperty, function( i, snakJson ) {
- snaksList.addSnak( wb.Snak.newFromJSON( snakJson ) );
+ if( !order ) {
+ // No order specified: Just loop through the json object:
+ $.each( json, function( propertyId, snaksPerProperty ) {
+ $.each( snaksPerProperty, function( i, snakJson ) {
+ snaksList.addSnak( wb.Snak.newFromJSON(
snakJson ) );
+ } );
} );
- } );
+
+ } else {
+ // Check whether all property ids that are featured by snaks
are specified in the order
+ // list:
+ $.each( json, function( propertyId, snakListJson ) {
+ if( $.inArray( propertyId, order ) === -1 ) {
+ throw new Error( 'Snak featuring the property
id ' + propertyId + ' is not present '
+ + 'within list of property ids defined
for ordering' );
+ }
+ } );
+
+ // Add all snaks grouped by property according to the order
specified via the "order"
+ // parameter:
+ for( var i = 0; i < order.length; i++ ) {
+ if( !json[order[i]] ) {
+ throw new Error( 'Trying to oder by property '
+ order[i] + ' without any snak '
+ + ' featuring this property being
present' );
+ }
+
+ for( var j = 0; j < json[order[i]].length; j++ ) {
+ snaksList.addSnak( wb.Snak.newFromJSON(
json[order[i]][j] ) );
+ }
+ }
+ }
return snaksList;
};
diff --git a/lib/tests/phpunit/serializers/ClaimSerializerTest.php
b/lib/tests/phpunit/serializers/ClaimSerializerTest.php
index c0a18d0..74695cf 100644
--- a/lib/tests/phpunit/serializers/ClaimSerializerTest.php
+++ b/lib/tests/phpunit/serializers/ClaimSerializerTest.php
@@ -1,8 +1,11 @@
<?php
namespace Wikibase\Test;
+
+use Wikibase\Claim;
use Wikibase\Statement;
use Wikibase\Lib\Serializers\ClaimSerializer;
+use Wikibase\Lib\Serializers\SnakSerializer;
/**
* Tests for the Wikibase\ClaimSerializer class.
@@ -34,6 +37,7 @@
*
* @licence GNU GPL v2+
* @author Jeroen De Dauw < [email protected] >
+ * @author H. Snater < [email protected] >
*/
class ClaimSerializerTest extends SerializerBaseTest {
@@ -60,13 +64,13 @@
$id = new \Wikibase\EntityId( \Wikibase\Property::ENTITY_TYPE,
42 );
- $validArgs[] = new \Wikibase\Claim( new
\Wikibase\PropertyNoValueSnak( $id ) );
+ $validArgs[] = new Claim( new \Wikibase\PropertyNoValueSnak(
$id ) );
- $validArgs[] = new \Wikibase\Claim( new
\Wikibase\PropertySomeValueSnak( $id ) );
+ $validArgs[] = new Claim( new \Wikibase\PropertySomeValueSnak(
$id ) );
$validArgs = $this->arrayWrap( $validArgs );
- $claim = new \Wikibase\Claim( new
\Wikibase\PropertyNoValueSnak( $id ) );
+ $claim = new Claim( new \Wikibase\PropertyNoValueSnak( $id ) );
$validArgs[] = array(
$claim,
@@ -80,7 +84,7 @@
),
);
- $statement = new \Wikibase\Statement( new
\Wikibase\PropertyNoValueSnak( $id ) );
+ $statement = new Statement( new \Wikibase\PropertyNoValueSnak(
$id ) );
$validArgs[] = array(
$statement,
@@ -95,6 +99,44 @@
),
);
+ $claim = new Claim(
+ new \Wikibase\PropertyNoValueSnak( $id ),
+ new \Wikibase\SnakList( array(
+ new \Wikibase\PropertyNoValueSnak( $id ),
+ new \Wikibase\PropertySomeValueSnak( $id ),
+ new \Wikibase\PropertyNoValueSnak(
+ new \Wikibase\EntityId(
\Wikibase\Property::ENTITY_TYPE, 1 )
+ ),
+ ) )
+ );
+
+ $snakSerializer = new SnakSerializer();
+
+ $validArgs[] = array(
+ $claim,
+ array(
+ 'id' => $claim->getGuid(),
+ 'mainsnak' => $snakSerializer->getSerialized(
+ new \Wikibase\PropertyNoValueSnak( $id )
+ ),
+ 'qualifiers' => array(
+ 'p42' => array(
+ $snakSerializer->getSerialized(
new \Wikibase\PropertyNoValueSnak( $id ) ),
+ $snakSerializer->getSerialized(
+ new
\Wikibase\PropertySomeValueSnak( $id )
+ ),
+ ),
+ 'p1' => array(
+ $snakSerializer->getSerialized(
new \Wikibase\PropertyNoValueSnak(
+ new \Wikibase\EntityId(
\Wikibase\Property::ENTITY_TYPE, 1 )
+ ) ),
+ ),
+ ),
+ 'qualifiers-order' => array( 'p42', 'p1' ),
+ 'type' => 'claim',
+ ),
+ );
+
return $validArgs;
}
diff --git a/lib/tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js
b/lib/tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js
index f75470a..05da285 100644
--- a/lib/tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js
+++ b/lib/tests/qunit/wikibase.datamodel/Wikibase.SnakList.tests.js
@@ -1,12 +1,10 @@
/**
- * QUnit tests for wikibase.SnakList
- * @see https://www.mediawiki.org/wiki/Extension:Wikibase
- *
* @since 0.4
* @ingroup WikibaseLib
*
* @licence GNU GPL v2+
* @author Daniel Werner < [email protected] >
+ * @author H. Snater < [email protected] >
*/
( function( wb, dv, $, QUnit ) {
@@ -15,10 +13,10 @@
QUnit.module( 'wikibase.datamodel.SnakList.js',
QUnit.newMwEnvironment() );
var snaks = [
- new wb.PropertyNoValueSnak( '9001' ),
- new wb.PropertySomeValueSnak( '42' ),
- new wb.PropertySomeValueSnak( '42' ), // two times 42!
- new wb.PropertyValueSnak( '42', new dv.StringValue(
'~=[,,_,,]:3' ) )
+ new wb.PropertyNoValueSnak( 'p9001' ),
+ new wb.PropertySomeValueSnak( 'p42' ),
+ new wb.PropertySomeValueSnak( 'p42' ), // two times 42!
+ new wb.PropertyValueSnak( 'p42', new dv.StringValue(
'~=[,,_,,]:3' ) )
];
var anotherSnak = new wb.PropertySomeValueSnak( 'p1' ),
anotherSnak2 = new wb.PropertySomeValueSnak( 'p2' );
@@ -72,6 +70,31 @@
);
} );
+ QUnit.test( 'newFromJSON()', function( assert ) {
+ var snakList = new wb.SnakList( snaks ),
+ initialOrder = snakList.getPropertyOrder(),
+ clonedSnakList = wb.SnakList.newFromJSON(
snakList.toJSON() );
+
+ assert.ok(
+ snakList.equals( clonedSnakList ),
+ 'Cloned snak list using the JSON representation.'
+ );
+
+ var reorderedClone = wb.SnakList.newFromJSON(
snakList.toJSON(), ['p42', 'p9001'] ),
+ cloneOrder = reorderedClone.getPropertyOrder();
+
+ assert.ok(
+ snakList.equals( reorderedClone ),
+ 'Cloned snak list with applying a different property
order.'
+ );
+
+ assert.ok(
+ initialOrder[0] === cloneOrder[1] && initialOrder[1]
=== cloneOrder[0],
+ 'Verified differing property order.'
+ );
+
+ } );
+
QUnit.test( 'SnakList list operations', function( assert ) {
var newSnakList = new wb.SnakList( snaks ),
initialLength = newSnakList.length;
@@ -92,6 +115,12 @@
'New Snak list does not recognize another Snak, not in
the list as one of its own'
);
+ assert.deepEqual(
+ newSnakList.getPropertyOrder(),
+ ['p9001', 'p42'],
+ 'Verified property order.'
+ );
+
assert.ok(
newSnakList.addSnak( anotherSnak ) &&
newSnakList.length === initialLength + 1,
'Another snak added, length attribute increased by one'
@@ -100,6 +129,12 @@
assert.ok(
newSnakList.hasSnak( anotherSnak ),
'Newly added Snak recognized as one of the list\'s own
Snaks now'
+ );
+
+ assert.deepEqual(
+ newSnakList.getPropertyOrder(),
+ ['p9001', 'p42', 'p1'],
+ 'Verified property order.'
);
var clonedSnak = wb.Snak.newFromJSON( anotherSnak.toJSON() );
@@ -123,6 +158,12 @@
newSnakList.removeSnak( clonedSnak ) &&
newSnakList.length === initialLength + 1,
'Newly added Snak removed again (identified by cloned
Snak, so we test for non === ' +
'case; list length decreased by one'
+ );
+
+ assert.deepEqual(
+ newSnakList.getPropertyOrder(),
+ ['p9001', 'p42', 'p2'],
+ 'Verified property order.'
);
var i = 0;
@@ -153,7 +194,7 @@
assert.throws(
function() {
- newSnakList.addSnak( 'foo' )
+ newSnakList.addSnak( 'foo' );
},
'Can not add some strange thing to the Snak list'
);
diff --git a/repo/tests/phpunit/includes/api/SetClaimTest.php
b/repo/tests/phpunit/includes/api/SetClaimTest.php
index 1bd2a4d..5ff3b02 100644
--- a/repo/tests/phpunit/includes/api/SetClaimTest.php
+++ b/repo/tests/phpunit/includes/api/SetClaimTest.php
@@ -105,6 +105,12 @@
$statement->getReferences()->addReference( new
\Wikibase\Reference( $snaks ) );
$statements[] = $statement;
+ $statement = clone $statement;
+ $snaks = new \Wikibase\SnakList( $this->snakProvider() );
+ $statement->setQualifiers( $snaks );
+ $statement->getReferences()->addReference( new
\Wikibase\Reference( $snaks ) );
+ $statements[] = $statement;
+
$ranks = array(
\Wikibase\Statement::RANK_DEPRECATED,
\Wikibase\Statement::RANK_NORMAL,
@@ -135,6 +141,19 @@
// Addition request
$this->makeRequest( $claim, $item->getId(), 1 );
+ // Reorder qualifiers:
+ if( count( $claim->getQualifiers() ) > 0 ) {
+ // Simply reorder the qualifiers by putting the
first qualifier to the end. This is
+ // supposed to be done in the serialized
representation since changing the actual
+ // object might apply intrinsic sorting.
+ $serializerFactory = new
\Wikibase\Lib\Serializers\SerializerFactory();
+ $serializer =
$serializerFactory->newSerializerForObject( $claim );
+ $serializedClaim = $serializer->getSerialized(
$claim );
+ $firstPropertyId = array_shift(
$serializedClaim['qualifiers-order'] );
+ array_push(
$serializedClaim['qualifiers-order'], $firstPropertyId );
+ $this->makeRequest( $serializedClaim,
$item->getId(), 1 );
+ }
+
$claim = new \Wikibase\Statement( new
\Wikibase\PropertyNoValueSnak( 9001 ) );
$claim->setGuid( $guid );
@@ -143,13 +162,26 @@
}
}
- protected function makeRequest( Claim $claim, \Wikibase\EntityId
$entityId, $claimCount ) {
+ /**
+ * @param \Wikibase\Claim|array $claim Native or serialized claim
object.
+ * @param EntityId $entityId
+ * @param $claimCount
+ */
+ protected function makeRequest( $claim, \Wikibase\EntityId $entityId,
$claimCount ) {
$serializerFactory = new
\Wikibase\Lib\Serializers\SerializerFactory();
- $serializer = $serializerFactory->newSerializerForObject(
$claim );
+
+ if( is_a( $claim, '\Wikibase\Claim' ) ) {
+ $serializer =
$serializerFactory->newSerializerForObject( $claim );
+ $serializedClaim = $serializer->getSerialized( $claim );
+ } else {
+ $serializer =
$serializerFactory->newUnserializerForClass( 'Wikibase\Claim' );
+ $serializedClaim = $claim;
+ $claim = $serializer->newFromSerialization(
$serializedClaim );
+ }
$params = array(
'action' => 'wbsetclaim',
- 'claim' => \FormatJson::encode(
$serializer->getSerialized( $claim ) ),
+ 'claim' => \FormatJson::encode( $serializedClaim ),
'token' => $GLOBALS['wgUser']->getEditToken()
);
@@ -163,6 +195,11 @@
$this->assertTrue( $claims->hasClaim( $claim ) );
+ $savedClaim = $claims->getClaimWithGuid( $claim->getGuid() );
+ if( count( $claim->getQualifiers() ) ) {
+ $this->assertArrayEquals(
$claim->getQualifiers()->toArray(), $savedClaim->getQualifiers()->toArray(),
true );
+ }
+
$this->assertEquals( $claimCount, $claims->count() );
}
@@ -173,6 +210,10 @@
$this->assertArrayHasKey( 'pageinfo', $resultArray, 'top level
element has a pageinfo key' );
$this->assertArrayHasKey( 'claim', $resultArray, 'top level
element has a statement key' );
+ if( isset( $resultArray['claim']['qualifiers'] ) ) {
+ $this->assertArrayHasKey( 'qualifiers-order',
$resultArray['claim'], '"qualifiers-order" key is set when returning
qualifiers' );
+ }
+
return $resultArray;
}
--
To view, visit https://gerrit.wikimedia.org/r/77862
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6f8399b621dddb6c84082db5fd35286a2ecd438c
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Henning Snater <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits