Jump to content

Module:Mock title

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Mr. Stradivarius (talk | contribs) at 09:47, 7 March 2021 (set simple properties). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mRepr = require('Module:Repr')

local p = {}
local mockTitleRegistry = {}

--[[
-- Patch an existing title object with the given options.
--]]
function p.patchTitleObject(title, options)
	-- Set simple properties
	for _, property in ipairs{"id", "isRedirect", "exists", "contentModel"} do
		local value = options[property]
		if value ~= nil then
			rawset(title, property, value)
		end
	end
	
	-- Set protection levels
	local levels = {
		edit = {},
		move = {},
		create = {},
		upload = {},
	}
	local protectionSet = false
	for action in pairs(levels) do
		local level = options[action .. "Protection"]
		if level then
			levels[action][1] = level
			protectionSet = true
		end
	end
	if protectionSet then
		rawset(title, "protectionLevels", levels)
	end

	return title
end

--[[
-- Construct a new mock title.
--]]
function p.MockTitle(options)
	checkType("MockTitle", 1, options, "table")
	checkTypeForNamedArg("MockTitle", "page", options.page, "string")
	local title = mw.title.new(options.page)
	return p.patchTitleObject(title, options)
end

--[[
-- Construct a mock title from a string or from an options table. If we were
-- passed a mock title object to start with, return it as-is.
--]]
local function constructMockTitle(titleOrOptions)
	if type(titleOrOptions) == "string" then
		return p.MockTitle{page = titleOrOptions}
	elseif type(titleOrOptions.getContent) == "function" then
		return titleOrOptions
	else
		return p.MockTitle(titleOrOptions)
	end
end

--[[
-- Register a mock title.
-- This can be a string, a mock title object or a table of options for
-- MockTitle.
--]]
function p.registerMockTitle(titleOrOptions)
	checkType("registerMockTitle", 1, titleOrOptions, "table")
	title = constructMockTitle(titleOrOptions)
	mockTitleRegistry[title.prefixedText] = title
end

--[[
-- Remove a title from the mock title registry.
-- Returns the title that was removed.
--]]
function p.deregisterMockTitle(titleOrOptions)
	checkType("deregisterMockTitle", 1, title, "table")
	title = constructMockTitle(titleOrOptions)
	registeredTitle = mockTitleRegistry[title.prefixedText]
	mockTitleRegistry[title.prefixedText] = nil
	return registeredTitle
end

--[[
-- Register multiple mock titles.
--]]
function p.registerMockTitles(...)
	checkType("registerMockTitles", 1, titleData, "table")
	for _, titleOrOptions in ipairs{...} do
		p.registerMockTitle(titleOrOptions)
	end
end

--[[
-- Deregister multiple mock titles.
-- Returns a sequence of titles that were removed.
--]]
function p.deregisterMockTitles(...)
	checkType("deregisterMockTitles", 1, titleData, "table")
	local removedTitles = {}
	for _, titleOrOptions in ipairs{...} do
		table.insert(removedTitles, p.deregisterMockTitle(titleOrOptions))
	end
	return removedTitles
end

--[[
-- Clear the mock title registry.
--]]
function p.clearMockTitleRegistry()
	mockTitleRegistry = {}
end

--[[
-- Patch the given title function.
-- This replaces the title function with a function that looks in the title
-- registry for the given title.
--]]
local function patchTitleFunc(funcName)
	local oldFunc = mw.title[funcName]
	mw.title[funcName] = function(...)
		local title = oldFunc(...)
		if not title then
			error(
				string.format(
					"Could not make title object from invocation %s",
					mRepr.invocationRepr{
						funcName = "mw.title." .. funcName,
						args = {...}
					}
				),
				2
			)
		end
		local mockTitle = mockTitleRegistry[title.prefixedText]
		if mockTitle then
			return mockTitle
		else
			return title
		end
	end
	return oldTitleNew
end

--[[
-- Patch mw.title.new.
-- The original mw.title.new is restored after running the given function.
--]]
function p.patchTitleNew(func, ...)
	local oldTitleNew = patchTitleFunc("new")
	func(...)
	mw.title.new = oldTitleNew
end

--[[
-- Patch mw.title.makeTitle.
-- The original mw.title.makeTitle is restored after running the given function.
--]]
function p.patchMakeTitle(func, ...)
	local oldMakeTitle = patchTitleFunc("makeTitle")
	func(...)
	mw.title.makeTitle = oldMakeTitle
end

--[[
-- Patch mw.title.new and mw.title.makeTitle.
-- The original title functions are restored after running the given function.
--]]
function p.patchTitleConstructors(func, ...)
	local oldTitleNew = patchTitleFunc("new")
	local oldMakeTitle = patchTitleFunc("makeTitle")
	func(...)
	mw.title.new = oldTitleNew
	mw.title.makeTitle = oldMakeTitle
end

return p