en>Mr. Stradivarius |
en>MZMcBride |
Line 1: |
Line 1: |
| -- This module implements {{pp-meta}} and its daughter templates such as
| | <div class="messagebox" id="template_doc_page_viewed_directly" style="text-align: center"> |
| -- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.
| | This is the [[Wikipedia:Template documentation|documentation]] page {{{1|for [[{{NAMESPACE}}:{{BASEPAGENAME}}]].}}} <div style="font-size: 90%">When it is viewed directly, links using [[Help:Variable|variables]] may appear broken; do not replace these with [[hard coding|hardcoded]] page names or URLs.</div> |
| | | </div><includeonly>{{#if: {{{inhib|{{{inhibit|}}}}}} |<!-- skip -->|[[Category:Template documentation|{{PAGENAME}}]]}}</includeonly><noinclude> |
| --------------------------------------------------------------------------------
| | {{pp-semi-protected|small=yes}} |
| -- Configuration
| | {{template doc}} |
| --------------------------------------------------------------------------------
| | <!-- Add categories and interwikis to the /doc subpage, not here! --> |
| | | </noinclude> |
| local cfg = {}
| |
| | |
| cfg.reasons = {
| |
| -- $1 = "until" or "or until" depending on the expiry
| |
| -- $2 = "disputes", with or without a section link
| |
| -- $3 = the type of the page, e.g. "article", "template", or "page"
| |
| -- $4 = A blurb "it has been protected for x years, x months and x days."
| |
| -- $5 = the protection date
| |
| -- $6 = Intro blurb, e.g. "This page is currently
| |
| -- [[Help:Protection|protected]] from editing"
| |
| -- $7 = {{vandal-m|username}} replacement
| |
| blp = {
| |
| text = '$6 to promote compliance with'
| |
| .. '[[Wikipedia:Biographies of living persons'
| |
| .. "|Wikipedia's policy on the biographies"
| |
| .. ' of living people]]',
| |
| tooltip = '$6 to promote compliance with the policy on biographies of'
| |
| .. ' living people',
| |
| categoryOrder = 'reason',
| |
| },
| |
| dispute = {
| |
| text = '$6 $1 editing $2 have been resolved',
| |
| tooltip = 'due to editing disputes',
| |
| dispute = true,
| |
| categoryOrder = 'reason',
| |
| },
| |
| office = {
| |
| text = 'This $3 is currently under the scrutiny of the'
| |
| .. ' [[Wikipedia:Office actions|Wikimedia Foundation Office]]'
| |
| .. ' and is protected. $4',
| |
| categoryOrder = 'reason',
| |
| },
| |
| reset = {
| |
| text = 'On $5 this article was reduced to a simplified,'
| |
| ..' "bare bones" version so that it may be completely rewritten to'
| |
| .. ' ensure it meets the policies of'
| |
| .. ' [[WP:NPOV|Neutral Point of View]] and [[WP:V|Verifiability]].'
| |
| .. ' Standard Wikipedia policies will apply to its rewriting—which'
| |
| .. ' will eventually be open to all editors—and will be strictly'
| |
| .. ' enforced. The article has been placed under a level of'
| |
| .. ' semi-protection temporarily during the rebuilding of this'
| |
| .. ' article.\n\nAny insertion of material directly from'
| |
| .. ' pre-protection revisions of the article will be removed, as'
| |
| .. ' will any material added to the article that is not properly'
| |
| .. ' sourced. The associated talk page(s) were also cleared on the'
| |
| .. " same date.\n\n'''Administrators may not override this action"
| |
| .. ' without approval from someone from the [[WP:OFFICE|Office]].'
| |
| .. " No editor may remove this notice.'''",
| |
| categoryOrder = 'reason',
| |
| categoryReason = 'office',
| |
| },
| |
| sock = {
| |
| text = '$6 to prevent [[Wikipedia:Sock puppetry|sock puppets]] of'
| |
| .. ' [[Wikipedia:Blocking policy|blocked]] or'
| |
| .. ' [[Wikipedia:List of banned users|banned users]]'
| |
| .. ' from editing it',
| |
| tooltip = '$6 to prevent sock puppets of blocked or banned users from'
| |
| .. ' editing it',
| |
| categoryOrder = 'reason',
| |
| },
| |
| usertalk = {
| |
| text = '$6 to prevent $7 from using it to make disruptive edits, such'
| |
| .. ' as abusing the'
| |
| .. ' {{[[Template:unblock|unblock]]}} template',
| |
| explanation = 'If you cannot edit this user talk page and you need to'
| |
| .. ' make a change or leave a message, you can'
| |
| .. ' [[Wikipedia:Requests for page protection'
| |
| .. '#Current requests for edits to a protected page'
| |
| .. '|request an edit]],'
| |
| .. ' [[Wikipedia:Requests for page protection'
| |
| .. '#Current requests for reduction in protection level'
| |
| .. '|request unprotection]],'
| |
| .. ' [[Special:Userlogin|log in]],'
| |
| .. ' or [[Special:UserLogin/signup|create an account]].',
| |
| categoryReason = 'all',
| |
| },
| |
| vandalism = {
| |
| text = '$6 due to [[Wikipedia:Vandalism|vandalism]]',
| |
| tooltip = 'due to vandalism',
| |
| categoryOrder = 'namespace',
| |
| },
| |
| }
| |
| | |
| cfg.categories = {
| |
| -- The key strings follow this format:
| |
| -- type, level, ns, reason, expiry
| |
| ['all-all-all-all-all'] = 'Wikipedia protected pages',
| |
| ['all-all-all-office-all'] = 'Wikipedia Office-protected pages',
| |
| ['edit-all-template-all-all'] = 'Wikipedia protected templates',
| |
| ['edit-autoconfirmed-all-all-all'] = 'Wikipedia semi-protected pages',
| |
| ['edit-autoconfirmed-all-all-indef'] = 'Wikipedia indefinitely semi-protected pages',
| |
| ['edit-autoconfirmed-all-blp-all'] = 'Wikipedia indefinitely semi-protected biographies of living people',
| |
| ['edit-autoconfirmed-all-blp-temp'] = 'Wikipedia temporarily semi-protected biographies of living people',
| |
| ['edit-autoconfirmed-all-dispute-all'] = 'Wikipedia pages semi-protected due to dispute',
| |
| ['edit-autoconfirmed-all-sock-all'] = 'Wikipedia pages semi-protected from banned users',
| |
| ['edit-autoconfirmed-all-vandalism-all'] = 'Wikipedia pages semi-protected against vandalism',
| |
| ['edit-autoconfirmed-category-all-all'] = 'Wikipedia semi-protected categories',
| |
| ['edit-autoconfirmed-file-all-all'] = 'Semi-protected images',
| |
| ['edit-autoconfirmed-portal-all-all'] = 'Semi-protected portals',
| |
| ['edit-autoconfirmed-project-all-all'] = 'Semi-protected project pages',
| |
| ['edit-autoconfirmed-talk-all-all'] = 'Semi-protected talk pages',
| |
| ['edit-autoconfirmed-template-all-all'] = 'Wikipedia semi-protected templates',
| |
| ['edit-autoconfirmed-template-all-all'] = 'Wikipedia semi-protected templates',
| |
| ['edit-autoconfirmed-user-all-all'] = 'Wikipedia semi-protected user and user talk pages',
| |
| ['edit-sysop-all-blp-all'] = 'Wikipedia indefinitely protected biographies of living people',
| |
| ['edit-sysop-all-blp-temp'] = 'Wikipedia temporarily protected biographies of living people',
| |
| ['edit-sysop-all-dispute-all'] = 'Wikipedia pages protected due to dispute',
| |
| ['edit-sysop-all-sock-all'] = 'Wikipedia pages protected from banned users',
| |
| ['edit-sysop-all-vandalism-all'] = 'Wikipedia pages protected against vandalism',
| |
| ['edit-sysop-category-all-all'] = 'Wikipedia protected categories',
| |
| ['edit-sysop-file-all-all'] = 'Protected images',
| |
| ['edit-sysop-project-all-all'] = 'Protected project pages',
| |
| ['edit-sysop-talk-all-all'] = 'Protected talk pages',
| |
| ['edit-sysop-template-all-all'] = 'Wikipedia protected templates',
| |
| ['edit-sysop-user-all-all'] = 'Wikipedia protected user and user talk pages',
| |
| ['move-sysop-all-all-all'] = 'Wikipedia move-protected pages',
| |
| ['move-sysop-all-all-indef'] = 'Wikipedia indefinitely move-protected pages',
| |
| ['move-sysop-all-dispute-all'] = 'Wikipedia pages move-protected due to dispute',
| |
| ['move-sysop-all-vandalism-all'] = 'Wikipedia pages move-protected due to vandalism',
| |
| ['move-sysop-portal-all-all'] = 'Wikipedia move-protected portals',
| |
| ['move-sysop-portal-all-all'] = 'Wikipedia move-protected portals',
| |
| ['move-sysop-project-all-all'] = 'Wikipedia move-protected project pages',
| |
| ['move-sysop-talk-all-all'] = 'Wikipedia move-protected talk pages',
| |
| ['move-sysop-template-all-all'] = 'Wikipedia move-protected templates',
| |
| ['move-sysop-user-all-all'] = 'Wikipedia move-protected user and user talk pages',
| |
| ['autoreview-autoconfirmed-all-all-all'] = 'Wikipedia pending changes protected pages (level 1)',
| |
| ['autoreview-reviewer-all-all-all'] = 'Wikipedia pending changes protected pages (level 2)',
| |
| }
| |
| | |
| cfg.categoryNamespaces = {
| |
| [2] = 'user',
| |
| [3] = 'user',
| |
| [4] = 'project',
| |
| [6] = 'file',
| |
| [10] = 'template',
| |
| [12] = 'project',
| |
| [14] = 'category',
| |
| [100] = 'portal',
| |
| }
| |
| | |
| cfg.pagetypeNamespaces = {
| |
| [0] = 'article',
| |
| [6] = 'file',
| |
| [10] = 'template',
| |
| [14] = 'category',
| |
| [828] = 'module',
| |
| default = 'page'
| |
| } | |
| | |
| --[[
| |
| -- Not currently used
| |
| local error_categories = {
| |
| incorrect = 'Wikipedia pages with incorrect protection templates',
| |
| no_expiry = 'Wikipedia protected pages without expiry',
| |
| create = 'Wikipedia pages tagged as create-protected',
| |
| template = 'Wikipedia template-protected pages other than templates and modules'
| |
| } | |
| --]]
| |
| | |
| --------------------------------------------------------------------------------
| |
| -- Main functions
| |
| --------------------------------------------------------------------------------
| |
| | |
| -- Initialise necessary modules.
| |
| local mArguments = require('Module:Arguments')
| |
| local mProtectionLevel = require('Module:Effective protection level')._main
| |
| local mMessageBox -- only needs to be loaded if we are outputting a banner, so lazily initialise
| |
| | |
| -- Define often-used functions as local variables.
| |
| local tconcat = table.concat
| |
| local tinsert = table.insert
| |
| local tremove = table.remove
| |
| local ceil = math.ceil
| |
| local format = string.format
| |
| | |
| local function toTableEnd(t, pos)
| |
| -- Sends the value at position pos to the end of array t, and shifts the
| |
| -- other items down accordingly.
| |
| return tinsert(t, tremove(t, pos))
| |
| end
| |
| | |
| local p = {}
| |
| | |
| function p.main(frame)
| |
| local args = mArguments.getArgs(frame)
| |
| return p._main(args)
| |
| end
| |
| | |
| function p._main(args)
| |
| local title
| |
| if args.page then
| |
| title = mw.title.new(args.page)
| |
| else
| |
| title = mw.title.getCurrentTitle()
| |
| end
| |
| local protectionData = p.getProtectionData(title)
| |
| end
| |
| | |
| function p.getProtectionData(title)
| |
| -- Gets a table containing protection data for the given title. The data
| |
| -- is cached using a metatable, and so can be indexed as needed without
| |
| -- a performance loss.
| |
| local protectionData = {}
| |
| local actions = {
| |
| create = true,
| |
| edit = true,
| |
| move = true,
| |
| autoreview = true
| |
| }
| |
| setmetatable(protectionData, {
| |
| __index = function (t, key)
| |
| local level
| |
| if actions[key] then
| |
| level = mProtectionLevel(key, title)
| |
| if level == 'accountcreator' then
| |
| -- Lump titleblacklisted pages in with template-protected pages,
| |
| -- since templateeditors can do both.
| |
| level = 'templateeditor'
| |
| end
| |
| end
| |
| protectionData[key] = level
| |
| return level
| |
| end
| |
| })
| |
| return protectionData
| |
| end
| |
| | |
| function p.getPagetype(ns)
| |
| -- Returns a string with the page's type. Takes a namespace number as input.
| |
| local pagetype = pagetypeNamespaces[ns] or pagetypeNamespaces.default
| |
| if not pagetype then
| |
| error('the page type could not be found; please define a name for the key "default"')
| |
| end
| |
| return pagetype
| |
| end
| |
| | |
| function p.matchNamespace(ns)
| |
| -- Matches a namespace number to a string that can be passed to the
| |
| -- namespace parameter of p.getCategoryName.
| |
| if not ns or type(ns) ~= 'number' then
| |
| return nil
| |
| end
| |
| local nskey = cfg.categoryNamespaces[ns]
| |
| if not nskey and ns % 2 == 1 then
| |
| nskey = 'talk'
| |
| end
| |
| return nskey
| |
| end
| |
| | |
| function p.getCategoryName(cats, action, level, namespace, reason, expiry)
| |
| --[[
| |
| -- Gets a category name from the category table, given a combination of
| |
| -- the protection type, the protection level, the namespace number, the
| |
| -- reason for protection, and the expiry date.
| |
| --]]
| |
| cats = cats or cfg.categories
| |
| | |
| --[[
| |
| -- Define the properties table. Each property is a table containing the
| |
| -- canonical order that the property is tested in, the position the
| |
| -- property has in the category key strings, and the property value itself.
| |
| --]]
| |
| local properties = {
| |
| expiry = {order = 1, keypos = 5, val = expiry},
| |
| namespace = {order = 2, keypos = 3, val = p.matchNamespace(namespace)},
| |
| reason = {order = 3, keypos = 4, val = reason},
| |
| level = {order = 4, keypos = 2, val = level},
| |
| action = {order = 5, keypos = 1, val = action}
| |
| }
| |
| | |
| --[[
| |
| -- Load the category order configuration for the reason specified.
| |
| -- The configuration is stored in the categoryOrder field of each reason
| |
| -- subtable of cfg.reasons. If the value is a table, then the order is the
| |
| -- values specified in the table. If the value is a string, then the
| |
| -- property corresponding to that string is tested last (i.e. it is the most
| |
| -- important, because it keeps its specified value the longest) and the
| |
| -- other properties are tested in the canonical order. If the value is of
| |
| -- any other type then the canonical order is used.
| |
| --]]
| |
| local reasonTable = reason and cfg.reasons[reason]
| |
| local categoryOrder = reasonTable and reasonTable.categoryOrder
| |
| local categoryOrderType = type(categoryOrder)
| |
| local configOrder = {}
| |
| if categoryOrderType == 'table' then
| |
| local dupes = {}
| |
| for i = 1, 5 do
| |
| local propertiesKey = categoryOrder[i]
| |
| if not propertiesKey then
| |
| local msg = 'no entry found for key '
| |
| .. i
| |
| .. ' in the cfg.reasons.'
| |
| .. reason
| |
| .. '.categoryOrder table'
| |
| error(msg)
| |
| end
| |
| local property = properties[propertiesKey]
| |
| if not property then
| |
| local msg = 'invalid value "'
| |
| .. propertiesKey
| |
| .. '" detected in the cfg.reasons.'
| |
| .. reason
| |
| .. '.categoryOrder table'
| |
| error(msg)
| |
| end
| |
| if dupes[propertiesKey] then
| |
| local msg = 'duplicate values "'
| |
| .. propertiesKey
| |
| .. '" detected in the cfg.reasons.'
| |
| .. reason
| |
| .. '.categoryOrder table'
| |
| error(msg)
| |
| else
| |
| dupes[propertiesKey] = true
| |
| end
| |
| configOrder[i] = property
| |
| end
| |
| else
| |
| for propertiesKey, t in pairs(properties) do
| |
| configOrder[t.order] = t
| |
| end
| |
| if categoryOrderType == 'string' then
| |
| local property = properties[categoryOrder]
| |
| if not property then
| |
| local msg = '"'
| |
| .. categoryOrder
| |
| .. '" is not a valid value of cfg.reasons.'
| |
| .. reason
| |
| .. '.categoryOrder'
| |
| error(msg)
| |
| end
| |
| toTableEnd(configOrder, property.order)
| |
| end
| |
| end
| |
| | |
| --[[
| |
| -- Define the attempt order. Properties with no value defined are moved
| |
| -- to the end, where they will later be given the value "all". This is
| |
| -- to cut down on the number of table lookups in the cats table, which
| |
| -- grows exponentially with the number of properties with valid values.
| |
| -- We keep track of the number of active properties with the noActive
| |
| -- parameter.
| |
| --]]
| |
| local active, inactive = {}, {}
| |
| for i, t in ipairs(configOrder) do
| |
| if t.val then
| |
| active[#active + 1] = t
| |
| else
| |
| inactive[#inactive + 1] = t
| |
| end
| |
| end
| |
| local noActive = #active
| |
| local attemptOrder = active
| |
| for i, t in ipairs(inactive) do
| |
| attemptOrder[#attemptOrder + 1] = t
| |
| end
| |
| | |
| --[[
| |
| -- Check increasingly generic key combinations until we find a match.
| |
| -- If a specific category exists for the combination of properties
| |
| -- we are given, that match will be found first. If not, we keep
| |
| -- trying different key combinations until we match using the key
| |
| -- "all-all-all-all-all".
| |
| --
| |
| -- To generate the keys, we index the property subtables using a
| |
| -- binary matrix with indexes i and j. j is only calculated up to
| |
| -- the number of active properties. For example, if there were three
| |
| -- active properties, the matrix would look like this, with 0
| |
| -- corresponding to the string "all", and 1 corresponding to the
| |
| -- val field in the property table:
| |
| --
| |
| -- j 1 2 3
| |
| -- i
| |
| -- 1 1 1 1
| |
| -- 2 0 1 1
| |
| -- 3 1 0 1
| |
| -- 4 0 0 1
| |
| -- 5 1 1 0
| |
| -- 6 0 1 0
| |
| -- 7 1 0 0
| |
| -- 8 0 0 0
| |
| --
| |
| -- Values of j higher than the number of active properties are set
| |
| -- to the string "all".
| |
| --
| |
| -- A key for the category table is constructed for each value of i.
| |
| -- The correct position of the value in the key is determined by the
| |
| -- pos field in the property table.
| |
| --]]
| |
| for i = 1, 2^noActive do
| |
| local key = {}
| |
| for j, t in ipairs(attemptOrder) do
| |
| if j > noActive then
| |
| key[t.keypos] = 'all'
| |
| else
| |
| local quotient = i / 2 ^ (j - 1)
| |
| quotient = ceil(quotient)
| |
| if quotient % 2 == 1 then
| |
| key[t.keypos] = t.val
| |
| else
| |
| key[t.keypos] = 'all'
| |
| end
| |
| end
| |
| end
| |
| key = tconcat(key, '-')
| |
| local attempt = cats[key]
| |
| if attempt then
| |
| return attempt
| |
| end
| |
| end
| |
| error(
| |
| 'No category match found;'
| |
| .. ' please define the category for key "all-all-all-all-all"'
| |
| )
| |
| end
| |
| | |
| function p.renderImageLink(image, size, link, text, alt)
| |
| --[[
| |
| -- Renders the image link wikitext All parameters are optional
| |
| -- apart from the display text.
| |
| --
| |
| -- @parameters:
| |
| -- image - the image name
| |
| -- size - the image size, as a number
| |
| -- link - page linked to by the image
| |
| -- text - the tooltip text
| |
| -- alt - the alt text
| |
| --
| |
| -- All parameters are optional apart from the text parameter.
| |
| --]]
| |
| image = image or 'Transparent.gif'
| |
| size = size or 20
| |
| if link then
| |
| link = '|link=' .. link
| |
| else
| |
| link = ''
| |
| end
| |
| text = text or error('No text parameter supplied to p.renderImageLink')
| |
| if alt then
| |
| alt = '|alt=' .. alt
| |
| else
| |
| alt = ''
| |
| end
| |
| return string.format('[[Image:%s|%dpx%s|%s%s]]', image, size, link, text, alt)
| |
| end
| |
| | |
| function p.renderPadlock(image, right)
| |
| --[[
| |
| -- Renders the html of the padlock seen in the top-right-hand corner
| |
| -- of protected pages.
| |
| --
| |
| -- @parameters:
| |
| -- image - the image wikitext (required)
| |
| -- right - the "right" css property value, as a string (optional)
| |
| --]]
| |
| image = image or error('No image parameter specified in p.renderPadlock')
| |
| local root = mw.html.create('div')
| |
| root
| |
| :addClass('metadata topicon nopopups')
| |
| :attr('id', 'protected-icon')
| |
| :css{display = 'none', right = right or '55px'}
| |
| :wikitext(image)
| |
| return tostring(root)
| |
| end
| |
| | |
| function p.renderBanner(page, image, text)
| |
| --[[
| |
| -- Renders the large protection banner placed at the top of articles,
| |
| -- using the data provided in the data table.
| |
| --
| |
| -- @parameters:
| |
| -- page - demo page parameter to pass to {{mbox}}
| |
| -- image - the image wikitext
| |
| -- text - the text to display
| |
| --
| |
| -- All parameters are optional.
| |
| --]]
| |
| mMessageBox = require('Module:Message box')
| |
| local mbargs = { -- arguments for the message box module
| |
| page = page,
| |
| type = 'protection',
| |
| image = image,
| |
| text = text
| |
| }
| |
| return mMessageBox.main('mbox', mbargs)
| |
| end
| |
| | |
| --[[
| |
| When to add "Category:Wikipedia pages with incorrect protection templates":
| |
| * If it uses a type which is incompatible with the actual protection level of a page, or
| |
| * If an expiry date is set and is in the past
| |
| | |
| When to add "Category:Wikipedia protected pages without expiry":
| |
| * No expiry is set, and
| |
| * Expiry can be set, and
| |
| * The protection type is not "move" (could change this?), and
| |
| * The reason doesn't have "indefinitely protected" categories (pp-blp, pp-semi-indef and pp-move-indef have these), and
| |
| * The reason is not the generic pp-protected (could change this?)
| |
| (This leaves reasons "dispute", "vandalism", "usertalk", and "sock")
| |
| ]]
| |
| | |
| return p
| |