MediaWiki:Gadget-twinkleprotect.js
Giao diện
Twinkle
Tiện ích Twinkle được phát triển trên GitHub. Phiên bản dành cho Wikipedia tiếng Việt cũng được biên dịch và bảo quản trên GitHub. Xin các bảo quản viên vui lòng thực hiện các thay đổi trong cành vi trên GitHub và sao chép vào đây thay vì sửa đổi tiện ích này trực tiếp. |
// <nowiki>
(function($) {
/*
****************************************
*** twinkleprotect.js: Protect/RPP module
****************************************
* Mode of invocation: Tab ("Khóa"/"Yêu cầu khóa")
* Active on: Non-special, non-MediaWiki pages
*/
// Note: a lot of code in this module is re-used/called by batchprotect.
Twinkle.protect = function twinkleprotect() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgNamespaceNumber') === 8) {
return;
}
Twinkle.addPortletLink(Twinkle.protect.callback, (Morebits.userIsSysop || Morebits.userIsInGroup('eliminator')) ? 'Khóa trang' : 'Yêu cầu khóa trang', 'tw-rpp',
(Morebits.userIsSysop || Morebits.userIsInGroup('eliminator')) ? 'Khóa trang' : 'Yêu cầu khóa trang');
};
Twinkle.protect.callback = function twinkleprotectCallback() {
var Window = new Morebits.simpleWindow(620, 530);
Window.setTitle((Morebits.userIsSysop || Morebits.userIsInGroup('eliminator')) ? 'Khóa trang, yêu cầu hoặc thêm bản mẫu khóa trang' : 'Yêu cầu hoặc thêm bản mẫu khóa trang');
Window.setScriptName('Twinkle');
Window.addFooterLink('Các bản mẫu khóa trang', 'Template:Protection templates');
Window.addFooterLink('Quy định khóa trang', 'WP:PROT');
Window.addFooterLink('Trợ giúp Twinkle', 'WP:TW/DOC#protect');
var form = new Morebits.quickForm(Twinkle.protect.callback.evaluate);
var actionfield = form.append({
type: 'field',
label: 'Loại tác vụ'
});
if (Morebits.userIsSysop || Morebits.userIsInGroup('eliminator')) {
actionfield.append({
type: 'radio',
name: 'actiontype',
event: Twinkle.protect.callback.changeAction,
list: [
{
label: 'Khóa trang',
value: 'protect',
tooltip: 'Thiết lập khóa trang.',
checked: true
}
]
});
}
actionfield.append({
type: 'radio',
name: 'actiontype',
event: Twinkle.protect.callback.changeAction,
list: [
{
label: 'Yêu cầu khóa trang',
value: 'request',
tooltip: 'Nếu bạn muốn đề nghị khóa trang WP:Khóa trang' + ((Morebits.userIsSysop || Morebits.userIsInGroup('eliminator')) ? ' thay vì bạn có thể tự thực hiện.' : '.'),
checked: !(Morebits.userIsSysop || Morebits.userIsInGroup('eliminator'))
},
{
label: 'Thêm bản mẫu khóa trang',
value: 'tag',
tooltip: 'Nếu bảo quản viên quên thêm bản mẫu khóa trang, hoặc bạn vừa khóa một trang mà chưa thêm bản mẫu, bạn có thể sử dụng tag này ở những trang tương ứng.',
disabled: mw.config.get('wgArticleId') === 0 || mw.config.get('wgPageContentModel') === 'Scribunto'
}
]
});
form.append({ type: 'field', label: 'Preset', name: 'field_preset' });
form.append({ type: 'field', label: '1', name: 'field1' });
form.append({ type: 'field', label: '2', name: 'field2' });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// We must init the controls
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.actiontype[0].dispatchEvent(evt);
// get current protection level asynchronously
Twinkle.protect.fetchProtectionLevel();
};
// A list of bots who may be the protecting sysop, for whom we shouldn't
// remind the user contact before requesting unprotection (evaluate)
Twinkle.protect.trustedBots = ['MusikBot II', 'TFA Protector Bot'];
// Customizable namespace and FlaggedRevs settings
// In theory it'd be nice to have restrictionlevels defined here,
// but those are only available via a siteinfo query
// mw.loader.getState('ext.flaggedRevs.review') returns null if the
// FlaggedRevs extension is not registered. Previously, this was done with
// wgFlaggedRevsParams, but after 1.34-wmf4 it is no longer exported if empty
// (https://gerrit.wikimedia.org/r/c/mediawiki/extensions/FlaggedRevs/+/508427)
var hasFlaggedRevs = mw.loader.getState('ext.flaggedRevs.review') &&
// FlaggedRevs only valid in some namespaces, hardcoded until [[phab:T218479]]
(mw.config.get('wgNamespaceNumber') === 0 || mw.config.get('wgNamespaceNumber') === 4);
// Limit template editor; a Twinkle restriction, not a site setting
var isTemplate = mw.config.get('wgNamespaceNumber') === 10 || mw.config.get('wgNamespaceNumber') === 828;
// 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 = {};
// returns a jQuery Deferred object, usage:
// Twinkle.protect.fetchProtectingAdmin(apiObject, pageName, protect/stable).done(function(admin_username) { ...code... });
Twinkle.protect.fetchProtectingAdmin = function twinkleprotectFetchProtectingAdmin(api, pageName, protType, logIds) {
logIds = logIds || [];
return api.get({
format: 'json',
action: 'query',
list: 'logevents',
letitle: pageName,
letype: protType
}).then(function(data) {
// don't check log entries that have already been checked (e.g. don't go into an infinite loop!)
var event = data.query ? $.grep(data.query.logevents, function(le) {
return $.inArray(le.logid, logIds);
})[0] : null;
if (!event) {
// fail gracefully
return null;
} else if (event.action === 'move_prot' || event.action === 'move_stable') {
return twinkleprotectFetchProtectingAdmin(api, protType === 'protect' ? event.params.oldtitle_title : event.params.oldtitle, protType, logIds.concat(event.logid));
}
return event.user;
});
};
Twinkle.protect.fetchProtectionLevel = function twinkleprotectFetchProtectionLevel() {
var api = new mw.Api();
var protectDeferred = api.get({
format: 'json',
indexpageids: true,
action: 'query',
list: 'logevents',
letype: 'protect',
letitle: mw.config.get('wgPageName'),
prop: hasFlaggedRevs ? 'info|flagged' : 'info',
inprop: 'protection',
titles: mw.config.get('wgPageName')
});
var stableDeferred = api.get({
format: 'json',
action: 'query',
list: 'logevents',
letype: 'stable',
letitle: mw.config.get('wgPageName')
});
var earlyDecision = [protectDeferred];
if (hasFlaggedRevs) {
earlyDecision.push(stableDeferred);
}
$.when.apply($, earlyDecision).done(function(protectData, stableData) {
// $.when.apply is supposed to take an unknown number of promises
// via an array, which it does, but the type of data returned varies.
// If there are two or more deferreds, it returns an array (of objects),
// but if there's just one deferred, it retuns a simple object.
// This is annoying.
protectData = $(protectData).toArray();
var pageid = protectData[0].query.pageids[0];
var page = protectData[0].query.pages[pageid];
var current = {}, adminEditDeferred;
$.each(page.protection, function(index, protection) {
if (protection.type !== 'aft') {
current[protection.type] = {
level: protection.level,
expiry: protection.expiry,
cascade: protection.cascade === ''
};
// logs report last admin who made changes to either edit/move/create protection, regardless if they only modified one of them
if (!adminEditDeferred) {
adminEditDeferred = Twinkle.protect.fetchProtectingAdmin(api, mw.config.get('wgPageName'), 'protect');
}
}
});
if (page.flagged) {
current.stabilize = {
level: page.flagged.protection_level,
expiry: page.flagged.protection_expiry
};
adminEditDeferred = Twinkle.protect.fetchProtectingAdmin(api, mw.config.get('wgPageName'), 'stable');
}
// show the protection level and log info
Twinkle.protect.hasProtectLog = !!protectData[0].query.logevents.length;
Twinkle.protect.hasStableLog = hasFlaggedRevs ? !!stableData[0].query.logevents.length : false;
Twinkle.protect.currentProtectionLevels = current;
if (adminEditDeferred) {
adminEditDeferred.done(function(admin) {
if (admin) {
$.each(['edit', 'move', 'create', 'stabilize'], function(i, type) {
if (Twinkle.protect.currentProtectionLevels[type]) {
Twinkle.protect.currentProtectionLevels[type].admin = admin;
}
});
}
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
});
} else {
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
}
});
};
Twinkle.protect.callback.showLogAndCurrentProtectInfo = function twinkleprotectCallbackShowLogAndCurrentProtectInfo() {
var currentlyProtected = !$.isEmptyObject(Twinkle.protect.currentProtectionLevels);
if (Twinkle.protect.hasProtectLog || Twinkle.protect.hasStableLog) {
var $linkMarkup = $('<span>');
if (Twinkle.protect.hasProtectLog) {
$linkMarkup.append(
$('<a target="_blank" href="' + mw.util.getUrl('Special:Log', {action: 'view', page: mw.config.get('wgPageName'), type: 'protect'}) + '">nhật trình khóa</a>'),
Twinkle.protect.hasStableLog ? $('<span> • </span>') : null
);
}
if (Twinkle.protect.hasStableLog) {
$linkMarkup.append($('<a target="_blank" href="' + mw.util.getUrl('Special:Log', {action: 'view', page: mw.config.get('wgPageName'), type: 'stable'}) + '">pending changes log</a>)'));
}
Morebits.status.init($('div[name="hasprotectlog"] span')[0]);
Morebits.status.warn(
currentlyProtected ? 'Các mức khóa trước' : 'Trang này đã được khóa trong quá khứ',
$linkMarkup[0]
);
}
Morebits.status.init($('div[name="currentprot"] span')[0]);
var protectionNode = [], statusLevel = 'info';
if (currentlyProtected) {
$.each(Twinkle.protect.currentProtectionLevels, function(type, settings) {
var label = type === 'stabilize' ? 'Các thay đổi đang chờ xử lý' : Morebits.string.toUpperCaseFirstChar(type);
protectionNode.push($('<b>' + label + ': ' + settings.level + '</b>')[0]);
if (settings.expiry === 'infinity') {
protectionNode.push(' (vô hạn) ');
} else {
protectionNode.push(' (hết hạn ' + new Date(settings.expiry).toUTCString() + ') ');
}
if (settings.cascade) {
protectionNode.push('(theo tầng) ');
}
if (settings.admin) {
var adminLink = '<a target="_blank" href="' + mw.util.getUrl('User talk:' + settings.admin) + '">' + settings.admin + '</a>';
protectionNode.push($('<span>bởi ' + adminLink + ' </span>')[0]);
}
protectionNode.push($('<span> \u2022 </span>')[0]);
});
protectionNode = protectionNode.slice(0, -1); // remove the trailing bullet
statusLevel = 'warn';
} else {
protectionNode.push($('<b>không khóa</b>')[0]);
}
Morebits.status[statusLevel]('Mức độ khóa hiện tại', protectionNode);
};
Twinkle.protect.callback.changeAction = function twinkleprotectCallbackChangeAction(e) {
var field_preset;
var field1;
var field2;
switch (e.target.values) {
case 'protect':
field_preset = new Morebits.quickForm.element({ type: 'field', label: 'Thiết lập', name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'category',
label: 'Chọn một thiết lập trước:',
event: Twinkle.protect.callback.changePreset,
list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate
});
field2 = new Morebits.quickForm.element({ type: 'field', label: 'Các tùy chọn khóa', name: 'field2' });
field2.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field2.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
// for existing pages
if (mw.config.get('wgArticleId')) {
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.editmodify,
list: [
{
label: 'Thay đổi mức khóa sửa đổi',
name: 'editmodify',
tooltip: 'Nếu tắt tính năng này, mức khóa sửa đổi và thời gian hết hạn sẽ được giữ nguyên.',
checked: true
}
]
});
field2.append({
type: 'select',
name: 'editlevel',
label: 'Khóa sửa đổi:',
event: Twinkle.protect.formevents.editlevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Filter TE outside of templates and modules
return isTemplate || level.value !== 'templateeditor';
})
});
field2.append({
type: 'select',
name: 'editexpiry',
label: 'Thời gian hết hạn:',
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (2 days) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.movemodify,
list: [
{
label: 'Thay đổi mức khóa di chuyển trang',
name: 'movemodify',
tooltip: 'Nếu tắt tính năng này, mức khoa di chuyển trang và thời gian hết hạn sẽ được giữ nguyên.',
checked: true
}
]
});
field2.append({
type: 'select',
name: 'movelevel',
label: 'Khóa di chuyển trang:',
event: Twinkle.protect.formevents.movelevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Autoconfirmed is required for a move, redundant
return level.value !== 'autoconfirmed' && (isTemplate || level.value !== 'templateeditor');
})
});
field2.append({
type: 'select',
name: 'moveexpiry',
label: 'Thời gian hết hạn:',
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (2 days) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
if (hasFlaggedRevs) {
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.pcmodify,
list: [
{
label: 'Chỉnh sửa mức khóa các thay đổi đang chờ xử lý',
name: 'pcmodify',
tooltip: 'Nếu tắt tính năng này, mức thay đổi đang chờ xử lý và thời gian hết hạn sẽ được giữ nguyên.',
checked: true
}
]
});
field2.append({
type: 'select',
name: 'pclevel',
label: 'Các thay đổi đang chờ xử lý:',
event: Twinkle.protect.formevents.pclevel,
list: [
{ label: 'None', value: 'none' },
{ label: 'Thay đổi đang chờ xử lý', value: 'autoconfirmed', selected: true }
]
});
field2.append({
type: 'select',
name: 'pcexpiry',
label: 'Thời gian hết hạn:',
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (1 month) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
}
} else { // for non-existing pages
field2.append({
type: 'select',
name: 'createlevel',
label: 'Tạo khóa:',
event: Twinkle.protect.formevents.createlevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Filter TE always, and autoconfirmed in mainspace, redundant since WP:ACPERM
return level.value !== 'templateeditor' && (mw.config.get('wgNamespaceNumber') !== 0 || level.value !== 'autoconfirmed');
})
});
field2.append({
type: 'select',
name: 'createexpiry',
label: 'Thời gian hết hạn:',
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (indefinite) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
}
field2.append({
type: 'textarea',
name: 'protectReason',
label: 'Lý do (cho nhật trình khóa):'
});
if (!mw.config.get('wgArticleId') || mw.config.get('wgPageContentModel') === 'Scribunto') { // tagging isn't relevant for non-existing or module pages
break;
}
/* falls through */
case 'tag':
field1 = new Morebits.quickForm.element({ type: 'field', label: 'Các tùy chọn gắn thẻ', name: 'field1' });
field1.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
field1.append({
type: 'select',
name: 'tagtype',
label: 'Chọn bản mẫu khóa:',
list: Twinkle.protect.protectionTags,
event: Twinkle.protect.formevents.tagtype
});
field1.append({
type: 'checkbox',
list: [
{
name: 'small',
label: 'Biểu tượng khóa (small=yes)',
tooltip: 'Sẽ sử dụng tính năng |small=yes của bản mẫu, và chỉ hiển thị nó dưới dạng một keylock',
checked: true
},
{
name: 'noinclude',
label: 'Bọc bản mẫu khóa lại với thẻ <noinclude>',
tooltip: 'Sẽ bọc bản mẫu khóa bên trong thẻ <noinclude>, vì vậy bản mẫu khóa sẽ không được nhúng vào nội dung',
checked: mw.config.get('wgNamespaceNumber') === 10
}
]
});
break;
case 'request':
field_preset = new Morebits.quickForm.element({ type: 'field', label: 'Loại khóa', name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'category',
label: 'Loại và lý do:',
event: Twinkle.protect.callback.changePreset,
list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate
});
field1 = new Morebits.quickForm.element({ type: 'field', label: 'Tùy chọn', name: 'field1' });
field1.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
field1.append({
type: 'select',
name: 'expiry',
label: 'Thời gian: ',
list: [
{ label: '', selected: true, value: '' },
{ label: 'Tạm thời', value: 'temporary' },
{ label: 'Vô thời hạn', value: 'infinity' }
]
});
field1.append({
type: 'textarea',
name: 'reason',
label: 'Lý do: '
});
break;
default:
alert("Có gì đó đang xảy ra trong twinkleprotect");
break;
}
var oldfield;
if (field_preset) {
oldfield = $(e.target.form).find('fieldset[name="field_preset"]')[0];
oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field_preset"]').css('display', 'none');
}
if (field1) {
oldfield = $(e.target.form).find('fieldset[name="field1"]')[0];
oldfield.parentNode.replaceChild(field1.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field1"]').css('display', 'none');
}
if (field2) {
oldfield = $(e.target.form).find('fieldset[name="field2"]')[0];
oldfield.parentNode.replaceChild(field2.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field2"]').css('display', 'none');
}
if (e.target.values === 'protect') {
// fake a change event on the preset dropdown
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
e.target.form.category.dispatchEvent(evt);
// reduce vertical height of dialog
$(e.target.form).find('fieldset[name="field2"] select').parent().css({ display: 'inline-block', marginRight: '0.5em' });
}
// re-add protection level and log info, if it's available
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
};
// NOTE: This function is used by batchprotect as well
Twinkle.protect.formevents = {
editmodify: function twinkleprotectFormEditmodifyEvent(e) {
e.target.form.editlevel.disabled = !e.target.checked;
e.target.form.editexpiry.disabled = !e.target.checked || (e.target.form.editlevel.value === 'all');
e.target.form.editlevel.style.color = e.target.form.editexpiry.style.color = e.target.checked ? '' : 'transparent';
},
editlevel: function twinkleprotectFormEditlevelEvent(e) {
e.target.form.editexpiry.disabled = e.target.value === 'all';
},
movemodify: function twinkleprotectFormMovemodifyEvent(e) {
// sync move settings with edit settings if applicable
if (e.target.form.movelevel.disabled && !e.target.form.editlevel.disabled) {
e.target.form.movelevel.value = e.target.form.editlevel.value;
e.target.form.moveexpiry.value = e.target.form.editexpiry.value;
} else if (e.target.form.editlevel.disabled) {
e.target.form.movelevel.value = 'sysop';
e.target.form.moveexpiry.value = 'infinity';
}
e.target.form.movelevel.disabled = !e.target.checked;
e.target.form.moveexpiry.disabled = !e.target.checked || (e.target.form.movelevel.value === 'all');
e.target.form.movelevel.style.color = e.target.form.moveexpiry.style.color = e.target.checked ? '' : 'transparent';
},
movelevel: function twinkleprotectFormMovelevelEvent(e) {
e.target.form.moveexpiry.disabled = e.target.value === 'all';
},
pcmodify: function twinkleprotectFormPcmodifyEvent(e) {
e.target.form.pclevel.disabled = !e.target.checked;
e.target.form.pcexpiry.disabled = !e.target.checked || (e.target.form.pclevel.value === 'none');
e.target.form.pclevel.style.color = e.target.form.pcexpiry.style.color = e.target.checked ? '' : 'transparent';
},
pclevel: function twinkleprotectFormPclevelEvent(e) {
e.target.form.pcexpiry.disabled = e.target.value === 'none';
},
createlevel: function twinkleprotectFormCreatelevelEvent(e) {
e.target.form.createexpiry.disabled = e.target.value === 'all';
},
tagtype: function twinkleprotectFormTagtypeEvent(e) {
e.target.form.small.disabled = e.target.form.noinclude.disabled = (e.target.value === 'none') || (e.target.value === 'noop');
}
};
Twinkle.protect.doCustomExpiry = function twinkleprotectDoCustomExpiry(target) {
var custom = prompt('Nhập thời gian hết hạn có thể tùy chỉnh. \nBạn có thể sử dụng thời gian tương đối, chẳng hạn "1 minute" hay "19 days", hoặc nhãn thời gian tuyệt đối, "yyyymmddhhmm" (ví dụ "200602011405" là ngày 1 tháng 2 năm 2006, lúc 14:05 UTC).', '');
if (custom) {
var option = document.createElement('option');
option.setAttribute('value', custom);
option.textContent = custom;
target.appendChild(option);
target.value = custom;
} else {
target.selectedIndex = 0;
}
};
// NOTE: This list is used by batchprotect as well
Twinkle.protect.protectionLevels = [
{ label: 'Tất cả', value: 'all' },
{ label: 'Thành viên tự xác nhận', value: 'autoconfirmed' },
{ label: 'Thành viên xác nhận mở rộng', value: 'extendedconfirmed' },
{ label: 'Kỹ thuật viên bản mẫu', value: 'templateeditor' },
{ label: 'Bảo quản viên', value: 'sysop', selected: true }
];
// default expiry selection is conditionally set in Twinkle.protect.callback.changePreset
// NOTE: This list is used by batchprotect as well
Twinkle.protect.protectionLengths = [
{ label: '1 giờ', value: '1 hour' },
{ label: '2 giờ', value: '2 hours' },
{ label: '3 giờ', value: '3 hours' },
{ label: '6 giờ', value: '6 hours' },
{ label: '12 giờ', value: '12 hours' },
{ label: '1 ngày', value: '1 day' },
{ label: '2 ngày', value: '2 days' },
{ label: '3 ngày', value: '3 days' },
{ label: '4 ngày', value: '4 days' },
{ label: '1 tuần', value: '1 week' },
{ label: '2 tuần', value: '2 weeks' },
{ label: '1 tháng', value: '1 month' },
{ label: '2 tháng', value: '2 months' },
{ label: '3 tháng', value: '3 months' },
{ label: '1 năm', value: '1 year' },
{ label: 'Vô hạn', value: 'infinity' },
{ label: 'Tùy chỉnh...', value: 'custom' }
];
Twinkle.protect.protectionTypes = [
{ label: 'Không khóa', value: 'unprotect' },
{
label: 'Khóa hoàn toàn',
list: [
{ label: 'Chung (hoàn toàn)', value: 'pp-protected' },
{ label: 'Tranh chấp nội dung/bút chiến (hoàn toàn)', value: 'pp-dispute' },
{ label: 'Phá hoại dai dẳng (hoàn toàn)', value: 'pp-vandalism' },
{ label: 'Trang Thảo luận Thành viên của thành viên bị cấm (hoàn toàn)', value: 'pp-usertalk' }
]
},
{
label: 'Khóa bản mẫu',
list: [
{ label: 'Bản mẫu nhiều người xem (TE)', value: 'pp-template' }
]
},
{
label: 'Khóa xác nhận mở rộng',
list: [
// { label: 'Tuân theo Ủy ban Trọng tài (ECP)', value: 'pp-30-500-arb' }, // viwiki không cần
{ label: 'Phá hoại dai dẳng (ECP)', selected: true, value: 'pp-30-500-vandalism' },
{ label: 'Sửa đổi phá hoại (ECP)', value: 'pp-30-500-disruptive' },
{ label: 'Vi phạm chính sách BLP (tiểu sử người còn sống) (ECP)', value: 'pp-30-500-blp' },
{ label: 'Con rối (ECP)', value: 'pp-30-500-sock' }
]
},
{
label: 'Bán khóa',
list: [
{ label: 'Chung (bán khóa)', value: 'pp-semi-protected' },
{ label: 'Phá hoại dai dẳng (bán khóa)', selected: true, value: 'pp-semi-vandalism' },
{ label: 'Sửa đổi phá hoại (bán khóa)', value: 'pp-semi-disruptive' },
{ label: 'Thêm nội dung không nguồn (bán khóa)', value: 'pp-semi-unsourced' },
{ label: 'Vi phạm chính sách BLP (tiểu sử người còn sống) (bán khóa)', value: 'pp-semi-blp' },
{ label: 'Con rối (bán khóa)', value: 'pp-semi-sock' },
{ label: 'Trang Thảo luận Thành viên của thành viên bị cấm (bán khóa)', value: 'pp-semi-usertalk' }
]
},
// {
// label: 'Thay đổi đang chờ xử lý',
// list: [
// { label: 'Chung (PC)', value: 'pp-pc-protected' },
// { label: 'Phá hoại dai dẳng (PC)', value: 'pp-pc-vandalism' },
// { label: 'Sửa đổi phá hoại (PC)', value: 'pp-pc-disruptive' },
// { label: 'Thêm nội dung không nguồn (PC)', value: 'pp-pc-unsourced' },
// { label: 'Vi phạm chính sách BLP (tiểu sử người còn sống) (PC)', value: 'pp-pc-blp' }
// ]
// },
{
label: 'Khóa di chuyển trang',
list: [
{ label: 'Chung (di chuyển)', value: 'pp-move' },
{ label: 'Tranh chấp di chuyển trang (di chuyển)', value: 'pp-move-dispute' },
{ label: 'Phá hoại di chuyển trang (di chuyển)', value: 'pp-move-vandalism' },
{ label: 'Trang nhiều người xem (di chuyển)', value: 'pp-move-indef' }
]
}
].filter(function(type) {
// Filter for templates and flaggedrevs
return (isTemplate || type.label !== 'Template protection') && (hasFlaggedRevs || type.label !== 'Pending changes');
});
Twinkle.protect.protectionTypesCreate = [
{ label: 'Không khóa', value: 'unprotect' },
{
label: 'Tạo khóa',
list: [
{ label: 'Chung ({{pp-create}})', value: 'pp-create' },
{ label: 'Tên xúc phạm', value: 'pp-create-offensive' },
{ label: 'Tạo lại nội dung nhiều lần', selected: true, value: 'pp-create-salt' },
{ label: 'Tiểu sử người còn sống (BLP) đã xóa gần đây', value: 'pp-create-blp' }
]
}
];
// A page with both regular and PC protection will be assigned its regular
// protection weight plus 2
Twinkle.protect.protectionWeight = {
sysop: 40,
templateeditor: 30,
extendedconfirmed: 20,
autoconfirmed: 10,
flaggedrevs_autoconfirmed: 5, // Pending Changes protection alone
all: 0,
flaggedrevs_none: 0 // just in case
};
// NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
// Also note: stabilize = Pending Changes level
// expiry will override any defaults
Twinkle.protect.protectionPresetsInfo = {
'pp-protected': {
edit: 'sysop',
move: 'sysop',
reason: null
},
'pp-dispute': {
edit: 'sysop',
move: 'sysop',
reason: '[[Wikipedia:Quy định khóa trang|Bút chiến / Nội dung tranh cãi]]'
},
'pp-vandalism': {
edit: 'sysop',
move: 'sysop',
reason: '[[WP:Vandalism|Phá hoại]] thường xuyên'
},
'pp-usertalk': {
edit: 'sysop',
move: 'sysop',
expiry: 'infinity',
reason: '[[Wikipedia:Quy định khóa trang|Sử dụng trang thảo luận của người dùng không phù hợp khi bị khóa]]'
},
'pp-template': {
edit: 'templateeditor',
move: 'templateeditor',
expiry: 'infinity',
reason: '[[WP:High-risk templates|Bản mẫu nhiều người xem]]'
},
'pp-30-500-arb': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
expiry: 'infinity',
reason: '[[WP:30/500|Tuân theo Ủy ban Trọng tài]]',
template: 'pp-30-500'
},
'pp-30-500-vandalism': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: '[[WP:Vandalism|Phá hoại]] thường xuyên từ tài khoản được xác nhận (tự động)',
template: 'pp-30-500'
},
'pp-30-500-disruptive': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: '[[WP:Disruptive editing|Sửa đổi phá hoại]] thường xuyên từ tài khoản được xác nhận (tự động)',
template: 'pp-30-500'
},
'pp-30-500-blp': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: 'Liên tục vi phạm [[Wikipedia:Tiểu sử người đang sống]] từ tài khoản được xác nhận (tự động)',
template: 'pp-30-500'
},
'pp-30-500-sock': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: '[[Wikipedia:Tài khoản con rối]] thường xuyên',
template: 'pp-30-500'
},
'pp-semi-vandalism': {
edit: 'autoconfirmed',
reason: '[[WP:Vandalism|Phá hoại]] thường xuyên',
template: 'pp-vandalism'
},
'pp-semi-disruptive': {
edit: 'autoconfirmed',
reason: '[[WP:Disruptive editing|Sửa đổi phá hoại]] thường xuyên',
template: 'pp-protected'
},
'pp-semi-unsourced': {
edit: 'autoconfirmed',
reason: 'Thêm thường xuyên [[WP:INTREF|nội dung không nguồn hoặc nguồn yếu]]',
template: 'pp-protected'
},
'pp-semi-blp': {
edit: 'autoconfirmed',
reason: 'Vi phạm chính sách [[Wikipedia:Tiểu sử người đang sống]]',
template: 'pp-blp'
},
'pp-semi-usertalk': {
edit: 'autoconfirmed',
move: 'autoconfirmed',
expiry: 'infinity',
reason: '[[Wikipedia:Quy định khóa trang|Sử dụng trang thảo luận của người dùng không phù hợp khi bị cấm]]',
template: 'pp-usertalk'
},
'pp-semi-template': { // removed for now
edit: 'autoconfirmed',
move: 'autoconfirmed',
expiry: 'infinity',
reason: '[[WP:High-risk templates|Bản mẫu nhiều người xem]]',
template: 'pp-template'
},
'pp-semi-sock': {
edit: 'autoconfirmed',
reason: '[[Wikipedia:Tài khoản con rối]] thường xuyên',
template: 'pp-sock'
},
'pp-semi-protected': {
edit: 'autoconfirmed',
reason: null,
template: 'pp-protected'
},
'pp-pc-vandalism': {
stabilize: 'autoconfirmed', // stabilize = Pending Changes
reason: '[[WP:Vandalism|Phá hoại]] thường xuyên',
template: 'pp-pc'
},
'pp-pc-disruptive': {
stabilize: 'autoconfirmed',
reason: '[[WP:Disruptive editing|Sửa đổi phá hoại]] thường xuyên',
template: 'pp-pc'
},
'pp-pc-unsourced': {
stabilize: 'autoconfirmed',
reason: 'Thêm thường xuyên [[WP:INTREF|nội dung không nguồn hoặc nguồn yếu]]',
template: 'pp-pc'
},
'pp-pc-blp': {
stabilize: 'autoconfirmed',
reason: 'Vi phạm chính sách [[Wikipedia:Tiểu sử người đang sống]]',
template: 'pp-pc'
},
'pp-pc-protected': {
stabilize: 'autoconfirmed',
reason: null,
template: 'pp-pc'
},
'pp-move': {
move: 'sysop',
reason: null
},
'pp-move-dispute': {
move: 'sysop',
reason: '[[WP:MOVP|Tranh chấp di chuyển trang]]'
},
'pp-move-vandalism': {
move: 'sysop',
reason: '[[WP:MOVP|Phá hoại di chuyển trang]'
},
'pp-move-indef': {
move: 'sysop',
expiry: 'infinity',
reason: '[[WP:MOVP|Trang nhiều người xem]]'
},
'unprotect': {
edit: 'all',
move: 'all',
stabilize: 'none',
create: 'all',
reason: null,
template: 'none'
},
'pp-create-offensive': {
create: 'sysop',
reason: '[[WP:SALT|Tên xúc phạm]]'
},
'pp-create-salt': {
create: 'extendedconfirmed',
reason: '[[WP:SALT|Tạo lại nội dung nhiều lần]]'
},
'pp-create-blp': {
create: 'extendedconfirmed',
reason: '[[WP:BLPDEL|Tiểu sử người còn sống (BLP) đã xóa gần đây]]'
},
'pp-create': {
create: 'extendedconfirmed',
reason: '{{pp-create}}'
}
};
Twinkle.protect.protectionTags = [
{
label: 'Không có bản mẫu (xóa các bản mẫu khóa hiện có)',
value: 'none'
},
{
label: 'Không có bản mẫu (không xóa các bản mẫu khóa hiện có)',
value: 'noop'
},
{
label: 'Chỉnh sửa các bản mẫu khóa',
list: [
{ label: '{{pp-vandalism}}: phá hoại', value: 'pp-vandalism' },
{ label: '{{pp-dispute}}: tranh cãi/bút chiến', value: 'pp-dispute' },
{ label: '{{pp-blp}}: Vi phạm BLP', value: 'pp-blp' },
{ label: '{{pp-sock}}: con rối', value: 'pp-sock' },
{ label: '{{pp-template}}: bản mẫu có nguy cơ cao bị phá hoại', value: 'pp-template' },
{ label: '{{pp-usertalk}}: Thảo luận người dùng bị cấm', value: 'pp-usertalk' },
{ label: '{{pp-protected}}: khóa chung', value: 'pp-protected' },
{ label: '{{pp-semi-indef}}: bán khóa chung dài hạn', value: 'pp-semi-indef' },
{ label: '{{pp-30-500}}: khóa xác nhận mở rộng', value: 'pp-30-500' }
]
},
{
label: 'Các bản mẫu thay đổi đang chờ xử lý',
list: [
{ label: '{{pp-pc}}: các thay đổi đang chờ xử lý', value: 'pp-pc' }
]
},
{
label: 'Các bản mẫu khóa di chuyển trang',
list: [
{ label: '{{pp-move-dispute}}: tranh chấp di chuyển trang', value: 'pp-move-dispute' },
{ label: '{{pp-move-vandalism}}: phá hoại di chuyển trang', value: 'pp-move-vandalism' },
{ label: '{{pp-move-indef}}: dài hạn chung', value: 'pp-move-indef' },
{ label: '{{pp-move}}: khác', value: 'pp-move' }
]
}
].filter(function(type) {
// Filter FlaggedRevs
return hasFlaggedRevs || type.label !== 'Các bản mẫu thay đổi đang chờ xử lý';
});
Twinkle.protect.callback.changePreset = function twinkleprotectCallbackChangePreset(e) {
var form = e.target.form;
var actiontypes = form.actiontype;
var actiontype;
for (var i = 0; i < actiontypes.length; i++) {
if (!actiontypes[i].checked) {
continue;
}
actiontype = actiontypes[i].values;
break;
}
if (actiontype === 'protect') { // actually protecting the page
var item = Twinkle.protect.protectionPresetsInfo[form.category.value];
if (mw.config.get('wgArticleId')) {
if (item.edit) {
form.editmodify.checked = true;
Twinkle.protect.formevents.editmodify({ target: form.editmodify });
form.editlevel.value = item.edit;
Twinkle.protect.formevents.editlevel({ target: form.editlevel });
} else {
form.editmodify.checked = false;
Twinkle.protect.formevents.editmodify({ target: form.editmodify });
}
if (item.move) {
form.movemodify.checked = true;
Twinkle.protect.formevents.movemodify({ target: form.movemodify });
form.movelevel.value = item.move;
Twinkle.protect.formevents.movelevel({ target: form.movelevel });
} else {
form.movemodify.checked = false;
Twinkle.protect.formevents.movemodify({ target: form.movemodify });
}
form.editexpiry.value = form.moveexpiry.value = item.expiry || '2 days';
if (form.pcmodify) {
if (item.stabilize) {
form.pcmodify.checked = true;
Twinkle.protect.formevents.pcmodify({ target: form.pcmodify });
form.pclevel.value = item.stabilize;
Twinkle.protect.formevents.pclevel({ target: form.pclevel });
} else {
form.pcmodify.checked = false;
Twinkle.protect.formevents.pcmodify({ target: form.pcmodify });
}
form.pcexpiry.value = item.expiry || '1 month';
}
} else {
if (item.create) {
form.createlevel.value = item.create;
Twinkle.protect.formevents.createlevel({ target: form.createlevel });
}
form.createexpiry.value = item.expiry || 'infinity';
}
var reasonField = actiontype === 'protect' ? form.protectReason : form.reason;
if (item.reason) {
reasonField.value = item.reason;
} else {
reasonField.value = '';
}
// sort out tagging options, disabled if nonexistent or lua
if (mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto') {
if (form.category.value === 'unprotect') {
form.tagtype.value = 'none';
} else {
form.tagtype.value = item.template ? item.template : form.category.value;
}
Twinkle.protect.formevents.tagtype({ target: form.tagtype });
// We only have one TE template at the moment, so this
// should be expanded if more are added (e.g. pp-semi-template)
if (form.category.value === 'pp-template') {
form.noinclude.checked = true;
} else if (mw.config.get('wgNamespaceNumber') !== 10) {
form.noinclude.checked = false;
}
}
} else { // RPP request
if (form.category.value === 'unprotect') {
form.expiry.value = '';
form.expiry.disabled = true;
} else {
form.expiry.value = '';
form.expiry.disabled = false;
}
}
};
Twinkle.protect.callback.evaluate = function twinkleprotectCallbackEvaluate(e) {
var form = e.target;
var input = Morebits.quickForm.getInputData(form);
var tagparams;
if (input.actiontype === 'tag' || (input.actiontype === 'protect' && mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto')) {
tagparams = {
tag: input.tagtype,
reason: (input.tagtype === 'pp-protected' || input.tagtype === 'pp-semi-protected' || input.tagtype === 'pp-move') && input.protectReason,
small: input.small,
noinclude: input.noinclude
};
}
switch (input.actiontype) {
case 'protect':
// protect the page
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = 'Khóa thành công';
var statusInited = false;
var thispage;
var allDone = function twinkleprotectCallbackAllDone() {
if (thispage) {
thispage.getStatusElement().info('xong');
}
if (tagparams) {
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
}
};
var protectIt = function twinkleprotectCallbackProtectIt(next) {
thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), 'Khóa trang');
if (mw.config.get('wgArticleId')) {
if (input.editmodify) {
thispage.setEditProtection(input.editlevel, input.editexpiry);
}
if (input.movemodify) {
// Ensure a level has actually been chosen
if (input.movelevel) {
thispage.setMoveProtection(input.movelevel, input.moveexpiry);
} else {
alert('Bạn phải chọn một mức khóa di chuyển!');
return;
}
}
} else {
thispage.setCreateProtection(input.createlevel, input.createexpiry);
thispage.setWatchlist(false);
}
if (input.protectReason) {
thispage.setEditSummary(input.protectReason);
} else {
alert('Bạn phải nhập lý do khóa, lý do này sẽ được ghi vào nhật trình khóa.');
return;
}
if (!statusInited) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
statusInited = true;
}
thispage.setChangeTags(Twinkle.changeTags);
thispage.protect(next);
};
var stabilizeIt = function twinkleprotectCallbackStabilizeIt() {
if (thispage) {
thispage.getStatusElement().info('xong');
}
thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), 'Áp dụng biện pháp khóa thay đổi đang chờ xử lý');
thispage.setFlaggedRevs(input.pclevel, input.pcexpiry);
if (input.protectReason) {
thispage.setEditSummary(input.protectReason + Twinkle.summaryAd); // flaggedrevs tag support: [[phab:T247721]]
} else {
alert('Bạn phải nhập lý do khóa, lý do này sẽ được ghi vào nhật trình khóa.');
return;
}
if (!statusInited) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
statusInited = true;
}
thispage.stabilize(allDone, function(error) {
if (error.errorCode === 'stabilize_denied') { // [[phab:T234743]]
thispage.getStatusElement().error('Không thể sửa đổi cài đặt thay đổi đang chờ xử lý, có thể do lỗi mediawiki. Các tác vụ khác (gắn thẻ hoặc khóa thường xuyên) có thể đã diễn ra. Hãy tải lại trang và thử lại.');
}
});
};
if (input.editmodify || input.movemodify || !mw.config.get('wgArticleId')) {
if (input.pcmodify) {
protectIt(stabilizeIt);
} else {
protectIt(allDone);
}
} else if (input.pcmodify) {
stabilizeIt();
} else {
alert("Làm ơn cho Twinkle làm gì đó! \nNếu bạn chỉ muốn gắn thẻ trang, bạn có thể chọn các tùy chọn 'Gắn thẻ trang với bản mẫu bảo vệ' ở trên cùng.");
}
break;
case 'tag':
// apply a protection template
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.followRedirect = false;
Morebits.wiki.actionCompleted.notice = 'Gắn thẻ hoàn thành';
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
break;
case 'request':
// file request at RFPP
var typename, typereason;
switch (input.category) {
case 'pp-dispute':
case 'pp-vandalism':
case 'pp-usertalk':
case 'pp-protected':
typename = 'khóa hoàn toàn';
break;
case 'pp-template':
typename = 'khóa bản mẫu';
break;
case 'pp-30-500-arb':
case 'pp-30-500-vandalism':
case 'pp-30-500-disruptive':
case 'pp-30-500-blp':
case 'pp-30-500-sock':
typename = 'khóa xác nhận mở rộng';
break;
case 'pp-semi-vandalism':
case 'pp-semi-disruptive':
case 'pp-semi-unsourced':
case 'pp-semi-usertalk':
case 'pp-semi-sock':
case 'pp-semi-blp':
case 'pp-semi-protected':
typename = 'bán khóa';
break;
case 'pp-pc-vandalism':
case 'pp-pc-blp':
case 'pp-pc-protected':
case 'pp-pc-unsourced':
case 'pp-pc-disruptive':
typename = 'các thay đổi đang chờ xử lý';
break;
case 'pp-move':
case 'pp-move-dispute':
case 'pp-move-indef':
case 'pp-move-vandalism':
typename = 'khóa di chuyển trang';
break;
case 'pp-create':
case 'pp-create-offensive':
case 'pp-create-blp':
case 'pp-create-salt':
typename = 'khóa khởi tạo';
break;
case 'unprotect':
var admins = $.map(Twinkle.protect.currentProtectionLevels, function(pl) {
if (!pl.admin || Twinkle.protect.trustedBots.indexOf(pl.admin) !== -1) {
return null;
}
return 'User:' + pl.admin;
});
if (admins.length && !confirm('Bạn đã cố gắng liên hệ với quản trị viên bảo vệ chưa (' + Morebits.array.uniq(admins).join(', ') + ') first?')) {
return false;
}
// otherwise falls through
default:
typename = 'không khóa';
break;
}
switch (input.category) {
case 'pp-dispute':
typereason = 'Tranh chấp nội dung / bút chiến';
break;
case 'pp-vandalism':
case 'pp-semi-vandalism':
case 'pp-pc-vandalism':
case 'pp-30-500-vandalism':
typereason = '[[WP:VAND|Phá hoại]] thường xuyên';
break;
case 'pp-semi-disruptive':
case 'pp-pc-disruptive':
case 'pp-30-500-disruptive':
typereason = '[[Wikipedia:Sửa đổi gây hại]] thường xuyên';
break;
case 'pp-semi-unsourced':
case 'pp-pc-unsourced':
typereason = 'Thêm thường xuyên [[WP:INTREF|nội dung không nguồn hoặc nguồn yếu]]';
break;
case 'pp-template':
typereason = '[[WP:HIGHRISK|Bản mẫu có nguy cơ bị phá hoại cao]]';
break;
case 'pp-30-500-arb':
typereason = '[[WP:30/500|Tuân theo Ủy ban Trọng tài]]';
break;
case 'pp-usertalk':
case 'pp-semi-usertalk':
typereason = 'Sử dụng trang thảo luận của người dùng không phù hợp khi bị cấm';
break;
case 'pp-semi-sock':
case 'pp-30-500-sock':
typereason = '[[Wikipedia:Tài khoản con rối]] thường xuyên';
break;
case 'pp-semi-blp':
case 'pp-pc-blp':
case 'pp-30-500-blp':
typereason = 'Vi phạm chính sách [[Wikipedia:Tiểu sử người đang sống]]';
break;
case 'pp-move-dispute':
typereason = 'Tranh chấp tên trang / di chuyển trang';
break;
case 'pp-move-vandalism':
typereason = 'Phá hoại di chuyển trang';
break;
case 'pp-move-indef':
typereason = 'Trang có nhiều người xem';
break;
case 'pp-create-offensive':
typereason = 'Tên xúc phạm';
break;
case 'pp-create-blp':
typereason = '[[Wikipedia:Tiểu sử người đang sống]] đã xóa gần đây';
break;
case 'pp-create-salt':
typereason = 'Tạo lại nội dung nhiều lần';
break;
default:
typereason = '';
break;
}
var reason = typereason;
if (input.reason !== '') {
if (typereason !== '') {
reason += '\u00A0\u2013 '; // U+00A0 NO-BREAK SPACE; U+2013 EN RULE
}
reason += input.reason;
}
if (reason !== '' && reason.charAt(reason.length - 1) !== '.') {
reason += '.';
}
var rppparams = {
reason: reason,
typename: typename,
category: input.category,
expiry: input.expiry
};
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var rppName = 'Wikipedia:Yêu cầu khóa hay mở khóa trang';
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = rppName;
Morebits.wiki.actionCompleted.notice = 'Tác vụ đã hoàn thành, hiện đang chuyển hướng đến trang thảo luận';
var rppPage = new Morebits.wiki.page(rppName, 'Yêu cầu khóa trang');
rppPage.setFollowRedirect(true);
rppPage.setCallbackParameters(rppparams);
rppPage.load(Twinkle.protect.callbacks.fileRequest);
break;
default:
alert('twinkleprotect: unknown kind of action');
break;
}
};
Twinkle.protect.callbacks = {
taggingPageInitial: function(tagparams) {
if (tagparams.tag === 'noop') {
Morebits.status.info('Áp dụng bản mẫu khóa', 'nothing to do');
return;
}
var protectedPage = new Morebits.wiki.page(mw.config.get('wgPageName'), 'Đang gắn thẻ trang');
protectedPage.setCallbackParameters(tagparams);
protectedPage.load(Twinkle.protect.callbacks.taggingPage);
},
taggingPage: function(protectedPage) {
var params = protectedPage.getCallbackParameters();
var text = protectedPage.getPageText();
var tag, summary;
var oldtag_re = /\s*(?:<noinclude>)?\s*\{\{\s*(pp-[^{}]*?|protected|(?:t|v|s|p-|usertalk-v|usertalk-s|sb|move)protected(?:2)?|protected template|privacy protection)\s*?\}\}\s*(?:<\/noinclude>)?\s*/gi;
var re_result = oldtag_re.exec(text);
if (re_result) {
if (params.tag === 'none' || confirm('{{' + re_result[1] + '}} đã được tìm thấy trên trang. \nNhấp vào OK để xóa hoặc nhấp vào Hủy để lại đó.')) {
text = text.replace(oldtag_re, '');
}
}
if (params.tag === 'none') {
summary = 'Removing protection template';
} else {
tag = params.tag;
if (params.reason) {
tag += '|reason=' + params.reason;
}
if (params.small) {
tag += '|small=yes';
}
if (/^\s*#redirect/i.test(text)) { // redirect page
// Only tag if no {{rcat shell}} is found
if (!text.match(/{{(?:redr|this is a redirect|r(?:edirect)?(?:.?cat.*)?[ _]?sh)/i)) {
text = text.replace(/#REDIRECT ?(\[\[.*?\]\])(.*)/i, '#REDIRECT $1$2\n\n{{' + tag + '}}');
} else {
Morebits.status.info('Chuyển hướng lớp vỏ thể loại hiện tại', 'nothing to do');
return;
}
} else {
if (params.noinclude) {
tag = '<noinclude>{{' + tag + '}}</noinclude>';
} else {
tag = '{{' + tag + '}}\n';
}
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
summary = 'Đang thêm {{' + params.tag + '}}';
}
protectedPage.setEditSummary(summary);
protectedPage.setChangeTags(Twinkle.changeTags);
protectedPage.setPageText(text);
protectedPage.setCreateOption('nocreate');
protectedPage.suppressProtectWarning(); // no need to let admins know they are editing through protection
protectedPage.save();
},
fileRequest: function(rppPage) {
var params = rppPage.getCallbackParameters();
var text = rppPage.getPageText();
var statusElement = rppPage.getStatusElement();
var rppRe = new RegExp('===\\s*(\\[\\[)?\\s*:?\\s*' + Morebits.string.escapeRegExp(Morebits.pageNameNorm) + '\\s*(\\]\\])?\\s*===', 'm');
var tag = rppRe.exec(text);
var rppLink = document.createElement('a');
rppLink.setAttribute('href', mw.util.getUrl(rppPage.getPageName()));
rppLink.appendChild(document.createTextNode(rppPage.getPageName()));
if (tag) {
statusElement.error([ 'Đã có yêu cầu khóa cho trang này tại ', rppLink, ', bị hủy bỏ.' ]);
return;
}
var newtag = '=== [[:' + Morebits.pageNameNorm + ']] ===\n';
if (new RegExp('^' + mw.util.escapeRegExp(newtag).replace(/\s+/g, '\\s*'), 'm').test(text)) {
statusElement.error([ 'Đã có yêu cầu khóa cho trang này tại ', rppLink, ', bị hủy bỏ.' ]);
return;
}
newtag += '* {{pagelinks|1=' + Morebits.pageNameNorm + '}}\n* {{Tình trạng khóa|1=' + Morebits.pageNameNorm + '}}\n\n';
var words;
switch (params.expiry) {
case 'temporary':
words = 'Tạm thời ';
break;
case 'infinity':
words = 'Vô hạn ';
break;
default:
words = '';
break;
}
words += params.typename;
newtag += "'''" + Morebits.string.toUpperCaseFirstChar(words) + (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 {
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;
if (increase) {
reg = /(\n==\s*Các yêu cầu đã giải quyết\s*==)/;
} else {
reg = /(\n==\s*Các yêu cầu đã giải quyết\s*==)/;
}
var originalTextLength = text.length;
// text = text.replace(reg, '\n' + newtag + '\n$1'); // Tạm không dùng (17/12/2021)
text += '\n\n' + newtag; // Thêm yêu cầu khóa trang vào cuối trang (17/12/2021)
if (text.length === originalTextLength) {
var linknode = document.createElement('a');
linknode.setAttribute('href', mw.util.getUrl('Wikipedia:Twinkle/Sửa RPP'));
linknode.appendChild(document.createTextNode('Cách sửa RPP'));
statusElement.error([ 'Không thể tìm thấy tiêu đề có liên quan tại WP:RPP. Để khắc phục sự cố này, vui lòng xem ', linknode, '.' ]);
return;
}
statusElement.status('Thêm yêu cầu mới...');
rppPage.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ Đang yêu cầu ' + params.typename + (params.typename === 'pending changes' ? ' [[:' : ' [[:') +
Morebits.pageNameNorm + ']].');
rppPage.setChangeTags(Twinkle.changeTags);
rppPage.setPageText(text);
rppPage.setCreateOption('recreate');
rppPage.save();
}
};
Twinkle.addInitCallback(Twinkle.protect, 'protect');
})(jQuery);
// </nowiki>