MediaWiki:Gadget-twinkleprotect.js: Difference between revisions

m
1 revision imported
(clean up)
m (1 revision imported)
(One intermediate revision by the same user not shown)
Line 26: Line 26:


Twinkle.protect.callback = function twinkleprotectCallback() {
Twinkle.protect.callback = function twinkleprotectCallback() {
Twinkle.protect.protectionLevel = null;
var Window = new Morebits.simpleWindow( 620, 530 );
var Window = new Morebits.simpleWindow( 620, 530 );
Window.setTitle( Morebits.userIsInGroup( 'sysop' ) ? "Apply, request or tag page protection" : "Request or tag page protection" );
Window.setTitle( Morebits.userIsInGroup( 'sysop' ) ? "Apply, request or tag page protection" : "Request or tag page protection" );
Line 89: Line 91:


// get current protection level asynchronously
// get current protection level asynchronously
Morebits.wiki.actionCompleted.postfix = false;  // avoid Action: completed notice
if (Morebits.userIsInGroup('sysop')) {
if (Morebits.userIsInGroup('sysop')) {
var query = {
Morebits.wiki.actionCompleted.postfix = false; // avoid Action: completed notice
action: 'query',
prop: 'info|flagged',
inprop: 'protection',
titles: mw.config.get('wgPageName')
};
Morebits.status.init($('div[name="currentprot"] span').last()[0]);
Morebits.status.init($('div[name="currentprot"] span').last()[0]);
var statelem = new Morebits.status("Current protection level");
var wpapi = new Morebits.wiki.api("retrieving...", query, Twinkle.protect.callback.protectionLevel, statelem);
wpapi.post();
}
}
Twinkle.protect.fetchProtectionLevel();
};
};


Twinkle.protect.protectionLevel = null;
// Current protection level in a human-readable format
// (a string, or null if no protection; only filled for sysops)
Twinkle.protect.protectionLevel = null
// Contains the current protection level in an object
// Once filled, it will look something like:
// { edit: { level: "sysop", expiry: <some date>, cascade: true }, ... }
Twinkle.protect.currentProtectionLevels = {};
 
Twinkle.protect.fetchProtectionLevel = function twinkleprotectFetchProtectionLevel() {
 
var api = new mw.Api();
api.get({
format: 'json',
indexpageids: true,
action: 'query',
prop: 'info|flagged',
inprop: 'protection',
titles: mw.config.get('wgPageName')
})
.done(function(data){
var pageid = data.query.pageids[0];
var page = data.query.pages[pageid];
var result = [];
var current = {};
 
var updateResult = function(label, level, expiry, cascade) {
// for sysops, stringify, so they can base their decision on existing protection
if (Morebits.userIsInGroup('sysop')) {
var boldnode = document.createElement('b');
boldnode.textContent = label + ": " + level;
result.push(boldnode);
if (expiry === 'infinity') {
result.push(" (indefinite) ");
} else {
result.push(" (expires " + new Date(expiry).toUTCString() + ") ");
}
if (cascade) {
result.push("(cascading) ");
}
}
};


Twinkle.protect.callback.protectionLevel = function twinkleprotectCallbackProtectionLevel(apiobj) {
$.each(page.protection, function( index, protection ) {
var xml = apiobj.getXML();
if (protection.type !== "aft") {
var result = [];
current[protection.type] = {
level: protection.level,
expiry: protection.expiry,
cascade: protection.cascade === ''
};
updateResult( Morebits.string.toUpperCaseFirstChar(protection.type), protection.level, protection.expiry, protection.cascade );
}
});


$(xml).find('pr, flagged').each(function(index, protectionEntry) {
if (page.flagged) {
var $protectionEntry = $(protectionEntry);
current.stabilize = {
var type, level, expiry, cascade = false;
level: page.flagged.protection_level,
expiry: page.flagged.protection_expiry
if (protectionEntry.tagName.toLowerCase() === "flagged") {
};
type = "Pending changes";
// FlaggedRevision gives bad date
level = $protectionEntry.attr('protection_level');
updateResult( 'Pending Changes', page.flagged.protection_level, page.flagged.protection_expiry, false );
expiry = $protectionEntry.attr('protection_expiry');
} else {
type = Morebits.string.toUpperCaseFirstChar($protectionEntry.attr('type'));
level = $protectionEntry.attr('level');
expiry = $protectionEntry.attr('expiry');
cascade = $protectionEntry.attr('cascade') === '';
}
}
 
var boldnode = document.createElement('b');
// show the protection level to sysops
boldnode.textContent = type + ": " + level;
if (Morebits.userIsInGroup('sysop')) {
result.push(boldnode);
if (!result.length) {
if (expiry === 'infinity') {
var boldnode = document.createElement('b');
result.push(" (indefinite) ");
boldnode.textContent = "no protection";
} else {
result.push(boldnode);
result.push(" (expires " + new Date(expiry).toUTCString() + ") ");
}
}
Twinkle.protect.protectionLevel = result;
if (cascade) {
Morebits.status.init($('div[name="currentprot"] span').last()[0]);
result.push("(cascading) ");
Morebits.status.info("Current protection level", Twinkle.protect.protectionLevel);
}
}
Twinkle.protect.currentProtectionLevels = current;
});
});
if (!result.length) {
var boldnode = document.createElement('b');
boldnode.textContent = "no protection";
result.push(boldnode);
}
Twinkle.protect.protectionLevel = result;
apiobj.statelem.info(result);
window.setTimeout(function() { Morebits.wiki.actionCompleted.postfix = "completed"; }, 500);  // restore actionCompleted message
};
};


Line 162: Line 190:
label: 'Choose a preset:',
label: 'Choose a preset:',
event: Twinkle.protect.callback.changePreset,
event: Twinkle.protect.callback.changePreset,
list: (mw.config.get('wgArticleId') ?  
list: (mw.config.get('wgArticleId') ?
Twinkle.protect.protectionTypes.filter(function(v) {
Twinkle.protect.protectionTypes.filter(function(v) {
return isTemplate || v.label !== 'Template protection';
return isTemplate || v.label !== 'Template protection';
}) :  
}) :
Twinkle.protect.protectionTypesCreate)
Twinkle.protect.protectionTypesCreate)
});
});
Line 537: Line 565:
if (Twinkle.protect.protectionLevel) {
if (Twinkle.protect.protectionLevel) {
Morebits.status.init($('div[name="currentprot"] span').last()[0]);
Morebits.status.init($('div[name="currentprot"] span').last()[0]);
// seems unneeded
Morebits.status.info("Current protection level", Twinkle.protect.protectionLevel);
//Morebits.status.info("Current protection level", Twinkle.protect.protectionLevel);
}
}


Line 650: Line 677:
}
}
];
];
// A page with both regular and PC protection will be assigned its regular
// protection weight plus 2 (for PC1) or 7 (for PC2)
Twinkle.protect.protectionWeight = {
sysop: 30,
templateeditor: 20,
flaggedrevs_review: 15,  // Pending Changes level 2 protection alone
autoconfirmed: 10,
flaggedrevs_autoconfirmed: 5,  // Pending Changes level 1 protection alone
all: 0,
flaggedrevs_none: 0  // just in case
};


// NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
// NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
Line 662: Line 701:
edit: 'sysop',
edit: 'sysop',
move: 'sysop',
move: 'sysop',
reason: '[[WP:PP#Content disputes|Edit warring / Content dispute]]'
reason: '[[WP:PP#Content disputes|Edit warring / content dispute]]'
},
},
'pp-vandalism': {
'pp-vandalism': {
Line 686: Line 725:
'pp-semi-blp': {
'pp-semi-blp': {
edit: 'autoconfirmed',
edit: 'autoconfirmed',
reason: 'Violations of the [[WP:Biographies of living persons|biographies of living persons policy]]'
reason: 'Violations of the [[WP:BLP|biographies of living persons policy]]',
template: 'pp-blp'
},
},
'pp-semi-usertalk': {
'pp-semi-usertalk': {
edit: 'autoconfirmed',
edit: 'autoconfirmed',
move: 'sysop',
move: 'sysop',
reason: '[[WP:PP#Talk-page protection|Inappropriate use of user talk page while blocked]]'
reason: '[[WP:PP#Talk-page protection|Inappropriate use of user talk page while blocked]]',
template: 'pp-usertalk'
},
},
'pp-semi-template': {  // removed for now
'pp-semi-template': {  // removed for now
Line 701: Line 742:
'pp-semi-sock': {
'pp-semi-sock': {
edit: 'autoconfirmed',
edit: 'autoconfirmed',
reason: 'Persistent [[WP:Sock puppetry|sock puppetry]]'
reason: 'Persistent [[WP:Sock puppetry|sock puppetry]]',
template: 'pp-sock'
},
},
'pp-semi-protected': {
'pp-semi-protected': {
Line 775: Line 817:
},
},
{
{
label: 'Full protection templates',
label: 'Edit protection templates',
list: [
list: [
{ label: '{{pp-vandalism}}: vandalism', value: 'pp-vandalism' },
{ label: '{{pp-dispute}}: dispute/edit war', value: 'pp-dispute', selected: true },
{ label: '{{pp-dispute}}: dispute/edit war', value: 'pp-dispute', selected: true },
{ label: '{{pp-usertalk}}: blocked user talk', value: 'pp-usertalk' }
{ label: '{{pp-blp}}: BLP violations', value: 'pp-blp' },
]
{ label: '{{pp-sock}}: sockpuppetry', value: 'pp-sock' },
},
{
label: 'Full/semi-protection templates',
list: [
{ label: '{{pp-vandalism}}: vandalism', value: 'pp-vandalism' },
{ label: '{{pp-template}}: high-risk template', value: 'pp-template' },
{ label: '{{pp-template}}: high-risk template', value: 'pp-template' },
{ label: '{{pp-protected}}: general protection', value: 'pp-protected' }
{ label: '{{pp-usertalk}}: blocked user talk', value: 'pp-usertalk' },
]
{ label: '{{pp-protected}}: general protection', value: 'pp-protected' },
},
{ label: '{{pp-semi-indef}}: general long-term semi-protection', value: 'pp-semi-indef' }
{
label: 'Semi-protection templates',
list: [
{ label: '{{pp-semi-usertalk}}: blocked user talk', value: 'pp-semi-usertalk' },
{ label: '{{pp-semi-sock}}: sockpuppetry', value: 'pp-semi-sock' },
{ label: '{{pp-semi-blp}}: BLP violations', value: 'pp-semi-blp' },
{ label: '{{pp-semi-indef}}: general long-term', value: 'pp-semi-indef' }
]
]
},
},
Line 916: Line 947:
}
}


var tagparams;
if( actiontype === 'tag' || (actiontype === 'protect' && mw.config.get('wgArticleId')) ) {
if( actiontype === 'tag' || (actiontype === 'protect' && mw.config.get('wgArticleId')) ) {
tagparams = {
tagparams = {
tag: form.tagtype.value,
tag: form.tagtype.value,
reason: ((form.tagtype.value === 'pp-protected' || form.tagtype.value === 'pp-semi-protected' || form.tagtype.value === 'pp-move') && form.protectReason) ? form.protectReason.value : null,
reason: ((form.tagtype.value === 'pp-protected' || form.tagtype.value === 'pp-semi-protected' || form.tagtype.value === 'pp-move') && form.protectReason) ? form.protectReason.value : null,
expiry: (actiontype === 'protect') ? (form.editmodify.checked ? form.editexpiry.value : (form.movemodify.checked ?
expiry: (actiontype === 'protect') ?
form.moveexpiry.value : null)) : null,
(form.editmodify.checked ? form.editexpiry.value :
(form.movemodify.checked ? form.moveexpiry.value :
(form.pcmodify.checked ? form.pcexpiry.value : null)
)
) : null,
small: form.small.checked,
small: form.small.checked,
noinclude: form.noinclude.checked
noinclude: form.noinclude.checked
Line 944: Line 980:
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
}
}
};
var stabilizeValues = {
pclevel: form.pclevel.value,
pcexpiry: form.pcexpiry.value,
protectReason: form.protectReason.value
};
};


Line 957: Line 999:
} else {
} else {
thispage.setCreateProtection(form.createlevel.value, form.createexpiry.value);
thispage.setCreateProtection(form.createlevel.value, form.createexpiry.value);
thispage.setWatchlist(false);
}
}


Line 981: Line 1,024:


thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), "Applying pending changes protection");
thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), "Applying pending changes protection");
thispage.setFlaggedRevs(form.pclevel.value, form.pcexpiry.value);
thispage.setFlaggedRevs(stabilizeValues.pclevel, stabilizeValues.pcexpiry);


if (form.protectReason.value) {
if (stabilizeValues.protectReason) {
thispage.setEditSummary(form.protectReason.value);
thispage.setEditSummary(stabilizeValues.protectReason);
} else {
} else {
alert("You must enter a protect reason, which will be inscribed into the protection log.");
alert("You must enter a protect reason, which will be inscribed into the protection log.");
Line 1,137: Line 1,180:
Morebits.status.init( form );
Morebits.status.init( form );


rppName = 'Sarkarverse:Requests for page protection';
var rppName = 'Wikipedia:Requests for page protection';


// Updating data for the action completed event
// Updating data for the action completed event
Line 1,217: Line 1,260:
var statusElement = rppPage.getStatusElement();
var statusElement = rppPage.getStatusElement();


// TODO Remove me once RPP moves to its new format
var ns2tag = {
var ns2tag = {
'0': 'la',
'0': 'la',
Line 1,237: Line 1,281:
'101': 'lpt',
'101': 'lpt',
'108': 'lb',
'108': 'lb',
'109': 'lbt'
'109': 'lbt',
'118': 'ld',
'119': 'ldt',
'710': 'lttxt',
'711': 'lttxtt',
'828': 'lmd',
'829': 'lmdt'
};
};


// TODO Remove me once RPP moves to its new format
var linkTemplate = ns2tag[ mw.config.get('wgNamespaceNumber') ];
var linkTemplate = ns2tag[ mw.config.get('wgNamespaceNumber') ];
// support other namespaces like TimedText
// support other namespaces like TimedText
Line 1,247: Line 1,298:
}
}


var rppRe = new RegExp( '====\\s*\\{\\{\\s*' + linkTemplate + '\\s*\\|\\s*' + RegExp.escape( mw.config.get('wgTitle'), true ) + '\\s*\\}\\}\\s*====', 'm' );
// TODO Remove both "=?" and the linkTemplate bit when RPP moves to its new format
var rppRe = new RegExp( '====?\\s*((\\[\\[)?\s*:?\s*' + RegExp.escape( Morebits.pageNameNorm, true ) + '\s*(\\]\\])?|\\{\\{\\s*' +
linkTemplate + '\\s*\\|\\s*' + RegExp.escape( mw.config.get('wgTitle'), true ) + '\\s*\\}\\})\\s*====?', 'm' );
var tag = rppRe.exec( text );
var tag = rppRe.exec( text );


var rppLink = document.createElement('a');
var rppLink = document.createElement('a');
rppLink.setAttribute('href', mw.util.wikiGetlink(rppPage.getPageName()) );
rppLink.setAttribute('href', mw.util.getUrl(rppPage.getPageName()) );
rppLink.appendChild(document.createTextNode(rppPage.getPageName()));
rppLink.appendChild(document.createTextNode(rppPage.getPageName()));


Line 1,259: Line 1,312:
}
}


var newtag = '==== {{' + linkTemplate + '|' + mw.config.get('wgTitle') + '}} ====' + "\n";
var newtag = '=== [[:' + Morebits.pageNameNorm + ']] ===\n';
if( ( new RegExp( '^' + RegExp.escape( newtag ).replace( /\s+/g, '\\s*' ), 'm' ) ).test( text ) ) {
if( ( new RegExp( '^' + RegExp.escape( newtag ).replace( /\s+/g, '\\s*' ), 'm' ) ).test( text ) ) {
statusElement.error( [ 'There is already a protection request for this page at ', rppLink, ', aborting.' ] );
statusElement.error( [ 'There is already a protection request for this page at ', rppLink, ', aborting.' ] );
return;
return;
}
}
newtag += '* {{pagelinks|' + Morebits.pageNameNorm + '}}\n\n';


var words;
var words;
Line 1,280: Line 1,334:
words += params.typename;
words += params.typename;


newtag += "'''" + Morebits.string.toUpperCaseFirstChar(words) + ( params.reason !== '' ? ( ":''' " +  
newtag += "'''" + Morebits.string.toUpperCaseFirstChar(words) + ( params.reason !== '' ? ( ":''' " +
Morebits.string.formatReasonText(params.reason) ) : ".'''" ) + " ~~~~";
Morebits.string.formatReasonText(params.reason) ) : ".'''" ) + " ~~~~";
// If either protection type results in a increased status, then post it under increase
// else we post it under decrease
var increase = false;
var protInfo = Twinkle.protect.protectionPresetsInfo[params.category];
// function to compute protection weights (see comment at Twinkle.protect.protectionWeight)
var computeWeight = function(mainLevel, stabilizeLevel) {
var result = Twinkle.protect.protectionWeight[mainLevel || 'all'];
if (stabilizeLevel) {
if (result) {
if (stabilizeLevel.level === "autoconfirmed") {
result += 2;
} else if (stabilizeLevel.level === "review") {
result += 7;
}
} else {
result = Twinkle.protect.protectionWeight["flaggedrevs_" + stabilizeLevel];
}
}
return result;
};
// compare the page's current protection weights with the protection we are requesting
var editWeight = computeWeight(Twinkle.protect.currentProtectionLevels.edit &&
Twinkle.protect.currentProtectionLevels.edit.level,
Twinkle.protect.currentProtectionLevels.stabilize &&
Twinkle.protect.currentProtectionLevels.stabilize.level);
if (computeWeight(protInfo.edit, protInfo.stabilize) > editWeight ||
computeWeight(protInfo.move) > computeWeight(Twinkle.protect.currentProtectionLevels.move &&
Twinkle.protect.currentProtectionLevels.move.level) ||
computeWeight(protInfo.create) > computeWeight(Twinkle.protect.currentProtectionLevels.create &&
Twinkle.protect.currentProtectionLevels.create.level)) {
increase = true;
}


var reg;
var reg;
if ( params.category === 'unprotect' ) {
if ( increase ) {
reg = /(\n==\s*Current requests for unprotection\s*==\s*\n\s*\{\{[^\}\}]+\}\}\s*\n)/;
reg = /(\n==\s*Current requests for increase in protection level\s*==\s*\n\s*\{\{[^\}\}]+\}\}\s*\n)([\s\S]*?)\s*(\n==[^=])/;
} else {
} else {
reg = /(\n==\s*Current requests for protection\s*==\s*\n\s*\{\{[^\}\}]+\}\}\s*\n)/;
reg = /(\n==\s*Current requests for reduction in protection level\s*==\s*\n\s*\{\{[^\}\}]+\}\}\s*\n)([\s\S]*?)\s*(\n==[^=])/;
}
}
var originalTextLength = text.length;
var originalTextLength = text.length;
text = text.replace( reg, "$1" + newtag + "\n");
text = text.replace( reg, "$1$2\n\n" + newtag + "\n$3");
if (text.length === originalTextLength)
if (text.length === originalTextLength)
{
{
var linknode = document.createElement('a');
var linknode = document.createElement('a');
linknode.setAttribute("href", mw.util.wikiGetlink("Sarkarverse:Twinkle/Fixing RPP") );
linknode.setAttribute("href", mw.util.getUrl("Wikipedia:Twinkle/Fixing RPP") );
linknode.appendChild(document.createTextNode('How to fix RPP'));
linknode.appendChild(document.createTextNode('How to fix RPP'));
statusElement.error( [ 'Could not find relevant heading on WP:RPP. To fix this problem, please see ', linknode, '.' ] );
statusElement.error( [ 'Could not find relevant heading on WP:RPP. To fix this problem, please see ', linknode, '.' ] );