User:Unifiedonallwikis/Tools/Global SUL.js

/** * This script provides an extra Special-page action called "Globalize SUL" which * allows easy auto-creation and unification of your SUL account on all local wikis. * After enabling the script, the tool is accessible from Special:BlankPage/globalsul. * * @source meta.wikimedia.org/wiki/User:Krinkle/Tools/Global_SUL * @revision 4 (2014-10-08) * @stats */ (function ($, mw) {

/**	 * Iterate over all SiteMatrix wikis. * @source www.mediawiki.org/wiki/User:Krinkle/Snippets/Iterate_SiteMatrix_in_JavaScript * @revision 5 (2012-01-29) * @example * 	 *	 * @param options {Object} * - centralApiPath string: Path to api of a wiki that has the SiteMatrix installed * - onIteration function: callback for action on each wiki */	if (mw.siteMatrix === undefined) { mw.siteMatrix = {}; }	mw.siteMatrix.Iterator = function Iterate(options) { var methods, i, current, list, instance = this; if (!options.centralApiPath || !options.onIteration) { throw new Error('Invalid arguments'); }		if (!(this instanceof mw.siteMatrix.Iterator)) { throw new TypeError('Illegal function call'); }		instance.start = function start { if (i !== undefined) { throw new Error('Cannot start twice'); }			$.getJSON(options.centralApiPath + '?format=json&action=sitematrix&callback=?', function (data) {				i = 0;				list = [];				if (!data || !data.sitematrix) {					return;				}				$.each(data.sitematrix, function (key, value) { var group, wi, wo; if (key === 'count') return; group = key === 'specials' ? value : value.site; if ($.isArray(group) && group.length) { for (wi = 0; wi < group.length; wi += 1) { // Only public wikis if (group[wi]/*reserved_word*/['private'] === undefined && group[wi].closed === undefined && group[wi].fishbowl === undefined) { list.push(group[wi]); }						}					}				});				instance.next;			}); };		instance.next = function next { if (i < list.length) { current = list[i]; options.onIteration(instance, current, i, list.length); i += 1; } else { options.onComplete(instance, current, list.length); }		};		return instance; };

function initGlobalSUL { var	$content, $fieldset, $subtitle, $table, $status, $btnStart, $progress, $done, $log, globalaccountinfo;

$content = $('#bodyContent').empty; $fieldset = $(' '); $subtitle = $(' '); $table = $(			' '		);

$status = $table.find('#mw-globalsul-status'); $btnStart = $table.find('#mw-globalsul-start'); $log = $table.find('#mw-globalsul-log > ul'); $progress = $table.find('#mw-globalsul-progress'); $done = $table.find('#mw-globalsul-done');

function doUpdate(msg, iterationNr, listLength) { $status.text(msg); $log.prepend('' + new Date.toString.replace(/^\w+ /, ).replace(/:[^:]+$/, ) + ': ' + mw.html.escape(msg) + ''); if (iterationNr && listLength) { $progress.text((Math.round(((iterationNr) / listLength) * 100 * 10) / 10) + '%'); $done.text('(' + iterationNr + '/' + listLength + ' wikis)'); }		}

function getGlobalAccountInfo(ok, err) { $.ajax({				url: mw.util.wikiScript('api'),				dataType: 'json',				data: {					format: 'json',					action: 'query',					meta: 'globaluserinfo',					guiuser: mw.user.getName,					guiprop: 'merged|unattached'				},				success: function (data) {					if (data && data.query && data.query.globaluserinfo) {						ok(data.query.globaluserinfo);					} else {						err;					}				},				error: err			}); }

// Build front-end $('#firstHeading').text('Globalize SUL'); document.title = 'Globalize SUL - ' + mw.config.get('wgSiteName');

$fieldset .text('Check all public Wikimedia wikis and auto-create and unify your account where it '				+ 'doesn\'t exist yet.') .prepend($(' ').text('Create account globally')) .append($table);

// Bind events $btnStart.click(function (e) {			var iterator, mergedList, unattachedList, attemptedList;			$(this).remove;			doUpdate('Initializing...');			iterator = new mw.siteMatrix.Iterator({ centralApiPath: mw.util.wikiScript('api'), onIteration: function (instance, wikiObj, iterationNr, listLength) { var img, url, hostname; // All WMF wikis support https, but canonical is still 'http' // convert API absolute urls to relative urls so that // users of this gadget can be on either http or https and it works url = wikiObj.url.replace(/^https?:/, ''); hostname = url.replace(/^\/\/?/, ''); doUpdate(hostname + ': checking...', iterationNr, listLength); if ($.inArray(wikiObj.dbname, mergedList) !== -1) { doUpdate(hostname + ': already merged'); setTimeout(instance.next, 1); } else if ($.inArray(wikiObj.dbname, unattachedList) !== -1) { doUpdate(hostname + ': local unattached account exists'); setTimeout(instance.next, 1); } else { doUpdate(hostname + ': attempting auto-create'); attemptedList.push(hostname); img = new Image; img.onload = img.onerror = instance.next; // SiteMatrix provides canonical urls // Force protocol relative to make it work for both http and https users img.src = url + '/w/index.php?title=MediaWiki:Delete/en&action=render'; }				},				onComplete: function (instance, wikiObj, listLength) { doUpdate('Finished.', listLength, listLength); $status.html('Made ' + attemptedList.length + ' auto-create attempts.'); if (attemptedList.length > 0) { $status.append('' + attemptedList.join('') + ''); }				}			});

doUpdate('Getting global account info...'); getGlobalAccountInfo(function (gui) {				doUpdate('Global account info received');				mergedList = [];				unattachedList = [];				attemptedList = [];				if (gui.merged) {					$.each(gui.merged, function (i, obj) { mergedList.push(obj.wiki); });				}				if (gui.unattached) {					$.each(gui.unattached, function (i, obj) { unattachedList.push(obj.wiki); });				}				doUpdate('Loading wiki SiteMatrix...');				iterator.start;			}, function {				doUpdate('Download of global account info failed!');			}); });

// Output $content.append($subtitle, $fieldset); }

// Enqueue init if (mw.config.get('wgCanonicalSpecialPageName') === 'Blankpage' && mw.config.get('wgTitle').indexOf('/globalsul') > 2) { mw.loader.using('mediawiki.util', initGlobalSUL); }

}(jQuery, mediaWiki));