en>Mr. Stradivarius |
en>Great Brightstar |
Line 1: |
Line 1: |
| -- This module implements {{pp-meta}} and its daughter templates such as
| | {{#ifeq:{{{border|}}}|no|<templatestyles src="Pre/styles.css" />}}<pre<includeonly></includeonly> {{#ifeq:{{{border|}}}|no|class="noborder"}} style="white-space: {{{space|pre-wrap}}}; {{#if:{{{width|}}}|width: {{{width}}};}}"><!-- |
| -- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.
| | -->{{#if:{{{1|}}}|{{{1}}}<noinclude>|Sample text</noinclude>}}<!-- |
| | | -->{{#if:{{{2|}}}|{{!}}{{{2}}}|}}<!-- |
| --------------------------------------------------------------------------------
| | -->{{#if:{{{3|}}}|{{!}}{{{3}}}|}}<!-- |
| -- Configuration | | -->{{#if:{{{4|}}}|{{!}}{{{4}}}|}}<!-- |
| --------------------------------------------------------------------------------
| | -->{{#if:{{{5|}}}|{{!}}{{{5}}}|}}<!-- |
| | | -->{{#if:{{{6|}}}|{{!}}{{{6}}}|}}<!-- |
| local cfg = {}
| | -->{{#if:{{{7|}}}|{{!}}{{{7}}}|}}<!-- |
| | | -->{{#if:{{{8|}}}|{{!}}{{{8}}}|}}<!-- |
| cfg.reasons = {
| | -->{{#if:{{{9|}}}|{{!}}{{{9}}}|}}<!-- |
| blp = {
| | -->{{#if:{{{10|}}}|{{!}}{{{10}}}|}}<!-- |
| categoryOrder = 'reason',
| | -->{{#if:{{{11|}}}|{{!}}{{{11}}}|}}<!-- |
| banner = 'blp'
| | -->{{#if:{{{12|}}}|{{!}}{{{12}}}|}}<!-- |
| },
| | -->{{#if:{{{13|}}}|{{!}}{{{13}}}|}}<!-- |
| dispute = {
| | -->{{#if:{{{14|}}}|{{!}}{{{14}}}|}}<!-- |
| categoryOrder = 'reason',
| | -->{{#if:{{{15|}}}|{{!}}{{{15}}}|}}<!-- |
| banner = 'dispute'
| | -->{{#if:{{{16|}}}|{{!}}{{{16}}}|}}<!-- |
| },
| | -->{{#if:{{{17|}}}|{{!}}{{{17}}}|}}<!-- |
| office = {
| | -->{{#if:{{{18|}}}|{{!}}{{{18}}}|}}<!-- |
| categoryOrder = 'reason',
| | -->{{#if:{{{19|}}}|{{!}}{{{19}}}|}}<!-- |
| banner = 'office'
| | -->{{#if:{{{20|}}}|{{!}}{{{20}}}|}}<!-- |
| },
| | --></pre><noinclude> |
| sock = {
| | {{Documentation}} |
| categoryOrder = 'reason',
| | <!-- |
| banner = 'sock'
| | PLEASE ADD CATEGORIES AND INTERWIKIS |
| },
| | TO THE /doc SUBPAGE, THANKS |
| usertalk = {
| | --> |
| banner = 'usertalk'
| | </noinclude> |
| },
| |
| vandalism = {
| |
| categoryOrder = 'namespace',
| |
| banner = 'vandalism'
| |
| }
| |
| } | |
| | |
| cfg.banners = {
| |
| -- $1 = "until" or "or until" depending on the expiry
| |
| -- $2 = "disputes", with or without a section link
| |
| blp = {
| |
| },
| |
| dispute = {
| |
| text = '$1 editing $2 have been resolved',
| |
| tooltip = 'due to editing disputes',
| |
| dispute = true
| |
| },
| |
| office = {
| |
| },
| |
| sock = {
| |
| },
| |
| usertalk = {
| |
| text = '',
| |
| 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]].'
| |
| },
| |
| vandalism = {
| |
| text = 'due to [[Wikipedia:Vandalism|vandalism]]',
| |
| tooltip = 'due to vandalism'
| |
| },
| |
| } | |
| | |
| 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',
| |
| ['pc-autoconfirmed-all-all-all'] = 'Wikipedia pending changes protected pages (level 1)',
| |
| ['pc-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 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.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
| |
| error('no properties key')
| |
| end
| |
| local property = properties[propertiesKey]
| |
| if not property then
| |
| error('invalid properties key')
| |
| end
| |
| if dupes[property] then
| |
| error('dupe detected')
| |
| else
| |
| dupes[property] = 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
| |
| error('invalid category order string')
| |
| 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
| |
| | |
| return p
| |