Module:Requested move
Appearance
-- This module implements {{requested move}} and {{move-multi}}.
local getArgs = require('Module:Arguments').getArgs
local tableTools = require('Module:TableTools')
local yesno = require('Module:Yesno')
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function err(msg)
-- Generates a wikitext error message
return string.format('{{error|%s}}', msg)
end
--------------------------------------------------------------------------------
-- Main function
--------------------------------------------------------------------------------
function p.main(frame)
----------------------------------------------------------------------------
-- Initialise variables and preprocess the arguments
----------------------------------------------------------------------------
local args = getArgs(frame)
local title = mw.title.getCurrentTitle()
--[[
-- To iterate over the current1, new1, current2, new2, ... arguments
-- we get an array of tables sorted by number and compressed so that
-- it can be traversed with ipairs. The table format looks like this:
-- {
-- {current = x, new = y, num = 1},
-- {current = z, new = q, num = 2},
-- ...
-- }
-- The "num" field is used to correctly preserve the number of the parameter
-- that was used, in case users skip any numbers in the invocation.
--
-- The current1 parameter is a special case, as it does not need to be
-- specified. To avoid clashes with later current parameters, we need to
-- add it to the args table manually. Although it does not need to be
-- specified, we don't want the module's behaviour to change if a user
-- specifies it anyway.
--
-- Also, we allow the first positional parameter to be an alias for the
-- new1 parameter, so that the syntax for the old templates
-- {{requested move}} and {{move-multi}} will both be supported.
--
-- The "multi" variable tracks whether we are using the syntax previously
-- produced by {{requested move}}, or the syntax previously produced by
-- {{move-multi}}. For the former, multi is false, and for the latter it is
-- true.
--]]
args.current1 = title.subjectPageTitle.prefixedText
args.new1 = args.new1 or args[1]
local argsByNum = {}
for k, v in pairs(args) do
k = tostring(k)
local prefix, num = k:match('^(%l*)([1-9][0-9]*)$')
if prefix == 'current' or prefix == 'new' then
num = tonumber(num)
local subtable = argsByNum[num] or {}
subtable[prefix] = v
subtable.num = num
argsByNum[num] = subtable
end
end
argsByNum = tableTools.compressSparseArray(argsByNum)
local argsByNumCount = #argsByNum
local multi
if argsByNumCount >= 2 then
multi = true
else
multi = false
end
--[[
-- Validate new params.
-- This check ensures we don't have any absent new parameters, and that
-- users haven't simply copied in the values from the documentation page.
--]]
if multi then
for i, t in ipairs(argsByNum) do
local new = t.new
local num = t.num
if not new or new == 'New title for page ' .. tostring(num) then
argsByNum[i].new = '?'
end
end
else
local new = argsByNum[1].new
if not new or new == 'NewName' then
argsByNum[1].new = '?'
end
end
----------------------------------------------------------------------------
-- Error checks
----------------------------------------------------------------------------
-- Subst check
if not mw.isSubsting() then
local lb = mw.text.nowiki('{{')
local rb = mw.text.nowiki('}}')
local msg = '<strong class="error">'
.. 'This template must be [[Wikipedia:Template substitution|substituted]];'
.. ' replace %srequested move%s with %ssubst:requested move%s'
.. '</strong>'
msg = string.format(msg, lb, rb, lb, rb)
return msg
end
-- Check we are on a talk page
if not title.isTalkPage then
local msg = '[[Template:Requested move]] must be used in a TALKSPACE, e.g., [[%s:%s]]'
msg = string.format(msg, mw.site.namespaces[title.namespace].talk.name, title.text)
return err(msg)
end
-- Check the arguments
local currentDupes = {}
for i, t in ipairs(argsByNum) do
local current = t.current
local num = t.num
local currentTitle
local subjectSpace
-- Check for invalid or missing currentn parameters
-- This check must come first, as mw.title.new will give an error if
-- it is given invalid input.
if not current then
local msg = '"current%d" parameter missing;'
.. ' please add it or remove the "new%d" parameter'
msg = string.format(msg, num, num)
return err(msg)
end
-- Check for invalid currentn titles
-- This check must come before the namespace checks and the check for
-- non-existent titles, as we cannot extract the relevant data from
-- the title object if the title object does not exist.
currentTitle = mw.title.new(current)
if not currentTitle then
local msg = 'Invalid title detected in parameter "current' .. num .. '";'
.. ' check for [[Wikipedia:Page name#'
.. 'Technical restrictions and limitations|invalid characters]] and'
.. ' incorrectly formatted'
.. ' [[Help:Interwiki linking|interwiki prefixes]]'
return err(msg)
end
-- Category namespace checks
subjectSpace = mw.site.namespaces[currentTitle.namespace].subject.id
if subjectSpace == 14 then
local msg = '[[Template:Requested move]] is not for categories,'
.. ' see [[Wikipedia:Categories for discussion]]'
return err(msg)
-- File namespace check
elseif subjectSpace == 6 then
local msg = '[[Template:Requested move]] is not for files;'
.. ' see [[Wikipedia:Moving a page#Moving a file page]]'
.. ' (use [[Template:Rename media]] instead)'
return err(msg)
-- User namespace check
elseif subjectSpace == 2 then
local msg = '[[Template:Requested move]] is not for moves from user space;'
.. ' see [[Wikipedia:Articles for creation]]'
.. ' (use '
.. mw.text.nowiki('{{')
.. '[[Wikipedia:Substitution|subst]]:[[Template:Submit|submit]]'
.. mw.text.nowiki('}}')
.. ' instead),'
.. ' or [[Help:How to move a page|move it yourself]]'
return err(msg)
end
-- Check for non-existent titles.
if not currentTitle.exists then
local msg = 'Must create [[:%s]] before requesting that it be moved'
msg = string.format(msg, current)
return err(msg)
end
-- Check for duplicate current titles
-- We know the id isn't zero because we have already checked for
-- existence.
local currentId = currentTitle.id
if currentDupes[currentId] then
local msg = 'Duplicate title detected ("'
.. currentTitle.prefixedText
.. '"); cannot move the same page to two different places'
return err(msg)
else
currentDupes[currentId] = true
end
end
----------------------------------------------------------------------------
-- Generate the heading
----------------------------------------------------------------------------
-- For custom values of |heading=, use those.
-- For |heading=yes, |heading=y, etc., use the current date as a heading.
-- Otherwise don't include a heading.
local heading = args.heading or args.header
local useHeading = yesno(heading, heading)
if heading and useHeading == heading then
heading = '== ' .. heading .. ' ==\n\n'
elseif useHeading then
local lang = mw.language.getContentLanguage()
local headingDate = lang:formatDate('d F Y')
heading = '== Requested move ' .. headingDate .. ' ==\n\n'
else
heading = ''
end
----------------------------------------------------------------------------
-- Build the {{requested move/dated}} invocation
----------------------------------------------------------------------------
local rmd = {}
rmd[#rmd + 1] = '{{ආරාධිත ගෙනයෑම/දාතම දරන'
if multi then
rmd[#rmd + 1] = '|multiple=yes'
rmd[#rmd + 1] = '\n|current1=' .. argsByNum[1].current
end
--[[
-- The first new title. This is used both by single and by multi; for single
-- it is the only parameter used. For single the parameter name is the first
-- positional parameter, and for multi the parameter name is "new1".
--]]
local new1param = multi and 'new1=' or ''
rmd[#rmd + 1] = '|' .. new1param .. argsByNum[1].new
-- Add the rest of the arguments for multi.
if multi then
for i = 2, argsByNumCount do
local t = argsByNum[i]
local numString = tostring(i)
local current = t.current
local new = t.new
rmd[#rmd + 1] = '|current' .. numString .. '=' .. current
rmd[#rmd + 1] = '|new' .. numString .. '=' .. new
end
-- The old multi template always has a bar before the closing curly
-- braces, so we will do that too.
rmd[#rmd + 1] = '|'
end
rmd[#rmd + 1] = '}}'
rmd = table.concat(rmd)
----------------------------------------------------------------------------
-- Generate the list of links to the pages to be moved
----------------------------------------------------------------------------
local linkList = {}
for i, t in ipairs(argsByNum) do
local current = t.current
local new = t.new
local item = string.format(
'\n%s[[:%s]] → {{no redirect|%s}}',
multi and '* ' or '', -- Don't make a list for single page moves.
current,
new
)
linkList[#linkList + 1] = item
end
linkList = table.concat(linkList)
----------------------------------------------------------------------------
-- Reason and talk blurb
----------------------------------------------------------------------------
-- Reason
local reason = args.reason or args[2] or 'Please place your rationale for the proposed move here.'
reason = '– ' .. reason .. ' ~~~~'
-- Talk blurb
local talk
if yesno(args.talk, true) then
talk = frame:expandTemplate{title = 'ආරාධිත ගෙනයෑම/සාකච්ඡාව'}
else
talk = ''
end
----------------------------------------------------------------------------
-- Assemble the output
----------------------------------------------------------------------------
-- The old templates start with a line break, so we will do that too.
local ret = string.format(
'\n%s%s\n%s%s%s%s',
heading,
rmd,
linkList,
multi and '\n' or ' ',
reason,
talk
)
return ret
end
return p