Module:Contentious topics/talk notice/sandbox: Difference between revisions

Content deleted Content added
sync with live template
save a WIP
 
(23 intermediate revisions by 2 users not shown)
Line 3:
local TableTools = require('Module:TableTools')
local yesno = require('Module:Yesno')
local setToList = require('Module:Set to list')
local checkForUnknownParameters = require('Module:Check for unknown parameters')._check
local messageBoxModule = require('Module:Message box')
local categoryDatabase = mw.loadJsonData("Template:Contentious topics/Category database.json")
local restrictionsDatabase = mw.loadJsonData("Template:Contentious topics/Additional restrictions.json")
local restrictionsDefinition = mw.loadJsonData("Template:Contentious topics/Restrictions definition.json")
local standardSet = mw.loadJsonData("Template:Contentious topics/Standard set.json")
 
local categoryDatabase = mw.loadJsonData("Template:Contentious topics/Category database.json")
local function callFromListTemplate(code, arg)
return mw.getCurrentFrame():expandTemplate{
title = "Contentious topics/list/sandbox", -- REMOVE /sandbox when publishing
args = { [arg] = code }
}
end
 
local function collectTopics(args, sectionParameter)
local seen = {}
local completeTopics = {}
local partialTopics = {}
local ECR = {}
local i = 2 -- initialize index
local keepGoing = true -- whether to keep checking for more CTOPs
local function addaddECR(value, scope)
if TableTools.inArray(restrictionsDatabase['topic-wide'][value] or {}, 'ECR') then
if value then
if yesno(scope, nil) then
value = mw.text.trim(value)
ECR[value] = true
if value ~= '' and not seen[value] then
else
local applicableSection = args[value .. '-section'] or sectionParameter
ECR[value] = scope
if applicableSection then
end
partialTopics[value] = applicableSection
end
else
end
table.insert(completeTopics, value)
end
local function add(value)
seen[value] = true
if value then
keepGoing = true
value = mw.ustring.lower(mw.text.trim(value))
end
value = callFromListTemplate(value, 'canonical') -- normalize to the canonical name after we find the applicableSection
end
local applicableSection = args[value .. '-section'] or sectionParameter
end
addECR(value, applicableSection)
if value ~= '' and not seen[value] then
if applicableSection then
partialTopics[value] = applicableSection
else
-- first we clear the partialTopics value
-- this code is needed for articles which are e.g. entirely Eastern Europe but partially [[WP:APL]]
partialTopics[value] = nil
-- then we add it to the list of completeTopics
table.insert(completeTopics, value)
end
seen[value] = true
keepGoing = true
end
end
end
 
-- Primary topic params
-- we manually add [1], t1, and topic1 to support {{ct/tn|topic=foo|topic2=bar}}
add(args[1])
add(args.t)
add(args.t1)
add(args.topic)
add(args.topic1)
-- Additional topics via numbered forms
while keepGoing do
keepGoing = false -- this is set back to true if any of the below are found
add(args[i])
add(args['t' .. i])
add(args['topic' .. i])
i = i + 1 -- increment the index
end
return completeTopics, partialTopics
end
 
function p.main(frame)
-- process the input
local args = require('Module:Arguments').getArgs(frame)
local args = require('Module:Arguments').getArgs(frame)
local sectionParameter = yesno(args.section, args.section) or yesno(args.relatedcontent, args.relatedcontent) -- whether we are sections all the way down
local completeTopics, partialTopics = collectTopics(args, sectionParameter) -- completeTopics is a sequence. partialTopics is a table with topics as keys and scope as values
-- check whether we are sections all the way down
local restrictions = {} -- A list of which restrictions are enabled for easier iteration
local sectionParameter = yesno(args.section, args.section) or yesno(args.relatedcontent, args.relatedcontent)
local restrictionFlags = {} -- Track which restrictions are enabled, as a set
local currentTitleObject = mw.title.getCurrentTitle()
-- set the topic variables:
local subjectTitleObject = currentTitleObject.subjectPageTitle
--* completeTopics is a sequence for each topic applying the the entire article
local underRestrictions -- a boolean for whether there are any active restrictions
--* partialTopics is a table with topics as keys and scope as values
local articleOrPage -- the string "article" (if a mainspace article) or "page" (if not)
--* active topics subject to ECR as keys, the scope (nil for the entire article, true for an unspecified scope) as the value
local protectionLevel -- the edit protection level
local numberOfCompleteTopics = #completeTopics, --partialTopics, theECR number of= completecollectTopics(args, topicssectionParameter)
 
local numberOfPartialTopics = TableTools.size(partialTopics) -- the number of partial topics (not a sequence, so we have to use TableTools.size)
-- and then declare a bunch more variables which will be needed later
local numberOfTopics = numberOfCompleteTopics + numberOfPartialTopics -- total number of topics
local restrictions = {} -- A list of which restrictions are enabled for easier iteration
local section = sectionParameter or numberOfPartialTopics > 0 -- whether any topics apply to parts of the article
local restrictionFlags = {} -- Track which restrictions are enabled, as a set
local messageBody -- the text within the message box
local currentTitleObject = mw.title.getCurrentTitle()
local underRestrictions -- a boolean for whether there are any active restrictions
local articleOrPage -- the string "article" (if a mainspace article) or "page" (if not)
local numberOfCompleteTopics = #completeTopics -- the number of complete topics
local numberOfPartialTopics = TableTools.size(partialTopics) -- the number of partial topics (not a sequence, so we have to use TableTools.size)
local numberOfTopics = numberOfCompleteTopics + numberOfPartialTopics -- total number of topics
local section = sectionParameter or numberOfPartialTopics > 0 -- whether any topics apply to parts of the article
local messageBody -- the text within the message box
local messageBox -- the message box itself
local unknownParameterCheck -- the result of [[Module:Check for unknown parameters]]
local unknownParameterTable -- the table to pass to the [[Module:Check for unknown parameters]] call
local categories = '' -- initialize categories
local manualRestrictions = false -- have we set any restrictions via |parameters? Set to true when |parameters are processed
--[[
Line 80 ⟶ 113:
--]]
-- Helpers to add a restriction if it's active and hasn't been added yet
local function maybeAddRestriction(restriction)
if yesno(args[restriction]) then
Line 99 ⟶ 132:
end
-- Add the always-available restrictions
for _, r in ipairs(standardSet) do
maybeAddRestriction(r)
end
 
-- Topic-based restrictions
for _, topic in ipairs (completeTopics) do
local topicWide = restrictionsDatabase["topic-wide"][topic]
if topicWide then
for _, restriction in ipairs(topicWide) do
alwaysAddRestriction(restriction)
end
end
end
local additional = restrictionsDatabase["additional-available"][topic]
if additional then
for _, restriction in ipairs(additional) do
maybeAddRestriction(restriction)
end
end
end
for topic, scope in pairs(partialTopics) do
local additional = restrictionsDatabase["additional-available"][topic]
if additional then
for _, restriction in ipairs(additional) do
maybeAddRestriction(restriction)
end
end
end
local always = restrictionsDatabase["topic-wide"][topic]
if always then
for _, restriction in ipairs(always) do
-- Allow disabling these restrictions (via |1RR=no or similar)
maybeAddRestriction(restriction)
if yesno(args[restriction], true) or args[restriction] == nil then
end
restrictionFlags[restriction] = true
end
else
end
restrictionFlags[restriction] = nil
end
-- Add the protection level
end
if yesno(args.protection, true) or yesno(args.aeprotection, true) then
end
protectionLevel = subjectTitleObject.protectionLevels["edit"][1]
end
-- Add the protection level
if yesno(args.protection, true) or yesno(args.aeprotection, true) then
local protectionLevel = (currentTitleObject.subjectPageTitle.protectionLevels["edit"] or {nil})[1] -- the or {nil} allows a graceful fail if the subjectPage does not (yet) exist
if protectionLevel then
-- we have a |protection=foo parameter, and the page is protected
if restrictionFlags["ECR"] then
-- handle ECR with protection correctly
if protectionLevel == "full" then alwaysAddRestriction("full") end
else
-- no ECR, so just add the protection as normal
alwaysAddRestriction(protectionLevel)
end
manualRestrictions = true
Line 152 ⟶ 190:
addCategory(categoryDatabase['protection-error'])
end
end
--[[
Clear duplicate restrictions (e.g. 0RR and 1RR; consensus-required is stronger than BRD)
--]]
-- if 0RR, then clear 1RR
if restrictionFlags["0RR"] then
Line 170 ⟶ 208:
-- and finally, convert our set to a list to make it easy to work with
restrictions = setToListTableTools.keysToList(restrictionFlags, false, true)
--[[
Restrictions are now all set. Here, we add additional helper functions and variables necessary for generating the banner
--]]
-- Check whether any of the added restrictions are enabled
underRestrictions = #restrictions > 0 or args.other or args.other1
-- Determines whether we should use the string "article" or "page"
local articleOrPage = currentTitleObject:inNamespaces(1) and "article" or "page"
local function addToMessage(s)
Line 187 ⟶ 225:
local function getTopicBlurb(code)
return frame:expandTemplate{callFromListTemplate(code, 'scope')
end
title = "Contentious topics/list",
args = { scope = code }
local function getSubtopicBlurb(code)
}
return callFromListTemplate(code, 'subtopic')
end
-- returns the code for a superTopic
local function getSupertopic(code)
return callFromListTemplate(code, 'supertopic')
end
local function makeSubtopicCompleteBlurb(code)
local topicSubpage = callFromListTemplate(code, 'topic-subpage')
return '<b>' .. '[[' .. topicSubpage ..'|'
.. mw.ustring.gsub(topicSubpage, 'Wikipedia:Contentious topics/', '')
.. ']]</b>.'
end
Line 196 ⟶ 248:
-- the scope is either a string representing the exact scope of the topic
-- and is nil if it applies to the entire page or unspecified parts of the page
local function makeTopicBulletPoint(code, scope)
local topicBlurb = getTopicBlurb(code)
if topicBlurb == '' then
addCategory(categoryDatabase['bad-topic'])
else
elseif scope then
if scope then
-- scope is not nil, so we write that into the bullet point
addToMessage('* <b>' .. topicBlurb .. '</b>, specifically the parts about <b>' .. scope .. '</b>\n')
else
-- scope is nil, so we have nothing to add
addToMessage('* <b>' .. topicBlurb .. '</b>\n')
end
-- check for a superTopic (e.g. South Asia is the superTopic of Indian military history)
end
local superTopic = getSupertopic(code)
if superTopic ~= '' then
-- we have a superTopic, so explain that
addToMessage(', a subtopic of <b>' .. makeSubtopicCompleteBlurb(superTopic) .. '</b>\n')
else
addToMessage('\n')
end
end
end
-- Makes a restriction bullet point
local function makeRestrictionBulletPoint(code)
local def = restrictionsDefinition[code]
return def and ('* <b>' .. def .. '</b>\n') or ''
end
--[[
Line 228 ⟶ 291:
--]]
messageBody = '<b>The [[Wikipedia:Contentious topics|contentious topics]] procedure applies to this ' .. articleOrPage .. '.</b>'
-- if there's only one topic, we make a short blurb
if numberOfTopics == 1 then
local theCTOP
if section then
for topic, part in pairs(partialTopics) do
-- there's only one item, so this loop one runs once
addToMessage( ' Parts of this ' .. articleOrPage
.. (yesno(part, false) and '' or (' about <b>' .. part .. '</b>'))
.. ' relate to <b>')
..theCTOP = getTopicBlurb(topic)
.. '</b>, a contentious topic.</p>')
end
else
addToMessage(' This ' .. articleOrPage .. ' relates to <b>')
..theCTOP = getTopicBlurb(completeTopics[1])
end
.. '</b>, a contentious topic.</p>'
local subtopicBlurb = getSubtopicBlurb(theCTOP)
)
if subtopicBlurb ~= '' then
addToMessage(' to <b>' .. subtopicBlurb .. '</b>, ' .. ' part of the contentious topic designation for ' .. makeSubtopicCompleteBlurb(theCTOP))
else
addToMessage(' to <b>' .. getTopicBlurb(theCTOP) .. '</b>, a contentious topic.')
end
else
-- there is more than one topic, so we have to do some more processing
-- we handle the cases for partialTopics and completeTopics completely seperately
if numberOfCompleteTopics ~= 0 then
-- if there are any complete topics, insert text about them
addToMessage('<p>The entire ' .. articleOrPage .. ' relates to ')
addToMessage(' The entire ' .. articleOrPage .. ' relates to ')
if numberOfCompleteTopics > 1 then
-- we either loop through adding bullet points
addToMessage('the following contentious topics:</p>\n')
addToMessage('the following contentious topics:\n')
for _, topic in ipairs(completeTopics) do
makeTopicBulletPoint(topic, nil)
end
else
-- or we do it once
addToMessage('<b>' .. getTopicBlurb(completeTopics[1]) .. '</b>, a contentious topic.</p>')
-- TODO: refactor makeTopicBulletPoint into a more versitile function, allowing it to be called here
addToMessage('<b>')
local superTopic = getSupertopic(completeTopics[1])
if superTopic ~= '' then
addToMessage(getSubtopicBlurb(completeTopics[1]) .. '</b>, part of the contentious topic designation for ' .. makeSubtopicCompleteBlurb(completeTopics[1]))
else
addToMessage(getTopicBlurb(completeTopics[1]) .. '</b>, a contentious topic.')
end
end
end
if numberOfPartialTopics ~= 0 then
-- if there are any partial topics, insert text about them. Note that this runs regardless of whether there are any completeTopics
addToMessage('<p>')
if numberOfCompleteTopics ~= 0 then
Line 280 ⟶ 360:
-- There's only one topic and scope, so this loop only runs once
for topic, scope in pairs(partialTopics) do
addToMessage('<b>'local ..superTopic getTopicBlurb= getSupertopic(topic) .. '</b>')
if superTopic ~= '' then
addToMessage('<b>' .. getSubtopicBlurb(topic) .. '</b>')
else
addToMessage('<b>' .. getTopicBlurb(topic) .. '</b>')
end
if yesno(scope, nil) == nil then
-- the scope is not a boolean value, so we have a free-text explanation of the applicable parts
addToMessage(', in particular the parts about <b>' .. scope .. '</b>.')
end
if superTopic ~= '' then
addToMessage('. This is a subtopic of ' .. makeSubtopicCompleteBlurb(topic) .. '</p>')
else
addToMessage('.</p>')
end
end
Line 292 ⟶ 380:
end
if underRestrictions then
messageBody = '<p style="margin-top:0"><strong style="text-transform: uppercase;">Warning: active arbitration remedies</strong></p>'
.. messageBody
.. '<p style="text-decoration:underline; text-align:center; font-size:120%;">The following restrictions apply to everyone editing this ' .. articleOrPage .. ':</p>\n'
for _, restriction in ipairs(restrictions) do
addToMessage(makeRestrictionBulletPoint(restriction))
addCategory(categoryDatabase[restriction])
end
if args.other or args.other1 then
-- we have some form of other restrictions, so add the category
addCategory(categoryDatabase["other"])
-- then define a helper function to add a restriction
local function addOther(s)
addToMessage('* <b>' .. s .. '</b>\n')
end
-- then add the generic 'other' parameter
if args.other then
addOther(args.other)
end
-- and now we loop to infinity and beyond
local i = 1
while true do
if args['other' .. i] then
addOther(args['other' .. i])
i = i + 1
else
break
end
end
end
-- restrictions are all added to the banner text. Here we specify a date placed and a tracking category if not but we have manual restrictions
end
if args['placed-date'] then
addToMessage('<p>Restrictions placed: ' .. require('Module:Format time')._main{args['placed-date']} .. '</p>')
elseif manualRestrictions then
addCategory(categoryDatabase['no-date'])
end
end
addToMessage(' Editors are advised to familiarise themselves with the [[Wikipedia:Contentious topics|contentious topics procedures]] before editing this page.')
if not yesno(args.brief) then
addToMessage(' <p>Editors who repeatedly or seriously fail to adhere to the [[WP:Five pillars|purpose of Wikipedia]], '
.. 'any expected [[WP:Etiquette|standards of behaviour]], '
.. 'or any [[WP:List of policies|normal editorial process]] may be blocked or restricted by an administrator.</p>')
end
Line 335 ⟶ 429:
addToMessage('<p>If it is unclear which parts of the page are related to this contentious topic, '
.. 'the content in question should be marked within the wiki text by an invisible comment. '
.. 'If no comment is present, please ask an administrator for assistance. If in doubt it is better to assume that the content is covered.</p>')
end
 
if underRestrictions then
if args['placed-date'] then
addToMessage('<p>Restrictions placed: ' .. require('Module:Format time')._main{args['placed-date']} .. '</p>')
elseif manualRestrictions then
addCategory(categoryDatabase['no-date'])
end
end
-- Now build the messageBox
messageBox = require('Module:Message box')messageBoxModule.main("tmbox", {
["type"] = underRestrictions and "delete" or "content",
["image"] = "[[File:Commons-emblem-"
["small"] = yesno(args.small),
.. (underRestrictions and "hand" or "issue")
["image"] = "[[File:Commons-emblem-"
.. ".svg|40px]]",
.. (underRestrictions and "hand" or "issue")
["text"] = messageBody
.. ".svg|"
})
.. (yesno(args.small) and "30" or "40")
.. "px]]",
["text"] = messageBody
})
-- If ECR is enabled, prepend the ECR warning
if restrictionFlags["ECR"] then
messageBox = frame:expandTemplate{
title = "Template:Contentious topics/talk notice/ECR warning",
args = { section = section and "yes" or "", small = args.small}}
.. messageBox
-- Hard code for [[WP:BER]]
if TableTools.inArray(completeTopics, "a-i") then
Line 371 ⟶ 449:
addCategory("Wikipedia pages subject to the extended confirmed restriction related to the Arab-Israeli conflict")
end
-- Then build the ECR box
messageBox = messageBoxModule.main("tmbox", {
["class"] = "nonextendedconfirmed-show ECR-edit-request-warning",
["style"] = "background: var(--background-color-destructive-subtle, #ffe9e5); border-color: var(--border-color-destructive, #f54739); color: var(--color-base, #202122);",
["image"] = "[[File:Commons-emblem-hand.svg|40px]]"
}).. messageBox
end
Line 376 ⟶ 461:
Categories!!!
We set the restriction categories back in the if underRestrictions loop
to avoid looping through the restrictions twice. So we only need to do some cleanup, check for unknown parameters, and handle nocat
Because nocat is only for the ultra-rare case of demonstration,
Line 382 ⟶ 467:
--]]
-- Start checking for unknown parameters
if yesno(args.nocat) then
-- Doing so with extensible modules is annoying; [[Module:Check for unknown parameters]] is primarily intended for hardcoded stuff
categories = ''
else
addCategory(categoryDatabase["all"])
end
-- checking for unknown parameters with extensible modules is annoying; the module is primarily intended for hardcoded stuff
-- luckily, it makes use of a table for its main settings, and we can do some clever stuff with that
Line 407 ⟶ 487:
addKnownParameter('relatedcontent')
addKnownParameter('section')
 
addKnownParameter('small')
-- then add all of the partialTopics section parameters
for code, _ in pairs(partialTopics) do
Line 421 ⟶ 500:
 
-- set the tracking category
unknownParameterTable['unknown'] = '[[Category:' .. categoryDatabase['unknown'] .. '|_VALUE_' .. currentTitleObject.text .. ']]'
if yesno(args.nocat) then
-- an finally, call the unknownParameterCheck
-- then handle nocat by clearing both category-holding parameters
unknownParameterCheck = checkForUnknownParameters(unknownParameterTable, args)
categories = ''
unknownParameterCheck = ''
else
-- nocat is not specified, so we add the universal category
addCategory(categoryDatabase["all"])
-- and call the unknownParameterCheck
unknownParameterCheck = checkForUnknownParameters(unknownParameterTable, args)
end
return messageBox .. categories .. unknownParameterCheck
end