Jump to content

Module:Reply to/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Mr. Stradivarius (talk | contribs) at 05:29, 16 November 2016 (finish tidying up this code). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- This module implements {{reply to}}.

local p = {}

-- The maximum number of users that can receive notifications in one edit
local MAX_USERS = 50

-- Make an HTML error from the supplied error message.
local function makeHTMLError(msg)
	msg = string.format(
		'Error in [[Template:Reply to]]: %s.',
		msg
	)
	return require('Module:Error').error{msg}
end

-- Make a title object for the given user's user page. If the username contains
-- invalid characters, returns nil. Usernames can be given as 'Foo' or
-- 'User:Foo'. If a user subpage is supplied, the title for the root user page
-- is returned.
local function makeUserTitle(user)
	local title = mw.title.new(user, 2)
	if title then
		return title.rootPageTitle
	else
		return nil
	end
end

-- Make a wikilink with the given page and display text.
local function makeWikilink(page, display)
	return string.format('[[%s|%s]]', page, display)
end

local function findArgNums(args)
	local ret = {}
	for k in pairs(args) do
		if type(k) == 'number' then
			table.insert(ret, k)
		end
	end
	table.sort(ret)
	return ret
end

-- Validate the arg nums. Returns true if the arg nums are valid, and returns
-- false and an error message if the nums are invalid.
local function validateArgNums(nums)
	local nUsers = #nums
	if nUsers < 1 then
		return false, 'No usernames given'
	elseif nUsers > MAX_USERS then
		return false, string.format('More than %d names specified', MAX_USERS)
	end
	return true
end

-- Make a table of user links from the arg nums and the args table. Returns
-- true plus the table of user links if everything went well; returns false and
-- an error message if there were any errors.
local function makeUserLinks(nums, args)
	local links = {}
	for i, num in ipairs(nums) do
		local username = args[num]
		local userTitle = makeUserTitle(username)
		if not userTitle then
			return false, string.format(
				"'%s' is not a valid username or user page",
				username
			)
		end
		local display = args['label' .. tostring(num)] or username
		table.insert(links, makeWikilink(userTitle.prefixedText, display))
	end
	return true, links
end

-- Assemble the output string from the table of links and from the arguments.
-- Returns the output string.
local function makeOutputString(links, args)
	local prefix = args.prefix or '@'
	local separator = ', '
	local conjunction
	if args.c == '' then
		conjunction = separator
	elseif args.c then
		conjunction = ' ' .. args.c .. ' '
	else
		conjunction = ' and '
	end
	local punctuation = args.p or ':'
	return string.format(
		'<span class="template-ping">%s%s%s</span>',
		prefix,
		mw.text.listToText(links, separator, conjunction),
		punctuation
	)
end

-- The entry point from other Lua modules.
function p._replyto(args)
	-- Find the numbers of positional arguments that have been specified, and
	-- check that they are valid.
	local nums = findArgNums(args)
	local numsAreValid, message = validateArgNums(nums)
	if not numsAreValid then
		return makeHTMLError(message)
	end
		
	-- Assemble the links
	local linksAreValid, links = makeUserLinks(nums, args)
	if not linksAreValid then
		return makeHTMLError(links)
	end

	-- Assemble the output
	return makeOutputString(links, args)
end

-- The entry point from #invoke.
function p.replyto(frame)
	local parentArgs = frame:getParent().args
	-- Trim and remove blanks for positional args, but leave named args as is.
	-- (Note that named args are trimmed by MediaWiki, so we don't need to do it
	-- again.)
	local args = {}
	for k, v in pairs(parentArgs) do
		if type(k) == 'number' then
			-- This is a positional arg
			v = v:match('^%s*(.-)%s*$') -- Trim whitespace
			if v ~= '' then
				args[k] = v
			end
		else
			-- This is a named arg
			args[k] = v
		end
	end
	return p._replyto(args)
end

return p