-- This module implements [[Template:Random portal component]]
local p = {}
local mRandom = require('Module:Random')
local currentTitle = mw.title.getCurrentTitle()
local portalNamesContainingSlashes = {
["AC/DC"] = true,
}
local function isSelectedHeader(header)
-- Whether a page is selected (a selected article, selected list, etc.).
-- The "'*" part of the pattern checks for italic or bold text, like
-- ''Selected'' or '''Selected'''.
if header then
return string.find(header, "^'*[sS]elected") ~= nil
else
return false
end
end
local function isInPortalNamespace(title)
-- Whether a title object is in the portal namespace.
return title.namespace == 100
end
local function isPortalSubpage(title)
-- Whether a title object is a portal subpage
return (
isInPortalNamespace(title)
and title.isSubpage
and not portalNamesContainingSlashes[title.text]
)
end
local function isRootPortalTitle(title)
-- Whether a title object is for a root portal page.
return isInPortalNamespace(title) and not isPortalSubpage(title)
end
local function makeCategoryLink(category)
-- Make a category link.
return string.format('[[Category:%s]]', category)
end
local function makeSubpageTrackingCategoryLink(fragment)
-- Make a subpage tracking category link.
return makeCategoryLink(
string.format(
'Random portal component with %s available subpages',
fragment
)
)
end
local function renderSubpageTrackingCategory(pages, header)
-- Render the link for the appropriate subpage tracking category.
-- Only track root portal pages that have "Selected x" sections.
if not isSelectedHeader(header) or not isRootPortalTitle(currentTitle) then
return ""
end
-- Check whether subpages exist at the category boundaries, and return the
-- appropriate category link. For example, if page 6 exists but page 11
-- doesn't, return
-- [[Category:Random portal component with 6–10 available subpages]].
local boundaries = {2, 6, 11, 16, 21, 26, 31, 41, 51, 101, 201, 501, 1001}
local fragment
for i, subpageNumber in ipairs(boundaries) do
local subpageName = pages.subpage .. '/' .. tostring(subpageNumber)
local subpageTitle = mw.title.new(subpageName)
if not subpageTitle.exists then
if i == 1 then
fragment = string.format("less than %d", boundaries[i])
else
fragment = string.format("%d–%d", boundaries[i - 1], boundaries[i] - 1)
end
return makeSubpageTrackingCategoryLink(fragment)
end
end
fragment = string.format("over %d", boundaries[#boundaries] - 1)
return makeSubpageTrackingCategoryLink(fragment)
end
local function getRandomNumber(max)
-- gets a random integer between 1 and max; max defaults to 1
return mRandom.number{max or 1}
end
local function expandArg(args, key)
-- Emulate how unspecified template parameters appear in wikitext. If the
-- specified argument exists, its value is returned, and if not the argument
-- name is returned inside triple curly braces.
local val = args[key]
if val then
return val
else
return string.format('{{{%s}}}', key)
end
end
local function getPages(args)
local pages = {}
pages.root = args.rootpage or currentTitle.prefixedText
pages.subpage = pages.root .. '/' .. expandArg(args, 'subpage')
pages.random = pages.subpage .. '/' .. getRandomNumber(args.max)
pages.footer = 'Template:Box-footer'
return pages
end
local function tryExpandTemplate(frame, title, args)
local success, result = pcall(frame.expandTemplate, frame, {title = title, args = args})
if success then
return result
else
local msg = string.format(
'<strong class="error">The page "[[%s]]" does not exist.</strong>',
title
)
if isRootPortalTitle(currentTitle) then
msg = msg .. '[[Category:Portals needing attention]]'
end
return msg
end
end
local function getHeader(frame, pages, header, template)
return tryExpandTemplate(
frame,
template or pages.root .. '/box-header',
{header, pages.random}
)
end
local function getRandomSubpageContent(frame, pages)
return tryExpandTemplate(
frame,
pages.random
)
end
local function getFooter(frame, pages, link)
return tryExpandTemplate(
frame,
pages.footer,
{link}
)
end
function p._main(args, frame)
frame = frame or mw.getCurrentFrame()
local pages = getPages(args)
local ret = {}
ret[#ret + 1] = getHeader(frame, pages, args.header or 'subpage', args.headertemplate)
ret[#ret + 1] = getRandomSubpageContent(frame, pages)
if not args.footer or not args.footer:find('%S') then
ret[#ret + 1] = '<div style="clear:both;"></div></div>'
else
ret[#ret + 1] = getFooter(frame, pages, string.format(
'[[%s|%s]]',
pages.subpage,
expandArg(args, 'footer')
))
end
return table.concat(ret, '\n') .. renderSubpageTrackingCategory(pages, args.header)
end
function p._nominate(args, frame)
frame = frame or mw.getCurrentFrame()
local pages = getPages(args)
local ret = {}
ret[#ret + 1] = getHeader(frame, pages, expandArg(args, 'header'), args.headertemplate)
ret[#ret + 1] = getRandomSubpageContent(frame, pages)
ret[#ret + 1] = getFooter(frame, pages, string.format(
'[[/Nominate/%s|Suggest]] • [[%s|%s]] ',
expandArg(args, 'subpage'),
pages.subpage,
args.footer or 'Archive'
))
return table.concat(ret, '\n') .. renderSubpageTrackingCategory(pages, args.header)
end
local function makeInvokeFunction(func)
return function (frame)
local args = require('Module:Arguments').getArgs(frame, {
trim = false,
removeBlanks = false,
wrappers = {
'Template:Random portal component',
'Template:Random portal component/BHG-test',
'Template:Random portal component with nominate'
}
})
return func(args, frame)
end
end
p.main = makeInvokeFunction(p._main)
p.nominate = makeInvokeFunction(p._nominate)
return p