/* Добавляет кнопку «Очистить кэш» в меню «инструменты»; её поведение зависит
* от пространства имён:
* — Для категорий сбрасывает кэш на всех входящих в них страницах.
* — Для файлов и шаблонов сбрасиывает кэш во всех включениях.
* — В основном пространстве сбрасывает кэш на страницах, ссылающихся на данную.
* — Для подстраниц пространств имён «Участник» и «Проект» сбрасывает кэш на
* всех страницах, на которые ссылается данная. Можно использовать для сброса
* кэша на произвольном списке страниц, собранного, например, через PetScan.
* Может также делать нулевую правку (ctrl+клик).
*
* По-умолчанию кэш сбрасывается с максимально разрешённой скоростью. Изменить
* это можно, задав глобальную переменную purgejs_ratelimit:
* var purgejs_ratelimit = { hits: страниц_за_запрос, seconds: задержка };
* Например:
* var purgejs_ratelimit = { hits: 50, seconds: 0 }; // 50 страниц за запрос
* var purgejs_ratelimit = { hits: 1, seconds: 1 }; // запрос в секунду
* Учтите, что при совершении нулевой правки будет сбрасываться одна страница
* на запрос независимо от присвоенных значений.
*
* Вдохновлено скриптом IKhitron:
* https://ru.wikipedia.org/wiki/Участник:IKhitron/purge.js
*
* Copyright (c) 2017 Facenapalm
* Licensed under the terms of the MIT license.
*/
mw.loader.using(['mediawiki.api']).then(function() {
"use strict";
var api = new mw.Api();
var element = null;
var ratelimit = null;
var request = null;
var count = 0;
mw.messages.set( {
'purgejs-link': 'Purge',
'purgejs-done': 'Done.',
'purgejs-error': 'Error.',
'purgejs-purged': 'Purged: $1',
'purgejs-tooltip-ctrl': 'Ctrl+Click to make a null edit.',
'purgejs-tooltip-backlinks': 'Purge the cache on pages that link to this page.',
'purgejs-tooltip-category': 'Purge the cache on pages in this category.',
'purgejs-tooltip-file': 'Purge the cache on pages that use this file.',
'purgejs-tooltip-template': 'Purge the cache on pages that use this template.',
'purgejs-tooltip-linked': 'Purge the cache on pages that are linked from this page.'
} );
if ( mw.config.get('wgUserLanguage' ) === 'ru' ) {
mw.messages.set( {
'purgejs-link': 'Сбросить кэш',
'purgejs-done': 'Готово.',
'purgejs-error': 'Ошибка.',
'purgejs-purged': 'Очищено: $1',
'purgejs-tooltip-ctrl': 'Ctrl+клик — сделать нулевую правку.',
'purgejs-tooltip-backlinks': 'Сбросить кэш на страницах, ссылающихся на эту.',
'purgejs-tooltip-category': 'Сбросить кэш на страницах, включённых в эту категорию.',
'purgejs-tooltip-file': 'Сбросить кэш на страницах с этим файлом.',
'purgejs-tooltip-template': 'Сбросить кэш на страницах, включающих этот шаблон.',
'purgejs-tooltip-linked': 'Сбросить кэш на страницах, на которые ведут ссылки с этой.'
} );
}
function status(message) {
message = message === undefined ? mw.message( 'purgejs-purged', count ).text() : message;
if (element)
element.text(message);
}
function error(message) {
status( mw.message( 'purgejs-error' ).text() );
message = message === undefined ? "unknown error" : message;
console.log("purge.js: " + message);
}
function calcGCD(x, y) {
if (x < y) {
var tmp = x;
x = y;
y = tmp;
}
while (true) {
if (y === 0)
return x;
x %= y;
if (x === 0)
return y;
y %= x;
}
}
function updateRatelimit(callback) {
if (typeof purgejs_ratelimit !== "undefined") {
ratelimit = purgejs_ratelimit;
if (callback)
callback();
return;
}
api.get({
meta: 'userinfo',
uiprop: 'rights|ratelimits'
}).done(function(data) {
if (data && data.query && data.query.userinfo) {
var ratelimits = data.query.userinfo.ratelimits;
var rights = data.query.userinfo.rights;
if (ratelimits && ratelimits.purge) {
if (ratelimits.purge.user) {
ratelimit = ratelimits.purge.user;
} else if (ratelimits.purge.ip) {
ratelimit = ratelimits.purge.ip;
} else {
return error("unable to parse ratelimits");
}
var gcd = calcGCD(ratelimit.hits, ratelimit.seconds);
if (gcd > 1) {
ratelimit.hits /= gcd;
ratelimit.seconds /= gcd;
}
} else {
if (rights && rights.indexOf("apihighlimits") !== -1) {
ratelimit = { hits: 500, seconds: 0 };
} else {
ratelimit = { hits: 50, seconds: 0 };
}
}
} else {
return error("unable to get userinfo");
}
if (callback)
callback();
});
}
function processPurge(continueinfo) {
api.post($.extend({}, request, continueinfo))
.done(function(data) {
if (data && data.purge && data.purge.length) {
count += data.purge.length;
} else {
return error("empty response");
}
if (data.warnings) {
error("warning received");
console.log(data.warnings);
return;
}
if (data["continue"]) {
status();
setTimeout(function() {
processPurge(data["continue"]);
}, 1000 * ratelimit.seconds);
} else {
status( mw.message( 'purgejs-done' ).text() );
}
})
.fail(function() {
error("request failed");
});
}
function startPurge(prefix, generator, linkupdate) {
request = { "action": "purge" };
if (linkupdate) {
request.forcelinkupdate = "1";
}
$.extend(request, generator);
updateRatelimit(function() {
var limit = prefix + "limit";
if (linkupdate) {
request[limit] = 1;
} else {
request[limit] = ratelimit.hits;
}
count = 0;
status();
processPurge(null);
});
}
function addButton() {
var pagename = mw.config.get("wgPageName");
var namespace = mw.config.get("wgCanonicalNamespace");
var action = mw.config.get("wgAction");
var exists = mw.config.get("wgArticleId") !== 0;
if (!(
action === "view" ||
namespace === "Category" && action === "edit" && !exists
)) {
return;
}
var prefix, generator;
var comment = "";
if (namespace === "") {
prefix = "gbl";
generator = {
"generator": "backlinks",
"gbltitle": pagename
};
comment = mw.message( 'purgejs-tooltip-backlinks' ).text();
} else if (namespace === "File") {
prefix = "gfu";
generator = {
"generator": "fileusage",
"titles": pagename
};
comment = mw.message( 'purgejs-tooltip-file' ).text();
} else if (namespace === "Template" || namespace === "Module") {
prefix = "gti";
generator = {
"generator": "transcludedin",
"titles": pagename
};
comment = mw.message( 'purgejs-tooltip-template' ).text();
} else if (namespace === "Category") {
prefix = "gcm";
generator = {
"generator": "categorymembers",
"gcmtitle": pagename
};
comment = mw.message( 'purgejs-tooltip-category' ).text();
} else if (
(namespace === "User" || namespace === "Wikiproject") &&
pagename.indexOf("/") != -1
) {
prefix = "gpl";
generator = {
"generator": "links",
"titles": pagename
};
comment = mw.message( 'purgejs-tooltip-linked' ).text();
}
if (prefix && generator) {
mw.loader.using( 'mediawiki.util', function() {
var link = mw.util.addPortletLink(
'p-tb',
'#',
mw.message( 'purgejs-link' ).text(),
't-purge',
comment + ' ' + mw.message( 'purgejs-tooltip-ctrl' ).text()
);
$( link ).find( 'a' ).on( 'click', function( ev ) {
ev.preventDefault();
startPurge(prefix, generator, ev.ctrlKey);
} );
element = $( '<div>' );
$( link ).append( element );
} );
}
}
addButton();
});