Module:Pagetype

From NationStates Sports Wiki
Revision as of 11:01, 25 October 2013 by wikipedia>Mr. Stradivarius (put the class value in lower case to match both "Dab" and "dab" etc., and some more comment tweaking)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Pagetype/doc

----------------------------------------------------------------------------------------------------
--                                                                                                --
--                                           PAGETYPE                                             --
--                                                                                                --
--      This is a meta-module intended to replace {{pagetype}} and similar templates. It          --
--      automatically detects namespaces, and allows for a great deal of customisation.           --
--      It can easily be ported to other wikis by changing the values in the configuration        --
--      table.
--                                                                                                --
----------------------------------------------------------------------------------------------------

local cfg = {}

----------------------------------------------------------------------------------------------------
--                                          Configuration data                                    --
--      This module can be localised for other wikis by using the configuration parameters below. --
----------------------------------------------------------------------------------------------------

-- This table holds the values to use for "main=true", "user=true", etc. Keys to this table should
-- be namespace parameters that can be used with [[Module:Namespace detect]]. 
cfg.pagetypes = {
	['main']              = 'article',
	['user']              = 'user page',
	['project']           = 'project page',
	['wikipedia']         = 'project page',
	['wp']                = 'project page',
	['file']              = 'file',
	['image']             = 'file',
	['mediawiki']         = 'interface page',
	['template']          = 'template',
	['help']              = 'help page',
	['category']          = 'category',
	['portal']            = 'portal',
	['book']              = 'book',
	['education program'] = 'education program page',
	['timedtext']         = 'Timed Text page',
	['module']            = 'module',
	['talk']              = 'talk page',
	['special']           = 'special page',
	['media']             = 'file'
}

-- This table holds the names of the namespaces to be looked up from cfg.pagetypes by default.
cfg.defaultNamespaces = {'main', 'file', 'template', 'category', 'module', 'book'}

-- The parameter name to use for disambiguation pages page.
cfg.dab = 'dab'

-- This table holds the different possible aliases for disambiguation-class pages. These should be lower-case.
cfg.dabAliases = {'disambiguation', 'disambig', 'disamb', 'dab'}

-- The default value for disambiguation pages.
cfg.dabDefault = 'page'

-- The parameter name to use for N/A-class page.
cfg.na = 'na'

-- This table holds the different possible aliases for N/A-class pages. These should be lower-case.
cfg.naAliases = {'na', 'n/a'}

-- The default value for N/A-class pages.
cfg.naDefault = 'page'

-- The parameter name to use for redirects.
cfg.redirect = 'redirect'

-- The default value to use for redirects.
cfg.redirectDefault = 'redirect'

-- The parameter name for undefined namespaces.
cfg.other = 'other'

-- The value used if the module detects an undefined namespace.
cfg.otherDefault = 'page'

----------------------------------------------------------------------------------------------------
--                                       End configuration data                                   --
----------------------------------------------------------------------------------------------------

-- Load required modules.
local yesno = require('Module:Yesno')
local nsDetectModule = require('Module:Namespace detect')
local nsDetect = nsDetectModule._main
local getPageObject = nsDetectModule.getPageObject

local p = {}

local function checkPagetypeInput(namespace, val)
	-- Checks to see whether we need the default value for the given namespace, and if so gets it from the pagetypes table.
	local ret = yesno(val, val) -- Returns true/false for "yes", "no", etc., and returns val for other input.
	if ret and type(ret) ~= 'string' then
		ret = cfg.pagetypes[namespace]
	end
	return ret
end

local function getPagetypeFromClass(class, param, aliasTable, default)
	-- Gets the pagetype from a class specified from the first positional parameter.
	param = yesno(param, param)
	if param ~= false then -- Check for classes unless they are specifically disallowed.
		for _, alias in ipairs(aliasTable) do
			if class == alias then
				if type(param) == 'string' then
					return param
				else
					return default
				end
			end
		end
	end
end

local function getNsDetectValue(args)
	-- Builds the arguments to pass to [[Module:Namespace detect]] and returns the result.
	local ndArgs = {}
	-- Get the default values.
	for _, namespace in ipairs(cfg.defaultNamespaces) do
		ndArgs[namespace] = cfg.pagetypes[namespace]
	end
	-- Add custom values passed in from the arguments. These overwrite the defaults.
	for namespace in pairs(cfg.pagetypes) do
		local ndArg = checkPagetypeInput(namespace, args[namespace])
		if ndArg == false then
			-- If any arguments are false, convert them to nil to protect against breakage by future changes
			-- to [[Module:Namespace detect]].
			ndArgs[namespace] = nil
		elseif ndArg then
			ndArgs[namespace] = ndArg
		end
	end
	-- If the main namespace argument is present, check for disambiguation-class and N/A-class pages.
	if ndArgs.main then
		local class = args[1]
		if type(class) == 'string' then
			-- Put in lower case so e.g. "Dab" and "dab" will both match.
			class = mw.ustring.lower(class)
		end
		local dab = getPagetypeFromClass(class, args[cfg.dab], cfg.dabAliases, cfg.dabDefault)
		if dab then
			ndArgs.main = dab
		else
			local na = getPagetypeFromClass(class, args[cfg.na], cfg.naAliases, cfg.naDefault)
			if na then
				ndArgs.main = na
			end
		end
	end
	-- If there is no talk value specified, use the corresponding subject namespace for talk pages.
	if not ndArgs.talk then
		ndArgs.subjectns = true
	end
	-- Add the fallback value. This can also be customised, but it cannot be disabled.
	local other = args[cfg.other]
	other = yesno(other, other) -- We will ignore true/false/nil results from yesno here, but using it anyway for consistency.
	if type(other) == 'string' then
		ndArgs.other = other
	else
		ndArgs.other = cfg.otherDefault
	end
	-- Allow custom page values.
	ndArgs.page = args.page
	return nsDetect(ndArgs)
end

local function detectRedirects(args)
	local redirect = args[cfg.redirect]
	redirect = yesno(redirect, redirect) -- Returns true/false for "yes", "no", etc., and returns redirect for other input.
	if redirect == false then return end -- Detect redirects unless they have been explicitly disallowed with "redirect=no" or similar.
	local pageObject = getPageObject(args.page)
	-- If we are using subject namespaces elsewhere, do so here as well.
	if pageObject and not yesno(args.talk, true) then
		pageObject = getPageObject(pageObject.subjectNsText .. ':' .. pageObject.text)
	end
	-- Allow custom values for redirects.
	if pageObject and pageObject.isRedirect then
		if type(redirect) == 'string' then
			return redirect
		else
			return cfg.redirectDefault
		end
	end
end

function p._main(args)
	local redirect = detectRedirects(args)
	if redirect then
		return redirect
	else
		return getNsDetectValue(args)
	end
end

function p.main(frame)
	-- If called via #invoke, use the args passed into the invoking template, or the args passed to #invoke if any exist.
	-- Otherwise assume args are being passed directly in from the debug console or from another Lua module.
	local origArgs
	if frame == mw.getCurrentFrame() then
		origArgs = frame:getParent().args
		for k, v in pairs(frame.args) do
			origArgs = frame.args
			break
		end
	else
		origArgs = frame
	end
	-- Trim whitespace and remove blank arguments.
	local args = {}
	for k, v in pairs(origArgs) do
		if type(v) == 'string' then
			v = mw.text.trim(v)
		end
		if v ~= '' then
			args[k] = v
		end
	end
	return p._main(args)
end

return p