No edit summary |
No edit summary |
||
Line 29: | Line 29: | ||
showLoadingDialog(windowManager, function (loadingDialog, updateLoadingText) { | showLoadingDialog(windowManager, function (loadingDialog, updateLoadingText) { | ||
executeAllActions(pageTitle, decisions, function () { | executeAllActions(pageTitle, decisions, function () { | ||
loadingDialog.close() | loadingDialog.close().closed.then(function() { | ||
location.reload(); | |||
}); | |||
}, updateLoadingText); | }, updateLoadingText); | ||
}); | }); | ||
Line 84: | Line 85: | ||
var choice = dialog.radioSelect.findSelectedItem(); | var choice = dialog.radioSelect.findSelectedItem(); | ||
if (choice && choice.data === 'change') { | if (choice && choice.data === 'change') { | ||
dialog.close().then(function () { | dialog.close().closed.then(function () { | ||
askForNewTarget(pageTitle, decisions, windowManager, callback); | askForNewTarget(pageTitle, decisions, windowManager, callback); | ||
}); | }); | ||
} else { | } else { | ||
decisions.links = ''; | decisions.links = ''; | ||
dialog.close().then(function () { | dialog.close().closed.then(function () { | ||
callback(); | callback(); | ||
}); | }); | ||
} | } | ||
} else if (action === 'cancel') { | } else if (action === 'cancel') { | ||
dialog.close().then(function () { | dialog.close().closed.then(function () { | ||
windowManager.destroy(); | windowManager.destroy(); | ||
}); | }); | ||
Line 150: | Line 151: | ||
if (action === 'continue') { | if (action === 'continue') { | ||
decisions.links = dialog.input.getValue(); | decisions.links = dialog.input.getValue(); | ||
dialog.close().then(function () { | dialog.close().closed.then(function () { | ||
callback(); | callback(); | ||
}); | }); | ||
} else if (action === 'cancel') { | } else if (action === 'cancel') { | ||
dialog.close().then(function () { | dialog.close().closed.then(function () { | ||
windowManager.destroy(); | windowManager.destroy(); | ||
}); | }); | ||
Line 219: | Line 220: | ||
callback(dialog, function (text) { | callback(dialog, function (text) { | ||
dialog.loadingLabel.setLabel(text); | dialog.loadingLabel.setLabel(text); | ||
console.log(text); // Log progress | |||
}); | }); | ||
}); | }); | ||
Line 238: | Line 240: | ||
var promises = data.query.backlinks.map(function (link) { | var promises = data.query.backlinks.map(function (link) { | ||
return new Promise(function (resolve) { | return new Promise(function (resolve) { | ||
if (action === 'update') { | |||
updateLink(link.title, newTarget, api).then(resolve); | |||
} else { | } else { | ||
resolve | removeLink(link.title, api).then(resolve); | ||
} | } | ||
}); | }); | ||
Line 273: | Line 265: | ||
action: 'edit', | action: 'edit', | ||
title: pageTitle, | title: pageTitle, | ||
text: | text: '#REDIRECT [[' + newTarget + ']]', | ||
summary: 'Updated redirect to new target [[' + newTarget + ']]' | |||
summary: 'Updated | |||
}).fail(function (error) { | }).fail(function (error) { | ||
console.error('Error updating link:', error); | console.error('Error updating link:', error); | ||
Line 286: | Line 276: | ||
action: 'edit', | action: 'edit', | ||
title: pageTitle, | title: pageTitle, | ||
text: | text: '', | ||
summary: 'Removed link to [[' + pageTitle + ']]' | summary: 'Removed link to [[' + pageTitle + ']]' | ||
}).fail(function (error) { | }).fail(function (error) { | ||
console.error('Error removing link:', error); | console.error('Error removing link:', error); | ||
}); | }); | ||
} | } |
Revision as of 22:54, 7 July 2024
// ==UserScript==
// @name MediaWiki Clean Delete
// @namespace MediaWikiScripts
// @description Adds a 'Clean Delete' action link to pages for admins to delete pages and clean up incoming links and redirects.
// ==/UserScript==
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
function addCleanDeleteLink() {
if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
if ($('#ca-cleandelete').length === 0) {
var $link = $('<div>').attr('id', 'ca-cleandelete').attr('class', 'mw-list-item').append(
$('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
e.preventDefault();
gatherAllDecisions(mw.config.get('wgPageName'));
})
);
$('#p-actions .tab-group').append($link);
}
}
}
function gatherAllDecisions(pageTitle) {
var decisions = {};
var windowManager = new OO.ui.WindowManager();
$('body').append(windowManager.$element);
askForLinkHandling(pageTitle, decisions, windowManager, function () {
confirmDeletion(pageTitle, decisions, windowManager, function () {
showLoadingDialog(windowManager, function (loadingDialog, updateLoadingText) {
executeAllActions(pageTitle, decisions, function () {
loadingDialog.close().closed.then(function() {
location.reload();
});
}, updateLoadingText);
});
});
});
}
function askForLinkHandling(pageTitle, decisions, windowManager, callback) {
function LinkHandlingDialog(config) {
LinkHandlingDialog.super.call(this, config);
}
OO.inheritClass(LinkHandlingDialog, OO.ui.ProcessDialog);
LinkHandlingDialog.static.name = 'linkHandlingDialog';
LinkHandlingDialog.static.title = 'Handle Links and Redirects';
LinkHandlingDialog.static.actions = [
{ action: 'continue', label: 'Continue', flags: ['primary', 'progressive'] },
{ action: 'cancel', label: 'Cancel', flags: ['safe', 'close'] }
];
LinkHandlingDialog.prototype.initialize = function () {
LinkHandlingDialog.super.prototype.initialize.apply(this, arguments);
this.radioSelect = new OO.ui.RadioSelectWidget({
items: [
new OO.ui.RadioOptionWidget({ data: 'delete', label: 'Delete Links and Redirects' }),
new OO.ui.RadioOptionWidget({ data: 'change', label: 'Change Target of Links and Redirects' })
]
});
var fieldset = new OO.ui.FieldsetLayout({
items: [
new OO.ui.FieldLayout(this.radioSelect, {
label: 'Specify how you would like to handle all incoming links and redirects:',
align: 'top'
})
]
});
this.content = new OO.ui.PanelLayout({
padded: true,
expanded: false
});
this.content.$element.append(fieldset.$element);
this.$body.append(this.content.$element);
};
LinkHandlingDialog.prototype.getActionProcess = function (action) {
var dialog = this;
var process = new OO.ui.Process(function () {
if (action === 'continue') {
var choice = dialog.radioSelect.findSelectedItem();
if (choice && choice.data === 'change') {
dialog.close().closed.then(function () {
askForNewTarget(pageTitle, decisions, windowManager, callback);
});
} else {
decisions.links = '';
dialog.close().closed.then(function () {
callback();
});
}
} else if (action === 'cancel') {
dialog.close().closed.then(function () {
windowManager.destroy();
});
}
});
return process;
};
windowManager.addWindows([new LinkHandlingDialog()]);
windowManager.openWindow('linkHandlingDialog');
}
function askForNewTarget(pageTitle, decisions, windowManager, callback) {
function NewTargetDialog(config) {
NewTargetDialog.super.call(this, config);
}
OO.inheritClass(NewTargetDialog, OO.ui.ProcessDialog);
NewTargetDialog.static.name = 'newTargetDialog';
NewTargetDialog.static.title = 'Specify New Target';
NewTargetDialog.static.actions = [
{ action: 'continue', label: 'Continue', flags: ['primary', 'progressive'] },
{ action: 'cancel', label: 'Cancel', flags: ['safe', 'close'] }
];
NewTargetDialog.prototype.initialize = function () {
NewTargetDialog.super.prototype.initialize.apply(this, arguments);
this.input = new OO.ui.TextInputWidget({
value: '',
placeholder: 'Enter new target'
});
var fieldset = new OO.ui.FieldsetLayout({
items: [
new OO.ui.FieldLayout(this.input, {
label: 'Enter the new target page name to update all links and redirects:',
align: 'top'
})
]
});
this.content = new OO.ui.PanelLayout({
padded: true,
expanded: false
});
this.content.$element.append(fieldset.$element);
this.$body.append(this.content.$element);
};
NewTargetDialog.prototype.getActionProcess = function (action) {
var dialog = this;
var process = new OO.ui.Process(function () {
if (action === 'continue') {
decisions.links = dialog.input.getValue();
dialog.close().closed.then(function () {
callback();
});
} else if (action === 'cancel') {
dialog.close().closed.then(function () {
windowManager.destroy();
});
}
});
return process;
};
windowManager.addWindows([new NewTargetDialog()]);
windowManager.openWindow('newTargetDialog');
}
function confirmDeletion(pageTitle, decisions, windowManager, callback) {
var dialog = new OO.ui.MessageDialog();
windowManager.addWindows([dialog]);
windowManager.openWindow(dialog, {
title: 'Confirm Page Deletion',
message: 'Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?',
actions: [
{ label: 'Confirm Deletion', action: 'confirm', flags: ['primary', 'destructive'] },
{ label: 'Cancel', action: 'cancel' }
]
}).closed.then(function (data) {
if (data.action === 'confirm') {
decisions.deletion = true;
callback();
} else {
windowManager.destroy();
}
});
}
function showLoadingDialog(windowManager, callback) {
function LoadingDialog(config) {
LoadingDialog.super.call(this, config);
}
OO.inheritClass(LoadingDialog, OO.ui.ProcessDialog);
LoadingDialog.static.name = 'loadingDialog';
LoadingDialog.static.title = 'Performing Cleanup';
LoadingDialog.prototype.initialize = function () {
LoadingDialog.super.prototype.initialize.apply(this, arguments);
this.loadingLabel = new OO.ui.LabelWidget({ label: 'Starting...' });
this.content = new OO.ui.PanelLayout({
padded: true,
expanded: false
});
this.content.$element.append(this.loadingLabel.$element);
this.$body.append(this.content.$element);
};
LoadingDialog.prototype.getActionProcess = function (action) {
return new OO.ui.Process();
};
windowManager.addWindows([new LoadingDialog()]);
windowManager.openWindow('loadingDialog').then(function (opened) {
opened.then(function (dialog) {
callback(dialog, function (text) {
dialog.loadingLabel.setLabel(text);
console.log(text); // Log progress
});
});
});
}
function executeAllActions(pageTitle, decisions, callback, updateLoadingText) {
var api = new mw.Api();
function handleLinksAndRedirects(action, newTarget, next) {
updateLoadingText(action === 'update' ? 'Updating all links and redirects...' : 'Removing all links and redirects...');
api.get({
action: 'query',
list: 'backlinks',
bltitle: pageTitle,
bllimit: 'max'
}).done(function (data) {
if (data.query.backlinks) {
var promises = data.query.backlinks.map(function (link) {
return new Promise(function (resolve) {
if (action === 'update') {
updateLink(link.title, newTarget, api).then(resolve);
} else {
removeLink(link.title, api).then(resolve);
}
});
});
Promise.all(promises).then(function () {
updateLoadingText(action === 'update' ? 'All links and redirects updated.' : 'All links and redirects removed.');
next();
});
} else {
next();
}
}).fail(function (error) {
console.error('Error fetching backlinks:', error);
updateLoadingText('Error fetching backlinks: ' + error);
next();
});
}
function updateLink(pageTitle, newTarget, api) {
return api.postWithToken('csrf', {
action: 'edit',
title: pageTitle,
text: '#REDIRECT [[' + newTarget + ']]',
summary: 'Updated redirect to new target [[' + newTarget + ']]'
}).fail(function (error) {
console.error('Error updating link:', error);
});
}
function removeLink(pageTitle, api) {
return api.postWithToken('csrf', {
action: 'edit',
title: pageTitle,
text: '',
summary: 'Removed link to [[' + pageTitle + ']]'
}).fail(function (error) {
console.error('Error removing link:', error);
});
}
function performDeletion(pageTitle, next) {
updateLoadingText('Deleting the page...');
api.postWithToken('csrf', {
action: 'delete',
title: pageTitle,
reason: 'Automated clean delete by admin'
}).done(function () {
updateLoadingText('Page deleted.');
next();
}).fail(function (error) {
console.error('Error during clean deletion:', error);
updateLoadingText('Error during clean deletion: ' + error);
next();
});
}
var tasks = [
function (resolve) {
if (decisions.links === '') {
handleLinksAndRedirects('remove', '', resolve);
} else {
handleLinksAndRedirects('update', decisions.links, resolve);
}
},
function (resolve) {
performDeletion(pageTitle, resolve);
}
];
(function executeTasks(i) {
if (i < tasks.length) {
tasks[i](function () {
executeTasks(i + 1);
});
} else {
callback();
}
})(0);
}
mw.hook('wikipage.content').add(addCleanDeleteLink);
});
This page was edited 146 days ago on 08/26/2024. What links here