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)
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') {
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.
    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.
// Handles marking the given element as resolved.
    // Foo is 0 or 1 for lonelypages section.
function takeAction($el) {
    function getQS($this, foo) {
if (window.cacheCheckRemove) {
        var qs = qstr,
$el.remove();
            select = isgallery ? '.gallerytext a:first' : 'a:first',
} else {
            url = $this.find(select).attr('href');
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>');
}
}
}


        if (page === 'Lonelypages') {
// Takes list element, returns generated API query string.
            qs += foo ? 'list=embeddedin&eititle=' : 'list=backlinks&bltitle=';
// Foo is 0 or 1 for lonelypages section.
        }
function getQS($this, foo) {
        qs += encodeURIComponent(mw.util.getParamValue('title', url));
var qs = qstr,
select = isgallery ? '.gallerytext a:first' : 'a:first',
url = $this.find(select).attr('href');


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


    // Takes a JSON request result, returns array relevant to current page.
return qs;
    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.
// Takes a JSON request result, returns array relevant to current page.
    function checkComplete() {
function getData(data) {
        pending -= 1;
for (var i = 0; i < structure.length; i++) {
        if (pending <= 0) {
if (structure[i] === 'placeholder') {
            $('#CacheCheck').text('CacheCheck completed!');
//shortcut/hack thanks to StackOverflow
        } else {
for (var first in data) break;
            $('#CacheCheck').text('CacheCheck is running... (' + pending + ' remaining)');
data = data[first];
        }
} else {
    }
data = data[structure[i]];
}
if (data === undefined) {
return [];
}
}
return data;
}


    // Note: all desired data is in the format of an array,
// Takes element in list, marks script as complete if it is the last list element.
    // which in the case of "prop=" queries is missing when there is no data,
function checkComplete() {
    // and otherwise is empty.
pending -= 1;
    switch (page) {
if (pending <= 0) {
        case 'Unusedtemplates':
$('#CacheCheck').text('CacheCheck completed!');
        case 'Wantedtemplates':
} else {
            qstr += 'list=embeddedin&eititle=';
$('#CacheCheck').text('CacheCheck is running... (' + pending + ' remaining)');
            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() {
// Note: all desired data is in the format of an array,
        $('.mw-spcontent').append(
// which in the case of "prop=" queries is missing when there is no data,
            $('<p>', {
// and otherwise is empty.
                id: 'CacheCheck',
switch (page) {
                text: 'CacheCheck is running... (' + pending + ' remaining)'
case 'Unusedtemplates':
            })
case 'Wantedtemplates':
        );
qstr += 'list=embeddedin&eititle=';
        $list.each(function() {
structure.push('embeddedin');
            var $this = $(this);
break;
            if (isgallery) {
case 'Uncategorizedcategories':
                // Uncategorizedimages, Unusedimages
case 'Uncategorizedpages':
                if ($this.find('img').length) {
case 'Uncategorizedtemplates':
                    $.getJSON(getQS($this), function(data) {
case 'Uncategorizedimages':
                        data = getData(data);
qstr += 'prop=categories&titles=';
                        if (data.length !== 0) {
structure.push('pages', 'placeholder', 'categories');
                            takeAction($this);
break;
                        }
case 'Unusedimages':
                        checkComplete();
case 'Wantedfiles':
                    });
qstr += 'list=imageusage&iutitle=';
                } else {
structure.push('imageusage');
                    takeAction($this);
break;
                    checkComplete();
case 'Unusedcategories':
                }
case 'Wantedcategories':
            } else if (page === 'Lonelypages') {
qstr += 'list=categorymembers&cmtitle=';
                // The only one that needs two queries
structure.push('categorymembers');
                $.getJSON(getQS($this, 0), function(data) {
break;
                    data = data.query.backlinks;
case 'Wantedpages':
                    if (data.length && !($this.children('s').length)) {
qstr += 'list=backlinks&bltitle=';
                        takeAction($this);
structure.push('backlinks');
                    }
break;
                    checkComplete();
case 'Deadendpages':
                });
qstr += 'prop=links&titles=';
                $.getJSON(getQS($this, 1), function(data) {
structure.push('pages', 'placeholder', 'links');
                    data = data.query.embeddedin;
break;
                    if (data.length && !($this.children('s').length)) {
default:
                        takeAction($this);
break;
                    }
}
                    checkComplete();
                });
            } else {
                $.getJSON(getQS($this), function(data) {
                    data = getData(data);
                    if (removeIfFalse === (data.length === 0)) {
                        takeAction($this);
                    }
                    checkComplete();
                });
            }
        });
    }


    init();
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();
});