MediaWiki:Gadget-CacheCheck.js: Difference between revisions

From NPOWiki
Jump to navigation Jump to search
(don't waste resources running on large lists. Also style changes)
m (spaces to tabs)
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') {
if (window.cacheCheckLoaded || mw.config.get('wgCanonicalNamespace') !== 'Special') {
        return;
return;
    }
}
    window.cacheCheckLoaded = true;
window.cacheCheckLoaded = true;


    var removeIfFalse = false,
var removeIfFalse = false,
        skips = window.cacheSkip || [],
skips = window.cacheSkip || [],
        skipLimit = Number(window.cacheSkipLimit) || 1000,
skipLimit = Number(window.cacheSkipLimit) || 1000,
        throttle = !window.cacheCheckAlways;
throttle = !window.cacheCheckAlways;
        $list = $('ol.special').length ? $('ol.special > li') : $('ul.gallery > li'),
$list = $('ol.special').length ? $('ol.special > li') : $('ul.gallery > li'),
        isgallery = $('ol.special').length ? false : true,
isgallery = $('ol.special').length ? false : true,
        pending = $list.length,
pending = $list.length,
        qstr = mw.util.wikiScript('api') + '?action=query&format=json&',
qstr = mw.util.wikiScript('api') + '?action=query&format=json&',
        structure = ['query'],
structure = ['query'],
        page = mw.config.get('wgCanonicalSpecialPageName'),
page = mw.config.get('wgCanonicalSpecialPageName'),
        pages = [
pages = [
            'Specialpages',
'Specialpages',
            'Deadendpages',
'Deadendpages',
            'Lonelypages',  
'Lonelypages',  
            'Uncategorizedcategories',
'Uncategorizedcategories',
            'Uncategorizedpages',
'Uncategorizedpages',
            'Uncategorizedimages',
'Uncategorizedimages',
            'Uncategorizedtemplates',
'Uncategorizedtemplates',
            'Unusedcategories',
'Unusedcategories',
            'Unusedimages',
'Unusedimages',
            'Unusedtemplates',
'Unusedtemplates',
            'Wantedcategories',
'Wantedcategories',
            'Wantedpages',
'Wantedpages',
            'Wantedfiles',
'Wantedfiles',
            'Wantedtemplates'
'Wantedtemplates'
        ];
];


    // Only on "Wanted" reports, entries are resolved if the query result is empty.
// Only on "Wanted" reports, entries are resolved if the query result is empty.
    if (page.substring(0, 6) === 'Wanted') {
if (page.substring(0, 6) === 'Wanted') {
        removeIfFalse = true;
removeIfFalse = true;
    }
}


    // Skip execution if not on a relevant page, page is skipped by user,  
// 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.
// or list on page is empty. Else, check for empty listings on SpecialPages.
    if (
if (
        pages.indexOf(page) === -1 ||
pages.indexOf(page) === -1 ||
        skips.indexOf(page) !== -1 ||
skips.indexOf(page) !== -1 ||
        ($list.length === 0 && page !== 'Specialpages') ||
($list.length === 0 && page !== 'Specialpages') ||
        (throttle && $list.length > 10 && page !== 'Specialpages') ||
(throttle && $list.length > 10 && page !== 'Specialpages') ||
        skipLimit < (Number(mw.util.getParamValue('limit')) || 0)
skipLimit < (Number(mw.util.getParamValue('limit')) || 0)
    ) {
) {
        return;
return;
    } else if (page === 'Specialpages') {
} else if (page === 'Specialpages') {
        pages.push('BrokenRedirects', 'DoubleRedirects');
pages.push('BrokenRedirects', 'DoubleRedirects');
        $('#mw-specialpagesgroup-maintenance + .mw-specialpages-list li').each(function() {
$('#mw-specialpagesgroup-maintenance + .mw-specialpages-list li').each(function() {
            var $this = $(this),
var $this = $(this),
                exceptions = {
exceptions = {
                    'Uncategorizedfiles': 'Uncategorizedimages',  
'Uncategorizedfiles': 'Uncategorizedimages',  
                    'Unusedfiles': 'Unusedimages',
'Unusedfiles': 'Unusedimages',
                    'Brokenredirects': 'BrokenRedirects',
'Brokenredirects': 'BrokenRedirects',
                    'Doubleredirects': 'DoubleRedirects'
'Doubleredirects': 'DoubleRedirects'
                },
},
                link = $this.children('a').attr('title').substring(8);
link = $this.children('a').attr('title').substring(8);
            link = link.charAt(0) + link.slice(1).toLowerCase();
link = link.charAt(0) + link.slice(1).toLowerCase();


            if (link in exceptions) {
if (link in exceptions) {
                link = exceptions[link];
link = exceptions[link];
            }
}
            if (pages.indexOf(link) === -1) {
if (pages.indexOf(link) === -1) {
                return;
return;
            }
}


            $.getJSON(qstr + 'list=querypage&qppage=' + link, function(data) {
$.getJSON(qstr + 'list=querypage&qppage=' + link, function(data) {
                var results = data.query.querypage.results;
var results = data.query.querypage.results;
                if (results.length === 0) {
if (results.length === 0) {
                    takeAction($this);
takeAction($this);
                }
}
                if (
if (
                    link === 'Uncategorizedcategories' &&
link === 'Uncategorizedcategories' &&
                    results.length === 1 &&
results.length === 1 &&
                    results[0].title === window.topLevelCat
results[0].title === window.topLevelCat
                ) {
) {
                    takeAction($this);
takeAction($this);
                }
}
            });
});
        });
});
        return;
return;
    }
}
   
    // Handles marking the given element as resolved.
// Handles marking the given element as resolved.
    function takeAction($el) {
function takeAction($el) {
        if (window.cacheCheckRemove) {
if (window.cacheCheckRemove) {
            $el.remove();
$el.remove();
        } else {
} else {
            var $gallery = $el.find('.gallerytext a:first');
var $gallery = $el.find('.gallerytext a:first');
            if ($gallery.length) {
if ($gallery.length) {
                if ($gallery.find('img')) {
if ($gallery.find('img')) {
                    // The link is actually on the image.
// The link is actually on the image.
                    $el.remove();
$el.remove();
                } else {
} else {
                    $gallery.wrap('<s></s>');
$gallery.wrap('<s></s>');
                }
}
            } else {
} else {
                $el.wrapInner('<s></s>');
$el.wrapInner('<s></s>');
            }
}
        }
}
    }
}


    // Takes list element, returns generated API query string.
// Takes list element, returns generated API query string.
    // Foo is 0 or 1 for lonelypages section.
// Foo is 0 or 1 for lonelypages section.
    function getQS($this, foo) {
function getQS($this, foo) {
        var qs = qstr,
var qs = qstr,
            select = isgallery ? '.gallerytext a:first' : 'a:first',
select = isgallery ? '.gallerytext a:first' : 'a:first',
            url = $this.find(select).attr('href');
url = $this.find(select).attr('href');


        if (page === 'Lonelypages') {
if (page === 'Lonelypages') {
            qs += foo ? 'list=embeddedin&eititle=' : 'list=backlinks&bltitle=';
qs += foo ? 'list=embeddedin&eititle=' : 'list=backlinks&bltitle=';
        }
}
        qs += encodeURIComponent(mw.util.getParamValue('title', url));
qs += encodeURIComponent(mw.util.getParamValue('title', url));


        return qs;
return qs;
    }
}


    // Takes a JSON request result, returns array relevant to current page.
// Takes a JSON request result, returns array relevant to current page.
    function getData(data) {
function getData(data) {
        for (var i = 0; i < structure.length; i++) {
for (var i = 0; i < structure.length; i++) {
            if (structure[i] === 'placeholder') {
if (structure[i] === 'placeholder') {
                //shortcut/hack thanks to https://archive.is/RwvEn
//shortcut/hack thanks to https://archive.is/RwvEn
                for (var first in data) break;
for (var first in data) break;
                data = data[first];
data = data[first];
            } else {
} else {
                data = data[structure[i]];
data = data[structure[i]];
            }
}
            if (data === undefined) {
if (data === undefined) {
                return [];
return [];
            }
}
        }
}
        return data;
return data;
    }
}


    // Takes element in list, marks script as complete if it is the last list element.
// Takes element in list, marks script as complete if it is the last list element.
    function checkComplete() {
function checkComplete() {
        pending -= 1;
pending -= 1;
        if (pending <= 0) {
if (pending <= 0) {
            $('#CacheCheck').text('CacheCheck completed!');
$('#CacheCheck').text('CacheCheck completed!');
        } else {
} else {
            $('#CacheCheck').text('CacheCheck is running... (' + pending + ' remaining)');
$('#CacheCheck').text('CacheCheck is running... (' + pending + ' remaining)');
        }
}
    }
}


    // Note: all desired data is in the format of an array,
// 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,
// which in the case of "prop=" queries is missing when there is no data,
    // and otherwise is empty.
// and otherwise is empty.
    switch (page) {
switch (page) {
        case 'Unusedtemplates':
case 'Unusedtemplates':
        case 'Wantedtemplates':
case 'Wantedtemplates':
            qstr += 'list=embeddedin&eititle=';
qstr += 'list=embeddedin&eititle=';
            structure.push('embeddedin');
structure.push('embeddedin');
            break;
break;
        case 'Uncategorizedcategories':
case 'Uncategorizedcategories':
        case 'Uncategorizedpages':
case 'Uncategorizedpages':
        case 'Uncategorizedtemplates':
case 'Uncategorizedtemplates':
        case 'Uncategorizedimages':
case 'Uncategorizedimages':
            qstr += 'prop=categories&titles=';
qstr += 'prop=categories&titles=';
            structure.push('pages', 'placeholder', 'categories');
structure.push('pages', 'placeholder', 'categories');
            break;
break;
        case 'Unusedimages':
case 'Unusedimages':
        case 'Wantedfiles':
case 'Wantedfiles':
            qstr += 'list=imageusage&iutitle=';
qstr += 'list=imageusage&iutitle=';
            structure.push('imageusage');
structure.push('imageusage');
            break;
break;
        case 'Unusedcategories':
case 'Unusedcategories':
        case 'Wantedcategories':
case 'Wantedcategories':
            qstr += 'list=categorymembers&cmtitle=';
qstr += 'list=categorymembers&cmtitle=';
            structure.push('categorymembers');
structure.push('categorymembers');
            break;
break;
        case 'Wantedpages':
case 'Wantedpages':
            qstr += 'list=backlinks&bltitle=';
qstr += 'list=backlinks&bltitle=';
            structure.push('backlinks');
structure.push('backlinks');
            break;
break;
        case 'Deadendpages':
case 'Deadendpages':
            qstr += 'prop=links&titles=';
qstr += 'prop=links&titles=';
            structure.push('pages', 'placeholder', 'links');
structure.push('pages', 'placeholder', 'links');
            break;
break;
        default:
default:
            break;
break;
    }
}


    function init() {
function init() {
        $('.mw-spcontent').append(
$('.mw-spcontent').append(
            $('<p>', {
$('<p>', {
                id: 'CacheCheck',
id: 'CacheCheck',
                text: 'CacheCheck is running... (' + pending + ' remaining)'
text: 'CacheCheck is running... (' + pending + ' remaining)'
            })
})
        );
);
        $list.each(function() {
$list.each(function() {
            var $this = $(this);
var $this = $(this);
            if (isgallery) {
if (isgallery) {
                // Uncategorizedimages, Unusedimages
// Uncategorizedimages, Unusedimages
                if ($this.find('img').length) {
if ($this.find('img').length) {
                    $.getJSON(getQS($this), function(data) {
$.getJSON(getQS($this), function(data) {
                        data = getData(data);
data = getData(data);
                        if (data.length !== 0) {
if (data.length !== 0) {
                            takeAction($this);
takeAction($this);
                        }
}
                        checkComplete();
checkComplete();
                    });
});
                } else {
} else {
                    takeAction($this);
takeAction($this);
                    checkComplete();
checkComplete();
                }
}
            } else if (page === 'Lonelypages') {
} else if (page === 'Lonelypages') {
                // The only one that needs two queries
// The only one that needs two queries
                $.getJSON(getQS($this, 0), function(data) {
$.getJSON(getQS($this, 0), function(data) {
                    data = data.query.backlinks;
data = data.query.backlinks;
                    if (data.length && !($this.children('s').length)) {
if (data.length && !($this.children('s').length)) {
                        takeAction($this);
takeAction($this);
                    }
}
                    checkComplete();
checkComplete();
                });
});
                $.getJSON(getQS($this, 1), function(data) {
$.getJSON(getQS($this, 1), function(data) {
                    data = data.query.embeddedin;
data = data.query.embeddedin;
                    if (data.length && !($this.children('s').length)) {
if (data.length && !($this.children('s').length)) {
                        takeAction($this);
takeAction($this);
                    }
}
                    checkComplete();
checkComplete();
                });
});
            } else {
} else {
                $.getJSON(getQS($this), function(data) {
$.getJSON(getQS($this), function(data) {
                    data = getData(data);
data = getData(data);
                    if (removeIfFalse === (data.length === 0)) {
if (removeIfFalse === (data.length === 0)) {
                        takeAction($this);
takeAction($this);
                    }
}
                    checkComplete();
checkComplete();
                });
});
            }
}
        });
});
    }
}


    init();
init();
});
});

Revision as of 11:20, 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 https://archive.is/RwvEn
				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();
});