Skip to content

Instantly share code, notes, and snippets.

@jdlrobson
Created December 18, 2014 23:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdlrobson/7af95ce2c09e49634c23 to your computer and use it in GitHub Desktop.
Save jdlrobson/7af95ce2c09e49634c23 to your computer and use it in GitHub Desktop.
WikiDataApiTest
( function ( M, $ ) {
var api = M.require( 'api' ),
Api = api.Api,
WikiDataApi;
/**
* Gets claims and labels from the WikiData API
* @class WikiDataApi
* @extends Api
*/
WikiDataApi = Api.extend( {
apiUrl: 'https://www.wikidata.org/w/api.php',
useJsonp: true,
language: mw.config.get( 'wgUserLanguage' ),
// Avoids loading token from cache.
getCentralAuthToken: function( type ) {
var data = {
action: 'tokens',
type: 'centralauth'
};
return api.get( data ).then( function( resp ) {
return resp.tokens.centralauthtoken;
} );
},
getToken: function( type, centralAuthToken ) {
var data = {
action: 'tokens',
origin: this.getOrigin(),
centralauthtoken: centralAuthToken,
type: type
};
return this.get( data ).then( function( resp ) {
return resp.tokens[type + 'token'].replace( '+\\', '' );
} );
},
// FIXME: Remove this when dev finished.
ajax: function ( data, options ) {
var key, request, self = this;
options = options || {};
if ( this.useJsonp ) {
options.url = this.apiUrl;
// new line
if ( data.action !== 'tokens' ) {
options.dataType = 'jsonp';
}
}
if ( typeof data !== 'string' ) {
for ( key in data ) {
if ( data[key] === false ) {
delete data[key];
} else if ( $.isArray( data[key] ) ) {
data[key] = data[key].join( '|' );
}
}
}
// FIXME: move to mw.Api (although no EventEmitter in core)?
options.xhr = function () {
var xhr = $.ajaxSettings.xhr();
if ( xhr.upload && ( mw.config.get( 'wgMFAjaxUploadProgressSupport' ) ) ) {
// need to bind this event before we open the connection (see note at
// https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress)
xhr.upload.addEventListener( 'progress', function ( ev ) {
if ( ev.lengthComputable ) {
self.emit( 'progress', request, ev.loaded / ev.total );
}
} );
}
return xhr;
};
request = mw.Api.prototype.ajax.call( this, data, options );
this.requests.push( request );
return request;
},
post: function( data ) {
var self = this,
d = $.Deferred();
// first let's sort out the token
self.getCentralAuthToken().done( function ( centralAuthTokenOne ) {
self.getToken( 'edit', centralAuthTokenOne ).done( function ( editToken ) {
self.getCentralAuthToken().done( function ( centralAuthTokenTwo ) {
data.format = 'json';
data.centralauthtoken = centralAuthTokenTwo;
data.token = editToken;
data.origin = self.getOrigin();
$.post( self.apiUrl, data ).done( function ( resp ) {
d.resolve( resp );
} );
} );
} )
} );
return d;
},
initialize: function ( options ) {
this.subjectId = options.itemId;
Api.prototype.initialize.apply( this, arguments );
},
getClaims: function () {
var self = this,
id = this.subjectId;
return this.ajax( {
action: 'wbgetentities',
ids: id,
languages: this.language,
props: [ 'descriptions', 'claims' ],
format: 'json'
} ).then( function ( data ) {
var description, instanceClaims, entityClaims, instanceOf,
claims = {};
// See if the page has any 'instance of' claims.
if (
data.entities !== undefined &&
data.entities[id].claims !== undefined &&
data.entities[id].claims.P31 !== undefined
) {
entityClaims = data.entities[id].claims;
instanceClaims = entityClaims.P31;
// Examine claims closely
$.each( instanceClaims, function ( i, claim ) {
instanceOf = claim.mainsnak.datavalue.value['numeric-id'];
if ( instanceOf === 5 ) {
claims.isHuman = true;
} else if ( instanceOf === 515 ) {
claims.isCity = true;
} else if ( instanceOf === 6256 ) {
claims.isCountry = true;
} else if ( instanceOf === 16521 ) {
claims.isTaxon = true;
} else if ( instanceOf === 11424 ) {
claims.isMovie = true;
} else if ( instanceOf === 5398426 ) {
claims.isTVSeries = true;
}
// Note: bands are subclassed as rock band, punk band etc.. not sure how we want
// to include them here.
} );
// set some claims
claims.hasOccupation = entityClaims.P106 ? true : false;
claims.hasCountryOfCitizenship = entityClaims.P27 ? true : false;
claims.hasDateOfBirth = entityClaims.P569 ? true : false;
claims.hasDateOfDeath = entityClaims.P570 ? true : false;
claims.entities = entityClaims;
description = data.entities[ id ];
if ( description && description.descriptions !== undefined ) {
if ( description.descriptions[ self.language ] ) {
claims.description = description.descriptions[ self.language ].value;
}
}
return claims;
} else {
// FIXME: logError does not exist
// self.logError( 'no-impression-cannot-fetch-claims' );
return false;
}
} ).fail( function () {
// FIXME: logError does not exist
// self.logError( 'no-impression-cannot-fetch-claims' );
} );
},
/**
* Get labels for an item from Wikidata
* See: https://www.wikidata.org/wiki/Help:Label
*
* @param {Array} itemIds for items in Wikidata
* @return {jQuery.Deferred} Object returned by ajax call
*/
getLabels: function ( itemIds ) {
var lang = this.language;
return this.ajax( {
action: 'wbgetentities',
props: 'labels',
languages: lang,
ids: itemIds
} ).then( function ( data ) {
var map = {};
$.each( itemIds, function ( i, itemId ) {
if ( data.entities[ itemId ].labels &&
data.entities[ itemId ].labels[ lang ] !== undefined
) {
map[ itemId ] = data.entities[ itemId ].labels[ lang ].value;
} else {
map[ itemId ] = null;
}
} );
return map;
} );
},
/**
* Store description.
*
* @param {string} value of new description
* @return {jQuery.Deferred} Object returned by ajax call
*/
saveDescription: function ( value ) {
var self = this,
d = $.Deferred();
this.getInfo().done( function ( info ) {
self.post( {
action: 'wbsetdescription',
id: this.subjectId,
value: value,
language: self.language,
baserevid: info.lastrevid,
bot: 1
} ).done( function ( resp ) {
d.resolve( resp );
} );
} );
return d;
},
/**
* Get information about current wikidata entity
*
* FIXME: add error handling.
* @inheritdoc
*/
getInfo: function () {
var id = this.subjectId;
return this.get( {
action: 'wbgetentities',
ids: id,
props: 'info'
} ).then( function ( resp ) {
return resp.entities[id];
} );
},
/**
* Expand item ids to find associated data such as labels and urls
* for the wikidata entities for the current sitename.
*
* @param {Array} itemIds for items in Wikidata
* @return {jQuery.Deferred} Object returned by ajax call
*/
getExpandedItemsData: function ( itemIds ) {
var lang = this.language,
wiki = mw.config.get( 'wgDBname' ) || 'enwiki';
return this.ajax( {
action: 'wbgetentities',
sites: wiki,
props: [ 'labels', 'sitelinks/urls' ],
languages: lang,
ids: itemIds
} ).then( function ( data ) {
var map = {};
$.each( itemIds, function ( i, itemId ) {
var item, sitelink;
if ( data.entities[ itemId ].labels &&
data.entities[ itemId ].labels[ lang ] !== undefined
) {
item = data.entities[ itemId ];
if ( item.sitelinks && item.sitelinks[wiki] ) {
sitelink = item.sitelinks[wiki];
}
map[ itemId ] = {
label: sitelink ? sitelink.title : item.labels[ lang ].value
};
if ( sitelink && sitelink.url ) {
map[ itemId ].url = sitelink.url;
}
} else {
map[ itemId ] = null;
}
} );
return map;
} );
}
} );
M.define( 'modules/wikigrok/WikiDataApi', WikiDataApi );
var w = new WikiDataApi( { itemId: 'Q2323140' } );
w.saveDescription( 'test' );
}( mw.mobileFrontend, jQuery ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment