Jump to content

User:IceWelder/copycat.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
function copycat_copy_page(_oldName, _newName, processContent, copyTalk, isTalk, createParents) {
    // Safe-prepend names with space key
    var spaceKey = isTalk ? 'Category talk' : 'Category';
    var oldName = `${spaceKey}:${_oldName.replace(/Category(?:[_ ]talk):/g, '')}`;
    var newName = `${spaceKey}:${_newName.replace(/Category(?:[_ ]talk):/g, '')}`;

    // Retrieve the original page to ge its content
    var oldPage = new Morebits.wiki.page(oldName, `Reading category ${oldName}`);
    oldPage.setCreateOption('nocreate');
    oldPage.load(
        function () {
            if (!oldPage.exists()) {
                Morebits.status.warn('Warning', `${oldName} does not exist.`);
                return;
            }

            // Process possible replacements
            var oldContent = oldPage.getPageText();
            var newContent = processContent(oldContent);

            // Create the new page
            var newPage = new Morebits.wiki.page(newName, `Creating category ${newName}`);
            newPage.setCreateOption('createonly');
            newPage.setAppendText(newContent);
            newPage.setWatchlist('default');
            newPage.setEditSummary(`Copied category from ${oldName} by [[w:User:IceWelder/copycat.js|script]]`);
            newPage.load(
                function () {
                    if (newPage.exists()) {
                        Morebits.status.info('Info', `${newName} already exists.`);
                        return;
                    }

                    newPage.append(
                        function () {
                            // Talk page -> Do nothing
                            if (isTalk) {
                                return;
                            }

                            // Copy talk page
                            if (copyTalk) {
                                copycat_copy_page(_oldName, _newName, processContent, copyTalk, true, createParents);
                            }

                            // Ignore parents -> Do nothing
                            if (!createParents) {
                                return;
                            }

                            // Retrieve all listed categories
                            var categoriesRegex = /(?<=\[\[[_ ]*[Cc]ategory[_ ]*:[_ ]*)[^\]|]+[_ ]*/g;
                            var match;
                            do {
                                match = categoriesRegex.exec(oldContent);
                                if (match) {
                                    var oldCategory = match[0];
                                    // Category did not contain an ordinal -> do nothing
                                    var newCategory = processContent(oldCategory);
                                    if (newCategory === oldCategory) {
                                        continue;
                                    }

                                    // Recursively create category
                                    copycat_copy_page(oldCategory, newCategory, processContent, copyTalk, false, createParents);
                                }
                            } while (match);
                        },
                        function () {
                            Morebits.status.error('Error', `An error occurred while creating ${newName}`);
                        }
                    );
                },
                function () {
                    Morebits.status.error('Error', `An error occurred while reading ${newName}`);
                }
            );
        },
        function () {
            Morebits.status.error('Error', `An error occurred while reading ${oldName}`);
        }
    );
}

function copycat_process_content(changeOrdinals, oldOrdinal, newOrdinal) {
    return function (content) {
        if (!changeOrdinals) {
            return content;
        }

        return content.replace(new RegExp(oldOrdinal, 'g'), newOrdinal);
    };
}

function copycat_submit(event) {
    var form = event.target;

    // Get parameters
    var newName = form['newName'].value;
    var copyTalk = form['copyTalk'].checked;
    var changeOrdinals = form['changeOrdinals'].checked;
    var newOrdinal = changeOrdinals ? form['changeOrdinals.newOrdinal'].value : null;
    var createParents = changeOrdinals ? form['createParents'].checked : null;

    // Configure actions
    Morebits.status.init(form);
    Morebits.wiki.actionCompleted.redirect = `Category:${newName}`;
    Morebits.wiki.actionCompleted.notice = 'Completed';
    Morebits.wiki.api.setApiUserAgent('Copycat ([[w:User:IceWelder/copycat.js]])');

    // Set up metadata
    var oldName = Morebits.pageNameNorm.replace(/Category:/g, '');
    var oldOrdinal = oldName.replace(/\D*(\d+)?\D*/, '$1');
    var processContent = copycat_process_content(changeOrdinals, oldOrdinal, newOrdinal);

    copycat_copy_page(oldName, newName, processContent, copyTalk, false, createParents);
}

function copycat_show_popup() {
    // Define window
    var dialog = new Morebits.simpleWindow(600, 450);
    dialog.setScriptName('Copycat');
    dialog.setTitle('Copy this category');
    dialog.addFooterLink('Report bug / request feature', 'w:User talk:IceWelder');

    // Define form
    var form = new Morebits.quickForm(copycat_submit);

    var oldName = Morebits.pageNameNorm.replace(/Category:/g, '');
    form.append({
        name: 'newName',
        type: 'input',
        label: 'New name: ',
        value: oldName,
    });

    var oldOrdinal = oldName.replace(/\D*(\d+)?\D*/, '$1');
    form.append({
        type: 'checkbox',
        list: [
            {
                name: 'copyTalk',
                label: 'Also copy talk page',
            },
            {
                name: 'changeOrdinals',
                label: 'Change year ordinals',
                tooltip: 'Changes all ordinals from the old category to the set value for the new category.',
                subgroup: [
                    {
                        name: 'newOrdinal',
                        type: 'input',
                        label: 'New ordinal: ',
                        value: oldOrdinal,
                    },
                    {
                        type: 'checkbox',
                        list: [
                            {
                                name: 'createParents',
                                type: 'input',
                                label: 'Create missing parent categories',
                                tooltip: 'Recursively creates new parent categories where required.',
                                subgroup: [
                                    {
                                        type: 'div',
                                        label: 'Warning: This can create a large number of new categories',
                                    },
                                ],
                            },
                        ],
                    },
                ],
            },
        ],
    });

    form.append({
        type: 'submit',
        label: 'Copy',
    });

    // Display window with form
    var render = form.render();
    dialog.setContent(render);
    dialog.display();
}

// If viewing category
if (mw.config.get('wgNamespaceNumber') === 14 && mw.config.get('wgAction') === 'view') {
    // Wait until article is loaded and MediaWiki utils are ready
    $.when($.ready, mw.loader.using(['mediawiki.util', 'ext.gadget.morebits'])).then(function () {
        // Add portlet link
        $(mw.util.addPortletLink('p-tb', '#', 'Copy this category')).click(copycat_show_popup);
    });
}