วิกิพีเดีย
มอดูล:Protected edit request/active
คู่มือการใช้งานมอดูล[สร้าง]
คุณอาจจะต้องการสร้างคู่มือการใช้งานของมอดูลนี้ ผู้เขียนสามารถทำการทดลองได้ที่กระบะทราย (สร้าง | คัดลอก) และชุดทดสอบ (สร้าง) ของมอดูลนี้ โปรดเพิ่มหมวดหมู่ไปที่หน้าย่อย /doc หน้าย่อยของมอดูลนี้ |
require('Module:No globals') local yesno, makeMessageBox -- passed in from Module:Protected edit request local makeToolbar = require('Module:Toolbar')._main local getPagetype = require('Module:Pagetype')._main local effectiveProtectionLevel = require('Module: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) end end ---------------------------------------------------------------------- -- Title class ---------------------------------------------------------------------- -- This is basically the mw.title class with some extras thrown in. local title = {} title.__index = title function title.getProtectionLevelText(protectionLevel) -- Gets the text to use in anchors and urn links. local levels = {unprotected = 'editunprotected', autoconfirmed = 'editsemiprotected', extendedconfirmed = 'editextendedprotected', templateeditor = 'edittemplateprotected', sysop = 'editprotected'} return levels[protectionLevel] end function 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 = 'ไม่'}, display) end function obj:makeEditLink(display) return self:makeUrlLink({action = 'แก้'}, display) end function obj:makeHistoryLink(display) return self:makeUrlLink({action = 'ประวัติ'}, display) end function obj:makeLastEditLink(display) return self:makeUrlLink({diff = 'ป', oldid = 'ก'}, display) end function obj:makeWhatLinksHereLink(display) return makeWikilink('Special:WhatLinksHere/' .. self.prefixedText, display) end function obj:makeCompareLink(otherTitle, display) display = display or 'diff' local comparePagesTitle = title.new('Special:ComparePages') return comparePagesTitle:makeUrlLink({page1 = self.prefixedText, page2 = otherTitle.prefixedText}, display) end function obj:makeLogLink(logType, display) local logTitle = title.new('Special:Log') 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 obj end ---------------------------------------------------------------------- -- TitleTable class ---------------------------------------------------------------------- local titleTable = {} titleTable.__index = titleTable function 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 titles end function titleTable:memoize(memoField, func, ...) if self[memoField] ~= nil then return self[memoField] else self[memoField] = func(...) return self[memoField] end end function titleTable:titleIterator() local i = 0 local n = #self return function() i = i + 1 if i <= n then return self[i] end end end function 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) end function 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 end end function titleTable:hasSamePagetype() -- Checks if all the titles have the same pagetype. return self:hasSameProperty('samePagetype', function (title) return title.pagetype end) end function 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) end function titleTable:hasNonInterfacePage() return self:propertyExists('nonInterfacePage', function (titleObj) return titleObj.namespace ~= 8 end) end function titleTable:hasTemplateOrModule() return self:propertyExists('templateOrModule', function (titleObj) return titleObj.namespace == 10 or titleObj.namespace == 828 end) end function titleTable:hasNonTemplateOrModule() return self:propertyExists('nontemplateormodule', function (titleobj) return titleobj.namespace ~= 10 and titleobj.namespace ~= 828 end) end function titleTable:hasOtherProtectionLevel(level) for titleObj in self:titleIterator() do if titleObj.protectionLevel ~= level then return true end end return false end function 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 = blurb function 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 obj end -- 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) end function blurb.makeTemplateLink(s) return mw.ustring.format('%s[[Template:%s|%s]]%s', mw.text.nowiki('{{'), s, s, mw.text.nowiki('}}')) end function blurb:makeProtectionText() local boxProtectionLevel = self.boxProtectionLevel local levels = {['*'] = 'ที่ไม่มีการป้องกัน', autoconfirmed = 'ที่กึ่งป้องกันไว้', extendedconfirmed = 'extended-confirmed-protected', templateeditor = 'แม่แบบถูกป้องกัน', sysop = 'ที่ป้องกันสมบูรณ์ไว้'} for level, protectionText in pairs(levels) do if level == boxProtectionLevel then return mw.ustring.format('[[วิธีใช้:การป้องกัน|%s]]', protectionText) end end error('Unknown protection level ' .. boxProtectionLevel) end function blurb.getPagetypePlural(title) local pagetype = title.pagetype if pagetype == 'category' then return 'categories' else return pagetype .. 's' end end -- Normal methods -- function blurb:makeLinkList(title) local tbargs = {} -- The argument list to pass to Module:Toolbar tbargs.style = 'font-size: smaller;' tbargs.separator = 'dot' -- Page links. table.insert(tbargs, title:makeEditLink('edit')) table.insert(tbargs, title:makeHistoryLink('history')) table.insert(tbargs, title:makeLastEditLink('last')) table.insert(tbargs, title:makeWhatLinksHereLink('links')) -- Sandbox links. local sandboxTitle = title:getSubpageTitle('sandbox') if sandboxTitle and sandboxTitle.exists then table.insert(tbargs, sandboxTitle:makeViewLink('sandbox')) table.insert(tbargs, sandboxTitle:makeEditLink('edit sandbox')) table.insert(tbargs, sandboxTitle:makeHistoryLink('sandbox history')) table.insert(tbargs, sandboxTitle:makeLastEditLink('sandbox last edit')) table.insert(tbargs, title:makeCompareLink(sandboxTitle, 'sandbox diff')) end -- Test cases links. local testcasesTitle = title:getSubpageTitle('testcases') if testcasesTitle and testcasesTitle.exists then table.insert(tbargs, testcasesTitle:makeViewLink('test cases')) 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 = 'en', name = title.text, namespace = title.namespace, }, fragment = 'bottom' } tclink = string.format('[%s transclusion count]', 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('ป้องกัน', 'ปูมการป้องกัน')) end self.linkCount = self.linkCount + #tbargs -- Keep track of the number of total links created by the object. return makeToolbar(tbargs) end function 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) end end function blurb:makeIntro() local titles = self.titles local requested = 'มีคำขอให้' 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 = 'หน้า' end return mw.ustring.format("'''%sแก้ไขต่อหน้าต่อไปนี้ %s %s''':", requested, protectionText, pagetype) end -- Deal with cases where we are passed only one title. local title = titles[1] local stringToFormat if title.exists then stringToFormat = '%sแก้ไขต่อ%s%sที่ %s' else stringToFormat = '%sให้สร้าง%s%sที่ %s' end stringToFormat = "'''" .. stringToFormat .. "'''" return mw.ustring.format(stringToFormat, requested, title.pagetype, protectionText, title:makeViewLink(title.prefixedText)) end function 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 = "แม่แบบนี้ต้องตามด้วย'''คำอธิบายที่สมบูรณ์และจำเพาะเจาะจง'''ของคำขอ" if boxProtectionLevel == 'sysop' or boxProtectionLevel == 'templateeditor' then local editText = 'edit' if isPlural then editText = editText .. 's' end local descriptionCompleteText = mw.ustring.format('เพื่อให้ผู้เขียนที่ไม่สันทัดกรณีในประเด็นเรื่องสามารถแก้ไขตามคำขอได้ทันที', editText) descriptionText = descriptionText .. descriptionCompleteText else descriptionText = descriptionText .. 'นั่นคือ เจาะจงว่าควรนำข้อความใดออกและสำเนาจดคำต่อคำของข้อความที่ควรใช้ทดแทน' .. [["กรุณาเปลี่ยน ''X''" '''ยอมรับไม่ได้''' และจะถูกปฏิเสธ คำขอ'''ต้อง'''อยู่ในรูป "กรุณาเปลี่ยน ''X'' เป็น ''Y''"]] end local smallText = '' if boxProtectionLevel == 'sysop' or boxProtectionLevel == 'templateeditor' then local templateFullText if boxProtectionLevel == 'sysop' then templateFullText = 'หน้าป้องกันสมบูรณ์' elseif boxProtectionLevel == 'templateeditor' then templateFullText = 'แม่แบบที่ถูกป้องกัน' end smallText = 'คำขอแก้ไขต่อ' .. templateFullText .. "ควรใช้หน้าเฉพาะสำหรับการแก้ไขที่'''ไม่เป็นที่ถกเถียง'''หรือมีความเห็นพ้องสนับสนุน" .. " หากการแก้ไขที่เสนออาจเป็นที่ถกเถียง ให้อภิปรายก่อนในหน้าคุยของหน้าที่ถูกป้องกัน'''ก่อน'''ใช้แม่แบบนี้" else local userText if boxProtectionLevel == 'extendedconfirmed' then userText = '[[Wikipedia:User access levels#Extended confirmed users|extended confirmed]] user' elseif boxProtectionLevel == 'autoconfirmed' then userText = '[[วิกิพีเดีย:ระดับการเข้าถึงของผู้ใช้#AUTOC|ผู้ใช้ยืนยันอัตโนมัติ]]' else userText = 'ผู้ใช้' end local answeredPara = blurb.makeParaText('answered', 'no') local stringToFormat = '%sทุกคนสามารถแก้ไขได้' .. [[พึงระลึกว่าเปลี่ยนตัวแปรเสริม%sเป็น "'''yes'''" เมื่อยอมรับ ปฏิเสธหรือพักคำขอเพื่อรอการอภิปรายของผู้ใช้แล้ว]] .. "เพื่อให้คำขอที่ไม่มีความเคลื่อนไหวหรือสำเร็จแล้วไม่เติมหมวดหมู่คำขอแก้ไขอย่างไม่จำเป็น" .. 'คุณยังอาจต้องการใช้แม่แบบ%sในการตอบ' smallText = mw.ustring.format(stringToFormat, userText, answeredPara, blurb.makeTemplateLink('ESp')) end if not isPlural then local title = titles[1] if title.namespace == 10 or title.namespace == 828 then local sandboxTitle = title:getSubpageTitle('sandbox') if sandboxTitle and sandboxTitle.exists then smallText = smallText .. ' พิจารณาเปลี่ยนแปลงในหน้า ' .. sandboxTitle:makeViewLink("กระบะทรายของ" .. title.pagetype) local testcasesTitle = title:getSubpageTitle('หน้าทดลอง') if testcasesTitle and testcasesTitle.exists then smallText = smallText .. ' and ' .. testcasesTitle:makeViewLink('ทดสอบอย่างถี่ถ้วนที่นี่') end smallText = smallText .. ' ก่อนเสนอคำขอแก้ไข' end end end if hasNonInterfacePage then smallText = smallText .. ' คำขอให้ป้องกันหรือเลิกป้องกันหน้า ให้[[WP:AN|แจ้งผู้ดูแลระบบ]]' end if boxProtectionLevel == 'sysop' or boxProtectionLevel == 'templateeditor' then smallText = smallText .. ' เมื่อแก้ไขตามคำขอแล้วหรือปฏิเสธคำขอ กรุณาเพิ่มตัวแปรเสริม ' .. blurb.makeParaText('answered', 'yes') .. ' เพื่อปิดใช้งานแม่แบบ' end return mw.ustring.format('%s\n<p style="font-size:smaller; line-height:1.3em;">\n%s\n</p>', descriptionText, smallText) end function 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 Module:Protected edit request's box class for active boxes ---------------------------------------------------------------------- local box = {} box.__index = box function 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', 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 obj end function box:setImage() local titles = self.titles local boxProtectionLevel = self.boxProtectionLevel local padlock if boxProtectionLevel == 'sysop' then padlock = 'Padlock.svg' elseif boxProtectionLevel == 'templateeditor' then padlock = 'Padlock-pink.svg' elseif boxProtectionLevel == 'autoconfirmed' then padlock = 'Padlock-silver.svg' elseif boxProtectionLevel == 'extendedconfirmed' then padlock = 'Padlock-blue.svg' else padlock = 'Padlock-bronze-open.svg' end local stringToFormat = '[[File:%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) end function 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)) end function box:setBlurbText() self:setArg('text', self.blurb:export() .. self:buildUrnLinks()) end function 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) end function box:exportRequestCategories() local cats = {} local boxProtectionLevel = self.boxProtectionLevel local function addCat(cat) table.insert(cats, mw.ustring.format('[[หมวดหมู่:%s]]', cat)) end local protectionCats = { autoconfirmed = 'คำขอแก้ไขหน้ากึ่งป้องกันวิกิพีเดีย', extendedconfirmed = 'Wikipedia extended-confirmed-protected edit requests', templateeditor = 'คำขอแก้ไขแม่แบบที่ถูกป้องกันวิกิพีเดีย', sysop = 'คำขอแก้ไขหน้าป้องกันสมบูรณ์วิกิพีเดีย' } addCat(protectionCats[boxProtectionLevel]) if self.titles:hasOtherProtectionLevel(boxProtectionLevel) then addCat('คำขอแก้ไขวิกิพีเดียที่อาจใช้แม่แบบไม่ถูกต้อง') end return table.concat(cats) end function box:export() if not self.titles.currentTitle.isTalkPage and not self.demo then return '<span class="error">ข้อผิดพลาด: คำขอแก้ไขที่ถูกป้องกันสามารถใช้ได้เฉพาะในหน้าคุย</span>[[หมวดหมู่:คำขอแก้ไขหน้าที่ถูกป้องกันที่ไม่อยู่ในหน้าคุย]]' 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 Module:Protected edit request ---------------------------------------------------------------------- return function(superclass, yn, mb) yesno = yn makeMessageBox = mb return setmetatable(box, superclass) end