MediaWiki:Gadget-morebits.js: Difference between revisions

Repo at 53b6bf4: convert to use Morebits.wiki.page.undeletePage; Add undeletePage to morebits.wiki.page; Remove string trimming shims
imported>Amorymeltzer
(Repo at 79b422a: Protection error needn't be full protection)
(Repo at 53b6bf4: convert to use Morebits.wiki.page.undeletePage; Add undeletePage to morebits.wiki.page; Remove string trimming shims)
Line 1,020:
* **************** String; Morebits.string ****************
*/
 
if (!String.prototype.trimLeft) {
String.prototype.trimLeft = function stringPrototypeLtrim( ) {
return this.replace( /^[\s]+/g, "" );
};
}
 
if (!String.prototype.trimRight) {
String.prototype.trimRight = function stringPrototypeRtrim( ) {
return this.replace( /[\s]+$/g, "" );
};
}
 
if (!String.prototype.trim) {
String.prototype.trim = function stringPrototypeTrim( ) {
return this.trimRight().trimLeft();
};
}
 
Morebits.string = {
Line 1,108 ⟶ 1,090:
*/
formatReasonText: function( str ) {
var result = str.toString().trimRighttrim();
var unbinder = new Morebits.unbinder(result);
unbinder.unbind("<no" + "wiki>", "</no" + "wiki>");
Line 1,641 ⟶ 1,623:
*
* save([onSuccess], [onFailure]): Saves the text set via setPageText() for the page.
* Must be preceded by calling load().
* Warning: Calling save() can result in additional calls to the previous load() callbacks to
* recover from edit conflicts!
Line 1,656 ⟶ 1,638:
*
* deletePage(onSuccess, [onFailure]): Deletes a page (for admins only)
*
* undeletePage(onSuccess, [onFailure]): Undeletes a page (for admins only)
*
* protect(onSuccess, [onFailure]): Protects a page
Line 1,801 ⟶ 1,785:
onDeleteSuccess: null,
onDeleteFailure: null,
onUndeleteSuccess: null,
onUndeleteFailure: null,
onProtectSuccess: null,
onProtectFailure: null,
Line 1,815 ⟶ 1,801:
deleteApi: null,
deleteProcessApi: null,
undeleteApi: null,
undeleteProcessApi: null,
protectApi: null,
protectProcessApi: null,
Line 2,422 ⟶ 2,410:
ctx.deleteApi.setParent(this);
ctx.deleteApi.post();
}
};
 
/**
* Undeletes a page (for admins only)
* @param {Function} onSuccess - callback function to run on success
* @param {Function} [onFailure] - callback function to run on failure (optional)
*/
this.undeletePage = function(onSuccess, onFailure) {
ctx.onUndeleteSuccess = onSuccess;
ctx.onUndeleteFailure = onFailure || emptyFunction;
 
// if a non-admin tries to do this, don't bother
if (!Morebits.userIsInGroup('sysop')) {
ctx.statusElement.error("Cannot undelete page: only admins can do that");
ctx.onUndeleteFailure(this);
return;
}
if (!ctx.editSummary) {
ctx.statusElement.error("Internal error: undelete reason not set before undelete (use setEditSummary function)!");
ctx.onUndeleteFailure(this);
return;
}
 
if (fnCanUseMwUserToken('undelete')) {
fnProcessUndelete.call(this, this);
} else {
var query = {
action: 'query',
prop: 'info',
inprop: 'protection',
intoken: 'undelete',
titles: ctx.pageName
};
 
ctx.undeleteApi = new Morebits.wiki.api("retrieving undelete token...", query, fnProcessUndelete, ctx.statusElement, ctx.onUndeleteFailure);
ctx.undeleteApi.setParent(this);
ctx.undeleteApi.post();
}
};
Line 2,898 ⟶ 2,924:
// check for "Database query error"
if ( errorCode === "internal_api_error_DBQueryError" && ctx.retries++ < ctx.maxRetries ) {
 
ctx.statusElement.info("Database query error, retrying");
--Morebits.wiki.numberOfActionsLeft; // allow for normal completion if retry succeeds
ctx.deleteProcessApi.post(); // give it another go!
 
} else if ( errorCode === "badtoken" ) {
// this is pathetic, but given the current state of Morebits.wiki.page it would
Line 2,910 ⟶ 2,934:
ctx.onDeleteFailure.call(this, this, ctx.deleteProcessApi);
}
 
} else if ( errorCode === "missingtitle" ) {
 
ctx.statusElement.error("Cannot delete the page, because it no longer exists");
if (ctx.onDeleteFailure) {
ctx.onDeleteFailure.call(this, ctx.deleteProcessApi); // invoke callback
}
 
// hard error, give up
} else {
 
ctx.statusElement.error( "Failed to delete the page: " + ctx.deleteProcessApi.getErrorText() );
if (ctx.onDeleteFailure) {
ctx.onDeleteFailure.call(this, ctx.deleteProcessApi); // invoke callback
}
}
};
 
var fnProcessUndelete = function() {
var pageTitle, token;
 
// The whole handling of tokens in Morebits is outdated (#615)
// but has generally worked since intoken has been deprecated
// but remains. intoken does not, however, take undelete, so
// fnCanUseMwUserToken('undelete') is no good. Everything
// except watching and patrolling should eventually use csrf,
// but until then (#615) the stupid hack below should work for
// undeletion.
if (fnCanUseMwUserToken('undelete')) {
token = mw.user.tokens.get('editToken');
pageTitle = ctx.pageName;
} else {
var xml = ctx.undeleteApi.getXML();
 
if ($(xml).find('page').attr('missing') !== "") {
ctx.statusElement.error("Cannot undelete the page, because it already exists");
ctx.onUndeleteFailure(this);
return;
}
 
// extract protection info
var editprot = $(xml).find('pr[type="create"]');
if (editprot.length > 0 && editprot.attr('level') === 'sysop' && !ctx.suppressProtectWarning &&
!confirm('You are about to undelete the fully create protected page "' + ctx.pageName +
(editprot.attr('expiry') === 'infinity' ? '" (protected indefinitely)' : ('" (protection expiring ' + editprot.attr('expiry') + ')')) +
'. \n\nClick OK to proceed with the undeletion, or Cancel to skip this undeletion.')) {
ctx.statusElement.error("Undeletion of fully create protected page was aborted.");
ctx.onUndeleteFailure(this);
return;
}
 
// KLUDGE:
token = mw.user.tokens.get('editToken');
pageTitle = ctx.pageName;
}
 
var query = {
'action': 'undelete',
'title': pageTitle,
'token': token,
'reason': ctx.editSummary
};
if (ctx.watchlistOption === 'watch') {
query.watch = 'true';
}
 
ctx.undeleteProcessApi = new Morebits.wiki.api("undeleting page...", query, ctx.onUndeleteSuccess, ctx.statusElement, fnProcessUndeleteError);
ctx.undeleteProcessApi.setParent(this);
ctx.undeleteProcessApi.post();
};
 
// callback from undeleteProcessApi.post()
var fnProcessUndeleteError = function() {
 
var errorCode = ctx.undeleteProcessApi.getErrorCode();
 
// check for "Database query error"
if ( errorCode === "internal_api_error_DBQueryError" && ctx.retries++ < ctx.maxRetries ) {
ctx.statusElement.info("Database query error, retrying");
--Morebits.wiki.numberOfActionsLeft; // allow for normal completion if retry succeeds
ctx.undeleteProcessApi.post(); // give it another go!
} else if ( errorCode === "badtoken" ) {
// this is pathetic, but given the current state of Morebits.wiki.page it would
// be a dog's breakfast to try and fix this
ctx.statusElement.error("Invalid token. Please refresh the page and try again.");
if (ctx.onUndeleteFailure) {
ctx.onUndeleteFailure.call(this, this, ctx.undeleteProcessApi);
}
} else if ( errorCode === "cantundelete" ) {
ctx.statusElement.error("Cannot undelete the page, either because there are no revisions to undelete or because it has already been undeleted");
if (ctx.onUndeleteFailure) {
ctx.onUndeleteFailure.call(this, ctx.undeleteProcessApi); // invoke callback
}
// hard error, give up
} else {
ctx.statusElement.error( "Failed to undelete the page: " + ctx.undeleteProcessApi.getErrorText() );
if (ctx.onUndeleteFailure) {
ctx.onUndeleteFailure.call(this, ctx.undeleteProcessApi); // invoke callback
}
}
Line 3,723 ⟶ 3,827:
*
* There are sample batchOperation implementations using Morebits.wiki.page in
* twinklebatchdelete.js, and using Morebitstwinklebatchundelete.wiki.apijs, inand twinklebatchundeletetwinklebatchprotect.js.
*/
 
Anonymous user