mediawiki-extensions-Revisi.../modules/ext.RevisionSlider.Api.js
thiemowmde 3d93003dcc Drop wikitext comment in favor of parsedcomment
The plain wikitext comment is apparently not used for anything,
anywhere. It was for some reason used for an "is empty" check. But
we can do the same with the `parsedcomment`. I checked and an empty
comment doesn't result in something non-empty like `<div></div>`, but
stays as an empty string.

Change-Id: Iedc5898b7b0f82231328ab3e0e46b1461ca845b1
2023-08-25 14:42:32 +02:00

229 lines
5.4 KiB
JavaScript

/**
* @class Api
* @param {string} apiUrl
* @constructor
*/
function Api( apiUrl ) {
this.url = apiUrl;
}
$.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
* @param {string} [options.dir='older'] Sort direction
* @param {number} [options.limit=500] Result limit
* @param {number} [options.startId]
* @param {number} [options.endId]
* @param {Object.<string,string>} [options.knownUserGenders]
* @return {jQuery.promise}
*/
fetchRevisionData: function ( pageName, options ) {
const deferred = $.Deferred(),
self = this;
let userXhr;
options = options || {};
const xhr = this.fetchRevisions( pageName, options )
.done( function ( data ) {
let revs = data.query.pages[ 0 ].revisions;
const revContinue = data.continue,
genderData = options.knownUserGenders || {},
changeTags = options.changeTags;
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
const 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 } );
}
const userNames = self.getUniqueUserNamesWithUnknownGender( revs, genderData );
userXhr = self.fetchUserGenderData( userNames )
.done( function ( data2 ) {
if ( typeof data2 === 'object' &&
data2.query &&
data2.query.users &&
data2.query.users.length > 0
) {
$.extend( genderData, self.getUserGenderData( data2.query.users, genderData ) );
}
revs.forEach( function ( rev ) {
if ( 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]
* @param {string} [options.dir='older'] Sort direction
* @param {number} [options.limit=500] Result limit
* @param {number} [options.startId]
* @param {number} [options.endId]
* @return {jQuery.jqXHR}
*/
fetchRevisions: function ( pageName, options ) {
options = options || {};
const data = {
action: 'query',
prop: 'revisions',
format: 'json',
rvprop: 'ids|timestamp|user|parsedcomment|size|flags|tags',
titles: pageName,
formatversion: 2,
continue: '',
rvlimit: 500,
rvdir: options.dir || 'older'
};
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.<string,string>} knownUserGenders
* @return {string[]}
*/
getUniqueUserNamesWithUnknownGender: function ( revs, knownUserGenders ) {
const allUsers = revs.map( function ( rev ) {
return !( 'anon' in rev ) && rev.user;
} );
return allUsers.filter( function ( name, index ) {
// Anonymous users don't have a name
return name && !( name in knownUserGenders ) &&
// This filters duplicates by rejecting all but the first one
allUsers.indexOf( name ) === index;
} );
},
/**
* @param {Object[]} users
* @return {Object.<string,string>}
*/
getUserGenderData: function ( users ) {
const genderData = {};
users.forEach( function ( user ) {
if ( user.gender && user.gender !== 'unknown' ) {
genderData[ user.name ] = user.gender;
}
} );
return genderData;
},
/**
* @param {Object[]} revs
* @param {Object[]} changeTags
* @return {Object[]}
*/
getRevisionsWithNewTags: function ( revs, changeTags ) {
revs.forEach( function ( rev ) {
rev.tags = rev.tags.map( function ( tag ) {
changeTags.some( function ( changeTag ) {
if ( tag === changeTag.name ) {
tag = changeTag.displayname;
return true;
}
return false;
} );
return tag;
} ).filter( function ( tag ) {
// Remove hidden tags (tags with no displayname)
return tag;
} );
} );
return revs;
}
} );
module.exports = Api;