MediaWiki:Gadget-CacheCheck.js: Difference between revisions
Jump to navigation
Jump to search
(don't waste resources running on large lists. Also style changes) |
mNo edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 11: | Line 11: | ||
mw.loader.using('mediawiki.util').done(function() { | mw.loader.using('mediawiki.util').done(function() { | ||
if (window.cacheCheckLoaded || mw.config.get('wgCanonicalNamespace') !== 'Special') { | |||
return; | |||
} | |||
window.cacheCheckLoaded = true; | |||
var removeIfFalse = false, | |||
skips = window.cacheSkip || [], | |||
skipLimit = Number(window.cacheSkipLimit) || 1000, | |||
throttle = !window.cacheCheckAlways; | |||
$list = $('ol.special').length ? $('ol.special > li') : $('ul.gallery > li'), | |||
isgallery = $('ol.special').length ? false : true, | |||
pending = $list.length, | |||
qstr = mw.util.wikiScript('api') + '?action=query&format=json&', | |||
structure = ['query'], | |||
page = mw.config.get('wgCanonicalSpecialPageName'), | |||
pages = [ | |||
'Specialpages', | |||
'Deadendpages', | |||
'Lonelypages', | |||
'Uncategorizedcategories', | |||
'Uncategorizedpages', | |||
'Uncategorizedimages', | |||
'Uncategorizedtemplates', | |||
'Unusedcategories', | |||
'Unusedimages', | |||
'Unusedtemplates', | |||
'Wantedcategories', | |||
'Wantedpages', | |||
'Wantedfiles', | |||
'Wantedtemplates' | |||
]; | |||
// Only on "Wanted" reports, entries are resolved if the query result is empty. | |||
if (page.substring(0, 6) === 'Wanted') { | |||
removeIfFalse = true; | |||
} | |||
// Skip execution if not on a relevant page, page is skipped by user, | |||
// or list on page is empty. Else, check for empty listings on SpecialPages. | |||
if ( | |||
pages.indexOf(page) === -1 || | |||
skips.indexOf(page) !== -1 || | |||
($list.length === 0 && page !== 'Specialpages') || | |||
(throttle && $list.length > 10 && page !== 'Specialpages') || | |||
skipLimit < (Number(mw.util.getParamValue('limit')) || 0) | |||
) { | |||
return; | |||
} else if (page === 'Specialpages') { | |||
pages.push('BrokenRedirects', 'DoubleRedirects'); | |||
$('#mw-specialpagesgroup-maintenance + .mw-specialpages-list li').each(function() { | |||
var $this = $(this), | |||
exceptions = { | |||
'Uncategorizedfiles': 'Uncategorizedimages', | |||
'Unusedfiles': 'Unusedimages', | |||
'Brokenredirects': 'BrokenRedirects', | |||
'Doubleredirects': 'DoubleRedirects' | |||
}, | |||
link = $this.children('a').attr('title').substring(8); | |||
link = link.charAt(0) + link.slice(1).toLowerCase(); | |||
if (link in exceptions) { | |||
link = exceptions[link]; | |||
} | |||
if (pages.indexOf(link) === -1) { | |||
return; | |||
} | |||
$.getJSON(qstr + 'list=querypage&qppage=' + link, function(data) { | |||
var results = data.query.querypage.results; | |||
if (results.length === 0) { | |||
takeAction($this); | |||
} | |||
if ( | |||
link === 'Uncategorizedcategories' && | |||
results.length === 1 && | |||
results[0].title === window.topLevelCat | |||
) { | |||
takeAction($this); | |||
} | |||
}); | |||
}); | |||
return; | |||
} | |||
// Handles marking the given element as resolved. | |||
function takeAction($el) { | |||
if (window.cacheCheckRemove) { | |||
$el.remove(); | |||
} else { | |||
var $gallery = $el.find('.gallerytext a:first'); | |||
if ($gallery.length) { | |||
if ($gallery.find('img')) { | |||
// The link is actually on the image | |||
$el.remove(); | |||
} else { | |||
$gallery.wrap('<s></s>'); | |||
} | |||
} else { | |||
$el.wrapInner('<s></s>'); | |||
} | |||
} | |||
} | |||
// Takes list element, returns generated API query string. | |||
// Foo is 0 or 1 for lonelypages section. | |||
function getQS($this, foo) { | |||
var qs = qstr, | |||
select = isgallery ? '.gallerytext a:first' : 'a:first', | |||
url = $this.find(select).attr('href'); | |||
if (page === 'Lonelypages') { | |||
qs += foo ? 'list=embeddedin&eititle=' : 'list=backlinks&bltitle='; | |||
} | |||
qs += encodeURIComponent(mw.util.getParamValue('title', url)); | |||
return qs; | |||
} | |||
// Takes a JSON request result, returns array relevant to current page. | |||
function getData(data) { | |||
for (var i = 0; i < structure.length; i++) { | |||
if (structure[i] === 'placeholder') { | |||
//shortcut/hack thanks to StackOverflow | |||
for (var first in data) break; | |||
data = data[first]; | |||
} else { | |||
data = data[structure[i]]; | |||
} | |||
if (data === undefined) { | |||
return []; | |||
} | |||
} | |||
return data; | |||
} | |||
// Takes element in list, marks script as complete if it is the last list element. | |||
function checkComplete() { | |||
pending -= 1; | |||
if (pending <= 0) { | |||
$('#CacheCheck').text('CacheCheck completed!'); | |||
} else { | |||
$('#CacheCheck').text('CacheCheck is running... (' + pending + ' remaining)'); | |||
} | |||
} | |||
// Note: all desired data is in the format of an array, | |||
// which in the case of "prop=" queries is missing when there is no data, | |||
// and otherwise is empty. | |||
switch (page) { | |||
case 'Unusedtemplates': | |||
case 'Wantedtemplates': | |||
qstr += 'list=embeddedin&eititle='; | |||
structure.push('embeddedin'); | |||
break; | |||
case 'Uncategorizedcategories': | |||
case 'Uncategorizedpages': | |||
case 'Uncategorizedtemplates': | |||
case 'Uncategorizedimages': | |||
qstr += 'prop=categories&titles='; | |||
structure.push('pages', 'placeholder', 'categories'); | |||
break; | |||
case 'Unusedimages': | |||
case 'Wantedfiles': | |||
qstr += 'list=imageusage&iutitle='; | |||
structure.push('imageusage'); | |||
break; | |||
case 'Unusedcategories': | |||
case 'Wantedcategories': | |||
qstr += 'list=categorymembers&cmtitle='; | |||
structure.push('categorymembers'); | |||
break; | |||
case 'Wantedpages': | |||
qstr += 'list=backlinks&bltitle='; | |||
structure.push('backlinks'); | |||
break; | |||
case 'Deadendpages': | |||
qstr += 'prop=links&titles='; | |||
structure.push('pages', 'placeholder', 'links'); | |||
break; | |||
default: | |||
break; | |||
} | |||
function init() { | |||
$('.mw-spcontent').append( | |||
$('<p>', { | |||
id: 'CacheCheck', | |||
text: 'CacheCheck is running... (' + pending + ' remaining)' | |||
}) | |||
); | |||
$list.each(function() { | |||
var $this = $(this); | |||
if (isgallery) { | |||
// Uncategorizedimages, Unusedimages | |||
if ($this.find('img').length) { | |||
$.getJSON(getQS($this), function(data) { | |||
data = getData(data); | |||
if (data.length !== 0) { | |||
takeAction($this); | |||
} | |||
checkComplete(); | |||
}); | |||
} else { | |||
takeAction($this); | |||
checkComplete(); | |||
} | |||
} else if (page === 'Lonelypages') { | |||
// The only one that needs two queries | |||
$.getJSON(getQS($this, 0), function(data) { | |||
data = data.query.backlinks; | |||
if (data.length && !($this.children('s').length)) { | |||
takeAction($this); | |||
} | |||
checkComplete(); | |||
}); | |||
$.getJSON(getQS($this, 1), function(data) { | |||
data = data.query.embeddedin; | |||
if (data.length && !($this.children('s').length)) { | |||
takeAction($this); | |||
} | |||
checkComplete(); | |||
}); | |||
} else { | |||
$.getJSON(getQS($this), function(data) { | |||
data = getData(data); | |||
if (removeIfFalse === (data.length === 0)) { | |||
takeAction($this); | |||
} | |||
checkComplete(); | |||
}); | |||
} | |||
}); | |||
} | |||
init(); | |||
}); | }); |
Latest revision as of 11:24, 26 July 2021
/* CacheCheck.js
* Crosses out resolved entries on the cached special pages to save time checking them.
* Note: these pages have a much shorter cache here, but the script also helps at-a-glance on SpecialPages.
* Therefore, the script will only run on a report page if ten or fewer items are listed.
* Use window.cacheCheckAlways = true; to disable this.
* Originally by Bobogoobo, edited by KockaAdmiralac and others, then ported off Wikia by Bobogoobo.
* For full documentation and contribution history (other than changes before publishing), please see:
* https://dev.fandom.com/wiki/CacheCheck
*/
window.topLevelCat = 'Category:Contents';
mw.loader.using('mediawiki.util').done(function() {
if (window.cacheCheckLoaded || mw.config.get('wgCanonicalNamespace') !== 'Special') {
return;
}
window.cacheCheckLoaded = true;
var removeIfFalse = false,
skips = window.cacheSkip || [],
skipLimit = Number(window.cacheSkipLimit) || 1000,
throttle = !window.cacheCheckAlways;
$list = $('ol.special').length ? $('ol.special > li') : $('ul.gallery > li'),
isgallery = $('ol.special').length ? false : true,
pending = $list.length,
qstr = mw.util.wikiScript('api') + '?action=query&format=json&',
structure = ['query'],
page = mw.config.get('wgCanonicalSpecialPageName'),
pages = [
'Specialpages',
'Deadendpages',
'Lonelypages',
'Uncategorizedcategories',
'Uncategorizedpages',
'Uncategorizedimages',
'Uncategorizedtemplates',
'Unusedcategories',
'Unusedimages',
'Unusedtemplates',
'Wantedcategories',
'Wantedpages',
'Wantedfiles',
'Wantedtemplates'
];
// Only on "Wanted" reports, entries are resolved if the query result is empty.
if (page.substring(0, 6) === 'Wanted') {
removeIfFalse = true;
}
// Skip execution if not on a relevant page, page is skipped by user,
// or list on page is empty. Else, check for empty listings on SpecialPages.
if (
pages.indexOf(page) === -1 ||
skips.indexOf(page) !== -1 ||
($list.length === 0 && page !== 'Specialpages') ||
(throttle && $list.length > 10 && page !== 'Specialpages') ||
skipLimit < (Number(mw.util.getParamValue('limit')) || 0)
) {
return;
} else if (page === 'Specialpages') {
pages.push('BrokenRedirects', 'DoubleRedirects');
$('#mw-specialpagesgroup-maintenance + .mw-specialpages-list li').each(function() {
var $this = $(this),
exceptions = {
'Uncategorizedfiles': 'Uncategorizedimages',
'Unusedfiles': 'Unusedimages',
'Brokenredirects': 'BrokenRedirects',
'Doubleredirects': 'DoubleRedirects'
},
link = $this.children('a').attr('title').substring(8);
link = link.charAt(0) + link.slice(1).toLowerCase();
if (link in exceptions) {
link = exceptions[link];
}
if (pages.indexOf(link) === -1) {
return;
}
$.getJSON(qstr + 'list=querypage&qppage=' + link, function(data) {
var results = data.query.querypage.results;
if (results.length === 0) {
takeAction($this);
}
if (
link === 'Uncategorizedcategories' &&
results.length === 1 &&
results[0].title === window.topLevelCat
) {
takeAction($this);
}
});
});
return;
}
// Handles marking the given element as resolved.
function takeAction($el) {
if (window.cacheCheckRemove) {
$el.remove();
} else {
var $gallery = $el.find('.gallerytext a:first');
if ($gallery.length) {
if ($gallery.find('img')) {
// The link is actually on the image
$el.remove();
} else {
$gallery.wrap('<s></s>');
}
} else {
$el.wrapInner('<s></s>');
}
}
}
// Takes list element, returns generated API query string.
// Foo is 0 or 1 for lonelypages section.
function getQS($this, foo) {
var qs = qstr,
select = isgallery ? '.gallerytext a:first' : 'a:first',
url = $this.find(select).attr('href');
if (page === 'Lonelypages') {
qs += foo ? 'list=embeddedin&eititle=' : 'list=backlinks&bltitle=';
}
qs += encodeURIComponent(mw.util.getParamValue('title', url));
return qs;
}
// Takes a JSON request result, returns array relevant to current page.
function getData(data) {
for (var i = 0; i < structure.length; i++) {
if (structure[i] === 'placeholder') {
//shortcut/hack thanks to StackOverflow
for (var first in data) break;
data = data[first];
} else {
data = data[structure[i]];
}
if (data === undefined) {
return [];
}
}
return data;
}
// Takes element in list, marks script as complete if it is the last list element.
function checkComplete() {
pending -= 1;
if (pending <= 0) {
$('#CacheCheck').text('CacheCheck completed!');
} else {
$('#CacheCheck').text('CacheCheck is running... (' + pending + ' remaining)');
}
}
// Note: all desired data is in the format of an array,
// which in the case of "prop=" queries is missing when there is no data,
// and otherwise is empty.
switch (page) {
case 'Unusedtemplates':
case 'Wantedtemplates':
qstr += 'list=embeddedin&eititle=';
structure.push('embeddedin');
break;
case 'Uncategorizedcategories':
case 'Uncategorizedpages':
case 'Uncategorizedtemplates':
case 'Uncategorizedimages':
qstr += 'prop=categories&titles=';
structure.push('pages', 'placeholder', 'categories');
break;
case 'Unusedimages':
case 'Wantedfiles':
qstr += 'list=imageusage&iutitle=';
structure.push('imageusage');
break;
case 'Unusedcategories':
case 'Wantedcategories':
qstr += 'list=categorymembers&cmtitle=';
structure.push('categorymembers');
break;
case 'Wantedpages':
qstr += 'list=backlinks&bltitle=';
structure.push('backlinks');
break;
case 'Deadendpages':
qstr += 'prop=links&titles=';
structure.push('pages', 'placeholder', 'links');
break;
default:
break;
}
function init() {
$('.mw-spcontent').append(
$('<p>', {
id: 'CacheCheck',
text: 'CacheCheck is running... (' + pending + ' remaining)'
})
);
$list.each(function() {
var $this = $(this);
if (isgallery) {
// Uncategorizedimages, Unusedimages
if ($this.find('img').length) {
$.getJSON(getQS($this), function(data) {
data = getData(data);
if (data.length !== 0) {
takeAction($this);
}
checkComplete();
});
} else {
takeAction($this);
checkComplete();
}
} else if (page === 'Lonelypages') {
// The only one that needs two queries
$.getJSON(getQS($this, 0), function(data) {
data = data.query.backlinks;
if (data.length && !($this.children('s').length)) {
takeAction($this);
}
checkComplete();
});
$.getJSON(getQS($this, 1), function(data) {
data = data.query.embeddedin;
if (data.length && !($this.children('s').length)) {
takeAction($this);
}
checkComplete();
});
} else {
$.getJSON(getQS($this), function(data) {
data = getData(data);
if (removeIfFalse === (data.length === 0)) {
takeAction($this);
}
checkComplete();
});
}
});
}
init();
});