MediaWiki:Gadget-CacheCheck.js

From NPOWiki
Revision as of 10:40, 26 July 2021 by Bobogoobo (talk | contribs) (create - latest version from wikia dev wiki, edited to suit vanilla MW)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* 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.
 * 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) {
        return;
    }
    window.CacheCheckLoaded = true;

    var removeIfFalse = false,
        skips = window.cacheSkip || [],
        skipLimit = Number(window.cacheSkipLimit) || 1000,
        $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'
        ];

    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>');
            }
        }
    }

    // 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') ||
        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;
    }

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

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