🇮🇷 Iran Proxy | https://www.wikipedia.org/wiki/Module:Contentious_topics_talk_banner
Jump to content

Module:Contentious topics/talk notice

Permanently protected module
From Wikipedia, the free encyclopedia

require('strict')
local p = {}
local TableTools = require('Module:TableTools')
local yesno = require('Module:Yesno')
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 function callFromListTemplate(code, arg)
	return mw.getCurrentFrame():expandTemplate{
		title = "Contentious topics/list",
		args = { [arg] = code }
	}
end

local function ucfirst(s)
	return mw.language.getContentLanguage():ucfirst(s)
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 addECR(value, scope)
		local hasECR = TableTools.inArray(restrictionsDatabase['topic-wide'][value] or {}, 'ECR')
		if yesno(args.ECR) and TableTools.inArray(restrictionsDatabase['additional-available'][value] or {}, 'ECR') then
			hasECR = true
		end
		if hasECR then
			if scope == nil then
				-- the scope is the entire CT, so we unset the scope
				ECR[value] = false
			elseif yesno(scope, false) then
				-- the scope is an unspecified part of the CT
				ECR[value] = true
			else
				-- otherwise the scope is a string detailing the scope
				ECR[value] = scope
			end
		end
	end
	
	local function add(value)
		if value then
			local applicableSection = args[value .. '-section'] or sectionParameter
			value = callFromListTemplate(value, 'canonical') -- normalize to the canonical name after we find the applicableSection
			
			if value ~= '' and not seen[value] then
				addECR(value, applicableSection)
				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
			end
			keepGoing = true
		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, ECR
end

function p.main(frame)
	--[[
	Begin by processing the inputs and declaring variables which we will need throughout the function
	--]]
	
	-- process the input
	local args = require('Module:Arguments').getArgs(frame)
	
	-- check whether we are sections all the way down
	local sectionParameter = yesno(args.section, args.section) or yesno(args.relatedcontent, args.relatedcontent)
	
	-- set the topic variables:
	--* completeTopics is a sequence for each topic applying the the entire article
	--* partialTopics is a table with topics as keys and scope as values
	--* active topics subject to ECR as keys, the scope (nil for the entire article, true for an unspecified scope) as the value
	local completeTopics, partialTopics, ECR = collectTopics(args, sectionParameter)

	-- calculate some easy variables
	local currentTitleObject = mw.title.getCurrentTitle()
	local articleOrPage = currentTitleObject:inNamespaces(1) and "article" or "page" -- 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
	
	-- and then declare a bunch more variables which will be needed later
	local restrictions = {} -- a sequence of which restrictions are enabled for easier iteration
	local restrictionFlags = {} -- track which restrictions are enabled, as a set
	local categories = '' -- initialize categories
	local manualRestrictions = false -- have we set any restrictions via |parameters? Set to true when |parameters are processed
	local underRestrictions -- a boolean for whether there are any active restrictions
	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
	
	--[[
	This area sets active restrictions
	The end goal is to get the restrictions variable into a nice, neat, sorted list of which restrictions are active
	This is a somewhat intense process
	--]]
	
	-- Helpers to add a restriction if it's active and hasn't been added yet
	local function maybeAddRestriction(restriction)
		if yesno(args[restriction]) then
			restrictionFlags[restriction] = true
			manualRestrictions = true
		end
	end
	
	local function alwaysAddRestriction(restriction)
		restrictionFlags[restriction] = true
	end
	
	-- Helper to add a category
	local function addCategory(cat)
		if cat then
			categories = categories .. '[[Category:' .. cat .. '|' .. currentTitleObject.text .. ']]'
		end
	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
		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
		local always = restrictionsDatabase["topic-wide"][topic]
		if always then
			for _, restriction in ipairs(always) do
				-- Allow disabling these restrictions (via |1RR=no or similar)
				if yesno(args[restriction], true) or args[restriction] == nil then
					restrictionFlags[restriction] = true
				else
					restrictionFlags[restriction] = nil
				end
			end
		end
	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 == "sysop" then alwaysAddRestriction("sysop") end
			else
				-- no ECR, so just add the protection as normal
				alwaysAddRestriction(protectionLevel)
			end
			manualRestrictions = true
		else
			-- we have a |protection=foo parameter, but the page is *not* protected
			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
		restrictionFlags["1RR"] = nil
	end

	-- clear BRD if consensus-required is enabled
	if restrictionFlags["consensus-required"] then
		restrictionFlags["BRD"] = nil
	end
	
	-- and finally, convert our set to a list to make it easy to work with
	
	restrictions = TableTools.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
	
	local function addToMessage(s)
		messageBody = messageBody .. s
	end
	
	local function getTopicBlurb(code)
		return callFromListTemplate(code, 'scope')
	end
	
	local function getSubtopicBlurb(code)
		return callFromListTemplate(code, 'subtopic')
	end
	
	-- returns the code for a superTopic
	local function getSupertopic(code)
		return callFromListTemplate(code, 'supertopic')
	end
	
	-- gets either the subtopic blurb (if one exists) or the regular topic blurb (if it does not)
	local function getSuptopicOrTopicBlurb(code)
		local subtopicBlurb = getSubtopicBlurb(code)
		if subtopicBlurb ~= '' then
			return subtopicBlurb
		else
			return getTopicBlurb(code)
		end
	end
	
	local function makeParentTopicLink(code)
		return '<b>' .. require('Module:Contentious topics/make link')._makeTopicLink(code) .. '</b>.'
	end
	
	-- Makes a bullet point for a given contentious topic
	-- 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 = getSuptopicOrTopicBlurb(code)
		if topicBlurb == '' then
			-- we have an invalid topic, so add to the error category
			addCategory(categoryDatabase['bad-topic'])
		else
			-- first write the bullet point
			addToMessage('* <b>' .. ucfirst(topicBlurb) .. '</b>')
			if scope then
				-- if the scope is not nil, add the scope to the blurb
				addToMessage(', specifically the parts about <b>' .. scope .. '</b>')
			end
			-- check for a superTopic (e.g. South Asia is the superTopic of Indian military history)
			local superTopic = getSupertopic(code)
			if superTopic ~= '' then
				-- we have a superTopic, so explain that
				addToMessage(', a subtopic of <b>' .. makeParentTopicLink(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
	
	
	--[[
	Error categories
	--]]
	
	-- No contentious topic codes
	if numberOfTopics == 0 then
		addCategory(categoryDatabase['no-topic'])
	end
	
	--[[
	Begin building the messageBody
	--]]
	
	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')
				theCTOP = topic
			end
		else
			addToMessage(' This ' .. articleOrPage .. ' relates')
			theCTOP = completeTopics[1]
		end
		local subtopicBlurb = getSubtopicBlurb(theCTOP)
		if subtopicBlurb ~= '' then
			addToMessage(' to <b>' .. subtopicBlurb .. '</b>, ' .. ' part of the contentious topic designation for ' .. makeParentTopicLink(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(' The entire ' .. articleOrPage .. ' relates to ')
			if numberOfCompleteTopics > 1 then
				-- we either loop through adding bullet points
				addToMessage('the following contentious topics:\n')
				for _, topic in ipairs(completeTopics) do
					makeTopicBulletPoint(topic, nil)
				end
			else
				-- or we do it once
				-- 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 ' .. makeParentTopicLink(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
				addToMessage('Additionally, parts ')
			else
				addToMessage('Parts ')
			end
			addToMessage('of this ' .. articleOrPage .. ' relate to ')
			if numberOfPartialTopics > 1 then
				addToMessage('the following contentious topics:</p>\n')
				for topic, scope in pairs(partialTopics) do
					if yesno(scope, false) then
						-- the scope parameter is something like 'yes', which we can treat as nil
						makeTopicBulletPoint(topic, nil)
					else
						makeTopicBulletPoint(topic, scope)
					end
				end
			else
				-- There's only one topic and scope, so this loop only runs once
				for topic, scope in pairs(partialTopics) do
					local superTopic = getSupertopic(topic)
					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 ' .. makeParentTopicLink(topic) .. '</p>')
					else
						addToMessage('.</p>')
					end
				end
			end
		end
	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 if not given one, add a tracking category if we have manual restrictions
		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
	
	if section then
		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
	
	-- Now build the messageBox
	
	messageBox = messageBoxModule.main("tmbox", {
		["type"] = underRestrictions and "delete" or "content",
		["image"] = "[[File:Commons-emblem-"
			.. (underRestrictions and "hand" or "issue")
			.. ".svg|40px]]",
		["text"] = messageBody
	})
	
	-- If ECR is enabled, prepend the ECR warning
	if restrictionFlags["ECR"] then
		-- Hard code for [[WP:BER]]
		if TableTools.inArray(completeTopics, "a-i") then
			messageBox = messageBox .. "<p class='PIA-flag' style='display:none; visibility:hidden;'>"
			 .. "This page is subject to the extended confirmed restriction related to the Arab-Israeli conflict.</p>"
			addCategory("Wikipedia pages subject to the extended confirmed restriction related to the Arab-Israeli conflict")
		end
		
		local ECRMessage
		
		-- helper to add to the blurb
		local function addToECRMessage(s)
			ECRMessage = ECRMessage .. s
		end
		
		-- add the "admins can skip this bit"
		ECRMessage = '<div class="mw-collapsible mw-collapsed sysop-show" '
			.. 'style="background-color:var(--background-color-interactive, #eaecf0); color:var(--color-base, #202122); padding:0.1em;">'
			.. '<div style="text-align:center; font-weight:bold;">You are an administrator, so you may disregard the message below</div>'
			.. '<div class="mw-collapsible-content">You are seeing this because of the limitations of '
			.. '{{[[Template:If extended confirmed|If extended confirmed]]}} and {{[[Template:If admin|If admin]]}}'
			.. '\nYou can hide this message box by adding the following to a new line of your <span class="plainlinks">['
			.. tostring(mw.uri.fullUrl('Special:MyPage/common.css', 'action=edit'))
			.. ' common.css]</span> page:'
			.. frame:callParserFunction{
				name = '#tag:syntaxhighlight',
				args = {
					'.ECR-edit-request-warning {\n\tdisplay: none;\n}',
					copy = 1,
					lang = 'css'
				}
			}
			.. '</div></div>'

		local ECRSize = TableTools.size(ECR) -- number of topics covered by ECR
		
		addToECRMessage('<div style="text-align:center;"><strong style="text-transform:uppercase; font-weight:bold; font-size:120%">')
		
		-- string to add if the entire article is ECR'd (constant)
		local onlyEditRequest = 'Stop: You may only use this page to create an edit request</strong></div><p>'
		
		-- string to add if only parts are ECR'd (constant)
		local partlyEditRequest = 'Stop: Parts of this page are restricted</strong></div><p>'
		
		if ECRSize <= 1 then
			if ECRSize == 1 then
				-- only one ECR CTOP detected
				for topic, scope in pairs(ECR) do
					-- there is only one ECR CTOP specified, so this loop only runs once
					if scope == false then
						-- the entire page is covered by the topic
						addToECRMessage(onlyEditRequest)
						addToECRMessage('This ' .. articleOrPage .. ' is')
					elseif scope == true then
						-- an unspecified part of the page is covered by the topic
						addToECRMessage(partlyEditRequest)
						addToECRMessage('Parts of this ' .. articleOrPage .. ' are')
					else
						-- the scope is a string explaining the part covered
						addToECRMessage(partlyEditRequest)
						addToECRMessage('Parts of this ' .. articleOrPage .. ' about <b>' .. scope .. '</b> are')
					end
					addToECRMessage(' related to <b>' .. getSuptopicOrTopicBlurb(topic) .. '</b>, which')
				end
			else
				-- there are zero (or fewer) ECR topics detected, but ECR is enabled. Use a fallback.
				addToECRMessage('This ' .. articleOrPage .. ', in whole or in part,')
			end
			addToECRMessage(' is <strong>subject to the [[Wikipedia:ARBECR|extended-confirmed restriction]]</strong>.</p>')
		else
			-- intialize a temporary string (necessary because we will prepend an introduction to the bullet points)
			-- and we don't know what that will say until we loop through
			local temporaryString = ''
			-- whether the entire article is ECR'd
			local completelyCovered = false
			-- add a function to add to the temporaryString
			local function addToTemporaryString(s)
				temporaryString = temporaryString .. s
			end
			
			for topic, scope in pairs(ECR) do
				-- first add the string to the list
				addToTemporaryString('\n* <b>' .. ucfirst(getSuptopicOrTopicBlurb(topic)) .. '</b>')
				if scope == false then
					-- ECR applies to the entire page, so append nothing and set completelyCovered to true
					completelyCovered = true
				elseif scope == true then
					-- ECR applies to an unspecified part, so just append (in part)
					addToTemporaryString(' (in part)')
				else
					-- append the exact scope of ECR
					addToTemporaryString(' (the part about ' .. scope .. ')')
				end
			end
			
			if completelyCovered then
				addToECRMessage(onlyEditRequest)
				addToECRMessage('This ' .. articleOrPage .. ' relates')
			else
				addToECRMessage(partlyEditRequest)
				addToECRMessage('Parts of this ' .. articleOrPage .. ' relate')
			end
			addToECRMessage(' to the following:</p>')
			addToECRMessage(temporaryString)
			addToECRMessage('\nwhich are <strong>subject to the [[Wikipedia:ARBECR|extended-confirmed restriction]]</strong>.')
		end
		
		addToECRMessage('<p>You are not an [[Wikipedia:User access levels#Extendedconfirmed|extended-confirmed]] user, so <strong>you must not edit or discuss ')
		addToECRMessage((ECRSize == 1) and 'this topic' or 'these topics')
		addToECRMessage(' anywhere on Wikipedia</strong> except to make an [[Wikipedia:Edit requests|edit request]]. (Additional details are in the message box ')
		addToECRMessage('just below this one.)</p><div style="padding-bottom:0.5em; text-align:center;">')
		
		-- Check if the *talk* page is protected
		-- We also care about semi-protection because there is no way to check if the editor is an IP
		if #(currentTitleObject.protectionLevels["edit"] or {}) == 0 then
			addToECRMessage(frame:expandTemplate{title = 'Request edit button', args = {'extendedconfirmed'}})
		else
			addToECRMessage(frame:expandTemplate{
				title = 'Clickable button',
				args = {
					[1] = 'Submit an edit request',
					color = 'blue',
					url = 'https://en.wikipedia.org/wiki/Wikipedia:Requests_for_page_protection/Edit/Form?withJS=MediaWiki:Request-page-protection-form.js'
				}
			})
		end
		addToECRMessage('</div>')
		
		-- 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]]",
			["text"] = ECRMessage
			}) .. messageBox
	end
	
	--[[
	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,
	manually clearing the categories is more efficient
	--]]
	
	if yesno(args.nocat) then
		-- then handle nocat by clearing both category-holding parameters
		categories = ''
		unknownParameterCheck = ''
	else
		-- nocat is not specified, so we add the universal category
		addCategory(categoryDatabase["all"])
		-- And start checking for unknown parameters
		-- Doing so with extensible modules is annoying; [[Module:Check for unknown parameters]] 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
		
		-- helper to mark a parameter as known
		local function addKnownParameter(s)
			table.insert(unknownParameterTable, s)
		end
		
		-- initialize the table with the keys of restrictionsDefinition JSON
		unknownParameterTable = TableTools.keysToList(restrictionsDefinition, false, true)
		
		-- then some hardcoded parameters
		addKnownParameter('aeprotection')
		addKnownParameter('brief')
		addKnownParameter('nocat')
		addKnownParameter('placed-date')
		addKnownParameter('protection')
		addKnownParameter('relatedcontent')
		addKnownParameter('section')
	
		-- then add all of the partialTopics section parameters
		for code, _ in pairs(partialTopics) do
			addKnownParameter(code .. '-section')
		end
		
		-- then all the various topic parameters. Table is no longer a sequence; perform any computation requring a sequence above
		unknownParameterTable['regexp1'] = 'topic[%d]*'
		unknownParameterTable['regexp2'] = 't[%d]*'
		unknownParameterTable['regexp3'] = '[%d]+'
		unknownParameterTable['regexp4'] = 'other[%d]*'
	
		-- set the tracking category
		unknownParameterTable['unknown'] = '[[Category:' .. categoryDatabase['unknown'] .. '|_VALUE_' .. currentTitleObject.text .. ']]'
		
		unknownParameterCheck = checkForUnknownParameters(unknownParameterTable, args)
	end
	
	return messageBox .. categories .. unknownParameterCheck
end

return p