User:Perhelion/justReplace.js

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
/**
* @description: Support for just replace a file global (without move).
* @usage / configuration:
	// Sets a prefilled custom reason (e.g. duplicate)
	window.GlobalReplaceDefaultReason = "duplicate";

	// Sets the checkboxes for namespace exclusion default off
	window.aqdUserNsOptOut = 1;
	window.aqdProjectNsOptOut = 1;
	window.aqdTalkNsOptOut = 1;

* @revision: 17:32, 16 October 2019 (UTC)
* @author: User:Perhelion - 2017 (Commons lib, jsHint ready, regex support)
* @author: Adapted from [[MediaWiki:Gadget-libGlobalReplace.js]] and [[User:Sreejithk2000/JustReplace.js]]
* @required modules: mediawiki.util, mediawiki.user, jquery.ui, ext.gadget.libCommons, ext.gadget.libJQuery,
		ext.gadget.libUtil, mediawiki.util, ext.gadget.libGlobalReplace, ext.gadget.AjaxQuickDelete,
		'mediawiki.api', 'mediawiki.jqueryMsg'
<nowiki>
**/

(function () {
'use strict';
// Guard against multiple inclusions
if (mw.libs.JustReplace) return;

var AQD = window.AjaxQuickDelete,
	pageName,
	file;

mw.libs.JustReplace = function (page) {
	file = page;
	// Parameter for external usage and also from non file namespace
	if (typeof file === 'string') {
		pageName = file;
	} else {
		// if (typeof file === 'boolean')
		AQD.initialize();
		file = false;
	}
	AQD.pageName = pageName;
	AQD.possibleReason = (window.GlobalReplaceDefaultReason || AQD.possibleReason || '').replace(/"/, '&quot;');

	if (!file) {
		AQD.addTask('loadWMmessages');
		if (!mw.config.get('wgIsRedirect') && document.getElementById('file'))
			AQD.addTask('getMoveToken'); // only works if source file exists
		AQD.addTask('promptForReplaceTarget');
		AQD.addTask('getFileExtension');
		AQD.fileNameExistsCB = 'fileExists';
		AQD.addTask('doesFileExist'); // AQD.destination get's now file-namspace
		AQD.addTask('declineReplace');
	}
	AQD.addTask('replaceUsage');
	if (!file) {
		AQD.addTask('queryRedirects');
		AQD.addTask('replaceRedirects');
		AQD.addTask('reloadPage');
	}
	AQD.nextTask();

	AQD.replaceUsage = function (reasonShort) {
		var notOnNs = [];
		AQD.showProgress(AQD.i18n.replacingUsage);
		reasonShort = (typeof reasonShort === 'string') ? reasonShort : ''; // TODO '[[COM:Duplicate|Duplicate]]:';
		if (AQD.notUserNS) notOnNs.push(2);
		if (AQD.notProjectNS) notOnNs.push(4);
		if (AQD.notTalkNS) notOnNs = notOnNs.concat([1, 3, 5, 7, 9, 11, 13, 15]);
		if (!notOnNs.length) notOnNs = '';

		mw.loader.using(['ext.gadget.libGlobalReplace']).always(function () {
			if (AQD.replaceUsingCORS) {
				mw.libs.globalReplace(pageName, AQD.destination, reasonShort,
					AQD.reason, AQD.replaceUsingCORS, notOnNs
				).progress(function (r) {
					console.log(r);
					AQD.showProgress(r);
				}).done(function (/* r*/) {
					// console.log(r);
					if (!AQD.tasks.length) {
					// mw.log("Redirect replaced");
						AQD.addTask('reloadPage');
					}
					AQD.nextTask();
				}).fail(function (r) {
					if (console.warn) console.warn('GlobalReplace fail, try again.', r);
					AQD.disableReport = true;
					mw.notify(r, {
						title: 'replaceUsingCORS', type: 'warn'
					});
					AQD.fail(r);
					// AQD.showProgress();
					AQD.nextTask();
				// throw new Error(r);
				});
			} else {
				mw.libs.globalReplaceDelinker(pageName, AQD.destination, reasonShort   ' '   AQD.reason, function () {
					AQD.nextTask();
				}, function (r) {
					mw.notify(r, {
						title: 'Global CommonsDelinker', type: 'warn'
					});
					console.log(r);
				});
			}
		});
	};

	/** TODO: replace with updateRedirects from AQD, getFileExtension is added **/
	AQD.replaceRedirectsCB = function (result) {
		this.redirectsToUpdate = 0;
		if ((result = result.query) && (result = result.pages)) {
			this.tasks.pop(); // remove last task, 'reloadPage'
			AQD.showProgress('Replacing redirects');
			for (var r in result) {
				var pg = result[r],
					rv = pg.revisions[0];
				if (!rv || !rv['*']) continue;
				// Replace only redirects with different mimetype
				if (!AQD.checkFileExt(pg.title, AQD.destination, true)) {
					mw.log('Redirect replace skipped, same mimetype', pg.title);
					continue;
				}
				AQD.addTask('updateRedirectsCB'); // go in race condition but buffer for next
				AQD.redirectsToUpdate  ;
				console.log('Update redirects', pg, AQD.redirectsToUpdate, AQD.tasks);
				mw.libs.JustReplace(pg.title);
			}
			// AQD.addTask('reloadPage'); // add last task again!? but it comes to late
		}
		if (!AQD.redirectsToUpdate) {
			AQD.destination = undefined; // Reset?
			if (AQD.tasks.length)
				AQD.nextTask();
		}
	};

	/**
	 **  Replace also the redirects to the current page
	 **  when moving or processing dupes immediately
	 **/
	AQD.replaceRedirects = function () {
		AQD.queryRedirectsCB = 'replaceRedirectsCB';
		AQD.queryRedirects(); // now in replace mode
	};
};

mw.libs.JustReplace.init = function (/* e*/) {
	AQD.loadWMmessages = function () {
		$.when(mw.loader.using(['mediawiki.api', 'mediawiki.jqueryMsg']), $.ready)
			.always(function () {
				return new mw.Api().loadMessagesIfMissing([
					'Translate-import-err-invalid-title',
					'Wikilove-err-gallery-again',
					// 'Whatlinkshere',
					'Createacct-reason'
				]);
			}).always(function () {
				AQD.nextTask();
			});
	};

	AQD.promptForReplaceTarget = function () {
		this.showProgress();
		this.prompt([{
			message: this.i18n.moveDestination,
			prefill: this.possibleDestination || this.destination || pageName,
			returnvalue: 'destination',
			cleanUp: false,
			noEmpty: true
		}, {
			message: mw.msg('Createacct-reason'), // i18n
			prefill: ((this.reason || this.possibleReason || '').replace(/'{2,}/g, '').replace(/\s{2,}/g, ' ')).trim(),
			returnvalue: 'reason',
			cleanUp: true,
			noEmpty: false
		}, {
			message: 'Ignore file check (be sure):',
			prefill: false,
			returnvalue: 'noFileCheck',
			type: 'checkbox'
		}, {
			message: 'Ignore User namespace:',
			prefill: !window.aqdUserNsOptOut,
			returnvalue: 'notUserNS',
			type: 'checkbox'
		}, {
			message: 'Ignore Project namespace:',
			prefill: !window.aqdProjectNsOptOut,
			returnvalue: 'notProjectNS',
			type: 'checkbox'
		}, {
			message: 'Ignore Talk namespace:',
			prefill: !window.aqdTalkNsOptOut,
			returnvalue: 'notTalkNS',
			type: 'checkbox'
		}, {
			message: this.i18n.useCORSForReplace,
			prefill: !window.aqdCORSOptOut,
			returnvalue: 'replaceUsingCORS',
			type: 'checkbox'
		}
		], 'JustReplace');
		setTimeout(function () {
			mw.hook('script-loaded.justreplace-prompt').fire();
		}, 200);
	};

	AQD.getFileExtension = function (fn) {
		// Hack: Overwrite mimetype from MoveToken
		// Needed for .doesFileExist (.cleanFileName) check
		if (this.noFileCheck) {
			this.tasks.shift(); // remove nextTask
			return this.fileExists();
		}
		var ext = (fn || this.destination || '').replace(/.*?\.(\w{2,5})$/, '$1').toLowerCase();
		if (ext) {
			if (fn)
				return ext;
			if (this.destination)
				this.mimeFileExtension = ext;
			else
				this.fail('No destination found!');
		} else {
			this.fail('Can’t get file extension!');
		}
		this.nextTask();
	};

	AQD.fileExists = function () {
		/* Only works if destination file has lowercase filename extension,
		but there is already a fileExists check in JustReplace */
		this.tasks.shift(); // remove declineReplace
		// if (!file) this.addTask('reloadPage');
		this.replaceUsage();
	};

	AQD.declineReplace = function () {
		this.possibleDestination = this.destination; // save for retry
		// i18ns
		this.i18n.moveDestination = mw.msg('Wikilove-err-gallery-again'); // Please again
		this.showProgress(mw.msg('Translate-import-err-invalid-title', this.destination)); // "Checking file: name is not valid!"
		mw.libs.JustReplace(file); // try again
	};

	mw.libs.JustReplace(file);
};

$(function () {
	if ([6, 14].indexOf(mw.config.get('wgNamespaceNumber')) !== -1) {
		mw.loader.using(['mediawiki.util', 'ext.gadget.AjaxQuickDelete'], function () {
			var a = document.getElementById('ca-justreplace'),
				wgUserGroups = mw.config.get('wgUserGroups'),
				userGroups = ['sysop', 'filemover'];
			AQD = window.AjaxQuickDelete;
			pageName = AQD.pageName || window.pn || mw.config.get('wgPageName');
			if (!AQD.userRights) { // Check user group
				userGroups.some(function (v) {
					if (wgUserGroups.indexOf(v) !== -1) {
						AQD.userRights = v;
						return true;
					}
				});
			}
			if (AQD.userRights) {
				if (!a && mw.libs.JustReplace) {
					a = $(mw.util.addPortletLink('p-cactions', '#', 'Global replace', 'ca-justreplace', 'Replace stuff'))
						.find('a').on('click', mw.libs.JustReplace.init);
				}
				mw.hook('script-loaded.justreplace').fire(a);
			}
		});
	}
});
}());
// </nowiki> EOF