mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/RevisionSlider
synced 2025-01-06 02:44:33 +00:00
7f38c9c579
In my PHPStorm IDE, this makes it possible to follow all methods and properties in these classes, even these that are later defined. Otherwise only the empty stub of each class is found. This might be different in other IDEs. Basically: PHPStorm does not understand the meaning of the $.extend() syntax from jQuery without these hints. Change-Id: I4aa76db183122f6669dc72561441f46f0056d793
239 lines
5.8 KiB
JavaScript
239 lines
5.8 KiB
JavaScript
( function () {
|
|
/**
|
|
* @param {string} apiUrl
|
|
* @constructor
|
|
*/
|
|
var Api = function ( apiUrl ) {
|
|
this.url = apiUrl;
|
|
};
|
|
|
|
/**
|
|
* @class mw.libs.revisionSlider.Api
|
|
*/
|
|
$.extend( Api.prototype, {
|
|
url: '',
|
|
|
|
/**
|
|
* Fetches change tags
|
|
*
|
|
* @return {jQuery.jqXHR}
|
|
*/
|
|
|
|
fetchAvailableChangeTags: function () {
|
|
return $.ajax( {
|
|
url: this.url,
|
|
data: {
|
|
action: 'query',
|
|
list: 'tags',
|
|
tgprop: 'displayname',
|
|
tglimit: 500,
|
|
format: 'json'
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Fetches a batch of revision data, including a gender setting for users who edited the revision
|
|
*
|
|
* @param {string} pageName
|
|
* @param {Object} options Options
|
|
* @param {string} [options.dir='older'] Sort direction
|
|
* @param {number} [options.limit=500] Result limit
|
|
* @param {number} [options.startId] Start ID
|
|
* @param {number} [options.endId] End ID
|
|
* @param {Object} [options.knownUserGenders] Known user genders
|
|
* @return {jQuery.promise}
|
|
*/
|
|
fetchRevisionData: function ( pageName, options ) {
|
|
var xhr, userXhr,
|
|
deferred = $.Deferred(),
|
|
self = this;
|
|
|
|
options = options || {};
|
|
|
|
xhr = this.fetchRevisions( pageName, options )
|
|
.done( function ( data ) {
|
|
var revs = data.query.pages[ 0 ].revisions,
|
|
revContinue = data.continue,
|
|
genderData = options.knownUserGenders || {},
|
|
changeTags = options.changeTags || [],
|
|
unknown,
|
|
userNames;
|
|
|
|
if ( !revs ) {
|
|
return deferred.reject;
|
|
}
|
|
|
|
if ( changeTags && changeTags.length > 0 ) {
|
|
revs = self.getRevisionsWithNewTags( revs, changeTags );
|
|
}
|
|
|
|
// No need to query any gender data if masculine, feminine, and neutral are all
|
|
// the same anyway
|
|
unknown = mw.msg( 'revisionslider-label-username', 'unknown' );
|
|
if ( mw.msg( 'revisionslider-label-username', 'male' ) === unknown &&
|
|
mw.msg( 'revisionslider-label-username', 'female' ) === unknown
|
|
) {
|
|
return deferred.resolve( { revisions: revs, continue: revContinue } );
|
|
}
|
|
|
|
userNames = self.getUniqueUserNamesWithUnknownGender( revs, genderData );
|
|
|
|
userXhr = self.fetchUserGenderData( userNames )
|
|
.done( function ( data ) {
|
|
if ( typeof data === 'object' &&
|
|
data.query &&
|
|
data.query.users &&
|
|
data.query.users.length > 0
|
|
) {
|
|
$.extend( genderData, self.getUserGenderData( data.query.users, genderData ) );
|
|
}
|
|
|
|
revs.forEach( function ( rev ) {
|
|
if ( 'user' in rev && rev.user in genderData ) {
|
|
rev.userGender = genderData[ rev.user ];
|
|
}
|
|
} );
|
|
|
|
deferred.resolve( { revisions: revs, continue: revContinue } );
|
|
} )
|
|
.fail( deferred.reject );
|
|
} )
|
|
.fail( deferred.reject );
|
|
|
|
return deferred.promise( {
|
|
abort: function () {
|
|
xhr.abort();
|
|
if ( userXhr ) {
|
|
userXhr.abort();
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Fetches up to 500 revisions at a time
|
|
*
|
|
* @param {string} pageName
|
|
* @param {Object} [options] Options
|
|
* @param {string} [options.dir='older'] Sort direction
|
|
* @param {number} [options.limit=500] Result limit
|
|
* @param {number} [options.startId] Start ID
|
|
* @param {number} [options.endId] End ID
|
|
* @return {jQuery.jqXHR}
|
|
*/
|
|
fetchRevisions: function ( pageName, options ) {
|
|
var dir, data;
|
|
|
|
options = options || {};
|
|
dir = 'dir' in options ? options.dir : 'older';
|
|
data = {
|
|
action: 'query',
|
|
prop: 'revisions',
|
|
format: 'json',
|
|
rvprop: 'ids|timestamp|user|comment|parsedcomment|size|flags|tags',
|
|
titles: pageName,
|
|
formatversion: 2,
|
|
continue: '',
|
|
rvlimit: 500,
|
|
rvdir: dir
|
|
};
|
|
|
|
if ( 'startId' in options ) {
|
|
data.rvstartid = options.startId;
|
|
}
|
|
if ( 'endId' in options ) {
|
|
data.rvendid = options.endId;
|
|
}
|
|
if ( 'limit' in options && options.limit <= 500 ) {
|
|
data.rvlimit = options.limit;
|
|
}
|
|
|
|
return $.ajax( {
|
|
url: this.url,
|
|
data: data
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Fetches gender data for maximum 50 user names
|
|
*
|
|
* @param {string[]} users
|
|
* @return {jQuery.jqXHR}
|
|
*/
|
|
fetchUserGenderData: function ( users ) {
|
|
if ( users.length === 0 ) {
|
|
return $.Deferred().resolve();
|
|
}
|
|
return $.ajax( {
|
|
url: this.url,
|
|
data: {
|
|
formatversion: 2,
|
|
action: 'query',
|
|
list: 'users',
|
|
format: 'json',
|
|
usprop: 'gender',
|
|
ususers: users.slice( 0, 50 ).join( '|' )
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* @param {Object[]} revs
|
|
* @param {Object} knownUserGenders
|
|
* @return {string[]}
|
|
*/
|
|
getUniqueUserNamesWithUnknownGender: function ( revs, knownUserGenders ) {
|
|
var allUsers = revs.map( function ( rev ) {
|
|
return 'user' in rev && !( 'anon' in rev ) ? rev.user : '';
|
|
} );
|
|
return allUsers.filter( function ( value, index, array ) {
|
|
return value !== '' && !( value in knownUserGenders ) && array.indexOf( value ) === index;
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* @param {Object[]} data
|
|
* @return {Object}
|
|
*/
|
|
getUserGenderData: function ( data ) {
|
|
var genderData = {},
|
|
usersWithGender = data.filter( function ( item ) {
|
|
return 'gender' in item && item.gender !== 'unknown';
|
|
} );
|
|
usersWithGender.forEach( function ( item ) {
|
|
genderData[ item.name ] = item.gender;
|
|
} );
|
|
return genderData;
|
|
},
|
|
|
|
/**
|
|
* @param {Object[]} revs
|
|
* @param {Object[]} changeTags
|
|
* @return {Object[]}
|
|
*/
|
|
getRevisionsWithNewTags: function ( revs, changeTags ) {
|
|
revs.forEach( function ( rev ) {
|
|
var oldTags = rev.tags,
|
|
newTags = [];
|
|
|
|
if ( oldTags.length > 0 ) {
|
|
oldTags.forEach( function ( tag ) {
|
|
changeTags.forEach( function ( changeTag ) {
|
|
if ( changeTag.name === tag ) {
|
|
tag = changeTag.displayname;
|
|
}
|
|
} );
|
|
newTags.push( tag );
|
|
} );
|
|
rev.tags = newTags;
|
|
}
|
|
} );
|
|
return revs;
|
|
}
|
|
} );
|
|
|
|
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
|
|
mw.libs.revisionSlider.Api = Api;
|
|
}() );
|