Mô đun:Protected edit request/active
Giao diện
require('strict')local yesno, makeMessageBox -- passed in from Mô đun:Protected edit requestlocal makeToolbar = require('Mô đun:Toolbar')._mainlocal getPagetype = require('Mô đun:Pagetype')._mainlocal effectiveProtectionLevel = require('Mô đun:Effective protection level')._main------------------------------------------------------------------------ Helper functions----------------------------------------------------------------------local function makeWikilink(page, display) if display then return mw.ustring.format('[[%s|%s]]', page, display) else return mw.ustring.format('[[%s]]', page) endend------------------------------------------------------------------------ Title class------------------------------------------------------------------------ This is basically the mw.title class with some extras thrown in.local title = {}title.__index = titlefunction title.getProtectionLevelText(protectionLevel) -- Gets the text to use in anchors and urn links. local levels = {unprotected = 'editunprotected', autoconfirmed = 'editsemiprotected', extendedconfirmed = 'editextendedprotected', templateeditor = 'edittemplateprotected', autopatrolled = 'editautopatrolprotected', sysop = 'editprotected', interfaceadmin = 'editinterfaceprotected'} return levels[protectionLevel]endfunction title.new(...) local success, obj = pcall(mw.title.new, ...) if not (success and obj) then return end -- Add a protectionLevel property. obj.protectionLevel = effectiveProtectionLevel(obj.exists and 'edit' or 'create', obj) if obj.protectionLevel == '*' then -- Make unprotected pages return "unprotected". obj.protectionLevel = 'unprotected' elseif obj.protectionLevel == 'user' then -- If we just need to be registered, pretend we need to be autoconfirmed, since it's the closest thing we have. obj.protectionLevel = 'autoconfirmed' end -- Add a pagetype property. obj.pagetype = getPagetype{page = obj.prefixedText, defaultns = 'all'} -- Add link-making methods. function obj:makeUrlLink(query, display) return mw.ustring.format('[%s %s]', self:fullUrl(query), display) end function obj:makeViewLink(display) return self:makeUrlLink({redirect = 'no'}, display) end function obj:makeEditLink(display) return self:makeUrlLink({action = 'edit'}, display) end function obj:makeHistoryLink(display) return self:makeUrlLink({action = 'history'}, display) end function obj:makeLastEditLink(display) return self:makeUrlLink({diff = 'cur', oldid = 'prev'}, display) end function obj:makeWhatLinksHereLink(display) return makeWikilink('Đặc biệt:Liên kết đến đây/' .. self.prefixedText, display) end function obj:makeCompareLink(otherTitle, display) display = display or 'diff' local comparePagesTitle = title.new('Đặc biệt:So sánh trang') return comparePagesTitle:makeUrlLink({page1 = self.prefixedText, page2 = otherTitle.prefixedText}, display) end function obj:makeLogLink(logType, display) local logTitle = title.new('Đặc biệt:Nhật trình') return logTitle:makeUrlLink({type = logType, page = self.prefixedText}, display) end function obj:urlEncode() return mw.uri.encode(self.prefixedText, 'WIKI') end function obj:makeUrnLink(boxProtectionLevel) -- Outputs a urn link. The protection level is taken from the template, rather than detected from page itself, -- as the detection may be inaccurate for cascade-protected and title-blacklisted pages as of Nov 2013. local protectionLinkText = title.getProtectionLevelText(boxProtectionLevel) return mw.ustring.format('[urn:x-wp-%s:%s <span></span>]', protectionLinkText, self:urlEncode()) end -- Get a subpage title object, but go through pcall rather than use the unprotected mw.title:subPageTitle. function obj:getSubpageTitle(subpage) return title.new(self.prefixedText .. '/' .. subpage) end return objend------------------------------------------------------------------------ TitleTable class----------------------------------------------------------------------local titleTable = {}titleTable.__index = titleTablefunction titleTable.new(args) -- Get numerical arguments and make title objects for each of them. local nums = {} for k, v in pairs(args) do if type(k) == 'number' then table.insert(nums, k) end end table.sort(nums) local titles = {} for _, num in ipairs(nums) do local title = title.new(args[num]) table.insert(titles, title) end -- Get the current title, and get the subject title if no titles were specified. titles.currentTitle = mw.title.getCurrentTitle() if #titles < 1 then local subjectNs = titles.currentTitle.subjectNsText if subjectNs ~= '' then subjectNs = subjectNs .. ':' end table.insert(titles, title.new(subjectNs .. titles.currentTitle.text)) end -- Set the metatable. setmetatable(titles, titleTable) return titlesendfunction titleTable:memoize(memoField, func, ...) if self[memoField] ~= nil then return self[memoField] else self[memoField] = func(...) return self[memoField] endendfunction titleTable:titleIterator() local i = 0 local n = #self return function() i = i + 1 if i <= n then return self[i] end endendfunction titleTable:hasSameProperty(memoField, getPropertyFunc) -- If the titles table has more than one title in it, check if they have the same property. -- The property is found using the getPropertyFunc function, which takes a title object as its single argument. local function hasSameProperty(getPropertyFunc) local property for i, obj in ipairs(self) do if i == 1 then property = getPropertyFunc(obj) elseif getPropertyFunc(obj) ~= property then return false end end return true end return self:memoize(memoField, hasSameProperty, getPropertyFunc)end function titleTable:hasSameExistenceStatus() -- Returns true if all the titles exist, or if they all don't exist. Returns false if there is a mixture of existence statuses. return self:hasSameProperty('sameExistenceStatus', function (title) return title.exists end)endfunction titleTable:hasSameProtectionStatus() -- Checks if all the titles have the same protection status (either for creation protection or for edit-protection - the two are not mixed). local sameExistenceStatus = self:hasSameExistenceStatus() if sameExistenceStatus then return self:hasSameProperty('sameProtectionStatus', function (title) return title.protectionLevel end) else return sameExistenceStatus endendfunction titleTable:hasSamePagetype() -- Checks if all the titles have the same pagetype. return self:hasSameProperty('samePagetype', function (title) return title.pagetype end)endfunction titleTable:propertyExists(memoField, getPropertyFunc) -- Checks if a title with a certain property exists. -- The property is found using the getPropertyFunc function, which takes a title object as its single argument -- and should return a boolean value. local function propertyExists(getPropertyFunc) for titleObj in self:titleIterator() do if getPropertyFunc(titleObj) then return true end end return false end return self:memoize(memoField, propertyExists, getPropertyFunc)endfunction titleTable:hasNonInterfacePage() return self:propertyExists('nonInterfacePage', function (titleObj) return titleObj.namespace ~= 8 end)endfunction titleTable:hasTemplateOrModule() return self:propertyExists('templateOrModule', function (titleObj) return titleObj.namespace == 10 or titleObj.namespace == 828 end)endfunction titleTable:hasNonTemplateOrModule() return self:propertyExists('nontemplateormodule', function (titleobj) return titleobj.namespace ~= 10 and titleobj.namespace ~= 828 end)endfunction titleTable:hasOtherProtectionLevel(level) for titleObj in self:titleIterator() do if titleObj.protectionLevel ~= level then return true end end return falseendfunction titleTable:getProtectionLevels() local function getProtectionLevels() local levels = {} for titleObj in self:titleIterator() do local level = titleObj.protectionLevel levels[level] = true end return levels end return self:memoize('protectionLevels', getProtectionLevels)end------------------------------------------------------------------------ Blurb class definition----------------------------------------------------------------------local blurb = {}blurb.__index = blurbfunction blurb.new(titleTable, boxProtectionLevel) local obj = {} obj.titles = titleTable obj.boxProtectionLevel = boxProtectionLevel obj.linkCount = 0 -- Counter for the number of total items in the object's link lists. setmetatable(obj, blurb) return objend-- Static methods --function blurb.makeParaText(name, val) local pipe = mw.text.nowiki('|') local equals = mw.text.nowiki('=') val = val and ("''" .. val .. "''") or '' return mw.ustring.format('<code style="white-space: nowrap;">%s%s%s%s</code>', pipe, name, equals, val)endfunction blurb.makeTemplateLink(s) return mw.ustring.format('%s[[Bản mẫu:%s|%s]]%s', mw.text.nowiki('{{'), s, s, mw.text.nowiki('}}'))endfunction blurb:makeProtectionText() local boxProtectionLevel = self.boxProtectionLevel local levels = {['*'] = 'không bị khóa', autoconfirmed = 'bán khóa', extendedconfirmed = 'khóa xác nhận mở rộng', templateeditor = 'khóa bản mẫu', sysop = 'khóa hoàn toàn', interfaceadmin = 'khóa giao diện'} for level, protectionText in pairs(levels) do if level == boxProtectionLevel then return mw.ustring.format('[[Wikipedia:Khóa trang|%s]]', protectionText) end end error('Mức khóa không rõ ' .. boxProtectionLevel)endfunction blurb.getPagetypePlural(title) local pagetype = title.pagetype if pagetype == 'category' then return 'categories' else return pagetype .. 's' endend-- Normal methods --function blurb:makeLinkList(title) local tbargs = {} -- The argument list to pass to Mô đun:Toolbar tbargs.style = 'font-size: smaller;' tbargs.separator = 'dot' -- Page links. table.insert(tbargs, title:makeEditLink('sửa')) table.insert(tbargs, title:makeHistoryLink('lịch sử')) table.insert(tbargs, title:makeLastEditLink('cuối')) table.insert(tbargs, title:makeWhatLinksHereLink('liên kết')) -- Sandbox links. local sandboxTitle = title:getSubpageTitle('sandbox') if sandboxTitle and sandboxTitle.exists then table.insert(tbargs, sandboxTitle:makeViewLink('chỗ thử')) table.insert(tbargs, sandboxTitle:makeEditLink('sửa chỗ thử')) table.insert(tbargs, sandboxTitle:makeHistoryLink('lịch sử chỗ thử')) table.insert(tbargs, sandboxTitle:makeLastEditLink('thay đổi chỗ thử cuối cùng')) table.insert(tbargs, title:makeCompareLink(sandboxTitle, 'khác biệt chỗ thử')) end -- Test cases links. local testcasesTitle = title:getSubpageTitle('testcases') if testcasesTitle and testcasesTitle.exists then table.insert(tbargs, testcasesTitle:makeViewLink('các ca kiểm thử')) end -- Transclusion count link. if title.namespace == 10 or title.namespace == 828 then -- Only add the transclusion count link for templates and modules. local tclink = mw.uri.new{ host = 'tools.wmflabs.org', path = '/templatecount/index.php', query = { lang = 'vi', name = title.text, namespace = title.namespace, }, fragment = 'bottom' } tclink = string.format('[%s số lần nhúng]', tostring(tclink)) table.insert(tbargs, tclink) end -- Protection log link. if title.namespace ~= 8 then -- MediaWiki pages don't have protection log entries. table.insert(tbargs, title:makeLogLink('protect', 'nhật trình khóa')) end self.linkCount = self.linkCount + #tbargs -- Keep track of the number of total links created by the object. return makeToolbar(tbargs)endfunction blurb:makeLinkLists() local titles = self.titles if #titles == 1 then return self:makeLinkList(titles[1]) else local ret = {} table.insert(ret, '<ul>') for i, titleObj in ipairs(titles) do table.insert(ret, mw.ustring.format('<li>%s %s</li>', titleObj:makeViewLink(titleObj.prefixedText), self:makeLinkList(titleObj))) end table.insert(ret, '</ul>') return table.concat(ret) endendfunction blurb:makeIntro() local titles = self.titles local requested = 'Có [[:Thể loại:Yêu cầu sửa đổi trang bị khóa|yêu cầu]]' local protectionText if titles:hasNonInterfacePage() then protectionText = ' ' .. self:makeProtectionText() else protectionText = '' -- Interface pages cannot be unprotected, so we don't need to explicitly say they are protected. end -- Deal with cases where we are passed multiple titles. if #titles > 1 then local pagetype if titles:hasSamePagetype() then pagetype = blurb.getPagetypePlural(titles[1]) else pagetype = 'trang' end return mw.ustring.format("'''%s muốn sửa các %s%s''':", requested, pagetype, protectionText) end -- Deal with cases where we are passed only one title. local title = titles[1] local stringToFormat if title.exists then stringToFormat = '%s muốn sửa %s%s %s.' else stringToFormat = '%s tạo %s%s %s.' end stringToFormat = "'''" .. stringToFormat .. "'''" return mw.ustring.format(stringToFormat, requested, title.pagetype, protectionText, title:makeViewLink(title.prefixedText))endfunction blurb:makeBody() local titles = self.titles local protectionLevels = titles:getProtectionLevels() local boxProtectionLevel = self.boxProtectionLevel local hasNonInterfacePage = titles:hasNonInterfacePage() local isPlural = false if #titles > 1 then isPlural = true end local descriptionText = "Vui lòng trình bày thật '''rõ ràng, cụ thể và dễ hiểu''' " if boxProtectionLevel == 'sysop' or boxProtectionLevel == 'templateeditor' then local editText = 'sửa đổi' if isPlural then editText = 'các' .. editText end local descriptionCompleteText = mw.ustring.format('để cả những người chưa quen vấn đề cũng có thể thực hiện %s được yêu cầu.', editText) descriptionText = descriptionText .. descriptionCompleteText else descriptionText = descriptionText .. 'tức phải ghi rõ nội dung cũ và nội dung mới. ' .. [["'''Phải''' theo hình thức "nhờ sửa ''X'' thành ''Y''". Hay nói cách khác, nếu chỉ ghi chung chung "nhờ sửa x" sẽ không được chấp nhận".]] end local smallText = '' if boxProtectionLevel == 'sysop' or boxProtectionLevel == 'templateeditor' then local templateFullText if boxProtectionLevel == 'sysop' then templateFullText = 'hẳn' elseif boxProtectionLevel == 'templateeditor' then templateFullText = 'bản mẫu' end smallText = 'Chỉ dùng bản mẫu này để yêu cầu tại trang [[Wikipedia:Quy định khóa|' .. templateFullText .. "]] để thực hiện các sửa đổi '''không gây tranh cãi''' hoặc đã đạt được [[Wikipedia:Đồng thuận|đồng thuận]]." .. " Nếu sửa đổi đó có thể gây tranh cãi, hãy thảo luận trước tại trang thảo luận của trang bị khóa '''rồi mới''' sử dụng bản mẫu này." else local userText local responseTemplate if boxProtectionLevel == 'extendedconfirmed' then userText = 'Thành viên [[Wikipedia:Quyền truy cập của thành viên#Thành viên được xác nhận mở rộng|được xác nhận mở rộng]]' responseTemplate = blurb.makeTemplateLink('EEp') elseif boxProtectionLevel == 'autoconfirmed' then userText = 'Thành viên [[Wikipedia:Quyền truy cập của thành viên#Thành viên tự xác nhận|tự động xác nhận]]' responseTemplate = blurb.makeTemplateLink('ESp') elseif boxProtectionLevel == 'interfaceadmin' then userText = '[[Wikipedia:Quyền truy cập của thành viên#Thành viên được xác nhận mở rộng|Bảo quản viên giao diện]]' responseTemplate = blurb.makeTemplateLink('EIp') else userText = 'thành viên' responseTemplate = blurb.makeTemplateLink('ESp') end local answeredPara = blurb.makeParaText('xong', 'chưa') local stringToFormat = 'Bất kỳ %s nào có thể thực hiện sửa đổi. ' .. [[Hãy nhớ đổi tham số %s thành “'''xong'''” nếu chấp nhận hay chờ người yêu cầu cho thêm chi tiết, hoặc đổi thành “'''từ chối'''” nếu từ chối yêu cầu. ]] .. "Tham số này giúp chúng ta dọn dẹp thể loại yêu cầu sửa trang. " .. 'Bạn cũng có thể sử dụng bản mẫu %s trong các phản ứng.' smallText = mw.ustring.format(stringToFormat, userText, answeredPara, blurb.makeTemplateLink('ESp')) end if hasNonInterfacePage then smallText = smallText .. ' Bạn cũng có thể [[Wikipedia:Yêu cầu khóa hay mở khóa trang|yêu cầu khóa hay mở khóa]].' end if boxProtectionLevel == 'sysop' or boxProtectionLevel == 'templateeditor' then smallText = smallText .. ' Sau khi thực hiện hoặc từ chối, hãy thêm tham số ' .. blurb.makeParaText('xong', 'xong') .. ' để tắt bản mẫu.' end return mw.ustring.format('%s\n<p style="font-size:smaller; line-height:1.3em;">\n%s\n</p>', descriptionText, smallText)endfunction blurb:export() local intro = self:makeIntro() local linkLists = self:makeLinkLists() local body = self:makeBody() -- Start long links lists on a new line. local linkListSep = ' ' if self.linkCount > 5 then linkListSep = '<br />' end return mw.ustring.format('%s%s%s\n\n%s', intro, linkListSep, linkLists, body)end------------------------------------------------------------------------ Subclass of Mô đun:Protected edit request's box class for active boxes----------------------------------------------------------------------local box = {}box.__index = boxfunction box.new(protectionType, args) -- In the inheritance system used here, an object's metatable is its class, and a class's metatable is its superclass local obj = getmetatable(box).new(protectionType, args) setmetatable(obj, box) local boxProtectionLevels = {semi = 'autoconfirmed', extended = 'extendedconfirmed', template = 'templateeditor', interface = 'interfaceadmin', full = 'sysop'} obj.boxProtectionLevel = boxProtectionLevels[protectionType] obj.demo = yesno(args.demo) -- Set dependent objects. obj.titles = titleTable.new(args) if not yesno(args.force) and obj.titles:hasSameProperty('sameProtectionStatus', function (title) return title.protectionLevel end) and obj.titles[1].protectionLevel ~= 'unprotected' then obj.boxProtectionLevel = obj.titles[1].protectionLevel end obj.blurb = blurb.new(obj.titles, obj.boxProtectionLevel) return objendfunction box:setImage() local titles = self.titles local boxProtectionLevel = self.boxProtectionLevel local padlock if boxProtectionLevel == 'sysop' then padlock = 'Full-protection-shackle-block.svg' elseif boxProtectionLevel == 'interfaceadmin' then padlock = 'Interface-protection-shackle-keyhole.svg ' elseif boxProtectionLevel == 'templateeditor' then padlock = 'Template-protection-shackle-brace-FF0066.svg' elseif boxProtectionLevel == 'autoconfirmed' then padlock = 'Semi-protection-shackle.svg' elseif boxProtectionLevel == 'extendedconfirmed' then padlock = 'Extended-protection-shackle-check-mark.svg' else padlock = 'Padlock-bronze-open.svg' end local stringToFormat = '[[Tập tin:%s|%dpx|alt=|link=]]' local smallPadlock = mw.ustring.format(stringToFormat, padlock, 25) local largePadlock = mw.ustring.format(stringToFormat, padlock, 60) self:setArg('smallimage', smallPadlock) self:setArg('image', largePadlock)endfunction box:buildUrnLinks() local ret = {} local boxProtectionLevel = self.boxProtectionLevel for titleObj in self.titles:titleIterator() do table.insert(ret, titleObj:makeUrnLink(boxProtectionLevel)) end return mw.ustring.format('<span class="plainlinks" style="display:none">%s</span>', table.concat(ret))endfunction box:setBlurbText() self:setArg('text', self.blurb:export() .. self:buildUrnLinks())endfunction box:exportRequestTmbox() self:setImage() self:setBlurbText() self:setArg('class', 'editrequest') self:setArg('id', title.getProtectionLevelText(self.boxProtectionLevel)) -- for anchor. yes, this leads to multiple elements with the same ID. we should probably fix this at some point return makeMessageBox('tmbox', self.tmboxArgs)endfunction box:exportRequestCategories() local cats = {} local boxProtectionLevel = self.boxProtectionLevel local function addCat(cat) table.insert(cats, mw.ustring.format('[[Thể loại:%s]]', cat)) end local protectionCats = { autoconfirmed = 'Yêu cầu sửa đổi trang bị bán khóa', extendedconfirmed = 'Yêu cầu sửa đổi trang bị khóa mở rộng', templateeditor = 'Yêu cầu sửa đổi trang bị khóa bản mẫu', sysop = 'Yêu cầu sửa đổi trang bị khóa hẳn', interfaceadmin = 'Yêu cầu sửa đổi trang bị khóa giao diện' } addCat(protectionCats[boxProtectionLevel]) if self.titles:hasOtherProtectionLevel(boxProtectionLevel) then addCat('Yêu cầu sửa đổi trang có thể dùng bản mẫu sai') end return table.concat(cats)endfunction box:export() if not self.titles.currentTitle.isTalkPage and not self.demo then return '<span class="error">Lỗi: Chỉ có thể yêu cầu sửa đổi trang bị khóa trên trang thảo luận.</span>[[Thể loại:Yêu cầu sửa đổi trang bị khóa không phải trên trang thảo luận]]' end local ret = {} table.insert(ret, self:exportRequestTmbox()) if not self.demo then table.insert(ret, self:exportRequestCategories()) end return table.concat(ret)end------------------------------------------------------------------------ Function exported to Mô đun:Protected edit request----------------------------------------------------------------------return function(superclass, yn, mb) yesno = yn makeMessageBox = mb return setmetatable(box, superclass)end