No edit summary |
No edit summary |
||
Line 5: | Line 5: | ||
// ==/UserScript== | // ==/UserScript== | ||
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'jquery | mw.loader.using(['mediawiki.api', 'mediawiki.util', 'jquery'], function () { | ||
function addCleanDeleteLink() { | function addCleanDeleteLink() { | ||
if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) { | if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) { | ||
Line 22: | Line 22: | ||
function gatherAllDecisions(pageTitle) { | function gatherAllDecisions(pageTitle) { | ||
var decisions = {}; | var decisions = {}; | ||
showModal('Handle Links and Redirects', | showModal('Handle Links and Redirects', '<div class="form-group">' + | ||
'<label>Specify how you would like to handle all incoming links and redirects:</label>' + | |||
'<select id="link-handling-select" class="form-control">' + | |||
'<option value="delete">Delete Links and Redirects</option>' + | |||
'<option value="change">Change Target of Links and Redirects</option>' + | |||
'</select>' + | |||
'</div>', function () { | |||
var choice = $('#link-handling-select').val(); | var choice = $('#link-handling-select').val(); | ||
if (choice === 'change') { | if (choice === 'change') { | ||
showModal('Specify New Target', | showModal('Specify New Target', '<div class="form-group">' + | ||
'<label>Enter the new target page name to update all links and redirects:</label>' + | |||
'<input type="text" id="new-target-input" class="form-control" placeholder="Enter new target">' + | |||
'</div>', function () { | |||
decisions.links = $('#new-target-input').val(); | decisions.links = $('#new-target-input').val(); | ||
confirmDeletion(pageTitle, decisions); | confirmDeletion(pageTitle, decisions); | ||
Line 50: | Line 46: | ||
function confirmDeletion(pageTitle, decisions) { | function confirmDeletion(pageTitle, decisions) { | ||
showModal('Confirm Page Deletion', | showModal('Confirm Page Deletion', '<p>Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?</p>', function () { | ||
decisions.deletion = true; | decisions.deletion = true; | ||
showLoadingDialog('Performing Cleanup', function (updateLoadingText) { | showLoadingDialog('Performing Cleanup', function (updateLoadingText) { | ||
Line 63: | Line 57: | ||
function showModal(title, body, onConfirm) { | function showModal(title, body, onConfirm) { | ||
var modal = $( | var modal = $( | ||
<div class="modal fade" tabindex="-1" role="dialog"> | '<div class="modal fade" tabindex="-1" role="dialog">' + | ||
<div class="modal-dialog" role="document"> | '<div class="modal-dialog" role="document">' + | ||
<div class="modal-content"> | '<div class="modal-content">' + | ||
<div class="modal-header"> | '<div class="modal-header">' + | ||
<h5 class="modal-title"> | '<h5 class="modal-title">' + title + '</h5>' + | ||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' + | ||
<span aria-hidden="true">×</span> | '<span aria-hidden="true">×</span>' + | ||
</button> | '</button>' + | ||
</div> | '</div>' + | ||
<div class="modal-body"> | '<div class="modal-body">' + body + '</div>' + | ||
'<div class="modal-footer">' + | |||
'<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>' + | |||
<div class="modal-footer"> | '<button type="button" class="btn btn-primary">Confirm</button>' + | ||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> | '</div>' + | ||
<button type="button" class="btn btn-primary">Confirm</button> | '</div>' + | ||
</div> | '</div>' + | ||
</div> | '</div>' | ||
</div> | ); | ||
</div> | |||
modal.find('.btn-primary').click(function () { | modal.find('.btn-primary').click(function () { | ||
Line 99: | Line 91: | ||
function showLoadingDialog(message, callback) { | function showLoadingDialog(message, callback) { | ||
var modal = $( | var modal = $( | ||
<div class="modal fade" tabindex="-1" role="dialog"> | '<div class="modal fade" tabindex="-1" role="dialog">' + | ||
<div class="modal-dialog" role="document"> | '<div class="modal-dialog" role="document">' + | ||
<div class="modal-content"> | '<div class="modal-content">' + | ||
<div class="modal-header"> | '<div class="modal-header">' + | ||
<h5 class="modal-title">Performing Cleanup</h5> | '<h5 class="modal-title">Performing Cleanup</h5>' + | ||
</div> | '</div>' + | ||
<div class="modal-body"> | '<div class="modal-body">' + | ||
<p id="loading-text"> | '<p id="loading-text">' + message + '</p>' + | ||
</div> | '</div>' + | ||
</div> | '</div>' + | ||
</div> | '</div>' + | ||
</div> | '</div>' | ||
); | |||
$('body').append(modal); | $('body').append(modal); | ||
Line 135: | Line 127: | ||
}).done(function (data) { | }).done(function (data) { | ||
if (data.query.backlinks) { | if (data.query.backlinks) { | ||
var promises = data.query.backlinks | var promises = $.map(data.query.backlinks, function (link) { | ||
return new | return new $.Deferred(function (defer) { | ||
if (action === 'update') { | if (action === 'update') { | ||
updateLink(link.title, newTarget, api).then(resolve); | updateLink(link.title, newTarget, api).then(defer.resolve); | ||
} else { | } else { | ||
removeLink(link.title, api).then(resolve); | removeLink(link.title, api).then(defer.resolve); | ||
} | } | ||
}); | }).promise(); | ||
}); | }); | ||
$.when.apply($, promises).then(function () { | |||
updateLoadingText(action === 'update' ? 'All links and redirects updated.' : 'All links and redirects removed.'); | updateLoadingText(action === 'update' ? 'All links and redirects updated.' : 'All links and redirects removed.'); | ||
next(); | next(); |
Revision as of 23:31, 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', 'jquery'], 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 = {};
showModal('Handle Links and Redirects', '<div class="form-group">' +
'<label>Specify how you would like to handle all incoming links and redirects:</label>' +
'<select id="link-handling-select" class="form-control">' +
'<option value="delete">Delete Links and Redirects</option>' +
'<option value="change">Change Target of Links and Redirects</option>' +
'</select>' +
'</div>', function () {
var choice = $('#link-handling-select').val();
if (choice === 'change') {
showModal('Specify New Target', '<div class="form-group">' +
'<label>Enter the new target page name to update all links and redirects:</label>' +
'<input type="text" id="new-target-input" class="form-control" placeholder="Enter new target">' +
'</div>', function () {
decisions.links = $('#new-target-input').val();
confirmDeletion(pageTitle, decisions);
});
} else {
decisions.links = '';
confirmDeletion(pageTitle, decisions);
}
});
}
function confirmDeletion(pageTitle, decisions) {
showModal('Confirm Page Deletion', '<p>Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?</p>', function () {
decisions.deletion = true;
showLoadingDialog('Performing Cleanup', function (updateLoadingText) {
executeAllActions(pageTitle, decisions, function () {
location.reload();
}, updateLoadingText);
});
});
}
function showModal(title, body, onConfirm) {
var modal = $(
'<div class="modal fade" tabindex="-1" role="dialog">' +
'<div class="modal-dialog" role="document">' +
'<div class="modal-content">' +
'<div class="modal-header">' +
'<h5 class="modal-title">' + title + '</h5>' +
'<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
'<span aria-hidden="true">×</span>' +
'</button>' +
'</div>' +
'<div class="modal-body">' + body + '</div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>' +
'<button type="button" class="btn btn-primary">Confirm</button>' +
'</div>' +
'</div>' +
'</div>' +
'</div>'
);
modal.find('.btn-primary').click(function () {
onConfirm();
modal.modal('hide');
});
modal.on('hidden.bs.modal', function () {
modal.remove();
});
$('body').append(modal);
modal.modal('show');
}
function showLoadingDialog(message, callback) {
var modal = $(
'<div class="modal fade" tabindex="-1" role="dialog">' +
'<div class="modal-dialog" role="document">' +
'<div class="modal-content">' +
'<div class="modal-header">' +
'<h5 class="modal-title">Performing Cleanup</h5>' +
'</div>' +
'<div class="modal-body">' +
'<p id="loading-text">' + message + '</p>' +
'</div>' +
'</div>' +
'</div>' +
'</div>'
);
$('body').append(modal);
modal.modal('show');
callback(function (text) {
$('#loading-text').text(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 = $.map(data.query.backlinks, function (link) {
return new $.Deferred(function (defer) {
if (action === 'update') {
updateLink(link.title, newTarget, api).then(defer.resolve);
} else {
removeLink(link.title, api).then(defer.resolve);
}
}).promise();
});
$.when.apply($, 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) {
if (decisions.deletion) {
performDeletion(pageTitle, resolve);
} else {
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